approval-md 0.0.1 → 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/LICENSE +176 -0
- package/NOTICE +5 -0
- package/README.md +940 -4
- package/SPEC.md +476 -34
- package/cli.js +29 -3
- package/dist/src/adapters/agentmail.d.ts +426 -0
- package/dist/src/adapters/agentmail.js +1200 -0
- package/dist/src/adapters/agentmail.js.map +1 -0
- package/dist/src/adapters/conformance.d.ts +149 -0
- package/dist/src/adapters/conformance.js +461 -0
- package/dist/src/adapters/conformance.js.map +1 -0
- package/dist/src/adapters/contract.d.ts +628 -0
- package/dist/src/adapters/contract.js +1035 -0
- package/dist/src/adapters/contract.js.map +1 -0
- package/dist/src/adapters/email.d.ts +324 -0
- package/dist/src/adapters/email.js +749 -0
- package/dist/src/adapters/email.js.map +1 -0
- package/dist/src/adapters/env-passphrase.d.ts +93 -0
- package/dist/src/adapters/env-passphrase.js +132 -0
- package/dist/src/adapters/env-passphrase.js.map +1 -0
- package/dist/src/adapters/public.d.ts +11 -0
- package/dist/src/adapters/public.js +11 -0
- package/dist/src/adapters/public.js.map +1 -0
- package/dist/src/adapters/registry.d.ts +59 -0
- package/dist/src/adapters/registry.js +77 -0
- package/dist/src/adapters/registry.js.map +1 -0
- package/dist/src/adapters/smtp.d.ts +213 -0
- package/dist/src/adapters/smtp.js +499 -0
- package/dist/src/adapters/smtp.js.map +1 -0
- package/dist/src/adapters/vault-provider.d.ts +114 -0
- package/dist/src/adapters/vault-provider.js +161 -0
- package/dist/src/adapters/vault-provider.js.map +1 -0
- package/dist/src/adapters/zzz.d.ts +66 -0
- package/dist/src/adapters/zzz.js +299 -0
- package/dist/src/adapters/zzz.js.map +1 -0
- package/dist/src/channels/batch.d.ts +109 -0
- package/dist/src/channels/batch.js +121 -0
- package/dist/src/channels/batch.js.map +1 -0
- package/dist/src/channels/cli.d.ts +193 -0
- package/dist/src/channels/cli.js +468 -0
- package/dist/src/channels/cli.js.map +1 -0
- package/dist/src/channels/conformance.d.ts +92 -0
- package/dist/src/channels/conformance.js +445 -0
- package/dist/src/channels/conformance.js.map +1 -0
- package/dist/src/channels/contract.d.ts +623 -0
- package/dist/src/channels/contract.js +494 -0
- package/dist/src/channels/contract.js.map +1 -0
- package/dist/src/channels/payload-view.d.ts +35 -0
- package/dist/src/channels/payload-view.js +43 -0
- package/dist/src/channels/payload-view.js.map +1 -0
- package/dist/src/channels/render-queue.d.ts +149 -0
- package/dist/src/channels/render-queue.js +564 -0
- package/dist/src/channels/render-queue.js.map +1 -0
- package/dist/src/channels/tagging.d.ts +196 -0
- package/dist/src/channels/tagging.js +723 -0
- package/dist/src/channels/tagging.js.map +1 -0
- package/dist/src/channels/telegram.d.ts +1832 -0
- package/dist/src/channels/telegram.js +3190 -0
- package/dist/src/channels/telegram.js.map +1 -0
- package/dist/src/channels/web.d.ts +341 -0
- package/dist/src/channels/web.js +903 -0
- package/dist/src/channels/web.js.map +1 -0
- package/dist/src/cli/adapter.d.ts +90 -0
- package/dist/src/cli/adapter.js +288 -0
- package/dist/src/cli/adapter.js.map +1 -0
- package/dist/src/cli/amend.d.ts +59 -0
- package/dist/src/cli/amend.js +2171 -0
- package/dist/src/cli/amend.js.map +1 -0
- package/dist/src/cli/args.d.ts +43 -0
- package/dist/src/cli/args.js +86 -0
- package/dist/src/cli/args.js.map +1 -0
- package/dist/src/cli/attest.d.ts +41 -0
- package/dist/src/cli/attest.js +307 -0
- package/dist/src/cli/attest.js.map +1 -0
- package/dist/src/cli/audit-card.d.ts +62 -0
- package/dist/src/cli/audit-card.js +201 -0
- package/dist/src/cli/audit-card.js.map +1 -0
- package/dist/src/cli/audit.d.ts +59 -0
- package/dist/src/cli/audit.js +460 -0
- package/dist/src/cli/audit.js.map +1 -0
- package/dist/src/cli/channel-telegram.d.ts +806 -0
- package/dist/src/cli/channel-telegram.js +2063 -0
- package/dist/src/cli/channel-telegram.js.map +1 -0
- package/dist/src/cli/channel-web.d.ts +131 -0
- package/dist/src/cli/channel-web.js +357 -0
- package/dist/src/cli/channel-web.js.map +1 -0
- package/dist/src/cli/channel.d.ts +71 -0
- package/dist/src/cli/channel.js +438 -0
- package/dist/src/cli/channel.js.map +1 -0
- package/dist/src/cli/checkpoint-tap.d.ts +169 -0
- package/dist/src/cli/checkpoint-tap.js +238 -0
- package/dist/src/cli/checkpoint-tap.js.map +1 -0
- package/dist/src/cli/codex.d.ts +2 -0
- package/dist/src/cli/codex.js +172 -0
- package/dist/src/cli/codex.js.map +1 -0
- package/dist/src/cli/coverage.d.ts +61 -0
- package/dist/src/cli/coverage.js +343 -0
- package/dist/src/cli/coverage.js.map +1 -0
- package/dist/src/cli/daemon.d.ts +120 -0
- package/dist/src/cli/daemon.js +631 -0
- package/dist/src/cli/daemon.js.map +1 -0
- package/dist/src/cli/doctor.d.ts +129 -0
- package/dist/src/cli/doctor.js +2762 -0
- package/dist/src/cli/doctor.js.map +1 -0
- package/dist/src/cli/env.d.ts +65 -0
- package/dist/src/cli/env.js +302 -0
- package/dist/src/cli/env.js.map +1 -0
- package/dist/src/cli/execute.d.ts +202 -0
- package/dist/src/cli/execute.js +1682 -0
- package/dist/src/cli/execute.js.map +1 -0
- package/dist/src/cli/exit-codes.d.ts +73 -0
- package/dist/src/cli/exit-codes.js +82 -0
- package/dist/src/cli/exit-codes.js.map +1 -0
- package/dist/src/cli/feedback.d.ts +60 -0
- package/dist/src/cli/feedback.js +205 -0
- package/dist/src/cli/feedback.js.map +1 -0
- package/dist/src/cli/gate-window.d.ts +40 -0
- package/dist/src/cli/gate-window.js +294 -0
- package/dist/src/cli/gate-window.js.map +1 -0
- package/dist/src/cli/gate.d.ts +68 -0
- package/dist/src/cli/gate.js +557 -0
- package/dist/src/cli/gate.js.map +1 -0
- package/dist/src/cli/git-scope.d.ts +190 -0
- package/dist/src/cli/git-scope.js +295 -0
- package/dist/src/cli/git-scope.js.map +1 -0
- package/dist/src/cli/gloss-attach.d.ts +85 -0
- package/dist/src/cli/gloss-attach.js +107 -0
- package/dist/src/cli/gloss-attach.js.map +1 -0
- package/dist/src/cli/gloss-codex-child.d.ts +9 -0
- package/dist/src/cli/gloss-codex-child.js +149 -0
- package/dist/src/cli/gloss-codex-child.js.map +1 -0
- package/dist/src/cli/gloss-codex.d.ts +24 -0
- package/dist/src/cli/gloss-codex.js +255 -0
- package/dist/src/cli/gloss-codex.js.map +1 -0
- package/dist/src/cli/gloss-options.d.ts +42 -0
- package/dist/src/cli/gloss-options.js +79 -0
- package/dist/src/cli/gloss-options.js.map +1 -0
- package/dist/src/cli/gloss.d.ts +265 -0
- package/dist/src/cli/gloss.js +362 -0
- package/dist/src/cli/gloss.js.map +1 -0
- package/dist/src/cli/help.d.ts +103 -0
- package/dist/src/cli/help.js +2339 -0
- package/dist/src/cli/help.js.map +1 -0
- package/dist/src/cli/hook-codex.d.ts +78 -0
- package/dist/src/cli/hook-codex.js +167 -0
- package/dist/src/cli/hook-codex.js.map +1 -0
- package/dist/src/cli/hook.d.ts +331 -0
- package/dist/src/cli/hook.js +2849 -0
- package/dist/src/cli/hook.js.map +1 -0
- package/dist/src/cli/import.d.ts +35 -0
- package/dist/src/cli/import.js +175 -0
- package/dist/src/cli/import.js.map +1 -0
- package/dist/src/cli/init.d.ts +84 -0
- package/dist/src/cli/init.js +336 -0
- package/dist/src/cli/init.js.map +1 -0
- package/dist/src/cli/instructions.d.ts +23 -0
- package/dist/src/cli/instructions.js +262 -0
- package/dist/src/cli/instructions.js.map +1 -0
- package/dist/src/cli/journal.d.ts +41 -0
- package/dist/src/cli/journal.js +238 -0
- package/dist/src/cli/journal.js.map +1 -0
- package/dist/src/cli/log-advance.d.ts +287 -0
- package/dist/src/cli/log-advance.js +840 -0
- package/dist/src/cli/log-advance.js.map +1 -0
- package/dist/src/cli/log-anchor.d.ts +176 -0
- package/dist/src/cli/log-anchor.js +387 -0
- package/dist/src/cli/log-anchor.js.map +1 -0
- package/dist/src/cli/log-checkpoint.d.ts +22 -0
- package/dist/src/cli/log-checkpoint.js +128 -0
- package/dist/src/cli/log-checkpoint.js.map +1 -0
- package/dist/src/cli/log-sync.d.ts +243 -0
- package/dist/src/cli/log-sync.js +849 -0
- package/dist/src/cli/log-sync.js.map +1 -0
- package/dist/src/cli/log-verbs.d.ts +16 -0
- package/dist/src/cli/log-verbs.js +360 -0
- package/dist/src/cli/log-verbs.js.map +1 -0
- package/dist/src/cli/long-help.d.ts +70 -0
- package/dist/src/cli/long-help.js +148 -0
- package/dist/src/cli/long-help.js.map +1 -0
- package/dist/src/cli/main.d.ts +77 -0
- package/dist/src/cli/main.js +1206 -0
- package/dist/src/cli/main.js.map +1 -0
- package/dist/src/cli/mcp.d.ts +52 -0
- package/dist/src/cli/mcp.js +306 -0
- package/dist/src/cli/mcp.js.map +1 -0
- package/dist/src/cli/paths.d.ts +56 -0
- package/dist/src/cli/paths.js +79 -0
- package/dist/src/cli/paths.js.map +1 -0
- package/dist/src/cli/payload.d.ts +58 -0
- package/dist/src/cli/payload.js +253 -0
- package/dist/src/cli/payload.js.map +1 -0
- package/dist/src/cli/policy.d.ts +43 -0
- package/dist/src/cli/policy.js +229 -0
- package/dist/src/cli/policy.js.map +1 -0
- package/dist/src/cli/preflight.d.ts +363 -0
- package/dist/src/cli/preflight.js +1175 -0
- package/dist/src/cli/preflight.js.map +1 -0
- package/dist/src/cli/progress.d.ts +78 -0
- package/dist/src/cli/progress.js +112 -0
- package/dist/src/cli/progress.js.map +1 -0
- package/dist/src/cli/prompt.d.ts +209 -0
- package/dist/src/cli/prompt.js +312 -0
- package/dist/src/cli/prompt.js.map +1 -0
- package/dist/src/cli/quickstart.d.ts +46 -0
- package/dist/src/cli/quickstart.js +297 -0
- package/dist/src/cli/quickstart.js.map +1 -0
- package/dist/src/cli/records.d.ts +34 -0
- package/dist/src/cli/records.js +66 -0
- package/dist/src/cli/records.js.map +1 -0
- package/dist/src/cli/render.d.ts +22 -0
- package/dist/src/cli/render.js +132 -0
- package/dist/src/cli/render.js.map +1 -0
- package/dist/src/cli/sandbox.d.ts +51 -0
- package/dist/src/cli/sandbox.js +150 -0
- package/dist/src/cli/sandbox.js.map +1 -0
- package/dist/src/cli/scaffold.d.ts +79 -0
- package/dist/src/cli/scaffold.js +137 -0
- package/dist/src/cli/scaffold.js.map +1 -0
- package/dist/src/cli/setup-adapter.d.ts +137 -0
- package/dist/src/cli/setup-adapter.js +509 -0
- package/dist/src/cli/setup-adapter.js.map +1 -0
- package/dist/src/cli/setup-channel.d.ts +117 -0
- package/dist/src/cli/setup-channel.js +635 -0
- package/dist/src/cli/setup-channel.js.map +1 -0
- package/dist/src/cli/setup-checkpoint.d.ts +57 -0
- package/dist/src/cli/setup-checkpoint.js +196 -0
- package/dist/src/cli/setup-checkpoint.js.map +1 -0
- package/dist/src/cli/setup-common.d.ts +275 -0
- package/dist/src/cli/setup-common.js +376 -0
- package/dist/src/cli/setup-common.js.map +1 -0
- package/dist/src/cli/setup-flow.d.ts +287 -0
- package/dist/src/cli/setup-flow.js +476 -0
- package/dist/src/cli/setup-flow.js.map +1 -0
- package/dist/src/cli/setup-service.d.ts +96 -0
- package/dist/src/cli/setup-service.js +308 -0
- package/dist/src/cli/setup-service.js.map +1 -0
- package/dist/src/cli/setup.d.ts +202 -0
- package/dist/src/cli/setup.js +473 -0
- package/dist/src/cli/setup.js.map +1 -0
- package/dist/src/cli/style.d.ts +320 -0
- package/dist/src/cli/style.js +469 -0
- package/dist/src/cli/style.js.map +1 -0
- package/dist/src/cli/token.d.ts +39 -0
- package/dist/src/cli/token.js +274 -0
- package/dist/src/cli/token.js.map +1 -0
- package/dist/src/cli/up.d.ts +155 -0
- package/dist/src/cli/up.js +849 -0
- package/dist/src/cli/up.js.map +1 -0
- package/dist/src/cli/usage.d.ts +37 -0
- package/dist/src/cli/usage.js +91 -0
- package/dist/src/cli/usage.js.map +1 -0
- package/dist/src/cli/values.d.ts +40 -0
- package/dist/src/cli/values.js +189 -0
- package/dist/src/cli/values.js.map +1 -0
- package/dist/src/cli/vault.d.ts +59 -0
- package/dist/src/cli/vault.js +362 -0
- package/dist/src/cli/vault.js.map +1 -0
- package/dist/src/cli/verb-registry.d.ts +76 -0
- package/dist/src/cli/verb-registry.js +2341 -0
- package/dist/src/cli/verb-registry.js.map +1 -0
- package/dist/src/cli/wordmark.d.ts +31 -0
- package/dist/src/cli/wordmark.js +52 -0
- package/dist/src/cli/wordmark.js.map +1 -0
- package/dist/src/codex/doctor.d.ts +13 -0
- package/dist/src/codex/doctor.js +41 -0
- package/dist/src/codex/doctor.js.map +1 -0
- package/dist/src/codex/manifest.d.ts +49 -0
- package/dist/src/codex/manifest.js +103 -0
- package/dist/src/codex/manifest.js.map +1 -0
- package/dist/src/codex/templates.d.ts +41 -0
- package/dist/src/codex/templates.js +319 -0
- package/dist/src/codex/templates.js.map +1 -0
- package/dist/src/codex/trust.d.ts +19 -0
- package/dist/src/codex/trust.js +183 -0
- package/dist/src/codex/trust.js.map +1 -0
- package/dist/src/codex/workspace-plan.d.ts +131 -0
- package/dist/src/codex/workspace-plan.js +561 -0
- package/dist/src/codex/workspace-plan.js.map +1 -0
- package/dist/src/core/actor.d.ts +2 -0
- package/dist/src/core/actor.js +5 -0
- package/dist/src/core/actor.js.map +1 -0
- package/dist/src/core/advance-cycle.d.ts +170 -0
- package/dist/src/core/advance-cycle.js +200 -0
- package/dist/src/core/advance-cycle.js.map +1 -0
- package/dist/src/core/agents-md.d.ts +276 -0
- package/dist/src/core/agents-md.js +747 -0
- package/dist/src/core/agents-md.js.map +1 -0
- package/dist/src/core/apply-patch.d.ts +49 -0
- package/dist/src/core/apply-patch.js +266 -0
- package/dist/src/core/apply-patch.js.map +1 -0
- package/dist/src/core/attest.d.ts +420 -0
- package/dist/src/core/attest.js +589 -0
- package/dist/src/core/attest.js.map +1 -0
- package/dist/src/core/audit.d.ts +492 -0
- package/dist/src/core/audit.js +882 -0
- package/dist/src/core/audit.js.map +1 -0
- package/dist/src/core/budgets.d.ts +238 -0
- package/dist/src/core/budgets.js +449 -0
- package/dist/src/core/budgets.js.map +1 -0
- package/dist/src/core/checkpoint.d.ts +500 -0
- package/dist/src/core/checkpoint.js +738 -0
- package/dist/src/core/checkpoint.js.map +1 -0
- package/dist/src/core/child-env.d.ts +88 -0
- package/dist/src/core/child-env.js +86 -0
- package/dist/src/core/child-env.js.map +1 -0
- package/dist/src/core/clock.d.ts +52 -0
- package/dist/src/core/clock.js +43 -0
- package/dist/src/core/clock.js.map +1 -0
- package/dist/src/core/command-class.d.ts +543 -0
- package/dist/src/core/command-class.js +2356 -0
- package/dist/src/core/command-class.js.map +1 -0
- package/dist/src/core/coverage-sources/adapter.d.ts +40 -0
- package/dist/src/core/coverage-sources/adapter.js +71 -0
- package/dist/src/core/coverage-sources/adapter.js.map +1 -0
- package/dist/src/core/coverage-sources/gh.d.ts +48 -0
- package/dist/src/core/coverage-sources/gh.js +136 -0
- package/dist/src/core/coverage-sources/gh.js.map +1 -0
- package/dist/src/core/coverage-sources/git.d.ts +101 -0
- package/dist/src/core/coverage-sources/git.js +269 -0
- package/dist/src/core/coverage-sources/git.js.map +1 -0
- package/dist/src/core/coverage.d.ts +217 -0
- package/dist/src/core/coverage.js +337 -0
- package/dist/src/core/coverage.js.map +1 -0
- package/dist/src/core/credential-spec.d.ts +72 -0
- package/dist/src/core/credential-spec.js +23 -0
- package/dist/src/core/credential-spec.js.map +1 -0
- package/dist/src/core/dark-session.d.ts +331 -0
- package/dist/src/core/dark-session.js +714 -0
- package/dist/src/core/dark-session.js.map +1 -0
- package/dist/src/core/decision-refusal.d.ts +185 -0
- package/dist/src/core/decision-refusal.js +265 -0
- package/dist/src/core/decision-refusal.js.map +1 -0
- package/dist/src/core/env-file.d.ts +450 -0
- package/dist/src/core/env-file.js +837 -0
- package/dist/src/core/env-file.js.map +1 -0
- package/dist/src/core/execute.d.ts +858 -0
- package/dist/src/core/execute.js +1271 -0
- package/dist/src/core/execute.js.map +1 -0
- package/dist/src/core/frontmatter.d.ts +78 -0
- package/dist/src/core/frontmatter.js +100 -0
- package/dist/src/core/frontmatter.js.map +1 -0
- package/dist/src/core/gate-window.d.ts +312 -0
- package/dist/src/core/gate-window.js +506 -0
- package/dist/src/core/gate-window.js.map +1 -0
- package/dist/src/core/gate.d.ts +1364 -0
- package/dist/src/core/gate.js +3002 -0
- package/dist/src/core/gate.js.map +1 -0
- package/dist/src/core/git-run.d.ts +73 -0
- package/dist/src/core/git-run.js +93 -0
- package/dist/src/core/git-run.js.map +1 -0
- package/dist/src/core/harness-version.d.ts +157 -0
- package/dist/src/core/harness-version.js +211 -0
- package/dist/src/core/harness-version.js.map +1 -0
- package/dist/src/core/harness-wait.d.ts +55 -0
- package/dist/src/core/harness-wait.js +58 -0
- package/dist/src/core/harness-wait.js.map +1 -0
- package/dist/src/core/head-retry.d.ts +107 -0
- package/dist/src/core/head-retry.js +121 -0
- package/dist/src/core/head-retry.js.map +1 -0
- package/dist/src/core/instance.d.ts +253 -0
- package/dist/src/core/instance.js +319 -0
- package/dist/src/core/instance.js.map +1 -0
- package/dist/src/core/intake-limits.d.ts +247 -0
- package/dist/src/core/intake-limits.js +350 -0
- package/dist/src/core/intake-limits.js.map +1 -0
- package/dist/src/core/jcs.d.ts +52 -0
- package/dist/src/core/jcs.js +132 -0
- package/dist/src/core/jcs.js.map +1 -0
- package/dist/src/core/journal.d.ts +144 -0
- package/dist/src/core/journal.js +200 -0
- package/dist/src/core/journal.js.map +1 -0
- package/dist/src/core/live-draw.d.ts +436 -0
- package/dist/src/core/live-draw.js +703 -0
- package/dist/src/core/live-draw.js.map +1 -0
- package/dist/src/core/log-reconcile.d.ts +89 -0
- package/dist/src/core/log-reconcile.js +136 -0
- package/dist/src/core/log-reconcile.js.map +1 -0
- package/dist/src/core/log-subscribe.d.ts +36 -0
- package/dist/src/core/log-subscribe.js +162 -0
- package/dist/src/core/log-subscribe.js.map +1 -0
- package/dist/src/core/log.d.ts +278 -0
- package/dist/src/core/log.js +546 -0
- package/dist/src/core/log.js.map +1 -0
- package/dist/src/core/loop.d.ts +274 -0
- package/dist/src/core/loop.js +487 -0
- package/dist/src/core/loop.js.map +1 -0
- package/dist/src/core/md-fence.d.ts +41 -0
- package/dist/src/core/md-fence.js +74 -0
- package/dist/src/core/md-fence.js.map +1 -0
- package/dist/src/core/money.d.ts +147 -0
- package/dist/src/core/money.js +195 -0
- package/dist/src/core/money.js.map +1 -0
- package/dist/src/core/payload-census.d.ts +74 -0
- package/dist/src/core/payload-census.js +146 -0
- package/dist/src/core/payload-census.js.map +1 -0
- package/dist/src/core/payload-store.d.ts +175 -0
- package/dist/src/core/payload-store.js +340 -0
- package/dist/src/core/payload-store.js.map +1 -0
- package/dist/src/core/payload.d.ts +71 -0
- package/dist/src/core/payload.js +80 -0
- package/dist/src/core/payload.js.map +1 -0
- package/dist/src/core/policy-diff.d.ts +292 -0
- package/dist/src/core/policy-diff.js +588 -0
- package/dist/src/core/policy-diff.js.map +1 -0
- package/dist/src/core/policy-expectations.d.ts +199 -0
- package/dist/src/core/policy-expectations.js +394 -0
- package/dist/src/core/policy-expectations.js.map +1 -0
- package/dist/src/core/policy-explain.d.ts +150 -0
- package/dist/src/core/policy-explain.js +258 -0
- package/dist/src/core/policy-explain.js.map +1 -0
- package/dist/src/core/policy-load.d.ts +527 -0
- package/dist/src/core/policy-load.js +536 -0
- package/dist/src/core/policy-load.js.map +1 -0
- package/dist/src/core/policy-match.d.ts +281 -0
- package/dist/src/core/policy-match.js +478 -0
- package/dist/src/core/policy-match.js.map +1 -0
- package/dist/src/core/policy-proposal.d.ts +265 -0
- package/dist/src/core/policy-proposal.js +458 -0
- package/dist/src/core/policy-proposal.js.map +1 -0
- package/dist/src/core/prompt-layout.d.ts +221 -0
- package/dist/src/core/prompt-layout.js +422 -0
- package/dist/src/core/prompt-layout.js.map +1 -0
- package/dist/src/core/protected-path-guard.d.ts +453 -0
- package/dist/src/core/protected-path-guard.js +1566 -0
- package/dist/src/core/protected-path-guard.js.map +1 -0
- package/dist/src/core/registration.d.ts +25 -0
- package/dist/src/core/registration.js +39 -0
- package/dist/src/core/registration.js.map +1 -0
- package/dist/src/core/reindex.d.ts +99 -0
- package/dist/src/core/reindex.js +336 -0
- package/dist/src/core/reindex.js.map +1 -0
- package/dist/src/core/sampler.d.ts +313 -0
- package/dist/src/core/sampler.js +388 -0
- package/dist/src/core/sampler.js.map +1 -0
- package/dist/src/core/sandbox.d.ts +290 -0
- package/dist/src/core/sandbox.js +424 -0
- package/dist/src/core/sandbox.js.map +1 -0
- package/dist/src/core/seal.d.ts +165 -0
- package/dist/src/core/seal.js +290 -0
- package/dist/src/core/seal.js.map +1 -0
- package/dist/src/core/state.d.ts +505 -0
- package/dist/src/core/state.js +1009 -0
- package/dist/src/core/state.js.map +1 -0
- package/dist/src/core/task-file.d.ts +185 -0
- package/dist/src/core/task-file.js +464 -0
- package/dist/src/core/task-file.js.map +1 -0
- package/dist/src/core/telegram-config.d.ts +93 -0
- package/dist/src/core/telegram-config.js +114 -0
- package/dist/src/core/telegram-config.js.map +1 -0
- package/dist/src/core/token.d.ts +409 -0
- package/dist/src/core/token.js +561 -0
- package/dist/src/core/token.js.map +1 -0
- package/dist/src/core/validate.d.ts +138 -0
- package/dist/src/core/validate.js +0 -0
- package/dist/src/core/validate.js.map +1 -0
- package/dist/src/core/values.d.ts +137 -0
- package/dist/src/core/values.js +153 -0
- package/dist/src/core/values.js.map +1 -0
- package/dist/src/core/vault.d.ts +291 -0
- package/dist/src/core/vault.js +612 -0
- package/dist/src/core/vault.js.map +1 -0
- package/dist/src/core/verified-snapshot.d.ts +204 -0
- package/dist/src/core/verified-snapshot.js +506 -0
- package/dist/src/core/verified-snapshot.js.map +1 -0
- package/dist/src/core/verify.d.ts +336 -0
- package/dist/src/core/verify.js +549 -0
- package/dist/src/core/verify.js.map +1 -0
- package/dist/src/core/version.d.ts +8 -0
- package/dist/src/core/version.js +9 -0
- package/dist/src/core/version.js.map +1 -0
- package/dist/src/core/wysiwys.d.ts +370 -0
- package/dist/src/core/wysiwys.js +728 -0
- package/dist/src/core/wysiwys.js.map +1 -0
- package/dist/src/daemon/advance-child.d.ts +39 -0
- package/dist/src/daemon/advance-child.js +78 -0
- package/dist/src/daemon/advance-child.js.map +1 -0
- package/dist/src/daemon/advance.d.ts +466 -0
- package/dist/src/daemon/advance.js +849 -0
- package/dist/src/daemon/advance.js.map +1 -0
- package/dist/src/daemon/audit.d.ts +87 -0
- package/dist/src/daemon/audit.js +90 -0
- package/dist/src/daemon/audit.js.map +1 -0
- package/dist/src/daemon/daemon.d.ts +1180 -0
- package/dist/src/daemon/daemon.js +1988 -0
- package/dist/src/daemon/daemon.js.map +1 -0
- package/dist/src/daemon/dark-session.d.ts +64 -0
- package/dist/src/daemon/dark-session.js +119 -0
- package/dist/src/daemon/dark-session.js.map +1 -0
- package/dist/src/daemon/draw-child.d.ts +36 -0
- package/dist/src/daemon/draw-child.js +132 -0
- package/dist/src/daemon/draw-child.js.map +1 -0
- package/dist/src/daemon/draw.d.ts +154 -0
- package/dist/src/daemon/draw.js +458 -0
- package/dist/src/daemon/draw.js.map +1 -0
- package/dist/src/daemon/git-evidence.d.ts +173 -0
- package/dist/src/daemon/git-evidence.js +345 -0
- package/dist/src/daemon/git-evidence.js.map +1 -0
- package/dist/src/daemon/projection.d.ts +180 -0
- package/dist/src/daemon/projection.js +233 -0
- package/dist/src/daemon/projection.js.map +1 -0
- package/dist/src/daemon/prune.d.ts +207 -0
- package/dist/src/daemon/prune.js +376 -0
- package/dist/src/daemon/prune.js.map +1 -0
- package/dist/src/mcp/http.d.ts +113 -0
- package/dist/src/mcp/http.js +343 -0
- package/dist/src/mcp/http.js.map +1 -0
- package/dist/src/mcp/server.d.ts +265 -0
- package/dist/src/mcp/server.js +602 -0
- package/dist/src/mcp/server.js.map +1 -0
- package/docs/adapter-api.md +106 -0
- package/docs/cli-reference.md +5716 -0
- package/docs/codex-enforced-session.md +30 -0
- package/package.json +53 -4
- package/schema/.gitkeep +0 -0
- package/schema/LICENSE +117 -0
- package/schema/codex-instance.schema.json +82 -0
- package/schema/envelope.schema.json +137 -0
- package/schema/event.schema.json +1811 -0
- package/schema/fixtures/codex-instance/invalid/unpinned-codex-version.json +40 -0
- package/schema/fixtures/codex-instance/valid/canonical.json +40 -0
- package/schema/fixtures/envelope/invalid/action-missing-idempotency-key.json +15 -0
- package/schema/fixtures/envelope/invalid/action-unknown-class-format.json +14 -0
- package/schema/fixtures/envelope/invalid/confidence-out-of-range.json +11 -0
- package/schema/fixtures/envelope/invalid/est-cost-bare-number.json +14 -0
- package/schema/fixtures/envelope/invalid/est-cost-noncanonical-string.json +14 -0
- package/schema/fixtures/envelope/invalid/malformed-assignee.json +10 -0
- package/schema/fixtures/envelope/invalid/malformed-created-by.json +7 -0
- package/schema/fixtures/envelope/invalid/malformed-max-latency.json +11 -0
- package/schema/fixtures/envelope/invalid/malformed-payload-hash.json +14 -0
- package/schema/fixtures/envelope/invalid/max-cost-bare-number.json +11 -0
- package/schema/fixtures/envelope/invalid/missing-origin.json +3 -0
- package/schema/fixtures/envelope/invalid/negative-est-cost.json +14 -0
- package/schema/fixtures/envelope/invalid/unknown-state.json +7 -0
- package/schema/fixtures/envelope/invalid/unknown-top-level-field.json +8 -0
- package/schema/fixtures/envelope/valid/action-payload-hash.json +17 -0
- package/schema/fixtures/envelope/valid/actions-without-budget.json +18 -0
- package/schema/fixtures/envelope/valid/canonical.json +25 -0
- package/schema/fixtures/envelope/valid/minimal.json +7 -0
- package/schema/fixtures/envelope/valid/multi-action-executed.json +30 -0
- package/schema/fixtures/envelope/valid/record-write-stage.json +22 -0
- package/schema/fixtures/event/invalid/approval-granted-agent-actor.json +15 -0
- package/schema/fixtures/event/invalid/approval-granted-empty-batch-delivery-id.json +17 -0
- package/schema/fixtures/event/invalid/approval-granted-fifth-reaction.json +16 -0
- package/schema/fixtures/event/invalid/approval-granted-missing-actor.json +14 -0
- package/schema/fixtures/event/invalid/approval-requested-missing-action-key.json +14 -0
- package/schema/fixtures/event/invalid/approval-withdrawn-agent-policy-drift.json +15 -0
- package/schema/fixtures/event/invalid/approval-withdrawn-missing-reason.json +15 -0
- package/schema/fixtures/event/invalid/approval-withdrawn-system-actor.json +15 -0
- package/schema/fixtures/event/invalid/audit-decision-refused-human-actor.json +17 -0
- package/schema/fixtures/event/invalid/audit-decision-refused-missing-code.json +16 -0
- package/schema/fixtures/event/invalid/audit-reviewed-agent-actor.json +15 -0
- package/schema/fixtures/event/invalid/audit-reviewed-loved-no-note.json +16 -0
- package/schema/fixtures/event/invalid/audit-reviewed-system-actor.json +15 -0
- package/schema/fixtures/event/invalid/bad-actor-prefix.json +15 -0
- package/schema/fixtures/event/invalid/est-cost-bare-number.json +17 -0
- package/schema/fixtures/event/invalid/execution-completed-fabricated-exit-code.json +16 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-empty-id.json +18 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-extra-field.json +19 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-id-not-string.json +18 -0
- package/schema/fixtures/event/invalid/execution-completed-provider-ref-missing-adapter.json +17 -0
- package/schema/fixtures/event/invalid/execution-failed-open-reported-by.json +16 -0
- package/schema/fixtures/event/invalid/execution-indeterminate-open-reason.json +14 -0
- package/schema/fixtures/event/invalid/execution-reconciled-agent-actor.json +17 -0
- package/schema/fixtures/event/invalid/execution-started-negative-env-stripped.json +16 -0
- package/schema/fixtures/event/invalid/gate-bypassed-missing-opened-seq.json +15 -0
- package/schema/fixtures/event/invalid/gate-closed-non-integer-opened-seq.json +13 -0
- package/schema/fixtures/event/invalid/gate-opened-agent-actor.json +16 -0
- package/schema/fixtures/event/invalid/gate-organ-attested-absolute-path.json +14 -0
- package/schema/fixtures/event/invalid/gate-organ-attested-agent-actor.json +14 -0
- package/schema/fixtures/event/invalid/gate-organ-attested-missing-organ-path.json +13 -0
- package/schema/fixtures/event/invalid/harness-unknown-kind.json +18 -0
- package/schema/fixtures/event/invalid/harness-version-multiline.json +16 -0
- package/schema/fixtures/event/invalid/log-checkpoint-agent-actor.json +17 -0
- package/schema/fixtures/event/invalid/log-checkpoint-missing-signature.json +16 -0
- package/schema/fixtures/event/invalid/log-checkpoint-short-signed-hash.json +17 -0
- package/schema/fixtures/event/invalid/log-checkpoint-unknown-signature-alg.json +17 -0
- package/schema/fixtures/event/invalid/malformed-ts.json +15 -0
- package/schema/fixtures/event/invalid/missing-alg.json +14 -0
- package/schema/fixtures/event/invalid/missing-hash.json +14 -0
- package/schema/fixtures/event/invalid/non-integer-seq.json +15 -0
- package/schema/fixtures/event/invalid/payload-pruned-human-actor.json +14 -0
- package/schema/fixtures/event/invalid/payload-pruned-missing-hash.json +14 -0
- package/schema/fixtures/event/invalid/policy-declined-agent-actor.json +15 -0
- package/schema/fixtures/event/invalid/policy-proposed-missing-diff.json +19 -0
- package/schema/fixtures/event/invalid/policy-proposed-system-actor.json +26 -0
- package/schema/fixtures/event/invalid/short-hash.json +15 -0
- package/schema/fixtures/event/invalid/unknown-alg.json +15 -0
- package/schema/fixtures/event/invalid/unknown-event-type.json +15 -0
- package/schema/fixtures/event/invalid/unknown-top-level-field.json +16 -0
- package/schema/fixtures/event/valid/approval-expired.json +15 -0
- package/schema/fixtures/event/valid/approval-granted-batch.json +19 -0
- package/schema/fixtures/event/valid/approval-granted-reaction.json +16 -0
- package/schema/fixtures/event/valid/approval-granted.json +15 -0
- package/schema/fixtures/event/valid/approval-rejected.json +15 -0
- package/schema/fixtures/event/valid/approval-requested.json +19 -0
- package/schema/fixtures/event/valid/approval-revoked.json +15 -0
- package/schema/fixtures/event/valid/approval-withdrawn-policy-drift.json +17 -0
- package/schema/fixtures/event/valid/approval-withdrawn.json +16 -0
- package/schema/fixtures/event/valid/audit-decision-refused.json +20 -0
- package/schema/fixtures/event/valid/audit-reviewed-reaction.json +17 -0
- package/schema/fixtures/event/valid/audit-reviewed.json +15 -0
- package/schema/fixtures/event/valid/audit-sampled.json +14 -0
- package/schema/fixtures/event/valid/budget-exceeded.json +21 -0
- package/schema/fixtures/event/valid/envelope-drift.json +16 -0
- package/schema/fixtures/event/valid/execution-completed-harness-report.json +16 -0
- package/schema/fixtures/event/valid/execution-completed-provider-ref.json +18 -0
- package/schema/fixtures/event/valid/execution-completed.json +15 -0
- package/schema/fixtures/event/valid/execution-failed-harness-report.json +16 -0
- package/schema/fixtures/event/valid/execution-failed.json +15 -0
- package/schema/fixtures/event/valid/execution-indeterminate.json +15 -0
- package/schema/fixtures/event/valid/execution-reconciled.json +17 -0
- package/schema/fixtures/event/valid/execution-started-env-stripped.json +17 -0
- package/schema/fixtures/event/valid/execution-started.json +14 -0
- package/schema/fixtures/event/valid/gate-bypassed-harness-version.json +18 -0
- package/schema/fixtures/event/valid/gate-bypassed.json +19 -0
- package/schema/fixtures/event/valid/gate-closed.json +14 -0
- package/schema/fixtures/event/valid/gate-opened.json +16 -0
- package/schema/fixtures/event/valid/gate-organ-attested.json +14 -0
- package/schema/fixtures/event/valid/genesis-null-prev.json +14 -0
- package/schema/fixtures/event/valid/log-checkpoint.json +17 -0
- package/schema/fixtures/event/valid/payload-pruned-orphan.json +13 -0
- package/schema/fixtures/event/valid/payload-pruned.json +17 -0
- package/schema/fixtures/event/valid/policy-declined.json +16 -0
- package/schema/fixtures/event/valid/policy-proposed.json +35 -0
- package/schema/fixtures/event/valid/policy-updated.json +14 -0
- package/schema/fixtures/event/valid/reconciliation-required.json +18 -0
- package/schema/fixtures/event/valid/reconciliation-satisfied.json +17 -0
- package/schema/fixtures/event/valid/route-accepted.json +15 -0
- package/schema/fixtures/event/valid/route-proposed.json +16 -0
- package/schema/fixtures/event/valid/spec-example.json +15 -0
- package/schema/fixtures/event/valid/task-registered-harness-version.json +23 -0
- package/schema/fixtures/event/valid/task-registered.json +14 -0
- package/schema/fixtures/hash/known-answer-pre-121.json +74 -0
- package/schema/fixtures/hash/known-answer.json +74 -0
- package/schema/fixtures/policy/invalid/bad-approval-ttl.json +7 -0
- package/schema/fixtures/policy/invalid/bad-web-port.json +4 -0
- package/schema/fixtures/policy/invalid/checkpoint-key-not-base64.json +6 -0
- package/schema/fixtures/policy/invalid/class-rule-missing-autonomy.json +9 -0
- package/schema/fixtures/policy/invalid/empty-class-key.json +6 -0
- package/schema/fixtures/policy/invalid/live-rate-on-human-only.json +7 -0
- package/schema/fixtures/policy/invalid/malformed-class-key.json +6 -0
- package/schema/fixtures/policy/invalid/missing-version.json +8 -0
- package/schema/fixtures/policy/invalid/negative-limit.json +9 -0
- package/schema/fixtures/policy/invalid/non-numeric-limit.json +9 -0
- package/schema/fixtures/policy/invalid/non-positive-max-pending.json +9 -0
- package/schema/fixtures/policy/invalid/on-expiry-grant.json +8 -0
- package/schema/fixtures/policy/invalid/payload-retention-bare-number.json +4 -0
- package/schema/fixtures/policy/invalid/payload-retention-compound.json +4 -0
- package/schema/fixtures/policy/invalid/payload-retention-fractional.json +4 -0
- package/schema/fixtures/policy/invalid/payload-retention-zero.json +4 -0
- package/schema/fixtures/policy/invalid/protected-paths-escape.json +4 -0
- package/schema/fixtures/policy/invalid/protected-paths-glob.json +4 -0
- package/schema/fixtures/policy/invalid/retro-rate-on-human-only.json +7 -0
- package/schema/fixtures/policy/invalid/retro-rate-on-manual.json +7 -0
- package/schema/fixtures/policy/invalid/retro-rate-zero.json +7 -0
- package/schema/fixtures/policy/invalid/sample-rate-too-high.json +5 -0
- package/schema/fixtures/policy/invalid/sampling-secret-env-empty.json +7 -0
- package/schema/fixtures/policy/invalid/sampling-secret-env-not-string.json +6 -0
- package/schema/fixtures/policy/invalid/skew-tolerance-compound.json +6 -0
- package/schema/fixtures/policy/invalid/unknown-autonomy.json +7 -0
- package/schema/fixtures/policy/invalid/unknown-class-rule-key.json +6 -0
- package/schema/fixtures/policy/invalid/unknown-top-level-key.json +7 -0
- package/schema/fixtures/policy/invalid/vault-passphrase-env-empty.json +6 -0
- package/schema/fixtures/policy/invalid/vault-passphrase-literal.json +6 -0
- package/schema/fixtures/policy/invalid/version-not-string.json +4 -0
- package/schema/fixtures/policy/valid/canonical.json +47 -0
- package/schema/fixtures/policy/valid/checkpoint-keys.json +18 -0
- package/schema/fixtures/policy/valid/class-approvers-limits.json +25 -0
- package/schema/fixtures/policy/valid/class-retro-rate.json +17 -0
- package/schema/fixtures/policy/valid/global-budgets.json +19 -0
- package/schema/fixtures/policy/valid/human-only.json +9 -0
- package/schema/fixtures/policy/valid/minimal.json +6 -0
- package/schema/fixtures/policy/valid/protected-paths.json +10 -0
- package/schema/fixtures/policy/valid/record-namespace.json +13 -0
- package/schema/fixtures/policy/valid/request-volume-limits.json +26 -0
- package/schema/fixtures/policy/valid/retention-and-sampling-secret.json +16 -0
- package/schema/fixtures/policy/valid/skew-tolerance.json +15 -0
- package/schema/fixtures/policy/valid/vault-passphrase-env.json +14 -0
- package/schema/fixtures/policy/valid/wildcards.json +15 -0
- package/schema/fixtures/policy-md/invalid/alias-bomb.md +15 -0
- package/schema/fixtures/policy-md/invalid/no-fence.md +7 -0
- package/schema/fixtures/policy-md/invalid/protected-route-not-a-subclass.md +16 -0
- package/schema/fixtures/policy-md/invalid/schema-invalid-autonomy.md +16 -0
- package/schema/fixtures/policy-md/invalid/schema-invalid-read-proof.md +17 -0
- package/schema/fixtures/policy-md/invalid/two-fences.md +19 -0
- package/schema/fixtures/policy-md/invalid/unclosed-fence.md +11 -0
- package/schema/fixtures/policy-md/invalid/wrong-info-string.md +11 -0
- package/schema/fixtures/policy-md/invalid/yaml-syntax-error.md +13 -0
- package/schema/fixtures/policy-md/precedence/both/APPROVAL.md +7 -0
- package/schema/fixtures/policy-md/precedence/both/APPROVALS.md +7 -0
- package/schema/fixtures/policy-md/precedence/fallback-only/APPROVALS.md +7 -0
- package/schema/fixtures/policy-md/valid/canonical.md +50 -0
- package/schema/fixtures/policy-md/valid/daemon-read-proof.md +18 -0
- package/schema/fixtures/policy-md/valid/minimal.md +3 -0
- package/schema/fixtures/policy-md/valid/prose-lookalikes.md +54 -0
- package/schema/fixtures/policy-md/valid/routed-protected-paths.md +49 -0
- package/schema/fixtures/policy-md/valid/with-values.md +79 -0
- package/schema/fixtures/sample-record/invalid/bad-date-time.json +4 -0
- package/schema/fixtures/sample-record/invalid/missing-required-field.json +3 -0
- package/schema/fixtures/sample-record/invalid/unknown-top-level-field.json +5 -0
- package/schema/fixtures/sample-record/invalid/wrong-type.json +4 -0
- package/schema/fixtures/sample-record/valid/minimal.json +4 -0
- package/schema/fixtures/sample-record/valid/with-note.json +5 -0
- package/schema/fixtures/values/invalid/class-shaped.json +9 -0
- package/schema/fixtures/values/invalid/duplicate-entry.json +4 -0
- package/schema/fixtures/values/invalid/non-string-item.json +4 -0
- package/schema/fixtures/values/invalid/over-cap.json +26 -0
- package/schema/fixtures/values/invalid/unknown-key.json +5 -0
- package/schema/fixtures/values/invalid/version-string.json +1 -0
- package/schema/fixtures/values/valid/empty-lists.json +7 -0
- package/schema/fixtures/values/valid/full.json +20 -0
- package/schema/fixtures/values/valid/minimal.json +1 -0
- package/schema/fixtures/values-md/invalid/schema-invalid.md +62 -0
- package/schema/fixtures/values-md/invalid/two-blocks.md +69 -0
- package/schema/fixtures/values-md/invalid/unterminated.md +61 -0
- package/schema/fixtures/values-md/invalid/yaml-error.md +63 -0
- package/schema/fixtures/values-md/valid/absent.md +50 -0
- package/schema/fixtures/values-md/valid/with-values.md +79 -0
- package/schema/policy.schema.json +501 -0
- package/schema/sample-record.schema.json +26 -0
- package/schema/values.schema.json +55 -0
- package/templates/codex/README.md +9 -0
|
@@ -0,0 +1,612 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The reference credential vault (SPEC.md §10.4, §11; APRV-68).
|
|
3
|
+
*
|
|
4
|
+
* SPEC.md §10.4 states the hard boundary in one sentence: adapters "hold the
|
|
5
|
+
* actual credentials in an encrypted vault and MUST require a valid, unexpired,
|
|
6
|
+
* single-use execution token bound to the action's `idempotency_key` … an agent
|
|
7
|
+
* that bypasses the CLI still cannot send, spend, or delete, because the
|
|
8
|
+
* credentials only answer to tokens." APRV-67 built the token half of that
|
|
9
|
+
* sentence (`adapters/contract.ts`: a credential provider that is live only
|
|
10
|
+
* inside the verified-token window). This module is the other half: the place
|
|
11
|
+
* the values actually sit when nobody is executing.
|
|
12
|
+
*
|
|
13
|
+
* ## What it is
|
|
14
|
+
*
|
|
15
|
+
* One file, `.approval/vault.enc`, beside the log's home in the same way
|
|
16
|
+
* `.approval/payloads/` is. It holds a JSON map from credential NAME to
|
|
17
|
+
* credential string, encrypted with AES-256-GCM under a key derived by scrypt
|
|
18
|
+
* from an operator passphrase. The passphrase is read from an environment
|
|
19
|
+
* variable whose NAME the policy declares (`vault.passphrase_env`, default
|
|
20
|
+
* {@link DEFAULT_PASSPHRASE_ENV}), which is the convention SPEC.md §5.1 already
|
|
21
|
+
* uses for `channels.telegram.token_env` and §5.2 for
|
|
22
|
+
* `audit.sampling_secret_env`: the policy file an agent may read carries a
|
|
23
|
+
* variable name, never a value.
|
|
24
|
+
*
|
|
25
|
+
* ## Threat model, stated plainly (SPEC.md §11)
|
|
26
|
+
*
|
|
27
|
+
* **What the vault defends.** Credentials at rest: a repository, a backup, or a
|
|
28
|
+
* synced folder that ends up somewhere it should not be carries ciphertext and
|
|
29
|
+
* a KDF header, not an SMTP password. And casual reads by an agent with file
|
|
30
|
+
* access: an agent that can `cat` every file in the working tree learns the
|
|
31
|
+
* NAMES of nothing and the values of nothing, because the names live inside the
|
|
32
|
+
* ciphertext too.
|
|
33
|
+
*
|
|
34
|
+
* **What it does not defend.** A compromised host. An agent that can read the
|
|
35
|
+
* passphrase environment variable — such an agent can decrypt the file at
|
|
36
|
+
* leisure, and no arrangement of this module changes that, which is why the
|
|
37
|
+
* passphrase belongs in an operator-held environment (a keychain-populated
|
|
38
|
+
* shell, a systemd credential) and outside every agent-readable path. Nor does
|
|
39
|
+
* it defend against an operator who exports the passphrase into the same
|
|
40
|
+
* process an agent drives. This is the same boundary SPEC.md §11 already draws
|
|
41
|
+
* for the sampling secret and for human identity: the trust boundary is the
|
|
42
|
+
* local machine, and anyone who can set that configuration is inside it. The
|
|
43
|
+
* vault raises the cost of a credential leak from "read a file" to "own the
|
|
44
|
+
* session"; it is not a claim of secrecy against the session's owner.
|
|
45
|
+
*
|
|
46
|
+
* ## Invariant 3 is the whole module
|
|
47
|
+
*
|
|
48
|
+
* SPEC.md §11.1 invariant 3 — raw secrets never appear in the log — is extended
|
|
49
|
+
* here to every surface this module touches. No credential VALUE appears in a
|
|
50
|
+
* return value except {@link getCredential}'s, in no message, no error, no
|
|
51
|
+
* refusal, and nothing here writes to the log at all. {@link listCredentials}
|
|
52
|
+
* returns names and a count. `set` and `remove` return counts. That asymmetry is
|
|
53
|
+
* deliberate and is pinned by a test: the module has exactly one function that
|
|
54
|
+
* can hand back a credential, and the adapter contract is what decides when it
|
|
55
|
+
* may be called.
|
|
56
|
+
*
|
|
57
|
+
* ## Determinism, and the one place it stops
|
|
58
|
+
*
|
|
59
|
+
* Reads are pure functions of the file bytes and the passphrase. Writes are not:
|
|
60
|
+
* every write draws a fresh 96-bit nonce and (on creation) a fresh 128-bit salt,
|
|
61
|
+
* so two writes of the same map produce different files. That is required, not
|
|
62
|
+
* incidental — GCM is catastrophically broken by nonce reuse under one key, and
|
|
63
|
+
* a deterministic file would also leak "nothing changed" to an observer who only
|
|
64
|
+
* sees the ciphertext.
|
|
65
|
+
*
|
|
66
|
+
* Nothing here throws. Every failure is a `{ ok: false, code, message }` from
|
|
67
|
+
* the frozen union {@link VAULT_REFUSAL_CODES}.
|
|
68
|
+
*/
|
|
69
|
+
import { chmodSync, closeSync, mkdirSync, openSync, readFileSync, renameSync, statSync, unlinkSync, writeSync, } from "node:fs";
|
|
70
|
+
import { createCipheriv, createDecipheriv, randomBytes, scryptSync, timingSafeEqual, } from "node:crypto";
|
|
71
|
+
import { basename, dirname, join } from "node:path";
|
|
72
|
+
import { canonicalize } from "./jcs.js";
|
|
73
|
+
// ---------------------------------------------------------------------------
|
|
74
|
+
// Locations and names
|
|
75
|
+
// ---------------------------------------------------------------------------
|
|
76
|
+
/** The vault's filename, beside the log's home: `.approval/vault.enc`. */
|
|
77
|
+
export const VAULT_FILENAME = "vault.enc";
|
|
78
|
+
/**
|
|
79
|
+
* The environment variable the passphrase is read from when the policy declares
|
|
80
|
+
* no `vault.passphrase_env`.
|
|
81
|
+
*
|
|
82
|
+
* A default rather than a hard requirement, because a runtime with no policy at
|
|
83
|
+
* all (or with an unparseable one) must still be able to open a vault an
|
|
84
|
+
* operator created: the variable name is not a permission, and treating it as
|
|
85
|
+
* one would mean an unrelated policy typo locked the credentials.
|
|
86
|
+
*/
|
|
87
|
+
export const DEFAULT_PASSPHRASE_ENV = "APPROVAL_VAULT_PASSPHRASE";
|
|
88
|
+
/**
|
|
89
|
+
* The vault file for a given log path — the convention every caller uses.
|
|
90
|
+
*
|
|
91
|
+
* Derived exactly as `payloadStoreDirFor` derives the payload store, so the
|
|
92
|
+
* vault, the store, and the log stay together under one home: SPEC.md §9 fixes
|
|
93
|
+
* the log at `<home>/log/events.jsonl`, so the vault is `<home>/vault.enc`, a
|
|
94
|
+
* sibling of the log DIRECTORY and never inside it. Pointing `--log` at some
|
|
95
|
+
* other layout puts the vault beside that file instead.
|
|
96
|
+
*/
|
|
97
|
+
export function vaultPathFor(logPath) {
|
|
98
|
+
const logDir = dirname(logPath);
|
|
99
|
+
const home = basename(logDir) === "log" ? dirname(logDir) : logDir;
|
|
100
|
+
return join(home, VAULT_FILENAME);
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* The NAME of the environment variable this policy says the passphrase lives in.
|
|
104
|
+
*
|
|
105
|
+
* The name only, in both directions: a policy that carried a passphrase would be
|
|
106
|
+
* a passphrase in a file agents may read, which is the thing the vault exists to
|
|
107
|
+
* avoid. A policy that failed to load names nothing, so the default applies.
|
|
108
|
+
*/
|
|
109
|
+
export function passphraseEnvFor(load) {
|
|
110
|
+
if (!load.ok)
|
|
111
|
+
return DEFAULT_PASSPHRASE_ENV;
|
|
112
|
+
const declared = load.policy.vault?.passphrase_env;
|
|
113
|
+
return typeof declared === "string" && declared.length > 0
|
|
114
|
+
? declared
|
|
115
|
+
: DEFAULT_PASSPHRASE_ENV;
|
|
116
|
+
}
|
|
117
|
+
/** Is there a vault file at this path? Says nothing about whether it opens. */
|
|
118
|
+
export function vaultExists(vaultPath) {
|
|
119
|
+
try {
|
|
120
|
+
return statSync(vaultPath).isFile();
|
|
121
|
+
}
|
|
122
|
+
catch {
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
// ---------------------------------------------------------------------------
|
|
127
|
+
// Refusals
|
|
128
|
+
// ---------------------------------------------------------------------------
|
|
129
|
+
/**
|
|
130
|
+
* Everything this module can refuse. Frozen public API, per SPEC.md §11.1(6).
|
|
131
|
+
*
|
|
132
|
+
* Each code names a different repair, which is the test of whether a code earns
|
|
133
|
+
* its place. Note the one deliberate *conflation*: {@link "vault-unreadable"}
|
|
134
|
+
* covers both a wrong passphrase and an altered file, and the message says so
|
|
135
|
+
* rather than choosing. Distinguishing them would publish an oracle — a caller
|
|
136
|
+
* who could tell "your passphrase is wrong" from "these bytes were tampered
|
|
137
|
+
* with" could confirm a guessed passphrase against a file they had modified, and
|
|
138
|
+
* GCM's authentication tag cannot tell the two apart anyway without first
|
|
139
|
+
* trusting one of them.
|
|
140
|
+
*/
|
|
141
|
+
export const VAULT_REFUSAL_CODES = [
|
|
142
|
+
/** No vault file exists. The repair is `approval vault set <name>`. */
|
|
143
|
+
"vault-absent",
|
|
144
|
+
/** The named environment variable is unset or empty in this process. */
|
|
145
|
+
"passphrase-unset",
|
|
146
|
+
/** The file could not be read or written. A filesystem fact, not a secret. */
|
|
147
|
+
"vault-io",
|
|
148
|
+
/** The file is not the JSON envelope this module writes, or its header lies. */
|
|
149
|
+
"vault-malformed",
|
|
150
|
+
/** The file declares a format version this build does not implement. */
|
|
151
|
+
"vault-version-unsupported",
|
|
152
|
+
/**
|
|
153
|
+
* The ciphertext did not authenticate: the passphrase is wrong OR the file
|
|
154
|
+
* was altered. Deliberately not distinguished — see the union's own doc.
|
|
155
|
+
*/
|
|
156
|
+
"vault-unreadable",
|
|
157
|
+
/** The vault opened and holds no credential under that name. */
|
|
158
|
+
"credential-absent",
|
|
159
|
+
/** The credential name is empty or not a usable name. */
|
|
160
|
+
"invalid-name",
|
|
161
|
+
/** The credential value is empty. An empty secret is a configuration error. */
|
|
162
|
+
"empty-value",
|
|
163
|
+
/** The re-encrypted file could not be put in place. Nothing was changed. */
|
|
164
|
+
"vault-write-failed",
|
|
165
|
+
];
|
|
166
|
+
function refuse(code, path, message) {
|
|
167
|
+
return { ok: false, code, message, path };
|
|
168
|
+
}
|
|
169
|
+
function detail(cause) {
|
|
170
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
171
|
+
}
|
|
172
|
+
// ---------------------------------------------------------------------------
|
|
173
|
+
// The file format
|
|
174
|
+
// ---------------------------------------------------------------------------
|
|
175
|
+
/**
|
|
176
|
+
* The only format version this build writes or reads.
|
|
177
|
+
*
|
|
178
|
+
* Versioned from the first byte so that a future scheme (a different AEAD, an
|
|
179
|
+
* Argon2 KDF, a hardware-backed key) is a migration with two readers rather than
|
|
180
|
+
* a silent reinterpretation of old bytes. A file declaring anything else is
|
|
181
|
+
* refused {@link "vault-version-unsupported"} and left untouched: guessing at an
|
|
182
|
+
* unknown layout is how a decryption bug becomes a corrupted vault.
|
|
183
|
+
*/
|
|
184
|
+
export const VAULT_FORMAT_VERSION = 1;
|
|
185
|
+
/**
|
|
186
|
+
* scrypt cost parameters, written into every file and read back from it.
|
|
187
|
+
*
|
|
188
|
+
* `N = 16384, r = 8, p = 1` is the classic interactive tuning: about 16 MiB of
|
|
189
|
+
* memory (128·N·r) and something on the order of 100 ms on a laptop, which is a
|
|
190
|
+
* meaningful brute-force cost against a human-typed passphrase while staying
|
|
191
|
+
* fast enough for a CLI verb a human runs interactively. `keylen` is 32 bytes,
|
|
192
|
+
* because AES-256-GCM takes a 256-bit key.
|
|
193
|
+
*
|
|
194
|
+
* The parameters live in the FILE rather than only in this constant so that a
|
|
195
|
+
* vault written under one tuning still opens after the tuning changes. They are
|
|
196
|
+
* bounded on read ({@link readKdf}) rather than trusted: a header claiming
|
|
197
|
+
* `N = 2^40` would otherwise be a denial-of-service delivered as a config file.
|
|
198
|
+
*/
|
|
199
|
+
export const SCRYPT_PARAMS = { N: 16_384, r: 8, p: 1, keylen: 32 };
|
|
200
|
+
/** Bounds on the KDF parameters this build will honour from a file's header. */
|
|
201
|
+
const KDF_LIMITS = { minN: 1 << 12, maxN: 1 << 20, maxR: 32, maxP: 16 };
|
|
202
|
+
/** 96 bits: the nonce size GCM is specified and optimised for. */
|
|
203
|
+
const NONCE_BYTES = 12;
|
|
204
|
+
/** 128 bits of salt. Per-vault, so two vaults never share a derived key. */
|
|
205
|
+
const SALT_BYTES = 16;
|
|
206
|
+
/** The full GCM tag. Truncating it would weaken the only integrity check here. */
|
|
207
|
+
const TAG_BYTES = 16;
|
|
208
|
+
/**
|
|
209
|
+
* The additional authenticated data for the AEAD: the header, canonically
|
|
210
|
+
* serialized.
|
|
211
|
+
*
|
|
212
|
+
* Binding the header to the ciphertext is what stops a header-only edit. Without
|
|
213
|
+
* it an attacker could swap the salt or drop `N` to 4096 and hand the file back;
|
|
214
|
+
* the decryption would simply fail, but it would fail *after* the runtime had
|
|
215
|
+
* spent the attacker's chosen work factor, and a future format that recovered
|
|
216
|
+
* partial state would fail worse. RFC 8785 canonicalization is used so the AAD
|
|
217
|
+
* bytes are a function of the header's VALUES and not of how a writer happened
|
|
218
|
+
* to order or space them.
|
|
219
|
+
*/
|
|
220
|
+
function headerAad(version, kdf, nonceB64) {
|
|
221
|
+
return Buffer.from(canonicalize({ version, kdf, nonce_b64: nonceB64 }), "utf8");
|
|
222
|
+
}
|
|
223
|
+
function deriveKey(passphrase, salt, kdf) {
|
|
224
|
+
// maxmem is set from the file's own parameters (with headroom) rather than
|
|
225
|
+
// left at Node's 32 MiB default, so a legitimately expensive vault opens
|
|
226
|
+
// instead of throwing an opaque "memory limit exceeded".
|
|
227
|
+
const maxmem = 256 * kdf.N * kdf.r + 1024 * 1024;
|
|
228
|
+
return scryptSync(passphrase, salt, SCRYPT_PARAMS.keylen, {
|
|
229
|
+
N: kdf.N,
|
|
230
|
+
r: kdf.r,
|
|
231
|
+
p: kdf.p,
|
|
232
|
+
maxmem,
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
/** Base64 that round-trips to exactly `bytes` bytes, or `null`. */
|
|
236
|
+
function decodeExact(text, bytes) {
|
|
237
|
+
if (typeof text !== "string")
|
|
238
|
+
return null;
|
|
239
|
+
let buffer;
|
|
240
|
+
try {
|
|
241
|
+
buffer = Buffer.from(text, "base64");
|
|
242
|
+
}
|
|
243
|
+
catch {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
return buffer.length === bytes ? buffer : null;
|
|
247
|
+
}
|
|
248
|
+
function readKdf(value) {
|
|
249
|
+
if (typeof value !== "object" || value === null)
|
|
250
|
+
return null;
|
|
251
|
+
const raw = value;
|
|
252
|
+
if (raw["alg"] !== "scrypt")
|
|
253
|
+
return null;
|
|
254
|
+
const N = raw["N"];
|
|
255
|
+
const r = raw["r"];
|
|
256
|
+
const p = raw["p"];
|
|
257
|
+
const salt = raw["salt_b64"];
|
|
258
|
+
if (typeof N !== "number" || !Number.isInteger(N) || N < KDF_LIMITS.minN || N > KDF_LIMITS.maxN) {
|
|
259
|
+
return null;
|
|
260
|
+
}
|
|
261
|
+
// scrypt requires N to be a power of two; an N that is not one would throw
|
|
262
|
+
// out of `scryptSync`, and this module does not throw.
|
|
263
|
+
if ((N & (N - 1)) !== 0)
|
|
264
|
+
return null;
|
|
265
|
+
if (typeof r !== "number" || !Number.isInteger(r) || r < 1 || r > KDF_LIMITS.maxR)
|
|
266
|
+
return null;
|
|
267
|
+
if (typeof p !== "number" || !Number.isInteger(p) || p < 1 || p > KDF_LIMITS.maxP)
|
|
268
|
+
return null;
|
|
269
|
+
if (typeof salt !== "string" || decodeExact(salt, SALT_BYTES) === null)
|
|
270
|
+
return null;
|
|
271
|
+
return { alg: "scrypt", N, r, p, salt_b64: salt };
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Decrypt the vault at `vaultPath`.
|
|
275
|
+
*
|
|
276
|
+
* **Not exported.** The plaintext map is the one thing this module must not hand
|
|
277
|
+
* out wholesale: an exported `openVault` would be a single call that returns
|
|
278
|
+
* every credential, and a caller who could make it would have no reason to go
|
|
279
|
+
* through the adapter contract's token window. Everything public here is built
|
|
280
|
+
* on top of this and returns names, counts, or exactly one requested value.
|
|
281
|
+
*/
|
|
282
|
+
function open(vaultPath, passphrase) {
|
|
283
|
+
let raw;
|
|
284
|
+
try {
|
|
285
|
+
raw = readFileSync(vaultPath, "utf8");
|
|
286
|
+
}
|
|
287
|
+
catch (cause) {
|
|
288
|
+
if (cause.code === "ENOENT") {
|
|
289
|
+
return refuse("vault-absent", vaultPath, `no vault at ${vaultPath}; credentials are stored there by \`approval vault set <name>\` and nothing else creates it`);
|
|
290
|
+
}
|
|
291
|
+
return refuse("vault-io", vaultPath, `vault ${vaultPath} could not be read: ${detail(cause)}`);
|
|
292
|
+
}
|
|
293
|
+
let parsed;
|
|
294
|
+
try {
|
|
295
|
+
parsed = JSON.parse(raw);
|
|
296
|
+
}
|
|
297
|
+
catch (cause) {
|
|
298
|
+
return refuse("vault-malformed", vaultPath, `vault ${vaultPath} is not the JSON envelope this runtime writes: ${detail(cause)}`);
|
|
299
|
+
}
|
|
300
|
+
if (typeof parsed !== "object" || parsed === null || Array.isArray(parsed)) {
|
|
301
|
+
return refuse("vault-malformed", vaultPath, `vault ${vaultPath} is not a JSON object`);
|
|
302
|
+
}
|
|
303
|
+
const file = parsed;
|
|
304
|
+
if (file.version !== VAULT_FORMAT_VERSION) {
|
|
305
|
+
return refuse("vault-version-unsupported", vaultPath, `vault ${vaultPath} declares format version ${JSON.stringify(file.version)}; this build reads version ${String(VAULT_FORMAT_VERSION)} only, and guessing at an unknown layout is how a vault gets destroyed rather than opened`);
|
|
306
|
+
}
|
|
307
|
+
const kdf = readKdf(file.kdf);
|
|
308
|
+
const nonce = decodeExact(file.nonce_b64, NONCE_BYTES);
|
|
309
|
+
const tag = decodeExact(file.tag_b64, TAG_BYTES);
|
|
310
|
+
if (kdf === null || nonce === null || tag === null) {
|
|
311
|
+
return refuse("vault-malformed", vaultPath, `vault ${vaultPath} has a header this runtime will not act on (expected kdf {alg:"scrypt", N (a power of two in [${String(KDF_LIMITS.minN)}, ${String(KDF_LIMITS.maxN)}]), r, p, salt_b64}, a ${String(NONCE_BYTES)}-byte nonce_b64 and a ${String(TAG_BYTES)}-byte tag_b64)`);
|
|
312
|
+
}
|
|
313
|
+
if (typeof file.ciphertext_b64 !== "string") {
|
|
314
|
+
return refuse("vault-malformed", vaultPath, `vault ${vaultPath} carries no ciphertext_b64`);
|
|
315
|
+
}
|
|
316
|
+
const salt = decodeExact(kdf.salt_b64, SALT_BYTES);
|
|
317
|
+
if (salt === null) {
|
|
318
|
+
return refuse("vault-malformed", vaultPath, `vault ${vaultPath} has an unusable kdf.salt_b64`);
|
|
319
|
+
}
|
|
320
|
+
let plaintext;
|
|
321
|
+
try {
|
|
322
|
+
const key = deriveKey(passphrase, salt, kdf);
|
|
323
|
+
const decipher = createDecipheriv("aes-256-gcm", key, nonce, { authTagLength: TAG_BYTES });
|
|
324
|
+
decipher.setAAD(headerAad(VAULT_FORMAT_VERSION, kdf, file.nonce_b64));
|
|
325
|
+
decipher.setAuthTag(tag);
|
|
326
|
+
plaintext = Buffer.concat([
|
|
327
|
+
decipher.update(Buffer.from(file.ciphertext_b64, "base64")),
|
|
328
|
+
decipher.final(),
|
|
329
|
+
]);
|
|
330
|
+
}
|
|
331
|
+
catch {
|
|
332
|
+
// The cause is deliberately dropped rather than reported. Node's message
|
|
333
|
+
// here is always the same string, but a future one that distinguished the
|
|
334
|
+
// failure modes would turn this refusal into the oracle the union's doc
|
|
335
|
+
// explains we will not publish.
|
|
336
|
+
return refuse("vault-unreadable", vaultPath, `passphrase wrong or file altered (${vaultPath}). These two are not distinguished on purpose: a runtime that told you which would let someone confirm a guessed passphrase against a file they had modified. Check the passphrase first, then the file's provenance.`);
|
|
337
|
+
}
|
|
338
|
+
let entries;
|
|
339
|
+
try {
|
|
340
|
+
entries = JSON.parse(plaintext.toString("utf8"));
|
|
341
|
+
}
|
|
342
|
+
catch (cause) {
|
|
343
|
+
return refuse("vault-malformed", vaultPath, `vault ${vaultPath} decrypted to something that is not JSON: ${detail(cause)}`);
|
|
344
|
+
}
|
|
345
|
+
if (typeof entries !== "object" || entries === null || Array.isArray(entries)) {
|
|
346
|
+
return refuse("vault-malformed", vaultPath, `vault ${vaultPath} decrypted to a ${Array.isArray(entries) ? "list" : typeof entries}, not the name -> credential map this runtime stores`);
|
|
347
|
+
}
|
|
348
|
+
const map = {};
|
|
349
|
+
for (const [name, value] of Object.entries(entries)) {
|
|
350
|
+
// A non-string member is dropped rather than reported with its value: the
|
|
351
|
+
// report would be the leak. The count tells the operator something is off.
|
|
352
|
+
if (typeof value === "string")
|
|
353
|
+
map[name] = value;
|
|
354
|
+
}
|
|
355
|
+
return { ok: true, entries: map, kdf };
|
|
356
|
+
}
|
|
357
|
+
// ---------------------------------------------------------------------------
|
|
358
|
+
// Writing
|
|
359
|
+
// ---------------------------------------------------------------------------
|
|
360
|
+
/** Distinguishes concurrent writers' temp files within one process. */
|
|
361
|
+
let tempCounter = 0;
|
|
362
|
+
/**
|
|
363
|
+
* Encrypt `entries` under a fresh nonce and put the file in place atomically.
|
|
364
|
+
*
|
|
365
|
+
* Fresh nonce on EVERY write, without exception: GCM under a repeated (key,
|
|
366
|
+
* nonce) pair leaks the XOR of the plaintexts and, worse, the authentication
|
|
367
|
+
* subkey, which turns an encrypted vault into a forgeable one. The salt is
|
|
368
|
+
* reused when a vault is being rewritten (so an unchanged passphrase still
|
|
369
|
+
* opens it) and drawn fresh when one is being created.
|
|
370
|
+
*
|
|
371
|
+
* temp + rename in the destination directory, and mode 0600 on the temp file
|
|
372
|
+
* before any bytes are written, so the ciphertext is never briefly world
|
|
373
|
+
* readable and an interrupted write leaves the previous vault intact.
|
|
374
|
+
*/
|
|
375
|
+
function writeVault(vaultPath, passphrase, entries, existingKdf) {
|
|
376
|
+
const kdf = existingKdf ?? {
|
|
377
|
+
alg: "scrypt",
|
|
378
|
+
N: SCRYPT_PARAMS.N,
|
|
379
|
+
r: SCRYPT_PARAMS.r,
|
|
380
|
+
p: SCRYPT_PARAMS.p,
|
|
381
|
+
salt_b64: randomBytes(SALT_BYTES).toString("base64"),
|
|
382
|
+
};
|
|
383
|
+
const salt = decodeExact(kdf.salt_b64, SALT_BYTES);
|
|
384
|
+
if (salt === null) {
|
|
385
|
+
return refuse("vault-write-failed", vaultPath, `the vault's salt is unusable; nothing was written`);
|
|
386
|
+
}
|
|
387
|
+
let file;
|
|
388
|
+
try {
|
|
389
|
+
const nonce = randomBytes(NONCE_BYTES);
|
|
390
|
+
const nonceB64 = nonce.toString("base64");
|
|
391
|
+
const key = deriveKey(passphrase, salt, kdf);
|
|
392
|
+
const cipher = createCipheriv("aes-256-gcm", key, nonce, { authTagLength: TAG_BYTES });
|
|
393
|
+
cipher.setAAD(headerAad(VAULT_FORMAT_VERSION, kdf, nonceB64));
|
|
394
|
+
const ciphertext = Buffer.concat([
|
|
395
|
+
cipher.update(Buffer.from(JSON.stringify(entries), "utf8")),
|
|
396
|
+
cipher.final(),
|
|
397
|
+
]);
|
|
398
|
+
file = {
|
|
399
|
+
version: VAULT_FORMAT_VERSION,
|
|
400
|
+
kdf,
|
|
401
|
+
nonce_b64: nonceB64,
|
|
402
|
+
tag_b64: cipher.getAuthTag().toString("base64"),
|
|
403
|
+
ciphertext_b64: ciphertext.toString("base64"),
|
|
404
|
+
};
|
|
405
|
+
}
|
|
406
|
+
catch (cause) {
|
|
407
|
+
return refuse("vault-write-failed", vaultPath, `the vault could not be encrypted: ${detail(cause)}. Nothing was written.`);
|
|
408
|
+
}
|
|
409
|
+
const directory = dirname(vaultPath);
|
|
410
|
+
tempCounter += 1;
|
|
411
|
+
const temp = join(directory, `.${basename(vaultPath)}.tmp-${String(process.pid)}-${String(tempCounter)}`);
|
|
412
|
+
try {
|
|
413
|
+
mkdirSync(directory, { recursive: true });
|
|
414
|
+
const handle = openSync(temp, "wx", 0o600);
|
|
415
|
+
try {
|
|
416
|
+
writeSync(handle, `${JSON.stringify(file, null, 2)}\n`, 0, "utf8");
|
|
417
|
+
}
|
|
418
|
+
finally {
|
|
419
|
+
closeSync(handle);
|
|
420
|
+
}
|
|
421
|
+
// Explicit chmod as well as the open mode: a permissive umask does not
|
|
422
|
+
// affect `openSync`'s mode argument, but a pre-existing file replaced by
|
|
423
|
+
// rename should not inherit anything looser either.
|
|
424
|
+
chmodSync(temp, 0o600);
|
|
425
|
+
renameSync(temp, vaultPath);
|
|
426
|
+
}
|
|
427
|
+
catch (cause) {
|
|
428
|
+
try {
|
|
429
|
+
unlinkSync(temp);
|
|
430
|
+
}
|
|
431
|
+
catch {
|
|
432
|
+
// The temp file may never have been created; nothing to clean up.
|
|
433
|
+
}
|
|
434
|
+
return refuse("vault-write-failed", vaultPath, `vault ${vaultPath} could not be written: ${detail(cause)}. The previous vault, if any, is unchanged.`);
|
|
435
|
+
}
|
|
436
|
+
return { ok: true };
|
|
437
|
+
}
|
|
438
|
+
// ---------------------------------------------------------------------------
|
|
439
|
+
// The public operations
|
|
440
|
+
// ---------------------------------------------------------------------------
|
|
441
|
+
/** A credential name: non-empty, no whitespace, no control characters. */
|
|
442
|
+
const NAME_PATTERN = /^[\x21-\x7e]+$/u;
|
|
443
|
+
function checkName(name, vaultPath) {
|
|
444
|
+
if (typeof name !== "string" || name.length === 0 || !NAME_PATTERN.test(name)) {
|
|
445
|
+
return refuse("invalid-name", vaultPath, `${JSON.stringify(name)} is not a usable credential name: names are non-empty printable ASCII without spaces, so that an adapter can ask for one by name from a configuration file`);
|
|
446
|
+
}
|
|
447
|
+
return null;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Store `value` under `name`, creating the vault when it does not exist.
|
|
451
|
+
*
|
|
452
|
+
* The whole map is decrypted, amended, and re-encrypted under a fresh nonce:
|
|
453
|
+
* there is no partial update, because an AEAD over the whole document is what
|
|
454
|
+
* makes a partial edit detectable in the first place.
|
|
455
|
+
*
|
|
456
|
+
* `value` is a parameter and nothing else — never logged, never echoed, never
|
|
457
|
+
* placed in a message, including in the refusals this can return.
|
|
458
|
+
*/
|
|
459
|
+
export function setCredential(vaultPath, passphrase, name, value) {
|
|
460
|
+
const badName = checkName(name, vaultPath);
|
|
461
|
+
if (badName !== null)
|
|
462
|
+
return badName;
|
|
463
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
464
|
+
return refuse("empty-value", vaultPath, `the value for ${JSON.stringify(name)} is empty; an empty credential is a configuration mistake that would surface as an authentication failure at the far end, so it is refused here instead`);
|
|
465
|
+
}
|
|
466
|
+
if (passphrase.length === 0) {
|
|
467
|
+
return refuse("passphrase-unset", vaultPath, `the vault passphrase is empty; nothing was written`);
|
|
468
|
+
}
|
|
469
|
+
let entries = {};
|
|
470
|
+
let kdf = null;
|
|
471
|
+
if (vaultExists(vaultPath)) {
|
|
472
|
+
const opened = open(vaultPath, passphrase);
|
|
473
|
+
if (!opened.ok)
|
|
474
|
+
return opened;
|
|
475
|
+
entries = opened.entries;
|
|
476
|
+
kdf = opened.kdf;
|
|
477
|
+
}
|
|
478
|
+
const created = !Object.prototype.hasOwnProperty.call(entries, name);
|
|
479
|
+
entries[name] = value;
|
|
480
|
+
const written = writeVault(vaultPath, passphrase, entries, kdf);
|
|
481
|
+
if (!written.ok)
|
|
482
|
+
return written;
|
|
483
|
+
return { ok: true, path: vaultPath, name, count: Object.keys(entries).length, created };
|
|
484
|
+
}
|
|
485
|
+
/**
|
|
486
|
+
* Delete `name`. A name the vault does not hold refuses `credential-absent`
|
|
487
|
+
* rather than reporting success: an operator removing a credential wants to know
|
|
488
|
+
* whether they removed the one they meant.
|
|
489
|
+
*/
|
|
490
|
+
export function removeCredential(vaultPath, passphrase, name) {
|
|
491
|
+
const badName = checkName(name, vaultPath);
|
|
492
|
+
if (badName !== null)
|
|
493
|
+
return badName;
|
|
494
|
+
const opened = open(vaultPath, passphrase);
|
|
495
|
+
if (!opened.ok)
|
|
496
|
+
return opened;
|
|
497
|
+
if (!Object.prototype.hasOwnProperty.call(opened.entries, name)) {
|
|
498
|
+
return refuse("credential-absent", vaultPath, `the vault holds no credential named ${JSON.stringify(name)}; nothing was removed and the file is unchanged`);
|
|
499
|
+
}
|
|
500
|
+
const entries = opened.entries;
|
|
501
|
+
// Overwrite before deleting: the string itself is immutable and this does not
|
|
502
|
+
// scrub the heap, but it does keep the doomed value out of the map that is
|
|
503
|
+
// about to be re-serialized even if a later edit here reordered the two steps.
|
|
504
|
+
entries[name] = "";
|
|
505
|
+
delete entries[name];
|
|
506
|
+
const written = writeVault(vaultPath, passphrase, entries, opened.kdf);
|
|
507
|
+
if (!written.ok)
|
|
508
|
+
return written;
|
|
509
|
+
return { ok: true, path: vaultPath, name, count: Object.keys(entries).length, created: false };
|
|
510
|
+
}
|
|
511
|
+
/**
|
|
512
|
+
* The names in the vault, sorted, and how many there are.
|
|
513
|
+
*
|
|
514
|
+
* Names and nothing else, on every path including the error ones. Sorted so two
|
|
515
|
+
* listings of the same vault are byte-identical, which is what lets a test and
|
|
516
|
+
* an operator compare them.
|
|
517
|
+
*/
|
|
518
|
+
export function listCredentials(vaultPath, passphrase) {
|
|
519
|
+
const opened = open(vaultPath, passphrase);
|
|
520
|
+
if (!opened.ok)
|
|
521
|
+
return opened;
|
|
522
|
+
const names = Object.keys(opened.entries).sort();
|
|
523
|
+
return { ok: true, path: vaultPath, names, count: names.length };
|
|
524
|
+
}
|
|
525
|
+
/**
|
|
526
|
+
* The value stored under `name`.
|
|
527
|
+
*
|
|
528
|
+
* **The only function here that returns a credential**, which is the module's
|
|
529
|
+
* structural rule and is pinned by `tests/vault.test.ts`. There is no
|
|
530
|
+
* `approval vault get`, because a verb that printed a credential would put it
|
|
531
|
+
* in a terminal, a scrollback buffer, a CI log, and a shell history, and would
|
|
532
|
+
* do so on a machine where the whole point is that the value only ever travels
|
|
533
|
+
* from this file into the use it was stored for.
|
|
534
|
+
*
|
|
535
|
+
* **Two sanctioned callers** (flagged by APRV-220, decided by APRV-257):
|
|
536
|
+
*
|
|
537
|
+
* 1. `adapters/vault-provider.ts`, whose provider `executeThroughAdapter`
|
|
538
|
+
* scopes to the verified-token window.
|
|
539
|
+
* 2. `cli/checkpoint-tap.ts`, which reads `approval.checkpoint.key` and hands
|
|
540
|
+
* it to `core/checkpoint.ts`'s signer — the one custody decision for every
|
|
541
|
+
* surface that can take a checkpoint.
|
|
542
|
+
*
|
|
543
|
+
* The rule this list keeps is not "one caller". It is that a credential's value
|
|
544
|
+
* goes from this file into a USE and never onto a SURFACE, and both callers
|
|
545
|
+
* obey it: the second takes a private key into an Ed25519 signature and hands
|
|
546
|
+
* back a signature and a fingerprint of the PUBLIC half.
|
|
547
|
+
*
|
|
548
|
+
* The alternative — move the checkpoint key somewhere else and keep this list
|
|
549
|
+
* at one name — was considered and rejected, because it would have made the key
|
|
550
|
+
* weaker rather than the module cleaner. The OS keystore has no equivalent of
|
|
551
|
+
* the passphrase variable `core/child-env.ts` strips from every child
|
|
552
|
+
* (APRV-205), and a file beside the log has no encryption at all. A checkpoint
|
|
553
|
+
* key is the one secret whose entire value is that a process an agent launched
|
|
554
|
+
* cannot reach it, so it belongs in the strictest store this runtime has. What
|
|
555
|
+
* that costs is a second name in this comment.
|
|
556
|
+
*/
|
|
557
|
+
export function getCredential(vaultPath, passphrase, name) {
|
|
558
|
+
const badName = checkName(name, vaultPath);
|
|
559
|
+
if (badName !== null)
|
|
560
|
+
return badName;
|
|
561
|
+
const opened = open(vaultPath, passphrase);
|
|
562
|
+
if (!opened.ok)
|
|
563
|
+
return opened;
|
|
564
|
+
const value = opened.entries[name];
|
|
565
|
+
if (typeof value !== "string") {
|
|
566
|
+
return refuse("credential-absent", vaultPath, `the vault holds no credential named ${JSON.stringify(name)}; store one with \`approval vault set ${name}\``);
|
|
567
|
+
}
|
|
568
|
+
return { ok: true, path: vaultPath, name, value };
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* Does this passphrase open the vault, and how many credentials does it hold?
|
|
572
|
+
*
|
|
573
|
+
* The diagnostic form, for `approval doctor`: a yes/no plus a count, with no
|
|
574
|
+
* name and no value in either the success or the failure. Distinct from
|
|
575
|
+
* {@link listCredentials} because a health check has no business learning which
|
|
576
|
+
* credentials an operator keeps.
|
|
577
|
+
*/
|
|
578
|
+
export function checkVault(vaultPath, passphrase) {
|
|
579
|
+
const opened = open(vaultPath, passphrase);
|
|
580
|
+
if (!opened.ok)
|
|
581
|
+
return opened;
|
|
582
|
+
return { ok: true, path: vaultPath, count: Object.keys(opened.entries).length };
|
|
583
|
+
}
|
|
584
|
+
/**
|
|
585
|
+
* Read the passphrase from the environment variable named by `envName`.
|
|
586
|
+
*
|
|
587
|
+
* Returns the value, or `null` when it is unset or empty. A separate function
|
|
588
|
+
* so that every caller reads the passphrase the same way and so that no caller
|
|
589
|
+
* is tempted to accept one as a flag: a passphrase on a command line is a
|
|
590
|
+
* passphrase in the shell history, in `ps`, and in the parent process's
|
|
591
|
+
* environment.
|
|
592
|
+
*/
|
|
593
|
+
export function passphraseFrom(envName, env = process.env) {
|
|
594
|
+
const value = env[envName];
|
|
595
|
+
return typeof value === "string" && value.length > 0 ? value : null;
|
|
596
|
+
}
|
|
597
|
+
/**
|
|
598
|
+
* Constant-time equality for two secrets, exported for callers that must
|
|
599
|
+
* compare one without leaking its length-prefix through timing.
|
|
600
|
+
*
|
|
601
|
+
* Not used by the vault's own paths (nothing here compares credentials), but the
|
|
602
|
+
* alternative — a caller writing `a === b` over a secret — is the kind of thing
|
|
603
|
+
* that gets written once and copied five times.
|
|
604
|
+
*/
|
|
605
|
+
export function secretsEqual(left, right) {
|
|
606
|
+
const a = Buffer.from(left, "utf8");
|
|
607
|
+
const b = Buffer.from(right, "utf8");
|
|
608
|
+
if (a.length !== b.length)
|
|
609
|
+
return false;
|
|
610
|
+
return timingSafeEqual(a, b);
|
|
611
|
+
}
|
|
612
|
+
//# sourceMappingURL=vault.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"vault.js","sourceRoot":"","sources":["../../../src/core/vault.ts"],"names":[],"mappings":"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"}
|