Initial Commit
This commit is contained in:
44
openspec/archive/2026-05-26-api-secrets-vault/proposal.md
Normal file
44
openspec/archive/2026-05-26-api-secrets-vault/proposal.md
Normal file
@@ -0,0 +1,44 @@
|
||||
# `@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"`.
|
||||
Reference in New Issue
Block a user