@agentproto/secrets 0.1.0-alpha.0 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/cli.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/cli.ts"],"names":[],"mappings":"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","file":"cli.mjs","sourcesContent":["/**\n * agentproto-secrets — a small CLI over the seal primitive + provision flow.\n *\n * agentproto-secrets keygen mint a sealing keypair (JSON)\n * agentproto-secrets seal --pubkey <b64> [src] seal a value -> sealed blob\n * agentproto-secrets unseal --privkey <b64> [blob] open a sealed blob -> plaintext\n * agentproto-secrets provision --provider P --method M \\\n * --seal-key-url URL --install-url URL [--header 'K: V']... [src]\n * seal a local credential and\n * install it into a vault,\n * carrying only ciphertext\n *\n * credential source [src]: --from-file <path> [--json-path a.b.c] | --from-env <VAR>\n *\n * Vendor-neutral: `provision` takes the server's URLs + auth headers as flags.\n * The plaintext credential is read, sealed, and sent — it is never printed.\n */\n\nimport {\n generateSealKeyPair,\n sealKeyId,\n seal,\n unseal,\n} from \"./seal/index.js\"\nimport {\n provisionSealed,\n httpTarget,\n resolveCredential,\n type CredentialSource,\n} from \"./provision/index.js\"\nimport {\n resolveRecipeMethod,\n resolveSourceSpec,\n listRecipeIds,\n} from \"./provision/recipe/index.js\"\n\ninterface Args {\n positionals: string[]\n flags: Record<string, string>\n headers: string[]\n}\n\nfunction parse(argv: string[]): Args {\n const positionals: string[] = []\n const flags: Record<string, string> = {}\n const headers: string[] = []\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!\n if (a.startsWith(\"--\")) {\n const eq = a.indexOf(\"=\")\n let key: string\n let val: string\n if (eq !== -1) {\n key = a.slice(2, eq)\n val = a.slice(eq + 1)\n } else {\n key = a.slice(2)\n const next = argv[i + 1]\n if (next !== undefined && !next.startsWith(\"--\")) {\n val = next\n i++\n } else {\n val = \"true\"\n }\n }\n if (key === \"header\") headers.push(val)\n else flags[key] = val\n } else {\n positionals.push(a)\n }\n }\n return { positionals, flags, headers }\n}\n\nfunction credentialSource(args: Args): CredentialSource {\n return {\n ...(args.flags[\"from-env\"] ? { fromEnv: args.flags[\"from-env\"] } : {}),\n ...(args.flags[\"from-file\"] ? { fromFile: args.flags[\"from-file\"] } : {}),\n ...(args.flags[\"json-path\"] ? { jsonPath: args.flags[\"json-path\"] } : {}),\n }\n}\n\n/** Read a value for seal: a positional, or a credential source. */\nasync function readValue(args: Args): Promise<string> {\n if (args.positionals[0]) return args.positionals[0]\n return resolveCredential(credentialSource(args))\n}\n\n/** Read one line from stdin (for a recipe's `prompt` credential source). */\nasync function promptStdin(prompt: string): Promise<string> {\n const { createInterface } = await import(\"node:readline/promises\")\n const rl = createInterface({ input: process.stdin, output: process.stderr })\n try {\n return (await rl.question(`${prompt}: `)).trim()\n } finally {\n rl.close()\n }\n}\n\n/**\n * Resolve the {methodId, credential, label} a provision installs. A recipe\n * (`--provider <id>`) supplies the auth-method id + where the credential lives,\n * so no source flags are needed; explicit `--from-file/--from-env` override the\n * recipe for ad-hoc / unknown providers (then `--method` is required).\n */\nasync function resolveProvision(\n args: Args,\n): Promise<{ methodId: string; credential: string; label?: string }> {\n const provider = args.flags.provider!\n const explicit = args.flags[\"from-file\"] || args.flags[\"from-env\"]\n if (explicit) {\n const methodId = args.flags.method\n if (!methodId)\n throw new Error(\n \"--method is required when passing an explicit --from-file/--from-env source\",\n )\n return {\n methodId,\n credential: await resolveCredential(credentialSource(args)),\n ...(args.flags.label ? { label: args.flags.label } : {}),\n }\n }\n const { recipe, method } = resolveRecipeMethod(provider, args.flags.method)\n const credential = await resolveSourceSpec(method.source, {\n promptImpl: promptStdin,\n })\n const label = args.flags.label ?? method.label ?? recipe.label\n return { methodId: method.id, credential, ...(label ? { label } : {}) }\n}\n\nfunction parseHeaders(raw: string[]): Record<string, string> {\n const out: Record<string, string> = {}\n for (const h of raw) {\n const idx = h.indexOf(\":\")\n if (idx === -1) continue\n out[h.slice(0, idx).trim()] = h.slice(idx + 1).trim()\n }\n return out\n}\n\nconst USAGE = `agentproto-secrets — seal secrets and install them into a vault\n\n keygen mint a sealing keypair (JSON to stdout)\n seal --pubkey <b64> [value|src] seal a value -> sealed blob (stdout)\n unseal --privkey <b64> [blob|src] open a sealed blob -> plaintext (stdout)\n provision --provider P --seal-key-url URL --install-url URL \\\\\n [--method M] [--header 'K: V']... [src]\n seal a local credential and install it,\n carrying only ciphertext. A known\n --provider resolves its method + source\n from a builtin recipe; --method picks a\n flavor; an explicit src overrides.\n\n src: --from-file <path> [--json-path a.b.c] | --from-env <VAR>\n builtin providers: ${listRecipeIds().join(\", \")}`\n\nasync function main(): Promise<number> {\n const [cmd, ...rest] = process.argv.slice(2)\n const args = parse(rest)\n\n switch (cmd) {\n case \"keygen\": {\n const kp = generateSealKeyPair()\n process.stdout.write(\n JSON.stringify(\n { keyId: sealKeyId(kp.publicKey), publicKey: kp.publicKey, privateKey: kp.privateKey },\n null,\n 2\n ) + \"\\n\"\n )\n return 0\n }\n\n case \"seal\": {\n const pubkey = args.flags.pubkey\n if (!pubkey) return fail(\"seal: --pubkey <b64> required\")\n const value = await readValue(args)\n process.stdout.write(seal(value, pubkey))\n return 0\n }\n\n case \"unseal\": {\n const privkey = args.flags.privkey\n if (!privkey) return fail(\"unseal: --privkey <b64> required\")\n const blob =\n args.positionals[0] ?? (await resolveCredential(credentialSource(args)))\n process.stdout.write(unseal(blob, privkey))\n return 0\n }\n\n case \"provision\": {\n const provider = args.flags.provider\n const sealKeyUrl = args.flags[\"seal-key-url\"]\n const installUrl = args.flags[\"install-url\"]\n if (!provider) return fail(\"provision: --provider required\")\n if (!sealKeyUrl || !installUrl)\n return fail(\"provision: --seal-key-url and --install-url required\")\n\n let methodId: string\n let credential: string\n let label: string | undefined\n try {\n ;({ methodId, credential, label } = await resolveProvision(args))\n } catch (err) {\n return fail(err instanceof Error ? err.message : String(err))\n }\n\n const target = httpTarget({\n sealKeyUrl,\n installUrl,\n headers: parseHeaders(args.headers),\n })\n try {\n const out = await provisionSealed({\n target,\n provider,\n methodId,\n credential,\n ...(label ? { label } : {}),\n })\n process.stdout.write(\n `sealed + installed ${provider} (${methodId})` +\n (out.secretId ? ` — secret ${out.secretId.slice(0, 8)}` : \"\") +\n ` [key ${out.keyId.slice(0, 8)}]\\n` +\n `the plaintext never left this machine; the server unsealed it.\\n`\n )\n return 0\n } catch (err) {\n return fail(err instanceof Error ? err.message : String(err))\n }\n }\n\n case \"-h\":\n case \"--help\":\n case \"help\":\n case undefined:\n process.stdout.write(USAGE + \"\\n\")\n return cmd ? 0 : 1\n\n default:\n return fail(`unknown command '${cmd}'\\n\\n${USAGE}`)\n }\n}\n\nfunction fail(message: string): number {\n process.stderr.write(`agentproto-secrets: ${message}\\n`)\n return 1\n}\n\nmain()\n .then(code => {\n process.exitCode = code\n })\n .catch(err => {\n process.stderr.write(\n `agentproto-secrets: ${err instanceof Error ? err.message : String(err)}\\n`\n )\n process.exitCode = 1\n })\n"]}
1
+ {"version":3,"sources":["../src/cli.ts"],"names":[],"mappings":"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","file":"cli.mjs","sourcesContent":["/**\n * agentproto-secrets — a small CLI over the seal primitive + provision flow.\n *\n * agentproto-secrets keygen mint a sealing keypair (JSON)\n * agentproto-secrets seal --pubkey <b64> [src] seal a value -> sealed blob\n * agentproto-secrets unseal --privkey <b64> [blob] open a sealed blob -> plaintext\n * agentproto-secrets provision --provider P --method M \\\n * --seal-key-url URL --install-url URL [--header 'K: V']... [src]\n * seal a local credential and\n * install it into a vault,\n * carrying only ciphertext\n *\n * credential source [src]: --from-file <path> [--json-path a.b.c] | --from-env <VAR>\n *\n * Vendor-neutral: `provision` takes the server's URLs + auth headers as flags.\n * The plaintext credential is read, sealed, and sent — it is never printed.\n * When `--header` is omitted and `--provider` names an auth provider\n * registered in `@agentproto/auth`, the Authorization header is instead\n * resolved via `CredentialBroker` (this is the only file in this package\n * that imports `@agentproto/auth` — see `ProvisionAuthDeps` below).\n */\n\nimport { CredentialBroker, KeychainStore, getAuthProvider } from \"@agentproto/auth\"\nimport {\n generateSealKeyPair,\n sealKeyId,\n seal,\n unseal,\n} from \"./seal/index.js\"\nimport {\n provisionSealed,\n httpTarget,\n resolveCredential,\n type CredentialSource,\n} from \"./provision/index.js\"\nimport {\n resolveRecipeMethod,\n resolveSourceSpec,\n listRecipeIds,\n} from \"./provision/recipe/index.js\"\n\ninterface Args {\n positionals: string[]\n flags: Record<string, string>\n headers: string[]\n}\n\nfunction parse(argv: string[]): Args {\n const positionals: string[] = []\n const flags: Record<string, string> = {}\n const headers: string[] = []\n for (let i = 0; i < argv.length; i++) {\n const a = argv[i]!\n if (a.startsWith(\"--\")) {\n const eq = a.indexOf(\"=\")\n let key: string\n let val: string\n if (eq !== -1) {\n key = a.slice(2, eq)\n val = a.slice(eq + 1)\n } else {\n key = a.slice(2)\n const next = argv[i + 1]\n if (next !== undefined && !next.startsWith(\"--\")) {\n val = next\n i++\n } else {\n val = \"true\"\n }\n }\n if (key === \"header\") headers.push(val)\n else flags[key] = val\n } else {\n positionals.push(a)\n }\n }\n return { positionals, flags, headers }\n}\n\nfunction credentialSource(args: Args): CredentialSource {\n return {\n ...(args.flags[\"from-env\"] ? { fromEnv: args.flags[\"from-env\"] } : {}),\n ...(args.flags[\"from-file\"] ? { fromFile: args.flags[\"from-file\"] } : {}),\n ...(args.flags[\"json-path\"] ? { jsonPath: args.flags[\"json-path\"] } : {}),\n }\n}\n\n/** Read a value for seal: a positional, or a credential source. */\nasync function readValue(args: Args): Promise<string> {\n if (args.positionals[0]) return args.positionals[0]\n return resolveCredential(credentialSource(args))\n}\n\n/** Read one line from stdin (for a recipe's `prompt` credential source). */\nasync function promptStdin(prompt: string): Promise<string> {\n const { createInterface } = await import(\"node:readline/promises\")\n const rl = createInterface({ input: process.stdin, output: process.stderr })\n try {\n return (await rl.question(`${prompt}: `)).trim()\n } finally {\n rl.close()\n }\n}\n\n/**\n * Resolve the {methodId, credential, label} a provision installs. A recipe\n * (`--provider <id>`) supplies the auth-method id + where the credential lives,\n * so no source flags are needed; explicit `--from-file/--from-env` override the\n * recipe for ad-hoc / unknown providers (then `--method` is required).\n */\nasync function resolveProvision(\n args: Args,\n): Promise<{ methodId: string; credential: string; label?: string }> {\n const provider = args.flags.provider!\n const explicit = args.flags[\"from-file\"] || args.flags[\"from-env\"]\n if (explicit) {\n const methodId = args.flags.method\n if (!methodId)\n throw new Error(\n \"--method is required when passing an explicit --from-file/--from-env source\",\n )\n return {\n methodId,\n credential: await resolveCredential(credentialSource(args)),\n ...(args.flags.label ? { label: args.flags.label } : {}),\n }\n }\n const { recipe, method } = resolveRecipeMethod(provider, args.flags.method)\n const credential = await resolveSourceSpec(method.source, {\n promptImpl: promptStdin,\n })\n const label = args.flags.label ?? method.label ?? recipe.label\n return { methodId: method.id, credential, ...(label ? { label } : {}) }\n}\n\nfunction parseHeaders(raw: string[]): Record<string, string> {\n const out: Record<string, string> = {}\n for (const h of raw) {\n const idx = h.indexOf(\":\")\n if (idx === -1) continue\n out[h.slice(0, idx).trim()] = h.slice(idx + 1).trim()\n }\n return out\n}\n\n/** Structural shape `CredentialBroker` satisfies — kept local (rather than\n * importing the class as a type) so tests can inject a fake without touching\n * Keychain or the network. */\nexport interface AuthHeaderResolver {\n resolveHeaders(o: {\n path: string\n audience?: string\n server?: string\n signal?: AbortSignal\n }): Promise<Record<string, string>>\n}\n\nexport interface ProvisionAuthDeps {\n /** Whether `providerId` is a known `@agentproto/auth` auth provider. */\n isRegistered(providerId: string): boolean\n resolver: AuthHeaderResolver\n}\n\nfunction defaultProvisionAuthDeps(): ProvisionAuthDeps {\n return {\n isRegistered: id => getAuthProvider(id) !== undefined,\n resolver: new CredentialBroker({\n store: new KeychainStore(),\n getProvider: getAuthProvider,\n }),\n }\n}\n\n/**\n * Resolve the Authorization (etc.) headers a provision request carries.\n * `--header` is an explicit override — when present, the broker is never\n * consulted. Otherwise, a `--provider` registered in `@agentproto/auth`\n * resolves its headers via the broker; an unregistered provider degrades to\n * `explicitHeaders` (empty when none were passed) rather than failing.\n */\nexport async function resolveProvisionHeaders(\n provider: string,\n explicitHeaders: string[],\n deps?: ProvisionAuthDeps,\n): Promise<Record<string, string>> {\n const parsed = parseHeaders(explicitHeaders)\n if (explicitHeaders.length > 0) return parsed\n const { isRegistered, resolver } = deps ?? defaultProvisionAuthDeps()\n if (!isRegistered(provider)) return parsed\n const brokered = await resolver.resolveHeaders({ path: provider, audience: \"api\" })\n return { ...brokered, ...parsed }\n}\n\nconst USAGE = `agentproto-secrets — seal secrets and install them into a vault\n\n keygen mint a sealing keypair (JSON to stdout)\n seal --pubkey <b64> [value|src] seal a value -> sealed blob (stdout)\n unseal --privkey <b64> [blob|src] open a sealed blob -> plaintext (stdout)\n provision --provider P --seal-key-url URL --install-url URL \\\\\n [--method M] [--header 'K: V']... [src]\n seal a local credential and install it,\n carrying only ciphertext. A known\n --provider resolves its method + source\n from a builtin recipe; --method picks a\n flavor; an explicit src overrides.\n\n src: --from-file <path> [--json-path a.b.c] | --from-env <VAR>\n builtin providers: ${listRecipeIds().join(\", \")}`\n\nexport async function main(): Promise<number> {\n const [cmd, ...rest] = process.argv.slice(2)\n const args = parse(rest)\n\n switch (cmd) {\n case \"keygen\": {\n const kp = generateSealKeyPair()\n process.stdout.write(\n JSON.stringify(\n { keyId: sealKeyId(kp.publicKey), publicKey: kp.publicKey, privateKey: kp.privateKey },\n null,\n 2\n ) + \"\\n\"\n )\n return 0\n }\n\n case \"seal\": {\n const pubkey = args.flags.pubkey\n if (!pubkey) return fail(\"seal: --pubkey <b64> required\")\n const value = await readValue(args)\n process.stdout.write(seal(value, pubkey))\n return 0\n }\n\n case \"unseal\": {\n const privkey = args.flags.privkey\n if (!privkey) return fail(\"unseal: --privkey <b64> required\")\n const blob =\n args.positionals[0] ?? (await resolveCredential(credentialSource(args)))\n process.stdout.write(unseal(blob, privkey))\n return 0\n }\n\n case \"provision\": {\n const provider = args.flags.provider\n const sealKeyUrl = args.flags[\"seal-key-url\"]\n const installUrl = args.flags[\"install-url\"]\n if (!provider) return fail(\"provision: --provider required\")\n if (!sealKeyUrl || !installUrl)\n return fail(\"provision: --seal-key-url and --install-url required\")\n\n let methodId: string\n let credential: string\n let label: string | undefined\n try {\n ;({ methodId, credential, label } = await resolveProvision(args))\n } catch (err) {\n return fail(err instanceof Error ? err.message : String(err))\n }\n\n let headers: Record<string, string>\n try {\n headers = await resolveProvisionHeaders(provider, args.headers)\n } catch (err) {\n return fail(err instanceof Error ? err.message : String(err))\n }\n\n const target = httpTarget({ sealKeyUrl, installUrl, headers })\n try {\n const out = await provisionSealed({\n target,\n provider,\n methodId,\n credential,\n ...(label ? { label } : {}),\n })\n process.stdout.write(\n `sealed + installed ${provider} (${methodId})` +\n (out.secretId ? ` — secret ${out.secretId.slice(0, 8)}` : \"\") +\n ` [key ${out.keyId.slice(0, 8)}]\\n` +\n `the plaintext never left this machine; the server unsealed it.\\n`\n )\n return 0\n } catch (err) {\n return fail(err instanceof Error ? err.message : String(err))\n }\n }\n\n case \"-h\":\n case \"--help\":\n case \"help\":\n case undefined:\n process.stdout.write(USAGE + \"\\n\")\n return cmd ? 0 : 1\n\n default:\n return fail(`unknown command '${cmd}'\\n\\n${USAGE}`)\n }\n}\n\nfunction fail(message: string): number {\n process.stderr.write(`agentproto-secrets: ${message}\\n`)\n return 1\n}\n"]}
@@ -1,4 +1,5 @@
1
- export { E as EgressSubstituteExposure, a as EnvExposure, F as FileExposure, S as SecretExposure, b as SecretExposureWrap, c as SecretExposureWrapContext, i as isExposureKind } from '../types-C2dZDHn7.js';
1
+ import { M as McpHeaderExposure } from '../types-DS9Qe9Cv.js';
2
+ export { E as EgressSubstituteExposure, a as EnvExposure, F as FileExposure, S as SecretExposure, b as SecretExposureWrap, c as SecretExposureWrapContext, i as isExposureKind } from '../types-DS9Qe9Cv.js';
2
3
 
