Files
skills/docs/api-stack/api/api-secrets-bun/src/allowlist/allowlist.md
2026-05-29 08:20:56 +01:00

2.7 KiB

allowlist

(no submodules)

Purpose

The allow-list module encapsulates the per-plugin scoping rule that defines the package's security boundary: a plugin can only read secrets that its manifest's secrets[] block declared, no matter what Bun.secrets happens to hold under the host's service namespace. Every get / require call routes through assertAllowed BEFORE any keystore round-trip, so a leaked plugin cannot probe key existence by name even when the OS daemon is reachable.

The interface is intentionally minimal — a frozen ordered names array plus an O(1) has probe and the throwing assertAllowed guard — so the adapter can compose it without re-implementing the membership semantics.

Features

  • Frozen names array preserving manifest declaration order; safe to return directly from the adapter's list().
  • has(name) boolean probe for branchy callers (e.g. selective writes).
  • assertAllowed(name) guard that throws SECRETS_BUN.NOT_ALLOWED with context.name populated for the audit log.
  • Silent de-duplication so a manifest that imports the same secret twice does not crash at construction.

Usage: Basic

import { createAllowlist } from "@suaveplan/api-secrets-bun/allowlist";

const al = createAllowlist(["STRIPE_SECRET_KEY", "JWT_SIGNING_KEY"]);

al.assertAllowed("STRIPE_SECRET_KEY"); // no-op
al.assertAllowed("AWS_SECRET_KEY"); // throws SECRETS_BUN.NOT_ALLOWED

Usage: Advanced

Compose the allow-list with the adapter to gate set as well as get:

import { createAllowlist } from "@suaveplan/api-secrets-bun/allowlist";

const al = createAllowlist(manifest.secrets.map((s) => s.name));

function writeIfAllowed(name: string, value: string): void {
    al.assertAllowed(name);
    return Bun.secrets.set({ service: "my-plugin", name, value });
}

API Reference

  • createAllowlist(names: readonly string[]): Allowlist — build a frozen allow-list from a manifest-derived name list.
  • Allowlist.names: readonly string[] — frozen ordered view.
  • Allowlist.has(name: string): boolean — membership probe.
  • Allowlist.assertAllowed(name: string): void — throws SecretsBunError with code SECRETS_BUN.NOT_ALLOWED on miss.

Implementation Notes

The allow-list owns its Set<string> once at construction so per-call lookup is O(1). The names array is frozen at the top level only; the strings inside are primitives and already immutable. assertAllowed populates context.name so the audit trail can route a denied lookup back to the offending plugin without surfacing the value (there is no value yet — the call is rejected before keystore consultation).