{"id":30905273,"url":"https://github.com/depapp/midnight-whistleblower","last_synced_at":"2025-09-09T10:08:25.322Z","repository":{"id":311252611,"uuid":"1043028729","full_name":"depapp/midnight-whistleblower","owner":"depapp","description":"Anonymous Whistleblower Inbox with Rate-Limit Nullifiers - A privacy-preserving DApp built on Midnight Network","archived":false,"fork":false,"pushed_at":"2025-08-23T04:20:21.000Z","size":141,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-08-23T04:28:16.275Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://midnight-whistleblower.vercel.app","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/depapp.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2025-08-23T02:13:46.000Z","updated_at":"2025-08-23T04:20:24.000Z","dependencies_parsed_at":"2025-08-23T04:28:18.042Z","dependency_job_id":"780c5f8c-33d1-46bd-a7c5-fdcfc00ed41c","html_url":"https://github.com/depapp/midnight-whistleblower","commit_stats":null,"previous_names":["depapp/midnight-whistleblower"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/depapp/midnight-whistleblower","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depapp%2Fmidnight-whistleblower","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depapp%2Fmidnight-whistleblower/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depapp%2Fmidnight-whistleblower/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depapp%2Fmidnight-whistleblower/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/depapp","download_url":"https://codeload.github.com/depapp/midnight-whistleblower/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/depapp%2Fmidnight-whistleblower/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":274278169,"owners_count":25255314,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-09-09T02:00:10.223Z","response_time":80,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2025-09-09T10:08:23.191Z","updated_at":"2025-09-09T10:08:25.314Z","avatar_url":"https://github.com/depapp.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Anonymous Whistleblower Inbox with Rate-Limit Nullifiers\n\nA privacy-preserving reporting platform built on **Midnight Network** for the \"Protect That Data\" challenge. This application demonstrates zero-knowledge proofs using Midnight's Compact language and MidnightJS SDK for anonymous, rate-limited whistleblowing.\n\n\n\u003cimg width=\"1448\" height=\"883\" alt=\"1\" src=\"https://github.com/user-attachments/assets/ae125bcd-61af-4f4f-918f-faea7116c359\" /\u003e\n\n| \u003cimg width=\"1444\" height=\"881\" alt=\"2\" src=\"https://github.com/user-attachments/assets/cd1bca3d-9276-4f51-957f-879abc5a76bc\" /\u003e | \u003cimg width=\"1447\" height=\"881\" alt=\"4 1\" src=\"https://github.com/user-attachments/assets/ca33c34a-29eb-475b-bda1-540fbc052473\" /\u003e |\n| ------------ | ----- |\n\n## 🚀 Features\n\n### Zero-Knowledge Proofs\n- **Membership Proofs**: Prove you're part of an organization without revealing identity\n- **Rate-Limit Nullifiers (RLN)**: Prevent spam with epoch-based nullifiers\n- **Poseidon Hashing**: Efficient ZK-friendly hash function implementation\n- **Groth16 Protocol**: Industry-standard SNARK construction\n\n### Privacy \u0026 Security\n- **End-to-End Encryption**: Web Crypto API (ECDH + AES-GCM)\n- **Client-Side Only**: No server, all processing in browser\n- **Key Management**: Flexible import/export with password protection\n- **Anonymous Submission**: No IP tracking or user identification\n\n### User Experience\n- **Modern UI**: Tiptap-inspired design with refined monochrome theme\n- **Accessibility**: WCAG 2.1 AA compliant\n- **Responsive**: Works on desktop and mobile devices\n- **Real-time Feedback**: Visual proof verification indicators\n- **Optional Cloud Sync**: Cross-device synchronization via Vercel KV (preserves privacy)\n\n## 🛠️ Technical Architecture\n\n### Smart Contract Integration\n\nThe DApp integrates smart contracts through a flexible adapter pattern:\n\n```typescript\n// Submit report to smart contract\nconst contractAdapter = contractManager.getAdapter();\nconst result = await contractAdapter.submitReport(\n  commitment,    // Hash of encrypted data\n  nullifier,     // Rate-limit nullifier\n  epoch,         // Current epoch\n  proof,         // ZK proof\n  encryptedData  // Encrypted report content\n);\n\n// Returns mock transaction hash\nconsole.log('Transaction:', result.txHash);\n```\n\n### Contract Architecture\n\n- **WhistleblowerInbox Contract**: Manages on-chain report anchoring\n  - Enforces nullifier uniqueness per epoch (RLN)\n  - Emits events for report submission and status updates\n  - Stores only commitments and public signals (privacy-preserving)\n\n- **Contract Adapter Pattern**: Two implementations\n  - `MockOnChainAdapter`: Simulates contract with IndexedDB persistence\n  - `FallbackAdapter`: Direct storage when contract mode disabled\n\n### Midnight Integration\n\n```typescript\n// Real MidnightJS proof generation\nconst proof = await midnightJS.generateProof('membership_rln', {\n  merkleRoot: organizationRoot,\n  epoch: currentEpoch,\n  identitySecret: userSecret,\n  merklePath: membershipPath,\n  // ... other inputs\n});\n\n// Verification with circuit artifacts\nconst isValid = await midnightJS.verifyProof('membership_rln', proof);\n```\n\n### Circuit Structure\n\nThe `membership_rln.compact` circuit implements:\n- Merkle tree membership verification (depth 20 = 1M members)\n- Epoch-based nullifier generation\n- Optional message binding for proof-of-statement\n\n### Development Modes\n\n1. **Real Mode** (default): Uses compiled circuit artifacts\n   ```bash\n   npm run compile-circuits  # Generate artifacts\n   npm run dev              # Run with real proofs\n   ```\n\n2. **Stub Mode**: Fast development without circuit compilation\n   ```bash\n   VITE_USE_REAL_MIDNIGHT=false npm run dev\n   ```\n\n3. **Smart Contract Mode** (enabled by default): Anchors reports on-chain\n   - Automatically enabled on first run\n   - Enforces nullifier uniqueness per epoch\n   - Generates mock transaction hashes\n   - Can be toggled in Settings page\n   - To disable via environment: `VITE_USE_CONTRACT=false`\n\n## 📦 Installation\n\n```bash\n# Clone the repository\ngit clone https://github.com/depapp/midnight-whistleblower.git\ncd midnight-whistleblower\n\n# Install dependencies\nnpm install\n\n# Compile Midnight circuits\nnpm run compile-circuits\n\n# Start development server\nnpm run dev\n\n# Smart Contract Mode is enabled by default\n# To disable, go to Settings page or set VITE_USE_CONTRACT=false\n```\n\n## 🔧 Circuit Compilation\n\nThe project includes a complete circuit compilation pipeline:\n\n```bash\nnpm run compile-circuits\n```\n\nThis generates:\n- `public/zk-artifacts/membership_rln.proving_key.json` - Proving key for proof generation\n- `public/zk-artifacts/membership_rln.verification_key.json` - Verification key\n- `public/zk-artifacts/membership_rln.wasm.json` - WASM module for witness calculation\n- `public/zk-artifacts/membership_rln.metadata.json` - Circuit metadata\n\n## 📚 Documentation\n\n### API Reference\n\n#### MidnightJS Integration\n```typescript\nimport { midnightJS } from './lib/midnightjs';\n\n// Generate proof\nconst proof = await midnightJS.generateProof(circuitName, input);\n\n// Verify proof\nconst isValid = await midnightJS.verifyProof(circuitName, proof);\n```\n\n#### Encryption Module\n```typescript\nimport { generateKeyPair, encryptMessage, decryptMessage } from './lib/encryption';\n\n// Generate keys\nconst keyPair = await generateKeyPair();\n\n// Encrypt/decrypt\nconst encrypted = await encryptMessage(data, publicKey);\nconst decrypted = await decryptMessage(encrypted, privateKey);\n```\n\n## 🏗️ Project Structure\n\n```\nmidnight-whistleblower/\n├── circuits/\n│   └── membership_rln.compact      # Midnight Compact circuit\n├── contracts/\n│   └── WhistleblowerInbox.ts      # Smart contract for report anchoring\n├── scripts/\n│   └── compile-circuits.js         # Circuit compilation script\n├── src/\n│   ├── lib/\n│   │   ├── midnightjs.ts          # MidnightJS integration\n│   │   ├── midnight-stub.ts       # SDK interface\n│   │   ├── contract-adapter.ts    # Smart contract adapter layer\n│   │   ├── sync-provider.ts       # Data sync abstraction\n│   │   ├── encryption.ts          # Crypto utilities\n│   │   └── zkProof.ts             # ZK proof helpers\n│   ├── pages/\n│   │   ├── ReporterPage.tsx       # Anonymous reporting UI\n│   │   ├── ModeratorPage.tsx      # Report management UI\n│   │   └── SettingsPage.tsx       # Contract \u0026 sync configuration\n│   └── components/                # UI components\n├── public/\n│   └── zk-artifacts/              # Compiled circuit artifacts\n└── package.json\n```\n\n## 🧪 Testing\n\n### Unit Tests\n```bash\nnpm test\n```\n\n### Manual Testing\n1. Generate moderator keys on the Moderator page\n2. Copy the public key\n3. Go to Submit Report page\n4. Paste the public key and submit a report\n5. Return to Moderator page to decrypt and verify\n\n### Proof Verification\nCheck browser console for MidnightJS logs:\n- `[MidnightJS] Loading artifacts...`\n- `[MidnightJS] Generating proof...`\n- `[MidnightJS] Proof verification result: true`\n\n## 🚢 Deployment\n\n### Basic Deployment (Local Storage Only)\n\n#### Vercel\n```bash\nvercel deploy\n```\n\n#### Netlify\n```bash\nnetlify deploy --prod\n```\n\nBoth platforms automatically serve the compiled circuit artifacts from `/public/zk-artifacts/`.\n\n### Advanced: Deployment with Optional Cloud Sync\n\nThe application supports optional cross-device synchronization using Vercel KV storage while maintaining privacy through encryption and zero-knowledge proofs.\n\n#### 1. Deploy to Vercel\n\n```bash\n# Install Vercel CLI\nnpm i -g vercel\n\n# Deploy the application\nvercel\n\n# Note your deployment URL (e.g., https://your-app.vercel.app)\n```\n\n#### 2. Set up Vercel KV Storage\n\n1. Go to your [Vercel Dashboard](https://vercel.com/dashboard)\n2. Select your project\n3. Navigate to the \"Storage\" tab\n4. Click \"Create Database\" → Select \"KV\"\n5. Choose a name and region\n6. Click \"Create\"\n\n#### 3. Configure Environment Variables\n\nIn your Vercel project settings, add:\n\n```bash\n# Required for KV storage\nKV_URL=\u003cyour-kv-url\u003e\nKV_REST_API_URL=\u003cyour-kv-rest-api-url\u003e\nKV_REST_API_TOKEN=\u003cyour-kv-rest-api-token\u003e\nKV_REST_API_READ_ONLY_TOKEN=\u003cyour-kv-read-only-token\u003e\n\n# Optional: Add API key protection\nAPI_KEY=\u003cyour-secret-api-key\u003e\n```\n\n#### 4. Enable Sync in the Application\n\nUsers can enable cloud sync through the Settings page (`/settings`):\n\n1. Navigate to Settings\n2. Toggle \"Enable Cloud Sync\"\n3. **For Vercel deployments**: Leave the URL field empty (it will use the current site automatically)\n4. **For local development**: Enter your Vercel deployment URL (e.g., `https://your-app.vercel.app`)\n5. Optionally add the API key if configured\n6. Click \"Save Settings\" and \"Test Connection\"\n\n#### Privacy Note on Cloud Sync\n\nWhen cloud sync is enabled:\n- **Reports remain encrypted** - Only ciphertext is transmitted\n- **Zero-knowledge proofs preserve anonymity** - Identity is never revealed\n- **Local-first architecture** - Data is always stored locally as backup\n- **Graceful fallback** - Automatically uses local storage if sync fails\n- **User control** - Sync can be disabled at any time\n\n### Environment Variables Reference\n\nFor local development:\n\n```bash\n# .env.local\n# Smart Contract Mode (enabled by default)\nVITE_USE_CONTRACT=true                           # Explicitly enable (default if not set)\n# VITE_USE_CONTRACT=false                        # To disable contract mode\n\n# Cloud Sync (optional)\nVITE_SYNC_ENABLED=true\nVITE_SYNC_BASE_URL=https://your-app.vercel.app  # Only needed for cross-origin sync\nVITE_SYNC_API_KEY=your-api-key                   # Optional\n```\n\n**Note**: When deployed to Vercel, the app automatically uses same-origin API routes (`/api/reports`). You only need to specify `VITE_SYNC_BASE_URL` when:\n- Testing locally against a deployed Vercel instance\n- Using a separate backend deployment\n- Setting up cross-origin sync between different domains\n\nFor Vercel deployment:\n\n```bash\n# Vercel Environment Variables\nKV_URL=\u003cfrom-vercel-kv-setup\u003e\nKV_REST_API_URL=\u003cfrom-vercel-kv-setup\u003e\nKV_REST_API_TOKEN=\u003cfrom-vercel-kv-setup\u003e\nKV_REST_API_READ_ONLY_TOKEN=\u003cfrom-vercel-kv-setup\u003e\nAPI_KEY=\u003coptional-api-key\u003e\n```\n\n## 📄 License\n\nThis project is licensed under the Apache License 2.0 - see the [LICENSE](LICENSE) file for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepapp%2Fmidnight-whistleblower","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdepapp%2Fmidnight-whistleblower","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdepapp%2Fmidnight-whistleblower/lists"}