3
4
  /**
4
5
  * Sigil + substitution engine for `$$SECRET[NAME]$$` placeholders.
@@ -91,4 +92,36 @@ declare class SecretSubstitutionError extends Error {
91
92
  constructor(code: string, message: string);
92
93
  }
93
94
 
94
- export { SECRET_PLACEHOLDER_PATTERN, type SecretResolver, SecretSubstitutionError, type SubstituteResult, type SubstitutionRecord, assertSafeSecretValue, formatPlaceholder, substituteSecrets };
95
+ /**
96
+ * Resolver for `McpHeaderExposure` — turns a broker path into ready-to-use
97
+ * HTTP headers for an MCP server's transport.
98
+ *
99
+ * `@agentproto/secrets` stays dependency-free of `@agentproto/auth`: instead
100
+ * of importing `CredentialBroker` directly, this module declares the
101
+ * structural shape it needs (`McpHeaderResolver`). `CredentialBroker`
102
+ * already satisfies it — no adapter required at call sites.
103
+ */
104
+
105
+ /** Structural shape a credential broker must satisfy to back
106
+ * `resolveMcpHeaderExposure`. `CredentialBroker` from `@agentproto/auth`
107
+ * matches this shape without any adapter. */
108
+ interface McpHeaderResolver {
109
+ resolveHeaders(o: {
110
+ path: string;
111
+ server?: string;
112
+ signal?: AbortSignal;
113
+ }): Promise<Record<string, string>>;
114
+ }
115
+ /**
116
+ * Resolve `exposure` into a header map by delegating to `resolver`, then
117
+ * guard every resolved header VALUE with `assertSafeSecretValue` before
118
+ * returning it. This closes off header-injection: a broker (or whatever
119
+ * sits behind it — a flow engine, a vault) that ever returns a value
120
+ * containing CR/LF/NUL would otherwise let that value smuggle extra
121
+ * header lines onto the MCP transport.
122
+ */
123
+ declare function resolveMcpHeaderExposure(exposure: McpHeaderExposure, resolver: McpHeaderResolver, opts?: {
124
+ signal?: AbortSignal;
125
+ }): Promise<Record<string, string>>;
126
+
127
+ export { McpHeaderExposure, type McpHeaderResolver, SECRET_PLACEHOLDER_PATTERN, type SecretResolver, SecretSubstitutionError, type SubstituteResult, type SubstitutionRecord, assertSafeSecretValue, formatPlaceholder, resolveMcpHeaderExposure, substituteSecrets };
@@ -86,6 +86,19 @@ var SecretSubstitutionError = class extends Error {
86
86
  }
