{"id":50876122,"url":"https://github.com/bujosa/sharepasswords","last_synced_at":"2026-06-15T10:01:38.777Z","repository":{"id":353348464,"uuid":"1136110905","full_name":"bujosa/sharepasswords","owner":"bujosa","description":"Backend/admin services for sharepasswords.com.","archived":false,"fork":false,"pushed_at":"2026-05-03T21:57:18.000Z","size":38,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-17T14:58:29.430Z","etag":null,"topics":["admin-panel","dashboard","gcp","mongodb","security"],"latest_commit_sha":null,"homepage":"https://sharepasswords.com","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bujosa.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"docs/security.md","support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-01-17T04:46:57.000Z","updated_at":"2026-05-03T21:57:21.000Z","dependencies_parsed_at":null,"dependency_job_id":"51be278b-35bd-47d0-94f2-36bf8613494e","html_url":"https://github.com/bujosa/sharepasswords","commit_stats":null,"previous_names":["bujosa/sharepasswords"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/bujosa/sharepasswords","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bujosa%2Fsharepasswords","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bujosa%2Fsharepasswords/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bujosa%2Fsharepasswords/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bujosa%2Fsharepasswords/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bujosa","download_url":"https://codeload.github.com/bujosa/sharepasswords/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bujosa%2Fsharepasswords/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34357282,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-15T02:00:07.085Z","response_time":63,"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":["admin-panel","dashboard","gcp","mongodb","security"],"created_at":"2026-06-15T10:01:35.739Z","updated_at":"2026-06-15T10:01:38.760Z","avatar_url":"https://github.com/bujosa.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"# SharePassword\n\n\u003e Secure, zero-knowledge password sharing platform with encrypted one-time links and organization vaults.\n\nSharePassword enables users to share sensitive information (passwords, API keys, credentials) via encrypted one-time links. The platform uses **client-side encryption**, ensuring the server **never** has access to plaintext content.\n\nSharePassword also includes an early encrypted team vault: users can create an account, get an organization automatically, invite teammates, and store encrypted notes or small files with version history.\n\n## Key Features\n\n- **Zero-Knowledge Architecture** - Encryption happens 100% client-side\n- **AES-256-GCM Encryption** - Industry-standard symmetric encryption\n- **One-Time Links** - Auto-destruct after viewing\n- **Configurable Expiration** - 1 hour, 24 hours, 7 days, or 30 days\n- **View Limits** - Set maximum number of views (1, 5, 10, or unlimited)\n- **No Account Required** - Anonymous secret sharing\n- **QR Code Generation** - Easy mobile sharing\n- **Accounts \u0026 Organizations** - Users get an organization and admin membership on registration\n- **Encrypted Team Vault** - Store encrypted notes and files in an organization vault\n- **Invite Links** - Organization admins can invite admins or normal users\n- **Version History** - Vault item updates create new encrypted versions\n- **Private File Storage** - Encrypted file payloads are stored in Google Cloud Storage, while MongoDB stores metadata\n- **Backoffice Dashboard** - Dedicated admin UI for stats, users, waitlist, organizations, registration gates, and maintenance mode\n\n## How It Works\n\n```\n┌─────────────┐     ┌─────────────┐     ┌─────────────┐\n│   SENDER    │     │   SERVER    │     │  RECIPIENT  │\n└─────────────┘     └─────────────┘     └─────────────┘\n      │                   │                   │\n      │ 1. Generate key   │                   │\n      │    \u0026 encrypt      │                   │\n      │    (client-side)  │                   │\n      │                   │                   │\n      │ 2. Send encrypted │                   │\n      │    blob ─────────►│ Store blob only   │\n      │                   │                   │\n      │ 3. Create URL:    │                   │\n      │    /s/{id}#{key}  │                   │\n      │                   │                   │\n      │ 4. Share URL ─────┼───────────────────┼──►\n      │                   │                   │\n      │                   │◄──────────────────┤ 5. Request (id only)\n      │                   │                   │\n      │                   │  Return encrypted ├──►\n      │                   │  blob             │\n      │                   │                   │ 6. Decrypt with\n      │                   │                   │    key from URL\n```\n\nThe encryption key is stored in the URL fragment (`#`), which is **never sent to the server** - providing true zero-knowledge architecture.\n\n## Vault Security Model\n\nThe vault keeps the same core principle as one-time links: plaintext should not be sent to the backend.\n\n```\nBrowser\n  ├─ Loads a local vault key\n  ├─ Encrypts note or file payload with AES-GCM\n  └─ Sends ciphertext to API\n\nAPI / MongoDB\n  ├─ Stores users, organizations, memberships, invites\n  ├─ Stores vault item metadata and encrypted names\n  ├─ Stores version records\n  └─ Stores GCS object paths for encrypted files\n\nGoogle Cloud Storage\n  └─ Stores encrypted file payloads only\n```\n\nCurrent vault file limits:\n\n- Raw file upload limit: `40KB`\n- Encrypted payload API limit: `96KB`\n- Storage path format: `vaults/{organizationId}/{vaultId}/{itemId}/versions/{versionId}.bin`\n\nImportant security note: the first vault release uses a browser-managed vault key. This keeps plaintext away from the server, but approved-device key transfer, mandatory MFA, and recovery-key based vault unlock are planned hardening layers before positioning the vault as a complete 1Password-style replacement.\n\n## Documentation\n\n| Document | Description |\n|----------|-------------|\n| [Architecture](docs/architecture.md) | System architecture and design decisions |\n| [API Reference](docs/api-reference.md) | Complete API documentation |\n| [Security](docs/security.md) | Encryption details and security model |\n| [Examples](docs/examples/) | Code examples in multiple languages |\n\n## Quick Example\n\n### Create a Secret (JavaScript)\n\n```javascript\n// 1. Generate encryption key\nconst key = await crypto.subtle.generateKey(\n  { name: 'AES-GCM', length: 256 },\n  true,\n  ['encrypt', 'decrypt']\n);\n\n// 2. Encrypt your secret\nconst iv = crypto.getRandomValues(new Uint8Array(12));\nconst encoded = new TextEncoder().encode('my-secret-password');\nconst ciphertext = await crypto.subtle.encrypt(\n  { name: 'AES-GCM', iv },\n  key,\n  encoded\n);\n\n// 3. Combine IV + ciphertext and encode\nconst combined = new Uint8Array(iv.length + ciphertext.byteLength);\ncombined.set(iv, 0);\ncombined.set(new Uint8Array(ciphertext), iv.length);\nconst encryptedContent = btoa(String.fromCharCode(...combined));\n\n// 4. Send to API\nconst secretId = crypto.randomUUID();\nconst response = await fetch('https://api.sharepasswords.com/v1/secrets', {\n  method: 'POST',\n  headers: { 'Content-Type': 'application/json' },\n  body: JSON.stringify({\n    secretId,\n    encryptedContent,\n    expiresIn: '24h',\n    maxViews: 1\n  })\n});\n\n// 5. Generate shareable URL with key in fragment\nconst keyBytes = await crypto.subtle.exportKey('raw', key);\nconst keyBase64 = btoa(String.fromCharCode(...new Uint8Array(keyBytes)));\nconst shareUrl = `https://sharepasswords.com/s/${secretId}#${keyBase64}`;\n```\n\n### Retrieve a Secret (cURL)\n\n```bash\ncurl https://api.sharepasswords.com/v1/secrets/{secretId}\n```\n\n## Community\n\n### Suggestions \u0026 Feature Requests\n\nWe welcome community input! See [SUGGESTIONS.md](SUGGESTIONS.md) for how to submit feature requests and suggestions via Pull Requests.\n\n### Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.\n\n## Technology Stack\n\n| Component | Technology |\n|-----------|------------|\n| Backend | NestJS 11 (Node.js) |\n| Database | MongoDB |\n| Frontend | Svelte 5 |\n| Backoffice | Svelte 5 + Cloud Run |\n| Encryption | Web Crypto API (AES-256-GCM) |\n| File Storage | Google Cloud Storage |\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbujosa%2Fsharepasswords","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbujosa%2Fsharepasswords","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbujosa%2Fsharepasswords/lists"}