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

2.9 KiB

Capability: api-secrets-vault

Package: @suaveplan/api-secrets-vault Status: ACTIVE

Every requirement below carries a **Verified by:** line.

Requirements

Requirement: Vault-backed adapter implements secrets

The package SHALL implement the abstract secrets capability over a @suaveplan/vault instance. The vault is passed in already unlocked; the adapter MUST NOT see the master key.

Scenario: get returns stored value

  • WHEN a secret is set on the underlying vault AND get(name) is called
  • THEN the adapter returns the value AND api.secrets.reads_total{backend="vault"} increments

Verified by: src/adapter/adapter.test.ts::"get returns stored value AND increments reads_total"


Requirement: Locked vault surfaces explicitly

The package SHALL distinguish a locked vault (SECRETS_VAULT_LOCKED) from a missing entry (SECRETS_VAULT_NOT_FOUND).

Scenario: locked vault raises specific code

  • WHEN the vault is locked at read time
  • THEN reads raise SECRETS_VAULT_LOCKED AND no plaintext fallback occurs

Verified by: src/adapter/adapter.test.ts::"locked vault raises SECRETS_VAULT_LOCKED"


Requirement: Per-plugin allowlist enforcement

The package SHALL refuse reads of secret names not in the plugin manifest's secrets[]. Refusals raise SECRETS_VAULT_NOT_ALLOWED.

Scenario: un-manifested read refused

  • WHEN a plugin's manifest declares secrets = [{ name: "STRIPE" }] AND code calls get("AWS")
  • THEN the call raises SECRETS_VAULT_NOT_ALLOWED

Verified by: src/allowlist/allowlist.test.ts::"un-manifested read raises SECRETS_VAULT_NOT_ALLOWED"


Requirement: Vault updates surface as secret.changed events

The package SHALL subscribe to the vault's secret.updated event AND, when the updated secret is in the plugin's allowlist, emit secret.changed on the host event bus carrying { name } only (no value).

Scenario: allowlisted update emits secret.changed

  • WHEN the vault publishes secret.updated for a name in the allowlist
  • THEN the host bus receives exactly one secret.changed event AND the payload contains only { name }

Scenario: non-allowlisted update does not emit

  • WHEN the vault publishes secret.updated for a name NOT in the allowlist
  • THEN no secret.changed event is emitted on the host bus

Verified by: src/watcher/watcher.test.ts::"allowlisted update emits secret.changed" AND src/watcher/watcher.test.ts::"non-allowlisted update does not emit"


Requirement: Passes runSecretsConformance

The package SHALL pass runSecretsConformance from @suaveplan/api-secrets/testing.

Scenario: conformance passes

  • WHEN runSecretsConformance("vault", makeVaultAdapter) runs
  • THEN every harness it(...) passes

Verified by: src/adapter/adapter.spec-conformance.test.ts::"vault adapter passes runSecretsConformance"