87
87
  };
88
88
 
89
- export { SECRET_PLACEHOLDER_PATTERN, SecretSubstitutionError, assertSafeSecretValue, formatPlaceholder, isExposureKind, substituteSecrets };
89
+ // src/exposure/mcp-header.ts
90
+ async function resolveMcpHeaderExposure(exposure, resolver, opts) {
91
+ const headers = await resolver.resolveHeaders({
92
+ path: exposure.credentialPath,
93
+ server: exposure.server,
94
+ signal: opts?.signal
95
+ });
96
+ for (const [name, value] of Object.entries(headers)) {
97
+ assertSafeSecretValue(name, value);
98
+ }
99
+ return headers;
100
+ }
101
+
102
+ export { SECRET_PLACEHOLDER_PATTERN, SecretSubstitutionError, assertSafeSecretValue, formatPlaceholder, isExposureKind, resolveMcpHeaderExposure, substituteSecrets };
90
103
  //# sourceMappingURL=index.mjs.map
91
104
  //# sourceMappingURL=index.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/exposure/types.ts","../../src/exposure/substitute.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * SecretExposure — describes HOW a secret value reaches the runtime\n * that needs it (env var, config file, egress placeholder, future\n * MCP-header injection, future HTTP-bearer routing, …).\n *\n * Distinct from `SecretEntry` (AIP-19), which describes the secret's\n * *declaration* (slug, kind, access policy). Exposure is a *runtime*\n * concern — same secret might be exposed multiple ways across hosts.\n *\n * Discriminated union by `kind` so each new mechanism slots in as one\n * variant rather than another top-level field on whatever catalog the\n * host uses to map secrets onto agent runtimes.\n *\n * # Why this lives here (not in @agentproto/egress)\n * The substitution sigil + the \"what surfaces does this secret have\"\n * vocabulary are properties of the secret itself — they describe its\n * exposure surface independent of WHO consumes it. Egress is one\n * consumer; future ones (MCP servers, HTTP relays) are others.\n *\n * The egress *gating* (mode registry, proxy core) lives in\n * @agentproto/egress because that's a different concern (network-\n * boundary control). Egress imports from here.\n */\n\n/** Function applied to the seed value before write. Receives the raw\n * secret value (or empty string when `field` is omitted) plus an\n * optional context bag the host populates. Returns the file body. */\nexport type SecretExposureWrap = (\n value: string,\n ctx?: SecretExposureWrapContext\n) => string\n\n/** Generic context passed to `wrap` callbacks. Hosts populate fields\n * they have; wraps that don't care ignore the second arg entirely.\n * Kept open-ended (string-keyed) so hosts can attach app-specific\n * data without forcing a schema change here. */\nexport interface SecretExposureWrapContext {\n [key: string]: unknown\n}\n\n/** Inject the secret value as a process env var inside the runtime. */\nexport interface EnvExposure {\n kind: \"env\"\n /** Env var name as the runtime sees it. */\n name: string\n /** Field on the secret/connector settings whose value seeds the env.\n * Required for env exposures — env vars don't have a `wrap` path. */\n field: string\n}\n\n/** Drop a file inside the runtime's filesystem before any process\n * starts. Path uses `~` expansion against the runtime's exec user\n * home (host-resolved). */\nexport interface FileExposure {\n kind: \"file\"\n /** Absolute path or `~`-relative path inside the runtime sandbox. */\n path: string\n /** Field on the secret/connector settings whose value seeds the file\n * body. Omit when `wrap` produces synthetic content (e.g. claude's\n * `.claude.json` migration flags don't depend on a token). */\n field?: string\n /** POSIX file mode. Default `0o600`. */\n mode?: number\n /** Transform applied before write — see SecretExposureWrap. */\n wrap?: SecretExposureWrap\n}\n\n/**\n * Mark this secret as eligible for substitution at the egress proxy.\n * Agents see only `$$SECRET[<placeholderName>]$$` placeholders; the\n * proxy substitutes the real value at the network boundary.\n *\n * The actual proxy + sigil regex + substitution engine live in\n * `@agentproto/egress` — this exposure variant just declares the\n * intent + the per-secret defaults the host install handler stamps.\n */\nexport interface EgressSubstituteExposure {\n kind: \"egress-substitute\"\n /** The token agents reference in `$$SECRET[NAME]$$`. By convention\n * this matches the env-exposure name on the same secret, but it\n * doesn't have to — placeholders and env vars are independent. */\n placeholderName: string\n /** Default value for the per-secret allowlist flag stamped at install\n * time. UI may offer a per-install override. When false, the secret\n * is declared egress-aware but rejected by the resolver until an\n * admin opts in. */\n allowedByDefault: boolean\n /** Audit / UX hint — the providers this secret is *meant* for. NOT\n * enforced at egress (proxy substitutes any matching placeholder\n * regardless of upstream); the field exists so UIs can surface\n * \"this secret is for OpenAI\" without parsing the slug. */\n intendedProviders?: string[]\n}\n\n/**\n * Discriminated union of all exposure mechanisms. Add new variants here\n * as new exposure surfaces are added (MCP-header, HTTP-bearer, etc.) —\n * each adds one variant, one switch case in consumers.\n */\nexport type SecretExposure =\n | EnvExposure\n | FileExposure\n | EgressSubstituteExposure\n\n/** Type guard — convenient for filtering an exposures array by kind. */\nexport function isExposureKind<K extends SecretExposure[\"kind\"]>(\n exposure: SecretExposure,\n kind: K\n): exposure is Extract<SecretExposure, { kind: K }> {\n return exposure.kind === kind\n}\n","/**\n * Sigil + substitution engine for `$$SECRET[NAME]$$` placeholders.\n *\n * Used by hosts that implement egress-time secret substitution (the\n * narrow case in `@agentproto/egress`'s cooperative mode), and any\n * other consumer that wants to materialize secrets only at the\n * boundary instead of in agent-process env.\n *\n * Sigil shape: `$$SECRET[<NAME>]$$` where `<NAME>` is `[A-Z_][A-Z0-9_]*`\n * (matches typical env-var naming). The double-`$$` boundary on both\n * sides plus the bracketed name means a single regex pass can extract\n * names without false positives on strings that happen to contain `$$`\n * elsewhere.\n *\n * # Security\n * Resolved values get a sanity check before substitution:\n * - Reject CR (`\\r`), LF (`\\n`), NUL (`\\0`) — header injection\n * - Reject empty strings — degenerate, almost always a bug\n *\n * Hosts that need stricter validation (length caps, charset narrowing)\n * wrap the resolver passed in; this layer only enforces the universal\n * \"won't break the wire\" guarantees.\n */\n\n/**\n * Match a single `$$SECRET[NAME]$$` placeholder. Capture group 1 is\n * the name. Use the global flag (`g`) when scanning a longer string;\n * the constant here is non-global so callers can `.exec()` reliably.\n *\n * Exported because some consumers (e.g. the host-side install form)\n * want to validate that a string contains no placeholder before\n * accepting user input — they can re-derive a global variant cheaply.\n */\nexport const SECRET_PLACEHOLDER_PATTERN = /\\$\\$SECRET\\[([A-Z_][A-Z0-9_]*)\\]\\$\\$/\n\n/** Global variant — used internally for scanning + substitution. */\nconst SECRET_PLACEHOLDER_PATTERN_G = new RegExp(\n SECRET_PLACEHOLDER_PATTERN.source,\n \"g\"\n)\n\n/** Resolver function the substitution engine calls per-name. Returns\n * the secret value or `null` when the name doesn't resolve. The\n * engine treats null as \"no substitution\" (placeholder remains in\n * the output). Hosts that prefer hard-fail-on-miss should throw from\n * the resolver; the engine propagates. */\nexport type SecretResolver = (name: string) => Promise<string | null> | string | null\n\n/** Outcome of a single substitution call. `replacements` includes one\n * entry per matched placeholder, in the order they appeared. Useful\n * for audit logs (\"this call substituted OPENAI_API_KEY\"). */\nexport interface SubstituteResult {\n output: string\n replacements: SubstitutionRecord[]\n}\n\nexport interface SubstitutionRecord {\n name: string\n /** True when the resolver returned a non-null value. False when the\n * resolver returned null (placeholder kept verbatim). */\n resolved: boolean\n}\n\n/**\n * Validate a resolved secret value before it's substituted. Throws\n * with a stable error code so hosts can map the failure to a 4xx\n * cleanly. Exported so resolvers that pre-fetch can run the same\n * check before handing values back.\n */\nexport function assertSafeSecretValue(name: string, value: string): void {\n if (value.length === 0) {\n throw new SecretSubstitutionError(\n \"secret_value_empty\",\n `Resolved value for '${name}' is empty.`\n )\n }\n // CR / LF / NUL break header framing and stdio respectively. Other\n // control chars are allowed — some legitimate tokens contain them\n // (rare, but a base64 with `\\t` would be wrongly rejected by a\n // broader filter).\n if (/[\\r\\n\\0]/.test(value)) {\n throw new SecretSubstitutionError(\n \"secret_value_unsafe\",\n `Resolved value for '${name}' contains forbidden control characters (CR/LF/NUL).`\n )\n }\n}\n\n/**\n * Substitute every `$$SECRET[NAME]$$` placeholder in `input` using\n * `resolver`. Returns the rewritten string + the list of names that\n * were touched (for audit).\n *\n * Async because resolvers usually decrypt or hit a vault. Even when\n * the resolver is synchronous, the result is a Promise — callers that\n * want the sync path can `await` it cheaply since the underlying work\n * is microtask-scheduled.\n *\n * Whole-string matches are NOT enforced — the placeholder may appear\n * anywhere inside the input (`Bearer $$SECRET[X]$$` is the common\n * case for HTTP Authorization headers). Hosts that want stricter\n * placement (e.g. body-substitution gated to specific JSON paths)\n * should pre-narrow the input before calling here.\n */\nexport async function substituteSecrets(\n input: string,\n resolver: SecretResolver\n): Promise<SubstituteResult> {\n const replacements: SubstitutionRecord[] = []\n // Two-pass: first find all matches + resolve concurrently, then\n // rewrite. Lets parallel resolvers (multiple secrets) overlap their\n // decrypt cost.\n const matches: Array<{ name: string; start: number; end: number }> = []\n let m: RegExpExecArray | null\n const scan = new RegExp(\n SECRET_PLACEHOLDER_PATTERN_G.source,\n SECRET_PLACEHOLDER_PATTERN_G.flags\n )\n while ((m = scan.exec(input)) !== null) {\n matches.push({\n name: m[1]!,\n start: m.index,\n end: m.index + m[0].length,\n })\n }\n if (matches.length === 0) {\n return { output: input, replacements: [] }\n }\n\n // Dedupe so multiple placeholders for the same name only resolve once.\n const uniqueNames = Array.from(new Set(matches.map((x) => x.name)))\n const resolved = new Map<string, string | null>()\n await Promise.all(\n uniqueNames.map(async (name) => {\n const value = await resolver(name)\n if (value !== null) assertSafeSecretValue(name, value)\n resolved.set(name, value)\n })\n )\n\n // Rewrite right-to-left so earlier substitutions don't shift\n // subsequent indices.\n let output = input\n for (let i = matches.length - 1; i >= 0; i--) {\n const { name, start, end } = matches[i]!\n const value = resolved.get(name) ?? null\n if (value !== null) {\n output = output.slice(0, start) + value + output.slice(end)\n }\n // Order-preserving record for audit (forward order).\n }\n for (const { name } of matches) {\n replacements.push({ name, resolved: resolved.get(name) !== null })\n }\n\n return { output, replacements }\n}\n\n/**\n * Convenience: format a placeholder string for a given name.\n * `formatPlaceholder(\"OPENAI_API_KEY\") === \"$$SECRET[OPENAI_API_KEY]$$\"`\n *\n * Throws on invalid names so a bug in the host can't accidentally\n * inject a placeholder that won't round-trip through the regex.\n */\nexport function formatPlaceholder(name: string): string {\n if (!/^[A-Z_][A-Z0-9_]*$/.test(name)) {\n throw new SecretSubstitutionError(\n \"invalid_placeholder_name\",\n `Placeholder name '${name}' must match [A-Z_][A-Z0-9_]*`\n )\n }\n return `$$SECRET[${name}]$$`\n}\n\n/** Stable error class — hosts catch by `.code` to map to user-facing\n * responses (typically 400 / 403 / 500). */\nexport class SecretSubstitutionError extends Error {\n readonly code: string\n constructor(code: string, message: string) {\n super(message)\n this.code = code\n this.name = \"SecretSubstitutionError\"\n }\n}\n"]}
