Keys
Koder Keys — Zero-Knowledge Password Manager
- *rea:*Foundation
- *ath:*
services/foundation/pass/app/(Flutter client, renamed fromapps/keysper RFC-001) +services/foundation/id/platform/services/keys/(Go backend service) - *ind:*Zero-knowledge vault — client app + Koder ID microservice
Role in the stack
Koder Keys is Koder's builtin password manager. It follows the zeroknowledge model: the server stores only encrypted blobs — it never sees plaintext passwords, notes, or card numbers. Decryption happens exclusively on the client using a Master Unlock Key (MUK) derived from the user's master password + Secret Key via Argon2id + HKDF-SHA256.
The backend is the 7th microservice of Koder ID (platform/id/services/keys/), defined in RFC-014. It exposes a gRPC API for vault CRUD operations (bootstrap, createreadupdate/delete items, folder management, version history) and integrates seamlessly with Koder ID's authentication stack.
Cryptographic model
- *aster password + Secret Key (34-char)*→ Argon2id (m64 MB, t3, p=4) → MUK
- *UK*→ HKDF-SHA256 → Vault Decryption Key (VDK)
- *DK*→ AES
256GCM per item - Secret Key is generated on first bootstrap and printed as an emergency kit. Loss of both master password and Secret Key = irrecoverable vault (by design).
Vault item types
login, card, note, totp, ssh_key — all five in schema from day one; v1 UI ships login only.
Primary couplings
| Module | Relationship |
|---|---|
platform/id |
Auth gateway — all vault RPCs require a valid Koder ID session |
platform/kdb (kdb-next) |
Storage substrate — vaults, items, folders, versions in TiKV |
apps/pass |
Sibling — Pass handles TOTP + passkeys; Keys handles passwords + cards |
Client shipping order
CLI (kode keys) → Koder Linux secret-service adapter → Chromium extension → Flutter mobile (apps/keys)
OAuth Token Vault (ticket KEYS-039)
The keys service also acts as an *Auth token vault*for servertoserver integrations with third-party providers (Google, Microsoft, GitHub). Other Koder services retrieve valid access tokens without implementing their own refresh logic.
Storage
- Table
keys_oauth_tokens— one row per provider+account pair, per tenant - Table
keys_service_account_keys— service account JSON key files - All secrets encrypted at rest with AES
256GCM (KEYS_OAUTH_PASSPHRASE) - Tenant isolation: kdbnext keyspace prefix + runtime check
Background refresh
A goroutine wakes every 5 minutes, finds tokens expiring within 10 minutes, and calls the provider token endpoint to refresh them. After 3 consecutive failures a token is marked refresh_failed and the consuming service must prompt the user to re-authorise.
HTTP API (internal)
Exposed on the existing HTTP port (default 4017):
| Method | Path | Description |
|---|---|---|
POST |
/oauth/tokens |
Store new token |
GET |
/oauth/tokens/:id |
Get token (auto-refresh if < 5 min left) |
GET |
/oauth/tokens/by/:provider/:email |
Get by provider+email |
DELETE |
/oauth/tokens/:id |
Revoke and delete |
GET |
/oauth/tokens?user_id=X |
List user tokens |
POST |
/oauth/service-accounts |
Store service account key |
GET |
/oauth/service-accounts/:id |
Get service account key |
GET |
/oauth/service-accounts/:id/jwt |
Get signed JWT (cached 55 min) |
DELETE |
/oauth/service-accounts/:id |
Delete service account key |
Required env vars: KEYS_OAUTH_PASSPHRASE, GOOGLE_CLIENT_ID, GOOGLE_CLIENT_SECRET. Maintenance: see meta/context/credentials/google-runbook.md.
RFCs
- *FC
014*— Vault service architecture (zeroknowledge model, crypto spec, schema, gRPC API)
See platform/id/docs/rfcs/RFC-014-vault-service.md.