@suaveplan/api-secrets-worker-proxy — worker-side proxy to a main-process SecretsLike adapter. Marshals every ctx.secrets.get/require/list call across api-worker-rpc, enforces a per-plugin allowed-keys whitelist on the main side BEFORE the secret value crosses the wire, and provides no worker-side caching so a rotated secret is picked up immediately and a compromised worker cannot exfiltrate cached values.
Stage-3 worker → main SecretsLike proxy for the API plugin system.
Documentation tree
- error-codes — Frozen registry of error codes thrown across the worker → main
SecretsLikeproxy boundary. The codes here are distinc…- error-codes — Frozen registry of error codes thrown across the worker → main
SecretsLikeproxy boundary. The codes here are distinc…
- error-codes — Frozen registry of error codes thrown across the worker → main
- main-side — Mounts a concrete
SecretsLikeadapter onto a main-processMessagePortso a worker-isolated API plugin can request s…- main-side — Mounts a concrete
SecretsLikeadapter onto a main-processMessagePortso a worker-isolated API plugin can request s…
- main-side — Mounts a concrete
- redaction — Re-exports the canonical
<redacted>marker andredactSecrethelper from@suaveplan/api-secrets, plus an additiona…- redaction — Re-exports the canonical
<redacted>marker andredactSecrethelper from@suaveplan/api-secrets, plus an additiona…
- redaction — Re-exports the canonical
- testing — Real, no-mock testing harness for the worker-side secrets proxy. Wraps a real
MessageChannel(viaapi-worker-rpc's…- testing — Real, no-mock testing harness for the worker-side secrets proxy. Wraps a real
MessageChannel(viaapi-worker-rpc's…
- testing — Real, no-mock testing harness for the worker-side secrets proxy. Wraps a real
- worker-side — Worker-side
SecretsLikeproxy. Every method call is marshalled across theapi-worker-rpctransport to the main-side…- worker-side — Worker-side
SecretsLikeproxy. Every method call is marshalled across theapi-worker-rpctransport to the main-side…
- worker-side — Worker-side
What it does
- Main side vends a concrete
SecretsLikeover aMessagePortviaapi-worker-rpc, enforcing a per-plugin allowed-keys whitelist BEFORE the secret value crosses the wire. - Worker side exposes a
SecretsLikeproxy. Every method call round-trips to the main side; there is no worker-side cache of values.
Security invariants
- A non-manifested key is rejected on the main side with
SECRETS_PROXY.KEY_NOT_PERMITTED. The underlying source is never consulted, so a malicious worker cannot probe the source's state. list()returns the FROZEN snapshot ofallowedKeys, not the source'slist(). The worker cannot enumerate names outside its manifest.- Two sequential
get("X")calls produce TWO main-side invocations. No caching means a rotated secret is picked up immediately AND a compromised worker has no internal state to exfiltrate. close()makes every subsequent method reject withSECRETS_PROXY.PROXY_DISPOSED.
Modules
error-codes—SECRETS_PROXY.*registry +SecretsProxyErrorclass.main-side—createSecretsProxyServer(port, secrets, allowedKeys).worker-side—createSecretsProxyClient(port, opts?).redaction—<redacted>marker +redactSecretLine.testing— realMessageChannel+InMemorySecretsharness.
Quick start
import { createSecretsProxyServer } from "@suaveplan/api-secrets-worker-proxy/main-side";
import { createSecretsProxyClient } from "@suaveplan/api-secrets-worker-proxy/worker-side";
import { createInProcessPortPair } from "@suaveplan/api-worker-rpc";
const ports = createInProcessPortPair();
const server = createSecretsProxyServer(ports.serverPort, mySecrets, ["STRIPE_KEY"]);
const proxy = createSecretsProxyClient(ports.clientPort, { initialList: ["STRIPE_KEY"] });
const key = await proxy.require("STRIPE_KEY");
proxy.close();
server.close();
ports.close();
Conformance
tests/conformance/run-secrets-conformance.test.ts runs
runSecretsConformance from @suaveplan/api-secrets/testing against the
worker-side proxy. This is The precondition gate — every scenario
that passes against a direct in-process adapter MUST also pass through the
proxy surface before Stage 4 can complete.
Dependencies
@suaveplan/api-secrets— canonical contract + redaction marker.@suaveplan/api-types—SecretsLiketype.@suaveplan/api-worker-rpc—MessagePort-based RPC transport.@suaveplan/error,tslib,zod.