1
+ {"version":3,"sources":["../../src/exposure/types.ts","../../src/exposure/substitute.ts","../../src/exposure/mcp-header.ts"],"names":[],"mappings":";;;;;;AAuHO,SAAS,cAAA,CACd,UACA,IAAA,EACkD;AAClD,EAAA,OAAO,SAAS,IAAA,KAAS,IAAA;AAC3B;;;AC3FO,IAAM,0BAAA,GAA6B;AAG1C,IAAM,+BAA+B,IAAI,MAAA;AAAA,EACvC,0BAAA,CAA2B,MAAA;AAAA,EAC3B;AACF,CAAA;AA8BO,SAAS,qBAAA,CAAsB,MAAc,KAAA,EAAqB;AACvE,EAAA,IAAI,KAAA,CAAM,WAAW,CAAA,EAAG;AACtB,IAAA,MAAM,IAAI,uBAAA;AAAA,MACR,oBAAA;AAAA,MACA,uBAAuB,IAAI,CAAA,WAAA;AAAA,KAC7B;AAAA,EACF;AAKA,EAAA,IAAI,UAAA,CAAW,IAAA,CAAK,KAAK,CAAA,EAAG;AAC1B,IAAA,MAAM,IAAI,uBAAA;AAAA,MACR,qBAAA;AAAA,MACA,uBAAuB,IAAI,CAAA,oDAAA;AAAA,KAC7B;AAAA,EACF;AACF;AAkBA,eAAsB,iBAAA,CACpB,OACA,QAAA,EAC2B;AAC3B,EAAA,MAAM,eAAqC,EAAC;AAI5C,EAAA,MAAM,UAA+D,EAAC;AACtE,EAAA,IAAI,CAAA;AACJ,EAAA,MAAM,OAAO,IAAI,MAAA;AAAA,IACf,4BAAA,CAA6B,MAAA;AAAA,IAC7B,4BAAA,CAA6B;AAAA,GAC/B;AACA,EAAA,OAAA,CAAQ,CAAA,GAAI,IAAA,CAAK,IAAA,CAAK,KAAK,OAAO,IAAA,EAAM;AACtC,IAAA,OAAA,CAAQ,IAAA,CAAK;AAAA,MACX,IAAA,EAAM,EAAE,CAAC,CAAA;AAAA,MACT,OAAO,CAAA,CAAE,KAAA;AAAA,MACT,GAAA,EAAK,CAAA,CAAE,KAAA,GAAQ,CAAA,CAAE,CAAC,CAAA,CAAE;AAAA,KACrB,CAAA;AAAA,EACH;AACA,EAAA,IAAI,OAAA,CAAQ,WAAW,CAAA,EAAG;AACxB,IAAA,OAAO,EAAE,MAAA,EAAQ,KAAA,EAAO,YAAA,EAAc,EAAC,EAAE;AAAA,EAC3C;AAGA,EAAA,MAAM,WAAA,GAAc,KAAA,CAAM,IAAA,CAAK,IAAI,GAAA,CAAI,OAAA,CAAQ,GAAA,CAAI,CAAC,CAAA,KAAM,CAAA,CAAE,IAAI,CAAC,CAAC,CAAA;AAClE,EAAA,MAAM,QAAA,uBAAe,GAAA,EAA2B;AAChD,EAAA,MAAM,OAAA,CAAQ,GAAA;AAAA,IACZ,WAAA,CAAY,GAAA,CAAI,OAAO,IAAA,KAAS;AAC9B,MAAA,MAAM,KAAA,GAAQ,MAAM,QAAA,CAAS,IAAI,CAAA;AACjC,MAAA,IAAI,KAAA,KAAU,IAAA,EAAM,qBAAA,CAAsB,IAAA,EAAM,KAAK,CAAA;AACrD,MAAA,QAAA,CAAS,GAAA,CAAI,MAAM,KAAK,CAAA;AAAA,IAC1B,CAAC;AAAA,GACH;AAIA,EAAA,IAAI,MAAA,GAAS,KAAA;AACb,EAAA,KAAA,IAAS,IAAI,OAAA,CAAQ,MAAA,GAAS,CAAA,EAAG,CAAA,IAAK,GAAG,CAAA,EAAA,EAAK;AAC5C,IAAA,MAAM,EAAE,IAAA,EAAM,KAAA,EAAO,GAAA,EAAI,GAAI,QAAQ,CAAC,CAAA;AACtC,IAAA,MAAM,KAAA,GAAQ,QAAA,CAAS,GAAA,CAAI,IAAI,CAAA,IAAK,IAAA;AACpC,IAAA,IAAI,UAAU,IAAA,EAAM;AAClB,MAAA,MAAA,GAAS,MAAA,CAAO,MAAM,CAAA,EAAG,KAAK,IAAI,KAAA,GAAQ,MAAA,CAAO,MAAM,GAAG,CAAA;AAAA,IAC5D;AAAA,EAEF;AACA,EAAA,KAAA,MAAW,EAAE,IAAA,EAAK,IAAK,OAAA,EAAS;AAC9B,IAAA,YAAA,CAAa,IAAA,CAAK,EAAE,IAAA,EAAM,QAAA,EAAU,SAAS,GAAA,CAAI,IAAI,CAAA,KAAM,IAAA,EAAM,CAAA;AAAA,EACnE;AAEA,EAAA,OAAO,EAAE,QAAQ,YAAA,EAAa;AAChC;AASO,SAAS,kBAAkB,IAAA,EAAsB;AACtD,EAAA,IAAI,CAAC,oBAAA,CAAqB,IAAA,CAAK,IAAI,CAAA,EAAG;AACpC,IAAA,MAAM,IAAI,uBAAA;AAAA,MACR,0BAAA;AAAA,MACA,qBAAqB,IAAI,CAAA,6BAAA;AAAA,KAC3B;AAAA,EACF;AACA,EAAA,OAAO,YAAY,IAAI,CAAA,GAAA,CAAA;AACzB;AAIO,IAAM,uBAAA,GAAN,cAAsC,KAAA,CAAM;AAAA,EACxC,IAAA;AAAA,EACT,WAAA,CAAY,MAAc,OAAA,EAAiB;AACzC,IAAA,KAAA,CAAM,OAAO,CAAA;AACb,IAAA,IAAA,CAAK,IAAA,GAAO,IAAA;AACZ,IAAA,IAAA,CAAK,IAAA,GAAO,yBAAA;AAAA,EACd;AACF;;;ACxJA,eAAsB,wBAAA,CACpB,QAAA,EACA,QAAA,EACA,IAAA,EACiC;AACjC,EAAA,MAAM,OAAA,GAAU,MAAM,QAAA,CAAS,cAAA,CAAe;AAAA,IAC5C,MAAM,QAAA,CAAS,cAAA;AAAA,IACf,QAAQ,QAAA,CAAS,MAAA;AAAA,IACjB,QAAQ,IAAA,EAAM;AAAA,GACf,CAAA;AACD,EAAA,KAAA,MAAW,CAAC,IAAA,EAAM,KAAK,KAAK,MAAA,CAAO,OAAA,CAAQ,OAAO,CAAA,EAAG;AACnD,IAAA,qBAAA,CAAsB,MAAM,KAAK,CAAA;AAAA,EACnC;AACA,EAAA,OAAO,OAAA;AACT","file":"index.mjs","sourcesContent":["/**\n * SecretExposure — describes HOW a secret value reaches the runtime\n * that needs it (env var, config file, egress placeholder, MCP-header\n * injection, future HTTP-bearer routing, …).\n *\n * Distinct from `SecretEntry` (AIP-19), which describes the secret's\n * *declaration* (slug, kind, access policy). Exposure is a *runtime*\n * concern — same secret might be exposed multiple ways across hosts.\n *\n * Discriminated union by `kind` so each new mechanism slots in as one\n * variant rather than another top-level field on whatever catalog the\n * host uses to map secrets onto agent runtimes.\n *\n * # Why this lives here (not in @agentproto/egress)\n * The substitution sigil + the \"what surfaces does this secret have\"\n * vocabulary are properties of the secret itself — they describe its\n * exposure surface independent of WHO consumes it. Egress is one\n * consumer; future ones (MCP servers, HTTP relays) are others.\n *\n * The egress *gating* (mode registry, proxy core) lives in\n * @agentproto/egress because that's a different concern (network-\n * boundary control). Egress imports from here.\n */\n\n/** Function applied to the seed value before write. Receives the raw\n * secret value (or empty string when `field` is omitted) plus an\n * optional context bag the host populates. Returns the file body. */\nexport type SecretExposureWrap = (\n value: string,\n ctx?: SecretExposureWrapContext\n) => string\n\n/** Generic context passed to `wrap` callbacks. Hosts populate fields\n * they have; wraps that don't care ignore the second arg entirely.\n * Kept open-ended (string-keyed) so hosts can attach app-specific\n * data without forcing a schema change here. */\nexport interface SecretExposureWrapContext {\n [key: string]: unknown\n}\n\n/** Inject the secret value as a process env var inside the runtime. */\nexport interface EnvExposure {\n kind: \"env\"\n /** Env var name as the runtime sees it. */\n name: string\n /** Field on the secret/connector settings whose value seeds the env.\n * Required for env exposures — env vars don't have a `wrap` path. */\n field: string\n}\n\n/** Drop a file inside the runtime's filesystem before any process\n * starts. Path uses `~` expansion against the runtime's exec user\n * home (host-resolved). */\nexport interface FileExposure {\n kind: \"file\"\n /** Absolute path or `~`-relative path inside the runtime sandbox. */\n path: string\n /** Field on the secret/connector settings whose value seeds the file\n * body. Omit when `wrap` produces synthetic content (e.g. claude's\n * `.claude.json` migration flags don't depend on a token). */\n field?: string\n /** POSIX file mode. Default `0o600`. */\n mode?: number\n /** Transform applied before write — see SecretExposureWrap. */\n wrap?: SecretExposureWrap\n}\n\n/**\n * Mark this secret as eligible for substitution at the egress proxy.\n * Agents see only `$$SECRET[<placeholderName>]$$` placeholders; the\n * proxy substitutes the real value at the network boundary.\n *\n * The actual proxy + sigil regex + substitution engine live in\n * `@agentproto/egress` — this exposure variant just declares the\n * intent + the per-secret defaults the host install handler stamps.\n */\nexport interface EgressSubstituteExposure {\n kind: \"egress-substitute\"\n /** The token agents reference in `$$SECRET[NAME]$$`. By convention\n * this matches the env-exposure name on the same secret, but it\n * doesn't have to — placeholders and env vars are independent. */\n placeholderName: string\n /** Default value for the per-secret allowlist flag stamped at install\n * time. UI may offer a per-install override. When false, the secret\n * is declared egress-aware but rejected by the resolver until an\n * admin opts in. */\n allowedByDefault: boolean\n /** Audit / UX hint — the providers this secret is *meant* for. NOT\n * enforced at egress (proxy substitutes any matching placeholder\n * regardless of upstream); the field exists so UIs can surface\n * \"this secret is for OpenAI\" without parsing the slug. */\n intendedProviders?: string[]\n}\n\n/** Inject the secret as an HTTP header on an MCP server's transport,\n * resolved fresh at connect-time via a credential broker. The broker\n * (not this exposure) owns refresh/rotation — this variant just names\n * WHICH credential and, optionally, the upstream server. */\nexport interface McpHeaderExposure {\n kind: \"mcp-header\"\n /** Broker path: \"<providerId>\" or \"<providerId>/<account>\". */\n credentialPath: string\n /** Optional upstream server / apiBase override forwarded to the\n * broker. Omit to let the broker use the provider's default. */\n server?: string\n}\n\n/**\n * Discriminated union of all exposure mechanisms. Add new variants here\n * as new exposure surfaces are added (HTTP-bearer, etc.) — each adds one\n * variant, one switch case in consumers.\n */\nexport type SecretExposure =\n | EnvExposure\n | FileExposure\n | EgressSubstituteExposure\n | McpHeaderExposure\n\n/** Type guard — convenient for filtering an exposures array by kind. */\nexport function isExposureKind<K extends SecretExposure[\"kind\"]>(\n exposure: SecretExposure,\n kind: K\n): exposure is Extract<SecretExposure, { kind: K }> {\n return exposure.kind === kind\n}\n","/**\n * Sigil + substitution engine for `$$SECRET[NAME]$$` placeholders.\n *\n * Used by hosts that implement egress-time secret substitution (the\n * narrow case in `@agentproto/egress`'s cooperative mode), and any\n * other consumer that wants to materialize secrets only at the\n * boundary instead of in agent-process env.\n *\n * Sigil shape: `$$SECRET[<NAME>]$$` where `<NAME>` is `[A-Z_][A-Z0-9_]*`\n * (matches typical env-var naming). The double-`$$` boundary on both\n * sides plus the bracketed name means a single regex pass can extract\n * names without false positives on strings that happen to contain `$$`\n * elsewhere.\n *\n * # Security\n * Resolved values get a sanity check before substitution:\n * - Reject CR (`\\r`), LF (`\\n`), NUL (`\\0`) — header injection\n * - Reject empty strings — degenerate, almost always a bug\n *\n * Hosts that need stricter validation (length caps, charset narrowing)\n * wrap the resolver passed in; this layer only enforces the universal\n * \"won't break the wire\" guarantees.\n */\n\n/**\n * Match a single `$$SECRET[NAME]$$` placeholder. Capture group 1 is\n * the name. Use the global flag (`g`) when scanning a longer string;\n * the constant here is non-global so callers can `.exec()` reliably.\n *\n * Exported because some consumers (e.g. the host-side install form)\n * want to validate that a string contains no placeholder before\n * accepting user input — they can re-derive a global variant cheaply.\n */\nexport const SECRET_PLACEHOLDER_PATTERN = /\\$\\$SECRET\\[([A-Z_][A-Z0-9_]*)\\]\\$\\$/\n\n/** Global variant — used internally for scanning + substitution. */\nconst SECRET_PLACEHOLDER_PATTERN_G = new RegExp(\n SECRET_PLACEHOLDER_PATTERN.source,\n \"g\"\n)\n\n/** Resolver function the substitution engine calls per-name. Returns\n * the secret value or `null` when the name doesn't resolve. The\n * engine treats null as \"no substitution\" (placeholder remains in\n * the output). Hosts that prefer hard-fail-on-miss should throw from\n * the resolver; the engine propagates. */\nexport type SecretResolver = (name: string) => Promise<string | null> | string | null\n\n/** Outcome of a single substitution call. `replacements` includes one\n * entry per matched placeholder, in the order they appeared. Useful\n * for audit logs (\"this call substituted OPENAI_API_KEY\"). */\nexport interface SubstituteResult {\n output: string\n replacements: SubstitutionRecord[]\n}\n\nexport interface SubstitutionRecord {\n name: string\n /** True when the resolver returned a non-null value. False when the\n * resolver returned null (placeholder kept verbatim). */\n resolved: boolean\n}\n\n/**\n * Validate a resolved secret value before it's substituted. Throws\n * with a stable error code so hosts can map the failure to a 4xx\n * cleanly. Exported so resolvers that pre-fetch can run the same\n * check before handing values back.\n */\nexport function assertSafeSecretValue(name: string, value: string): void {\n if (value.length === 0) {\n throw new SecretSubstitutionError(\n \"secret_value_empty\",\n `Resolved value for '${name}' is empty.`\n )\n }\n // CR / LF / NUL break header framing and stdio respectively. Other\n // control chars are allowed — some legitimate tokens contain them\n // (rare, but a base64 with `\\t` would be wrongly rejected by a\n // broader filter).\n if (/[\\r\\n\\0]/.test(value)) {\n throw new SecretSubstitutionError(\n \"secret_value_unsafe\",\n `Resolved value for '${name}' contains forbidden control characters (CR/LF/NUL).`\n )\n }\n}\n\n/**\n * Substitute every `$$SECRET[NAME]$$` placeholder in `input` using\n * `resolver`. Returns the rewritten string + the list of names that\n * were touched (for audit).\n *\n * Async because resolvers usually decrypt or hit a vault. Even when\n * the resolver is synchronous, the result is a Promise — callers that\n * want the sync path can `await` it cheaply since the underlying work\n * is microtask-scheduled.\n *\n * Whole-string matches are NOT enforced — the placeholder may appear\n * anywhere inside the input (`Bearer $$SECRET[X]$$` is the common\n * case for HTTP Authorization headers). Hosts that want stricter\n * placement (e.g. body-substitution gated to specific JSON paths)\n * should pre-narrow the input before calling here.\n */\nexport async function substituteSecrets(\n input: string,\n resolver: SecretResolver\n): Promise<SubstituteResult> {\n const replacements: SubstitutionRecord[] = []\n // Two-pass: first find all matches + resolve concurrently, then\n // rewrite. Lets parallel resolvers (multiple secrets) overlap their\n // decrypt cost.\n const matches: Array<{ name: string; start: number; end: number }> = []\n let m: RegExpExecArray | null\n const scan = new RegExp(\n SECRET_PLACEHOLDER_PATTERN_G.source,\n SECRET_PLACEHOLDER_PATTERN_G.flags\n )\n while ((m = scan.exec(input)) !== null) {\n matches.push({\n name: m[1]!,\n start: m.index,\n end: m.index + m[0].length,\n })\n }\n if (matches.length === 0) {\n return { output: input, replacements: [] }\n }\n\n // Dedupe so multiple placeholders for the same name only resolve once.\n const uniqueNames = Array.from(new Set(matches.map((x) => x.name)))\n const resolved = new Map<string, string | null>()\n await Promise.all(\n uniqueNames.map(async (name) => {\n const value = await resolver(name)\n if (value !== null) assertSafeSecretValue(name, value)\n resolved.set(name, value)\n })\n )\n\n // Rewrite right-to-left so earlier substitutions don't shift\n // subsequent indices.\n let output = input\n for (let i = matches.length - 1; i >= 0; i--) {\n const { name, start, end } = matches[i]!\n const value = resolved.get(name) ?? null\n if (value !== null) {\n output = output.slice(0, start) + value + output.slice(end)\n }\n // Order-preserving record for audit (forward order).\n }\n for (const { name } of matches) {\n replacements.push({ name, resolved: resolved.get(name) !== null })\n }\n\n return { output, replacements }\n}\n\n/**\n * Convenience: format a placeholder string for a given name.\n * `formatPlaceholder(\"OPENAI_API_KEY\") === \"$$SECRET[OPENAI_API_KEY]$$\"`\n *\n * Throws on invalid names so a bug in the host can't accidentally\n * inject a placeholder that won't round-trip through the regex.\n */\nexport function formatPlaceholder(name: string): string {\n if (!/^[A-Z_][A-Z0-9_]*$/.test(name)) {\n throw new SecretSubstitutionError(\n \"invalid_placeholder_name\",\n `Placeholder name '${name}' must match [A-Z_][A-Z0-9_]*`\n )\n }\n return `$$SECRET[${name}]$$`\n}\n\n/** Stable error class — hosts catch by `.code` to map to user-facing\n * responses (typically 400 / 403 / 500). */\nexport class SecretSubstitutionError extends Error {\n readonly code: string\n constructor(code: string, message: string) {\n super(message)\n this.code = code\n this.name = \"SecretSubstitutionError\"\n }\n}\n","/**\n * Resolver for `McpHeaderExposure` — turns a broker path into ready-to-use\n * HTTP headers for an MCP server's transport.\n *\n * `@agentproto/secrets` stays dependency-free of `@agentproto/auth`: instead\n * of importing `CredentialBroker` directly, this module declares the\n * structural shape it needs (`McpHeaderResolver`). `CredentialBroker`\n * already satisfies it — no adapter required at call sites.\n */\n\nimport type { McpHeaderExposure } from \"./types.js\"\nimport { assertSafeSecretValue } from \"./substitute.js\"\n\n/** Structural shape a credential broker must satisfy to back\n * `resolveMcpHeaderExposure`. `CredentialBroker` from `@agentproto/auth`\n * matches this shape without any adapter. */\nexport interface McpHeaderResolver {\n resolveHeaders(o: {\n path: string\n server?: string\n signal?: AbortSignal\n }): Promise<Record<string, string>>\n}\n\n/**\n * Resolve `exposure` into a header map by delegating to `resolver`, then\n * guard every resolved header VALUE with `assertSafeSecretValue` before\n * returning it. This closes off header-injection: a broker (or whatever\n * sits behind it — a flow engine, a vault) that ever returns a value\n * containing CR/LF/NUL would otherwise let that value smuggle extra\n * header lines onto the MCP transport.\n */\nexport async function resolveMcpHeaderExposure(\n exposure: McpHeaderExposure,\n resolver: McpHeaderResolver,\n opts?: { signal?: AbortSignal }\n): Promise<Record<string, string>> {\n const headers = await resolver.resolveHeaders({\n path: exposure.credentialPath,\n server: exposure.server,\n signal: opts?.signal,\n })\n for (const [name, value] of Object.entries(headers)) {\n assertSafeSecretValue(name, value)\n }\n return headers\n}\n"]}
@@ -0,0 +1,89 @@
1
+ /**
2
+ * @agentproto/secrets/identity — the daemon's persistent cryptographic
3
+ * identity for E2E pairing (design: PAIRING / DESIGN §1).
4
+ *
5
+ * A daemon that accepts pairings needs a stable identity a client can pin:
6
+ * - an **X25519** keypair for key agreement (the client seals its hello to
7
+ * this key, and it is one of the two ECDH inputs to the session key), and
8
+ * - an **Ed25519** keypair for authenticity (the daemon signs the handshake
9
+ * transcript so the client — who learned the public halves out-of-band via
10
+ * the offer URL — can prove it is really talking to the daemon it scanned,
11
+ * not an evil rendezvous in the middle).
12
+ *
13
+ * Both keypairs are stored base64-DER (SPKI public / PKCS8 private), the exact
14
+ * shape `@agentproto/secrets/seal` already uses, so the identity file travels
15
+ * as plain JSON and the seal box can consume the X25519 public half verbatim.
16
+ *
17
+ * Everything here is `node:crypto` — X25519, Ed25519, SHA-256 — so the package
18
+ * keeps its zero-native-dependency footprint. The private halves never leave
19
+ * the identity file (mode 0600) and are never logged.
20
+ */
21
+ /** Current identity-file schema version. */
22
+ declare const IDENTITY_VERSION: 1;
23
+ /** Raised for every identity load/generate/sign/verify failure. The message
24
+ * is safe to surface — it never contains private key material. */
25
+ declare class IdentityError extends Error {
26
+ constructor(message: string);
27
+ }
28
+ /** One keypair, both halves base64-DER. Public = SPKI, private = PKCS8. */
29
+ interface IdentityKeyPair {
30
+ /** base64 DER (SPKI) public key — publishable. */
31
+ pub: string;
32
+ /** base64 DER (PKCS8) private key — secret. */
33
+ priv: string;
34
+ }
35
+ /**
36
+ * A daemon's persistent identity. Serialized verbatim to
37
+ * `~/.agentproto/identity.json` (0600). The `x25519` public half is the key a
38
+ * client seals its hello to; the `ed25519` public half is the key a client
39
+ * verifies the daemon's transcript signature against. Both public halves are
40
+ * carried in the offer URL.
41
+ */
42
+ interface DaemonIdentity {
43
+ v: typeof IDENTITY_VERSION;
44
+ /** Encryption / key-agreement keypair. */
45
+ x25519: IdentityKeyPair;
46
+ /** Signing / authenticity keypair. */
47
+ ed25519: IdentityKeyPair;
48
+ /** ISO-8601 creation timestamp. */
49
+ createdAt: string;
50
+ }
51
+ /**
52
+ * Mint a fresh daemon identity: one X25519 keypair (encryption) and one
53
+ * Ed25519 keypair (signing). Called lazily on first `pair offer`.
54
+ */
55
+ declare function generateIdentity(): DaemonIdentity;
56
+ /**
57
+ * Stable short identifier for a daemon, derived from its X25519 public key —
58
+ * the same construction as `sealKeyId` in `@agentproto/secrets/seal` (first 16
59
+ * hex of `sha256(pub DER)`). Displayed everywhere a human confirms identity
60
+ * (offer QR, `pair accept`, `pair ls`). Not a secret.
61
+ */
62
+ declare function identityFingerprint(x25519Pub: string): string;
63
+ /**
64
+ * Load the daemon identity from `filePath`, creating it on first use. The
65
+ * caller supplies the path (typically `~/.agentproto/identity.json`) so this
66
+ * module stays free of any home-dir policy.
67
+ *
68
+ * The private halves are secret, so a freshly created file is written 0600 and
69
+ * atomically (temp file in the same directory + `rename`, so a crash mid-write
70
+ * can never leave a half-written identity or a world-readable window). A
71
+ * malformed existing file is a hard error — never silently overwritten, since
72
+ * that would rotate the daemon's identity and orphan every existing pairing.
73
+ */
74
+ declare function loadOrCreateIdentity(filePath: string): Promise<DaemonIdentity>;
75
+ /**
76
+ * Sign a handshake transcript with the daemon's Ed25519 private key. Returns a
77
+ * base64 signature. `transcript` is the exact bytes both sides agree on
78
+ * (`sha256(e_pub ‖ ct₀ ‖ d_e_pub)`); signing it — not the raw messages — is
79
+ * what binds the daemon's authenticity to the whole exchange.
80
+ */
81
+ declare function signTranscript(ed25519Priv: string, transcript: Uint8Array): string;
82
+ /**
83
+ * Verify a transcript signature against a daemon's Ed25519 public key. Returns
84
+ * a boolean — never throws on a bad signature (only on a structurally invalid
85
+ * key), so callers branch on the result rather than a control-flow exception.
86
+ */
87
+ declare function verifyTranscript(ed25519Pub: string, transcript: Uint8Array, signature: string): boolean;
88
+
89
+ export { type DaemonIdentity, IDENTITY_VERSION, IdentityError, type IdentityKeyPair, generateIdentity, identityFingerprint, loadOrCreateIdentity, signTranscript, verifyTranscript };
@@ -0,0 +1,3 @@
1
+ export { IDENTITY_VERSION, IdentityError, generateIdentity, identityFingerprint, loadOrCreateIdentity, signTranscript, verifyTranscript } from '../chunk-2DL6W33G.mjs';
2
+ //# sourceMappingURL=index.mjs.map
3
+ //# sourceMappingURL=index.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":[],"names":[],"mappings":"","file":"index.mjs"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,6 @@
1
- import { S as SecretsDefinition } from './types-Clav8IDA.js';
2
- export { a as SecretsHandle } from './types-Clav8IDA.js';
3
- import './types-C2dZDHn7.js';
1
+ import { S as SecretsDefinition } from './types-CHQpxFPe.js';
2
+ export { a as SecretsHandle } from './types-CHQpxFPe.js';
3
+ import './types-DS9Qe9Cv.js';
4
4
 
5
5
  /**
6
6
  * AIP-19 reference implementation of `defineSecrets`.
@@ -1,6 +1,6 @@
1
1
  import { z } from 'zod';
2
- import { a as SecretsHandle } from '../types-Clav8IDA.js';
3
- import '../types-C2dZDHn7.js';
2
+ import { a as SecretsHandle } from '../types-CHQpxFPe.js';
3
+ import '../types-DS9Qe9Cv.js';
4
4
 
5
5
  /**
6
6
  * AIP-19 SECRETS.md frontmatter zod schema.