Files
suaveplan/openspec/specs/api-secrets-bun/spec.md
2026-05-27 23:29:53 +01:00

2.2 KiB

Capability Spec Delta: api-secrets-bun (api-secrets-bun)

Package: @suaveplan/api-secrets-bun Status: PROPOSED

Every requirement below carries a **Verified by:** line at authoring time.

ADDED Requirements

Requirement: Bun-keystore-backed secrets adapter implements secrets

The package SHALL implement the abstract secrets capability from api-secrets using Bun.secrets (macOS Keychain, Linux libsecret, Windows Credential Manager).

Scenario: get returns stored value

  • WHEN a secret has been written via the adapter
  • THEN get(name) returns its value AND increments api.secrets.reads_total{backend="bun"}

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


Requirement: Per-plugin allowlist enforcement

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

Scenario: un-manifested read is refused

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

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


Requirement: Locked keystore surfaces explicitly

The package SHALL distinguish a locked keystore (SECRETS_BUN_KEYSTORE_LOCKED) from a missing entry (SECRETS_BUN_NOT_FOUND). The adapter MUST NOT fall back silently when the OS keystore is locked.

Scenario: locked keystore raises specific code

  • WHEN the OS keystore is locked
  • THEN reads raise SECRETS_BUN_KEYSTORE_LOCKED AND no plaintext fallback occurs

Verified by: src/adapter/adapter.test.ts::"locked keystore raises SECRETS_BUN_KEYSTORE_LOCKED"


Requirement: Passes runSecretsConformance

The package SHALL pass the conformance harness exported by @suaveplan/api-secrets/testing. This pins the Bun adapter to the same observable contract as every other secrets backend.

Scenario: conformance passes

  • WHEN runSecretsConformance("bun", makeBunAdapter) runs
  • THEN every harness it(...) passes

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