@agentproto/secrets 0.2.6 → 1.0.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.
Files changed (40) hide show
  1. package/dist/{chunk-Q6K3AT3V.mjs → chunk-2FHFW2AU.mjs} +3 -3
  2. package/dist/{chunk-Q6K3AT3V.mjs.map → chunk-2FHFW2AU.mjs.map} +1 -1
  3. package/dist/chunk-3YRYO6LK.mjs +222 -0
  4. package/dist/chunk-3YRYO6LK.mjs.map +1 -0
  5. package/dist/chunk-432SC3XS.mjs +100 -0
  6. package/dist/chunk-432SC3XS.mjs.map +1 -0
  7. package/dist/chunk-5HUHYBPR.mjs +69 -0
  8. package/dist/chunk-5HUHYBPR.mjs.map +1 -0
  9. package/dist/{chunk-NLZ5HXGO.mjs → chunk-7V6U6DII.mjs} +4 -4
  10. package/dist/{chunk-NLZ5HXGO.mjs.map → chunk-7V6U6DII.mjs.map} +1 -1
  11. package/dist/chunk-JNTDSOZQ.mjs +623 -0
  12. package/dist/chunk-JNTDSOZQ.mjs.map +1 -0
  13. package/dist/chunk-NQX3KBPW.mjs +50 -0
  14. package/dist/chunk-NQX3KBPW.mjs.map +1 -0
  15. package/dist/chunk-PCFPJ47T.mjs +28 -0
  16. package/dist/chunk-PCFPJ47T.mjs.map +1 -0
  17. package/dist/cli.mjs +10 -7
  18. package/dist/cli.mjs.map +1 -1
  19. package/dist/core-CIn0-z-Y.d.ts +42 -0
  20. package/dist/core-D8zVNPDb.d.ts +58 -0
  21. package/dist/identity/index.d.ts +25 -46
  22. package/dist/identity/index.mjs +76 -1
  23. package/dist/identity/index.mjs.map +1 -1
  24. package/dist/pairing/browser.d.ts +18 -0
  25. package/dist/pairing/browser.mjs +6 -0
  26. package/dist/pairing/browser.mjs.map +1 -0
  27. package/dist/pairing/index.d.ts +45 -440
  28. package/dist/pairing/index.mjs +33 -465
  29. package/dist/pairing/index.mjs.map +1 -1
  30. package/dist/provision/index.mjs +5 -2
  31. package/dist/provision/recipe/index.mjs +6 -3
  32. package/dist/seal/index.d.ts +21 -31
  33. package/dist/seal/index.mjs +4 -1
  34. package/dist/types-B2ZfEhsU.d.ts +57 -0
  35. package/dist/webcrypto-BU57p0_g.d.ts +652 -0
  36. package/package.json +8 -2
  37. package/dist/chunk-2DL6W33G.mjs +0 -126
  38. package/dist/chunk-2DL6W33G.mjs.map +0 -1
  39. package/dist/chunk-MVHOJPML.mjs +0 -132
  40. package/dist/chunk-MVHOJPML.mjs.map +0 -1
@@ -1,4 +1,4 @@
1
- import { resolveCredential, extractJsonPath } from './chunk-NLZ5HXGO.mjs';
1
+ import { resolveCredential, extractJsonPath } from './chunk-7V6U6DII.mjs';
2
2
  import { z } from 'zod';
3
3
  import { createDoctype } from '@agentproto/define-doctype';
4
4
  import matter from 'gray-matter';
@@ -278,5 +278,5 @@ async function resolveKeychain(source) {
278
278
  }
279
279
 
280
280
  export { BUILTIN_RECIPES, claudeCodeOauthRecipe, codexRecipe, credentialSourceSpecSchema, defineProvisionRecipe, geminiRecipe, getRecipe, listRecipeIds, listRecipes, parseRecipeManifest, parseRecipeManifestRaw, provisionRecipeFrontmatterSchema, recipeMethodSchema, registerRecipe, resolveRecipeMethod, resolveSourceSpec };
