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,376 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Payload retention pruning — the enforcement half of amended SPEC.md §5.2
|
|
3
|
+
* (APRV-38's vocabulary, APRV-41's daemon).
|
|
4
|
+
*
|
|
5
|
+
* > "A payload is prunable once the action it is bound to has been in a terminal
|
|
6
|
+
* > state (`executed`, `rejected`, `expired`, `revoked`) for longer than the
|
|
7
|
+
* > duration. A payload whose action is not terminal is never prunable, at any
|
|
8
|
+
* > age […]. Orphaned payloads (bytes with no recorded binding) are prunable
|
|
9
|
+
* > regardless of the key. […] Pruning is performed by the daemon and by nothing
|
|
10
|
+
* > else, and each removal appends a `payload.pruned` event, so a log states what
|
|
11
|
+
* > its store no longer holds."
|
|
12
|
+
*
|
|
13
|
+
* ## Write-ahead, always in that order
|
|
14
|
+
*
|
|
15
|
+
* For every file this module removes, the `payload.pruned` event lands in the
|
|
16
|
+
* log **first** and the `unlink` follows. The ordering is the whole design: a
|
|
17
|
+
* crash between the two leaves a file on disk that the log already says is gone,
|
|
18
|
+
* which the next tick completes by unlinking it and appending nothing further
|
|
19
|
+
* ({@link PrunePlan.completions}). The opposite order would leave the other
|
|
20
|
+
* failure — bytes deleted with no record of the deletion — which is the one
|
|
21
|
+
* outcome a store holding the material evidence of what a human approved cannot
|
|
22
|
+
* afford. Deleting evidence is acceptable; deleting it silently is not.
|
|
23
|
+
*
|
|
24
|
+
* Idempotence needs no remembered state: a hash that already carries a
|
|
25
|
+
* `payload.pruned` event is never given a second one, and the plan is re-derived
|
|
26
|
+
* from the verified log on every tick.
|
|
27
|
+
*
|
|
28
|
+
* ## Terminal time comes from the log, never from the filesystem
|
|
29
|
+
*
|
|
30
|
+
* The clock that decides whether retention has elapsed reads the timestamp of the
|
|
31
|
+
* event that made the action terminal (`execution.completed`, `approval.rejected`,
|
|
32
|
+
* `approval.revoked`, `approval.expired`). File mtimes are not evidence: they are
|
|
33
|
+
* rewritten by a copy, a checkout, a backup restore, or an `rsync`, and pruning on
|
|
34
|
+
* them would let a routine filesystem operation decide when approval evidence
|
|
35
|
+
* disappears.
|
|
36
|
+
*
|
|
37
|
+
* A **lazily** expired request (the TTL has arithmetically lapsed but no
|
|
38
|
+
* `approval.expired` record exists) is deliberately not terminal here. The
|
|
39
|
+
* daemon's own TTL sweep appends that event on the same tick; the payload becomes
|
|
40
|
+
* prunable once the log says so, and retention is then measured from the recorded
|
|
41
|
+
* moment rather than from one this module computed for itself.
|
|
42
|
+
*
|
|
43
|
+
* `execution.failed` is likewise not terminal: a failed action may be retried
|
|
44
|
+
* against the very bytes in question, and loop escalation (SPEC.md §10.2) exists
|
|
45
|
+
* precisely because failures recur.
|
|
46
|
+
*
|
|
47
|
+
* ## The orphan rule, resolved conservatively (flagged for review)
|
|
48
|
+
*
|
|
49
|
+
* §5.2 says orphaned payloads are "prunable regardless of the key", which reads
|
|
50
|
+
* as though orphans could be swept even with `payload_retention` absent. APRV-41's
|
|
51
|
+
* acceptance criteria say the absent key means no pruning at all. This module
|
|
52
|
+
* takes the strictest reading that satisfies both:
|
|
53
|
+
*
|
|
54
|
+
* - **`payload_retention` absent: the pruning subsystem does not run.** Nothing is
|
|
55
|
+
* deleted, orphan or not, and no `payload.pruned` is appended. Retention is an
|
|
56
|
+
* operator's explicit choice to forget, and an operator who never made it never
|
|
57
|
+
* asked this runtime to delete anything.
|
|
58
|
+
* - **`payload_retention` present: orphans are prunable at any age**, which is
|
|
59
|
+
* what "regardless of the key" then means — the duration governs bound payloads
|
|
60
|
+
* and does not gate residue nothing ever bound.
|
|
61
|
+
*
|
|
62
|
+
* An orphan is a file whose hash appears in **no** log record other than a
|
|
63
|
+
* `payload.pruned` (head-moved residue: the gate stored the bytes, its append was
|
|
64
|
+
* refused, and no request ever declared them). A hash mentioned by any other
|
|
65
|
+
* record is bound, and a binding this module cannot attribute to an action key is
|
|
66
|
+
* treated as live rather than as an orphan — fail closed in both directions.
|
|
67
|
+
*
|
|
68
|
+
* ## Nothing else here decides anything
|
|
69
|
+
*
|
|
70
|
+
* Which hashes the log already binds, and which it already says are pruned, is
|
|
71
|
+
* `core/payload-census.ts`'s — the same computation the reporting surfaces read,
|
|
72
|
+
* so what a reader is shown and what this module would delete can never drift
|
|
73
|
+
* apart. Approval state per action is `core/state.ts`'s `requestState`; the append is
|
|
74
|
+
* `core/log.ts`'s `appendEvent` with `expectedHead` (compare-and-append, SPEC.md
|
|
75
|
+
* §11.1 invariant 5); the unlink is `core/payload-store.ts`'s. The timestamp on
|
|
76
|
+
* every `payload.pruned` is the runtime's, read from the injected clock at the
|
|
77
|
+
* write boundary, and the actor is `system:daemon` — a party under oversight must
|
|
78
|
+
* never be able to author either.
|
|
79
|
+
*/
|
|
80
|
+
import { tick as readClock } from "../core/clock.js";
|
|
81
|
+
import { appendEvent } from "../core/log.js";
|
|
82
|
+
import { isPayloadHash } from "../core/payload.js";
|
|
83
|
+
import { bindingsOf, prunedHashes } from "../core/payload-census.js";
|
|
84
|
+
import { listStoredPayloadHashes, payloadStoreDirFor, removeStoredPayload, } from "../core/payload-store.js";
|
|
85
|
+
import { loadPolicy, parseDuration } from "../core/policy-load.js";
|
|
86
|
+
import { readVerifiedRecords, requestState } from "../core/state.js";
|
|
87
|
+
/**
|
|
88
|
+
* SPEC.md §8 and `event.schema.json`: `payload.pruned` carries a `system:` actor.
|
|
89
|
+
* Declared here rather than imported from `daemon.ts` so the pruner has no
|
|
90
|
+
* dependency on the loop that calls it.
|
|
91
|
+
*/
|
|
92
|
+
export const PRUNE_ACTOR = "system:daemon";
|
|
93
|
+
/** A fresh empty plan each time: a shared one could be mutated by a caller. */
|
|
94
|
+
function emptyPlan() {
|
|
95
|
+
return { candidates: [], completions: [] };
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* When (and whether) `actionKey` became terminal, per the log alone.
|
|
99
|
+
*
|
|
100
|
+
* `ttlMs` is passed as `null` to `requestState` on purpose: lazy expiry is
|
|
101
|
+
* arithmetic this module refuses to prune on (see the module header), so the only
|
|
102
|
+
* expiry that counts is one `approval.expired` recorded.
|
|
103
|
+
*
|
|
104
|
+
* A key whose request is live (`requested`) is never terminal, even when an older
|
|
105
|
+
* execution completed: a fresh request binds to those bytes again and the earlier
|
|
106
|
+
* outcome does not release them.
|
|
107
|
+
*/
|
|
108
|
+
function terminalOf(records, actionKey, nowIso) {
|
|
109
|
+
const derived = requestState(records, actionKey, nowIso, null);
|
|
110
|
+
// A live request binds the bytes, whatever else the key's history holds.
|
|
111
|
+
if (derived.state === "requested")
|
|
112
|
+
return null;
|
|
113
|
+
// `none` is not itself terminal: an action that was registered and never
|
|
114
|
+
// requested still declares these bytes, and a request may yet be made for it.
|
|
115
|
+
// It becomes terminal only by executing (the autonomous path, which requests
|
|
116
|
+
// nothing), which the `execution.completed` branch below picks up.
|
|
117
|
+
const seen = [];
|
|
118
|
+
const decision = derived.decision;
|
|
119
|
+
if (decision === "rejected" || decision === "revoked") {
|
|
120
|
+
if (derived.decisionTs !== null)
|
|
121
|
+
seen.push({ state: decision, ts: derived.decisionTs });
|
|
122
|
+
}
|
|
123
|
+
if (decision === "expired" && derived.expiredByEvent && derived.decisionTs !== null) {
|
|
124
|
+
seen.push({ state: "expired", ts: derived.decisionTs });
|
|
125
|
+
}
|
|
126
|
+
if (derived.execution.completed !== null) {
|
|
127
|
+
const completed = records.find((record) => record.seq === derived.execution.completed);
|
|
128
|
+
if (completed !== undefined)
|
|
129
|
+
seen.push({ state: "executed", ts: completed.ts });
|
|
130
|
+
}
|
|
131
|
+
let terminal = null;
|
|
132
|
+
for (const entry of seen) {
|
|
133
|
+
const at = Date.parse(entry.ts);
|
|
134
|
+
if (Number.isNaN(at))
|
|
135
|
+
continue;
|
|
136
|
+
if (terminal === null || at > Date.parse(terminal.ts))
|
|
137
|
+
terminal = entry;
|
|
138
|
+
}
|
|
139
|
+
return terminal;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* What may be pruned right now. Pure: no I/O, no clock, no policy loading.
|
|
143
|
+
*
|
|
144
|
+
* `retentionMs` is `null` when the policy declares no `payload_retention` — or
|
|
145
|
+
* when the policy could not be loaded at all, which fails closed to the same
|
|
146
|
+
* answer. Either way the plan is empty: the subsystem does not run.
|
|
147
|
+
*
|
|
148
|
+
* `nowIso` is the evaluation moment, injected. A pruner that read the clock
|
|
149
|
+
* itself could not be replayed, and retention arithmetic that cannot be replayed
|
|
150
|
+
* cannot be audited.
|
|
151
|
+
*/
|
|
152
|
+
export function planPrune(records, presentHashes, nowIso, retentionMs) {
|
|
153
|
+
if (retentionMs === null)
|
|
154
|
+
return emptyPlan();
|
|
155
|
+
const now = Date.parse(nowIso);
|
|
156
|
+
// An unparseable evaluation moment cannot be compared against anything, so
|
|
157
|
+
// nothing is old enough for anything.
|
|
158
|
+
if (Number.isNaN(now))
|
|
159
|
+
return emptyPlan();
|
|
160
|
+
const pruned = prunedHashes(records);
|
|
161
|
+
const bindings = bindingsOf(records);
|
|
162
|
+
const candidates = [];
|
|
163
|
+
const completions = [];
|
|
164
|
+
for (const hash of [...presentHashes].sort()) {
|
|
165
|
+
if (!isPayloadHash(hash))
|
|
166
|
+
continue;
|
|
167
|
+
if (pruned.has(hash)) {
|
|
168
|
+
completions.push(hash);
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
const binding = bindings.get(hash);
|
|
172
|
+
if (binding === undefined) {
|
|
173
|
+
candidates.push({
|
|
174
|
+
hash,
|
|
175
|
+
reason: "orphaned",
|
|
176
|
+
actionKey: null,
|
|
177
|
+
task: null,
|
|
178
|
+
terminalState: null,
|
|
179
|
+
terminalTs: null,
|
|
180
|
+
});
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
// A binding nobody can attribute to an action key has no derivable terminal
|
|
184
|
+
// state, so it is treated as live forever.
|
|
185
|
+
if (binding.unattributed || binding.actionKeys.size === 0)
|
|
186
|
+
continue;
|
|
187
|
+
// EVERY action bound to these bytes must have released them. One live
|
|
188
|
+
// request among ten settled ones keeps the payload.
|
|
189
|
+
let latest = null;
|
|
190
|
+
let latestKey = null;
|
|
191
|
+
let live = false;
|
|
192
|
+
for (const key of [...binding.actionKeys].sort()) {
|
|
193
|
+
const terminal = terminalOf(records, key, nowIso);
|
|
194
|
+
if (terminal === null) {
|
|
195
|
+
live = true;
|
|
196
|
+
break;
|
|
197
|
+
}
|
|
198
|
+
if (latest === null || Date.parse(terminal.ts) > Date.parse(latest.ts)) {
|
|
199
|
+
latest = terminal;
|
|
200
|
+
latestKey = key;
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
if (live || latest === null || latestKey === null)
|
|
204
|
+
continue;
|
|
205
|
+
if (!(now - Date.parse(latest.ts) > retentionMs))
|
|
206
|
+
continue;
|
|
207
|
+
candidates.push({
|
|
208
|
+
hash,
|
|
209
|
+
reason: "payload_retention",
|
|
210
|
+
actionKey: latestKey,
|
|
211
|
+
task: taskOf(records, latestKey),
|
|
212
|
+
terminalState: latest.state,
|
|
213
|
+
terminalTs: latest.ts,
|
|
214
|
+
});
|
|
215
|
+
}
|
|
216
|
+
return { candidates, completions };
|
|
217
|
+
}
|
|
218
|
+
/** The task an action key was last seen under, for the event's `task` field. */
|
|
219
|
+
function taskOf(records, actionKey) {
|
|
220
|
+
let task = null;
|
|
221
|
+
for (const record of records) {
|
|
222
|
+
if (record.action_key === actionKey && typeof record.task === "string")
|
|
223
|
+
task = record.task;
|
|
224
|
+
}
|
|
225
|
+
return task;
|
|
226
|
+
}
|
|
227
|
+
/**
|
|
228
|
+
* Read `payload_retention` from the policy in force right now.
|
|
229
|
+
*
|
|
230
|
+
* Fails closed to `null` exactly as the daemon's TTL read does: a policy that
|
|
231
|
+
* cannot be loaded declares no retention, so nothing is pruned on its behalf. An
|
|
232
|
+
* unparseable duration is likewise `null` — the schema's duration pattern makes
|
|
233
|
+
* that unreachable through a validated policy, and a retention rule this module
|
|
234
|
+
* cannot read is not one it may guess at.
|
|
235
|
+
*/
|
|
236
|
+
export function retentionMsOf(policy, schemaDir) {
|
|
237
|
+
const where = policy.file !== undefined ? { file: policy.file } : { dir: policy.dir ?? process.cwd() };
|
|
238
|
+
if (schemaDir !== undefined)
|
|
239
|
+
where.schemaDir = schemaDir;
|
|
240
|
+
const load = loadPolicy(where);
|
|
241
|
+
if (!load.ok)
|
|
242
|
+
return null;
|
|
243
|
+
const text = load.policy.payload_retention;
|
|
244
|
+
if (text === undefined)
|
|
245
|
+
return null;
|
|
246
|
+
return parseDuration(text);
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* One pruning pass: plan, append, unlink, repeat.
|
|
250
|
+
*
|
|
251
|
+
* The log is re-read before each append rather than once for the pass, because
|
|
252
|
+
* each append moves the head the next one is compared against and because a CLI
|
|
253
|
+
* verb may have appended in between. `expectedHead` therefore always names the
|
|
254
|
+
* head the decision was made from; a `head-moved` refusal drops the candidate and
|
|
255
|
+
* the next tick re-derives it.
|
|
256
|
+
*
|
|
257
|
+
* Nothing is retried in place, and no state survives the call.
|
|
258
|
+
*/
|
|
259
|
+
export function prunePayloads(options) {
|
|
260
|
+
const retentionMs = retentionMsOf(options.policy, options.schemaDir);
|
|
261
|
+
const report = {
|
|
262
|
+
retentionMs,
|
|
263
|
+
appended: [],
|
|
264
|
+
pruned: [],
|
|
265
|
+
removed: [],
|
|
266
|
+
completed: [],
|
|
267
|
+
warnings: [],
|
|
268
|
+
};
|
|
269
|
+
if (retentionMs === null)
|
|
270
|
+
return report;
|
|
271
|
+
const storeDir = options.storeDir ?? payloadStoreDirFor(options.logPath);
|
|
272
|
+
const readOptions = options.schemaDir === undefined ? {} : { schemaDir: options.schemaDir };
|
|
273
|
+
const clockOptions = options.clock === undefined ? {} : { clock: options.clock };
|
|
274
|
+
// Hashes this pass has already acted on, so a plan re-derived after an append
|
|
275
|
+
// cannot hand the same file back twice within one call.
|
|
276
|
+
const handled = new Set();
|
|
277
|
+
for (;;) {
|
|
278
|
+
const read = readVerifiedRecords(options.logPath, readOptions);
|
|
279
|
+
if (!read.ok) {
|
|
280
|
+
// A log that does not verify stops the *daemon* (its own tick refuses to
|
|
281
|
+
// continue); here it simply means this pass plans nothing. Pruning never
|
|
282
|
+
// appends onto a chain it could not read.
|
|
283
|
+
report.warnings.push({ code: "log-unreadable", message: read.message });
|
|
284
|
+
return report;
|
|
285
|
+
}
|
|
286
|
+
const now = readClock(clockOptions);
|
|
287
|
+
const plan = planPrune(read.records, listStoredPayloadHashes(storeDir), now, retentionMs);
|
|
288
|
+
// Crash-window completions first: they append nothing, so they cannot move
|
|
289
|
+
// the head out from under the candidate below.
|
|
290
|
+
for (const hash of plan.completions) {
|
|
291
|
+
if (handled.has(hash))
|
|
292
|
+
continue;
|
|
293
|
+
handled.add(hash);
|
|
294
|
+
const removal = removeStoredPayload(storeDir, hash);
|
|
295
|
+
if (!removal.ok) {
|
|
296
|
+
report.warnings.push({ code: "unlink-failed", message: removal.message });
|
|
297
|
+
continue;
|
|
298
|
+
}
|
|
299
|
+
report.completed.push(hash);
|
|
300
|
+
if (removal.existed)
|
|
301
|
+
report.removed.push(hash);
|
|
302
|
+
}
|
|
303
|
+
const candidate = plan.candidates.find((entry) => !handled.has(entry.hash));
|
|
304
|
+
if (candidate === undefined)
|
|
305
|
+
return report;
|
|
306
|
+
handled.add(candidate.hash);
|
|
307
|
+
const payload = {
|
|
308
|
+
payload_hash: candidate.hash,
|
|
309
|
+
reason: candidate.reason,
|
|
310
|
+
};
|
|
311
|
+
if (candidate.reason === "payload_retention") {
|
|
312
|
+
payload["retention"] = durationText(retentionMs);
|
|
313
|
+
if (candidate.terminalState !== null)
|
|
314
|
+
payload["terminal_state"] = candidate.terminalState;
|
|
315
|
+
if (candidate.terminalTs !== null)
|
|
316
|
+
payload["terminal_ts"] = candidate.terminalTs;
|
|
317
|
+
}
|
|
318
|
+
const input = {
|
|
319
|
+
ts: now,
|
|
320
|
+
event: "payload.pruned",
|
|
321
|
+
actor: PRUNE_ACTOR,
|
|
322
|
+
payload,
|
|
323
|
+
};
|
|
324
|
+
if (candidate.task !== null)
|
|
325
|
+
input.task = candidate.task;
|
|
326
|
+
if (candidate.actionKey !== null)
|
|
327
|
+
input.action_key = candidate.actionKey;
|
|
328
|
+
const appended = appendEvent(options.logPath, input, {
|
|
329
|
+
...readOptions,
|
|
330
|
+
expectedHead: read.head,
|
|
331
|
+
});
|
|
332
|
+
if (!appended.ok) {
|
|
333
|
+
// WRITE-AHEAD: the file stays. An unlogged deletion is the one outcome
|
|
334
|
+
// this module exists to prevent, so a refused append prunes nothing.
|
|
335
|
+
report.warnings.push({
|
|
336
|
+
code: "append-refused",
|
|
337
|
+
message: `payload.pruned for ${candidate.hash} was not appended (${appended.error.code}): ${appended.error.message}; the file was left in place`,
|
|
338
|
+
});
|
|
339
|
+
continue;
|
|
340
|
+
}
|
|
341
|
+
report.appended.push(candidate);
|
|
342
|
+
const removal = removeStoredPayload(storeDir, candidate.hash);
|
|
343
|
+
if (!removal.ok) {
|
|
344
|
+
// The event is in the log and the bytes are still on disk: the log is
|
|
345
|
+
// ahead of the store, which is the safe direction. The next tick sees the
|
|
346
|
+
// file as a completion and unlinks it without a second event.
|
|
347
|
+
report.warnings.push({ code: "unlink-failed", message: removal.message });
|
|
348
|
+
continue;
|
|
349
|
+
}
|
|
350
|
+
report.removed.push(candidate.hash);
|
|
351
|
+
report.pruned.push({ candidate, seq: appended.record.seq });
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
/**
|
|
355
|
+
* The retention duration as the policy would have written it, for the event.
|
|
356
|
+
*
|
|
357
|
+
* Reconstructed from milliseconds rather than carried through from the policy
|
|
358
|
+
* text so the value recorded is the one the arithmetic used: a log that says
|
|
359
|
+
* `30d` when the code compared against something else would be worse than a log
|
|
360
|
+
* that says nothing.
|
|
361
|
+
*/
|
|
362
|
+
function durationText(ms) {
|
|
363
|
+
const units = [
|
|
364
|
+
[604_800_000, "w"],
|
|
365
|
+
[86_400_000, "d"],
|
|
366
|
+
[3_600_000, "h"],
|
|
367
|
+
[60_000, "m"],
|
|
368
|
+
[1_000, "s"],
|
|
369
|
+
];
|
|
370
|
+
for (const [scale, unit] of units) {
|
|
371
|
+
if (ms % scale === 0 && ms >= scale)
|
|
372
|
+
return `${String(ms / scale)}${unit}`;
|
|
373
|
+
}
|
|
374
|
+
return `${String(ms)}ms`;
|
|
375
|
+
}
|
|
376
|
+
//# sourceMappingURL=prune.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prune.js","sourceRoot":"","sources":["../../../src/daemon/prune.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `approval mcp serve --http` — the §10.5 wrapper over the MCP streamable-HTTP
|
|
3
|
+
* transport, one session per connection (APRV-174).
|
|
4
|
+
*
|
|
5
|
+
* The stdio server of `./server.ts` serves ONE client through the pipe the
|
|
6
|
+
* operator handed it: one process, one connection, one identity. This module
|
|
7
|
+
* changes exactly one thing about that picture, the transport, and it changes it
|
|
8
|
+
* so that several clients can be served at once. Everything else is the same
|
|
9
|
+
* code: the tool list is still {@link createApprovalMcpServer}'s, a tool call
|
|
10
|
+
* still builds an argv and calls the function the CLI dispatches to, and a
|
|
11
|
+
* refusal is still the CLI's refusal.
|
|
12
|
+
*
|
|
13
|
+
* ## One `Server` + one transport per session
|
|
14
|
+
*
|
|
15
|
+
* The SDK's `StreamableHTTPServerTransport` is stateful per session: it mints an
|
|
16
|
+
* `mcp-session-id` at `initialize`, stamps it on every response, and expects the
|
|
17
|
+
* client to send it back. This module owns one `node:http` listener and a map
|
|
18
|
+
* from that id to the `{ Server, transport, actor }` triple it belongs to. An
|
|
19
|
+
* initialize POST with no session header opens a triple; every later request is
|
|
20
|
+
* routed by the header; the triple is dropped when its transport closes (a
|
|
21
|
+
* DELETE, or the socket going away).
|
|
22
|
+
*
|
|
23
|
+
* ## Identity is minted BEFORE the transport exists, per session
|
|
24
|
+
*
|
|
25
|
+
* `cli/mcp.ts` settles identity before it constructs the stdio transport,
|
|
26
|
+
* because "a server that connected first and refused later would be a server a
|
|
27
|
+
* client had already spoken to". That property is preserved verbatim here, once
|
|
28
|
+
* per session: {@link mintSessionActor} runs before the `Server`/transport pair
|
|
29
|
+
* is built, and its result is the `actor` that pair closes over for its whole
|
|
30
|
+
* life.
|
|
31
|
+
*
|
|
32
|
+
* **Nothing a client sends reaches that actor.** There is no code path from a
|
|
33
|
+
* header, a URL, an `initialize` payload's `clientInfo`, or a tool argument into
|
|
34
|
+
* the identity a session runs as. `clientInfo.name` is a label a client chose
|
|
35
|
+
* for itself, and SPEC.md §11 says a self-reported field never reduces scrutiny;
|
|
36
|
+
* an identity a caller could name would be an identity a caller could escalate,
|
|
37
|
+
* so the server names it:
|
|
38
|
+
*
|
|
39
|
+
* - plain `--http`: every session runs as the operator's own `--as` /
|
|
40
|
+
* `APPROVAL_AGENT` actor, which is the stdio behavior with more connections;
|
|
41
|
+
* - `--guest`: every session mints its own `agent:guest-<6 hex>`, so the log,
|
|
42
|
+
* the budgets and the refusals see one stranger per connection rather than one
|
|
43
|
+
* crowd. That is the whole reason this scheme exists — an actor a limit can be
|
|
44
|
+
* keyed on.
|
|
45
|
+
*
|
|
46
|
+
* ## Loopback, caps, and no authentication whatsoever
|
|
47
|
+
*
|
|
48
|
+
* This listener authenticates nobody, exactly like `channels/web.ts`. It binds
|
|
49
|
+
* `127.0.0.1` unless the operator writes another host out in full, and the CLI
|
|
50
|
+
* prints a loud banner when they do; the deployment this was built for
|
|
51
|
+
* (SPEC.md §10.5, the crowd demo) is a tunnel in front of a loopback bind, where
|
|
52
|
+
* the tunnel is the thing that faces the network.
|
|
53
|
+
*
|
|
54
|
+
* Two caps bound what a stranger can spend: {@link MAX_CONCURRENT_SESSIONS} live
|
|
55
|
+
* at once and {@link MAX_LIFETIME_SESSIONS} over the process's life. Over either
|
|
56
|
+
* one, an initialize is refused with a plain HTTP 503 naming the reason, before
|
|
57
|
+
* a session exists.
|
|
58
|
+
*/
|
|
59
|
+
import { type ServerPaths } from "./server.js";
|
|
60
|
+
/** Live sessions this listener will hold at once. */
|
|
61
|
+
export declare const MAX_CONCURRENT_SESSIONS = 20;
|
|
62
|
+
/** Sessions this listener will open over the life of the process. */
|
|
63
|
+
export declare const MAX_LIFETIME_SESSIONS = 200;
|
|
64
|
+
/** Largest request body accepted, in bytes. A tool call is small. */
|
|
65
|
+
export declare const MAX_BODY_BYTES: number;
|
|
66
|
+
/** The prefix every guest session's actor carries. */
|
|
67
|
+
export declare const GUEST_ACTOR_PREFIX = "agent:guest-";
|
|
68
|
+
/**
|
|
69
|
+
* Mint one session's actor.
|
|
70
|
+
*
|
|
71
|
+
* `used` is the set of actors this listener has already handed out, for the life
|
|
72
|
+
* of the process rather than of the live map: two sessions that shared an actor
|
|
73
|
+
* would share a budget and a refusal history, which is the one thing this scheme
|
|
74
|
+
* exists to keep apart. Six hex digits is short enough to read out loud in a
|
|
75
|
+
* demo, so the collision check is not decoration.
|
|
76
|
+
*/
|
|
77
|
+
export declare function mintSessionActor(used: ReadonlySet<string>): string;
|
|
78
|
+
export interface HttpServeOptions extends ServerPaths {
|
|
79
|
+
/**
|
|
80
|
+
* The actor every session runs as, or `null` under {@link guest}, where each
|
|
81
|
+
* session mints its own. Already validated by `resolveAgentActor`.
|
|
82
|
+
*/
|
|
83
|
+
actor: string | null;
|
|
84
|
+
/**
|
|
85
|
+
* Guest mode: per-session identity (APRV-174), plus the narrowed tool list,
|
|
86
|
+
* the `mcp-guest-restricted` call-time refusal and the `wait` clamp that
|
|
87
|
+
* `./server.ts` applies (APRV-175).
|
|
88
|
+
*/
|
|
89
|
+
guest: boolean;
|
|
90
|
+
/** Interface to bind. Defaults to `127.0.0.1`; the CLI owns the widening decision. */
|
|
91
|
+
host?: string;
|
|
92
|
+
/** TCP port. `0` asks the kernel for an ephemeral one, which is what tests use. */
|
|
93
|
+
port: number;
|
|
94
|
+
/** Session lifecycle lines. The CLI passes stderr; stdout is never written to. */
|
|
95
|
+
notice?: (text: string) => void;
|
|
96
|
+
}
|
|
97
|
+
export interface McpHttpServer {
|
|
98
|
+
/** The interface actually bound. */
|
|
99
|
+
readonly host: string;
|
|
100
|
+
/** The port actually bound, resolved after an ephemeral request. */
|
|
101
|
+
readonly port: number;
|
|
102
|
+
/** Actors of the live sessions, in open order. Diagnostics and tests. */
|
|
103
|
+
sessionActors(): string[];
|
|
104
|
+
/** How many sessions this listener has opened, ever. */
|
|
105
|
+
lifetimeSessions(): number;
|
|
106
|
+
/** Close every session and the listener. Idempotent. */
|
|
107
|
+
close(): Promise<void>;
|
|
108
|
+
}
|
|
109
|
+
/**
|
|
110
|
+
* Start the HTTP MCP listener. Resolves once it is bound and its real port is
|
|
111
|
+
* known; rejects when the bind fails, so the CLI can report it and exit.
|
|
112
|
+
*/
|
|
113
|
+
export declare function serveApprovalMcpHttp(options: HttpServeOptions): Promise<McpHttpServer>;
|