# `@suaveplan/api-secrets-bun` — `Bun.secrets`-backed secrets adapter **Package**: `@suaveplan/api-secrets-bun` **Status**: PROPOSED **Type**: new-package **Stage**: 8 — see umbrella `openspec/changes/api-plugin-foundation/` ## Why Per design doc §3 (`secrets[]` manifest block) and §13.2 (the `secrets` capability slot), plugins read configured secrets via the `secrets` capability. `Bun.secrets` exposes the OS keystore (macOS Keychain, Linux libsecret, Windows Credential Manager) which is the right default for local-dev and single-host operator setups — secrets never touch disk in plaintext and rotate via the OS UI. ## What changes - ADDED: `createBunSecretsAdapter({ service, allowlist })` — implements the abstract `secrets` capability from `api-secrets`. Reads from `Bun.secrets.get({ service, name })`; writes via `Bun.secrets.set({ service, name, value })`. - ADDED: Per-plugin scoping — adapter is instantiated per plugin with its manifest's `secrets[]` as the allowlist. Reads outside the allowlist raise `SECRETS_BUN_NOT_ALLOWED`. - ADDED: Capability `secrets.bun` declared so plugins that specifically require the Bun-keystore backend (e.g. for desktop runtimes) can require it via `requiredCapabilities`. - ADDED: Conformance — passes `runSecretsConformance` from `api-secrets/testing`. - ADDED: Error codes (`SECRETS_BUN_*`): `NOT_FOUND`, `NOT_ALLOWED`, `KEYSTORE_UNAVAILABLE`, `KEYSTORE_LOCKED`, `WRITE_FAILED`. ## Out of scope - Other secret backends — sibling packages (`api-secrets-vault`, future `api-secrets-aws-sm`, etc.). - Migrating existing OS keychain entries between machines — operator concern. - Plaintext fallback when the OS keystore is unavailable — adapter refuses to start; another adapter must be selected. ## 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 | | `secrets.bun` capability declarable in manifest | §3 (`requiredCapabilities`) | | Per-plugin allowlist from manifest `secrets[]` | §3 | ## Verification approach - `src/adapter/adapter.test.ts` — read / write / list against a fixture `Bun.secrets` namespace; allowlist enforcement (read of un-manifested name raises `SECRETS_BUN_NOT_ALLOWED`). - `src/adapter/adapter.spec-conformance.test.ts` — runs `runSecretsConformance` from `api-secrets/testing` against the Bun adapter. - `src/error-codes.ts` — every code listed. - `tests/dep-graph.test.ts` — runtime deps (`api-types`, `api-secrets`, `error`, `logger`). ## Migration impact None — additive only. `api-host` registers this when `host.secrets.backend = "bun"`.