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,589 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Policy attestation (SPEC.md §5.2, §11) — the mechanical form of "agents MUST
|
|
3
|
+
* NOT be able to modify `APPROVAL.md`".
|
|
4
|
+
*
|
|
5
|
+
* The problem this solves is not that an agent *can* edit the policy file — on
|
|
6
|
+
* a single machine nothing stops it — but that an edited policy would otherwise
|
|
7
|
+
* take effect silently. Attestation closes that: a human runs
|
|
8
|
+
* `approval policy attest`, which appends a `policy.updated` event carrying the
|
|
9
|
+
* SHA-256 of the policy file's exact bytes. From then on the live file either
|
|
10
|
+
* hashes to the latest attestation or it does not, and {@link checkAttestation}
|
|
11
|
+
* says which. Gate operations (request intake, grant recording, token minting —
|
|
12
|
+
* APRV-16) refuse on anything but a match. An edited policy is inoperative
|
|
13
|
+
* until a human re-attests it.
|
|
14
|
+
*
|
|
15
|
+
* ## What this proves, and what it does not
|
|
16
|
+
*
|
|
17
|
+
* Human identity at v0.1 is **config-declared**: `--as human:<id>` or the
|
|
18
|
+
* `APPROVAL_HUMAN` environment variable (see {@link resolveHumanActor}). The
|
|
19
|
+
* trust boundary is the local machine. Anyone who can set that environment
|
|
20
|
+
* variable and write to the log is inside the boundary, so an attestation
|
|
21
|
+
* proves that *someone with local control* signed off — not *who*. There is no
|
|
22
|
+
* cryptographic identity here and this module claims none; that is future work,
|
|
23
|
+
* stated plainly rather than dressed up. What attestation buys, even so, is
|
|
24
|
+
* real: a policy edit made by an agent mid-run cannot become operative without
|
|
25
|
+
* a separate, deliberate, logged human act.
|
|
26
|
+
*
|
|
27
|
+
* ## Fail closed, in this order
|
|
28
|
+
*
|
|
29
|
+
* A policy file that cannot be read is `unreadable`, never `attested`. No
|
|
30
|
+
* attestation at all is `not-attested`. Bytes that do not match the latest
|
|
31
|
+
* attestation are `hash-mismatch`. Only an exact match is `attested`.
|
|
32
|
+
*
|
|
33
|
+
* Everything here is read-only except {@link appendAttestation}, which writes
|
|
34
|
+
* through `core/log.ts`'s `appendEvent` — the one sanctioned append path — and
|
|
35
|
+
* therefore inherits its locking, chain stamping, and write-boundary schema
|
|
36
|
+
* validation. Nothing in this file opens the log itself.
|
|
37
|
+
*/
|
|
38
|
+
import { createHash } from "node:crypto";
|
|
39
|
+
import { readFileSync } from "node:fs";
|
|
40
|
+
import { basename, isAbsolute, join } from "node:path";
|
|
41
|
+
import { tick } from "./clock.js";
|
|
42
|
+
import { builtinProtectedPathClass, isGateOrganPath, normalizePathSpelling, } from "./command-class.js";
|
|
43
|
+
import { APPEND_ERROR_CODES, appendEvent, } from "./log.js";
|
|
44
|
+
/**
|
|
45
|
+
* Actors permitted to attest. Deliberately narrower than the event schema's
|
|
46
|
+
* `^(human|agent|system):.+`: attestation is the one verb an agent must not be
|
|
47
|
+
* able to perform, so `agent:` and `system:` are refused here — in code, not
|
|
48
|
+
* only in prose.
|
|
49
|
+
*/
|
|
50
|
+
const HUMAN_ACTOR = /^human:.+/;
|
|
51
|
+
/** Environment variable naming the human on whose behalf the CLI attests. */
|
|
52
|
+
export const HUMAN_ACTOR_ENV = "APPROVAL_HUMAN";
|
|
53
|
+
/**
|
|
54
|
+
* The machine-readable refusal code emitted when policy is not attested.
|
|
55
|
+
*
|
|
56
|
+
* Deliberately distinct from any generic policy-load failure. A caller must be
|
|
57
|
+
* able to tell "the policy says manual" from "the policy is unverified", because
|
|
58
|
+
* the repairs are different: the first is answered by asking a human to approve
|
|
59
|
+
* an action, the second by asking a human to attest a file.
|
|
60
|
+
*/
|
|
61
|
+
export const ATTESTATION_REFUSAL = "policy-not-attested";
|
|
62
|
+
/**
|
|
63
|
+
* The payload field carrying the attested policy hash a gate event was decided
|
|
64
|
+
* under (APRV-118, amended SPEC.md §5.2).
|
|
65
|
+
*
|
|
66
|
+
* Written on `approval.requested` and `approval.granted`, and named here rather
|
|
67
|
+
* than in `core/gate.ts` because the value is this module's: it is the SHA-256
|
|
68
|
+
* the live policy file matched when {@link checkAttestation} said `attested`.
|
|
69
|
+
* Pinning it lets a reader of the log answer a question attestation alone cannot
|
|
70
|
+
* — whether the approver decided under the rules the requester was routed by.
|
|
71
|
+
*/
|
|
72
|
+
export const POLICY_HASH_FIELD = "policy_sha256";
|
|
73
|
+
/** Is `value` a lowercase-hex SHA-256, the shape {@link POLICY_HASH_FIELD} takes? */
|
|
74
|
+
export function isPolicySha256(value) {
|
|
75
|
+
return typeof value === "string" && /^[a-f0-9]{64}$/u.test(value);
|
|
76
|
+
}
|
|
77
|
+
/**
|
|
78
|
+
* Why an attestation append failed: every reason `appendEvent` can give, plus
|
|
79
|
+
* the one rule this module enforces on its own.
|
|
80
|
+
*
|
|
81
|
+
* ### Why `actor-not-human` lives here and not in `core/log.ts`
|
|
82
|
+
*
|
|
83
|
+
* Until APRV-20 pass two the non-human-actor refusal reused `validation`, which
|
|
84
|
+
* conflated two different facts: "the record failed `event.schema.json` at the
|
|
85
|
+
* write boundary" and "the caller is not allowed to perform this verb". A
|
|
86
|
+
* caller branching on `validation` could not tell a malformed event from a
|
|
87
|
+
* forbidden one, and the two call for opposite responses (fix the record;
|
|
88
|
+
* fetch a human).
|
|
89
|
+
*
|
|
90
|
+
* The fix does **not** add the code to `APPEND_ERROR_CODES`. That union is the
|
|
91
|
+
* log writer's vocabulary — the ways a byte can fail to reach the file — and
|
|
92
|
+
* "only humans may attest" is a fact about attestation, not about writing.
|
|
93
|
+
* Widening the writer's union to carry a caller's policy rule would oblige every
|
|
94
|
+
* future append site to consider a code that can only ever come from this one,
|
|
95
|
+
* and would make `core/log.ts` the place people look for permission rules.
|
|
96
|
+
* Instead this module widens the union *for itself*: `AppendResult` remains
|
|
97
|
+
* assignable to {@link AttestationAppendResult}, so nothing downstream is
|
|
98
|
+
* forced to change, and the CLI adds one case.
|
|
99
|
+
*/
|
|
100
|
+
export const ATTEST_ERROR_CODES = [...APPEND_ERROR_CODES, "actor-not-human"];
|
|
101
|
+
function detail(cause) {
|
|
102
|
+
return cause instanceof Error ? cause.message : String(cause);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* SHA-256 (lowercase hex) of a file's **exact bytes**.
|
|
106
|
+
*
|
|
107
|
+
* Bytes, not text: no encoding round-trip, no newline normalization, no parse.
|
|
108
|
+
* A policy file that differs only in trailing whitespace is a different policy
|
|
109
|
+
* file as far as attestation is concerned, which is the conservative reading
|
|
110
|
+
* and the only one that survives an adversary who knows what gets normalized.
|
|
111
|
+
*
|
|
112
|
+
* Throws if the file cannot be read; callers that need a status rather than an
|
|
113
|
+
* exception use {@link checkAttestation}, which converts that into
|
|
114
|
+
* `unreadable`.
|
|
115
|
+
*/
|
|
116
|
+
export function policyFileHash(path) {
|
|
117
|
+
return policyBytesHash(readFileSync(path));
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* SHA-256 (lowercase hex) of policy bytes a caller has already read.
|
|
121
|
+
*
|
|
122
|
+
* The same digest {@link policyFileHash} computes, over bytes rather than a
|
|
123
|
+
* path. It exists so a gate operation can read `APPROVAL.md` once and hash the
|
|
124
|
+
* exact buffer it is also about to parse (APRV-142): hashing by path a second
|
|
125
|
+
* time would reopen the window where the attestation check and the parse can
|
|
126
|
+
* see different bytes.
|
|
127
|
+
*/
|
|
128
|
+
export function policyBytesHash(bytes) {
|
|
129
|
+
return createHash("sha256").update(bytes).digest("hex");
|
|
130
|
+
}
|
|
131
|
+
/**
|
|
132
|
+
* Append a `policy.updated` attestation for `policyPath` to `logPath`.
|
|
133
|
+
*
|
|
134
|
+
* `actor` MUST match `^human:.+`. An `agent:` or `system:` actor is refused
|
|
135
|
+
* before anything is read or written — the refusal is a structured result,
|
|
136
|
+
* never a throw, consistent with the rest of the write path. Its code is
|
|
137
|
+
* `actor-not-human`, this module's own (see {@link ATTEST_ERROR_CODES}): the
|
|
138
|
+
* actor failed the rule *this verb* enforces, which is a different fact from a
|
|
139
|
+
* record failing the event schema, and the two used to share `validation`.
|
|
140
|
+
*
|
|
141
|
+
* The event is deliberately minimal:
|
|
142
|
+
*
|
|
143
|
+
* ```json
|
|
144
|
+
* { "event": "policy.updated", "actor": "human:alice",
|
|
145
|
+
* "payload": { "policy_path": "APPROVAL.md", "sha256": "<64 hex>" } }
|
|
146
|
+
* ```
|
|
147
|
+
*
|
|
148
|
+
* `policy_path` is the **basename**, not the absolute path: the log is meant to
|
|
149
|
+
* be copied, exported, and read on other machines, and an absolute path would
|
|
150
|
+
* leak the writer's home directory into a permanent record while saying nothing
|
|
151
|
+
* a reader can use. `sha256` is the file's byte digest — the field
|
|
152
|
+
* {@link checkAttestation} compares against.
|
|
153
|
+
*
|
|
154
|
+
* `ts` is **not** a parameter. `policy.updated` is one of the gate-typed events
|
|
155
|
+
* of amended SPEC.md §8 (A2), so its timestamp is assigned by the runtime at the
|
|
156
|
+
* write boundary — read once from {@link AttestOptions.clock}, which defaults to
|
|
157
|
+
* the real clock and which tests inject. Attestation is the verb that decides
|
|
158
|
+
* which policy bytes are operative from a moment onward; a caller that could
|
|
159
|
+
* choose that moment could backdate the answer.
|
|
160
|
+
*
|
|
161
|
+
* ## Why this append carries no `expectedHead` (APRV-20 finding B1)
|
|
162
|
+
*
|
|
163
|
+
* Every *other* append site in the codebase reads the log, decides something
|
|
164
|
+
* from what it read, and must therefore prove the log has not moved before it
|
|
165
|
+
* writes. This one does not read the log at all. Its only precondition is the
|
|
166
|
+
* actor check and the policy file's bytes — neither of which the log can
|
|
167
|
+
* invalidate — so there is no check-then-act window to close. A concurrent
|
|
168
|
+
* appender simply means this attestation lands after that record, which is
|
|
169
|
+
* correct: attestation is an unconditional assertion about a file's bytes at a
|
|
170
|
+
* moment, and the *latest* attestation is the one `checkAttestation` honors.
|
|
171
|
+
* Passing a precondition here would only manufacture spurious failures.
|
|
172
|
+
*/
|
|
173
|
+
export function appendAttestation(logPath, policyPath, actor, options = {}) {
|
|
174
|
+
if (!HUMAN_ACTOR.test(actor)) {
|
|
175
|
+
return {
|
|
176
|
+
ok: false,
|
|
177
|
+
error: {
|
|
178
|
+
code: "actor-not-human",
|
|
179
|
+
message: `attestation requires a human actor matching ^human:.+, got ${JSON.stringify(actor)}; attestation is the one verb an agent must not perform, and the log was left unchanged`,
|
|
180
|
+
},
|
|
181
|
+
};
|
|
182
|
+
}
|
|
183
|
+
let sha256;
|
|
184
|
+
try {
|
|
185
|
+
// One read supplies both the expected-digest check and the recorded digest.
|
|
186
|
+
// A later edit naturally leaves the live policy hash-mismatched; it cannot
|
|
187
|
+
// make this record attest bytes other than the ones checked here.
|
|
188
|
+
sha256 = policyBytesHash(readFileSync(policyPath));
|
|
189
|
+
}
|
|
190
|
+
catch (cause) {
|
|
191
|
+
return {
|
|
192
|
+
ok: false,
|
|
193
|
+
error: {
|
|
194
|
+
code: "io",
|
|
195
|
+
message: `policy ${policyPath} could not be read for attestation: ${detail(cause)}`,
|
|
196
|
+
},
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
if (options.expectedSha256 !== undefined && sha256 !== options.expectedSha256) {
|
|
200
|
+
return {
|
|
201
|
+
ok: false,
|
|
202
|
+
error: {
|
|
203
|
+
code: "io",
|
|
204
|
+
message: `policy ${policyPath} changed after the reviewed bytes were shown; expected sha256 ${options.expectedSha256}, found ${sha256}; the log was left unchanged`,
|
|
205
|
+
},
|
|
206
|
+
};
|
|
207
|
+
}
|
|
208
|
+
return appendEvent(logPath, {
|
|
209
|
+
ts: tick(options),
|
|
210
|
+
event: "policy.updated",
|
|
211
|
+
actor,
|
|
212
|
+
payload: { policy_path: basename(policyPath), sha256 },
|
|
213
|
+
}, options);
|
|
214
|
+
}
|
|
215
|
+
/**
|
|
216
|
+
* Is this record an attestation — a `policy.updated` carrying a `sha256`?
|
|
217
|
+
*
|
|
218
|
+
* `policy.updated` records **without** a `payload.sha256` are ignored for
|
|
219
|
+
* attestation purposes. Two reasons, one forward and one backward: the event
|
|
220
|
+
* type predates this verb (SPEC.md §8 has always had it, and the schema keeps
|
|
221
|
+
* it base-only with no required payload fields), so pre-attestation logs and
|
|
222
|
+
* hand-rolled tooling may carry `policy.updated` events that assert nothing
|
|
223
|
+
* about bytes; and treating such a record as an attestation would mean a
|
|
224
|
+
* payload-less event could *satisfy* the guard, which is exactly backwards.
|
|
225
|
+
* Ignoring them means an old log reads as `not-attested` — fail closed.
|
|
226
|
+
*/
|
|
227
|
+
function attestationSha256(record) {
|
|
228
|
+
if (record.event !== "policy.updated")
|
|
229
|
+
return null;
|
|
230
|
+
const payload = record.payload;
|
|
231
|
+
if (payload === undefined)
|
|
232
|
+
return null;
|
|
233
|
+
const value = payload["sha256"];
|
|
234
|
+
return typeof value === "string" ? value : null;
|
|
235
|
+
}
|
|
236
|
+
/**
|
|
237
|
+
* Compare the live policy file against the latest attestation in `records`.
|
|
238
|
+
*
|
|
239
|
+
* `records` is the log in append order, as a caller has already read and
|
|
240
|
+
* verified it; this function does no I/O on the log and never writes. The
|
|
241
|
+
* **latest** attestation wins — re-attesting after an edit is the supported
|
|
242
|
+
* repair, and an older attestation must not be able to vouch for bytes that a
|
|
243
|
+
* newer one already disagreed with.
|
|
244
|
+
*
|
|
245
|
+
* `payload.policy_path` is recorded but deliberately **not** matched against
|
|
246
|
+
* `policyPath`: v0.1 has exactly one policy file per approval home (SPEC.md
|
|
247
|
+
* §5), and a filename filter would let an attestation of `APPROVALS.md` and a
|
|
248
|
+
* live `APPROVAL.md` drift apart silently. Comparing only bytes means the
|
|
249
|
+
* mismatch surfaces as a mismatch.
|
|
250
|
+
*/
|
|
251
|
+
export function checkAttestation(records, policyPath) {
|
|
252
|
+
// Read the live file first: unreadable is its own status, and it outranks
|
|
253
|
+
// "never attested" because it is the fact we are most sure of.
|
|
254
|
+
let bytes;
|
|
255
|
+
try {
|
|
256
|
+
bytes = readFileSync(policyPath);
|
|
257
|
+
}
|
|
258
|
+
catch (cause) {
|
|
259
|
+
return unreadablePolicyStatus(policyPath, detail(cause));
|
|
260
|
+
}
|
|
261
|
+
return checkAttestationOfBytes(records, bytes);
|
|
262
|
+
}
|
|
263
|
+
/** The `unreadable` status for a policy read the caller performed itself. */
|
|
264
|
+
export function unreadablePolicyStatus(policyPath, cause) {
|
|
265
|
+
return {
|
|
266
|
+
status: "unreadable",
|
|
267
|
+
message: `policy ${policyPath} could not be read: ${cause}`,
|
|
268
|
+
};
|
|
269
|
+
}
|
|
270
|
+
/**
|
|
271
|
+
* {@link checkAttestation} against bytes the caller already holds.
|
|
272
|
+
*
|
|
273
|
+
* Same comparison, no read. A gate operation reads the policy file once and
|
|
274
|
+
* passes that one buffer here and to the parser (APRV-142), which is what makes
|
|
275
|
+
* "attested one policy, enforced another" structurally impossible rather than
|
|
276
|
+
* merely unlikely.
|
|
277
|
+
*
|
|
278
|
+
* The `unreadable` status has no counterpart here: bytes that exist were read.
|
|
279
|
+
* A caller whose read failed calls {@link unreadablePolicyStatus} instead, so
|
|
280
|
+
* the fail-closed ordering of {@link checkAttestation} survives the split.
|
|
281
|
+
*/
|
|
282
|
+
export function checkAttestationOfBytes(records, bytes) {
|
|
283
|
+
const liveSha256 = policyBytesHash(bytes);
|
|
284
|
+
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
285
|
+
const record = records[index];
|
|
286
|
+
const attested = attestationSha256(record);
|
|
287
|
+
if (attested === null)
|
|
288
|
+
continue;
|
|
289
|
+
if (attested === liveSha256) {
|
|
290
|
+
return { status: "attested", seq: record.seq, sha256: liveSha256 };
|
|
291
|
+
}
|
|
292
|
+
return {
|
|
293
|
+
status: "hash-mismatch",
|
|
294
|
+
attestedSha256: attested,
|
|
295
|
+
liveSha256,
|
|
296
|
+
seq: record.seq,
|
|
297
|
+
};
|
|
298
|
+
}
|
|
299
|
+
return { status: "not-attested" };
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* The refusal for a non-`attested` status, or `null` when policy is attested.
|
|
303
|
+
*
|
|
304
|
+
* One code (`policy-not-attested`) with a `detail` discriminator, rather than
|
|
305
|
+
* three codes: a caller that wants to refuse needs to branch on one value, and
|
|
306
|
+
* a caller that wants to explain has `detail` and `message`.
|
|
307
|
+
*/
|
|
308
|
+
export function attestationRefusal(status) {
|
|
309
|
+
switch (status.status) {
|
|
310
|
+
case "attested":
|
|
311
|
+
return null;
|
|
312
|
+
case "not-attested":
|
|
313
|
+
return {
|
|
314
|
+
code: ATTESTATION_REFUSAL,
|
|
315
|
+
detail: "not-attested",
|
|
316
|
+
message: "the policy file has never been attested; a human must run `approval policy attest` before gated operations can proceed",
|
|
317
|
+
};
|
|
318
|
+
case "hash-mismatch":
|
|
319
|
+
return {
|
|
320
|
+
code: ATTESTATION_REFUSAL,
|
|
321
|
+
detail: "hash-mismatch",
|
|
322
|
+
message: `the policy file has changed since it was attested at seq ${status.seq} (attested ${status.attestedSha256}, live ${status.liveSha256}); an edited policy is inoperative until a human re-attests it`,
|
|
323
|
+
};
|
|
324
|
+
case "unreadable":
|
|
325
|
+
return {
|
|
326
|
+
code: ATTESTATION_REFUSAL,
|
|
327
|
+
detail: "unreadable",
|
|
328
|
+
message: `${status.message}; an unverifiable policy is treated as unattested`,
|
|
329
|
+
};
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
/**
|
|
333
|
+
* The human identity to record as `actor`, or `null` when none is declared.
|
|
334
|
+
*
|
|
335
|
+
* Precedence: `options.actor` (the CLI's `--as`) first, then the
|
|
336
|
+
* `APPROVAL_HUMAN` environment variable. An explicit `--as` that does not match
|
|
337
|
+
* `^human:.+` yields `null` rather than falling back to the environment —
|
|
338
|
+
* silently substituting a different identity for the one the caller typed would
|
|
339
|
+
* be worse than refusing.
|
|
340
|
+
*
|
|
341
|
+
* This is **config-declared identity**. The trust boundary is the local
|
|
342
|
+
* machine: whoever can set `APPROVAL_HUMAN` and write to the log is inside it.
|
|
343
|
+
* v0.1 makes no cryptographic claim about who attested, only that a locally
|
|
344
|
+
* privileged act occurred and was recorded.
|
|
345
|
+
*/
|
|
346
|
+
export function resolveHumanActor(options = {}) {
|
|
347
|
+
const explicit = options.actor;
|
|
348
|
+
if (explicit !== undefined) {
|
|
349
|
+
return HUMAN_ACTOR.test(explicit) ? explicit : null;
|
|
350
|
+
}
|
|
351
|
+
const fromEnv = process.env[HUMAN_ACTOR_ENV];
|
|
352
|
+
if (fromEnv !== undefined && HUMAN_ACTOR.test(fromEnv))
|
|
353
|
+
return fromEnv;
|
|
354
|
+
return null;
|
|
355
|
+
}
|
|
356
|
+
// ===========================================================================
|
|
357
|
+
// Organ attestation (APRV-272, amended SPEC.md §5.2 and §8)
|
|
358
|
+
// ===========================================================================
|
|
359
|
+
/**
|
|
360
|
+
* The event an ORGAN attestation is: a human's sign-off on the exact bytes of
|
|
361
|
+
* one of the gate's own organ files.
|
|
362
|
+
*
|
|
363
|
+
* ## Why the organs need this at all
|
|
364
|
+
*
|
|
365
|
+
* `.claude/settings.json` and Cursor's hook files classify `policy.core`, and
|
|
366
|
+
* `policy.core` is human-only in this repository's policy and inert to agents
|
|
367
|
+
* by §11.1 invariant 9. So the gate mints NOTHING for them: `core/gate.ts`
|
|
368
|
+
* refuses a human-only class before any record is appended, which means the
|
|
369
|
+
* protected-path guard's `granted-file` and `granted-command` verdicts cannot
|
|
370
|
+
* exist for an organ, however correctly a human edited it. PR #300 is that hole,
|
|
371
|
+
* exactly: a human hand-committed hook entries and CI failed the change because
|
|
372
|
+
* the only evidence the guard could accept was evidence the gate is designed
|
|
373
|
+
* never to produce.
|
|
374
|
+
*
|
|
375
|
+
* Attestation is the primitive that already fits. It records "a human saw these
|
|
376
|
+
* exact bytes", it needs no grant, and it matches CONTENT rather than a path, so
|
|
377
|
+
* the guard can hash the blob at head and ask the log about it.
|
|
378
|
+
*
|
|
379
|
+
* ## Why a separate event type
|
|
380
|
+
*
|
|
381
|
+
* `core/log.ts`'s `EventType` note carries the argument in full. In one line:
|
|
382
|
+
* every reader of the POLICY attestation selects on `event === "policy.updated"`,
|
|
383
|
+
* so a distinct type is invisible to all of them by construction, and
|
|
384
|
+
* {@link checkAttestationOfBytes} returns at the first `sha256`-bearing record
|
|
385
|
+
* it meets scanning backwards — an organ record wearing `policy.updated` would
|
|
386
|
+
* have made a correctly attested policy read as `hash-mismatch`.
|
|
387
|
+
*/
|
|
388
|
+
export const ORGAN_ATTESTATION_EVENT = "gate.organ.attested";
|
|
389
|
+
/**
|
|
390
|
+
* The payload field naming which organ was attested.
|
|
391
|
+
*
|
|
392
|
+
* Repository-relative and `/`-separated, never absolute: the log is meant to be
|
|
393
|
+
* copied and read on other machines, and an absolute path would leak the
|
|
394
|
+
* writer's home directory into a permanent record. Unlike the policy
|
|
395
|
+
* attestation, which records a BASENAME because v0.1 has exactly one policy file
|
|
396
|
+
* per approval home, an organ record has to carry the whole relative path —
|
|
397
|
+
* there are several organs, they live in different directories, and the guard's
|
|
398
|
+
* rule is that a digest attested for one path is not evidence for another.
|
|
399
|
+
*/
|
|
400
|
+
export const ORGAN_PATH_FIELD = "organ_path";
|
|
401
|
+
/**
|
|
402
|
+
* Why an organ attestation was refused: the policy attestation's codes, plus
|
|
403
|
+
* the two rules this verb has of its own.
|
|
404
|
+
*
|
|
405
|
+
* Two codes and not one, because the repairs are different and a caller must be
|
|
406
|
+
* able to tell them apart. `path-is-policy` means the caller aimed the organ
|
|
407
|
+
* verb at the policy file, whose attestation is `approval policy attest` with no
|
|
408
|
+
* `--organ` and which the gate reads on every operation. `path-not-organ` covers
|
|
409
|
+
* everything else the runtime will not attest this way: the approval home, whose
|
|
410
|
+
* contents are the human's own ceremony surface, and any ordinary file, which is
|
|
411
|
+
* not part of the gate and needs no attestation to be edited.
|
|
412
|
+
*/
|
|
413
|
+
export const ORGAN_ATTEST_ERROR_CODES = [
|
|
414
|
+
...ATTEST_ERROR_CODES,
|
|
415
|
+
"path-not-organ",
|
|
416
|
+
"path-is-policy",
|
|
417
|
+
];
|
|
418
|
+
/**
|
|
419
|
+
* Append a `gate.organ.attested` record for `target` to `logPath`.
|
|
420
|
+
*
|
|
421
|
+
* The rules, all of them refused as structured results and never as throws, in
|
|
422
|
+
* the order they are checked:
|
|
423
|
+
*
|
|
424
|
+
* 1. `actor` MUST match `^human:.+`. Attestation is the verb an agent must not
|
|
425
|
+
* perform, and it is refused here in code and again at the CLI, exactly as
|
|
426
|
+
* {@link appendAttestation} is.
|
|
427
|
+
* 2. The path must be repository-relative: absolute paths and `..` are refused,
|
|
428
|
+
* because the recorded identity has to mean the same file on the machine
|
|
429
|
+
* that later reads the log.
|
|
430
|
+
* 3. The policy file is refused with its own code. It has its own attestation
|
|
431
|
+
* and the gate reads it on every operation; letting the organ verb write a
|
|
432
|
+
* record about it would create a second thing that looks like a policy
|
|
433
|
+
* attestation and is not one.
|
|
434
|
+
* 4. The path must be a gate organ ({@link isGateOrganPath}). Nothing else is
|
|
435
|
+
* attestable this way, so the verb cannot be turned into a general
|
|
436
|
+
* "bless these bytes" primitive for any file at all.
|
|
437
|
+
*
|
|
438
|
+
* The digest is computed by the runtime from the file's exact bytes. There is
|
|
439
|
+
* no parameter for it, which is the same reason there is no `ts` parameter: a
|
|
440
|
+
* caller who could supply the hash could attest bytes nobody read, and a caller
|
|
441
|
+
* who could supply the moment could backdate what was operative when.
|
|
442
|
+
*
|
|
443
|
+
* Like {@link appendAttestation} this append carries no `expectedHead`. It reads
|
|
444
|
+
* nothing from the log, so it has no check-then-act window to close; a
|
|
445
|
+
* concurrent appender only means this record lands after theirs.
|
|
446
|
+
*/
|
|
447
|
+
export function appendOrganAttestation(logPath, target, actor, options = {}) {
|
|
448
|
+
if (!HUMAN_ACTOR.test(actor)) {
|
|
449
|
+
return {
|
|
450
|
+
ok: false,
|
|
451
|
+
error: {
|
|
452
|
+
code: "actor-not-human",
|
|
453
|
+
message: `attesting a gate organ requires a human actor matching ^human:.+, got ${JSON.stringify(actor)}; the organs are the files that install the hook, so an agent that could attest one could vouch for its own way out of the gate, and the log was left unchanged`,
|
|
454
|
+
},
|
|
455
|
+
};
|
|
456
|
+
}
|
|
457
|
+
const refusal = organPathRefusal(target.path);
|
|
458
|
+
if (refusal !== null)
|
|
459
|
+
return { ok: false, error: refusal };
|
|
460
|
+
const organPath = normalizePathSpelling(target.path);
|
|
461
|
+
let sha256;
|
|
462
|
+
try {
|
|
463
|
+
sha256 = policyFileHash(join(target.root, organPath));
|
|
464
|
+
}
|
|
465
|
+
catch (cause) {
|
|
466
|
+
return {
|
|
467
|
+
ok: false,
|
|
468
|
+
error: {
|
|
469
|
+
code: "io",
|
|
470
|
+
message: `gate organ ${organPath} could not be read under ${target.root} for attestation: ${detail(cause)}`,
|
|
471
|
+
},
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
return appendEvent(logPath, {
|
|
475
|
+
ts: tick(options),
|
|
476
|
+
event: ORGAN_ATTESTATION_EVENT,
|
|
477
|
+
actor,
|
|
478
|
+
payload: { [ORGAN_PATH_FIELD]: organPath, sha256 },
|
|
479
|
+
}, options);
|
|
480
|
+
}
|
|
481
|
+
/** Rules 2 to 4 of {@link appendOrganAttestation}, or `null` when the path passes. */
|
|
482
|
+
function organPathRefusal(candidate) {
|
|
483
|
+
const normalized = normalizePathSpelling(candidate);
|
|
484
|
+
if (normalized.length === 0 || isAbsolute(candidate) || normalized.split("/").includes("..")) {
|
|
485
|
+
return {
|
|
486
|
+
code: "path-not-organ",
|
|
487
|
+
message: `${JSON.stringify(candidate)} is not a repository-relative path; an organ attestation records the path itself, so it must name the same file on every machine that later reads the log`,
|
|
488
|
+
};
|
|
489
|
+
}
|
|
490
|
+
if (isGateOrganPath(normalized))
|
|
491
|
+
return null;
|
|
492
|
+
if (builtinProtectedPathClass(normalized) === "policy.core") {
|
|
493
|
+
const last = normalized.split("/").pop() ?? normalized;
|
|
494
|
+
if (POLICY_FILE_NAMES.includes(last)) {
|
|
495
|
+
return {
|
|
496
|
+
code: "path-is-policy",
|
|
497
|
+
message: `${normalized} is the policy file, not a gate organ; its attestation is \`approval policy attest\` with no --organ, and the gate reads that one on every operation`,
|
|
498
|
+
};
|
|
499
|
+
}
|
|
500
|
+
return {
|
|
501
|
+
code: "path-not-organ",
|
|
502
|
+
message: `${normalized} is inside the approval home, which is the human's own ceremony surface and is not attested this way; the gate organs are the harness files that install the hook`,
|
|
503
|
+
};
|
|
504
|
+
}
|
|
505
|
+
return {
|
|
506
|
+
code: "path-not-organ",
|
|
507
|
+
message: `${normalized} does not classify policy.core, so it is not one of the gate's organs; only the harness files that install the hook are attested by content, and an ordinary protected path is edited through the gate and evidenced by the grant`,
|
|
508
|
+
};
|
|
509
|
+
}
|
|
510
|
+
/**
|
|
511
|
+
* The policy filenames, for the one refusal that has to name them.
|
|
512
|
+
*
|
|
513
|
+
* Spelled here rather than imported from `core/policy-load.ts`: this module is
|
|
514
|
+
* below the policy loader and stays there, and the two candidate names are a
|
|
515
|
+
* SPEC.md §5 constant rather than a loader detail.
|
|
516
|
+
*/
|
|
517
|
+
const POLICY_FILE_NAMES = ["APPROVAL.md", "APPROVALS.md"];
|
|
518
|
+
/**
|
|
519
|
+
* Is this record an organ attestation, and which bytes of which file does it
|
|
520
|
+
* vouch for?
|
|
521
|
+
*
|
|
522
|
+
* A record missing either field is ignored, for the reason a `policy.updated`
|
|
523
|
+
* with no `sha256` is ignored: a record that asserts nothing about bytes must
|
|
524
|
+
* never be able to SATISFY a check about bytes. Fail closed.
|
|
525
|
+
*/
|
|
526
|
+
export function organAttestationOf(record) {
|
|
527
|
+
if (record.event !== ORGAN_ATTESTATION_EVENT)
|
|
528
|
+
return null;
|
|
529
|
+
const payload = record.payload;
|
|
530
|
+
if (payload === undefined)
|
|
531
|
+
return null;
|
|
532
|
+
const organPath = payload[ORGAN_PATH_FIELD];
|
|
533
|
+
const sha256 = payload["sha256"];
|
|
534
|
+
if (typeof organPath !== "string" || typeof sha256 !== "string")
|
|
535
|
+
return null;
|
|
536
|
+
const normalized = normalizePathSpelling(organPath);
|
|
537
|
+
if (normalized.length === 0)
|
|
538
|
+
return null;
|
|
539
|
+
return { organPath: normalized, sha256 };
|
|
540
|
+
}
|
|
541
|
+
/**
|
|
542
|
+
* The record in which a human attested THIS digest FOR THIS path, latest first,
|
|
543
|
+
* or `null`.
|
|
544
|
+
*
|
|
545
|
+
* Both halves are required and that is the whole rule: a digest attested for
|
|
546
|
+
* some other organ is not evidence for this one. Two organ files with identical
|
|
547
|
+
* bytes (two checkouts of the same hook entry, say) are still two files, and a
|
|
548
|
+
* human who signed one has said nothing about the other.
|
|
549
|
+
*
|
|
550
|
+
* Unlike the policy attestation there is no "latest wins" supersession here.
|
|
551
|
+
* Every organ attestation stands for the bytes it names: the guard asks about a
|
|
552
|
+
* blob at a commit that may be months old, and the newest attestation of a file
|
|
553
|
+
* says nothing about whether an older set of bytes was once signed off. The
|
|
554
|
+
* gate reads none of these records, so a stale one authorizes nothing on its
|
|
555
|
+
* own — it is evidence about a change, and evidence does not expire the way an
|
|
556
|
+
* operative policy does.
|
|
557
|
+
*/
|
|
558
|
+
export function findOrganAttestation(records, organPath, sha256) {
|
|
559
|
+
const want = normalizePathSpelling(organPath);
|
|
560
|
+
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
561
|
+
const record = records[index];
|
|
562
|
+
const fields = organAttestationOf(record);
|
|
563
|
+
if (fields === null)
|
|
564
|
+
continue;
|
|
565
|
+
if (fields.organPath === want && fields.sha256 === sha256)
|
|
566
|
+
return record;
|
|
567
|
+
}
|
|
568
|
+
return null;
|
|
569
|
+
}
|
|
570
|
+
/**
|
|
571
|
+
* The most recent attestation of `organPath` at ANY digest, or `null`.
|
|
572
|
+
*
|
|
573
|
+
* What a status surface needs to tell "this file has never been attested" from
|
|
574
|
+
* "this file was attested and has been edited since". Nothing enforcing reads
|
|
575
|
+
* it: {@link findOrganAttestation} is the question the guard asks.
|
|
576
|
+
*/
|
|
577
|
+
export function latestOrganAttestation(records, organPath) {
|
|
578
|
+
const want = normalizePathSpelling(organPath);
|
|
579
|
+
for (let index = records.length - 1; index >= 0; index -= 1) {
|
|
580
|
+
const record = records[index];
|
|
581
|
+
const fields = organAttestationOf(record);
|
|
582
|
+
if (fields === null)
|
|
583
|
+
continue;
|
|
584
|
+
if (fields.organPath === want)
|
|
585
|
+
return { ...fields, record };
|
|
586
|
+
}
|
|
587
|
+
return null;
|
|
588
|
+
}
|
|
589
|
+
//# sourceMappingURL=attest.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"attest.js","sourceRoot":"","sources":["../../../src/core/attest.ts"],"names":[],"mappings":"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"}
|