Overview
open-secret is a Bun-workspace monorepo with four parts: one you deploy, two you use, and one they both depend on.
Workspaces
- open-secret/
- backend/ - Go + Connect-RPC server over SQLite (the only deployable)
- open-secret-shared/ - TypeScript crypto + protocol core (used by both frontends)
- open-secret-ui/ - SvelteKit web app
- open-secret-extension/ - WXT browser extension (Chrome / Edge, MV3)
| Workspace | Responsibility |
|---|---|
| backend | Six Connect-RPC services (Auth, User, Device, Entry, Instance, Idp) over SQLite. Stores ciphertext + public keys, mints stateless session tokens, enforces coarse authorization. |
| open-secret-shared | The crypto primitives, the proto-derived payload schema, the auto-refreshing Connect transport, the TOTP module, and the WebAuthn ceremony orchestrator. Both frontends import it. |
| open-secret-ui | The web app: account management, vault, settings. |
| open-secret-extension | The everyday surface: autofill, save prompts, password generation, TOTP, passkeys. Popup is a Svelte app; a content script does form scanning and a WebAuthn page bridge. |
Crucially, all encryption lives in open-secret-shared and runs on the client. The backend is a storage-and-authz layer that never decrypts.
How an entry flows
The server only ever sees the boxes on the right: per-device ciphertext, signatures, content hashes, and public keys. Plaintext exists only inside the open-secret-shared layer on a device.
Transport
Frontends talk to the backend over Connect-RPC (HTTP, works with plain fetch). The shared transport attaches the session token and transparently re-authenticates when a token expires, coalescing concurrent callers so a token refresh happens once, not N times.
Cross-workspace changes
Anything touching the wire starts in the proto definitions and flows outward: edit the proto in backend, regenerate stubs in backend and open-secret-shared, then consume in the web app and extension. The server may add optional fields without breaking older clients; backward compatibility lives with the client.