45 lines
2.5 KiB
Markdown
45 lines
2.5 KiB
Markdown
# `@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"`.
|