281
- //# sourceMappingURL=chunk-Q6K3AT3V.mjs.map
282
- //# sourceMappingURL=chunk-Q6K3AT3V.mjs.map
281
+ //# sourceMappingURL=chunk-2FHFW2AU.mjs.map
282
+ //# sourceMappingURL=chunk-2FHFW2AU.mjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/provision/recipe/schema.ts","../src/provision/recipe/define-recipe.ts","../src/provision/recipe/manifest.ts","../src/provision/recipe/builtins.ts","../src/provision/recipe/registry.ts","../src/provision/recipe/resolve.ts"],"names":[],"mappings":"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","file":"chunk-Q6K3AT3V.mjs","sourcesContent":["/**\n * Provision-recipe frontmatter / literal zod schema.\n *\n * Single source of truth for both authoring paths: `defineProvisionRecipe`\n * (TS literal) and `parseRecipeManifest` (.md) run this same schema, so a\n * malformed literal and a malformed manifest fail identically — mirrors how\n * `secretsFrontmatterSchema` backs both `defineSecrets` and\n * `parseSecretsManifest`.\n *\n * Hand-written rather than scaffold-aip-generated: a recipe is not yet a\n * numbered-AIP artifact. Promote to a generated schema if it gets its own spec.\n */\n\nimport { z } from \"zod\"\n\n/** Exactly one of file / env / keychain / prompt. `value` is explicitly\n * forbidden — a recipe carries locations, never secrets. */\nexport const credentialSourceSpecSchema = z\n .union([\n z\n .object({\n file: z.string().min(1),\n jsonPath: z.string().min(1).optional(),\n })\n .strict(),\n z.object({ env: z.string().min(1) }).strict(),\n z\n .object({\n keychain: z.string().min(1),\n account: z.string().min(1).optional(),\n jsonPath: z.string().min(1).optional(),\n })\n .strict(),\n z.object({ prompt: z.string().min(1) }).strict(),\n ])\n .describe(\n \"Where a method's credential is read on the origin machine: a file (optionally a JSON field), an env var, the macOS Keychain, or an interactive prompt. Never a literal value.\",\n )\n\n/** A method's source: a single spec or an ordered fallback chain (first that\n * resolves wins). */\nexport const methodSourceSchema = z.union([\n credentialSourceSpecSchema,\n z.array(credentialSourceSpecSchema).min(1),\n])\n\nexport const recipeMethodSchema = z\n .object({\n id: z.string().min(1),\n label: z.string().min(1).optional(),\n source: methodSourceSchema,\n })\n .strict()\n\nexport const provisionRecipeFrontmatterSchema = z\n .object({\n id: z.string().min(2).max(80),\n description: z.string().min(1).max(2000),\n methods: z.array(recipeMethodSchema).min(1),\n label: z.string().min(1).optional(),\n })\n .strict()\n .describe(\n \"A credential-provision recipe: for one provider, the installable flavors (methods) and where each flavor's credential lives locally. Holds locations, never values.\",\n )\n\nexport type ProvisionRecipeFrontmatter = z.infer<\n typeof provisionRecipeFrontmatterSchema\n>\n","/**\n * `defineProvisionRecipe` — the TS-literal authoring path for a recipe.\n *\n * Built on `createDoctype` so a recipe gets the same cross-AIP invariants as\n * every other doctype: id-pattern check, ≤2000-char description, frozen handle,\n * canonical \"defineProvisionRecipe (AIP-19): …\" error prefix. Field-level\n * validation runs the shared zod from `./schema.ts`, so a malformed literal\n * fails with the same diagnostic as a malformed `.md`.\n */\n\nimport { createDoctype } from \"@agentproto/define-doctype\"\nimport { provisionRecipeFrontmatterSchema } from \"./schema.js\"\nimport type {\n ProvisionRecipe,\n ProvisionRecipeDefinition,\n} from \"./types.js\"\n\nexport const defineProvisionRecipe = createDoctype<\n ProvisionRecipeDefinition,\n ProvisionRecipe\n>({\n aip: 19,\n name: \"provisionRecipe\",\n validate(def) {\n const result = provisionRecipeFrontmatterSchema.safeParse(def)\n if (!result.success) {\n throw new Error(\n `defineProvisionRecipe (AIP-19): ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n },\n build(def) {\n return {\n ...def,\n methods: def.methods.map((m) => Object.freeze({ ...m })) as ProvisionRecipe[\"methods\"],\n }\n },\n})\n","/**\n * `.md` authoring path for a provision recipe — parse a frontmatter manifest\n * into a frozen handle. Mirrors `parseSecretsManifest`: gray-matter splits the\n * frontmatter, the shared zod validates it, `defineProvisionRecipe` builds the\n * handle so the `.md` and TS-literal paths converge on one validated shape.\n *\n * The package ships its builtin recipes as TS literals (they bundle with zero\n * fs); this parser is for a HOST that reads its own external `.md` recipes and\n * registers them — the extension seam.\n */\n\nimport matter from \"gray-matter\"\nimport {\n provisionRecipeFrontmatterSchema,\n type ProvisionRecipeFrontmatter,\n} from \"./schema.js\"\nimport { defineProvisionRecipe } from \"./define-recipe.js\"\nimport type { ProvisionRecipe, ProvisionRecipeDefinition } from \"./types.js\"\n\nexport interface ProvisionRecipeManifest {\n frontmatter: ProvisionRecipeFrontmatter\n body: string\n}\n\nexport function parseRecipeManifestRaw(\n source: string,\n): ProvisionRecipeManifest {\n const parsed = matter(source)\n if (Object.keys(parsed.data).length === 0) {\n throw new Error(\"parseRecipeManifest: missing or empty frontmatter\")\n }\n const result = provisionRecipeFrontmatterSchema.safeParse(parsed.data)\n if (!result.success) {\n throw new Error(\n `parseRecipeManifest: invalid frontmatter — ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n return { frontmatter: result.data, body: parsed.content }\n}\n\n/** Parse a recipe `.md` straight to a frozen handle (frontmatter →\n * `defineProvisionRecipe`). */\nexport function parseRecipeManifest(source: string): ProvisionRecipe {\n const { frontmatter } = parseRecipeManifestRaw(source)\n return defineProvisionRecipe(\n frontmatter as unknown as ProvisionRecipeDefinition,\n )\n}\n","/**\n * Builtin provision recipes — the credential providers the flow knows out of\n * the box. Shipped as TS literals (not `.md`) so they bundle into the tsup\n * output with zero filesystem read at runtime. A host adds more by parsing its\n * own `.md` with `parseRecipeManifest` and `registerRecipe`-ing the result.\n *\n * Each recipe describes the credential's PUBLIC local convention for that CLI\n * (where it writes its token) — no vendor's private infra, no values.\n */\n\nimport { defineProvisionRecipe } from \"./define-recipe.js\"\nimport type { ProvisionRecipe } from \"./types.js\"\n\n/** Claude Code subscription OAuth token. macOS stores it in the login Keychain;\n * Linux writes it to ~/.claude/.credentials.json. Try the Keychain first, fall\n * back to the file, so one recipe spans both. */\nexport const claudeCodeOauthRecipe = defineProvisionRecipe({\n id: \"claude-code-oauth\",\n description:\n \"Claude Code subscription OAuth access token, read from the macOS Keychain or the local CLI's credential file.\",\n label: \"Claude Code (subscription)\",\n methods: [\n {\n id: \"subscription-token\",\n source: [\n {\n keychain: \"Claude Code-credentials\",\n jsonPath: \"claudeAiOauth.accessToken\",\n },\n {\n file: \"~/.claude/.credentials.json\",\n jsonPath: \"claudeAiOauth.accessToken\",\n },\n ],\n },\n ],\n})\n\n/** Codex CLI — two flavors: the subscription OAuth token, or a raw API key. */\nexport const codexRecipe = defineProvisionRecipe({\n id: \"codex\",\n description:\n \"OpenAI Codex CLI credential — either the subscription OAuth access token from the local auth file, or an API key from the environment.\",\n label: \"Codex\",\n methods: [\n {\n id: \"oauth-subscription\",\n label: \"Codex (subscription)\",\n source: { file: \"~/.codex/auth.json\", jsonPath: \"tokens.access_token\" },\n },\n {\n id: \"api-key\",\n label: \"Codex (API key)\",\n source: { env: \"OPENAI_API_KEY\" },\n },\n ],\n})\n\n/** opencode — Anthropic (Claude Pro/Max) OAuth login stored by the CLI's own\n * `opencode auth login` flow. opencode keeps its auth store under the XDG\n * data dir on every platform (macOS included — verified live). The entry\n * shape is `{anthropic: {type: \"oauth\", access, refresh, expires}}`.\n *\n * `openai-oauth` covers opencode's separate \"ChatGPT Pro/Plus\" OAuth login\n * (`opencode auth login` → select provider \"openai\", browser or headless\n * device-code flow against auth.openai.com). Reverse-engineered from the\n * shipped binary (`~/.opencode/bin/opencode`, no OSS source for this build\n * available to read directly): the plugin registers its two OAuth methods\n * under `integrationID: R.ID.make(\"openai\")`, and the generic provider-login\n * handler (`Cli.providers.login` → `Cli.providers.pluginAuth`) writes the\n * credential via `Auth.set(provider.id, {type:\"oauth\", access, refresh,\n * expires, ...})` where `provider.id` is the SAME \"openai\" id the user\n * selected — there is no separate \"chatgpt\" key. This mirrors exactly how\n * the already-verified `anthropic` entry is keyed by provider id, so the\n * ChatGPT login lands at `openai.access` in the same auth.json. */\nexport const opencodeRecipe = defineProvisionRecipe({\n id: \"opencode\",\n description:\n \"opencode's Claude Pro/Max and ChatGPT Pro/Plus subscription OAuth access tokens, read from the CLI's own auth store (written by `opencode auth login`).\",\n label: \"opencode (Claude/ChatGPT subscription)\",\n methods: [\n {\n id: \"anthropic-oauth\",\n source: {\n file: \"~/.local/share/opencode/auth.json\",\n jsonPath: \"anthropic.access\",\n },\n },\n {\n id: \"openai-oauth\",\n source: {\n file: \"~/.local/share/opencode/auth.json\",\n jsonPath: \"openai.access\",\n },\n },\n ],\n})\n\n/** mastracode — two independent OAuth logins from the TUI's own `/login`\n * flow. mastracode's app-data dir is platform-dependent (`getAppDataDir()`\n * in its source: Application Support on macOS, XDG data dir elsewhere).\n *\n * `anthropic-oauth`: Claude Pro/Max login, entry shape `{anthropic:\n * {type: \"oauth\", access, refresh, expires}}` — verified against a live\n * login.\n *\n * `openai-oauth`: ChatGPT login via mastracode's `openaiCodexOAuthProvider`,\n * stored under the DISTINCT key `openai-codex` (not `openai` — mastracode's\n * own naming, unrelated to opencode's), entry shape `{\"openai-codex\":\n * {type: \"oauth\", access, refresh, expires, accountId}}` — also verified\n * against a live login on this machine. */\nexport const mastracodeRecipe = defineProvisionRecipe({\n id: \"mastracode\",\n description:\n \"mastracode's Claude Pro/Max and ChatGPT subscription OAuth access tokens, read from the CLI's own auth store (written by its /login flow).\",\n label: \"mastracode (Claude/ChatGPT subscription)\",\n methods: [\n {\n id: \"anthropic-oauth\",\n source: [\n {\n file: \"~/Library/Application Support/mastracode/auth.json\",\n jsonPath: \"anthropic.access\",\n },\n {\n file: \"~/.local/share/mastracode/auth.json\",\n jsonPath: \"anthropic.access\",\n },\n ],\n },\n {\n id: \"openai-oauth\",\n source: [\n {\n file: \"~/Library/Application Support/mastracode/auth.json\",\n jsonPath: \"openai-codex.access\",\n },\n {\n file: \"~/.local/share/mastracode/auth.json\",\n jsonPath: \"openai-codex.access\",\n },\n ],\n },\n ],\n})\n\n/** Gemini CLI OAuth token written by the local CLI. */\nexport const geminiRecipe = defineProvisionRecipe({\n id: \"gemini\",\n description:\n \"Google Gemini CLI OAuth access token, read from the local CLI's credential cache.\",\n label: \"Gemini\",\n methods: [\n {\n id: \"oauth-token\",\n source: {\n file: \"~/.gemini/oauth_creds.json\",\n jsonPath: \"access_token\",\n },\n },\n ],\n})\n\nexport const BUILTIN_RECIPES: readonly ProvisionRecipe[] = [\n claudeCodeOauthRecipe,\n codexRecipe,\n geminiRecipe,\n opencodeRecipe,\n mastracodeRecipe,\n]\n","/**\n * Provision-recipe registry — id → recipe lookup, pre-seeded with the builtins.\n *\n * Mirrors the host-side OAuth-provider registry shape: a module-level Map a\n * caller resolves by id at provision time, plus a `registerRecipe` seam so a\n * host can add recipes parsed from its own `.md` (`parseRecipeManifest`)\n * without editing this package. Re-registering an id overrides it — last write\n * wins, so a host can shadow a builtin.\n */\n\nimport { BUILTIN_RECIPES } from \"./builtins.js\"\nimport type { ProvisionRecipe, RecipeMethod } from \"./types.js\"\n\nconst _registry = new Map<string, ProvisionRecipe>()\nfor (const r of BUILTIN_RECIPES) _registry.set(r.id, r)\n\nexport function registerRecipe(recipe: ProvisionRecipe): void {\n _registry.set(recipe.id, recipe)\n}\n\nexport function getRecipe(id: string): ProvisionRecipe | undefined {\n return _registry.get(id)\n}\n\nexport function listRecipes(): ProvisionRecipe[] {\n return [..._registry.values()]\n}\n\nexport function listRecipeIds(): string[] {\n return [..._registry.keys()]\n}\n\n/**\n * Resolve a recipe + one of its methods. `methodId` selects among the recipe's\n * flavors; omitted picks the first (default). Throws a caller-friendly error\n * naming the available methods when the id is unknown or ambiguous.\n */\nexport function resolveRecipeMethod(\n id: string,\n methodId?: string,\n): { recipe: ProvisionRecipe; method: RecipeMethod } {\n const recipe = getRecipe(id)\n if (!recipe) {\n throw new Error(\n `unknown provider '${id}' — known: ${listRecipeIds().join(\", \") || \"(none)\"}`,\n )\n }\n if (!methodId) {\n return { recipe, method: recipe.methods[0] }\n }\n const method = recipe.methods.find((m) => m.id === methodId)\n if (!method) {\n throw new Error(\n `provider '${id}' has no method '${methodId}' — methods: ${recipe.methods\n .map((m) => m.id)\n .join(\", \")}`,\n )\n }\n return { recipe, method }\n}\n","/**\n * Resolve a recipe method's source to plaintext.\n *\n * A source is a single `CredentialSourceSpec` or an ordered fallback chain\n * (array) — the first that resolves wins, so one recipe spans platforms\n * (macOS Keychain → file). Bridges onto `resolveCredential` (file / env), the\n * macOS `security` Keychain, and an injected prompt impl (interactive, e.g. a\n * website password for a remote browser). The prompt impl is INJECTED — no\n * hard TTY dependency at import, same discipline as `fetchImpl` on\n * `httpTarget`. The result is sensitive: seal it immediately, never print it.\n */\n\nimport { resolveCredential, extractJsonPath } from \"../index.js\"\nimport type { CredentialSourceSpec } from \"./types.js\"\n\nexport interface ResolveSourceOptions {\n /** Asked for a `{ prompt }` source. Receives the prompt text, returns the\n * entered value. Required only when a method uses a prompt source. */\n promptImpl?: (prompt: string) => Promise<string>\n}\n\nexport async function resolveSourceSpec(\n source: CredentialSourceSpec | CredentialSourceSpec[],\n opts: ResolveSourceOptions = {},\n): Promise<string> {\n const chain = Array.isArray(source) ? source : [source]\n const errors: string[] = []\n for (const spec of chain) {\n try {\n return await resolveOne(spec, opts)\n } catch (err) {\n errors.push(err instanceof Error ? err.message : String(err))\n }\n }\n throw new Error(`no credential source resolved (${errors.join(\"; \")})`)\n}\n\nasync function resolveOne(\n source: CredentialSourceSpec,\n opts: ResolveSourceOptions,\n): Promise<string> {\n if (\"env\" in source) {\n return resolveCredential({ fromEnv: source.env })\n }\n if (\"file\" in source) {\n return resolveCredential({\n fromFile: source.file,\n ...(source.jsonPath ? { jsonPath: source.jsonPath } : {}),\n })\n }\n if (\"keychain\" in source) {\n return resolveKeychain(source)\n }\n // prompt\n if (!opts.promptImpl) {\n throw new Error(\n `credential source needs an interactive prompt but no promptImpl was provided`,\n )\n }\n const value = await opts.promptImpl(source.prompt)\n if (!value) throw new Error(\"prompt returned an empty credential\")\n return value\n}\n\nasync function resolveKeychain(source: {\n keychain: string\n account?: string\n jsonPath?: string\n}): Promise<string> {\n if (process.platform !== \"darwin\") {\n throw new Error(\"keychain source is macOS-only\")\n }\n const { execFileSync } = await import(\"node:child_process\")\n const args = [\"find-generic-password\", \"-w\", \"-s\", source.keychain]\n if (source.account) args.push(\"-a\", source.account)\n let raw: string\n try {\n raw = execFileSync(\"security\", args, { encoding: \"utf8\" }).trim()\n } catch {\n throw new Error(`keychain item '${source.keychain}' not found`)\n }\n if (!raw) throw new Error(`keychain item '${source.keychain}' is empty`)\n return source.jsonPath ? extractJsonPath(raw, source.jsonPath) : raw\n}\n"]}
1
+ {"version":3,"sources":["../src/provision/recipe/schema.ts","../src/provision/recipe/define-recipe.ts","../src/provision/recipe/manifest.ts","../src/provision/recipe/builtins.ts","../src/provision/recipe/registry.ts","../src/provision/recipe/resolve.ts"],"names":[],"mappings":"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","file":"chunk-2FHFW2AU.mjs","sourcesContent":["/**\n * Provision-recipe frontmatter / literal zod schema.\n *\n * Single source of truth for both authoring paths: `defineProvisionRecipe`\n * (TS literal) and `parseRecipeManifest` (.md) run this same schema, so a\n * malformed literal and a malformed manifest fail identically — mirrors how\n * `secretsFrontmatterSchema` backs both `defineSecrets` and\n * `parseSecretsManifest`.\n *\n * Hand-written rather than scaffold-aip-generated: a recipe is not yet a\n * numbered-AIP artifact. Promote to a generated schema if it gets its own spec.\n */\n\nimport { z } from \"zod\"\n\n/** Exactly one of file / env / keychain / prompt. `value` is explicitly\n * forbidden — a recipe carries locations, never secrets. */\nexport const credentialSourceSpecSchema = z\n .union([\n z\n .object({\n file: z.string().min(1),\n jsonPath: z.string().min(1).optional(),\n })\n .strict(),\n z.object({ env: z.string().min(1) }).strict(),\n z\n .object({\n keychain: z.string().min(1),\n account: z.string().min(1).optional(),\n jsonPath: z.string().min(1).optional(),\n })\n .strict(),\n z.object({ prompt: z.string().min(1) }).strict(),\n ])\n .describe(\n \"Where a method's credential is read on the origin machine: a file (optionally a JSON field), an env var, the macOS Keychain, or an interactive prompt. Never a literal value.\",\n )\n\n/** A method's source: a single spec or an ordered fallback chain (first that\n * resolves wins). */\nexport const methodSourceSchema = z.union([\n credentialSourceSpecSchema,\n z.array(credentialSourceSpecSchema).min(1),\n])\n\nexport const recipeMethodSchema = z\n .object({\n id: z.string().min(1),\n label: z.string().min(1).optional(),\n source: methodSourceSchema,\n })\n .strict()\n\nexport const provisionRecipeFrontmatterSchema = z\n .object({\n id: z.string().min(2).max(80),\n description: z.string().min(1).max(2000),\n methods: z.array(recipeMethodSchema).min(1),\n label: z.string().min(1).optional(),\n })\n .strict()\n .describe(\n \"A credential-provision recipe: for one provider, the installable flavors (methods) and where each flavor's credential lives locally. Holds locations, never values.\",\n )\n\nexport type ProvisionRecipeFrontmatter = z.infer<\n typeof provisionRecipeFrontmatterSchema\n>\n","/**\n * `defineProvisionRecipe` — the TS-literal authoring path for a recipe.\n *\n * Built on `createDoctype` so a recipe gets the same cross-AIP invariants as\n * every other doctype: id-pattern check, ≤2000-char description, frozen handle,\n * canonical \"defineProvisionRecipe (AIP-19): …\" error prefix. Field-level\n * validation runs the shared zod from `./schema.ts`, so a malformed literal\n * fails with the same diagnostic as a malformed `.md`.\n */\n\nimport { createDoctype } from \"@agentproto/define-doctype\"\nimport { provisionRecipeFrontmatterSchema } from \"./schema.js\"\nimport type {\n ProvisionRecipe,\n ProvisionRecipeDefinition,\n} from \"./types.js\"\n\nexport const defineProvisionRecipe = createDoctype<\n ProvisionRecipeDefinition,\n ProvisionRecipe\n>({\n aip: 19,\n name: \"provisionRecipe\",\n validate(def) {\n const result = provisionRecipeFrontmatterSchema.safeParse(def)\n if (!result.success) {\n throw new Error(\n `defineProvisionRecipe (AIP-19): ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n },\n build(def) {\n return {\n ...def,\n methods: def.methods.map((m) => Object.freeze({ ...m })) as ProvisionRecipe[\"methods\"],\n }\n },\n})\n","/**\n * `.md` authoring path for a provision recipe — parse a frontmatter manifest\n * into a frozen handle. Mirrors `parseSecretsManifest`: gray-matter splits the\n * frontmatter, the shared zod validates it, `defineProvisionRecipe` builds the\n * handle so the `.md` and TS-literal paths converge on one validated shape.\n *\n * The package ships its builtin recipes as TS literals (they bundle with zero\n * fs); this parser is for a HOST that reads its own external `.md` recipes and\n * registers them — the extension seam.\n */\n\nimport matter from \"gray-matter\"\nimport {\n provisionRecipeFrontmatterSchema,\n type ProvisionRecipeFrontmatter,\n} from \"./schema.js\"\nimport { defineProvisionRecipe } from \"./define-recipe.js\"\nimport type { ProvisionRecipe, ProvisionRecipeDefinition } from \"./types.js\"\n\nexport interface ProvisionRecipeManifest {\n frontmatter: ProvisionRecipeFrontmatter\n body: string\n}\n\nexport function parseRecipeManifestRaw(\n source: string,\n): ProvisionRecipeManifest {\n const parsed = matter(source)\n if (Object.keys(parsed.data).length === 0) {\n throw new Error(\"parseRecipeManifest: missing or empty frontmatter\")\n }\n const result = provisionRecipeFrontmatterSchema.safeParse(parsed.data)\n if (!result.success) {\n throw new Error(\n `parseRecipeManifest: invalid frontmatter — ${result.error.issues\n .map((i) => `${i.path.join(\".\")}: ${i.message}`)\n .join(\"; \")}`,\n )\n }\n return { frontmatter: result.data, body: parsed.content }\n}\n\n/** Parse a recipe `.md` straight to a frozen handle (frontmatter →\n * `defineProvisionRecipe`). */\nexport function parseRecipeManifest(source: string): ProvisionRecipe {\n const { frontmatter } = parseRecipeManifestRaw(source)\n return defineProvisionRecipe(\n frontmatter as unknown as ProvisionRecipeDefinition,\n )\n}\n","/**\n * Builtin provision recipes — the credential providers the flow knows out of\n * the box. Shipped as TS literals (not `.md`) so they bundle into the tsup\n * output with zero filesystem read at runtime. A host adds more by parsing its\n * own `.md` with `parseRecipeManifest` and `registerRecipe`-ing the result.\n *\n * Each recipe describes the credential's PUBLIC local convention for that CLI\n * (where it writes its token) — no vendor's private infra, no values.\n */\n\nimport { defineProvisionRecipe } from \"./define-recipe.js\"\nimport type { ProvisionRecipe } from \"./types.js\"\n\n/** Claude Code subscription OAuth token. macOS stores it in the login Keychain;\n * Linux writes it to ~/.claude/.credentials.json. Try the Keychain first, fall\n * back to the file, so one recipe spans both. */\nexport const claudeCodeOauthRecipe = defineProvisionRecipe({\n id: \"claude-code-oauth\",\n description:\n \"Claude Code subscription OAuth access token, read from the macOS Keychain or the local CLI's credential file.\",\n label: \"Claude Code (subscription)\",\n methods: [\n {\n id: \"subscription-token\",\n source: [\n {\n keychain: \"Claude Code-credentials\",\n jsonPath: \"claudeAiOauth.accessToken\",\n },\n {\n file: \"~/.claude/.credentials.json\",\n jsonPath: \"claudeAiOauth.accessToken\",\n },\n ],\n },\n ],\n})\n\n/** Codex CLI — two flavors: the subscription OAuth token, or a raw API key. */\nexport const codexRecipe = defineProvisionRecipe({\n id: \"codex\",\n description:\n \"OpenAI Codex CLI credential — either the subscription OAuth access token from the local auth file, or an API key from the environment.\",\n label: \"Codex\",\n methods: [\n {\n id: \"oauth-subscription\",\n label: \"Codex (subscription)\",\n source: { file: \"~/.codex/auth.json\", jsonPath: \"tokens.access_token\" },\n },\n {\n id: \"api-key\",\n label: \"Codex (API key)\",\n source: { env: \"OPENAI_API_KEY\" },\n },\n ],\n})\n\n/** opencode — Anthropic (Claude Pro/Max) OAuth login stored by the CLI's own\n * `opencode auth login` flow. opencode keeps its auth store under the XDG\n * data dir on every platform (macOS included — verified live). The entry\n * shape is `{anthropic: {type: \"oauth\", access, refresh, expires}}`.\n *\n * `openai-oauth` covers opencode's separate \"ChatGPT Pro/Plus\" OAuth login\n * (`opencode auth login` → select provider \"openai\", browser or headless\n * device-code flow against auth.openai.com). Reverse-engineered from the\n * shipped binary (`~/.opencode/bin/opencode`, no OSS source for this build\n * available to read directly): the plugin registers its two OAuth methods\n * under `integrationID: R.ID.make(\"openai\")`, and the generic provider-login\n * handler (`Cli.providers.login` → `Cli.providers.pluginAuth`) writes the\n * credential via `Auth.set(provider.id, {type:\"oauth\", access, refresh,\n * expires, ...})` where `provider.id` is the SAME \"openai\" id the user\n * selected — there is no separate \"chatgpt\" key. This mirrors exactly how\n * the already-verified `anthropic` entry is keyed by provider id, so the\n * ChatGPT login lands at `openai.access` in the same auth.json. */\nexport const opencodeRecipe = defineProvisionRecipe({\n id: \"opencode\",\n description:\n \"opencode's Claude Pro/Max and ChatGPT Pro/Plus subscription OAuth access tokens, read from the CLI's own auth store (written by `opencode auth login`).\",\n label: \"opencode (Claude/ChatGPT subscription)\",\n methods: [\n {\n id: \"anthropic-oauth\",\n source: {\n file: \"~/.local/share/opencode/auth.json\",\n jsonPath: \"anthropic.access\",\n },\n },\n {\n id: \"openai-oauth\",\n source: {\n file: \"~/.local/share/opencode/auth.json\",\n jsonPath: \"openai.access\",\n },\n },\n ],\n})\n\n/** mastracode — two independent OAuth logins from the TUI's own `/login`\n * flow. mastracode's app-data dir is platform-dependent (`getAppDataDir()`\n * in its source: Application Support on macOS, XDG data dir elsewhere).\n *\n * `anthropic-oauth`: Claude Pro/Max login, entry shape `{anthropic:\n * {type: \"oauth\", access, refresh, expires}}` — verified against a live\n * login.\n *\n * `openai-oauth`: ChatGPT login via mastracode's `openaiCodexOAuthProvider`,\n * stored under the DISTINCT key `openai-codex` (not `openai` — mastracode's\n * own naming, unrelated to opencode's), entry shape `{\"openai-codex\":\n * {type: \"oauth\", access, refresh, expires, accountId}}` — also verified\n * against a live login on this machine. */\nexport const mastracodeRecipe = defineProvisionRecipe({\n id: \"mastracode\",\n description:\n \"mastracode's Claude Pro/Max and ChatGPT subscription OAuth access tokens, read from the CLI's own auth store (written by its /login flow).\",\n label: \"mastracode (Claude/ChatGPT subscription)\",\n methods: [\n {\n id: \"anthropic-oauth\",\n source: [\n {\n file: \"~/Library/Application Support/mastracode/auth.json\",\n jsonPath: \"anthropic.access\",\n },\n {\n file: \"~/.local/share/mastracode/auth.json\",\n jsonPath: \"anthropic.access\",\n },\n ],\n },\n {\n id: \"openai-oauth\",\n source: [\n {\n file: \"~/Library/Application Support/mastracode/auth.json\",\n jsonPath: \"openai-codex.access\",\n },\n {\n file: \"~/.local/share/mastracode/auth.json\",\n jsonPath: \"openai-codex.access\",\n },\n ],\n },\n ],\n})\n\n/** Gemini CLI OAuth token written by the local CLI. */\nexport const geminiRecipe = defineProvisionRecipe({\n id: \"gemini\",\n description:\n \"Google Gemini CLI OAuth access token, read from the local CLI's credential cache.\",\n label: \"Gemini\",\n methods: [\n {\n id: \"oauth-token\",\n source: {\n file: \"~/.gemini/oauth_creds.json\",\n jsonPath: \"access_token\",\n },\n },\n ],\n})\n\nexport const BUILTIN_RECIPES: readonly ProvisionRecipe[] = [\n claudeCodeOauthRecipe,\n codexRecipe,\n geminiRecipe,\n opencodeRecipe,\n mastracodeRecipe,\n]\n","/**\n * Provision-recipe registry — id → recipe lookup, pre-seeded with the builtins.\n *\n * Mirrors the host-side OAuth-provider registry shape: a module-level Map a\n * caller resolves by id at provision time, plus a `registerRecipe` seam so a\n * host can add recipes parsed from its own `.md` (`parseRecipeManifest`)\n * without editing this package. Re-registering an id overrides it — last write\n * wins, so a host can shadow a builtin.\n */\n\nimport { BUILTIN_RECIPES } from \"./builtins.js\"\nimport type { ProvisionRecipe, RecipeMethod } from \"./types.js\"\n\nconst _registry = new Map<string, ProvisionRecipe>()\nfor (const r of BUILTIN_RECIPES) _registry.set(r.id, r)\n\nexport function registerRecipe(recipe: ProvisionRecipe): void {\n _registry.set(recipe.id, recipe)\n}\n\nexport function getRecipe(id: string): ProvisionRecipe | undefined {\n return _registry.get(id)\n}\n\nexport function listRecipes(): ProvisionRecipe[] {\n return [..._registry.values()]\n}\n\nexport function listRecipeIds(): string[] {\n return [..._registry.keys()]\n}\n\n/**\n * Resolve a recipe + one of its methods. `methodId` selects among the recipe's\n * flavors; omitted picks the first (default). Throws a caller-friendly error\n * naming the available methods when the id is unknown or ambiguous.\n */\nexport function resolveRecipeMethod(\n id: string,\n methodId?: string,\n): { recipe: ProvisionRecipe; method: RecipeMethod } {\n const recipe = getRecipe(id)\n if (!recipe) {\n throw new Error(\n `unknown provider '${id}' — known: ${listRecipeIds().join(\", \") || \"(none)\"}`,\n )\n }\n if (!methodId) {\n return { recipe, method: recipe.methods[0] }\n }\n const method = recipe.methods.find((m) => m.id === methodId)\n if (!method) {\n throw new Error(\n `provider '${id}' has no method '${methodId}' — methods: ${recipe.methods\n .map((m) => m.id)\n .join(\", \")}`,\n )\n }\n return { recipe, method }\n}\n","/**\n * Resolve a recipe method's source to plaintext.\n *\n * A source is a single `CredentialSourceSpec` or an ordered fallback chain\n * (array) — the first that resolves wins, so one recipe spans platforms\n * (macOS Keychain → file). Bridges onto `resolveCredential` (file / env), the\n * macOS `security` Keychain, and an injected prompt impl (interactive, e.g. a\n * website password for a remote browser). The prompt impl is INJECTED — no\n * hard TTY dependency at import, same discipline as `fetchImpl` on\n * `httpTarget`. The result is sensitive: seal it immediately, never print it.\n */\n\nimport { resolveCredential, extractJsonPath } from \"../index.js\"\nimport type { CredentialSourceSpec } from \"./types.js\"\n\nexport interface ResolveSourceOptions {\n /** Asked for a `{ prompt }` source. Receives the prompt text, returns the\n * entered value. Required only when a method uses a prompt source. */\n promptImpl?: (prompt: string) => Promise<string>\n}\n\nexport async function resolveSourceSpec(\n source: CredentialSourceSpec | CredentialSourceSpec[],\n opts: ResolveSourceOptions = {},\n): Promise<string> {\n const chain = Array.isArray(source) ? source : [source]\n const errors: string[] = []\n for (const spec of chain) {\n try {\n return await resolveOne(spec, opts)\n } catch (err) {\n errors.push(err instanceof Error ? err.message : String(err))\n }\n }\n throw new Error(`no credential source resolved (${errors.join(\"; \")})`)\n}\n\nasync function resolveOne(\n source: CredentialSourceSpec,\n opts: ResolveSourceOptions,\n): Promise<string> {\n if (\"env\" in source) {\n return resolveCredential({ fromEnv: source.env })\n }\n if (\"file\" in source) {\n return resolveCredential({\n fromFile: source.file,\n ...(source.jsonPath ? { jsonPath: source.jsonPath } : {}),\n })\n }\n if (\"keychain\" in source) {\n return resolveKeychain(source)\n }\n // prompt\n if (!opts.promptImpl) {\n throw new Error(\n `credential source needs an interactive prompt but no promptImpl was provided`,\n )\n }\n const value = await opts.promptImpl(source.prompt)\n if (!value) throw new Error(\"prompt returned an empty credential\")\n return value\n}\n\nasync function resolveKeychain(source: {\n keychain: string\n account?: string\n jsonPath?: string\n}): Promise<string> {\n if (process.platform !== \"darwin\") {\n throw new Error(\"keychain source is macOS-only\")\n }\n const { execFileSync } = await import(\"node:child_process\")\n const args = [\"find-generic-password\", \"-w\", \"-s\", source.keychain]\n if (source.account) args.push(\"-a\", source.account)\n let raw: string\n try {\n raw = execFileSync(\"security\", args, { encoding: \"utf8\" }).trim()\n } catch {\n throw new Error(`keychain item '${source.keychain}' not found`)\n }\n if (!raw) throw new Error(`keychain item '${source.keychain}' is empty`)\n return source.jsonPath ? extractJsonPath(raw, source.jsonPath) : raw\n}\n"]}
@@ -0,0 +1,222 @@
1
+ /**
2
+ * @agentproto/secrets v0.1.0-alpha
3
+ * AIP-19 SECRETS.md `defineSecrets` reference implementation.
4
+ */
5
+
6
+ // src/crypto/bytes.ts
7
+ function nodeBuffer() {
8
+ const b = globalThis.Buffer;
9
+ return typeof b?.from === "function" ? b : void 0;
10
+ }
11
+ var ENC_ALPHABET = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
12
+ var DEC_TABLE = (() => {
13
+ const t = new Int16Array(128).fill(-1);
14
+ for (let i = 0; i < ENC_ALPHABET.length; i++) t[ENC_ALPHABET.charCodeAt(i)] = i;
15
+ t["-".charCodeAt(0)] = 62;
16
+ t["_".charCodeAt(0)] = 63;
17
+ return t;
18
+ })();
19
+ function base64EncodePortable(bytes) {
20
+ let out = "";
21
+ let i = 0;
22
+ for (; i + 2 < bytes.length; i += 3) {
23
+ const n = bytes[i] << 16 | bytes[i + 1] << 8 | bytes[i + 2];
24
+ out += ENC_ALPHABET[n >> 18 & 63] + ENC_ALPHABET[n >> 12 & 63] + ENC_ALPHABET[n >> 6 & 63] + ENC_ALPHABET[n & 63];
25
+ }
26
+ const rest = bytes.length - i;
27
+ if (rest === 1) {
28
+ const n = bytes[i] << 16;
29
+ out += ENC_ALPHABET[n >> 18 & 63] + ENC_ALPHABET[n >> 12 & 63] + "==";
30
+ } else if (rest === 2) {
31
+ const n = bytes[i] << 16 | bytes[i + 1] << 8;
32
+ out += ENC_ALPHABET[n >> 18 & 63] + ENC_ALPHABET[n >> 12 & 63] + ENC_ALPHABET[n >> 6 & 63] + "=";
33
+ }
34
+ return out;
35
+ }
36
+ function base64DecodePortable(s) {
37
+ const out = new Uint8Array(Math.floor(s.length * 3 / 4) + 3);
38
+ let len = 0;
39
+ let acc = 0;
40
+ let bits = 0;
41
+ for (let i = 0; i < s.length; i++) {
42
+ const c = s.charCodeAt(i);
43
+ if (c === 61) break;
44
+ const v = c < 128 ? DEC_TABLE[c] : -1;
45
+ if (v < 0) continue;
46
+ acc = (acc << 6 | v) & 16777215;
47
+ bits += 6;
48
+ if (bits >= 8) {
49
+ bits -= 8;
50
+ out[len++] = acc >> bits & 255;
51
+ }
52
+ }
53
+ return out.slice(0, len);
54
+ }
55
+ function base64Encode(bytes) {
56
+ const B = nodeBuffer();
57
+ return B ? B.from(bytes).toString("base64") : base64EncodePortable(bytes);
58
+ }
59
+ function base64Decode(s) {
60
+ const B = nodeBuffer();
61
+ return B ? B.from(s, "base64") : base64DecodePortable(s);
62
+ }
63
+ function base64UrlEncode(bytes) {
64
+ return base64Encode(bytes).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
65
+ }
66
+ var textEncoder = new TextEncoder();
67
+ var textDecoder = new TextDecoder("utf-8", { ignoreBOM: true });
68
+ function utf8Encode(s) {
69
+ return textEncoder.encode(s);
70
+ }
71
+ function utf8Decode(bytes) {
72
+ return textDecoder.decode(bytes);
73
+ }
74
+ function concatBytes(...parts) {
75
+ let total = 0;
76
+ for (const p of parts) total += p.length;
77
+ const out = new Uint8Array(total);
78
+ let off = 0;
79
+ for (const p of parts) {
80
+ out.set(p, off);
81
+ off += p.length;
82
+ }
83
+ return out;
84
+ }
85
+ function compareBytes(a, b) {
86
+ const n = Math.min(a.length, b.length);
87
+ for (let i = 0; i < n; i++) {
88
+ if (a[i] !== b[i]) return a[i] < b[i] ? -1 : 1;
89
+ }
90
+ return a.length === b.length ? 0 : a.length < b.length ? -1 : 1;
91
+ }
92
+ function timingSafeEqualBytes(a, b) {
93
+ if (a.length !== b.length) return false;
94
+ let diff = 0;
95
+ for (let i = 0; i < a.length; i++) diff |= a[i] ^ b[i];
96
+ return diff === 0;
97
+ }
98
+ function toHex(bytes) {
99
+ let out = "";
100
+ for (const b of bytes) out += b.toString(16).padStart(2, "0");
101
+ return out;
102
+ }
103
+ function u64be(n) {
104
+ const out = new Uint8Array(8);
105
+ new DataView(out.buffer).setBigUint64(0, BigInt(n));
106
+ return out;
107
+ }
108
+
109
+ // src/crypto/types.ts
110
+ var GCM_TAG_LEN = 16;
111
+
112
+ // src/crypto/webcrypto.ts
113
+ function buf(u8) {
114
+ return u8.buffer instanceof ArrayBuffer ? u8 : new Uint8Array(u8);
115
+ }
116
+ function subtle() {
117
+ const s = globalThis.crypto?.subtle;
118
+ if (!s) {
119
+ throw new Error("WebCrypto (globalThis.crypto.subtle) is not available in this environment");
120
+ }
121
+ return s;
122
+ }
123
+ var X25519_SPKI_PREFIX = new Uint8Array([
124
+ 48,
125
+ 42,
126
+ 48,
127
+ 5,
128
+ 6,
129
+ 3,
130
+ 43,
131
+ 101,
132
+ 110,
133
+ 3,
134
+ 33,
135
+ 0
136
+ ]);
137
+ async function importPublic(spki, name, usages) {
138
+ return subtle().importKey("spki", buf(spki), { name }, true, usages);
139
+ }
140
+ async function importPrivate(pkcs8, name, usages) {
141
+ return subtle().importKey("pkcs8", buf(pkcs8), { name }, true, usages);
142
+ }
143
+ async function generate(name) {
144
+ const usages = name === "X25519" ? ["deriveBits"] : ["sign", "verify"];
145
+ const kp = await subtle().generateKey({ name }, true, usages);
146
+ const [publicKey, privateKey] = await Promise.all([
147
+ subtle().exportKey("spki", kp.publicKey),
148
+ subtle().exportKey("pkcs8", kp.privateKey)
149
+ ]);
150
+ return { publicKey: new Uint8Array(publicKey), privateKey: new Uint8Array(privateKey) };
151
+ }
152
+ async function aesKey(key, usage) {
153
+ return subtle().importKey("raw", buf(key), { name: "AES-GCM" }, false, [usage]);
154
+ }
155
+ function gcmParams(iv, aad) {
156
+ return aad ? { name: "AES-GCM", iv: buf(iv), additionalData: buf(aad), tagLength: GCM_TAG_LEN * 8 } : { name: "AES-GCM", iv: buf(iv), tagLength: GCM_TAG_LEN * 8 };
157
+ }
158
+ var webCryptoProvider = {
159
+ name: "webcrypto",
160
+ randomBytes: (n) => {
161
+ const out = new Uint8Array(n);
162
+ for (let off = 0; off < n; off += 65536) {
163
+ globalThis.crypto.getRandomValues(out.subarray(off, Math.min(n, off + 65536)));
164
+ }
165
+ return out;
166
+ },
167
+ sha256: async (data) => new Uint8Array(await subtle().digest("SHA-256", buf(data))),
168
+ hmacSha256: async (key, data) => {
169
+ const k = await subtle().importKey("raw", buf(key), { name: "HMAC", hash: "SHA-256" }, false, ["sign"]);
170
+ return new Uint8Array(await subtle().sign("HMAC", k, buf(data)));
171
+ },
172
+ hkdfSha256: async (ikm, salt, info, length) => {
173
+ const k = await subtle().importKey("raw", buf(ikm), "HKDF", false, ["deriveBits"]);
174
+ const bits = await subtle().deriveBits(
175
+ { name: "HKDF", hash: "SHA-256", salt: buf(salt), info: buf(info) },
176
+ k,
177
+ length * 8
178
+ );
179
+ return new Uint8Array(bits);
180
+ },
181
+ x25519GenerateKeyPair: () => generate("X25519"),
182
+ x25519ValidatePublicKey: async (spki) => {
183
+ await importPublic(spki, "X25519", []);
184
+ },
185
+ x25519PublicKeyFromPrivate: async (pkcs8) => {
186
+ const jwk = await subtle().exportKey("jwk", await importPrivate(pkcs8, "X25519", ["deriveBits"]));
187
+ if (typeof jwk.x !== "string") throw new Error("X25519 private key JWK has no public component");
188
+ return concatBytes(X25519_SPKI_PREFIX, base64Decode(jwk.x));
189
+ },
190
+ x25519: async (privatePkcs8, publicSpki) => {
191
+ const [privateKey, publicKey] = await Promise.all([
192
+ importPrivate(privatePkcs8, "X25519", ["deriveBits"]),
193
+ importPublic(publicSpki, "X25519", [])
194
+ ]);
195
+ return new Uint8Array(await subtle().deriveBits({ name: "X25519", public: publicKey }, privateKey, 256));
196
+ },
197
+ ed25519GenerateKeyPair: () => generate("Ed25519"),
198
+ ed25519ValidatePublicKey: async (spki) => {
199
+ await importPublic(spki, "Ed25519", ["verify"]);
200
+ },
201
+ ed25519Sign: async (privatePkcs8, message) => {
202
+ const k = await importPrivate(privatePkcs8, "Ed25519", ["sign"]);
203
+ return new Uint8Array(await subtle().sign({ name: "Ed25519" }, k, buf(message)));
204
+ },
205
+ ed25519Verify: async (publicSpki, message, signature) => {
206
+ try {
207
+ const k = await importPublic(publicSpki, "Ed25519", ["verify"]);
208
+ return await subtle().verify({ name: "Ed25519" }, k, buf(signature), buf(message));
209
+ } catch {
210
+ return false;
211
+ }
212
+ },
213
+ aesGcmEncrypt: async (key, iv, plaintext, aad) => new Uint8Array(await subtle().encrypt(gcmParams(iv, aad), await aesKey(key, "encrypt"), buf(plaintext))),
214
+ aesGcmDecrypt: async (key, iv, sealed, aad) => {
215
+ if (sealed.length < GCM_TAG_LEN) throw new Error("ciphertext shorter than the GCM tag");
216
+ return new Uint8Array(await subtle().decrypt(gcmParams(iv, aad), await aesKey(key, "decrypt"), buf(sealed)));
217
+ }
218
+ };
219
+
220
+ export { GCM_TAG_LEN, base64Decode, base64Encode, base64UrlEncode, compareBytes, concatBytes, timingSafeEqualBytes, toHex, u64be, utf8Decode, utf8Encode, webCryptoProvider };
221
+ //# sourceMappingURL=chunk-3YRYO6LK.mjs.map
222
+ //# sourceMappingURL=chunk-3YRYO6LK.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/crypto/bytes.ts","../src/crypto/types.ts","../src/crypto/webcrypto.ts"],"names":[],"mappings":"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","file":"chunk-3YRYO6LK.mjs","sourcesContent":["/**\n * Byte helpers shared by the Node and browser builds of the pairing / seal /\n * identity code — the `Uint8Array` replacements for the `Buffer` calls this\n * code used to make.\n *\n * Browser-safe: no `node:` import. When a global `Buffer` exists (Node) the\n * base64 helpers delegate to it, so Node output is byte-identical to the\n * `Buffer.from(…, \"base64\")` / `.toString(\"base64\")` calls they replace by\n * construction. Elsewhere a portable implementation with the SAME semantics\n * takes over — including Buffer's lenient decode (both alphabets accepted,\n * unknown characters skipped, decoding stops at the first `=`), so a peer can't\n * craft a string the two runtimes read differently. `bytes.test.ts` pins the\n * portable path against `Buffer`.\n */\n\ninterface BufferLike {\n from(input: string, encoding: \"base64\"): Uint8Array\n from(input: Uint8Array): Uint8Array & { toString(encoding: \"base64\"): string }\n}\n\nfunction nodeBuffer(): BufferLike | undefined {\n const b = (globalThis as { Buffer?: BufferLike }).Buffer\n return typeof b?.from === \"function\" ? b : undefined\n}\n\nconst ENC_ALPHABET = \"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\"\n\n/** char code → 6-bit value; -1 = not in either base64 alphabet. */\nconst DEC_TABLE: Int16Array = (() => {\n const t = new Int16Array(128).fill(-1)\n for (let i = 0; i < ENC_ALPHABET.length; i++) t[ENC_ALPHABET.charCodeAt(i)] = i\n t[\"-\".charCodeAt(0)] = 62\n t[\"_\".charCodeAt(0)] = 63\n return t\n})()\n\n/** Portable standard base64 (padded). Exported for the parity test. */\nexport function base64EncodePortable(bytes: Uint8Array): string {\n let out = \"\"\n let i = 0\n for (; i + 2 < bytes.length; i += 3) {\n const n = (bytes[i]! << 16) | (bytes[i + 1]! << 8) | bytes[i + 2]!\n out +=\n ENC_ALPHABET[(n >> 18) & 63]! +\n ENC_ALPHABET[(n >> 12) & 63]! +\n ENC_ALPHABET[(n >> 6) & 63]! +\n ENC_ALPHABET[n & 63]!\n }\n const rest = bytes.length - i\n if (rest === 1) {\n const n = bytes[i]! << 16\n out += ENC_ALPHABET[(n >> 18) & 63]! + ENC_ALPHABET[(n >> 12) & 63]! + \"==\"\n } else if (rest === 2) {\n const n = (bytes[i]! << 16) | (bytes[i + 1]! << 8)\n out +=\n ENC_ALPHABET[(n >> 18) & 63]! +\n ENC_ALPHABET[(n >> 12) & 63]! +\n ENC_ALPHABET[(n >> 6) & 63]! +\n \"=\"\n }\n return out\n}\n\n/** Portable lenient base64 decode with `Buffer.from(s, \"base64\")` semantics.\n * Exported for the parity test. */\nexport function base64DecodePortable(s: string): Uint8Array {\n const out = new Uint8Array(Math.floor((s.length * 3) / 4) + 3)\n let len = 0\n let acc = 0\n let bits = 0\n for (let i = 0; i < s.length; i++) {\n const c = s.charCodeAt(i)\n if (c === 61) break // \"=\" ends the data, as in Buffer\n const v = c < 128 ? DEC_TABLE[c]! : -1\n if (v < 0) continue\n acc = ((acc << 6) | v) & 0xffffff\n bits += 6\n if (bits >= 8) {\n bits -= 8\n out[len++] = (acc >> bits) & 0xff\n }\n }\n return out.slice(0, len)\n}\n\n/** Standard base64 (padded) — identical to `Buffer#toString(\"base64\")`. */\nexport function base64Encode(bytes: Uint8Array): string {\n const B = nodeBuffer()\n return B ? B.from(bytes).toString(\"base64\") : base64EncodePortable(bytes)\n}\n\n/** Lenient base64 decode — identical to `Buffer.from(s, \"base64\")`. Returns a\n * plain `Uint8Array` view (a `Buffer` under Node). Never throws. */\nexport function base64Decode(s: string): Uint8Array {\n const B = nodeBuffer()\n return B ? B.from(s, \"base64\") : base64DecodePortable(s)\n}\n\n/** base64url without padding. */\nexport function base64UrlEncode(bytes: Uint8Array): string {\n return base64Encode(bytes).replace(/\\+/g, \"-\").replace(/\\//g, \"_\").replace(/=+$/, \"\")\n}\n\nconst textEncoder = new TextEncoder()\n// ignoreBOM: keep a leading U+FEFF in the output, as Buffer#toString does.\nconst textDecoder = new TextDecoder(\"utf-8\", { ignoreBOM: true })\n\nexport function utf8Encode(s: string): Uint8Array {\n return textEncoder.encode(s)\n}\n\n/** UTF-8 decode, replacing invalid sequences with U+FFFD (like Buffer). */\nexport function utf8Decode(bytes: Uint8Array): string {\n return textDecoder.decode(bytes)\n}\n\nexport function concatBytes(...parts: Uint8Array[]): Uint8Array {\n let total = 0\n for (const p of parts) total += p.length\n const out = new Uint8Array(total)\n let off = 0\n for (const p of parts) {\n out.set(p, off)\n off += p.length\n }\n return out\n}\n\n/** Lexicographic byte comparison — same ordering as `Buffer.compare`. */\nexport function compareBytes(a: Uint8Array, b: Uint8Array): number {\n const n = Math.min(a.length, b.length)\n for (let i = 0; i < n; i++) {\n if (a[i] !== b[i]) return a[i]! < b[i]! ? -1 : 1\n }\n return a.length === b.length ? 0 : a.length < b.length ? -1 : 1\n}\n\n/** Constant-time equality for equal-length inputs (length itself is not\n * secret). Replaces `timingSafeEqual`. */\nexport function timingSafeEqualBytes(a: Uint8Array, b: Uint8Array): boolean {\n if (a.length !== b.length) return false\n let diff = 0\n for (let i = 0; i < a.length; i++) diff |= a[i]! ^ b[i]!\n return diff === 0\n}\n\nexport function toHex(bytes: Uint8Array): string {\n let out = \"\"\n for (const b of bytes) out += b.toString(16).padStart(2, \"0\")\n return out\n}\n\n/** 8-byte big-endian encoding of a non-negative integer (≤ 2^64-1). */\nexport function u64be(n: number | bigint): Uint8Array {\n const out = new Uint8Array(8)\n new DataView(out.buffer).setBigUint64(0, BigInt(n))\n return out\n}\n","/**\n * The crypto seam behind the pairing handshake, the seal box and the daemon\n * identity: the handful of primitives they need, and nothing else.\n *\n * Two implementations:\n * - `nodeCryptoProvider` (`./node.ts`) — `node:crypto`; the default in every\n * Node entry point (`@agentproto/secrets/pairing`, `/seal`, `/identity`).\n * - `webCryptoProvider` (`./webcrypto.ts`) — `globalThis.crypto.subtle`; the\n * default in the browser-safe entry (`@agentproto/secrets/pairing/browser`).\n * Works in current Chrome / Safari / Firefox and in Node ≥ 20.\n *\n * The protocol code on top is written once against this interface, so both\n * runtimes run the same key schedule. The methods are Promise-based because\n * WebCrypto is; `randomBytes` stays synchronous (`getRandomValues` is).\n *\n * Key encoding: keys cross this seam as DER bytes — SPKI for public keys,\n * PKCS#8 for private keys — which is exactly what travels on the wire and in\n * `identity.json` (base64 of the same bytes). Both implementations import and\n * export the same DER, so keys minted by one are usable by the other.\n */\nexport interface CryptoProvider {\n /** Implementation label, for diagnostics and tests (\"node\" | \"webcrypto\"). */\n readonly name: string\n\n /** `n` cryptographically-random bytes. */\n randomBytes(n: number): Uint8Array\n sha256(data: Uint8Array): Promise<Uint8Array>\n hmacSha256(key: Uint8Array, data: Uint8Array): Promise<Uint8Array>\n /** RFC 5869 HKDF with SHA-256; `length` output bytes. */\n hkdfSha256(\n ikm: Uint8Array,\n salt: Uint8Array,\n info: Uint8Array,\n length: number,\n ): Promise<Uint8Array>\n\n /** Fresh X25519 keypair: `publicKey` SPKI DER, `privateKey` PKCS#8 DER. */\n x25519GenerateKeyPair(): Promise<KeyPairDer>\n /** Throws if `spki` is not an importable X25519 public key. */\n x25519ValidatePublicKey(spki: Uint8Array): Promise<void>\n /** The SPKI DER public half of a PKCS#8 X25519 private key. */\n x25519PublicKeyFromPrivate(pkcs8: Uint8Array): Promise<Uint8Array>\n /** X25519 ECDH → 32-byte shared secret. */\n x25519(privatePkcs8: Uint8Array, publicSpki: Uint8Array): Promise<Uint8Array>\n\n /** Fresh Ed25519 keypair: `publicKey` SPKI DER, `privateKey` PKCS#8 DER. */\n ed25519GenerateKeyPair(): Promise<KeyPairDer>\n /** Throws if `spki` is not an importable Ed25519 public key. */\n ed25519ValidatePublicKey(spki: Uint8Array): Promise<void>\n ed25519Sign(privatePkcs8: Uint8Array, message: Uint8Array): Promise<Uint8Array>\n /** Never throws on a bad signature — resolves false. */\n ed25519Verify(publicSpki: Uint8Array, message: Uint8Array, signature: Uint8Array): Promise<boolean>\n\n /** AES-256-GCM, 16-byte tag. Returns `ciphertext ‖ tag`. */\n aesGcmEncrypt(key: Uint8Array, iv: Uint8Array, plaintext: Uint8Array, aad?: Uint8Array): Promise<Uint8Array>\n /** Opens `ciphertext ‖ tag`. Rejects on any authentication failure. */\n aesGcmDecrypt(key: Uint8Array, iv: Uint8Array, sealed: Uint8Array, aad?: Uint8Array): Promise<Uint8Array>\n}\n\nexport interface KeyPairDer {\n /** SPKI DER. */\n publicKey: Uint8Array\n /** PKCS#8 DER. */\n privateKey: Uint8Array\n}\n\n/** AES-GCM tag length used throughout (bytes). */\nexport const GCM_TAG_LEN = 16\n","/**\n * `CryptoProvider` over WebCrypto (`globalThis.crypto.subtle`) — the default in\n * the browser-safe entry. Browser-safe: no `node:` import, no `Buffer`.\n *\n * Needs X25519 + Ed25519 in `SubtleCrypto` (Chrome 133+, Safari 17+, Firefox\n * 130+, Node ≥ 20). The subtle instance is resolved lazily, per call, so merely\n * importing this module never throws in an environment without WebCrypto.\n */\n\nimport { base64Decode, concatBytes } from \"./bytes.js\"\nimport { GCM_TAG_LEN, type CryptoProvider, type KeyPairDer } from \"./types.js\"\n\n// Local names for the WebCrypto dictionary types: this package compiles without\n// the DOM lib, and @types/node only declares the interfaces.\ntype KeyUsage = \"sign\" | \"verify\" | \"deriveBits\" | \"encrypt\" | \"decrypt\"\ntype AesGcmParams = Parameters<SubtleCrypto[\"encrypt\"]>[0]\ntype CryptoKeyPair = { publicKey: CryptoKey; privateKey: CryptoKey }\n\n/** The DOM `BufferSource` excludes SharedArrayBuffer-backed views; our inputs\n * are always plain `Uint8Array`s, so copy into a fresh ArrayBuffer-backed view\n * when the static type can't prove it (a no-op for the common case). */\nfunction buf(u8: Uint8Array): Uint8Array<ArrayBuffer> {\n return u8.buffer instanceof ArrayBuffer\n ? (u8 as Uint8Array<ArrayBuffer>)\n : new Uint8Array(u8)\n}\n\nfunction subtle(): SubtleCrypto {\n const s = globalThis.crypto?.subtle\n if (!s) {\n throw new Error(\"WebCrypto (globalThis.crypto.subtle) is not available in this environment\")\n }\n return s\n}\n\n// X25519 / Ed25519 public-key SPKI prefixes (RFC 8410): SEQUENCE { SEQUENCE {\n// OID }, BIT STRING (0 unused bits) 32 bytes }. Used only to rebuild a public\n// key from a JWK `x`; this is the exact DER both Node and WebCrypto emit.\nconst X25519_SPKI_PREFIX = new Uint8Array([\n 0x30, 0x2a, 0x30, 0x05, 0x06, 0x03, 0x2b, 0x65, 0x6e, 0x03, 0x21, 0x00,\n])\n\nasync function importPublic(spki: Uint8Array, name: \"X25519\" | \"Ed25519\", usages: KeyUsage[]): Promise<CryptoKey> {\n return subtle().importKey(\"spki\", buf(spki), { name }, true, usages)\n}\n\nasync function importPrivate(pkcs8: Uint8Array, name: \"X25519\" | \"Ed25519\", usages: KeyUsage[]): Promise<CryptoKey> {\n return subtle().importKey(\"pkcs8\", buf(pkcs8), { name }, true, usages)\n}\n\nasync function generate(name: \"X25519\" | \"Ed25519\"): Promise<KeyPairDer> {\n const usages: KeyUsage[] = name === \"X25519\" ? [\"deriveBits\"] : [\"sign\", \"verify\"]\n // Extractable: the provider contract hands private keys around as PKCS#8.\n const kp = (await subtle().generateKey({ name }, true, usages)) as unknown as CryptoKeyPair\n const [publicKey, privateKey] = await Promise.all([\n subtle().exportKey(\"spki\", kp.publicKey),\n subtle().exportKey(\"pkcs8\", kp.privateKey),\n ])\n return { publicKey: new Uint8Array(publicKey), privateKey: new Uint8Array(privateKey) }\n}\n\nasync function aesKey(key: Uint8Array, usage: KeyUsage): Promise<CryptoKey> {\n return subtle().importKey(\"raw\", buf(key), { name: \"AES-GCM\" }, false, [usage])\n}\n\nfunction gcmParams(iv: Uint8Array, aad?: Uint8Array): AesGcmParams {\n return aad\n ? { name: \"AES-GCM\", iv: buf(iv), additionalData: buf(aad), tagLength: GCM_TAG_LEN * 8 }\n : { name: \"AES-GCM\", iv: buf(iv), tagLength: GCM_TAG_LEN * 8 }\n}\n\nexport const webCryptoProvider: CryptoProvider = {\n name: \"webcrypto\",\n\n randomBytes: n => {\n const out = new Uint8Array(n)\n // getRandomValues caps a single call at 65536 bytes.\n for (let off = 0; off < n; off += 65536) {\n globalThis.crypto.getRandomValues(out.subarray(off, Math.min(n, off + 65536)))\n }\n return out\n },\n\n sha256: async data => new Uint8Array(await subtle().digest(\"SHA-256\", buf(data))),\n\n hmacSha256: async (key, data) => {\n const k = await subtle().importKey(\"raw\", buf(key), { name: \"HMAC\", hash: \"SHA-256\" }, false, [\"sign\"])\n return new Uint8Array(await subtle().sign(\"HMAC\", k, buf(data)))\n },\n\n hkdfSha256: async (ikm, salt, info, length) => {\n const k = await subtle().importKey(\"raw\", buf(ikm), \"HKDF\", false, [\"deriveBits\"])\n const bits = await subtle().deriveBits(\n { name: \"HKDF\", hash: \"SHA-256\", salt: buf(salt), info: buf(info) },\n k,\n length * 8,\n )\n return new Uint8Array(bits)\n },\n\n x25519GenerateKeyPair: () => generate(\"X25519\"),\n\n x25519ValidatePublicKey: async spki => {\n await importPublic(spki, \"X25519\", [])\n },\n\n x25519PublicKeyFromPrivate: async pkcs8 => {\n // WebCrypto can't derive a public CryptoKey from a private one directly,\n // but the private JWK carries the public `x` coordinate.\n const jwk = await subtle().exportKey(\"jwk\", await importPrivate(pkcs8, \"X25519\", [\"deriveBits\"]))\n if (typeof jwk.x !== \"string\") throw new Error(\"X25519 private key JWK has no public component\")\n return concatBytes(X25519_SPKI_PREFIX, base64Decode(jwk.x))\n },\n\n x25519: async (privatePkcs8, publicSpki) => {\n const [privateKey, publicKey] = await Promise.all([\n importPrivate(privatePkcs8, \"X25519\", [\"deriveBits\"]),\n importPublic(publicSpki, \"X25519\", []),\n ])\n return new Uint8Array(await subtle().deriveBits({ name: \"X25519\", public: publicKey }, privateKey, 256))\n },\n\n ed25519GenerateKeyPair: () => generate(\"Ed25519\"),\n\n ed25519ValidatePublicKey: async spki => {\n await importPublic(spki, \"Ed25519\", [\"verify\"])\n },\n\n ed25519Sign: async (privatePkcs8, message) => {\n const k = await importPrivate(privatePkcs8, \"Ed25519\", [\"sign\"])\n return new Uint8Array(await subtle().sign({ name: \"Ed25519\" }, k, buf(message)))\n },\n\n ed25519Verify: async (publicSpki, message, signature) => {\n try {\n const k = await importPublic(publicSpki, \"Ed25519\", [\"verify\"])\n return await subtle().verify({ name: \"Ed25519\" }, k, buf(signature), buf(message))\n } catch {\n return false\n }\n },\n\n aesGcmEncrypt: async (key, iv, plaintext, aad) =>\n new Uint8Array(await subtle().encrypt(gcmParams(iv, aad), await aesKey(key, \"encrypt\"), buf(plaintext))),\n\n aesGcmDecrypt: async (key, iv, sealed, aad) => {\n if (sealed.length < GCM_TAG_LEN) throw new Error(\"ciphertext shorter than the GCM tag\")\n return new Uint8Array(await subtle().decrypt(gcmParams(iv, aad), await aesKey(key, \"decrypt\"), buf(sealed)))\n },\n}\n"]}
@@ -0,0 +1,100 @@
1
+ import { utf8Encode, webCryptoProvider, base64Encode, base64Decode, toHex, utf8Decode, concatBytes } from './chunk-3YRYO6LK.mjs';
2
+
3
+ /**
4
+ * @agentproto/secrets v0.1.0-alpha
5
+ * AIP-19 SECRETS.md `defineSecrets` reference implementation.
6
+ */
7
+
8
+ // src/seal/core.ts
9
+ var SEAL_ALG = "x25519-hkdf-sha256-aes256gcm";
10
+ var SEAL_VERSION = 1;
11
+ var HKDF_INFO = utf8Encode("agentproto/secrets/seal v1");
12
+ var IV_LEN = 12;
13
+ var TAG_LEN = 16;
14
+ var SealError = class extends Error {
15
+ constructor(message) {
16
+ super(message);
17
+ this.name = "SealError";
18
+ }
19
+ };
20
+ async function generateSealKeyPair(crypto = webCryptoProvider) {
21
+ const kp = await crypto.x25519GenerateKeyPair();
22
+ return { publicKey: base64Encode(kp.publicKey), privateKey: base64Encode(kp.privateKey) };
23
+ }
24
+ async function sealingPublicKey(privateKey, crypto = webCryptoProvider) {
25
+ try {
26
+ return base64Encode(await crypto.x25519PublicKeyFromPrivate(base64Decode(privateKey)));
27
+ } catch {
28
+ throw new SealError("invalid private key");
29
+ }
30
+ }
31
+ async function sealKeyId(publicKey, crypto = webCryptoProvider) {
32
+ return toHex(await crypto.sha256(base64Decode(publicKey))).slice(0, 16);
33
+ }
34
+ function deriveKey(crypto, shared, epkDer, rpkDer) {
35
+ return crypto.hkdfSha256(shared, concatBytes(epkDer, rpkDer), HKDF_INFO, 32);
36
+ }
37
+ async function seal(plaintext, recipientPublicKey, crypto = webCryptoProvider) {
38
+ const rpkDer = base64Decode(recipientPublicKey);
39
+ try {
40
+ await crypto.x25519ValidatePublicKey(rpkDer);
41
+ } catch {
42
+ throw new SealError("invalid recipient public key");
43
+ }
44
+ const ephemeral = await crypto.x25519GenerateKeyPair();
45
+ const shared = await crypto.x25519(ephemeral.privateKey, rpkDer);
46
+ const key = await deriveKey(crypto, shared, ephemeral.publicKey, rpkDer);
47
+ const iv = crypto.randomBytes(IV_LEN);
48
+ const pt = typeof plaintext === "string" ? utf8Encode(plaintext) : plaintext;
49
+ const sealed = await crypto.aesGcmEncrypt(key, iv, pt);
50
+ const envelope = {
51
+ v: SEAL_VERSION,
52
+ alg: SEAL_ALG,
53
+ epk: base64Encode(ephemeral.publicKey),
54
+ iv: base64Encode(iv),
55
+ ct: base64Encode(sealed.subarray(0, sealed.length - TAG_LEN)),
56
+ tag: base64Encode(sealed.subarray(sealed.length - TAG_LEN))
57
+ };
58
+ return base64Encode(utf8Encode(JSON.stringify(envelope)));
59
+ }
60
+ async function unseal(sealed, privateKey, crypto = webCryptoProvider) {
61
+ let envelope;
62
+ try {
63
+ envelope = JSON.parse(utf8Decode(base64Decode(sealed)));
64
+ } catch {
65
+ throw new SealError("malformed sealed envelope");
66
+ }
67
+ if (envelope.v !== SEAL_VERSION || envelope.alg !== SEAL_ALG) {
68
+ throw new SealError(`unsupported sealed envelope (v=${envelope.v} alg=${envelope.alg})`);
69
+ }
70
+ const priv = base64Decode(privateKey);
71
+ let rpkDer;
72
+ try {
73
+ rpkDer = await crypto.x25519PublicKeyFromPrivate(priv);
74
+ } catch {
75
+ throw new SealError("invalid private key");
76
+ }
77
+ const epkDer = base64Decode(envelope.epk);
78
+ let shared;
79
+ try {
80
+ await crypto.x25519ValidatePublicKey(epkDer);
81
+ shared = await crypto.x25519(priv, epkDer);
82
+ } catch {
83
+ throw new SealError("malformed ephemeral key in envelope");
84
+ }
85
+ const key = await deriveKey(crypto, shared, epkDer, rpkDer);
86
+ try {
87
+ const pt = await crypto.aesGcmDecrypt(
88
+ key,
89
+ base64Decode(envelope.iv),
90
+ concatBytes(base64Decode(envelope.ct), base64Decode(envelope.tag))
91
+ );
92
+ return utf8Decode(pt);
93
+ } catch {
94
+ throw new SealError("unseal failed \u2014 wrong key or tampered ciphertext");
95
+ }
96
+ }
97
+
98
+ export { SEAL_ALG, SEAL_VERSION, SealError, generateSealKeyPair, seal, sealKeyId, sealingPublicKey, unseal };
99
+ //# sourceMappingURL=chunk-432SC3XS.mjs.map
100
+ //# sourceMappingURL=chunk-432SC3XS.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/seal/core.ts"],"names":[],"mappings":"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","file":"chunk-432SC3XS.mjs","sourcesContent":["/**\n * The seal box, written once against `CryptoProvider` — see ./index.ts for the\n * construction and the Node entry, and `@agentproto/secrets/pairing/browser`\n * for the browser one. Browser-safe: no `node:` import, no `Buffer`.\n *\n * Every function takes an optional trailing `crypto` provider, defaulting to\n * WebCrypto here; the Node entry point (./index.ts) defaults to `node:crypto`.\n */\n\nimport {\n base64Decode,\n base64Encode,\n concatBytes,\n toHex,\n utf8Decode,\n utf8Encode,\n} from \"../crypto/bytes.js\"\nimport type { CryptoProvider } from \"../crypto/types.js\"\nimport { webCryptoProvider } from \"../crypto/webcrypto.js\"\n\n/** Versioned algorithm tag embedded in every envelope so the format can\n * evolve without ambiguity at the unseal site. */\nexport const SEAL_ALG = \"x25519-hkdf-sha256-aes256gcm\" as const\nexport const SEAL_VERSION = 1 as const\n\nconst HKDF_INFO = utf8Encode(\"agentproto/secrets/seal v1\")\nconst IV_LEN = 12\nconst TAG_LEN = 16\n\n/** Raised for every seal/unseal failure. The message is safe to surface —\n * it never contains key material or plaintext. */\nexport class SealError extends Error {\n constructor(message: string) {\n super(message)\n this.name = \"SealError\"\n }\n}\n\n/** An X25519 keypair for sealing. Both halves are base64-encoded DER so they\n * travel as plain strings (env vars, JSON, config). The public half is safe\n * to publish; the private half must stay with the unseal boundary. */\nexport interface SealKeyPair {\n /** base64 DER (SPKI) X25519 public key — publishable. */\n publicKey: string\n /** base64 DER (PKCS8) X25519 private key — secret. */\n privateKey: string\n}\n\ninterface SealEnvelope {\n v: number\n alg: string\n /** ephemeral public key, base64 DER (SPKI) */\n epk: string\n /** AES-GCM iv, base64 (12 bytes) */\n iv: string\n /** ciphertext, base64 */\n ct: string\n /** AES-GCM auth tag, base64 (16 bytes) */\n tag: string\n}\n\n/** Mint a fresh sealing keypair. */\nexport async function generateSealKeyPair(crypto: CryptoProvider = webCryptoProvider): Promise<SealKeyPair> {\n const kp = await crypto.x25519GenerateKeyPair()\n return { publicKey: base64Encode(kp.publicKey), privateKey: base64Encode(kp.privateKey) }\n}\n\n/** Derive the publishable public key from a stored private key. */\nexport async function sealingPublicKey(privateKey: string, crypto: CryptoProvider = webCryptoProvider): Promise<string> {\n try {\n return base64Encode(await crypto.x25519PublicKeyFromPrivate(base64Decode(privateKey)))\n } catch {\n throw new SealError(\"invalid private key\")\n }\n}\n\n/** Stable short identifier for a sealing key: first 16 hex of\n * `sha256(public DER)`. Not a secret. */\nexport async function sealKeyId(publicKey: string, crypto: CryptoProvider = webCryptoProvider): Promise<string> {\n return toHex(await crypto.sha256(base64Decode(publicKey))).slice(0, 16)\n}\n\n// The key-derivation salt binds the symmetric key to BOTH the ephemeral and\n// the recipient public key (sealed-box style) so a derived key is unique to a\n// single (ephemeral, recipient) pair and can't be transplanted.\nfunction deriveKey(\n crypto: CryptoProvider,\n shared: Uint8Array,\n epkDer: Uint8Array,\n rpkDer: Uint8Array,\n): Promise<Uint8Array> {\n return crypto.hkdfSha256(shared, concatBytes(epkDer, rpkDer), HKDF_INFO, 32)\n}\n\n/** Seal a plaintext value to a recipient's public key. */\nexport async function seal(\n plaintext: string | Uint8Array,\n recipientPublicKey: string,\n crypto: CryptoProvider = webCryptoProvider,\n): Promise<string> {\n const rpkDer = base64Decode(recipientPublicKey)\n try {\n await crypto.x25519ValidatePublicKey(rpkDer)\n } catch {\n throw new SealError(\"invalid recipient public key\")\n }\n const ephemeral = await crypto.x25519GenerateKeyPair()\n const shared = await crypto.x25519(ephemeral.privateKey, rpkDer)\n const key = await deriveKey(crypto, shared, ephemeral.publicKey, rpkDer)\n\n const iv = crypto.randomBytes(IV_LEN)\n const pt = typeof plaintext === \"string\" ? utf8Encode(plaintext) : plaintext\n const sealed = await crypto.aesGcmEncrypt(key, iv, pt)\n\n const envelope: SealEnvelope = {\n v: SEAL_VERSION,\n alg: SEAL_ALG,\n epk: base64Encode(ephemeral.publicKey),\n iv: base64Encode(iv),\n ct: base64Encode(sealed.subarray(0, sealed.length - TAG_LEN)),\n tag: base64Encode(sealed.subarray(sealed.length - TAG_LEN)),\n }\n return base64Encode(utf8Encode(JSON.stringify(envelope)))\n}\n\n/** Open a sealed envelope with the recipient's private key. */\nexport async function unseal(sealed: string, privateKey: string, crypto: CryptoProvider = webCryptoProvider): Promise<string> {\n let envelope: SealEnvelope\n try {\n envelope = JSON.parse(utf8Decode(base64Decode(sealed)))\n } catch {\n throw new SealError(\"malformed sealed envelope\")\n }\n if (envelope.v !== SEAL_VERSION || envelope.alg !== SEAL_ALG) {\n throw new SealError(`unsupported sealed envelope (v=${envelope.v} alg=${envelope.alg})`)\n }\n\n const priv = base64Decode(privateKey)\n let rpkDer: Uint8Array\n try {\n rpkDer = await crypto.x25519PublicKeyFromPrivate(priv)\n } catch {\n throw new SealError(\"invalid private key\")\n }\n const epkDer = base64Decode(envelope.epk)\n let shared: Uint8Array\n try {\n await crypto.x25519ValidatePublicKey(epkDer)\n shared = await crypto.x25519(priv, epkDer)\n } catch {\n throw new SealError(\"malformed ephemeral key in envelope\")\n }\n const key = await deriveKey(crypto, shared, epkDer, rpkDer)\n\n try {\n const pt = await crypto.aesGcmDecrypt(\n key,\n base64Decode(envelope.iv),\n concatBytes(base64Decode(envelope.ct), base64Decode(envelope.tag)),\n )\n return utf8Decode(pt)\n } catch {\n throw new SealError(\"unseal failed — wrong key or tampered ciphertext\")\n }\n}\n"]}
@@ -0,0 +1,69 @@
1
+ import { GCM_TAG_LEN } from './chunk-3YRYO6LK.mjs';
2
+ import { createDecipheriv, createCipheriv, verify, sign, diffieHellman, createPublicKey, hkdfSync, createHmac, createHash, randomBytes, createPrivateKey, generateKeyPairSync } from 'crypto';
3
+
4
+ /**
5
+ * @agentproto/secrets v0.1.0-alpha
6
+ * AIP-19 SECRETS.md `defineSecrets` reference implementation.
7
+ */
8
+ function pub(spki) {
9
+ return createPublicKey({ key: Buffer.from(spki), format: "der", type: "spki" });
10
+ }
11
+ function priv(pkcs8) {
12
+ return createPrivateKey({ key: Buffer.from(pkcs8), format: "der", type: "pkcs8" });
13
+ }
14
+ function assertType(key, type) {
15
+ if (key.asymmetricKeyType !== type) throw new Error(`expected an ${type} key`);
16
+ return key;
17
+ }
18
+ function generate(type) {
19
+ const kp = type === "x25519" ? generateKeyPairSync("x25519") : generateKeyPairSync("ed25519");
20
+ return {
21
+ publicKey: kp.publicKey.export({ type: "spki", format: "der" }),
22
+ privateKey: kp.privateKey.export({ type: "pkcs8", format: "der" })
23
+ };
24
+ }
25
+ var nodeCryptoProvider = {
26
+ name: "node",
27
+ randomBytes: (n) => randomBytes(n),
28
+ sha256: async (data) => createHash("sha256").update(data).digest(),
29
+ hmacSha256: async (key, data) => createHmac("sha256", key).update(data).digest(),
30
+ hkdfSha256: async (ikm, salt, info, length) => new Uint8Array(hkdfSync("sha256", ikm, salt, info, length)),
31
+ x25519GenerateKeyPair: async () => generate("x25519"),
32
+ x25519ValidatePublicKey: async (spki) => {
33
+ assertType(pub(spki), "x25519");
34
+ },
35
+ x25519PublicKeyFromPrivate: async (pkcs8) => createPublicKey(assertType(priv(pkcs8), "x25519")).export({ type: "spki", format: "der" }),
36
+ x25519: async (privatePkcs8, publicSpki) => diffieHellman({
37
+ privateKey: assertType(priv(privatePkcs8), "x25519"),
38
+ publicKey: assertType(pub(publicSpki), "x25519")
39
+ }),
40
+ ed25519GenerateKeyPair: async () => generate("ed25519"),
41
+ ed25519ValidatePublicKey: async (spki) => {
42
+ assertType(pub(spki), "ed25519");
43
+ },
44
+ // Ed25519 takes a null digest algorithm — it hashes internally.
45
+ ed25519Sign: async (privatePkcs8, message) => sign(null, message, assertType(priv(privatePkcs8), "ed25519")),
46
+ ed25519Verify: async (publicSpki, message, signature) => {
47
+ try {
48
+ return verify(null, message, assertType(pub(publicSpki), "ed25519"), signature);
49
+ } catch {
50
+ return false;
51
+ }
52
+ },
53
+ aesGcmEncrypt: async (key, iv, plaintext, aad) => {
54
+ const cipher = createCipheriv("aes-256-gcm", key, iv);
55
+ if (aad) cipher.setAAD(aad);
56
+ return Buffer.concat([cipher.update(plaintext), cipher.final(), cipher.getAuthTag()]);
57
+ },
58
+ aesGcmDecrypt: async (key, iv, sealed, aad) => {
59
+ if (sealed.length < GCM_TAG_LEN) throw new Error("ciphertext shorter than the GCM tag");
60
+ const decipher = createDecipheriv("aes-256-gcm", key, iv);
61
+ if (aad) decipher.setAAD(aad);
62
+ decipher.setAuthTag(sealed.subarray(sealed.length - GCM_TAG_LEN));
63
+ return Buffer.concat([decipher.update(sealed.subarray(0, sealed.length - GCM_TAG_LEN)), decipher.final()]);
64
+ }
65
+ };
66
+
67
+ export { nodeCryptoProvider };
68
+ //# sourceMappingURL=chunk-5HUHYBPR.mjs.map
69
+ //# sourceMappingURL=chunk-5HUHYBPR.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/crypto/node.ts"],"names":[],"mappings":"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","file":"chunk-5HUHYBPR.mjs","sourcesContent":["/**\n * `CryptoProvider` over `node:crypto` — the default in every Node entry point.\n * These are the exact calls the pairing / seal / identity code made before the\n * provider seam existed, so Node output is unchanged.\n */\n\nimport {\n createCipheriv,\n createDecipheriv,\n createHash,\n createHmac,\n createPrivateKey,\n createPublicKey,\n diffieHellman,\n generateKeyPairSync,\n hkdfSync,\n randomBytes,\n sign,\n verify,\n type KeyObject,\n} from \"node:crypto\"\nimport { GCM_TAG_LEN, type CryptoProvider, type KeyPairDer } from \"./types.js\"\n\nfunction pub(spki: Uint8Array): KeyObject {\n return createPublicKey({ key: Buffer.from(spki), format: \"der\", type: \"spki\" })\n}\n\nfunction priv(pkcs8: Uint8Array): KeyObject {\n return createPrivateKey({ key: Buffer.from(pkcs8), format: \"der\", type: \"pkcs8\" })\n}\n\nfunction assertType(key: KeyObject, type: \"x25519\" | \"ed25519\"): KeyObject {\n if (key.asymmetricKeyType !== type) throw new Error(`expected an ${type} key`)\n return key\n}\n\nfunction generate(type: \"x25519\" | \"ed25519\"): KeyPairDer {\n // The overloads need a literal type argument.\n const kp = type === \"x25519\" ? generateKeyPairSync(\"x25519\") : generateKeyPairSync(\"ed25519\")\n return {\n publicKey: kp.publicKey.export({ type: \"spki\", format: \"der\" }),\n privateKey: kp.privateKey.export({ type: \"pkcs8\", format: \"der\" }),\n }\n}\n\nexport const nodeCryptoProvider: CryptoProvider = {\n name: \"node\",\n\n randomBytes: n => randomBytes(n),\n\n sha256: async data => createHash(\"sha256\").update(data).digest(),\n\n hmacSha256: async (key, data) => createHmac(\"sha256\", key).update(data).digest(),\n\n hkdfSha256: async (ikm, salt, info, length) =>\n new Uint8Array(hkdfSync(\"sha256\", ikm, salt, info, length)),\n\n x25519GenerateKeyPair: async () => generate(\"x25519\"),\n\n x25519ValidatePublicKey: async spki => {\n assertType(pub(spki), \"x25519\")\n },\n\n x25519PublicKeyFromPrivate: async pkcs8 =>\n createPublicKey(assertType(priv(pkcs8), \"x25519\")).export({ type: \"spki\", format: \"der\" }),\n\n x25519: async (privatePkcs8, publicSpki) =>\n diffieHellman({\n privateKey: assertType(priv(privatePkcs8), \"x25519\"),\n publicKey: assertType(pub(publicSpki), \"x25519\"),\n }),\n\n ed25519GenerateKeyPair: async () => generate(\"ed25519\"),\n\n ed25519ValidatePublicKey: async spki => {\n assertType(pub(spki), \"ed25519\")\n },\n\n // Ed25519 takes a null digest algorithm — it hashes internally.\n ed25519Sign: async (privatePkcs8, message) =>\n sign(null, message, assertType(priv(privatePkcs8), \"ed25519\")),\n\n ed25519Verify: async (publicSpki, message, signature) => {\n try {\n return verify(null, message, assertType(pub(publicSpki), \"ed25519\"), signature)\n } catch {\n return false\n }\n },\n\n aesGcmEncrypt: async (key, iv, plaintext, aad) => {\n const cipher = createCipheriv(\"aes-256-gcm\", key, iv)\n if (aad) cipher.setAAD(aad)\n return Buffer.concat([cipher.update(plaintext), cipher.final(), cipher.getAuthTag()])\n },\n\n aesGcmDecrypt: async (key, iv, sealed, aad) => {\n if (sealed.length < GCM_TAG_LEN) throw new Error(\"ciphertext shorter than the GCM tag\")\n const decipher = createDecipheriv(\"aes-256-gcm\", key, iv)\n if (aad) decipher.setAAD(aad)\n decipher.setAuthTag(sealed.subarray(sealed.length - GCM_TAG_LEN))\n return Buffer.concat([decipher.update(sealed.subarray(0, sealed.length - GCM_TAG_LEN)), decipher.final()])\n },\n}\n"]}