{"id":51111694,"url":"https://github.com/bastipnt/passmgr","last_synced_at":"2026-06-24T18:30:43.778Z","repository":{"id":359844308,"uuid":"1107608167","full_name":"bastipnt/passmgr","owner":"bastipnt","description":"Zero-knowledge password manager — cross-platform web + mobile, TypeScript monorepo. Early prototype.","archived":false,"fork":false,"pushed_at":"2026-06-16T09:42:50.000Z","size":3483,"stargazers_count":0,"open_issues_count":4,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-06-16T11:23:15.159Z","etag":null,"topics":["bun","cryptography","drizzle-orm","e2ee","end-to-end-encryption","expo","fastify","monorepo","opaque","pake","password-manager","react","react-native","self-hosted","tailwindcss","trpc","turborepo","typescript","zero-knowledge"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/bastipnt.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":"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":"AGENTS.md","dco":null,"cla":null}},"created_at":"2025-12-01T11:23:15.000Z","updated_at":"2026-06-16T09:46:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/bastipnt/passmgr","commit_stats":null,"previous_names":["bastipnt/passmgr"],"tags_count":7,"template":false,"template_full_name":null,"purl":"pkg:github/bastipnt/passmgr","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastipnt%2Fpassmgr","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastipnt%2Fpassmgr/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastipnt%2Fpassmgr/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastipnt%2Fpassmgr/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/bastipnt","download_url":"https://codeload.github.com/bastipnt/passmgr/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/bastipnt%2Fpassmgr/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34745456,"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-24T02:00:07.484Z","response_time":106,"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":["bun","cryptography","drizzle-orm","e2ee","end-to-end-encryption","expo","fastify","monorepo","opaque","pake","password-manager","react","react-native","self-hosted","tailwindcss","trpc","turborepo","typescript","zero-knowledge"],"created_at":"2026-06-24T18:30:41.885Z","updated_at":"2026-06-24T18:30:43.766Z","avatar_url":"https://github.com/bastipnt.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# passmgr\n\nA full-stack, cross-platform password manager built on **OPAQUE** zero-knowledge authentication. TypeScript monorepo, pnpm + Turborepo.\n\n[![License: AGPL v3](https://img.shields.io/badge/License-AGPL_v3-blue.svg)](./LICENSE)\n\n\u003e ⚠️ **Early prototype — not production-ready.**\n\u003e\n\u003e The cryptographic stack has not been audited. The architecture, API, and storage format change frequently. **Do not store real passwords with this yet.** Treat this as a research / learning project that happens to compile.\n\n## What it is\n\nA password manager that uses [OPAQUE](https://datatracker.ietf.org/doc/draft-irtf-cfrg-opaque/) (an asymmetric PAKE) so the server never sees your plaintext password — not at registration, not at login, not even in transit. The vault key is wrapped client-side and stored encrypted on the server.\n\n### Key hierarchy\n\n```\npassword ──Argon2id──► passwordKEK ──encrypt──► vaultKey\nrecoveryKey ──HKDF──► recoveryKEK ──encrypt──► vaultKey  (backup wrap)\n\nsessionKey ──HKDF──► sessionSecret ──HKDF(+salt)──► authKey  (HMAC request signing)\n```\n\nEmail is stored encrypted (XChaCha20-Poly1305) and indexed via a server-keyed HMAC — never as plaintext.\n\n## What works today\n\n- **Web client**: registration, login, vault list / view / add / edit / delete, real-time record sync.\n- **Server**: OPAQUE flow end to end, HMAC-signed request auth, session storage in Redis, replay protection (5 min timestamp window).\n- **Tests**: Vitest unit + integration suites, Playwright E2E for register/login, Stryker mutation testing on crypto / store / server-auth / client packages.\n\n## What's missing\n\n- **Web**: no idle lock, no password recovery UI, no auto-relock on tab close.\n- **Mobile**: auth flow only. No vault, no records, no biometric unlock yet.\n- **Server**: no rate limiting, some signature-validation edge cases still TODO.\n\nSee [roadmap.md](./roadmap.md) for the full plan.\n\n## Stack\n\n| Layer   | Tech                                                                  |\n| ------- | --------------------------------------------------------------------- |\n| Web     | React 19, Vite (rolldown-vite), Tailwind v4, wouter, tRPC client      |\n| Mobile  | React Native 0.83, Expo 55, Tamagui, NativeWind                       |\n| Server  | Fastify 5, tRPC 11, Bun runtime, Drizzle ORM (1.0 beta)               |\n| Data    | PostgreSQL 17, Redis 7                                                |\n| Crypto  | `@cloudflare/opaque-ts`, `@noble/hashes`, `@noble/ciphers`            |\n| Tooling | pnpm 10 workspaces, Turborepo, OXLint, Prettier, Lefthook, commitlint |\n\n## Repo layout\n\n```\napps/\n  web/       React 19 + Vite web client\n  mobile/    React Native + Expo client (auth-only for now)\n  server/    Fastify + tRPC backend, runs on Bun\npackages/\n  client/             Shared React hooks (useLogin, useRegistration) + tRPC client + secrets store\n  crypto/             All cryptographic primitives\n  db/                 Drizzle schema + migrations (PostgreSQL)\n  schema/             Zod schemas shared between client and server\n  store/              Frontend data store + sync logic\n  tokens/             Design tokens (colors, spacing)\n  types/              Shared TypeScript types\n  typescript-config/  Shared tsconfig base files\n  ui/                 Shared web component library (shadcn-based)\n  ui-native/          Mobile component library (Tamagui-based)\n  util/               Base64 / string encoding helpers\n```\n\n## Quick start\n\nYou need: Node 18+, pnpm 10, Docker (for Postgres + Redis), and optionally Bun (server runtime).\n\n```bash\npnpm install\n\n# Start Postgres + Redis\npnpm db:up\n\n# Run migrations\npnpm db:migrate\n\n# Start everything in watch mode\npnpm dev\n```\n\n### Required env vars\n\nServer (`apps/server/.env`):\n\n| Var                   | Notes                                                                              |\n| --------------------- | ---------------------------------------------------------------------------------- |\n| `DATABASE_URL`        | PostgreSQL connection string                                                       |\n| `REDIS_HOST`          | e.g. `localhost`                                                                   |\n| `REDIS_PORT`          | e.g. `6379`                                                                        |\n| `OPAQUE_SERVER_SETUP` | base64 OPAQUE server setup. **Must stay stable** — rotating invalidates all users. |\n\nDB package (`packages/db/.env`):\n\n| Var            | Notes                          |\n| -------------- | ------------------------------ |\n| `DATABASE_URL` | Same as above, used by Drizzle |\n\n### Common scripts\n\n```bash\npnpm dev              # all apps in watch mode\npnpm build            # build everything via turbo\npnpm lint             # OXLint, type-aware\npnpm typecheck        # tsc across the monorepo\npnpm test             # Vitest unit tests\npnpm test:integration # integration suites\npnpm e2e              # Playwright\npnpm format           # Prettier\npnpm db:generate      # Drizzle migration generation\npnpm db:migrate       # Drizzle migration apply\n```\n\nPer-app:\n\n```bash\npnpm --filter web dev\npnpm --filter server dev\npnpm --filter mobile start\n```\n\n## Per-app docs\n\n- [apps/web/README.md](./apps/web/README.md)\n- [apps/mobile/README.md](./apps/mobile/README.md)\n- [apps/server/README.md](./apps/server/README.md)\n\n## Contributing\n\nPRs welcome — see [CONTRIBUTING.md](./CONTRIBUTING.md). Open an issue before tackling anything large; the architecture is still in motion.\n\n## Security\n\n**Do not file public issues for security problems.** See [SECURITY.md](./SECURITY.md) for the private disclosure path.\n\nThe crypto stack is **unaudited**.\n\n## License\n\n[AGPL-3.0-only](./LICENSE). You can self-host and modify freely; if you run a modified version as a network service, you must publish your source under the same license.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbastipnt%2Fpassmgr","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fbastipnt%2Fpassmgr","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fbastipnt%2Fpassmgr/lists"}