Files
2026-05-27 23:29:53 +01:00

2.5 KiB

@suaveplan/api-secrets-vault — @suaveplan/vault-backed secrets adapter

Package: @suaveplan/api-secrets-vault Status: PROPOSED Type: new-package Stage: 8 — see umbrella openspec/changes/api-plugin-foundation/

Why

For multi-host / cloud deployments, secrets need to live in an encrypted, replicated container with a controlled unlock flow. @suaveplan/vault already implements that container (BIP39 + Argon2id + 2SKD + HKDF + SRP-6a + SecureBuffer). Wrapping it as the secrets capability gives the host a production-grade backend that sits alongside its own DB without depending on a third-party vault service.

What changes

  • ADDED: createVaultSecretsAdapter({ vault, allowlist }) — implements the abstract secrets capability over a @suaveplan/vault instance. vault is passed in unlocked by the host's startup sequence; the adapter never sees the master key.
  • ADDED: Per-plugin scoping — same allowlist contract as api-secrets-bun; reads outside the allowlist raise SECRETS_VAULT_NOT_ALLOWED.
  • ADDED: Watcher support — when the vault publishes a secret.updated event for a name in the allowlist, the adapter emits a secret.changed event on the host event bus so plugins that cached the value can refresh.
  • ADDED: Conformance — passes runSecretsConformance from api-secrets/testing.
  • ADDED: Error codes (SECRETS_VAULT_*): NOT_FOUND, NOT_ALLOWED, VAULT_LOCKED, VAULT_UNAVAILABLE, WRITE_FAILED.

Out of scope

  • Vault unlock UX — host owns the unlock flow (interactive prompt, KMS-derived key, etc.).
  • Vault snapshot / restore — @suaveplan/vault owns it.
  • Cross-region vault replication — operator concern.

Source mapping

Genesis-original. Source of design intent: docs/superpowers/specs/2026-05-13-api-plugin-foundation-design.md.

Requirement Design doc section
secrets capability §3, §5, §13.2
Per-plugin allowlist §3

Verification approach

  • src/adapter/adapter.test.ts — read / write / list against a real in-memory vault; locked vault raises SECRETS_VAULT_LOCKED.
  • src/adapter/adapter.spec-conformance.test.ts — runSecretsConformance passes.
  • src/watcher/watcher.test.ts — secret.updated from vault → secret.changed on host bus, only for names in allowlist.
  • tests/dep-graph.test.ts — runtime deps (api-types, api-secrets, vault, error, logger, events).

Migration impact

None — additive only. api-host registers this when host.secrets.backend = "vault".