open-multi-agent-kit 1.0.0 → 1.2.2
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/CHANGELOG.md +52 -1
- package/README.md +2 -2
- package/dist/approval-api.d.ts +5 -0
- package/dist/approval-api.d.ts.map +1 -0
- package/dist/approval-api.js +5 -0
- package/dist/approval-api.js.map +1 -0
- package/dist/cli/help.d.ts.map +1 -1
- package/dist/cli/help.js +1 -0
- package/dist/cli/help.js.map +1 -1
- package/dist/cli/session-picker.d.ts +2 -2
- package/dist/cli/session-picker.d.ts.map +1 -1
- package/dist/cli/session-picker.js.map +1 -1
- package/dist/commands/verified-run-cli.d.ts.map +1 -1
- package/dist/commands/verified-run-cli.js +69 -22
- package/dist/commands/verified-run-cli.js.map +1 -1
- package/dist/commands/verified-run-signal.d.ts +3 -0
- package/dist/commands/verified-run-signal.d.ts.map +1 -0
- package/dist/commands/verified-run-signal.js +15 -0
- package/dist/commands/verified-run-signal.js.map +1 -0
- package/dist/coordination/awareness.d.ts +32 -0
- package/dist/coordination/awareness.d.ts.map +1 -0
- package/dist/coordination/awareness.js +55 -0
- package/dist/coordination/awareness.js.map +1 -0
- package/dist/coordination/broker.d.ts +79 -0
- package/dist/coordination/broker.d.ts.map +1 -0
- package/dist/coordination/broker.js +202 -0
- package/dist/coordination/broker.js.map +1 -0
- package/dist/coordination/index.d.ts +16 -0
- package/dist/coordination/index.d.ts.map +1 -0
- package/dist/coordination/index.js +16 -0
- package/dist/coordination/index.js.map +1 -0
- package/dist/coordination/integration.d.ts +59 -0
- package/dist/coordination/integration.d.ts.map +1 -0
- package/dist/coordination/integration.js +126 -0
- package/dist/coordination/integration.js.map +1 -0
- package/dist/coordination/operation.d.ts +107 -0
- package/dist/coordination/operation.d.ts.map +1 -0
- package/dist/coordination/operation.js +231 -0
- package/dist/coordination/operation.js.map +1 -0
- package/dist/coordination/resource.d.ts +33 -0
- package/dist/coordination/resource.d.ts.map +1 -0
- package/dist/coordination/resource.js +95 -0
- package/dist/coordination/resource.js.map +1 -0
- package/dist/coordination/session.d.ts +74 -0
- package/dist/coordination/session.d.ts.map +1 -0
- package/dist/coordination/session.js +143 -0
- package/dist/coordination/session.js.map +1 -0
- package/dist/coordination/types.d.ts +68 -0
- package/dist/coordination/types.d.ts.map +1 -0
- package/dist/coordination/types.js +26 -0
- package/dist/coordination/types.js.map +1 -0
- package/dist/core/adaptorch-bridge.d.ts +1 -1
- package/dist/core/adaptorch-bridge.d.ts.map +1 -1
- package/dist/core/adaptorch-bridge.js +1 -1
- package/dist/core/adaptorch-bridge.js.map +1 -1
- package/dist/core/agent-session-runtime.d.ts.map +1 -1
- package/dist/core/agent-session-runtime.js +16 -16
- package/dist/core/agent-session-runtime.js.map +1 -1
- package/dist/core/agent-session.d.ts.map +1 -1
- package/dist/core/agent-session.js +35 -15
- package/dist/core/agent-session.js.map +1 -1
- package/dist/core/canonical-json.d.ts +3 -0
- package/dist/core/canonical-json.d.ts.map +1 -0
- package/dist/core/canonical-json.js +20 -0
- package/dist/core/canonical-json.js.map +1 -0
- package/dist/core/compaction/compaction.d.ts +7 -3
- package/dist/core/compaction/compaction.d.ts.map +1 -1
- package/dist/core/compaction/compaction.js +14 -29
- package/dist/core/compaction/compaction.js.map +1 -1
- package/dist/core/compaction/control-state.d.ts +41 -0
- package/dist/core/compaction/control-state.d.ts.map +1 -0
- package/dist/core/compaction/control-state.js +85 -0
- package/dist/core/compaction/control-state.js.map +1 -0
- package/dist/core/compaction/fallback.d.ts +71 -0
- package/dist/core/compaction/fallback.d.ts.map +1 -0
- package/dist/core/compaction/fallback.js +118 -0
- package/dist/core/compaction/fallback.js.map +1 -0
- package/dist/core/compaction/index.d.ts +2 -0
- package/dist/core/compaction/index.d.ts.map +1 -1
- package/dist/core/compaction/index.js +2 -0
- package/dist/core/compaction/index.js.map +1 -1
- package/dist/core/compaction/model-failover.d.ts +21 -0
- package/dist/core/compaction/model-failover.d.ts.map +1 -0
- package/dist/core/compaction/model-failover.js +46 -0
- package/dist/core/compaction/model-failover.js.map +1 -0
- package/dist/core/compaction/session-summary.d.ts +21 -0
- package/dist/core/compaction/session-summary.d.ts.map +1 -0
- package/dist/core/compaction/session-summary.js +27 -0
- package/dist/core/compaction/session-summary.js.map +1 -0
- package/dist/core/context-budget-headroom-candidates.d.ts +16 -1
- package/dist/core/context-budget-headroom-candidates.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-candidates.js +31 -13
- package/dist/core/context-budget-headroom-candidates.js.map +1 -1
- package/dist/core/context-budget-headroom-types.d.ts +7 -1
- package/dist/core/context-budget-headroom-types.d.ts.map +1 -1
- package/dist/core/context-budget-headroom-types.js +0 -1
- package/dist/core/context-budget-headroom-types.js.map +1 -1
- package/dist/core/context-budget-headroom.d.ts +10 -0
- package/dist/core/context-budget-headroom.d.ts.map +1 -1
- package/dist/core/context-budget-headroom.js +11 -2
- package/dist/core/context-budget-headroom.js.map +1 -1
- package/dist/core/context-budget-v2-global-pass.d.ts +21 -0
- package/dist/core/context-budget-v2-global-pass.d.ts.map +1 -0
- package/dist/core/context-budget-v2-global-pass.js +203 -0
- package/dist/core/context-budget-v2-global-pass.js.map +1 -0
- package/dist/core/context-budget-v2-planned-items.d.ts +12 -0
- package/dist/core/context-budget-v2-planned-items.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planned-items.js +21 -2
- package/dist/core/context-budget-v2-planned-items.js.map +1 -1
- package/dist/core/context-budget-v2-planner.d.ts.map +1 -1
- package/dist/core/context-budget-v2-planner.js +18 -19
- package/dist/core/context-budget-v2-planner.js.map +1 -1
- package/dist/core/context-budget-v2-scoring.d.ts +7 -1
- package/dist/core/context-budget-v2-scoring.d.ts.map +1 -1
- package/dist/core/context-budget-v2-scoring.js.map +1 -1
- package/dist/core/context-budget-v2-selection.d.ts +3 -0
- package/dist/core/context-budget-v2-selection.d.ts.map +1 -1
- package/dist/core/context-budget-v2-selection.js +6 -2
- package/dist/core/context-budget-v2-selection.js.map +1 -1
- package/dist/core/context-budget-v2-types.d.ts +6 -1
- package/dist/core/context-budget-v2-types.d.ts.map +1 -1
- package/dist/core/context-budget-v2-types.js +6 -1
- package/dist/core/context-budget-v2-types.js.map +1 -1
- package/dist/core/export-html/template.js +14 -0
- package/dist/core/extensions/index.d.ts +1 -1
- package/dist/core/extensions/index.d.ts.map +1 -1
- package/dist/core/extensions/index.js.map +1 -1
- package/dist/core/extensions/session-lifecycle-types.d.ts +14 -0
- package/dist/core/extensions/session-lifecycle-types.d.ts.map +1 -0
- package/dist/core/extensions/session-lifecycle-types.js +2 -0
- package/dist/core/extensions/session-lifecycle-types.js.map +1 -0
- package/dist/core/extensions/types.d.ts +4 -9
- package/dist/core/extensions/types.d.ts.map +1 -1
- package/dist/core/extensions/types.js.map +1 -1
- package/dist/core/http-dispatcher.d.ts.map +1 -1
- package/dist/core/http-dispatcher.js +10 -1
- package/dist/core/http-dispatcher.js.map +1 -1
- package/dist/core/keybindings.d.ts.map +1 -1
- package/dist/core/keybindings.js +3 -6
- package/dist/core/keybindings.js.map +1 -1
- package/dist/core/legacy-resource-policy.d.ts +7 -0
- package/dist/core/legacy-resource-policy.d.ts.map +1 -0
- package/dist/core/legacy-resource-policy.js +9 -0
- package/dist/core/legacy-resource-policy.js.map +1 -0
- package/dist/core/mcp/config.d.ts.map +1 -1
- package/dist/core/mcp/config.js +17 -3
- package/dist/core/mcp/config.js.map +1 -1
- package/dist/core/mcp/connection-queue.d.ts +12 -0
- package/dist/core/mcp/connection-queue.d.ts.map +1 -0
- package/dist/core/mcp/connection-queue.js +46 -0
- package/dist/core/mcp/connection-queue.js.map +1 -0
- package/dist/core/mcp/manager-runtime.d.ts +55 -0
- package/dist/core/mcp/manager-runtime.d.ts.map +1 -0
- package/dist/core/mcp/manager-runtime.js +66 -0
- package/dist/core/mcp/manager-runtime.js.map +1 -0
- package/dist/core/mcp/manager.d.ts +12 -68
- package/dist/core/mcp/manager.d.ts.map +1 -1
- package/dist/core/mcp/manager.js +33 -113
- package/dist/core/mcp/manager.js.map +1 -1
- package/dist/core/mcp/protocol.d.ts.map +1 -1
- package/dist/core/mcp/protocol.js +70 -40
- package/dist/core/mcp/protocol.js.map +1 -1
- package/dist/core/package-manager.d.ts +4 -0
- package/dist/core/package-manager.d.ts.map +1 -1
- package/dist/core/package-manager.js +59 -129
- package/dist/core/package-manager.js.map +1 -1
- package/dist/core/package-resource-patterns.d.ts +7 -0
- package/dist/core/package-resource-patterns.d.ts.map +1 -0
- package/dist/core/package-resource-patterns.js +99 -0
- package/dist/core/package-resource-patterns.js.map +1 -0
- package/dist/core/provider-default-models.d.ts +1 -0
- package/dist/core/provider-default-models.d.ts.map +1 -1
- package/dist/core/provider-default-models.js +1 -0
- package/dist/core/provider-default-models.js.map +1 -1
- package/dist/core/provider-display-names.d.ts.map +1 -1
- package/dist/core/provider-display-names.js +1 -0
- package/dist/core/provider-display-names.js.map +1 -1
- package/dist/core/provider-resilience.d.ts +9 -0
- package/dist/core/provider-resilience.d.ts.map +1 -1
- package/dist/core/provider-resilience.js +15 -0
- package/dist/core/provider-resilience.js.map +1 -1
- package/dist/core/reasoning-router-resolver.d.ts +7 -0
- package/dist/core/reasoning-router-resolver.d.ts.map +1 -1
- package/dist/core/reasoning-router-resolver.js +21 -3
- package/dist/core/reasoning-router-resolver.js.map +1 -1
- package/dist/core/reasoning-router-v4.d.ts +13 -7
- package/dist/core/reasoning-router-v4.d.ts.map +1 -1
- package/dist/core/reasoning-router-v4.js +8 -5
- package/dist/core/reasoning-router-v4.js.map +1 -1
- package/dist/core/resource-loader.d.ts.map +1 -1
- package/dist/core/resource-loader.js +4 -8
- package/dist/core/resource-loader.js.map +1 -1
- package/dist/core/run-execution-api.d.ts +8 -1
- package/dist/core/run-execution-api.d.ts.map +1 -1
- package/dist/core/run-execution-api.js +4 -0
- package/dist/core/run-execution-api.js.map +1 -1
- package/dist/core/run-journal.d.ts +1 -2
- package/dist/core/run-journal.d.ts.map +1 -1
- package/dist/core/run-journal.js +2 -19
- package/dist/core/run-journal.js.map +1 -1
- package/dist/core/session-compaction-service.d.ts +15 -0
- package/dist/core/session-compaction-service.d.ts.map +1 -1
- package/dist/core/session-compaction-service.js +17 -4
- package/dist/core/session-compaction-service.js.map +1 -1
- package/dist/core/session-listing.d.ts +51 -0
- package/dist/core/session-listing.d.ts.map +1 -0
- package/dist/core/session-listing.js +111 -0
- package/dist/core/session-listing.js.map +1 -0
- package/dist/core/session-manager.d.ts +12 -37
- package/dist/core/session-manager.d.ts.map +1 -1
- package/dist/core/session-manager.js +12 -118
- package/dist/core/session-manager.js.map +1 -1
- package/dist/core/session-message-text.d.ts +5 -0
- package/dist/core/session-message-text.d.ts.map +1 -0
- package/dist/core/session-message-text.js +9 -0
- package/dist/core/session-message-text.js.map +1 -0
- package/dist/core/skills-catalog-cache.d.ts +2 -0
- package/dist/core/skills-catalog-cache.d.ts.map +1 -1
- package/dist/core/skills-catalog-cache.js +71 -17
- package/dist/core/skills-catalog-cache.js.map +1 -1
- package/dist/core/todo-runtime-state.d.ts +12 -0
- package/dist/core/todo-runtime-state.d.ts.map +1 -1
- package/dist/core/todo-runtime-state.js +23 -0
- package/dist/core/todo-runtime-state.js.map +1 -1
- package/dist/core/tools/read.d.ts.map +1 -1
- package/dist/core/tools/read.js +1 -1
- package/dist/core/tools/read.js.map +1 -1
- package/dist/core/verified-run/authority-clock.d.ts +3 -0
- package/dist/core/verified-run/authority-clock.d.ts.map +1 -0
- package/dist/core/verified-run/authority-clock.js +25 -0
- package/dist/core/verified-run/authority-clock.js.map +1 -0
- package/dist/core/verified-run/authority-errors.d.ts +10 -0
- package/dist/core/verified-run/authority-errors.d.ts.map +1 -0
- package/dist/core/verified-run/authority-errors.js +17 -0
- package/dist/core/verified-run/authority-errors.js.map +1 -0
- package/dist/core/verified-run/authority-events.d.ts +126 -0
- package/dist/core/verified-run/authority-events.d.ts.map +1 -0
- package/dist/core/verified-run/authority-events.js +482 -0
- package/dist/core/verified-run/authority-events.js.map +1 -0
- package/dist/core/verified-run/authority-journal.d.ts +27 -0
- package/dist/core/verified-run/authority-journal.d.ts.map +1 -0
- package/dist/core/verified-run/authority-journal.js +83 -0
- package/dist/core/verified-run/authority-journal.js.map +1 -0
- package/dist/core/verified-run/authority-meaning.d.ts +13 -0
- package/dist/core/verified-run/authority-meaning.d.ts.map +1 -0
- package/dist/core/verified-run/authority-meaning.js +40 -0
- package/dist/core/verified-run/authority-meaning.js.map +1 -0
- package/dist/core/verified-run/authority-runtime.d.ts +82 -0
- package/dist/core/verified-run/authority-runtime.d.ts.map +1 -0
- package/dist/core/verified-run/authority-runtime.js +169 -0
- package/dist/core/verified-run/authority-runtime.js.map +1 -0
- package/dist/core/verified-run/authority-store.d.ts +204 -0
- package/dist/core/verified-run/authority-store.d.ts.map +1 -0
- package/dist/core/verified-run/authority-store.js +852 -0
- package/dist/core/verified-run/authority-store.js.map +1 -0
- package/dist/core/verified-run/broker.d.ts +8 -1
- package/dist/core/verified-run/broker.d.ts.map +1 -1
- package/dist/core/verified-run/broker.js +94 -90
- package/dist/core/verified-run/broker.js.map +1 -1
- package/dist/core/verified-run/candidate-policy.d.ts +10 -0
- package/dist/core/verified-run/candidate-policy.d.ts.map +1 -0
- package/dist/core/verified-run/candidate-policy.js +33 -0
- package/dist/core/verified-run/candidate-policy.js.map +1 -0
- package/dist/core/verified-run/candidate.d.ts.map +1 -1
- package/dist/core/verified-run/candidate.js +5 -10
- package/dist/core/verified-run/candidate.js.map +1 -1
- package/dist/core/verified-run/coordinator.d.ts +35 -17
- package/dist/core/verified-run/coordinator.d.ts.map +1 -1
- package/dist/core/verified-run/coordinator.js +111 -57
- package/dist/core/verified-run/coordinator.js.map +1 -1
- package/dist/core/verified-run/dag-phase.d.ts.map +1 -1
- package/dist/core/verified-run/dag-phase.js +1 -1
- package/dist/core/verified-run/dag-phase.js.map +1 -1
- package/dist/core/verified-run/dag-recovery.d.ts +5 -1
- package/dist/core/verified-run/dag-recovery.d.ts.map +1 -1
- package/dist/core/verified-run/dag-recovery.js +10 -4
- package/dist/core/verified-run/dag-recovery.js.map +1 -1
- package/dist/core/verified-run/event-parser.d.ts.map +1 -1
- package/dist/core/verified-run/event-parser.js +33 -0
- package/dist/core/verified-run/event-parser.js.map +1 -1
- package/dist/core/verified-run/evidence-read-projection.d.ts +4 -0
- package/dist/core/verified-run/evidence-read-projection.d.ts.map +1 -0
- package/dist/core/verified-run/evidence-read-projection.js +27 -0
- package/dist/core/verified-run/evidence-read-projection.js.map +1 -0
- package/dist/core/verified-run/evidence.d.ts +12 -1
- package/dist/core/verified-run/evidence.d.ts.map +1 -1
- package/dist/core/verified-run/evidence.js +51 -2
- package/dist/core/verified-run/evidence.js.map +1 -1
- package/dist/core/verified-run/git-candidate-preflight.d.ts +4 -0
- package/dist/core/verified-run/git-candidate-preflight.d.ts.map +1 -0
- package/dist/core/verified-run/git-candidate-preflight.js +34 -0
- package/dist/core/verified-run/git-candidate-preflight.js.map +1 -0
- package/dist/core/verified-run/git-effect-supervisor.d.ts +24 -0
- package/dist/core/verified-run/git-effect-supervisor.d.ts.map +1 -0
- package/dist/core/verified-run/git-effect-supervisor.js +174 -0
- package/dist/core/verified-run/git-effect-supervisor.js.map +1 -0
- package/dist/core/verified-run/git-execution.d.ts +27 -0
- package/dist/core/verified-run/git-execution.d.ts.map +1 -0
- package/dist/core/verified-run/git-execution.js +118 -0
- package/dist/core/verified-run/git-execution.js.map +1 -0
- package/dist/core/verified-run/git-plumbing.d.ts +37 -0
- package/dist/core/verified-run/git-plumbing.d.ts.map +1 -0
- package/dist/core/verified-run/git-plumbing.js +171 -0
- package/dist/core/verified-run/git-plumbing.js.map +1 -0
- package/dist/core/verified-run/git-publication-worker.d.ts +2 -0
- package/dist/core/verified-run/git-publication-worker.d.ts.map +1 -0
- package/dist/core/verified-run/git-publication-worker.js +54 -0
- package/dist/core/verified-run/git-publication-worker.js.map +1 -0
- package/dist/core/verified-run/git-sandbox-layout.d.ts +4 -0
- package/dist/core/verified-run/git-sandbox-layout.d.ts.map +1 -0
- package/dist/core/verified-run/git-sandbox-layout.js +29 -0
- package/dist/core/verified-run/git-sandbox-layout.js.map +1 -0
- package/dist/core/verified-run/git-worker-protocol.d.ts +19 -0
- package/dist/core/verified-run/git-worker-protocol.d.ts.map +1 -0
- package/dist/core/verified-run/git-worker-protocol.js +109 -0
- package/dist/core/verified-run/git-worker-protocol.js.map +1 -0
- package/dist/core/verified-run/git-worker-runtime.d.ts +19 -0
- package/dist/core/verified-run/git-worker-runtime.d.ts.map +1 -0
- package/dist/core/verified-run/git-worker-runtime.js +74 -0
- package/dist/core/verified-run/git-worker-runtime.js.map +1 -0
- package/dist/core/verified-run/journal.d.ts +2 -3
- package/dist/core/verified-run/journal.d.ts.map +1 -1
- package/dist/core/verified-run/journal.js.map +1 -1
- package/dist/core/verified-run/namespace-identity.d.ts.map +1 -1
- package/dist/core/verified-run/namespace-identity.js +1 -1
- package/dist/core/verified-run/namespace-identity.js.map +1 -1
- package/dist/core/verified-run/owned-execution.d.ts +10 -1
- package/dist/core/verified-run/owned-execution.d.ts.map +1 -1
- package/dist/core/verified-run/owned-execution.js +124 -31
- package/dist/core/verified-run/owned-execution.js.map +1 -1
- package/dist/core/verified-run/phase-context.d.ts +2 -0
- package/dist/core/verified-run/phase-context.d.ts.map +1 -1
- package/dist/core/verified-run/phase-context.js.map +1 -1
- package/dist/core/verified-run/projection.d.ts.map +1 -1
- package/dist/core/verified-run/projection.js +51 -1
- package/dist/core/verified-run/projection.js.map +1 -1
- package/dist/core/verified-run/publish-preflight.d.ts +12 -0
- package/dist/core/verified-run/publish-preflight.d.ts.map +1 -0
- package/dist/core/verified-run/publish-preflight.js +38 -0
- package/dist/core/verified-run/publish-preflight.js.map +1 -0
- package/dist/core/verified-run/publish-start.d.ts +5 -0
- package/dist/core/verified-run/publish-start.d.ts.map +1 -0
- package/dist/core/verified-run/publish-start.js +7 -0
- package/dist/core/verified-run/publish-start.js.map +1 -0
- package/dist/core/verified-run/recovery-projection.d.ts.map +1 -1
- package/dist/core/verified-run/recovery-projection.js +5 -0
- package/dist/core/verified-run/recovery-projection.js.map +1 -1
- package/dist/core/verified-run/recovery.d.ts +5 -1
- package/dist/core/verified-run/recovery.d.ts.map +1 -1
- package/dist/core/verified-run/recovery.js +10 -4
- package/dist/core/verified-run/recovery.js.map +1 -1
- package/dist/core/verified-run/run-plan.d.ts +17 -0
- package/dist/core/verified-run/run-plan.d.ts.map +1 -0
- package/dist/core/verified-run/run-plan.js +18 -0
- package/dist/core/verified-run/run-plan.js.map +1 -0
- package/dist/core/verified-run/run-publish-owned.d.ts +6 -0
- package/dist/core/verified-run/run-publish-owned.d.ts.map +1 -0
- package/dist/core/verified-run/run-publish-owned.js +199 -0
- package/dist/core/verified-run/run-publish-owned.js.map +1 -0
- package/dist/core/verified-run/run-publish.d.ts +19 -0
- package/dist/core/verified-run/run-publish.d.ts.map +1 -0
- package/dist/core/verified-run/run-publish.js +210 -0
- package/dist/core/verified-run/run-publish.js.map +1 -0
- package/dist/core/verified-run/run-status-owned.d.ts +4 -0
- package/dist/core/verified-run/run-status-owned.d.ts.map +1 -0
- package/dist/core/verified-run/run-status-owned.js +14 -0
- package/dist/core/verified-run/run-status-owned.js.map +1 -0
- package/dist/core/verified-run/run-status.d.ts +133 -0
- package/dist/core/verified-run/run-status.d.ts.map +1 -0
- package/dist/core/verified-run/run-status.js +193 -0
- package/dist/core/verified-run/run-status.js.map +1 -0
- package/dist/core/verified-run/run-types.d.ts +31 -0
- package/dist/core/verified-run/run-types.d.ts.map +1 -1
- package/dist/core/verified-run/run-types.js.map +1 -1
- package/dist/core/verified-run/storage.d.ts.map +1 -1
- package/dist/core/verified-run/storage.js +1 -1
- package/dist/core/verified-run/storage.js.map +1 -1
- package/dist/core/verified-run/supervisor-adapter.d.ts +77 -0
- package/dist/core/verified-run/supervisor-adapter.d.ts.map +1 -0
- package/dist/core/verified-run/supervisor-adapter.js +164 -0
- package/dist/core/verified-run/supervisor-adapter.js.map +1 -0
- package/dist/core/verified-run/verification-phase.d.ts.map +1 -1
- package/dist/core/verified-run/verification-phase.js +1 -1
- package/dist/core/verified-run/verification-phase.js.map +1 -1
- package/dist/core/verified-run/writer-phase.d.ts.map +1 -1
- package/dist/core/verified-run/writer-phase.js +1 -0
- package/dist/core/verified-run/writer-phase.js.map +1 -1
- package/dist/core/verified-run/writer-recovery.d.ts +2 -0
- package/dist/core/verified-run/writer-recovery.d.ts.map +1 -1
- package/dist/core/verified-run/writer-recovery.js +1 -0
- package/dist/core/verified-run/writer-recovery.js.map +1 -1
- package/dist/core/workload-shard-execution-types.d.ts +4 -1
- package/dist/core/workload-shard-execution-types.d.ts.map +1 -1
- package/dist/core/workload-shard-execution-types.js.map +1 -1
- package/dist/core/workload-shard-executor.d.ts +2 -2
- package/dist/core/workload-shard-executor.d.ts.map +1 -1
- package/dist/core/workload-shard-executor.js +16 -37
- package/dist/core/workload-shard-executor.js.map +1 -1
- package/dist/core/workload-shard-frontier.d.ts +5 -0
- package/dist/core/workload-shard-frontier.d.ts.map +1 -0
- package/dist/core/workload-shard-frontier.js +47 -0
- package/dist/core/workload-shard-frontier.js.map +1 -0
- package/dist/core/workload-shard-runner.d.ts.map +1 -1
- package/dist/core/workload-shard-runner.js +28 -17
- package/dist/core/workload-shard-runner.js.map +1 -1
- package/dist/index.d.ts +4 -5
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -4
- package/dist/index.js.map +1 -1
- package/dist/main.d.ts.map +1 -1
- package/dist/main.js +2 -1
- package/dist/main.js.map +1 -1
- package/dist/metacognition/bridge-result.d.ts +148 -0
- package/dist/metacognition/bridge-result.d.ts.map +1 -0
- package/dist/metacognition/bridge-result.js +46 -0
- package/dist/metacognition/bridge-result.js.map +1 -0
- package/dist/metacognition/calibration-selective.d.ts +78 -0
- package/dist/metacognition/calibration-selective.d.ts.map +1 -0
- package/dist/metacognition/calibration-selective.js +167 -0
- package/dist/metacognition/calibration-selective.js.map +1 -0
- package/dist/metacognition/calibration.d.ts +62 -0
- package/dist/metacognition/calibration.d.ts.map +1 -0
- package/dist/metacognition/calibration.js +122 -0
- package/dist/metacognition/calibration.js.map +1 -0
- package/dist/metacognition/checkpoint.d.ts +60 -0
- package/dist/metacognition/checkpoint.d.ts.map +1 -0
- package/dist/metacognition/checkpoint.js +57 -0
- package/dist/metacognition/checkpoint.js.map +1 -0
- package/dist/metacognition/context7.d.ts +48 -0
- package/dist/metacognition/context7.d.ts.map +1 -0
- package/dist/metacognition/context7.js +154 -0
- package/dist/metacognition/context7.js.map +1 -0
- package/dist/metacognition/decision.d.ts +44 -0
- package/dist/metacognition/decision.d.ts.map +1 -0
- package/dist/metacognition/decision.js +111 -0
- package/dist/metacognition/decision.js.map +1 -0
- package/dist/metacognition/evaluation.d.ts +73 -0
- package/dist/metacognition/evaluation.d.ts.map +1 -0
- package/dist/metacognition/evaluation.js +97 -0
- package/dist/metacognition/evaluation.js.map +1 -0
- package/dist/metacognition/index.d.ts +32 -0
- package/dist/metacognition/index.d.ts.map +1 -0
- package/dist/metacognition/index.js +32 -0
- package/dist/metacognition/index.js.map +1 -0
- package/dist/metacognition/knowledge-action.d.ts +43 -0
- package/dist/metacognition/knowledge-action.d.ts.map +1 -0
- package/dist/metacognition/knowledge-action.js +60 -0
- package/dist/metacognition/knowledge-action.js.map +1 -0
- package/dist/metacognition/knowledge.d.ts +84 -0
- package/dist/metacognition/knowledge.d.ts.map +1 -0
- package/dist/metacognition/knowledge.js +165 -0
- package/dist/metacognition/knowledge.js.map +1 -0
- package/dist/metacognition/obligations.d.ts +82 -0
- package/dist/metacognition/obligations.d.ts.map +1 -0
- package/dist/metacognition/obligations.js +139 -0
- package/dist/metacognition/obligations.js.map +1 -0
- package/dist/metacognition/observation-validity.d.ts +83 -0
- package/dist/metacognition/observation-validity.d.ts.map +1 -0
- package/dist/metacognition/observation-validity.js +118 -0
- package/dist/metacognition/observation-validity.js.map +1 -0
- package/dist/metacognition/observe.d.ts +45 -0
- package/dist/metacognition/observe.d.ts.map +1 -0
- package/dist/metacognition/observe.js +59 -0
- package/dist/metacognition/observe.js.map +1 -0
- package/dist/metacognition/policy.d.ts +53 -0
- package/dist/metacognition/policy.d.ts.map +1 -0
- package/dist/metacognition/policy.js +155 -0
- package/dist/metacognition/policy.js.map +1 -0
- package/dist/metacognition/predictions.d.ts +78 -0
- package/dist/metacognition/predictions.d.ts.map +1 -0
- package/dist/metacognition/predictions.js +181 -0
- package/dist/metacognition/predictions.js.map +1 -0
- package/dist/metacognition/retrieval.d.ts +53 -0
- package/dist/metacognition/retrieval.d.ts.map +1 -0
- package/dist/metacognition/retrieval.js +170 -0
- package/dist/metacognition/retrieval.js.map +1 -0
- package/dist/metacognition/risk.d.ts +48 -0
- package/dist/metacognition/risk.d.ts.map +1 -0
- package/dist/metacognition/risk.js +179 -0
- package/dist/metacognition/risk.js.map +1 -0
- package/dist/metacognition/route-economics.d.ts +95 -0
- package/dist/metacognition/route-economics.d.ts.map +1 -0
- package/dist/metacognition/route-economics.js +110 -0
- package/dist/metacognition/route-economics.js.map +1 -0
- package/dist/metacognition/runtime-bridge.d.ts +81 -0
- package/dist/metacognition/runtime-bridge.d.ts.map +1 -0
- package/dist/metacognition/runtime-bridge.js +458 -0
- package/dist/metacognition/runtime-bridge.js.map +1 -0
- package/dist/metacognition/skills.d.ts +42 -0
- package/dist/metacognition/skills.d.ts.map +1 -0
- package/dist/metacognition/skills.js +220 -0
- package/dist/metacognition/skills.js.map +1 -0
- package/dist/metacognition/state.d.ts +110 -0
- package/dist/metacognition/state.d.ts.map +1 -0
- package/dist/metacognition/state.js +52 -0
- package/dist/metacognition/state.js.map +1 -0
- package/dist/metacognition/validation.d.ts +19 -0
- package/dist/metacognition/validation.d.ts.map +1 -0
- package/dist/metacognition/validation.js +58 -0
- package/dist/metacognition/validation.js.map +1 -0
- package/dist/metacognition/verification.d.ts +93 -0
- package/dist/metacognition/verification.d.ts.map +1 -0
- package/dist/metacognition/verification.js +132 -0
- package/dist/metacognition/verification.js.map +1 -0
- package/dist/metacognition/verifier.d.ts +49 -0
- package/dist/metacognition/verifier.d.ts.map +1 -0
- package/dist/metacognition/verifier.js +88 -0
- package/dist/metacognition/verifier.js.map +1 -0
- package/dist/modes/interactive/components/assistant-message.d.ts +2 -0
- package/dist/modes/interactive/components/assistant-message.d.ts.map +1 -1
- package/dist/modes/interactive/components/assistant-message.js +42 -26
- package/dist/modes/interactive/components/assistant-message.js.map +1 -1
- package/dist/modes/interactive/components/chat-container.d.ts +7 -0
- package/dist/modes/interactive/components/chat-container.d.ts.map +1 -0
- package/dist/modes/interactive/components/chat-container.js +14 -0
- package/dist/modes/interactive/components/chat-container.js.map +1 -0
- package/dist/modes/interactive/components/dynamic-border.d.ts.map +1 -1
- package/dist/modes/interactive/components/dynamic-border.js +4 -2
- package/dist/modes/interactive/components/dynamic-border.js.map +1 -1
- package/dist/modes/interactive/components/login-dialog.d.ts.map +1 -1
- package/dist/modes/interactive/components/login-dialog.js +0 -1
- package/dist/modes/interactive/components/login-dialog.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-async-search.d.ts +33 -0
- package/dist/modes/interactive/components/session-selector-async-search.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-async-search.js +109 -0
- package/dist/modes/interactive/components/session-selector-async-search.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-loaders.d.ts +6 -0
- package/dist/modes/interactive/components/session-selector-loaders.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-loaders.js +9 -0
- package/dist/modes/interactive/components/session-selector-loaders.js.map +1 -0
- package/dist/modes/interactive/components/session-selector-search.d.ts +1 -1
- package/dist/modes/interactive/components/session-selector-search.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector-search.js.map +1 -1
- package/dist/modes/interactive/components/session-selector-tree.d.ts +16 -0
- package/dist/modes/interactive/components/session-selector-tree.d.ts.map +1 -0
- package/dist/modes/interactive/components/session-selector-tree.js +46 -0
- package/dist/modes/interactive/components/session-selector-tree.js.map +1 -0
- package/dist/modes/interactive/components/session-selector.d.ts +6 -1
- package/dist/modes/interactive/components/session-selector.d.ts.map +1 -1
- package/dist/modes/interactive/components/session-selector.js +36 -76
- package/dist/modes/interactive/components/session-selector.js.map +1 -1
- package/dist/modes/interactive/components/tool-execution-images.d.ts +32 -0
- package/dist/modes/interactive/components/tool-execution-images.d.ts.map +1 -0
- package/dist/modes/interactive/components/tool-execution-images.js +144 -0
- package/dist/modes/interactive/components/tool-execution-images.js.map +1 -0
- package/dist/modes/interactive/components/tool-execution.d.ts +3 -4
- package/dist/modes/interactive/components/tool-execution.d.ts.map +1 -1
- package/dist/modes/interactive/components/tool-execution.js +22 -71
- package/dist/modes/interactive/components/tool-execution.js.map +1 -1
- package/dist/modes/interactive/interactive-mode.d.ts.map +1 -1
- package/dist/modes/interactive/interactive-mode.js +7 -9
- package/dist/modes/interactive/interactive-mode.js.map +1 -1
- package/dist/modes/interactive/tui-diagnostics.d.ts +8 -4
- package/dist/modes/interactive/tui-diagnostics.d.ts.map +1 -1
- package/dist/modes/interactive/tui-diagnostics.js +35 -1
- package/dist/modes/interactive/tui-diagnostics.js.map +1 -1
- package/dist/modes/rpc/rpc-mode.d.ts.map +1 -1
- package/dist/modes/rpc/rpc-mode.js +14 -17
- package/dist/modes/rpc/rpc-mode.js.map +1 -1
- package/dist/modes/rpc/rpc-response.d.ts +5 -0
- package/dist/modes/rpc/rpc-response.d.ts.map +1 -0
- package/dist/modes/rpc/rpc-response.js +17 -0
- package/dist/modes/rpc/rpc-response.js.map +1 -0
- package/dist/observation/identity.d.ts +14 -0
- package/dist/observation/identity.d.ts.map +1 -0
- package/dist/observation/identity.js +29 -0
- package/dist/observation/identity.js.map +1 -0
- package/dist/observation/index.d.ts +13 -0
- package/dist/observation/index.d.ts.map +1 -0
- package/dist/observation/index.js +13 -0
- package/dist/observation/index.js.map +1 -0
- package/dist/observation/observe-mode.d.ts +46 -0
- package/dist/observation/observe-mode.d.ts.map +1 -0
- package/dist/observation/observe-mode.js +83 -0
- package/dist/observation/observe-mode.js.map +1 -0
- package/dist/observation/store.d.ts +53 -0
- package/dist/observation/store.d.ts.map +1 -0
- package/dist/observation/store.js +126 -0
- package/dist/observation/store.js.map +1 -0
- package/dist/observation/types.d.ts +72 -0
- package/dist/observation/types.d.ts.map +1 -0
- package/dist/observation/types.js +9 -0
- package/dist/observation/types.js.map +1 -0
- package/dist/observation/view.d.ts +39 -0
- package/dist/observation/view.d.ts.map +1 -0
- package/dist/observation/view.js +173 -0
- package/dist/observation/view.js.map +1 -0
- package/dist/utils/exif-orientation.d.ts.map +1 -1
- package/dist/utils/exif-orientation.js +2 -3
- package/dist/utils/exif-orientation.js.map +1 -1
- package/dist/utils/tools-manager.d.ts.map +1 -1
- package/dist/utils/tools-manager.js +3 -5
- package/dist/utils/tools-manager.js.map +1 -1
- package/docs/adaptorch-preview-spec.md +7 -7
- package/docs/atomic-commit-planning.md +69 -0
- package/docs/compaction.md +26 -1
- package/docs/extensions.md +14 -0
- package/docs/mcp.md +22 -0
- package/docs/metacognition.md +130 -0
- package/docs/model-catalog-refresh.md +218 -1
- package/docs/models.md +1 -1
- package/docs/providers.md +53 -0
- package/docs/runtime-algorithms.md +156 -7
- package/docs/session-format.md +8 -0
- package/docs/sessions.md +19 -0
- package/docs/skills.md +19 -0
- package/docs/terminal-setup.md +15 -0
- package/docs/tui.md +41 -0
- package/docs/verified-run-safety.md +75 -0
- package/examples/extensions/custom-provider-anthropic/index.ts +1 -1
- package/examples/extensions/custom-provider-anthropic/package-lock.json +2 -2
- package/examples/extensions/custom-provider-anthropic/package.json +1 -1
- package/examples/extensions/custom-provider-gitlab-duo/package.json +1 -1
- package/examples/extensions/doom-overlay/wad-finder.ts +7 -3
- package/examples/extensions/gondolin/package-lock.json +2 -2
- package/examples/extensions/gondolin/package.json +1 -1
- package/examples/extensions/sandbox/package-lock.json +2 -2
- package/examples/extensions/sandbox/package.json +1 -1
- package/examples/extensions/with-deps/package-lock.json +2 -2
- package/examples/extensions/with-deps/package.json +1 -1
- package/npm-shrinkwrap.json +18 -18
- package/package.json +6 -8
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/evidence.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,KAAK,iBAAiB,EAAiB,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EAAE,KAAK,gBAAgB,EAA2C,MAAM,uBAAuB,CAAC;AACvG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAa9D,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,IAAI,GAAG,QAAQ,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;CAC9C;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGrD;AAQD,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE;IACT,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC7C,GACC;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAuBzD;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,MAAM,GAAG,mBAAmB,CAoEnH","sourcesContent":["import { createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { RunContract } from \"omk-protocol\";\nimport type { EvidenceReceipt } from \"../../types/evidence.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport { type CandidateManifest, loadCandidate } from \"./candidate.ts\";\nimport { readCheckReceipts } from \"./check-receipt.ts\";\nimport { type CheckObservation, closesRunClaims, parseCheckObservations } from \"./evidence-binding.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { digestObject, publishBytes, publishObject, readJson, readRegularFile, VerifiedRunError } from \"./storage.ts\";\n\nexport type { CheckObservation } from \"./evidence-binding.ts\";\n\ninterface Attestation {\n\treadonly version: 1 | 2 | 3;\n\treadonly runId: string;\n\treadonly generation: number;\n\treadonly contractDigest: string;\n\treadonly candidateDigest: string;\n\treadonly environmentDigest: string;\n\treadonly verifierDigest: string;\n\treadonly checks: readonly CheckObservation[];\n\treadonly verified: boolean;\n}\nexport interface VerifiedRunEvidence {\n\treadonly candidateDigest: string;\n\treadonly manifest: CandidateManifest;\n\treadonly receiptDigest: string;\n\treadonly verified: boolean;\n\treadonly checks: readonly CheckObservation[];\n\treadonly receiptFormat: \"v3\" | \"legacy\";\n\treadonly receipts: readonly EvidenceReceipt[];\n}\n\nexport function createRunIssuer(runPath: string): void {\n\t// Recovery must never replace a missing key and re-sign old evidence.\n\tpublishBytes(join(runPath, \"issuer.key\"), randomBytes(32));\n}\n\nfunction tag(runPath: string, receipt: unknown): Buffer {\n\tconst key = readRegularFile(join(runPath, \"issuer.key\"), 32);\n\tif (key.length !== 32) throw new VerifiedRunError(\"integrity\");\n\treturn createHmac(\"sha256\", key).update(\"omk.verified-run.attestation.v1\\0\").update(canonicalJson(receipt)).digest();\n}\n\nexport function issueRunEvidence(\n\trunPath: string,\n\tcontract: RunContract,\n\tmaterial: {\n\t\treadonly generation: number;\n\t\treadonly candidateDigest: string;\n\t\treadonly environmentDigest: string;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): { readonly digest: string; readonly verified: boolean } {\n\tconst checks = parseCheckObservations(material.checks, true);\n\tconst candidate = loadCandidate(runPath, material.candidateDigest, contract.budget);\n\treadCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks });\n\tconst receipt: Attestation = {\n\t\tversion: 3,\n\t\trunId: contract.runId,\n\t\tgeneration: material.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest: material.candidateDigest,\n\t\tenvironmentDigest: material.environmentDigest,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified: closesRunClaims(contract, {\n\t\t\tcandidate: material.candidateDigest,\n\t\t\tenvironment: material.environmentDigest,\n\t\t\tchecks,\n\t\t}),\n\t};\n\tconst envelope = { receipt, authenticationTag: tag(runPath, receipt).toString(\"hex\") };\n\tconst digest = digestObject(envelope);\n\tpublishObject(join(runPath, \"attestations\", `${digest}.json`), envelope);\n\treturn { digest, verified: receipt.verified };\n}\n\nexport function readRunEvidence(runPath: string, journal: JournalSnapshot, environment: string): VerifiedRunEvidence {\n\tconst first = journal.records[0]?.event;\n\tconst { candidateDigest, receiptDigest } = journal.state;\n\tif (first?.kind !== \"created\" || !candidateDigest || !receiptDigest) throw new VerifiedRunError(\"evidence_missing\");\n\tconst raw = readJson(join(runPath, \"attestations\", `${receiptDigest}.json`));\n\tif (\n\t\tdigestObject(raw) !== receiptDigest ||\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"receipt\" in raw) ||\n\t\t!(\"authenticationTag\" in raw) ||\n\t\ttypeof raw.authenticationTag !== \"string\" ||\n\t\t!/^[a-f0-9]{64}$/.test(raw.authenticationTag) ||\n\t\t!timingSafeEqual(tag(runPath, raw.receipt), Buffer.from(raw.authenticationTag, \"hex\"))\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst receipt = raw.receipt;\n\tif (\n\t\ttypeof receipt !== \"object\" ||\n\t\treceipt === null ||\n\t\t!(\"checks\" in receipt) ||\n\t\t!(\"version\" in receipt) ||\n\t\t(receipt.version !== 1 && receipt.version !== 2 && receipt.version !== 3)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst checks = parseCheckObservations(receipt.checks, receipt.version !== 1);\n\tconst contract = first.contract;\n\tconst dispatches = journal.records.flatMap(({ event, generation }) =>\n\t\tgeneration === journal.state.generation && event.kind === \"dispatch\" && event.role === \"verifier\" ? [event] : [],\n\t);\n\tif (\n\t\tchecks.length !== contract.checks.length ||\n\t\tchecks.length !== dispatches.length ||\n\t\tnew Set(checks.map((check) => check.claimId)).size !== checks.length ||\n\t\tchecks.some(\n\t\t\t(check) =>\n\t\t\t\t!dispatches.some((event) => event.executionId === check.executionId && event.claimId === check.claimId),\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst verified = closesRunClaims(contract, { candidate: candidateDigest, environment, checks });\n\tconst expected: Attestation = {\n\t\tversion: receipt.version,\n\t\trunId: contract.runId,\n\t\tgeneration: journal.state.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest,\n\t\tenvironmentDigest: environment,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified,\n\t};\n\tif (canonicalJson(receipt) !== canonicalJson(expected) || verified !== (journal.state.verification === \"verified\"))\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst candidate = loadCandidate(runPath, candidateDigest, contract.budget);\n\tconst receipts =\n\t\treceipt.version !== 1\n\t\t\t? readCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks })\n\t\t\t: Object.freeze([]);\n\treturn Object.freeze({\n\t\tcandidateDigest,\n\t\tmanifest: candidate.manifest,\n\t\treceiptDigest,\n\t\tverified,\n\t\tchecks,\n\t\treceiptFormat: receipt.version !== 1 ? \"v3\" : \"legacy\",\n\t\treceipts,\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"evidence.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/evidence.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAChD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,yBAAyB,CAAC;AAE/D,OAAO,EAAE,KAAK,iBAAiB,EAAiB,MAAM,gBAAgB,CAAC;AAEvE,OAAO,EAAE,KAAK,gBAAgB,EAA2C,MAAM,uBAAuB,CAAC;AACvG,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,cAAc,CAAC;AAGpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,uBAAuB,CAAC;AAa9D,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,QAAQ,EAAE,iBAAiB,CAAC;IACrC,QAAQ,CAAC,aAAa,EAAE,MAAM,CAAC;IAC/B,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;IAC7C,QAAQ,CAAC,aAAa,EAAE,IAAI,GAAG,QAAQ,CAAC;IACxC,QAAQ,CAAC,QAAQ,EAAE,SAAS,eAAe,EAAE,CAAC;IAC9C,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;CACnC;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAGrD;AAQD,wBAAgB,gBAAgB,CAC/B,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,WAAW,EACrB,QAAQ,EAAE;IACT,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,eAAe,EAAE,MAAM,CAAC;IACjC,QAAQ,CAAC,iBAAiB,EAAE,MAAM,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,SAAS,gBAAgB,EAAE,CAAC;CAC7C,GACC;IAAE,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,OAAO,CAAA;CAAE,CAuBzD;AAED,MAAM,WAAW,YAAY;IAC5B,QAAQ,CAAC,YAAY,EAAE,OAAO,GAAG,SAAS,GAAG,cAAc,CAAC;IAC5D,QAAQ,CAAC,YAAY,EAAE,QAAQ,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC1D,QAAQ,CAAC,6BAA6B,EAAE,UAAU,GAAG,WAAW,GAAG,aAAa,GAAG,SAAS,CAAC;IAC7F,QAAQ,CAAC,QAAQ,EAAE,mBAAmB,GAAG,IAAI,CAAC;CAC9C;AAED,2FAA2F;AAC3F,wBAAgB,oBAAoB,CACnC,OAAO,EAAE,MAAM,EACf,OAAO,EAAE,eAAe,EACxB,kBAAkB,CAAC,EAAE,MAAM,GAAG;IAAE,QAAQ,CAAC,MAAM,EAAE,aAAa,GAAG,SAAS,CAAA;CAAE,GAC1E,YAAY,CAqCd;AAED,wBAAgB,eAAe,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,eAAe,EAAE,WAAW,CAAC,EAAE,MAAM,GAAG,mBAAmB,CAgFpH","sourcesContent":["import { createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { RunContract } from \"omk-protocol\";\nimport type { EvidenceReceipt } from \"../../types/evidence.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport { type CandidateManifest, loadCandidate } from \"./candidate.ts\";\nimport { readCheckReceipts } from \"./check-receipt.ts\";\nimport { type CheckObservation, closesRunClaims, parseCheckObservations } from \"./evidence-binding.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { digestObject, publishBytes, publishObject, readJson, readRegularFile, VerifiedRunError } from \"./storage.ts\";\n\nexport type { CheckObservation } from \"./evidence-binding.ts\";\n\ninterface Attestation {\n\treadonly version: 1 | 2 | 3;\n\treadonly runId: string;\n\treadonly generation: number;\n\treadonly contractDigest: string;\n\treadonly candidateDigest: string;\n\treadonly environmentDigest: string;\n\treadonly verifierDigest: string;\n\treadonly checks: readonly CheckObservation[];\n\treadonly verified: boolean;\n}\nexport interface VerifiedRunEvidence {\n\treadonly candidateDigest: string;\n\treadonly manifest: CandidateManifest;\n\treadonly receiptDigest: string;\n\treadonly verified: boolean;\n\treadonly checks: readonly CheckObservation[];\n\treadonly receiptFormat: \"v3\" | \"legacy\";\n\treadonly receipts: readonly EvidenceReceipt[];\n\treadonly environmentDigest: string;\n}\n\nexport function createRunIssuer(runPath: string): void {\n\t// Recovery must never replace a missing key and re-sign old evidence.\n\tpublishBytes(join(runPath, \"issuer.key\"), randomBytes(32));\n}\n\nfunction tag(runPath: string, receipt: unknown): Buffer {\n\tconst key = readRegularFile(join(runPath, \"issuer.key\"), 32);\n\tif (key.length !== 32) throw new VerifiedRunError(\"integrity\");\n\treturn createHmac(\"sha256\", key).update(\"omk.verified-run.attestation.v1\\0\").update(canonicalJson(receipt)).digest();\n}\n\nexport function issueRunEvidence(\n\trunPath: string,\n\tcontract: RunContract,\n\tmaterial: {\n\t\treadonly generation: number;\n\t\treadonly candidateDigest: string;\n\t\treadonly environmentDigest: string;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): { readonly digest: string; readonly verified: boolean } {\n\tconst checks = parseCheckObservations(material.checks, true);\n\tconst candidate = loadCandidate(runPath, material.candidateDigest, contract.budget);\n\treadCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks });\n\tconst receipt: Attestation = {\n\t\tversion: 3,\n\t\trunId: contract.runId,\n\t\tgeneration: material.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest: material.candidateDigest,\n\t\tenvironmentDigest: material.environmentDigest,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified: closesRunClaims(contract, {\n\t\t\tcandidate: material.candidateDigest,\n\t\t\tenvironment: material.environmentDigest,\n\t\t\tchecks,\n\t\t}),\n\t};\n\tconst envelope = { receipt, authenticationTag: tag(runPath, receipt).toString(\"hex\") };\n\tconst digest = digestObject(envelope);\n\tpublishObject(join(runPath, \"attestations\", `${digest}.json`), envelope);\n\treturn { digest, verified: receipt.verified };\n}\n\nexport interface EvidenceRead {\n\treadonly authenticity: \"valid\" | \"invalid\" | \"unverifiable\";\n\treadonly verification: \"passed\" | \"failed\" | \"incomplete\";\n\treadonly currentEnvironmentEligibility: \"matching\" | \"different\" | \"unsupported\" | \"unknown\";\n\treadonly evidence: VerifiedRunEvidence | null;\n}\n\n/** Historical authenticity is separate from whether this machine can rerun the receipt. */\nexport function classifyEvidenceRead(\n\trunPath: string,\n\tjournal: JournalSnapshot,\n\tcurrentEnvironment?: string | { readonly status: \"unsupported\" | \"unknown\" },\n): EvidenceRead {\n\ttry {\n\t\tconst evidence = readRunEvidence(runPath, journal);\n\t\tconst currentEnvironmentEligibility =\n\t\t\ttypeof currentEnvironment === \"string\"\n\t\t\t\t? evidence.environmentDigest === currentEnvironment\n\t\t\t\t\t? \"matching\"\n\t\t\t\t\t: \"different\"\n\t\t\t\t: (currentEnvironment?.status ?? \"unknown\");\n\t\treturn {\n\t\t\tauthenticity: \"valid\",\n\t\t\tverification: evidence.verified\n\t\t\t\t? \"passed\"\n\t\t\t\t: evidence.checks.some((check) => check.exitCode === null)\n\t\t\t\t\t? \"incomplete\"\n\t\t\t\t\t: \"failed\",\n\t\t\tcurrentEnvironmentEligibility,\n\t\t\tevidence,\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof VerifiedRunError) {\n\t\t\treturn {\n\t\t\t\tauthenticity: error.code === \"evidence_missing\" ? \"unverifiable\" : \"invalid\",\n\t\t\t\tverification: \"incomplete\",\n\t\t\t\tcurrentEnvironmentEligibility: \"unknown\",\n\t\t\t\tevidence: null,\n\t\t\t};\n\t\t}\n\t\tif (error instanceof Error && \"code\" in error && [\"ENOENT\", \"EACCES\", \"EIO\"].includes(String(error.code)))\n\t\t\treturn {\n\t\t\t\tauthenticity: \"unverifiable\",\n\t\t\t\tverification: \"incomplete\",\n\t\t\t\tcurrentEnvironmentEligibility: \"unknown\",\n\t\t\t\tevidence: null,\n\t\t\t};\n\t\tthrow error;\n\t}\n}\n\nexport function readRunEvidence(runPath: string, journal: JournalSnapshot, environment?: string): VerifiedRunEvidence {\n\tconst first = journal.records[0]?.event;\n\tconst { candidateDigest, receiptDigest } = journal.state;\n\tif (first?.kind !== \"created\" || !candidateDigest || !receiptDigest) throw new VerifiedRunError(\"evidence_missing\");\n\tconst raw = readJson(join(runPath, \"attestations\", `${receiptDigest}.json`));\n\tif (\n\t\tdigestObject(raw) !== receiptDigest ||\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"receipt\" in raw) ||\n\t\t!(\"authenticationTag\" in raw) ||\n\t\ttypeof raw.authenticationTag !== \"string\" ||\n\t\t!/^[a-f0-9]{64}$/.test(raw.authenticationTag) ||\n\t\t!timingSafeEqual(tag(runPath, raw.receipt), Buffer.from(raw.authenticationTag, \"hex\"))\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst receipt = raw.receipt;\n\tif (\n\t\ttypeof receipt !== \"object\" ||\n\t\treceipt === null ||\n\t\t!(\"checks\" in receipt) ||\n\t\t!(\"version\" in receipt) ||\n\t\t(receipt.version !== 1 && receipt.version !== 2 && receipt.version !== 3)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tif (\n\t\t!(\"environmentDigest\" in receipt) ||\n\t\ttypeof receipt.environmentDigest !== \"string\" ||\n\t\t!/^[a-f0-9]{64}$/.test(receipt.environmentDigest)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst storedEnvironment = receipt.environmentDigest;\n\tif (journal.state.environmentDigest !== null && journal.state.environmentDigest !== storedEnvironment)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tif (environment !== undefined && environment !== storedEnvironment)\n\t\tthrow new VerifiedRunError(\"environment_mismatch\");\n\tconst checks = parseCheckObservations(receipt.checks, receipt.version !== 1);\n\tconst contract = first.contract;\n\tconst dispatches = journal.records.flatMap(({ event, generation }) =>\n\t\tgeneration === journal.state.generation && event.kind === \"dispatch\" && event.role === \"verifier\" ? [event] : [],\n\t);\n\tif (\n\t\tchecks.length !== contract.checks.length ||\n\t\tchecks.length !== dispatches.length ||\n\t\tnew Set(checks.map((check) => check.claimId)).size !== checks.length ||\n\t\tchecks.some(\n\t\t\t(check) =>\n\t\t\t\t!dispatches.some((event) => event.executionId === check.executionId && event.claimId === check.claimId),\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst verified = closesRunClaims(contract, { candidate: candidateDigest, environment: storedEnvironment, checks });\n\tconst expected: Attestation = {\n\t\tversion: receipt.version,\n\t\trunId: contract.runId,\n\t\tgeneration: journal.state.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest,\n\t\tenvironmentDigest: storedEnvironment,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified,\n\t};\n\tif (canonicalJson(receipt) !== canonicalJson(expected) || verified !== (journal.state.verification === \"verified\"))\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst candidate = loadCandidate(runPath, candidateDigest, contract.budget);\n\tconst receipts =\n\t\treceipt.version !== 1\n\t\t\t? readCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks })\n\t\t\t: Object.freeze([]);\n\treturn Object.freeze({\n\t\tcandidateDigest,\n\t\tmanifest: candidate.manifest,\n\t\treceiptDigest,\n\t\tverified,\n\t\tchecks,\n\t\treceiptFormat: receipt.version !== 1 ? \"v3\" : \"legacy\",\n\t\treceipts,\n\t\tenvironmentDigest: storedEnvironment,\n\t});\n}\n"]}
|
|
@@ -39,6 +39,45 @@ export function issueRunEvidence(runPath, contract, material) {
|
|
|
39
39
|
publishObject(join(runPath, "attestations", `${digest}.json`), envelope);
|
|
40
40
|
return { digest, verified: receipt.verified };
|
|
41
41
|
}
|
|
42
|
+
/** Historical authenticity is separate from whether this machine can rerun the receipt. */
|
|
43
|
+
export function classifyEvidenceRead(runPath, journal, currentEnvironment) {
|
|
44
|
+
try {
|
|
45
|
+
const evidence = readRunEvidence(runPath, journal);
|
|
46
|
+
const currentEnvironmentEligibility = typeof currentEnvironment === "string"
|
|
47
|
+
? evidence.environmentDigest === currentEnvironment
|
|
48
|
+
? "matching"
|
|
49
|
+
: "different"
|
|
50
|
+
: (currentEnvironment?.status ?? "unknown");
|
|
51
|
+
return {
|
|
52
|
+
authenticity: "valid",
|
|
53
|
+
verification: evidence.verified
|
|
54
|
+
? "passed"
|
|
55
|
+
: evidence.checks.some((check) => check.exitCode === null)
|
|
56
|
+
? "incomplete"
|
|
57
|
+
: "failed",
|
|
58
|
+
currentEnvironmentEligibility,
|
|
59
|
+
evidence,
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (error instanceof VerifiedRunError) {
|
|
64
|
+
return {
|
|
65
|
+
authenticity: error.code === "evidence_missing" ? "unverifiable" : "invalid",
|
|
66
|
+
verification: "incomplete",
|
|
67
|
+
currentEnvironmentEligibility: "unknown",
|
|
68
|
+
evidence: null,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
if (error instanceof Error && "code" in error && ["ENOENT", "EACCES", "EIO"].includes(String(error.code)))
|
|
72
|
+
return {
|
|
73
|
+
authenticity: "unverifiable",
|
|
74
|
+
verification: "incomplete",
|
|
75
|
+
currentEnvironmentEligibility: "unknown",
|
|
76
|
+
evidence: null,
|
|
77
|
+
};
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
}
|
|
42
81
|
export function readRunEvidence(runPath, journal, environment) {
|
|
43
82
|
const first = journal.records[0]?.event;
|
|
44
83
|
const { candidateDigest, receiptDigest } = journal.state;
|
|
@@ -61,6 +100,15 @@ export function readRunEvidence(runPath, journal, environment) {
|
|
|
61
100
|
!("version" in receipt) ||
|
|
62
101
|
(receipt.version !== 1 && receipt.version !== 2 && receipt.version !== 3))
|
|
63
102
|
throw new VerifiedRunError("integrity");
|
|
103
|
+
if (!("environmentDigest" in receipt) ||
|
|
104
|
+
typeof receipt.environmentDigest !== "string" ||
|
|
105
|
+
!/^[a-f0-9]{64}$/.test(receipt.environmentDigest))
|
|
106
|
+
throw new VerifiedRunError("integrity");
|
|
107
|
+
const storedEnvironment = receipt.environmentDigest;
|
|
108
|
+
if (journal.state.environmentDigest !== null && journal.state.environmentDigest !== storedEnvironment)
|
|
109
|
+
throw new VerifiedRunError("integrity");
|
|
110
|
+
if (environment !== undefined && environment !== storedEnvironment)
|
|
111
|
+
throw new VerifiedRunError("environment_mismatch");
|
|
64
112
|
const checks = parseCheckObservations(receipt.checks, receipt.version !== 1);
|
|
65
113
|
const contract = first.contract;
|
|
66
114
|
const dispatches = journal.records.flatMap(({ event, generation }) => generation === journal.state.generation && event.kind === "dispatch" && event.role === "verifier" ? [event] : []);
|
|
@@ -69,14 +117,14 @@ export function readRunEvidence(runPath, journal, environment) {
|
|
|
69
117
|
new Set(checks.map((check) => check.claimId)).size !== checks.length ||
|
|
70
118
|
checks.some((check) => !dispatches.some((event) => event.executionId === check.executionId && event.claimId === check.claimId)))
|
|
71
119
|
throw new VerifiedRunError("integrity");
|
|
72
|
-
const verified = closesRunClaims(contract, { candidate: candidateDigest, environment, checks });
|
|
120
|
+
const verified = closesRunClaims(contract, { candidate: candidateDigest, environment: storedEnvironment, checks });
|
|
73
121
|
const expected = {
|
|
74
122
|
version: receipt.version,
|
|
75
123
|
runId: contract.runId,
|
|
76
124
|
generation: journal.state.generation,
|
|
77
125
|
contractDigest: digestObject(contract),
|
|
78
126
|
candidateDigest,
|
|
79
|
-
environmentDigest:
|
|
127
|
+
environmentDigest: storedEnvironment,
|
|
80
128
|
verifierDigest: digestObject(contract.checks),
|
|
81
129
|
checks,
|
|
82
130
|
verified,
|
|
@@ -95,6 +143,7 @@ export function readRunEvidence(runPath, journal, environment) {
|
|
|
95
143
|
checks,
|
|
96
144
|
receiptFormat: receipt.version !== 1 ? "v3" : "legacy",
|
|
97
145
|
receipts,
|
|
146
|
+
environmentDigest: storedEnvironment,
|
|
98
147
|
});
|
|
99
148
|
}
|
|
100
149
|
//# sourceMappingURL=evidence.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/core/verified-run/evidence.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { RunContract } from \"omk-protocol\";\nimport type { EvidenceReceipt } from \"../../types/evidence.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport { type CandidateManifest, loadCandidate } from \"./candidate.ts\";\nimport { readCheckReceipts } from \"./check-receipt.ts\";\nimport { type CheckObservation, closesRunClaims, parseCheckObservations } from \"./evidence-binding.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { digestObject, publishBytes, publishObject, readJson, readRegularFile, VerifiedRunError } from \"./storage.ts\";\n\nexport type { CheckObservation } from \"./evidence-binding.ts\";\n\ninterface Attestation {\n\treadonly version: 1 | 2 | 3;\n\treadonly runId: string;\n\treadonly generation: number;\n\treadonly contractDigest: string;\n\treadonly candidateDigest: string;\n\treadonly environmentDigest: string;\n\treadonly verifierDigest: string;\n\treadonly checks: readonly CheckObservation[];\n\treadonly verified: boolean;\n}\nexport interface VerifiedRunEvidence {\n\treadonly candidateDigest: string;\n\treadonly manifest: CandidateManifest;\n\treadonly receiptDigest: string;\n\treadonly verified: boolean;\n\treadonly checks: readonly CheckObservation[];\n\treadonly receiptFormat: \"v3\" | \"legacy\";\n\treadonly receipts: readonly EvidenceReceipt[];\n}\n\nexport function createRunIssuer(runPath: string): void {\n\t// Recovery must never replace a missing key and re-sign old evidence.\n\tpublishBytes(join(runPath, \"issuer.key\"), randomBytes(32));\n}\n\nfunction tag(runPath: string, receipt: unknown): Buffer {\n\tconst key = readRegularFile(join(runPath, \"issuer.key\"), 32);\n\tif (key.length !== 32) throw new VerifiedRunError(\"integrity\");\n\treturn createHmac(\"sha256\", key).update(\"omk.verified-run.attestation.v1\\0\").update(canonicalJson(receipt)).digest();\n}\n\nexport function issueRunEvidence(\n\trunPath: string,\n\tcontract: RunContract,\n\tmaterial: {\n\t\treadonly generation: number;\n\t\treadonly candidateDigest: string;\n\t\treadonly environmentDigest: string;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): { readonly digest: string; readonly verified: boolean } {\n\tconst checks = parseCheckObservations(material.checks, true);\n\tconst candidate = loadCandidate(runPath, material.candidateDigest, contract.budget);\n\treadCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks });\n\tconst receipt: Attestation = {\n\t\tversion: 3,\n\t\trunId: contract.runId,\n\t\tgeneration: material.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest: material.candidateDigest,\n\t\tenvironmentDigest: material.environmentDigest,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified: closesRunClaims(contract, {\n\t\t\tcandidate: material.candidateDigest,\n\t\t\tenvironment: material.environmentDigest,\n\t\t\tchecks,\n\t\t}),\n\t};\n\tconst envelope = { receipt, authenticationTag: tag(runPath, receipt).toString(\"hex\") };\n\tconst digest = digestObject(envelope);\n\tpublishObject(join(runPath, \"attestations\", `${digest}.json`), envelope);\n\treturn { digest, verified: receipt.verified };\n}\n\nexport function readRunEvidence(runPath: string, journal: JournalSnapshot, environment: string): VerifiedRunEvidence {\n\tconst first = journal.records[0]?.event;\n\tconst { candidateDigest, receiptDigest } = journal.state;\n\tif (first?.kind !== \"created\" || !candidateDigest || !receiptDigest) throw new VerifiedRunError(\"evidence_missing\");\n\tconst raw = readJson(join(runPath, \"attestations\", `${receiptDigest}.json`));\n\tif (\n\t\tdigestObject(raw) !== receiptDigest ||\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"receipt\" in raw) ||\n\t\t!(\"authenticationTag\" in raw) ||\n\t\ttypeof raw.authenticationTag !== \"string\" ||\n\t\t!/^[a-f0-9]{64}$/.test(raw.authenticationTag) ||\n\t\t!timingSafeEqual(tag(runPath, raw.receipt), Buffer.from(raw.authenticationTag, \"hex\"))\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst receipt = raw.receipt;\n\tif (\n\t\ttypeof receipt !== \"object\" ||\n\t\treceipt === null ||\n\t\t!(\"checks\" in receipt) ||\n\t\t!(\"version\" in receipt) ||\n\t\t(receipt.version !== 1 && receipt.version !== 2 && receipt.version !== 3)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst checks = parseCheckObservations(receipt.checks, receipt.version !== 1);\n\tconst contract = first.contract;\n\tconst dispatches = journal.records.flatMap(({ event, generation }) =>\n\t\tgeneration === journal.state.generation && event.kind === \"dispatch\" && event.role === \"verifier\" ? [event] : [],\n\t);\n\tif (\n\t\tchecks.length !== contract.checks.length ||\n\t\tchecks.length !== dispatches.length ||\n\t\tnew Set(checks.map((check) => check.claimId)).size !== checks.length ||\n\t\tchecks.some(\n\t\t\t(check) =>\n\t\t\t\t!dispatches.some((event) => event.executionId === check.executionId && event.claimId === check.claimId),\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst verified = closesRunClaims(contract, { candidate: candidateDigest, environment, checks });\n\tconst expected: Attestation = {\n\t\tversion: receipt.version,\n\t\trunId: contract.runId,\n\t\tgeneration: journal.state.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest,\n\t\tenvironmentDigest: environment,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified,\n\t};\n\tif (canonicalJson(receipt) !== canonicalJson(expected) || verified !== (journal.state.verification === \"verified\"))\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst candidate = loadCandidate(runPath, candidateDigest, contract.budget);\n\tconst receipts =\n\t\treceipt.version !== 1\n\t\t\t? readCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks })\n\t\t\t: Object.freeze([]);\n\treturn Object.freeze({\n\t\tcandidateDigest,\n\t\tmanifest: candidate.manifest,\n\t\treceiptDigest,\n\t\tverified,\n\t\tchecks,\n\t\treceiptFormat: receipt.version !== 1 ? \"v3\" : \"legacy\",\n\t\treceipts,\n\t});\n}\n"]}
|
|
1
|
+
{"version":3,"file":"evidence.js","sourceRoot":"","sources":["../../../src/core/verified-run/evidence.ts"],"names":[],"mappings":"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","sourcesContent":["import { createHmac, randomBytes, timingSafeEqual } from \"node:crypto\";\nimport { join } from \"node:path\";\nimport type { RunContract } from \"omk-protocol\";\nimport type { EvidenceReceipt } from \"../../types/evidence.ts\";\nimport { canonicalJson } from \"../run-journal.ts\";\nimport { type CandidateManifest, loadCandidate } from \"./candidate.ts\";\nimport { readCheckReceipts } from \"./check-receipt.ts\";\nimport { type CheckObservation, closesRunClaims, parseCheckObservations } from \"./evidence-binding.ts\";\nimport type { JournalSnapshot } from \"./journal.ts\";\nimport { digestObject, publishBytes, publishObject, readJson, readRegularFile, VerifiedRunError } from \"./storage.ts\";\n\nexport type { CheckObservation } from \"./evidence-binding.ts\";\n\ninterface Attestation {\n\treadonly version: 1 | 2 | 3;\n\treadonly runId: string;\n\treadonly generation: number;\n\treadonly contractDigest: string;\n\treadonly candidateDigest: string;\n\treadonly environmentDigest: string;\n\treadonly verifierDigest: string;\n\treadonly checks: readonly CheckObservation[];\n\treadonly verified: boolean;\n}\nexport interface VerifiedRunEvidence {\n\treadonly candidateDigest: string;\n\treadonly manifest: CandidateManifest;\n\treadonly receiptDigest: string;\n\treadonly verified: boolean;\n\treadonly checks: readonly CheckObservation[];\n\treadonly receiptFormat: \"v3\" | \"legacy\";\n\treadonly receipts: readonly EvidenceReceipt[];\n\treadonly environmentDigest: string;\n}\n\nexport function createRunIssuer(runPath: string): void {\n\t// Recovery must never replace a missing key and re-sign old evidence.\n\tpublishBytes(join(runPath, \"issuer.key\"), randomBytes(32));\n}\n\nfunction tag(runPath: string, receipt: unknown): Buffer {\n\tconst key = readRegularFile(join(runPath, \"issuer.key\"), 32);\n\tif (key.length !== 32) throw new VerifiedRunError(\"integrity\");\n\treturn createHmac(\"sha256\", key).update(\"omk.verified-run.attestation.v1\\0\").update(canonicalJson(receipt)).digest();\n}\n\nexport function issueRunEvidence(\n\trunPath: string,\n\tcontract: RunContract,\n\tmaterial: {\n\t\treadonly generation: number;\n\t\treadonly candidateDigest: string;\n\t\treadonly environmentDigest: string;\n\t\treadonly checks: readonly CheckObservation[];\n\t},\n): { readonly digest: string; readonly verified: boolean } {\n\tconst checks = parseCheckObservations(material.checks, true);\n\tconst candidate = loadCandidate(runPath, material.candidateDigest, contract.budget);\n\treadCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks });\n\tconst receipt: Attestation = {\n\t\tversion: 3,\n\t\trunId: contract.runId,\n\t\tgeneration: material.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest: material.candidateDigest,\n\t\tenvironmentDigest: material.environmentDigest,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified: closesRunClaims(contract, {\n\t\t\tcandidate: material.candidateDigest,\n\t\t\tenvironment: material.environmentDigest,\n\t\t\tchecks,\n\t\t}),\n\t};\n\tconst envelope = { receipt, authenticationTag: tag(runPath, receipt).toString(\"hex\") };\n\tconst digest = digestObject(envelope);\n\tpublishObject(join(runPath, \"attestations\", `${digest}.json`), envelope);\n\treturn { digest, verified: receipt.verified };\n}\n\nexport interface EvidenceRead {\n\treadonly authenticity: \"valid\" | \"invalid\" | \"unverifiable\";\n\treadonly verification: \"passed\" | \"failed\" | \"incomplete\";\n\treadonly currentEnvironmentEligibility: \"matching\" | \"different\" | \"unsupported\" | \"unknown\";\n\treadonly evidence: VerifiedRunEvidence | null;\n}\n\n/** Historical authenticity is separate from whether this machine can rerun the receipt. */\nexport function classifyEvidenceRead(\n\trunPath: string,\n\tjournal: JournalSnapshot,\n\tcurrentEnvironment?: string | { readonly status: \"unsupported\" | \"unknown\" },\n): EvidenceRead {\n\ttry {\n\t\tconst evidence = readRunEvidence(runPath, journal);\n\t\tconst currentEnvironmentEligibility =\n\t\t\ttypeof currentEnvironment === \"string\"\n\t\t\t\t? evidence.environmentDigest === currentEnvironment\n\t\t\t\t\t? \"matching\"\n\t\t\t\t\t: \"different\"\n\t\t\t\t: (currentEnvironment?.status ?? \"unknown\");\n\t\treturn {\n\t\t\tauthenticity: \"valid\",\n\t\t\tverification: evidence.verified\n\t\t\t\t? \"passed\"\n\t\t\t\t: evidence.checks.some((check) => check.exitCode === null)\n\t\t\t\t\t? \"incomplete\"\n\t\t\t\t\t: \"failed\",\n\t\t\tcurrentEnvironmentEligibility,\n\t\t\tevidence,\n\t\t};\n\t} catch (error) {\n\t\tif (error instanceof VerifiedRunError) {\n\t\t\treturn {\n\t\t\t\tauthenticity: error.code === \"evidence_missing\" ? \"unverifiable\" : \"invalid\",\n\t\t\t\tverification: \"incomplete\",\n\t\t\t\tcurrentEnvironmentEligibility: \"unknown\",\n\t\t\t\tevidence: null,\n\t\t\t};\n\t\t}\n\t\tif (error instanceof Error && \"code\" in error && [\"ENOENT\", \"EACCES\", \"EIO\"].includes(String(error.code)))\n\t\t\treturn {\n\t\t\t\tauthenticity: \"unverifiable\",\n\t\t\t\tverification: \"incomplete\",\n\t\t\t\tcurrentEnvironmentEligibility: \"unknown\",\n\t\t\t\tevidence: null,\n\t\t\t};\n\t\tthrow error;\n\t}\n}\n\nexport function readRunEvidence(runPath: string, journal: JournalSnapshot, environment?: string): VerifiedRunEvidence {\n\tconst first = journal.records[0]?.event;\n\tconst { candidateDigest, receiptDigest } = journal.state;\n\tif (first?.kind !== \"created\" || !candidateDigest || !receiptDigest) throw new VerifiedRunError(\"evidence_missing\");\n\tconst raw = readJson(join(runPath, \"attestations\", `${receiptDigest}.json`));\n\tif (\n\t\tdigestObject(raw) !== receiptDigest ||\n\t\ttypeof raw !== \"object\" ||\n\t\traw === null ||\n\t\t!(\"receipt\" in raw) ||\n\t\t!(\"authenticationTag\" in raw) ||\n\t\ttypeof raw.authenticationTag !== \"string\" ||\n\t\t!/^[a-f0-9]{64}$/.test(raw.authenticationTag) ||\n\t\t!timingSafeEqual(tag(runPath, raw.receipt), Buffer.from(raw.authenticationTag, \"hex\"))\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst receipt = raw.receipt;\n\tif (\n\t\ttypeof receipt !== \"object\" ||\n\t\treceipt === null ||\n\t\t!(\"checks\" in receipt) ||\n\t\t!(\"version\" in receipt) ||\n\t\t(receipt.version !== 1 && receipt.version !== 2 && receipt.version !== 3)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tif (\n\t\t!(\"environmentDigest\" in receipt) ||\n\t\ttypeof receipt.environmentDigest !== \"string\" ||\n\t\t!/^[a-f0-9]{64}$/.test(receipt.environmentDigest)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst storedEnvironment = receipt.environmentDigest;\n\tif (journal.state.environmentDigest !== null && journal.state.environmentDigest !== storedEnvironment)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tif (environment !== undefined && environment !== storedEnvironment)\n\t\tthrow new VerifiedRunError(\"environment_mismatch\");\n\tconst checks = parseCheckObservations(receipt.checks, receipt.version !== 1);\n\tconst contract = first.contract;\n\tconst dispatches = journal.records.flatMap(({ event, generation }) =>\n\t\tgeneration === journal.state.generation && event.kind === \"dispatch\" && event.role === \"verifier\" ? [event] : [],\n\t);\n\tif (\n\t\tchecks.length !== contract.checks.length ||\n\t\tchecks.length !== dispatches.length ||\n\t\tnew Set(checks.map((check) => check.claimId)).size !== checks.length ||\n\t\tchecks.some(\n\t\t\t(check) =>\n\t\t\t\t!dispatches.some((event) => event.executionId === check.executionId && event.claimId === check.claimId),\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst verified = closesRunClaims(contract, { candidate: candidateDigest, environment: storedEnvironment, checks });\n\tconst expected: Attestation = {\n\t\tversion: receipt.version,\n\t\trunId: contract.runId,\n\t\tgeneration: journal.state.generation,\n\t\tcontractDigest: digestObject(contract),\n\t\tcandidateDigest,\n\t\tenvironmentDigest: storedEnvironment,\n\t\tverifierDigest: digestObject(contract.checks),\n\t\tchecks,\n\t\tverified,\n\t};\n\tif (canonicalJson(receipt) !== canonicalJson(expected) || verified !== (journal.state.verification === \"verified\"))\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst candidate = loadCandidate(runPath, candidateDigest, contract.budget);\n\tconst receipts =\n\t\treceipt.version !== 1\n\t\t\t? readCheckReceipts(runPath, contract, { manifest: candidate.manifest, checks })\n\t\t\t: Object.freeze([]);\n\treturn Object.freeze({\n\t\tcandidateDigest,\n\t\tmanifest: candidate.manifest,\n\t\treceiptDigest,\n\t\tverified,\n\t\tchecks,\n\t\treceiptFormat: receipt.version !== 1 ? \"v3\" : \"legacy\",\n\t\treceipts,\n\t\tenvironmentDigest: storedEnvironment,\n\t});\n}\n"]}
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { CandidateManifest } from "./candidate.ts";
|
|
2
|
+
/** Validate every entry before the first Git object write, including legacy candidates. */
|
|
3
|
+
export declare function preflightGitCandidate(manifest: CandidateManifest, contents: ReadonlyMap<string, Buffer>): void;
|
|
4
|
+
//# sourceMappingURL=git-candidate-preflight.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-candidate-preflight.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/git-candidate-preflight.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,gBAAgB,CAAC;AAIxD,2FAA2F;AAC3F,wBAAgB,qBAAqB,CAAC,QAAQ,EAAE,iBAAiB,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,IAAI,CA2B9G","sourcesContent":["import type { CandidateManifest } from \"./candidate.ts\";\nimport { assertPublishablePath, safeCandidatePath } from \"./candidate-policy.ts\";\nimport { digestBytes, VerifiedRunError } from \"./storage.ts\";\n\n/** Validate every entry before the first Git object write, including legacy candidates. */\nexport function preflightGitCandidate(manifest: CandidateManifest, contents: ReadonlyMap<string, Buffer>): void {\n\tif (manifest.version !== 1 || !Array.isArray(manifest.directories) || !Array.isArray(manifest.files))\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst directories = new Set(manifest.directories);\n\tconst paths = new Set<string>();\n\tconst checkPath = (path: string) => {\n\t\tsafeCandidatePath(path);\n\t\tassertPublishablePath(path);\n\t\tif (paths.has(path)) throw new VerifiedRunError(\"integrity\");\n\t\tpaths.add(path);\n\t\tconst slash = path.lastIndexOf(\"/\");\n\t\tif (slash !== -1 && !directories.has(path.slice(0, slash))) throw new VerifiedRunError(\"integrity\");\n\t};\n\tfor (const directory of manifest.directories) checkPath(directory);\n\tfor (const file of manifest.files) {\n\t\tcheckPath(file.path);\n\t\tif (file.mode !== 0o644 && file.mode !== 0o755) throw new VerifiedRunError(\"mode_unrepresentable\");\n\t\tconst bytes = contents.get(file.digest);\n\t\tif (\n\t\t\t!bytes ||\n\t\t\t!Number.isSafeInteger(file.size) ||\n\t\t\tfile.size < 0 ||\n\t\t\tbytes.length !== file.size ||\n\t\t\tdigestBytes(bytes) !== file.digest\n\t\t)\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { assertPublishablePath, safeCandidatePath } from "./candidate-policy.js";
|
|
2
|
+
import { digestBytes, VerifiedRunError } from "./storage.js";
|
|
3
|
+
/** Validate every entry before the first Git object write, including legacy candidates. */
|
|
4
|
+
export function preflightGitCandidate(manifest, contents) {
|
|
5
|
+
if (manifest.version !== 1 || !Array.isArray(manifest.directories) || !Array.isArray(manifest.files))
|
|
6
|
+
throw new VerifiedRunError("integrity");
|
|
7
|
+
const directories = new Set(manifest.directories);
|
|
8
|
+
const paths = new Set();
|
|
9
|
+
const checkPath = (path) => {
|
|
10
|
+
safeCandidatePath(path);
|
|
11
|
+
assertPublishablePath(path);
|
|
12
|
+
if (paths.has(path))
|
|
13
|
+
throw new VerifiedRunError("integrity");
|
|
14
|
+
paths.add(path);
|
|
15
|
+
const slash = path.lastIndexOf("/");
|
|
16
|
+
if (slash !== -1 && !directories.has(path.slice(0, slash)))
|
|
17
|
+
throw new VerifiedRunError("integrity");
|
|
18
|
+
};
|
|
19
|
+
for (const directory of manifest.directories)
|
|
20
|
+
checkPath(directory);
|
|
21
|
+
for (const file of manifest.files) {
|
|
22
|
+
checkPath(file.path);
|
|
23
|
+
if (file.mode !== 0o644 && file.mode !== 0o755)
|
|
24
|
+
throw new VerifiedRunError("mode_unrepresentable");
|
|
25
|
+
const bytes = contents.get(file.digest);
|
|
26
|
+
if (!bytes ||
|
|
27
|
+
!Number.isSafeInteger(file.size) ||
|
|
28
|
+
file.size < 0 ||
|
|
29
|
+
bytes.length !== file.size ||
|
|
30
|
+
digestBytes(bytes) !== file.digest)
|
|
31
|
+
throw new VerifiedRunError("integrity");
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=git-candidate-preflight.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-candidate-preflight.js","sourceRoot":"","sources":["../../../src/core/verified-run/git-candidate-preflight.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,uBAAuB,CAAC;AACjF,OAAO,EAAE,WAAW,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE7D,2FAA2F;AAC3F,MAAM,UAAU,qBAAqB,CAAC,QAA2B,EAAE,QAAqC,EAAQ;IAC/G,IAAI,QAAQ,CAAC,OAAO,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAC;QACnG,MAAM,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;IACzC,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAC;IAClD,MAAM,KAAK,GAAG,IAAI,GAAG,EAAU,CAAC;IAChC,MAAM,SAAS,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC;QACnC,iBAAiB,CAAC,IAAI,CAAC,CAAC;QACxB,qBAAqB,CAAC,IAAI,CAAC,CAAC;QAC5B,IAAI,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC;YAAE,MAAM,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;QAC7D,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACpC,IAAI,KAAK,KAAK,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;YAAE,MAAM,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAAA,CACpG,CAAC;IACF,KAAK,MAAM,SAAS,IAAI,QAAQ,CAAC,WAAW;QAAE,SAAS,CAAC,SAAS,CAAC,CAAC;IACnE,KAAK,MAAM,IAAI,IAAI,QAAQ,CAAC,KAAK,EAAE,CAAC;QACnC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QACrB,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK,IAAI,IAAI,CAAC,IAAI,KAAK,KAAK;YAAE,MAAM,IAAI,gBAAgB,CAAC,sBAAsB,CAAC,CAAC;QACnG,MAAM,KAAK,GAAG,QAAQ,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACxC,IACC,CAAC,KAAK;YACN,CAAC,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,IAAI,CAAC;YAChC,IAAI,CAAC,IAAI,GAAG,CAAC;YACb,KAAK,CAAC,MAAM,KAAK,IAAI,CAAC,IAAI;YAC1B,WAAW,CAAC,KAAK,CAAC,KAAK,IAAI,CAAC,MAAM;YAElC,MAAM,IAAI,gBAAgB,CAAC,WAAW,CAAC,CAAC;IAC1C,CAAC;AAAA,CACD","sourcesContent":["import type { CandidateManifest } from \"./candidate.ts\";\nimport { assertPublishablePath, safeCandidatePath } from \"./candidate-policy.ts\";\nimport { digestBytes, VerifiedRunError } from \"./storage.ts\";\n\n/** Validate every entry before the first Git object write, including legacy candidates. */\nexport function preflightGitCandidate(manifest: CandidateManifest, contents: ReadonlyMap<string, Buffer>): void {\n\tif (manifest.version !== 1 || !Array.isArray(manifest.directories) || !Array.isArray(manifest.files))\n\t\tthrow new VerifiedRunError(\"integrity\");\n\tconst directories = new Set(manifest.directories);\n\tconst paths = new Set<string>();\n\tconst checkPath = (path: string) => {\n\t\tsafeCandidatePath(path);\n\t\tassertPublishablePath(path);\n\t\tif (paths.has(path)) throw new VerifiedRunError(\"integrity\");\n\t\tpaths.add(path);\n\t\tconst slash = path.lastIndexOf(\"/\");\n\t\tif (slash !== -1 && !directories.has(path.slice(0, slash))) throw new VerifiedRunError(\"integrity\");\n\t};\n\tfor (const directory of manifest.directories) checkPath(directory);\n\tfor (const file of manifest.files) {\n\t\tcheckPath(file.path);\n\t\tif (file.mode !== 0o644 && file.mode !== 0o755) throw new VerifiedRunError(\"mode_unrepresentable\");\n\t\tconst bytes = contents.get(file.digest);\n\t\tif (\n\t\t\t!bytes ||\n\t\t\t!Number.isSafeInteger(file.size) ||\n\t\t\tfile.size < 0 ||\n\t\t\tbytes.length !== file.size ||\n\t\t\tdigestBytes(bytes) !== file.digest\n\t\t)\n\t\t\tthrow new VerifiedRunError(\"integrity\");\n\t}\n}\n"]}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { type ResourceClaimInput } from "../../coordination/resource.ts";
|
|
2
|
+
import type { GrantToken } from "../../coordination/types.ts";
|
|
3
|
+
import type { RunAuthority } from "./authority-runtime.ts";
|
|
4
|
+
import type { GitOperationBudget } from "./git-execution.ts";
|
|
5
|
+
import { type SealCandidateInput } from "./git-plumbing.ts";
|
|
6
|
+
import { type GitWorkerNotice } from "./git-worker-protocol.ts";
|
|
7
|
+
import { type GitWorkerRuntime } from "./git-worker-runtime.ts";
|
|
8
|
+
export interface OwnedGitPublication {
|
|
9
|
+
readonly workspace: string;
|
|
10
|
+
readonly input: SealCandidateInput;
|
|
11
|
+
readonly authority: RunAuthority;
|
|
12
|
+
readonly token: GrantToken;
|
|
13
|
+
readonly claims: readonly ResourceClaimInput[];
|
|
14
|
+
readonly runtime: GitWorkerRuntime;
|
|
15
|
+
readonly budget: GitOperationBudget;
|
|
16
|
+
readonly deadlineNs: string;
|
|
17
|
+
readonly cleanupMs: number;
|
|
18
|
+
readonly signal?: AbortSignal;
|
|
19
|
+
readonly onPrepared: (candidateOid: string) => void | Promise<void>;
|
|
20
|
+
readonly afterCas?: () => void | Promise<void>;
|
|
21
|
+
}
|
|
22
|
+
/** One owner for staging, durable dispatch, seal/CAS gates, namespace drain and grant settlement. */
|
|
23
|
+
export declare function executeOwnedGitPublication(request: OwnedGitPublication): Promise<GitWorkerNotice>;
|
|
24
|
+
//# sourceMappingURL=git-effect-supervisor.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-effect-supervisor.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/git-effect-supervisor.ts"],"names":[],"mappings":"AAGA,OAAO,EAAkB,KAAK,kBAAkB,EAAgB,MAAM,gCAAgC,CAAC;AACvG,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,6BAA6B,CAAC;AAE9D,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAE3D,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAC7D,OAAO,EAAgC,KAAK,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AAC1F,OAAO,EAAE,KAAK,eAAe,EAAkC,MAAM,0BAA0B,CAAC;AAChG,OAAO,EAAE,KAAK,gBAAgB,EAAyC,MAAM,yBAAyB,CAAC;AAKvG,MAAM,WAAW,mBAAmB;IACnC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,KAAK,EAAE,kBAAkB,CAAC;IACnC,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC;IACjC,QAAQ,CAAC,KAAK,EAAE,UAAU,CAAC;IAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,kBAAkB,EAAE,CAAC;IAC/C,QAAQ,CAAC,OAAO,EAAE,gBAAgB,CAAC;IACnC,QAAQ,CAAC,MAAM,EAAE,kBAAkB,CAAC;IACpC,QAAQ,CAAC,UAAU,EAAE,MAAM,CAAC;IAC5B,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAC3B,QAAQ,CAAC,MAAM,CAAC,EAAE,WAAW,CAAC;IAC9B,QAAQ,CAAC,UAAU,EAAE,CAAC,YAAY,EAAE,MAAM,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACpE,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC/C;AAED,qGAAqG;AACrG,wBAAsB,0BAA0B,CAAC,OAAO,EAAE,mBAAmB,GAAG,OAAO,CAAC,eAAe,CAAC,CAuJvG","sourcesContent":["import { existsSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { canonicalClaim, type ResourceClaimInput, sameClaimSet } from \"../../coordination/resource.ts\";\nimport type { GrantToken } from \"../../coordination/types.ts\";\nimport { sameGrantToken } from \"./authority-meaning.ts\";\nimport type { RunAuthority } from \"./authority-runtime.ts\";\nimport { executeSandbox, type SandboxOutcome } from \"./broker.ts\";\nimport type { GitOperationBudget } from \"./git-execution.ts\";\nimport { OMK_ACCEPTED_REF, resolveRef, type SealCandidateInput } from \"./git-plumbing.ts\";\nimport { type GitWorkerNotice, readGitNotice, writeGitControl } from \"./git-worker-protocol.ts\";\nimport { type GitWorkerRuntime, type GitWorkerStage, prepareGitWorker } from \"./git-worker-runtime.ts\";\nimport type { NamespaceIdentity } from \"./namespace-identity.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\nimport { loadSupervisorBackend, probeOwnedNamespace } from \"./supervisor-adapter.ts\";\n\nexport interface OwnedGitPublication {\n\treadonly workspace: string;\n\treadonly input: SealCandidateInput;\n\treadonly authority: RunAuthority;\n\treadonly token: GrantToken;\n\treadonly claims: readonly ResourceClaimInput[];\n\treadonly runtime: GitWorkerRuntime;\n\treadonly budget: GitOperationBudget;\n\treadonly deadlineNs: string;\n\treadonly cleanupMs: number;\n\treadonly signal?: AbortSignal;\n\treadonly onPrepared: (candidateOid: string) => void | Promise<void>;\n\treadonly afterCas?: () => void | Promise<void>;\n}\n\n/** One owner for staging, durable dispatch, seal/CAS gates, namespace drain and grant settlement. */\nexport async function executeOwnedGitPublication(request: OwnedGitPublication): Promise<GitWorkerNotice> {\n\tconst authority = request.authority.store.state;\n\tconst reservation = authority.grants.get(request.token.grantSequence);\n\tif (\n\t\t!reservation ||\n\t\treservation.state !== \"reserved\" ||\n\t\treservation.effectLive ||\n\t\t!sameGrantToken(reservation.token, request.token) ||\n\t\tauthority.epoch !== request.token.authorityEpoch ||\n\t\tauthority.incarnations.get(request.token.sessionId) !== request.token.sessionIncarnation ||\n\t\t!sameClaimSet(\n\t\t\tArray.from(request.claims, (claim) => canonicalClaim(claim)),\n\t\t\treservation.claims,\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"authority\");\n\tloadSupervisorBackend();\n\tconst controller = new AbortController();\n\tconst cancel = () => controller.abort();\n\trequest.signal?.addEventListener(\"abort\", cancel, { once: true });\n\tif (request.signal?.aborted) cancel();\n\tlet stage: GitWorkerStage | undefined;\n\tlet identity: NamespaceIdentity | undefined;\n\tlet completion: Promise<void> | undefined;\n\tlet finished = false;\n\tlet outcome: SandboxOutcome | undefined;\n\tlet executionFailure: unknown;\n\tlet failure: unknown;\n\tlet result: GitWorkerNotice | undefined;\n\tlet preparedOid: string | undefined;\n\tlet terminationObserved = false;\n\tlet afterCasCalled = false;\n\tlet callbackFailed = false;\n\tconst { store } = request.authority;\n\tconst waitNotice = async (name: string): Promise<GitWorkerNotice> => {\n\t\tif (!stage) throw new VerifiedRunError(\"git_worker_protocol\");\n\t\tconst path = join(stage.root, name);\n\t\twhile (!existsSync(path)) {\n\t\t\tif (finished) throw executionFailure ?? new VerifiedRunError(outcome?.failure ?? \"git_worker_failed\");\n\t\t\trequest.budget.remaining();\n\t\t\tawait delay(5);\n\t\t}\n\t\treturn readGitNotice(path);\n\t};\n\ttry {\n\t\trequest.budget.remaining();\n\t\tstage = prepareGitWorker(request.workspace, request.runtime, {\n\t\t\tinput: request.input,\n\t\t\ttimeoutMs: Math.min(60_000, request.budget.remainingWorkMs()),\n\t\t\tdeadlineNs: request.deadlineNs,\n\t\t});\n\t\trequest.budget.remaining();\n\t\tif (!store.dispatchIntent(request.token, stage.dispatchId)) throw new VerifiedRunError(\"authority\");\n\t\tcompletion = executeSandbox({\n\t\t\tworkspace: request.workspace,\n\t\t\twritable: false,\n\t\t\tgitPublication: true,\n\t\t\targv: [\"/omk-node\", \"--experimental-strip-types\", stage.worker, stage.request],\n\t\t\ttimeoutMs: request.budget.remainingWorkMs(),\n\t\t\tcleanupMs: request.cleanupMs,\n\t\t\tmaxOutputBytes: 8192,\n\t\t\tsignal: controller.signal,\n\t\t\tonReady: (ready) => {\n\t\t\t\tidentity = ready;\n\t\t\t\tif (!store.effectStarted(request.token, request.claims, ready)) throw new VerifiedRunError(\"authority\");\n\t\t\t},\n\t\t}).then(\n\t\t\t(value) => {\n\t\t\t\toutcome = value;\n\t\t\t\tterminationObserved = true;\n\t\t\t\tfinished = true;\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\texecutionFailure = error;\n\t\t\t\tfinished = true;\n\t\t\t},\n\t\t);\n\t\tconst prepared = await waitNotice(\"prepared.json\");\n\t\tif (prepared.kind !== \"prepared\") throw new VerifiedRunError(\"git_worker_protocol\");\n\t\tpreparedOid = prepared.candidateOid;\n\t\ttry {\n\t\t\tawait request.onPrepared(preparedOid);\n\t\t} catch (error) {\n\t\t\tcallbackFailed = true;\n\t\t\tthrow error;\n\t\t}\n\t\trequest.budget.remaining();\n\t\tif (!store.effectAuthorized(request.token, request.claims)) throw new VerifiedRunError(\"authority\");\n\t\twriteGitControl(join(stage.root, \"cas-go.json\"), {\n\t\t\t...prepared,\n\t\t\tauthorizationDeadline: request.token.authorizationDeadline,\n\t\t});\n\t\tresult = await waitNotice(\"result.json\");\n\t\tif (result.kind === \"prepared\" || result.candidateOid !== preparedOid)\n\t\t\tthrow new VerifiedRunError(\"git_worker_protocol\");\n\t\tif (result.kind === \"committed\") {\n\t\t\tafterCasCalled = true;\n\t\t\ttry {\n\t\t\t\tawait request.afterCas?.();\n\t\t\t} catch (error) {\n\t\t\t\tcallbackFailed = true;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\twriteGitControl(join(stage.root, \"finish.json\"), result);\n\t} catch (error) {\n\t\tfailure = error;\n\t\tcontroller.abort();\n\t} finally {\n\t\tawait completion;\n\t\trequest.signal?.removeEventListener(\"abort\", cancel);\n\t\t// A callback error may reject the broker even after drain. Re-observe, never infer it.\n\t\tif (!terminationObserved && identity) terminationObserved = probeOwnedNamespace(identity) === \"terminated\";\n\t\tconst neverStarted =\n\t\t\tcompletion === undefined ||\n\t\t\t(!identity &&\n\t\t\t\texecutionFailure instanceof VerifiedRunError &&\n\t\t\t\t[\"cancelled\", \"deadline\", \"unsupported_boundary\"].includes(executionFailure.code));\n\t\ttry {\n\t\t\tif (terminationObserved || neverStarted) store.confirmTerminated(request.token);\n\t\t\telse store.cancel(request.token);\n\t\t} catch (error) {\n\t\t\tfailure =\n\t\t\t\tfailure === undefined ? error : new AggregateError([failure, error], \"Git authority settlement failed\");\n\t\t}\n\t\tif (stage && (terminationObserved || neverStarted)) {\n\t\t\ttry {\n\t\t\t\trmSync(stage.root, { recursive: true, force: true });\n\t\t\t} catch (error) {\n\t\t\t\tfailure =\n\t\t\t\t\tfailure === undefined ? error : new AggregateError([failure, error], \"Git staging cleanup failed\");\n\t\t\t}\n\t\t}\n\t}\n\tif (!terminationObserved && completion !== undefined)\n\t\tthrow failure ?? executionFailure ?? new VerifiedRunError(\"git_effect_unsettled\");\n\t// An abort racing the CAS cannot erase a ref that is already committed.\n\tif (\n\t\t!callbackFailed &&\n\t\tfailure instanceof VerifiedRunError &&\n\t\t[\"cancelled\", \"deadline\", \"git_worker_failed\"].includes(failure.code) &&\n\t\tpreparedOid &&\n\t\tresolveRef(request.workspace, OMK_ACCEPTED_REF) === preparedOid\n\t) {\n\t\tif (!afterCasCalled) await request.afterCas?.();\n\t\treturn { kind: \"committed\", candidateOid: preparedOid };\n\t}\n\tif (failure !== undefined) throw failure;\n\tif (executionFailure !== undefined) throw executionFailure;\n\tif (!result) throw new VerifiedRunError(\"git_worker_failed\");\n\treturn result;\n}\n"]}
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import { existsSync, rmSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { setTimeout as delay } from "node:timers/promises";
|
|
4
|
+
import { canonicalClaim, sameClaimSet } from "../../coordination/resource.js";
|
|
5
|
+
import { sameGrantToken } from "./authority-meaning.js";
|
|
6
|
+
import { executeSandbox } from "./broker.js";
|
|
7
|
+
import { OMK_ACCEPTED_REF, resolveRef } from "./git-plumbing.js";
|
|
8
|
+
import { readGitNotice, writeGitControl } from "./git-worker-protocol.js";
|
|
9
|
+
import { prepareGitWorker } from "./git-worker-runtime.js";
|
|
10
|
+
import { VerifiedRunError } from "./storage.js";
|
|
11
|
+
import { loadSupervisorBackend, probeOwnedNamespace } from "./supervisor-adapter.js";
|
|
12
|
+
/** One owner for staging, durable dispatch, seal/CAS gates, namespace drain and grant settlement. */
|
|
13
|
+
export async function executeOwnedGitPublication(request) {
|
|
14
|
+
const authority = request.authority.store.state;
|
|
15
|
+
const reservation = authority.grants.get(request.token.grantSequence);
|
|
16
|
+
if (!reservation ||
|
|
17
|
+
reservation.state !== "reserved" ||
|
|
18
|
+
reservation.effectLive ||
|
|
19
|
+
!sameGrantToken(reservation.token, request.token) ||
|
|
20
|
+
authority.epoch !== request.token.authorityEpoch ||
|
|
21
|
+
authority.incarnations.get(request.token.sessionId) !== request.token.sessionIncarnation ||
|
|
22
|
+
!sameClaimSet(Array.from(request.claims, (claim) => canonicalClaim(claim)), reservation.claims))
|
|
23
|
+
throw new VerifiedRunError("authority");
|
|
24
|
+
loadSupervisorBackend();
|
|
25
|
+
const controller = new AbortController();
|
|
26
|
+
const cancel = () => controller.abort();
|
|
27
|
+
request.signal?.addEventListener("abort", cancel, { once: true });
|
|
28
|
+
if (request.signal?.aborted)
|
|
29
|
+
cancel();
|
|
30
|
+
let stage;
|
|
31
|
+
let identity;
|
|
32
|
+
let completion;
|
|
33
|
+
let finished = false;
|
|
34
|
+
let outcome;
|
|
35
|
+
let executionFailure;
|
|
36
|
+
let failure;
|
|
37
|
+
let result;
|
|
38
|
+
let preparedOid;
|
|
39
|
+
let terminationObserved = false;
|
|
40
|
+
let afterCasCalled = false;
|
|
41
|
+
let callbackFailed = false;
|
|
42
|
+
const { store } = request.authority;
|
|
43
|
+
const waitNotice = async (name) => {
|
|
44
|
+
if (!stage)
|
|
45
|
+
throw new VerifiedRunError("git_worker_protocol");
|
|
46
|
+
const path = join(stage.root, name);
|
|
47
|
+
while (!existsSync(path)) {
|
|
48
|
+
if (finished)
|
|
49
|
+
throw executionFailure ?? new VerifiedRunError(outcome?.failure ?? "git_worker_failed");
|
|
50
|
+
request.budget.remaining();
|
|
51
|
+
await delay(5);
|
|
52
|
+
}
|
|
53
|
+
return readGitNotice(path);
|
|
54
|
+
};
|
|
55
|
+
try {
|
|
56
|
+
request.budget.remaining();
|
|
57
|
+
stage = prepareGitWorker(request.workspace, request.runtime, {
|
|
58
|
+
input: request.input,
|
|
59
|
+
timeoutMs: Math.min(60_000, request.budget.remainingWorkMs()),
|
|
60
|
+
deadlineNs: request.deadlineNs,
|
|
61
|
+
});
|
|
62
|
+
request.budget.remaining();
|
|
63
|
+
if (!store.dispatchIntent(request.token, stage.dispatchId))
|
|
64
|
+
throw new VerifiedRunError("authority");
|
|
65
|
+
completion = executeSandbox({
|
|
66
|
+
workspace: request.workspace,
|
|
67
|
+
writable: false,
|
|
68
|
+
gitPublication: true,
|
|
69
|
+
argv: ["/omk-node", "--experimental-strip-types", stage.worker, stage.request],
|
|
70
|
+
timeoutMs: request.budget.remainingWorkMs(),
|
|
71
|
+
cleanupMs: request.cleanupMs,
|
|
72
|
+
maxOutputBytes: 8192,
|
|
73
|
+
signal: controller.signal,
|
|
74
|
+
onReady: (ready) => {
|
|
75
|
+
identity = ready;
|
|
76
|
+
if (!store.effectStarted(request.token, request.claims, ready))
|
|
77
|
+
throw new VerifiedRunError("authority");
|
|
78
|
+
},
|
|
79
|
+
}).then((value) => {
|
|
80
|
+
outcome = value;
|
|
81
|
+
terminationObserved = true;
|
|
82
|
+
finished = true;
|
|
83
|
+
}, (error) => {
|
|
84
|
+
executionFailure = error;
|
|
85
|
+
finished = true;
|
|
86
|
+
});
|
|
87
|
+
const prepared = await waitNotice("prepared.json");
|
|
88
|
+
if (prepared.kind !== "prepared")
|
|
89
|
+
throw new VerifiedRunError("git_worker_protocol");
|
|
90
|
+
preparedOid = prepared.candidateOid;
|
|
91
|
+
try {
|
|
92
|
+
await request.onPrepared(preparedOid);
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
callbackFailed = true;
|
|
96
|
+
throw error;
|
|
97
|
+
}
|
|
98
|
+
request.budget.remaining();
|
|
99
|
+
if (!store.effectAuthorized(request.token, request.claims))
|
|
100
|
+
throw new VerifiedRunError("authority");
|
|
101
|
+
writeGitControl(join(stage.root, "cas-go.json"), {
|
|
102
|
+
...prepared,
|
|
103
|
+
authorizationDeadline: request.token.authorizationDeadline,
|
|
104
|
+
});
|
|
105
|
+
result = await waitNotice("result.json");
|
|
106
|
+
if (result.kind === "prepared" || result.candidateOid !== preparedOid)
|
|
107
|
+
throw new VerifiedRunError("git_worker_protocol");
|
|
108
|
+
if (result.kind === "committed") {
|
|
109
|
+
afterCasCalled = true;
|
|
110
|
+
try {
|
|
111
|
+
await request.afterCas?.();
|
|
112
|
+
}
|
|
113
|
+
catch (error) {
|
|
114
|
+
callbackFailed = true;
|
|
115
|
+
throw error;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
writeGitControl(join(stage.root, "finish.json"), result);
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
failure = error;
|
|
122
|
+
controller.abort();
|
|
123
|
+
}
|
|
124
|
+
finally {
|
|
125
|
+
await completion;
|
|
126
|
+
request.signal?.removeEventListener("abort", cancel);
|
|
127
|
+
// A callback error may reject the broker even after drain. Re-observe, never infer it.
|
|
128
|
+
if (!terminationObserved && identity)
|
|
129
|
+
terminationObserved = probeOwnedNamespace(identity) === "terminated";
|
|
130
|
+
const neverStarted = completion === undefined ||
|
|
131
|
+
(!identity &&
|
|
132
|
+
executionFailure instanceof VerifiedRunError &&
|
|
133
|
+
["cancelled", "deadline", "unsupported_boundary"].includes(executionFailure.code));
|
|
134
|
+
try {
|
|
135
|
+
if (terminationObserved || neverStarted)
|
|
136
|
+
store.confirmTerminated(request.token);
|
|
137
|
+
else
|
|
138
|
+
store.cancel(request.token);
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
failure =
|
|
142
|
+
failure === undefined ? error : new AggregateError([failure, error], "Git authority settlement failed");
|
|
143
|
+
}
|
|
144
|
+
if (stage && (terminationObserved || neverStarted)) {
|
|
145
|
+
try {
|
|
146
|
+
rmSync(stage.root, { recursive: true, force: true });
|
|
147
|
+
}
|
|
148
|
+
catch (error) {
|
|
149
|
+
failure =
|
|
150
|
+
failure === undefined ? error : new AggregateError([failure, error], "Git staging cleanup failed");
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
}
|
|
154
|
+
if (!terminationObserved && completion !== undefined)
|
|
155
|
+
throw failure ?? executionFailure ?? new VerifiedRunError("git_effect_unsettled");
|
|
156
|
+
// An abort racing the CAS cannot erase a ref that is already committed.
|
|
157
|
+
if (!callbackFailed &&
|
|
158
|
+
failure instanceof VerifiedRunError &&
|
|
159
|
+
["cancelled", "deadline", "git_worker_failed"].includes(failure.code) &&
|
|
160
|
+
preparedOid &&
|
|
161
|
+
resolveRef(request.workspace, OMK_ACCEPTED_REF) === preparedOid) {
|
|
162
|
+
if (!afterCasCalled)
|
|
163
|
+
await request.afterCas?.();
|
|
164
|
+
return { kind: "committed", candidateOid: preparedOid };
|
|
165
|
+
}
|
|
166
|
+
if (failure !== undefined)
|
|
167
|
+
throw failure;
|
|
168
|
+
if (executionFailure !== undefined)
|
|
169
|
+
throw executionFailure;
|
|
170
|
+
if (!result)
|
|
171
|
+
throw new VerifiedRunError("git_worker_failed");
|
|
172
|
+
return result;
|
|
173
|
+
}
|
|
174
|
+
//# sourceMappingURL=git-effect-supervisor.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-effect-supervisor.js","sourceRoot":"","sources":["../../../src/core/verified-run/git-effect-supervisor.ts"],"names":[],"mappings":"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","sourcesContent":["import { existsSync, rmSync } from \"node:fs\";\nimport { join } from \"node:path\";\nimport { setTimeout as delay } from \"node:timers/promises\";\nimport { canonicalClaim, type ResourceClaimInput, sameClaimSet } from \"../../coordination/resource.ts\";\nimport type { GrantToken } from \"../../coordination/types.ts\";\nimport { sameGrantToken } from \"./authority-meaning.ts\";\nimport type { RunAuthority } from \"./authority-runtime.ts\";\nimport { executeSandbox, type SandboxOutcome } from \"./broker.ts\";\nimport type { GitOperationBudget } from \"./git-execution.ts\";\nimport { OMK_ACCEPTED_REF, resolveRef, type SealCandidateInput } from \"./git-plumbing.ts\";\nimport { type GitWorkerNotice, readGitNotice, writeGitControl } from \"./git-worker-protocol.ts\";\nimport { type GitWorkerRuntime, type GitWorkerStage, prepareGitWorker } from \"./git-worker-runtime.ts\";\nimport type { NamespaceIdentity } from \"./namespace-identity.ts\";\nimport { VerifiedRunError } from \"./storage.ts\";\nimport { loadSupervisorBackend, probeOwnedNamespace } from \"./supervisor-adapter.ts\";\n\nexport interface OwnedGitPublication {\n\treadonly workspace: string;\n\treadonly input: SealCandidateInput;\n\treadonly authority: RunAuthority;\n\treadonly token: GrantToken;\n\treadonly claims: readonly ResourceClaimInput[];\n\treadonly runtime: GitWorkerRuntime;\n\treadonly budget: GitOperationBudget;\n\treadonly deadlineNs: string;\n\treadonly cleanupMs: number;\n\treadonly signal?: AbortSignal;\n\treadonly onPrepared: (candidateOid: string) => void | Promise<void>;\n\treadonly afterCas?: () => void | Promise<void>;\n}\n\n/** One owner for staging, durable dispatch, seal/CAS gates, namespace drain and grant settlement. */\nexport async function executeOwnedGitPublication(request: OwnedGitPublication): Promise<GitWorkerNotice> {\n\tconst authority = request.authority.store.state;\n\tconst reservation = authority.grants.get(request.token.grantSequence);\n\tif (\n\t\t!reservation ||\n\t\treservation.state !== \"reserved\" ||\n\t\treservation.effectLive ||\n\t\t!sameGrantToken(reservation.token, request.token) ||\n\t\tauthority.epoch !== request.token.authorityEpoch ||\n\t\tauthority.incarnations.get(request.token.sessionId) !== request.token.sessionIncarnation ||\n\t\t!sameClaimSet(\n\t\t\tArray.from(request.claims, (claim) => canonicalClaim(claim)),\n\t\t\treservation.claims,\n\t\t)\n\t)\n\t\tthrow new VerifiedRunError(\"authority\");\n\tloadSupervisorBackend();\n\tconst controller = new AbortController();\n\tconst cancel = () => controller.abort();\n\trequest.signal?.addEventListener(\"abort\", cancel, { once: true });\n\tif (request.signal?.aborted) cancel();\n\tlet stage: GitWorkerStage | undefined;\n\tlet identity: NamespaceIdentity | undefined;\n\tlet completion: Promise<void> | undefined;\n\tlet finished = false;\n\tlet outcome: SandboxOutcome | undefined;\n\tlet executionFailure: unknown;\n\tlet failure: unknown;\n\tlet result: GitWorkerNotice | undefined;\n\tlet preparedOid: string | undefined;\n\tlet terminationObserved = false;\n\tlet afterCasCalled = false;\n\tlet callbackFailed = false;\n\tconst { store } = request.authority;\n\tconst waitNotice = async (name: string): Promise<GitWorkerNotice> => {\n\t\tif (!stage) throw new VerifiedRunError(\"git_worker_protocol\");\n\t\tconst path = join(stage.root, name);\n\t\twhile (!existsSync(path)) {\n\t\t\tif (finished) throw executionFailure ?? new VerifiedRunError(outcome?.failure ?? \"git_worker_failed\");\n\t\t\trequest.budget.remaining();\n\t\t\tawait delay(5);\n\t\t}\n\t\treturn readGitNotice(path);\n\t};\n\ttry {\n\t\trequest.budget.remaining();\n\t\tstage = prepareGitWorker(request.workspace, request.runtime, {\n\t\t\tinput: request.input,\n\t\t\ttimeoutMs: Math.min(60_000, request.budget.remainingWorkMs()),\n\t\t\tdeadlineNs: request.deadlineNs,\n\t\t});\n\t\trequest.budget.remaining();\n\t\tif (!store.dispatchIntent(request.token, stage.dispatchId)) throw new VerifiedRunError(\"authority\");\n\t\tcompletion = executeSandbox({\n\t\t\tworkspace: request.workspace,\n\t\t\twritable: false,\n\t\t\tgitPublication: true,\n\t\t\targv: [\"/omk-node\", \"--experimental-strip-types\", stage.worker, stage.request],\n\t\t\ttimeoutMs: request.budget.remainingWorkMs(),\n\t\t\tcleanupMs: request.cleanupMs,\n\t\t\tmaxOutputBytes: 8192,\n\t\t\tsignal: controller.signal,\n\t\t\tonReady: (ready) => {\n\t\t\t\tidentity = ready;\n\t\t\t\tif (!store.effectStarted(request.token, request.claims, ready)) throw new VerifiedRunError(\"authority\");\n\t\t\t},\n\t\t}).then(\n\t\t\t(value) => {\n\t\t\t\toutcome = value;\n\t\t\t\tterminationObserved = true;\n\t\t\t\tfinished = true;\n\t\t\t},\n\t\t\t(error: unknown) => {\n\t\t\t\texecutionFailure = error;\n\t\t\t\tfinished = true;\n\t\t\t},\n\t\t);\n\t\tconst prepared = await waitNotice(\"prepared.json\");\n\t\tif (prepared.kind !== \"prepared\") throw new VerifiedRunError(\"git_worker_protocol\");\n\t\tpreparedOid = prepared.candidateOid;\n\t\ttry {\n\t\t\tawait request.onPrepared(preparedOid);\n\t\t} catch (error) {\n\t\t\tcallbackFailed = true;\n\t\t\tthrow error;\n\t\t}\n\t\trequest.budget.remaining();\n\t\tif (!store.effectAuthorized(request.token, request.claims)) throw new VerifiedRunError(\"authority\");\n\t\twriteGitControl(join(stage.root, \"cas-go.json\"), {\n\t\t\t...prepared,\n\t\t\tauthorizationDeadline: request.token.authorizationDeadline,\n\t\t});\n\t\tresult = await waitNotice(\"result.json\");\n\t\tif (result.kind === \"prepared\" || result.candidateOid !== preparedOid)\n\t\t\tthrow new VerifiedRunError(\"git_worker_protocol\");\n\t\tif (result.kind === \"committed\") {\n\t\t\tafterCasCalled = true;\n\t\t\ttry {\n\t\t\t\tawait request.afterCas?.();\n\t\t\t} catch (error) {\n\t\t\t\tcallbackFailed = true;\n\t\t\t\tthrow error;\n\t\t\t}\n\t\t}\n\t\twriteGitControl(join(stage.root, \"finish.json\"), result);\n\t} catch (error) {\n\t\tfailure = error;\n\t\tcontroller.abort();\n\t} finally {\n\t\tawait completion;\n\t\trequest.signal?.removeEventListener(\"abort\", cancel);\n\t\t// A callback error may reject the broker even after drain. Re-observe, never infer it.\n\t\tif (!terminationObserved && identity) terminationObserved = probeOwnedNamespace(identity) === \"terminated\";\n\t\tconst neverStarted =\n\t\t\tcompletion === undefined ||\n\t\t\t(!identity &&\n\t\t\t\texecutionFailure instanceof VerifiedRunError &&\n\t\t\t\t[\"cancelled\", \"deadline\", \"unsupported_boundary\"].includes(executionFailure.code));\n\t\ttry {\n\t\t\tif (terminationObserved || neverStarted) store.confirmTerminated(request.token);\n\t\t\telse store.cancel(request.token);\n\t\t} catch (error) {\n\t\t\tfailure =\n\t\t\t\tfailure === undefined ? error : new AggregateError([failure, error], \"Git authority settlement failed\");\n\t\t}\n\t\tif (stage && (terminationObserved || neverStarted)) {\n\t\t\ttry {\n\t\t\t\trmSync(stage.root, { recursive: true, force: true });\n\t\t\t} catch (error) {\n\t\t\t\tfailure =\n\t\t\t\t\tfailure === undefined ? error : new AggregateError([failure, error], \"Git staging cleanup failed\");\n\t\t\t}\n\t\t}\n\t}\n\tif (!terminationObserved && completion !== undefined)\n\t\tthrow failure ?? executionFailure ?? new VerifiedRunError(\"git_effect_unsettled\");\n\t// An abort racing the CAS cannot erase a ref that is already committed.\n\tif (\n\t\t!callbackFailed &&\n\t\tfailure instanceof VerifiedRunError &&\n\t\t[\"cancelled\", \"deadline\", \"git_worker_failed\"].includes(failure.code) &&\n\t\tpreparedOid &&\n\t\tresolveRef(request.workspace, OMK_ACCEPTED_REF) === preparedOid\n\t) {\n\t\tif (!afterCasCalled) await request.afterCas?.();\n\t\treturn { kind: \"committed\", candidateOid: preparedOid };\n\t}\n\tif (failure !== undefined) throw failure;\n\tif (executionFailure !== undefined) throw executionFailure;\n\tif (!result) throw new VerifiedRunError(\"git_worker_failed\");\n\treturn result;\n}\n"]}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
export declare class GitOperationBudget {
|
|
2
|
+
private readonly deadline;
|
|
3
|
+
private readonly clock;
|
|
4
|
+
private readonly signal;
|
|
5
|
+
private readonly counts;
|
|
6
|
+
constructor(options?: {
|
|
7
|
+
timeoutMs?: number;
|
|
8
|
+
signal?: AbortSignal;
|
|
9
|
+
clock?: () => number;
|
|
10
|
+
});
|
|
11
|
+
remaining(): number;
|
|
12
|
+
remainingWorkMs(): number;
|
|
13
|
+
record(command: string): void;
|
|
14
|
+
get commandCounts(): Readonly<Record<string, number>>;
|
|
15
|
+
}
|
|
16
|
+
export declare function assertPrivateEmptyHooks(path: string): void;
|
|
17
|
+
/** A private hooks directory belongs to this synchronous child, never to a predictable shared path. */
|
|
18
|
+
export declare function runGit(root: string, args: readonly string[], options?: {
|
|
19
|
+
write?: boolean;
|
|
20
|
+
input?: Buffer;
|
|
21
|
+
allowedExitCodes?: readonly number[];
|
|
22
|
+
budget?: GitOperationBudget;
|
|
23
|
+
}): {
|
|
24
|
+
status: number;
|
|
25
|
+
stdout: Buffer;
|
|
26
|
+
};
|
|
27
|
+
//# sourceMappingURL=git-execution.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"git-execution.d.ts","sourceRoot":"","sources":["../../../src/core/verified-run/git-execution.ts"],"names":[],"mappings":"AAWA,qBAAa,kBAAkB;IAC9B,OAAO,CAAC,QAAQ,CAAC,QAAQ,CAAS;IAClC,OAAO,CAAC,QAAQ,CAAC,KAAK,CAAe;IACrC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA0B;IACjD,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;IACpD,YAAY,OAAO,GAAE;QAAE,SAAS,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,WAAW,CAAC;QAAC,KAAK,CAAC,EAAE,MAAM,MAAM,CAAA;KAAO,EAM3F;IACD,SAAS,IAAI,MAAM,CAElB;IACD,eAAe,IAAI,MAAM,CAKxB;IACD,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,IAAI,CAE5B;IACD,IAAI,aAAa,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAEpD;CACD;AAED,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,MAAM,GAAG,IAAI,CAU1D;AAuBD,uGAAuG;AACvG,wBAAgB,MAAM,CACrB,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,SAAS,MAAM,EAAE,EACvB,OAAO,GAAE;IAAE,KAAK,CAAC,EAAE,OAAO,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,gBAAgB,CAAC,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,kBAAkB,CAAA;CAAO,GAClH;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,MAAM,EAAE,MAAM,CAAA;CAAE,CA0CpC","sourcesContent":["import { spawnSync } from \"node:child_process\";\nimport { chmodSync, lstatSync, mkdtempSync, readdirSync, rmSync } from \"node:fs\";\nimport { devNull, tmpdir } from \"node:os\";\nimport { join } from \"node:path\";\nimport { performance } from \"node:perf_hooks\";\nimport { VerifiedRunError } from \"./storage.ts\";\n\nconst COMMAND_TIMEOUT_MS = 30_000;\nconst MAX_OUTPUT_BYTES = 16 * 1024 * 1024;\nconst ENV_NAMES = [\"PATH\", \"SystemRoot\", \"SYSTEMROOT\", \"WINDIR\", \"TMPDIR\", \"TEMP\", \"TMP\"];\n\nexport class GitOperationBudget {\n\tprivate readonly deadline: number;\n\tprivate readonly clock: () => number;\n\tprivate readonly signal: AbortSignal | undefined;\n\tprivate readonly counts = new Map<string, number>();\n\tconstructor(options: { timeoutMs?: number; signal?: AbortSignal; clock?: () => number } = {}) {\n\t\tconst timeout = options.timeoutMs ?? COMMAND_TIMEOUT_MS;\n\t\tif (!Number.isFinite(timeout) || timeout <= 0) throw new VerifiedRunError(\"deadline\");\n\t\tthis.clock = options.clock ?? (() => performance.now());\n\t\tthis.deadline = this.clock() + timeout;\n\t\tthis.signal = options.signal;\n\t}\n\tremaining(): number {\n\t\treturn Math.min(COMMAND_TIMEOUT_MS, this.remainingWorkMs());\n\t}\n\tremainingWorkMs(): number {\n\t\tif (this.signal?.aborted) throw new VerifiedRunError(\"cancelled\");\n\t\tconst remaining = this.deadline - this.clock();\n\t\tif (!(remaining > 0)) throw new VerifiedRunError(\"deadline\");\n\t\treturn Math.max(1, Math.ceil(remaining));\n\t}\n\trecord(command: string): void {\n\t\tthis.counts.set(command, (this.counts.get(command) ?? 0) + 1);\n\t}\n\tget commandCounts(): Readonly<Record<string, number>> {\n\t\treturn Object.freeze(Object.fromEntries(this.counts));\n\t}\n}\n\nexport function assertPrivateEmptyHooks(path: string): void {\n\tconst stat = lstatSync(path);\n\tif (\n\t\t!stat.isDirectory() ||\n\t\tstat.isSymbolicLink() ||\n\t\t(stat.mode & 0o777) !== 0o700 ||\n\t\t(process.getuid && stat.uid !== process.getuid()) ||\n\t\treaddirSync(path).length !== 0\n\t)\n\t\tthrow new VerifiedRunError(\"git_hooks_boundary\");\n}\n\nfunction gitEnvironment(write: boolean): NodeJS.ProcessEnv {\n\tconst env: NodeJS.ProcessEnv = {};\n\tfor (const name of ENV_NAMES) if (process.env[name] !== undefined) env[name] = process.env[name];\n\treturn {\n\t\t...env,\n\t\tGIT_CONFIG_NOSYSTEM: \"1\",\n\t\tGIT_CONFIG_GLOBAL: devNull,\n\t\tGIT_CONFIG_COUNT: \"0\",\n\t\tGIT_TERMINAL_PROMPT: \"0\",\n\t\tGIT_NO_REPLACE_OBJECTS: \"1\",\n\t\tGIT_OPTIONAL_LOCKS: write ? \"1\" : \"0\",\n\t\tLC_ALL: \"C\",\n\t\tGIT_AUTHOR_NAME: \"OMK verified-run\",\n\t\tGIT_AUTHOR_EMAIL: \"omk-verified-run@localhost\",\n\t\tGIT_AUTHOR_DATE: \"2000-01-01T00:00:00Z\",\n\t\tGIT_COMMITTER_NAME: \"OMK verified-run\",\n\t\tGIT_COMMITTER_EMAIL: \"omk-verified-run@localhost\",\n\t\tGIT_COMMITTER_DATE: \"2000-01-01T00:00:00Z\",\n\t};\n}\n\n/** A private hooks directory belongs to this synchronous child, never to a predictable shared path. */\nexport function runGit(\n\troot: string,\n\targs: readonly string[],\n\toptions: { write?: boolean; input?: Buffer; allowedExitCodes?: readonly number[]; budget?: GitOperationBudget } = {},\n): { status: number; stdout: Buffer } {\n\tconst budget = options.budget ?? new GitOperationBudget();\n\tbudget.remaining();\n\tconst hooks = mkdtempSync(join(tmpdir(), \"omk-verified-git-\"));\n\ttry {\n\t\tchmodSync(hooks, 0o700);\n\t\tassertPrivateEmptyHooks(hooks);\n\t\tconst isolated = [\n\t\t\t\"-c\",\n\t\t\t`core.hooksPath=${hooks}`,\n\t\t\t\"-c\",\n\t\t\t\"core.fsmonitor=false\",\n\t\t\t\"-c\",\n\t\t\t\"gc.auto=0\",\n\t\t\t\"-c\",\n\t\t\t\"maintenance.auto=false\",\n\t\t\t\"-c\",\n\t\t\t\"commit.gpgsign=false\",\n\t\t\t\"-C\",\n\t\t\troot,\n\t\t\t...args,\n\t\t];\n\t\tconst timeout = budget.remaining();\n\t\tbudget.record(args[0] ?? \"unknown\");\n\t\tconst result = spawnSync(\"git\", isolated, {\n\t\t\tenv: gitEnvironment(options.write === true),\n\t\t\tmaxBuffer: MAX_OUTPUT_BYTES,\n\t\t\ttimeout,\n\t\t\tkillSignal: \"SIGKILL\",\n\t\t\tstdio: [options.input === undefined ? \"ignore\" : \"pipe\", \"pipe\", \"pipe\"],\n\t\t\tinput: options.input,\n\t\t\twindowsHide: true,\n\t\t});\n\t\tif (result.error !== undefined)\n\t\t\tthrow new VerifiedRunError(options.write ? \"git_outcome_unknown\" : \"git_plumbing\");\n\t\tconst allowed = options.allowedExitCodes ?? [0];\n\t\tif (result.status === null || !allowed.includes(result.status)) throw new VerifiedRunError(\"git_plumbing\");\n\t\treturn { status: result.status, stdout: result.stdout };\n\t} finally {\n\t\t// spawnSync has observed the direct child's exit, including SIGKILL on timeout.\n\t\trmSync(hooks, { recursive: true, force: true });\n\t}\n}\n"]}
|