Initial Commit

This commit is contained in:
2026-05-27 23:29:53 +01:00
commit fbc70f96e6
10000 changed files with 1102152 additions and 0 deletions

View File

@@ -0,0 +1,73 @@
# `allowlist`
<!-- begin:auto-docs -->
_(no submodules)_
<!-- end:auto-docs -->
## 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
```ts
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`:
```ts
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).