Keys

Koder Keys — Zero-Knowledge Password Manager

  • *rea:*Foundation
  • *ath:*services/foundation/pass/app/ (Flutter client, renamed from apps/keys per 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

  1. *aster password + Secret Key (34-char)*→ Argon2id (m64 MB, t3, p=4) → MUK
  2. *UK*→ HKDF-SHA256 → Vault Decryption Key (VDK)
  3. *DK*→ AES256GCM per item
  4. 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 AES256GCM (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

  • *FC014*— Vault service architecture (zeroknowledge model, crypto spec, schema, gRPC API)

See platform/id/docs/rfcs/RFC-014-vault-service.md.

Source: ../home/koder/dev/koder/meta/docs/stack/modules/keys.md