chainlesschain 0.165.2 → 0.165.4
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/README.md +151 -29
- package/package.json +2 -2
- package/src/assets/web-panel/assets/{AIOps-lS1R0Cza.js → AIOps-C__nnraW.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BmlgBPsj.js → ActionButton-CsKWHEZ-.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CNKczv1S.js → Analytics-BhIjfjWO.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-BuZGJARQ.js → AppLayout-BjuXFzWZ.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-Dm73Sl-O.js → Artifacts-k6whDkZJ.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BGMW7A5e.js → Audit-C4FBMYRh.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-BQ6M54JR.js → BackgroundAgents-C_vRrSXk.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-DBzGP0bR.js → Backup-CngFZeVp.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-D1mLCoOV.js → BaseInput-B_H9EBRm.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BUfcN7p8.js → Chat-DLEC5kt7.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-xijcWkJe.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-Du0Yg5Pi.js → Checkbox-m3ClR4xh.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-B2RXziHW.js → Codegen-CmLSFrgp.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DWhekOrR.js → Col-DFGQteHN.js} +1 -1
- package/src/assets/web-panel/assets/{Community-HQhrkon4.js → Community-EUUVORHE.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-izHNb4uz.js → Compact-2PSg0Yr7.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BDwLy41-.js → Compliance-CcKur7gB.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DFJhLa7K.js → Cowork-DK_Fezfa.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-DYY9RG7-.js → Cron-Dbw89xl7.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-rr7tJTtv.js → Crosschain-CH66h_Ec.js} +1 -1
- package/src/assets/web-panel/assets/{DID-D2sfHRLi.js → DID-D1igRb17.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-q_eGdhha.js → Dashboard-DVAsrobk.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Cufrh2Bz.js → Dropdown-Dl7W8AQs.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-B-kdv10f.js → EmailListRenderer-D5tpaEQC.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-D21XjgfG.js → FamilyGuardDashboard-O_VQf8gq.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CAwRTLZH.js → Federation-BTVcgS9n.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-vx3daNDF.js → FormItemContext-BRnkJAIz.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-CRWY2wU4.js → GenericCardRenderer-8OWSCkDj.js} +1 -1
- package/src/assets/web-panel/assets/{Git-Q6SwauyD.js → Git-WXLYTQj2.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-BJ1q4IQZ.js → Governance-BezaUhtc.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CSWjROgD.js → Inference-CuRay3Gu.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-fzuQsWuY.js → KnowledgeGraph-DfWLDW1m.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-DVF8Mnns.js → Logs-C55y2pPY.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-hDpWdiBc.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-BQP7LOA4.js → Marketplace-Dk08Uycg.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BNlJCmNc.js → McpTools-C11fSB5V.js} +4 -4
- package/src/assets/web-panel/assets/{Memory-DLLg5WQ4.js → Memory-mr0eZc97.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CR2skNAF.js → MobileBridge-C0iCSRbb.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BxVavObl.js → MobileProjects-CY-xMG8Z.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-B17pgqMI.js → Mtc-Bplqc_Wc.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-4UmV5cIL.js → MtcAudit-BlzwsoSM.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DoMEXEcU.js → Multisig-BBLmTty6.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-h9DMXFX4.js → NLProgramming-DtT1uf1W.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-Cihn-xX8.js → Notes-DcqQAxTK.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-BE6ZGa3R.js → NotificationSettings-cb0kWoZe.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-CnwojoSI.js → OrderTableRenderer-kw9HZQNN.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-B2vpwmjb.js → Organization-DlTlbkUN.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-C4z28R0-.js → Overflow-pp1qs-oY.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-BVlFkwhW.js → P2P-BESLnyYz.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BXbEdL5B.js → PdhVaultBrowser-B-J1mGuf.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-C28xs4lp.js → Permissions-B36PeT1_.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Dgl_rBjM.js → PersonalDataHub-CTK2ad-3.js} +3 -3
- package/src/assets/web-panel/assets/{Pipeline-3QUIhrKI.js → Pipeline-zJNGXsac.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-8Gh33OZ5.js → Privacy-b9fz0Qf0.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BNmg4tZi.js → ProjectInit-DjZbZgiB.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-vgMfeCf9.js → ProjectSettings-C-hHJXlD.js} +2 -2
- package/src/assets/web-panel/assets/Projects-BC9KSDM6.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CXoOa8eX.js → Providers-Dz-CAYYU.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BhfTF0oS.js → QrScannerModal-A0yoQ3-3.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-C746HEAj.js → QuickAsk-DrFgFJNC.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-BSej8Eo0.js → Recommend-KC8hF1g4.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-f3gmnlG3.js → RemoteSession-DGTPIk6u.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-CyvybpkN.js → Reputation-QmbwM7Yk.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DwV2PeYn.js → Row-BxjJylia.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-11GrzjZy.js → RssFeed-B7Wda1J6.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BjKXkrAY.js → Search-_plQ_YSA.js} +1 -1
- package/src/assets/web-panel/assets/{Security-eWiFb9Yk.js → Security-CD2YJZfx.js} +2 -2
- package/src/assets/web-panel/assets/{Services-CdCsMAtt.js → Services-qQE7NmwE.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-4Q2UTKQ5.js → Skeleton-DgQqkFf7.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-v4rtYrRj.js → Skills-C4C0oFFt.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-CRhsFvd_.js → Sla-Px2N2B5c.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-DN6C3lQd.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-D16zonl7.js → SyncSettings-jm5aH_m7.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Xxozz0i_.js → Tasks-DlkJcv67.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CXJpPtCT.js → Templates-DyrTHUBs.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-XRV0L1ZF.js → Tenant-mC434PtL.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-CYuO1i_w.js → Terminal-o0_s3NgK.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-BXqitWsu.js → TimelineRenderer-DAGlAXOw.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BvPrDHIy.js → Tokens-BnulS_bs.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DhCrSTf5.js → Trigger-suQbVXYM.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-DmsuZD6K.js → Trust-DbIJAPo5.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-D_yrts5C.js → UkeySign-CQNpbIHi.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-B01ihPrm.js → VideoEditing-D8aWCERk.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-DpUjKa-N.js → Wallet-CuLpYfZc.js} +2 -2
- package/src/assets/web-panel/assets/{WebAuthn-CL07yON6.js → WebAuthn-CsfG8ZMc.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-CLMflnRr.js → WorkflowEditor-BYsEAZbd.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DtUqe8h_.js → chat-FT4Um3-I.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DPKrgVfy.js → colors-CKbS_Wlt.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BTt2GtOm.js → compact-item-CFJtzuJM.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-D_VeUc1J.js → createContext-B9kSRW6K.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-DJZ0gAMu.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-1kndiylj.js → hasIn-DR-x0Xpi.js} +1 -1
- package/src/assets/web-panel/assets/{index-dVc-CXY4.js → index-7jHr_A_k.js} +1 -1
- package/src/assets/web-panel/assets/{index-DFIZ_1Sf.js → index-B3ZX81mK.js} +1 -1
- package/src/assets/web-panel/assets/{index-fk2Rjacw.js → index-B7osrXqy.js} +3 -3
- package/src/assets/web-panel/assets/{index-CHG-KcS4.js → index-BGbPnC5x.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dbbymxpj.js → index-BI5hP_qy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BaZAbw9A.js → index-BK3TiKVq.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzjkKUmR.js → index-BVPU43b1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BAXfRKfG.js → index-BW-t9n-q.js} +1 -1
- package/src/assets/web-panel/assets/{index-8nz_fmlj.js → index-BfFCQHL3.js} +1 -1
- package/src/assets/web-panel/assets/index-Bizb4hkw.js +1 -0
- package/src/assets/web-panel/assets/{index-DdkplL9R.js → index-Bt4fS2eL.js} +1 -1
- package/src/assets/web-panel/assets/{index-DG2MZQ3f.js → index-BwR7yc2h.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfKBRdSS.js → index-Bzz0C1BZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-GsoUQ2M7.js → index-C2JvmYRc.js} +1 -1
- package/src/assets/web-panel/assets/{index-l1BETrDb.js → index-CGaXUsIs.js} +1 -1
- package/src/assets/web-panel/assets/{index-4bna2_SR.js → index-CJmIQ9XR.js} +1 -1
- package/src/assets/web-panel/assets/{index-DfGl8CqG.js → index-C_enk9I_.js} +1 -1
- package/src/assets/web-panel/assets/{index-D95OFht7.js → index-Cr2FLUsD.js} +1 -1
- package/src/assets/web-panel/assets/{index-DsJCDUJG.js → index-CvrCCqJt.js} +1 -1
- package/src/assets/web-panel/assets/{index-sDoMHTNA.js → index-D4LfPvWA.js} +1 -1
- package/src/assets/web-panel/assets/{index-By5n8up9.js → index-DMGmg497.js} +1 -1
- package/src/assets/web-panel/assets/{index-ocf06EVQ.js → index-DShSkww-.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bhudc_Ez.js → index-DTxNy0ZU.js} +1 -1
- package/src/assets/web-panel/assets/{index-CX81qSM4.js → index-DW4BWjTk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlDNVgBt.js → index-DWdqx7zI.js} +1 -1
- package/src/assets/web-panel/assets/{index-CcO04eDn.js → index-Dap9c3eD.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dwqmtk65.js → index-DcfxhKXR.js} +1 -1
- package/src/assets/web-panel/assets/{index-2eyAXE3d.js → index-DdkIhfi-.js} +1 -1
- package/src/assets/web-panel/assets/{index-brCInrzq.js → index-DeSgw-WV.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJ8vXGOa.js → index-DiNUEpSQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-BHpBMWCh.js → index-DjEP7WkH.js} +1 -1
- package/src/assets/web-panel/assets/{index-m31Ka8hZ.js → index-DtkFqPVA.js} +1 -1
- package/src/assets/web-panel/assets/{index-CtF7EN49.js → index-KqDaCApw.js} +1 -1
- package/src/assets/web-panel/assets/index-OHSl-xCh.js +1 -0
- package/src/assets/web-panel/assets/{index-B9KvcS7R.js → index-OSzjTzGM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CauoBQkH.js → index-QBSeNVO3.js} +1 -1
- package/src/assets/web-panel/assets/{index-FzdwcSy2.js → index-WE08gMJP.js} +1 -1
- package/src/assets/web-panel/assets/{index-DxdTdBix.js → index-r2VI1Ikk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BepLZwgB.js → index-tqSEHPRT.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CvyYJd7z.js → initDefaultProps-Dd7n7VgI.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DYZkhUdz.js → motion-BwxouRw1.js} +1 -1
- package/src/assets/web-panel/assets/{move-slnJRVT1.js → move-DObN0PG9.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DVc0CKmy.js → mtc-parser-B3nOUQc7.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BCXAtHCq.js → omit-o9WU2Nbl.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DBsemz_K.js → pickAttrs-CL_vvfQ_.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-BRtkJ-nv.js → placementArrow-CYrM2tyK.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-Cebq7EZn.js → responsiveObserve-k_06cQ96.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DT7qvId2.js → slide-CPKG0pxS.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-pQiITLkG.js → statusUtils-BDDEeLTw.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-c-19BVKQ.js → styleChecker-Cmb7RTh7.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DsS5-0bE.js → useFlexGapSupport-e2IedC4N.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-CxGiMe5n.js → useFs-CE_gxVnm.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-D9btVID5.js → usePersonalDataHub-BkMIIKMz.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CUYFsFEN.js → vnode-DW886XV1.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CXmn_35j.js → zoom-Dwo_adaf.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +3 -3
- package/src/commands/agent.js +105 -35
- package/src/commands/artifacts.js +363 -33
- package/src/commands/cowork.js +202 -36
- package/src/commands/session-budget.js +155 -0
- package/src/commands/session-location.js +948 -0
- package/src/commands/session.js +72 -46
- package/src/data/changelog.json +26 -0
- package/src/gateways/ws/artifact-protocol.js +77 -13
- package/src/gateways/ws/session-protocol.js +391 -24
- package/src/gateways/ws/ws-agent-handler.js +191 -14
- package/src/gateways/ws/ws-server.js +14 -3
- package/src/gateways/ws/ws-session-gateway.js +101 -5
- package/src/harness/jsonl-session-store.js +1210 -0
- package/src/lib/agent-team/team-runner.js +43 -13
- package/src/lib/artifact-access-ledger.js +461 -0
- package/src/lib/artifact-cleanup-ledger.js +861 -0
- package/src/lib/artifact-deletion-ledger.js +677 -0
- package/src/lib/artifact-store.js +256 -51
- package/src/lib/background-agent-keeper-protocol.js +75 -4
- package/src/lib/background-agent-launch-barrier.js +74 -0
- package/src/lib/background-agent-supervisor.js +149 -5
- package/src/lib/background-turn-bootstrap-protocol.js +4 -0
- package/src/lib/command-lifecycle-report.js +8 -4
- package/src/lib/cowork-adapter.js +9 -5
- package/src/lib/cowork-task-runner.js +20 -0
- package/src/lib/cowork-workflow.js +178 -20
- package/src/lib/direct-model-usage.js +62 -22
- package/src/lib/dynamic-workflow-runtime.js +3184 -111
- package/src/lib/execution-location-result-apply.js +339 -0
- package/src/lib/execution-location-result-artifact.js +271 -0
- package/src/lib/execution-location-result-review.js +253 -0
- package/src/lib/execution-location-result-store.js +331 -0
- package/src/lib/execution-location-result.js +617 -0
- package/src/lib/execution-location-target.js +236 -1
- package/src/lib/managed-tool-checkpoint.js +47 -4
- package/src/lib/process-execution-broker/workspace-transaction.js +3 -0
- package/src/lib/session-budget-production-root.js +376 -0
- package/src/lib/session-budget-runtime.js +109 -18
- package/src/lib/session-budget-usage.js +63 -0
- package/src/lib/session-host-snapshot.js +19 -2
- package/src/lib/session-resource-budget.js +766 -105
- package/src/lib/sub-agent-context.js +69 -22
- package/src/lib/web-ui-server.js +12 -1
- package/src/lib/with-file-lock.js +175 -26
- package/src/repl/agent-repl.js +237 -16
- package/src/runtime/agent-core.js +123 -0
- package/src/runtime/headless-runner.js +135 -46
- package/src/runtime/headless-stream.js +133 -25
- package/src/runtime/policies/agent-policy.js +10 -0
- package/src/workers/background-agent-keeper.js +112 -19
- package/src/workers/background-agent-worker.js +383 -134
- package/src/workers/background-turn-bootstrap.js +13 -8
- package/src/assets/web-panel/assets/ChatBubbleRenderer-CY5m8ZHg.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-BLif4QSg.js +0 -1
- package/src/assets/web-panel/assets/Projects-BhtAVilc.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-DLjKsDVu.js +0 -1
- package/src/assets/web-panel/assets/devWarning-Bj5nUW2v.js +0 -1
- package/src/assets/web-panel/assets/index-CPcM-eqo.js +0 -1
- package/src/assets/web-panel/assets/index-xeSyVoRe.js +0 -1
|
@@ -83,6 +83,12 @@ import {
|
|
|
83
83
|
readSessionAntiRollbackAnchor,
|
|
84
84
|
sessionAntiRollbackPredecessorWitness,
|
|
85
85
|
} from "../lib/session-anti-rollback-anchor.js";
|
|
86
|
+
import { normalizeSessionBudgetRootConfig } from "../lib/session-budget-production-root.js";
|
|
87
|
+
import {
|
|
88
|
+
normalizeExecutionLocationResultBundle,
|
|
89
|
+
verifyExecutionLocationResultBundle,
|
|
90
|
+
} from "../lib/execution-location-result.js";
|
|
91
|
+
import { normalizeExecutionLocationResultStoreReceipt } from "../lib/execution-location-result-store.js";
|
|
86
92
|
|
|
87
93
|
let securedSessionsDir = null;
|
|
88
94
|
let securedSessionsDirIdentity = null;
|
|
@@ -114,6 +120,9 @@ export const _sessionScaleFaultHooks = Object.seal({
|
|
|
114
120
|
beforeReplicaDirectoryFsync: null,
|
|
115
121
|
afterReplicaDirectoryFsync: null,
|
|
116
122
|
afterLocationHandoffAppend: null,
|
|
123
|
+
afterResultCollectionSettlementAppend: null,
|
|
124
|
+
afterResultApplyReservationAppend: null,
|
|
125
|
+
afterResultApplyTerminalAppend: null,
|
|
117
126
|
beforeDeleteDirectoryFsync: null,
|
|
118
127
|
afterDeleteDirectoryFsync: null,
|
|
119
128
|
afterAntiRollbackPublish: null,
|
|
@@ -134,6 +143,26 @@ export const SESSION_EXECUTION_LOCATION_HANDOFF_SCHEMA =
|
|
|
134
143
|
"chainlesschain.session-execution-location-handoff/v1";
|
|
135
144
|
export const SESSION_EXECUTION_LOCATION_HANDOFF_INSTALL_SCHEMA =
|
|
136
145
|
"chainlesschain.session-execution-location-handoff-install/v1";
|
|
146
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_EVENT =
|
|
147
|
+
"execution_location_result_collection";
|
|
148
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA_V1 =
|
|
149
|
+
"chainlesschain.session-execution-location-result-collection/v1";
|
|
150
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA =
|
|
151
|
+
"chainlesschain.session-execution-location-result-collection/v2";
|
|
152
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA_V1 =
|
|
153
|
+
"chainlesschain.session-execution-location-result-collection-receipt/v1";
|
|
154
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA =
|
|
155
|
+
"chainlesschain.session-execution-location-result-collection-receipt/v2";
|
|
156
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_APPLY_RESERVATION_EVENT =
|
|
157
|
+
"execution_location_result_apply_reserved";
|
|
158
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_APPLY_RESERVATION_SCHEMA =
|
|
159
|
+
"chainlesschain.session-execution-location-result-apply-reservation/v1";
|
|
160
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_APPLY_TERMINAL_EVENT =
|
|
161
|
+
"execution_location_result_apply_terminal";
|
|
162
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_APPLY_TERMINAL_SCHEMA =
|
|
163
|
+
"chainlesschain.session-execution-location-result-apply-terminal/v1";
|
|
164
|
+
export const SESSION_EXECUTION_LOCATION_RESULT_APPLY_RECEIPT_SCHEMA =
|
|
165
|
+
"chainlesschain.session-execution-location-result-apply-receipt/v1";
|
|
137
166
|
export const MAX_SESSION_REPLICA_BYTES = 64 * 1024 * 1024;
|
|
138
167
|
const WS_TURN_CONTENT_MAX_BYTES = 4 * 1024 * 1024;
|
|
139
168
|
const WS_TURN_REQUEST_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:@-]*$/;
|
|
@@ -2639,6 +2668,13 @@ export function startSession(sessionId, meta = {}) {
|
|
|
2639
2668
|
),
|
|
2640
2669
|
}
|
|
2641
2670
|
: {}),
|
|
2671
|
+
...(meta.sessionBudgetRoot != null
|
|
2672
|
+
? {
|
|
2673
|
+
sessionBudgetRoot: normalizeSessionBudgetRootConfig(
|
|
2674
|
+
meta.sessionBudgetRoot,
|
|
2675
|
+
),
|
|
2676
|
+
}
|
|
2677
|
+
: {}),
|
|
2642
2678
|
});
|
|
2643
2679
|
|
|
2644
2680
|
return id;
|
|
@@ -2677,6 +2713,16 @@ export function getVerifiedSessionExecutionLocationAuthority(sessionId) {
|
|
|
2677
2713
|
executionLocation = locationHandoff.target.binding;
|
|
2678
2714
|
bindingEventHash = event.hash;
|
|
2679
2715
|
bindingEventCount = eventCount;
|
|
2716
|
+
return;
|
|
2717
|
+
}
|
|
2718
|
+
if (
|
|
2719
|
+
event?.type === SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_EVENT
|
|
2720
|
+
) {
|
|
2721
|
+
projectSessionResultCollectionSettlement(
|
|
2722
|
+
sessionId,
|
|
2723
|
+
event,
|
|
2724
|
+
eventCount,
|
|
2725
|
+
);
|
|
2680
2726
|
}
|
|
2681
2727
|
},
|
|
2682
2728
|
finish(authority) {
|
|
@@ -3813,6 +3859,1170 @@ function sessionLocationHandoffInstallReceipt(
|
|
|
3813
3859
|
});
|
|
3814
3860
|
}
|
|
3815
3861
|
|
|
3862
|
+
function normalizeSessionLocationDigest(value, field) {
|
|
3863
|
+
const normalized = boundedAuthorityString(value, field, 80).toLowerCase();
|
|
3864
|
+
if (!/^sha256:[a-f0-9]{64}$/u.test(normalized)) {
|
|
3865
|
+
throw new TypeError(`${field} is invalid`);
|
|
3866
|
+
}
|
|
3867
|
+
return normalized;
|
|
3868
|
+
}
|
|
3869
|
+
|
|
3870
|
+
function normalizeSessionLocationHead(value, field) {
|
|
3871
|
+
const normalized = boundedAuthorityString(value, field, 64).toLowerCase();
|
|
3872
|
+
if (!/^[a-f0-9]{64}$/u.test(normalized)) {
|
|
3873
|
+
throw new TypeError(`${field} is invalid`);
|
|
3874
|
+
}
|
|
3875
|
+
return normalized;
|
|
3876
|
+
}
|
|
3877
|
+
|
|
3878
|
+
function normalizeSessionLocationEventCount(value, field) {
|
|
3879
|
+
const normalized = Number(value);
|
|
3880
|
+
if (!Number.isSafeInteger(normalized) || normalized < 1) {
|
|
3881
|
+
throw new TypeError(`${field} is invalid`);
|
|
3882
|
+
}
|
|
3883
|
+
return normalized;
|
|
3884
|
+
}
|
|
3885
|
+
|
|
3886
|
+
function normalizeSessionResultCollectionRequestId(value) {
|
|
3887
|
+
const requestId = boundedAuthorityString(
|
|
3888
|
+
value,
|
|
3889
|
+
"result collection request id",
|
|
3890
|
+
128,
|
|
3891
|
+
);
|
|
3892
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:@+-]{0,127}$/u.test(requestId)) {
|
|
3893
|
+
throw new TypeError("result collection request id is invalid");
|
|
3894
|
+
}
|
|
3895
|
+
return requestId;
|
|
3896
|
+
}
|
|
3897
|
+
|
|
3898
|
+
function normalizeSessionResultCollectionSource(value, sessionId) {
|
|
3899
|
+
const source = exactRecord(
|
|
3900
|
+
value,
|
|
3901
|
+
["sessionId", "headHash", "eventCount"],
|
|
3902
|
+
"session result collection source",
|
|
3903
|
+
);
|
|
3904
|
+
if (source.sessionId !== sessionId) {
|
|
3905
|
+
throw new TypeError("session result collection source is invalid");
|
|
3906
|
+
}
|
|
3907
|
+
return Object.freeze({
|
|
3908
|
+
sessionId,
|
|
3909
|
+
headHash: normalizeSessionLocationHead(
|
|
3910
|
+
source.headHash,
|
|
3911
|
+
"result collection source head",
|
|
3912
|
+
),
|
|
3913
|
+
eventCount: normalizeSessionLocationEventCount(
|
|
3914
|
+
source.eventCount,
|
|
3915
|
+
"result collection source event count",
|
|
3916
|
+
),
|
|
3917
|
+
});
|
|
3918
|
+
}
|
|
3919
|
+
|
|
3920
|
+
function createSessionResultCollectionSettlementData(
|
|
3921
|
+
sessionId,
|
|
3922
|
+
requestIdInput,
|
|
3923
|
+
collection,
|
|
3924
|
+
storageInput,
|
|
3925
|
+
) {
|
|
3926
|
+
if (
|
|
3927
|
+
!collection ||
|
|
3928
|
+
typeof collection !== "object" ||
|
|
3929
|
+
Array.isArray(collection)
|
|
3930
|
+
) {
|
|
3931
|
+
throw new TypeError("execution-location result collection is invalid");
|
|
3932
|
+
}
|
|
3933
|
+
const requestId = normalizeSessionResultCollectionRequestId(requestIdInput);
|
|
3934
|
+
if (
|
|
3935
|
+
collection.schema !== "cc-execution-location-target-result-collection/v1" ||
|
|
3936
|
+
collection.requestId !== requestId ||
|
|
3937
|
+
collection.applied !== false
|
|
3938
|
+
) {
|
|
3939
|
+
throw new TypeError("execution-location result collection is invalid");
|
|
3940
|
+
}
|
|
3941
|
+
const source = normalizeSessionResultCollectionSource(
|
|
3942
|
+
collection.sourceAuthority,
|
|
3943
|
+
sessionId,
|
|
3944
|
+
);
|
|
3945
|
+
const bundle = normalizeExecutionLocationResultBundle(collection.bundle);
|
|
3946
|
+
const verification = verifyExecutionLocationResultBundle({
|
|
3947
|
+
bundle,
|
|
3948
|
+
sourceAuthority: source,
|
|
3949
|
+
expectedHandoffId: collection.handoffId,
|
|
3950
|
+
});
|
|
3951
|
+
const target = Object.freeze({
|
|
3952
|
+
headHash: normalizeSessionLocationHead(
|
|
3953
|
+
collection.targetHeadHash,
|
|
3954
|
+
"result collection target head",
|
|
3955
|
+
),
|
|
3956
|
+
eventCount: normalizeSessionLocationEventCount(
|
|
3957
|
+
collection.targetEventCount,
|
|
3958
|
+
"result collection target event count",
|
|
3959
|
+
),
|
|
3960
|
+
});
|
|
3961
|
+
const totalBytes = Number(verification.totalBytes);
|
|
3962
|
+
if (
|
|
3963
|
+
!Number.isSafeInteger(totalBytes) ||
|
|
3964
|
+
totalBytes < 1 ||
|
|
3965
|
+
collection.resultId !== bundle.resultId ||
|
|
3966
|
+
collection.handoffId !== bundle.session.handoffId ||
|
|
3967
|
+
collection.targetHeadHash !== bundle.session.target.headHash ||
|
|
3968
|
+
Number(collection.targetEventCount) !== bundle.session.target.eventCount ||
|
|
3969
|
+
collection.profileDigest !== bundle.session.target.profileDigest ||
|
|
3970
|
+
collection.targetFactsDigest !== bundle.session.target.targetFactsDigest ||
|
|
3971
|
+
collection.bundleDigest !== bundle.bundleDigest ||
|
|
3972
|
+
collection.verificationDigest !== verification.verificationDigest ||
|
|
3973
|
+
collection.verification?.verificationDigest !==
|
|
3974
|
+
verification.verificationDigest ||
|
|
3975
|
+
collection.verification?.applied !== false
|
|
3976
|
+
) {
|
|
3977
|
+
throw new TypeError("execution-location result verification is invalid");
|
|
3978
|
+
}
|
|
3979
|
+
const storage = normalizeExecutionLocationResultStoreReceipt(storageInput);
|
|
3980
|
+
if (
|
|
3981
|
+
storage.sessionId !== sessionId ||
|
|
3982
|
+
storage.resultId !== bundle.resultId ||
|
|
3983
|
+
storage.handoffId !== bundle.session.handoffId ||
|
|
3984
|
+
storage.bundleDigest !== bundle.bundleDigest
|
|
3985
|
+
) {
|
|
3986
|
+
throw new TypeError("execution-location result storage receipt is invalid");
|
|
3987
|
+
}
|
|
3988
|
+
const collectionMaterial = {
|
|
3989
|
+
schema: "cc-execution-location-target-result-collection/v1",
|
|
3990
|
+
requestId,
|
|
3991
|
+
requestDigest: collection.requestDigest,
|
|
3992
|
+
resultId: collection.resultId,
|
|
3993
|
+
target: collection.target,
|
|
3994
|
+
profileDigest: collection.profileDigest,
|
|
3995
|
+
targetFactsDigest: collection.targetFactsDigest,
|
|
3996
|
+
collectionAttestationDigest: collection.collectionAttestationDigest,
|
|
3997
|
+
handoffId: collection.handoffId,
|
|
3998
|
+
sourceAuthority: collection.sourceAuthority,
|
|
3999
|
+
targetHeadHash: collection.targetHeadHash,
|
|
4000
|
+
targetEventCount: collection.targetEventCount,
|
|
4001
|
+
bundleDigest: collection.bundleDigest,
|
|
4002
|
+
verificationDigest: collection.verificationDigest,
|
|
4003
|
+
applied: collection.applied,
|
|
4004
|
+
continuity: collection.continuity,
|
|
4005
|
+
gaps: collection.gaps,
|
|
4006
|
+
};
|
|
4007
|
+
if (
|
|
4008
|
+
!["wsl", "ssh", "container"].includes(collection.target) ||
|
|
4009
|
+
collection.continuity !== "single-fixed-command-response" ||
|
|
4010
|
+
JSON.stringify(collection.gaps) !==
|
|
4011
|
+
JSON.stringify([
|
|
4012
|
+
"returned-result-bytes-not-durable",
|
|
4013
|
+
"cross-host-concurrent-writer-fencing-not-durable",
|
|
4014
|
+
"returned-result-not-applied",
|
|
4015
|
+
]) ||
|
|
4016
|
+
collection.collectionDigest !==
|
|
4017
|
+
sessionLocationDigest(
|
|
4018
|
+
"chainlesschain.execution-location.target-result-collection.v1\0",
|
|
4019
|
+
collectionMaterial,
|
|
4020
|
+
)
|
|
4021
|
+
) {
|
|
4022
|
+
throw new TypeError(
|
|
4023
|
+
"execution-location result collection digest is invalid",
|
|
4024
|
+
);
|
|
4025
|
+
}
|
|
4026
|
+
const material = {
|
|
4027
|
+
schema: SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA,
|
|
4028
|
+
requestId,
|
|
4029
|
+
requestDigest: normalizeSessionLocationDigest(
|
|
4030
|
+
collection.requestDigest,
|
|
4031
|
+
"result collection request digest",
|
|
4032
|
+
),
|
|
4033
|
+
resultId: boundedAuthorityString(
|
|
4034
|
+
collection.resultId,
|
|
4035
|
+
"result collection result id",
|
|
4036
|
+
128,
|
|
4037
|
+
),
|
|
4038
|
+
handoffId: normalizeSessionLocationDigest(
|
|
4039
|
+
collection.handoffId,
|
|
4040
|
+
"result collection handoff id",
|
|
4041
|
+
),
|
|
4042
|
+
source,
|
|
4043
|
+
target,
|
|
4044
|
+
profileDigest: normalizeSessionLocationDigest(
|
|
4045
|
+
collection.profileDigest,
|
|
4046
|
+
"result collection profile digest",
|
|
4047
|
+
),
|
|
4048
|
+
targetFactsDigest: normalizeSessionLocationDigest(
|
|
4049
|
+
collection.targetFactsDigest,
|
|
4050
|
+
"result collection target facts digest",
|
|
4051
|
+
),
|
|
4052
|
+
collectionAttestationDigest: normalizeSessionLocationDigest(
|
|
4053
|
+
collection.collectionAttestationDigest,
|
|
4054
|
+
"result collection attestation digest",
|
|
4055
|
+
),
|
|
4056
|
+
bundleDigest: normalizeSessionLocationDigest(
|
|
4057
|
+
collection.bundleDigest,
|
|
4058
|
+
"result collection bundle digest",
|
|
4059
|
+
),
|
|
4060
|
+
verificationDigest: normalizeSessionLocationDigest(
|
|
4061
|
+
collection.verificationDigest,
|
|
4062
|
+
"result collection verification digest",
|
|
4063
|
+
),
|
|
4064
|
+
collectionDigest: normalizeSessionLocationDigest(
|
|
4065
|
+
collection.collectionDigest,
|
|
4066
|
+
"result collection digest",
|
|
4067
|
+
),
|
|
4068
|
+
storage,
|
|
4069
|
+
totalBytes,
|
|
4070
|
+
applied: false,
|
|
4071
|
+
};
|
|
4072
|
+
return Object.freeze({
|
|
4073
|
+
...material,
|
|
4074
|
+
settlementId: sessionLocationDigest(
|
|
4075
|
+
"chainlesschain.session-execution-location-result-collection-id.v1\0",
|
|
4076
|
+
material,
|
|
4077
|
+
),
|
|
4078
|
+
});
|
|
4079
|
+
}
|
|
4080
|
+
|
|
4081
|
+
function normalizeSessionResultCollectionSettlementData(sessionId, data) {
|
|
4082
|
+
const isLegacy =
|
|
4083
|
+
data.schema === SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA_V1;
|
|
4084
|
+
if (
|
|
4085
|
+
!isLegacy &&
|
|
4086
|
+
data.schema !== SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA
|
|
4087
|
+
) {
|
|
4088
|
+
throw new TypeError("session result collection settlement schema is invalid");
|
|
4089
|
+
}
|
|
4090
|
+
const source = normalizeSessionResultCollectionSource(data.source, sessionId);
|
|
4091
|
+
const target = exactRecord(
|
|
4092
|
+
data.target,
|
|
4093
|
+
["headHash", "eventCount"],
|
|
4094
|
+
"session result collection target",
|
|
4095
|
+
);
|
|
4096
|
+
const resultId = boundedAuthorityString(
|
|
4097
|
+
data.resultId,
|
|
4098
|
+
"result collection result id",
|
|
4099
|
+
128,
|
|
4100
|
+
);
|
|
4101
|
+
const totalBytes = Number(data.totalBytes);
|
|
4102
|
+
if (
|
|
4103
|
+
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/u.test(resultId) ||
|
|
4104
|
+
!Number.isSafeInteger(totalBytes) ||
|
|
4105
|
+
totalBytes < 1 ||
|
|
4106
|
+
data.applied !== false
|
|
4107
|
+
) {
|
|
4108
|
+
throw new TypeError("session result collection settlement is invalid");
|
|
4109
|
+
}
|
|
4110
|
+
const material = {
|
|
4111
|
+
schema: data.schema,
|
|
4112
|
+
requestId: normalizeSessionResultCollectionRequestId(data.requestId),
|
|
4113
|
+
requestDigest: normalizeSessionLocationDigest(
|
|
4114
|
+
data.requestDigest,
|
|
4115
|
+
"result collection request digest",
|
|
4116
|
+
),
|
|
4117
|
+
resultId,
|
|
4118
|
+
handoffId: normalizeSessionLocationDigest(
|
|
4119
|
+
data.handoffId,
|
|
4120
|
+
"result collection handoff id",
|
|
4121
|
+
),
|
|
4122
|
+
source,
|
|
4123
|
+
target: Object.freeze({
|
|
4124
|
+
headHash: normalizeSessionLocationHead(
|
|
4125
|
+
target.headHash,
|
|
4126
|
+
"result collection target head",
|
|
4127
|
+
),
|
|
4128
|
+
eventCount: normalizeSessionLocationEventCount(
|
|
4129
|
+
target.eventCount,
|
|
4130
|
+
"result collection target event count",
|
|
4131
|
+
),
|
|
4132
|
+
}),
|
|
4133
|
+
profileDigest: normalizeSessionLocationDigest(
|
|
4134
|
+
data.profileDigest,
|
|
4135
|
+
"result collection profile digest",
|
|
4136
|
+
),
|
|
4137
|
+
targetFactsDigest: normalizeSessionLocationDigest(
|
|
4138
|
+
data.targetFactsDigest,
|
|
4139
|
+
"result collection target facts digest",
|
|
4140
|
+
),
|
|
4141
|
+
collectionAttestationDigest: normalizeSessionLocationDigest(
|
|
4142
|
+
data.collectionAttestationDigest,
|
|
4143
|
+
"result collection attestation digest",
|
|
4144
|
+
),
|
|
4145
|
+
bundleDigest: normalizeSessionLocationDigest(
|
|
4146
|
+
data.bundleDigest,
|
|
4147
|
+
"result collection bundle digest",
|
|
4148
|
+
),
|
|
4149
|
+
verificationDigest: normalizeSessionLocationDigest(
|
|
4150
|
+
data.verificationDigest,
|
|
4151
|
+
"result collection verification digest",
|
|
4152
|
+
),
|
|
4153
|
+
collectionDigest: normalizeSessionLocationDigest(
|
|
4154
|
+
data.collectionDigest,
|
|
4155
|
+
"result collection digest",
|
|
4156
|
+
),
|
|
4157
|
+
...(!isLegacy
|
|
4158
|
+
? {
|
|
4159
|
+
storage: normalizeExecutionLocationResultStoreReceipt(data.storage),
|
|
4160
|
+
}
|
|
4161
|
+
: {}),
|
|
4162
|
+
totalBytes,
|
|
4163
|
+
applied: false,
|
|
4164
|
+
};
|
|
4165
|
+
const settlementId = sessionLocationDigest(
|
|
4166
|
+
"chainlesschain.session-execution-location-result-collection-id.v1\0",
|
|
4167
|
+
material,
|
|
4168
|
+
);
|
|
4169
|
+
if (data.settlementId !== settlementId) {
|
|
4170
|
+
throw new TypeError("session result collection settlement id is invalid");
|
|
4171
|
+
}
|
|
4172
|
+
if (
|
|
4173
|
+
!isLegacy &&
|
|
4174
|
+
(material.storage.sessionId !== sessionId ||
|
|
4175
|
+
material.storage.resultId !== resultId ||
|
|
4176
|
+
material.storage.handoffId !== material.handoffId ||
|
|
4177
|
+
material.storage.bundleDigest !== material.bundleDigest)
|
|
4178
|
+
) {
|
|
4179
|
+
throw new TypeError("session result collection storage is invalid");
|
|
4180
|
+
}
|
|
4181
|
+
return Object.freeze({ ...material, settlementId });
|
|
4182
|
+
}
|
|
4183
|
+
|
|
4184
|
+
function projectSessionResultCollectionSettlement(
|
|
4185
|
+
sessionId,
|
|
4186
|
+
event,
|
|
4187
|
+
eventCount,
|
|
4188
|
+
) {
|
|
4189
|
+
const legacy =
|
|
4190
|
+
event?.data?.schema ===
|
|
4191
|
+
SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA_V1;
|
|
4192
|
+
const data = exactRecord(
|
|
4193
|
+
event?.data,
|
|
4194
|
+
[
|
|
4195
|
+
"schema",
|
|
4196
|
+
"settlementId",
|
|
4197
|
+
"requestId",
|
|
4198
|
+
"requestDigest",
|
|
4199
|
+
"resultId",
|
|
4200
|
+
"handoffId",
|
|
4201
|
+
"source",
|
|
4202
|
+
"target",
|
|
4203
|
+
"profileDigest",
|
|
4204
|
+
"targetFactsDigest",
|
|
4205
|
+
"collectionAttestationDigest",
|
|
4206
|
+
"bundleDigest",
|
|
4207
|
+
"verificationDigest",
|
|
4208
|
+
"collectionDigest",
|
|
4209
|
+
...(!legacy ? ["storage"] : []),
|
|
4210
|
+
"totalBytes",
|
|
4211
|
+
"applied",
|
|
4212
|
+
],
|
|
4213
|
+
"session result collection settlement",
|
|
4214
|
+
);
|
|
4215
|
+
if (
|
|
4216
|
+
!legacy &&
|
|
4217
|
+
data.schema !== SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA
|
|
4218
|
+
) {
|
|
4219
|
+
throw new TypeError("session result collection settlement schema is invalid");
|
|
4220
|
+
}
|
|
4221
|
+
const normalized = normalizeSessionResultCollectionSettlementData(
|
|
4222
|
+
sessionId,
|
|
4223
|
+
data,
|
|
4224
|
+
);
|
|
4225
|
+
if (
|
|
4226
|
+
normalized.settlementId !== data.settlementId ||
|
|
4227
|
+
normalized.source.headHash !== event?.prevHash ||
|
|
4228
|
+
normalized.source.eventCount !== eventCount - 1
|
|
4229
|
+
) {
|
|
4230
|
+
throw new TypeError("session result collection predecessor is invalid");
|
|
4231
|
+
}
|
|
4232
|
+
return Object.freeze({
|
|
4233
|
+
...normalized,
|
|
4234
|
+
eventHash: event.hash,
|
|
4235
|
+
eventCount,
|
|
4236
|
+
at: new Date(event.timestamp).toISOString(),
|
|
4237
|
+
});
|
|
4238
|
+
}
|
|
4239
|
+
|
|
4240
|
+
function sessionResultCollectionReceipt(sessionId, settlement) {
|
|
4241
|
+
const legacy =
|
|
4242
|
+
settlement.schema ===
|
|
4243
|
+
SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_SCHEMA_V1;
|
|
4244
|
+
const receiptSchema = legacy
|
|
4245
|
+
? SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA_V1
|
|
4246
|
+
: SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_RECEIPT_SCHEMA;
|
|
4247
|
+
const material = {
|
|
4248
|
+
schema: receiptSchema,
|
|
4249
|
+
sessionId,
|
|
4250
|
+
settlementId: settlement.settlementId,
|
|
4251
|
+
requestId: settlement.requestId,
|
|
4252
|
+
requestDigest: settlement.requestDigest,
|
|
4253
|
+
resultId: settlement.resultId,
|
|
4254
|
+
handoffId: settlement.handoffId,
|
|
4255
|
+
sourceHeadHash: settlement.source.headHash,
|
|
4256
|
+
sourceEventCount: settlement.source.eventCount,
|
|
4257
|
+
settlementEventHash: settlement.eventHash,
|
|
4258
|
+
settlementEventCount: settlement.eventCount,
|
|
4259
|
+
targetHeadHash: settlement.target.headHash,
|
|
4260
|
+
targetEventCount: settlement.target.eventCount,
|
|
4261
|
+
bundleDigest: settlement.bundleDigest,
|
|
4262
|
+
verificationDigest: settlement.verificationDigest,
|
|
4263
|
+
collectionDigest: settlement.collectionDigest,
|
|
4264
|
+
...(!legacy ? { storage: settlement.storage } : {}),
|
|
4265
|
+
totalBytes: settlement.totalBytes,
|
|
4266
|
+
applied: false,
|
|
4267
|
+
};
|
|
4268
|
+
return Object.freeze({
|
|
4269
|
+
...material,
|
|
4270
|
+
receiptDigest: sessionLocationDigest(
|
|
4271
|
+
legacy
|
|
4272
|
+
? "chainlesschain.session-execution-location-result-collection-receipt.v1\0"
|
|
4273
|
+
: "chainlesschain.session-execution-location-result-collection-receipt.v2\0",
|
|
4274
|
+
material,
|
|
4275
|
+
),
|
|
4276
|
+
});
|
|
4277
|
+
}
|
|
4278
|
+
|
|
4279
|
+
export function readVerifiedSessionExecutionLocationResultSettlement(
|
|
4280
|
+
sessionId,
|
|
4281
|
+
requestIdInput,
|
|
4282
|
+
options = {},
|
|
4283
|
+
) {
|
|
4284
|
+
const requestId = normalizeSessionResultCollectionRequestId(requestIdInput);
|
|
4285
|
+
const expectedRequestDigest =
|
|
4286
|
+
options.requestDigest == null
|
|
4287
|
+
? null
|
|
4288
|
+
: normalizeSessionLocationDigest(
|
|
4289
|
+
options.requestDigest,
|
|
4290
|
+
"result collection request digest",
|
|
4291
|
+
);
|
|
4292
|
+
return readVerifiedProjection(sessionId, () => {
|
|
4293
|
+
let eventCount = 0;
|
|
4294
|
+
let found = null;
|
|
4295
|
+
return {
|
|
4296
|
+
accept(event) {
|
|
4297
|
+
eventCount += 1;
|
|
4298
|
+
if (event?.type !== SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_EVENT) {
|
|
4299
|
+
return;
|
|
4300
|
+
}
|
|
4301
|
+
const settlement = projectSessionResultCollectionSettlement(
|
|
4302
|
+
sessionId,
|
|
4303
|
+
event,
|
|
4304
|
+
eventCount,
|
|
4305
|
+
);
|
|
4306
|
+
if (settlement.requestId !== requestId) return;
|
|
4307
|
+
if (found !== null) {
|
|
4308
|
+
throw new TypeError("duplicate session result collection request id");
|
|
4309
|
+
}
|
|
4310
|
+
found = settlement;
|
|
4311
|
+
},
|
|
4312
|
+
finish() {
|
|
4313
|
+
if (
|
|
4314
|
+
found !== null &&
|
|
4315
|
+
expectedRequestDigest !== null &&
|
|
4316
|
+
found.requestDigest !== expectedRequestDigest
|
|
4317
|
+
) {
|
|
4318
|
+
throw new Error(
|
|
4319
|
+
"result collection request id is already bound to different inputs",
|
|
4320
|
+
);
|
|
4321
|
+
}
|
|
4322
|
+
return found === null
|
|
4323
|
+
? null
|
|
4324
|
+
: sessionResultCollectionReceipt(sessionId, found);
|
|
4325
|
+
},
|
|
4326
|
+
};
|
|
4327
|
+
});
|
|
4328
|
+
}
|
|
4329
|
+
|
|
4330
|
+
export function settleSessionExecutionLocationResultCollection(
|
|
4331
|
+
sessionId,
|
|
4332
|
+
requestIdInput,
|
|
4333
|
+
collection,
|
|
4334
|
+
storage,
|
|
4335
|
+
) {
|
|
4336
|
+
const data = createSessionResultCollectionSettlementData(
|
|
4337
|
+
sessionId,
|
|
4338
|
+
requestIdInput,
|
|
4339
|
+
collection,
|
|
4340
|
+
storage,
|
|
4341
|
+
);
|
|
4342
|
+
const prior = readVerifiedSessionExecutionLocationResultSettlement(
|
|
4343
|
+
sessionId,
|
|
4344
|
+
data.requestId,
|
|
4345
|
+
{ requestDigest: data.requestDigest },
|
|
4346
|
+
);
|
|
4347
|
+
if (prior !== null) {
|
|
4348
|
+
if (prior.settlementId !== data.settlementId) {
|
|
4349
|
+
throw new Error(
|
|
4350
|
+
"result collection request id is already settled with a different result",
|
|
4351
|
+
);
|
|
4352
|
+
}
|
|
4353
|
+
return Object.freeze({
|
|
4354
|
+
...prior,
|
|
4355
|
+
settlementAppended: false,
|
|
4356
|
+
recovered: true,
|
|
4357
|
+
});
|
|
4358
|
+
}
|
|
4359
|
+
try {
|
|
4360
|
+
appendAuthorityEventIfHead(
|
|
4361
|
+
sessionId,
|
|
4362
|
+
SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_EVENT,
|
|
4363
|
+
data,
|
|
4364
|
+
data.source.headHash,
|
|
4365
|
+
);
|
|
4366
|
+
} catch (error) {
|
|
4367
|
+
const raced = readVerifiedSessionExecutionLocationResultSettlement(
|
|
4368
|
+
sessionId,
|
|
4369
|
+
data.requestId,
|
|
4370
|
+
{ requestDigest: data.requestDigest },
|
|
4371
|
+
);
|
|
4372
|
+
if (raced === null || raced.settlementId !== data.settlementId) {
|
|
4373
|
+
throw error;
|
|
4374
|
+
}
|
|
4375
|
+
return Object.freeze({
|
|
4376
|
+
...raced,
|
|
4377
|
+
settlementAppended: false,
|
|
4378
|
+
recovered: true,
|
|
4379
|
+
});
|
|
4380
|
+
}
|
|
4381
|
+
runSessionScaleFaultHook(
|
|
4382
|
+
"afterResultCollectionSettlementAppend",
|
|
4383
|
+
Object.freeze({
|
|
4384
|
+
sessionId,
|
|
4385
|
+
requestId: data.requestId,
|
|
4386
|
+
requestDigest: data.requestDigest,
|
|
4387
|
+
settlementId: data.settlementId,
|
|
4388
|
+
}),
|
|
4389
|
+
);
|
|
4390
|
+
const receipt = readVerifiedSessionExecutionLocationResultSettlement(
|
|
4391
|
+
sessionId,
|
|
4392
|
+
data.requestId,
|
|
4393
|
+
{ requestDigest: data.requestDigest },
|
|
4394
|
+
);
|
|
4395
|
+
if (receipt === null || receipt.settlementId !== data.settlementId) {
|
|
4396
|
+
throw new Error("result collection settlement is not canonical");
|
|
4397
|
+
}
|
|
4398
|
+
return Object.freeze({
|
|
4399
|
+
...receipt,
|
|
4400
|
+
settlementAppended: true,
|
|
4401
|
+
recovered: false,
|
|
4402
|
+
});
|
|
4403
|
+
}
|
|
4404
|
+
|
|
4405
|
+
function normalizeSessionResultApplyId(value) {
|
|
4406
|
+
const applyId = boundedAuthorityString(
|
|
4407
|
+
value,
|
|
4408
|
+
"result apply id",
|
|
4409
|
+
128,
|
|
4410
|
+
);
|
|
4411
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:@-]{0,127}$/u.test(applyId)) {
|
|
4412
|
+
throw new TypeError("result apply id is invalid");
|
|
4413
|
+
}
|
|
4414
|
+
return applyId;
|
|
4415
|
+
}
|
|
4416
|
+
|
|
4417
|
+
function normalizeSessionResultApplyGit(input) {
|
|
4418
|
+
const value = exactRecord(
|
|
4419
|
+
input,
|
|
4420
|
+
["rootDigest", "commit"],
|
|
4421
|
+
"result apply source git",
|
|
4422
|
+
);
|
|
4423
|
+
const commit = String(value.commit || "").toLowerCase();
|
|
4424
|
+
if (!/^[a-f0-9]{40,64}$/u.test(commit)) {
|
|
4425
|
+
throw new TypeError("result apply source git commit is invalid");
|
|
4426
|
+
}
|
|
4427
|
+
return Object.freeze({
|
|
4428
|
+
rootDigest: normalizeSessionLocationDigest(
|
|
4429
|
+
value.rootDigest,
|
|
4430
|
+
"result apply source git root digest",
|
|
4431
|
+
),
|
|
4432
|
+
commit,
|
|
4433
|
+
});
|
|
4434
|
+
}
|
|
4435
|
+
|
|
4436
|
+
function normalizeSessionResultApplyPreparedTransaction(input) {
|
|
4437
|
+
const value = exactRecord(
|
|
4438
|
+
input,
|
|
4439
|
+
[
|
|
4440
|
+
"id",
|
|
4441
|
+
"checkpointId",
|
|
4442
|
+
"checkpointDigest",
|
|
4443
|
+
"coverage",
|
|
4444
|
+
"externalSideEffects",
|
|
4445
|
+
],
|
|
4446
|
+
"result apply prepared transaction",
|
|
4447
|
+
);
|
|
4448
|
+
const id = boundedAuthorityString(value.id, "result apply transaction id", 192);
|
|
4449
|
+
const checkpointId = boundedAuthorityString(
|
|
4450
|
+
value.checkpointId,
|
|
4451
|
+
"result apply checkpoint id",
|
|
4452
|
+
192,
|
|
4453
|
+
);
|
|
4454
|
+
if (
|
|
4455
|
+
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,191}$/u.test(id) ||
|
|
4456
|
+
!/^[A-Za-z0-9][A-Za-z0-9._-]{0,191}$/u.test(checkpointId) ||
|
|
4457
|
+
!["full", "partial"].includes(value.coverage) ||
|
|
4458
|
+
value.externalSideEffects !== false
|
|
4459
|
+
) {
|
|
4460
|
+
throw new TypeError("result apply prepared transaction is invalid");
|
|
4461
|
+
}
|
|
4462
|
+
return Object.freeze({
|
|
4463
|
+
id,
|
|
4464
|
+
checkpointId,
|
|
4465
|
+
checkpointDigest: normalizeSessionLocationDigest(
|
|
4466
|
+
value.checkpointDigest,
|
|
4467
|
+
"result apply checkpoint digest",
|
|
4468
|
+
),
|
|
4469
|
+
coverage: value.coverage,
|
|
4470
|
+
externalSideEffects: false,
|
|
4471
|
+
});
|
|
4472
|
+
}
|
|
4473
|
+
|
|
4474
|
+
function normalizeSessionResultApplyTerminalTransaction(input) {
|
|
4475
|
+
const value = exactRecord(
|
|
4476
|
+
input,
|
|
4477
|
+
[
|
|
4478
|
+
"id",
|
|
4479
|
+
"checkpointId",
|
|
4480
|
+
"checkpointDigest",
|
|
4481
|
+
"evidenceDigest",
|
|
4482
|
+
"writeManifestDigest",
|
|
4483
|
+
"coverage",
|
|
4484
|
+
"fileCoverage",
|
|
4485
|
+
"externalSideEffects",
|
|
4486
|
+
"uncoveredPaths",
|
|
4487
|
+
],
|
|
4488
|
+
"result apply terminal transaction",
|
|
4489
|
+
);
|
|
4490
|
+
const prepared = normalizeSessionResultApplyPreparedTransaction({
|
|
4491
|
+
id: value.id,
|
|
4492
|
+
checkpointId: value.checkpointId,
|
|
4493
|
+
checkpointDigest: value.checkpointDigest,
|
|
4494
|
+
coverage: value.coverage,
|
|
4495
|
+
externalSideEffects: value.externalSideEffects,
|
|
4496
|
+
});
|
|
4497
|
+
if (
|
|
4498
|
+
!["full", "partial", "none"].includes(value.fileCoverage) ||
|
|
4499
|
+
!Array.isArray(value.uncoveredPaths) ||
|
|
4500
|
+
value.uncoveredPaths.length > 128
|
|
4501
|
+
) {
|
|
4502
|
+
throw new TypeError("result apply terminal transaction is invalid");
|
|
4503
|
+
}
|
|
4504
|
+
const uncoveredPaths = value.uncoveredPaths.map((entry) =>
|
|
4505
|
+
boundedAuthorityString(entry, "result apply uncovered path", 512),
|
|
4506
|
+
);
|
|
4507
|
+
if (
|
|
4508
|
+
new Set(uncoveredPaths).size !== uncoveredPaths.length ||
|
|
4509
|
+
uncoveredPaths.some((entry, index) =>
|
|
4510
|
+
index > 0 ? entry.localeCompare(uncoveredPaths[index - 1]) < 0 : false,
|
|
4511
|
+
)
|
|
4512
|
+
) {
|
|
4513
|
+
throw new TypeError("result apply uncovered paths are invalid");
|
|
4514
|
+
}
|
|
4515
|
+
return Object.freeze({
|
|
4516
|
+
...prepared,
|
|
4517
|
+
evidenceDigest: normalizeSessionLocationDigest(
|
|
4518
|
+
value.evidenceDigest,
|
|
4519
|
+
"result apply evidence digest",
|
|
4520
|
+
),
|
|
4521
|
+
writeManifestDigest: normalizeSessionLocationDigest(
|
|
4522
|
+
value.writeManifestDigest,
|
|
4523
|
+
"result apply write manifest digest",
|
|
4524
|
+
),
|
|
4525
|
+
fileCoverage: value.fileCoverage,
|
|
4526
|
+
uncoveredPaths: Object.freeze(uncoveredPaths),
|
|
4527
|
+
});
|
|
4528
|
+
}
|
|
4529
|
+
|
|
4530
|
+
function normalizeSessionResultApplyReview(review, settlement) {
|
|
4531
|
+
if (
|
|
4532
|
+
review?.schema !== "cc-execution-location-result-review/v1" ||
|
|
4533
|
+
review.sessionId !== settlement.sessionId ||
|
|
4534
|
+
review.requestId !== settlement.requestId ||
|
|
4535
|
+
review.resultId !== settlement.resultId ||
|
|
4536
|
+
review.handoffId !== settlement.handoffId ||
|
|
4537
|
+
review.settlement?.settlementId !== settlement.settlementId ||
|
|
4538
|
+
review.settlement?.eventHash !== settlement.settlementEventHash ||
|
|
4539
|
+
review.settlement?.eventCount !== settlement.settlementEventCount ||
|
|
4540
|
+
review.settlement?.receiptDigest !== settlement.receiptDigest ||
|
|
4541
|
+
review.bundleDigest !== settlement.bundleDigest ||
|
|
4542
|
+
review.verificationDigest !== settlement.verificationDigest ||
|
|
4543
|
+
review.collectionDigest !== settlement.collectionDigest ||
|
|
4544
|
+
review.diff?.digest == null ||
|
|
4545
|
+
review.applied !== false ||
|
|
4546
|
+
review.applyPolicy?.automaticApply !== false
|
|
4547
|
+
) {
|
|
4548
|
+
throw new TypeError("result apply review authority is invalid");
|
|
4549
|
+
}
|
|
4550
|
+
return Object.freeze({
|
|
4551
|
+
reviewDigest: normalizeSessionLocationDigest(
|
|
4552
|
+
review.reviewDigest,
|
|
4553
|
+
"result apply review digest",
|
|
4554
|
+
),
|
|
4555
|
+
diffDigest: normalizeSessionLocationDigest(
|
|
4556
|
+
review.diff.digest,
|
|
4557
|
+
"result apply diff digest",
|
|
4558
|
+
),
|
|
4559
|
+
});
|
|
4560
|
+
}
|
|
4561
|
+
|
|
4562
|
+
function createSessionResultApplyReservationData(
|
|
4563
|
+
sessionId,
|
|
4564
|
+
applyIdInput,
|
|
4565
|
+
review,
|
|
4566
|
+
settlement,
|
|
4567
|
+
sourceGit,
|
|
4568
|
+
transaction,
|
|
4569
|
+
) {
|
|
4570
|
+
const applyId = normalizeSessionResultApplyId(applyIdInput);
|
|
4571
|
+
const reviewed = normalizeSessionResultApplyReview(review, settlement);
|
|
4572
|
+
const material = {
|
|
4573
|
+
schema: SESSION_EXECUTION_LOCATION_RESULT_APPLY_RESERVATION_SCHEMA,
|
|
4574
|
+
applyId,
|
|
4575
|
+
requestId: settlement.requestId,
|
|
4576
|
+
reviewDigest: reviewed.reviewDigest,
|
|
4577
|
+
settlementId: settlement.settlementId,
|
|
4578
|
+
settlementEventHash: settlement.settlementEventHash,
|
|
4579
|
+
settlementEventCount: settlement.settlementEventCount,
|
|
4580
|
+
bundleDigest: settlement.bundleDigest,
|
|
4581
|
+
diffDigest: reviewed.diffDigest,
|
|
4582
|
+
sourceGit: normalizeSessionResultApplyGit(sourceGit),
|
|
4583
|
+
transaction: normalizeSessionResultApplyPreparedTransaction(transaction),
|
|
4584
|
+
applied: false,
|
|
4585
|
+
};
|
|
4586
|
+
return Object.freeze({
|
|
4587
|
+
...material,
|
|
4588
|
+
reservationId: sessionLocationDigest(
|
|
4589
|
+
"chainlesschain.session-execution-location-result-apply-reservation-id.v1\0",
|
|
4590
|
+
{ sessionId, ...material },
|
|
4591
|
+
),
|
|
4592
|
+
});
|
|
4593
|
+
}
|
|
4594
|
+
|
|
4595
|
+
function projectSessionResultApplyReservation(
|
|
4596
|
+
sessionId,
|
|
4597
|
+
event,
|
|
4598
|
+
eventCount,
|
|
4599
|
+
settlement,
|
|
4600
|
+
) {
|
|
4601
|
+
const data = exactRecord(
|
|
4602
|
+
event?.data,
|
|
4603
|
+
[
|
|
4604
|
+
"schema",
|
|
4605
|
+
"reservationId",
|
|
4606
|
+
"applyId",
|
|
4607
|
+
"requestId",
|
|
4608
|
+
"reviewDigest",
|
|
4609
|
+
"settlementId",
|
|
4610
|
+
"settlementEventHash",
|
|
4611
|
+
"settlementEventCount",
|
|
4612
|
+
"bundleDigest",
|
|
4613
|
+
"diffDigest",
|
|
4614
|
+
"sourceGit",
|
|
4615
|
+
"transaction",
|
|
4616
|
+
"applied",
|
|
4617
|
+
],
|
|
4618
|
+
"session result apply reservation",
|
|
4619
|
+
);
|
|
4620
|
+
if (
|
|
4621
|
+
!settlement ||
|
|
4622
|
+
settlement.settlementId !== data.settlementId ||
|
|
4623
|
+
settlement.requestId !== data.requestId ||
|
|
4624
|
+
settlement.bundleDigest !== data.bundleDigest ||
|
|
4625
|
+
settlement.eventHash !== data.settlementEventHash ||
|
|
4626
|
+
settlement.eventCount !== data.settlementEventCount ||
|
|
4627
|
+
event?.prevHash !== settlement.eventHash ||
|
|
4628
|
+
eventCount !== settlement.eventCount + 1 ||
|
|
4629
|
+
data.applied !== false
|
|
4630
|
+
) {
|
|
4631
|
+
throw new TypeError("session result apply reservation predecessor is invalid");
|
|
4632
|
+
}
|
|
4633
|
+
const material = {
|
|
4634
|
+
schema: SESSION_EXECUTION_LOCATION_RESULT_APPLY_RESERVATION_SCHEMA,
|
|
4635
|
+
applyId: normalizeSessionResultApplyId(data.applyId),
|
|
4636
|
+
requestId: normalizeSessionResultCollectionRequestId(data.requestId),
|
|
4637
|
+
reviewDigest: normalizeSessionLocationDigest(
|
|
4638
|
+
data.reviewDigest,
|
|
4639
|
+
"result apply review digest",
|
|
4640
|
+
),
|
|
4641
|
+
settlementId: normalizeSessionLocationDigest(
|
|
4642
|
+
data.settlementId,
|
|
4643
|
+
"result apply settlement id",
|
|
4644
|
+
),
|
|
4645
|
+
settlementEventHash: normalizeSessionLocationHead(
|
|
4646
|
+
data.settlementEventHash,
|
|
4647
|
+
"result apply settlement event hash",
|
|
4648
|
+
),
|
|
4649
|
+
settlementEventCount: normalizeSessionLocationEventCount(
|
|
4650
|
+
data.settlementEventCount,
|
|
4651
|
+
"result apply settlement event count",
|
|
4652
|
+
),
|
|
4653
|
+
bundleDigest: normalizeSessionLocationDigest(
|
|
4654
|
+
data.bundleDigest,
|
|
4655
|
+
"result apply bundle digest",
|
|
4656
|
+
),
|
|
4657
|
+
diffDigest: normalizeSessionLocationDigest(
|
|
4658
|
+
data.diffDigest,
|
|
4659
|
+
"result apply diff digest",
|
|
4660
|
+
),
|
|
4661
|
+
sourceGit: normalizeSessionResultApplyGit(data.sourceGit),
|
|
4662
|
+
transaction: normalizeSessionResultApplyPreparedTransaction(
|
|
4663
|
+
data.transaction,
|
|
4664
|
+
),
|
|
4665
|
+
applied: false,
|
|
4666
|
+
};
|
|
4667
|
+
const reservationId = sessionLocationDigest(
|
|
4668
|
+
"chainlesschain.session-execution-location-result-apply-reservation-id.v1\0",
|
|
4669
|
+
{ sessionId, ...material },
|
|
4670
|
+
);
|
|
4671
|
+
if (data.reservationId !== reservationId) {
|
|
4672
|
+
throw new TypeError("session result apply reservation id is invalid");
|
|
4673
|
+
}
|
|
4674
|
+
return Object.freeze({
|
|
4675
|
+
...material,
|
|
4676
|
+
reservationId,
|
|
4677
|
+
eventHash: event.hash,
|
|
4678
|
+
eventCount,
|
|
4679
|
+
at: new Date(event.timestamp).toISOString(),
|
|
4680
|
+
});
|
|
4681
|
+
}
|
|
4682
|
+
|
|
4683
|
+
function createSessionResultApplyTerminalData(
|
|
4684
|
+
sessionId,
|
|
4685
|
+
reservation,
|
|
4686
|
+
source,
|
|
4687
|
+
outcome,
|
|
4688
|
+
transaction,
|
|
4689
|
+
) {
|
|
4690
|
+
if (!["applied", "rolled_back"].includes(outcome)) {
|
|
4691
|
+
throw new TypeError("result apply terminal outcome is invalid");
|
|
4692
|
+
}
|
|
4693
|
+
const material = {
|
|
4694
|
+
schema: SESSION_EXECUTION_LOCATION_RESULT_APPLY_TERMINAL_SCHEMA,
|
|
4695
|
+
applyId: reservation.applyId,
|
|
4696
|
+
reservationId: reservation.reservationId,
|
|
4697
|
+
reviewDigest: reservation.reviewDigest,
|
|
4698
|
+
settlementId: reservation.settlementId,
|
|
4699
|
+
bundleDigest: reservation.bundleDigest,
|
|
4700
|
+
diffDigest: reservation.diffDigest,
|
|
4701
|
+
source: Object.freeze({
|
|
4702
|
+
headHash: normalizeSessionLocationHead(
|
|
4703
|
+
source.headHash,
|
|
4704
|
+
"result apply terminal source head",
|
|
4705
|
+
),
|
|
4706
|
+
eventCount: normalizeSessionLocationEventCount(
|
|
4707
|
+
source.eventCount,
|
|
4708
|
+
"result apply terminal source event count",
|
|
4709
|
+
),
|
|
4710
|
+
}),
|
|
4711
|
+
sourceGit: reservation.sourceGit,
|
|
4712
|
+
transaction: normalizeSessionResultApplyTerminalTransaction(transaction),
|
|
4713
|
+
outcome,
|
|
4714
|
+
applied: outcome === "applied",
|
|
4715
|
+
};
|
|
4716
|
+
return Object.freeze({
|
|
4717
|
+
...material,
|
|
4718
|
+
terminalId: sessionLocationDigest(
|
|
4719
|
+
"chainlesschain.session-execution-location-result-apply-terminal-id.v1\0",
|
|
4720
|
+
{ sessionId, ...material },
|
|
4721
|
+
),
|
|
4722
|
+
});
|
|
4723
|
+
}
|
|
4724
|
+
|
|
4725
|
+
function projectSessionResultApplyTerminal(
|
|
4726
|
+
sessionId,
|
|
4727
|
+
event,
|
|
4728
|
+
eventCount,
|
|
4729
|
+
reservation,
|
|
4730
|
+
) {
|
|
4731
|
+
const data = exactRecord(
|
|
4732
|
+
event?.data,
|
|
4733
|
+
[
|
|
4734
|
+
"schema",
|
|
4735
|
+
"terminalId",
|
|
4736
|
+
"applyId",
|
|
4737
|
+
"reservationId",
|
|
4738
|
+
"reviewDigest",
|
|
4739
|
+
"settlementId",
|
|
4740
|
+
"bundleDigest",
|
|
4741
|
+
"diffDigest",
|
|
4742
|
+
"source",
|
|
4743
|
+
"sourceGit",
|
|
4744
|
+
"transaction",
|
|
4745
|
+
"outcome",
|
|
4746
|
+
"applied",
|
|
4747
|
+
],
|
|
4748
|
+
"session result apply terminal",
|
|
4749
|
+
);
|
|
4750
|
+
const source = exactRecord(
|
|
4751
|
+
data.source,
|
|
4752
|
+
["headHash", "eventCount"],
|
|
4753
|
+
"session result apply terminal source",
|
|
4754
|
+
);
|
|
4755
|
+
if (
|
|
4756
|
+
!reservation ||
|
|
4757
|
+
data.applyId !== reservation.applyId ||
|
|
4758
|
+
data.reservationId !== reservation.reservationId ||
|
|
4759
|
+
data.reviewDigest !== reservation.reviewDigest ||
|
|
4760
|
+
data.settlementId !== reservation.settlementId ||
|
|
4761
|
+
data.bundleDigest !== reservation.bundleDigest ||
|
|
4762
|
+
data.diffDigest !== reservation.diffDigest ||
|
|
4763
|
+
event?.prevHash !== source.headHash ||
|
|
4764
|
+
eventCount !== Number(source.eventCount) + 1 ||
|
|
4765
|
+
data.applied !== (data.outcome === "applied")
|
|
4766
|
+
) {
|
|
4767
|
+
throw new TypeError("session result apply terminal authority is invalid");
|
|
4768
|
+
}
|
|
4769
|
+
const normalized = createSessionResultApplyTerminalData(
|
|
4770
|
+
sessionId,
|
|
4771
|
+
reservation,
|
|
4772
|
+
source,
|
|
4773
|
+
data.outcome,
|
|
4774
|
+
data.transaction,
|
|
4775
|
+
);
|
|
4776
|
+
if (
|
|
4777
|
+
data.terminalId !== normalized.terminalId ||
|
|
4778
|
+
canonicalJson(data.sourceGit, "resultApplySourceGit") !==
|
|
4779
|
+
canonicalJson(reservation.sourceGit, "resultApplySourceGit")
|
|
4780
|
+
) {
|
|
4781
|
+
throw new TypeError("session result apply terminal id is invalid");
|
|
4782
|
+
}
|
|
4783
|
+
return Object.freeze({
|
|
4784
|
+
...normalized,
|
|
4785
|
+
eventHash: event.hash,
|
|
4786
|
+
eventCount,
|
|
4787
|
+
at: new Date(event.timestamp).toISOString(),
|
|
4788
|
+
});
|
|
4789
|
+
}
|
|
4790
|
+
|
|
4791
|
+
function sessionResultApplyReceipt(sessionId, reservation, terminal) {
|
|
4792
|
+
const material = {
|
|
4793
|
+
schema: SESSION_EXECUTION_LOCATION_RESULT_APPLY_RECEIPT_SCHEMA,
|
|
4794
|
+
sessionId,
|
|
4795
|
+
applyId: reservation.applyId,
|
|
4796
|
+
requestId: reservation.requestId,
|
|
4797
|
+
status: terminal?.outcome || "reserved",
|
|
4798
|
+
reviewDigest: reservation.reviewDigest,
|
|
4799
|
+
settlementId: reservation.settlementId,
|
|
4800
|
+
bundleDigest: reservation.bundleDigest,
|
|
4801
|
+
diffDigest: reservation.diffDigest,
|
|
4802
|
+
sourceGit: reservation.sourceGit,
|
|
4803
|
+
transaction: terminal?.transaction || reservation.transaction,
|
|
4804
|
+
reservation: Object.freeze({
|
|
4805
|
+
reservationId: reservation.reservationId,
|
|
4806
|
+
eventHash: reservation.eventHash,
|
|
4807
|
+
eventCount: reservation.eventCount,
|
|
4808
|
+
}),
|
|
4809
|
+
terminal: terminal
|
|
4810
|
+
? Object.freeze({
|
|
4811
|
+
terminalId: terminal.terminalId,
|
|
4812
|
+
eventHash: terminal.eventHash,
|
|
4813
|
+
eventCount: terminal.eventCount,
|
|
4814
|
+
outcome: terminal.outcome,
|
|
4815
|
+
})
|
|
4816
|
+
: null,
|
|
4817
|
+
applied: terminal?.outcome === "applied",
|
|
4818
|
+
};
|
|
4819
|
+
return Object.freeze({
|
|
4820
|
+
...material,
|
|
4821
|
+
receiptDigest: sessionLocationDigest(
|
|
4822
|
+
"chainlesschain.session-execution-location-result-apply-receipt.v1\0",
|
|
4823
|
+
material,
|
|
4824
|
+
),
|
|
4825
|
+
});
|
|
4826
|
+
}
|
|
4827
|
+
|
|
4828
|
+
export function readVerifiedSessionExecutionLocationResultApply(
|
|
4829
|
+
sessionId,
|
|
4830
|
+
applyIdInput,
|
|
4831
|
+
) {
|
|
4832
|
+
const applyId = normalizeSessionResultApplyId(applyIdInput);
|
|
4833
|
+
return readVerifiedProjection(sessionId, () => {
|
|
4834
|
+
let eventCount = 0;
|
|
4835
|
+
const settlements = new Map();
|
|
4836
|
+
const reservations = new Map();
|
|
4837
|
+
const terminals = new Map();
|
|
4838
|
+
return {
|
|
4839
|
+
accept(event) {
|
|
4840
|
+
eventCount += 1;
|
|
4841
|
+
if (event?.type === SESSION_EXECUTION_LOCATION_RESULT_COLLECTION_EVENT) {
|
|
4842
|
+
const settlement = projectSessionResultCollectionSettlement(
|
|
4843
|
+
sessionId,
|
|
4844
|
+
event,
|
|
4845
|
+
eventCount,
|
|
4846
|
+
);
|
|
4847
|
+
settlements.set(settlement.settlementId, settlement);
|
|
4848
|
+
return;
|
|
4849
|
+
}
|
|
4850
|
+
if (event?.type === SESSION_EXECUTION_LOCATION_RESULT_APPLY_RESERVATION_EVENT) {
|
|
4851
|
+
const settlement = settlements.get(event?.data?.settlementId) || null;
|
|
4852
|
+
const reservation = projectSessionResultApplyReservation(
|
|
4853
|
+
sessionId,
|
|
4854
|
+
event,
|
|
4855
|
+
eventCount,
|
|
4856
|
+
settlement,
|
|
4857
|
+
);
|
|
4858
|
+
if (
|
|
4859
|
+
reservations.has(reservation.applyId) ||
|
|
4860
|
+
[...reservations.values()].some(
|
|
4861
|
+
(entry) => entry.reservationId === reservation.reservationId,
|
|
4862
|
+
)
|
|
4863
|
+
) {
|
|
4864
|
+
throw new TypeError("duplicate session result apply reservation");
|
|
4865
|
+
}
|
|
4866
|
+
reservations.set(reservation.applyId, reservation);
|
|
4867
|
+
return;
|
|
4868
|
+
}
|
|
4869
|
+
if (event?.type === SESSION_EXECUTION_LOCATION_RESULT_APPLY_TERMINAL_EVENT) {
|
|
4870
|
+
const reservation = reservations.get(event?.data?.applyId) || null;
|
|
4871
|
+
const terminal = projectSessionResultApplyTerminal(
|
|
4872
|
+
sessionId,
|
|
4873
|
+
event,
|
|
4874
|
+
eventCount,
|
|
4875
|
+
reservation,
|
|
4876
|
+
);
|
|
4877
|
+
if (terminals.has(terminal.applyId)) {
|
|
4878
|
+
throw new TypeError("duplicate session result apply terminal");
|
|
4879
|
+
}
|
|
4880
|
+
terminals.set(terminal.applyId, terminal);
|
|
4881
|
+
}
|
|
4882
|
+
},
|
|
4883
|
+
finish() {
|
|
4884
|
+
const reservation = reservations.get(applyId) || null;
|
|
4885
|
+
return reservation === null
|
|
4886
|
+
? null
|
|
4887
|
+
: sessionResultApplyReceipt(
|
|
4888
|
+
sessionId,
|
|
4889
|
+
reservation,
|
|
4890
|
+
terminals.get(applyId) || null,
|
|
4891
|
+
);
|
|
4892
|
+
},
|
|
4893
|
+
};
|
|
4894
|
+
});
|
|
4895
|
+
}
|
|
4896
|
+
|
|
4897
|
+
export function reserveSessionExecutionLocationResultApply(
|
|
4898
|
+
sessionId,
|
|
4899
|
+
applyId,
|
|
4900
|
+
review,
|
|
4901
|
+
sourceGit,
|
|
4902
|
+
transaction,
|
|
4903
|
+
) {
|
|
4904
|
+
const settlement = readVerifiedSessionExecutionLocationResultSettlement(
|
|
4905
|
+
sessionId,
|
|
4906
|
+
review?.requestId,
|
|
4907
|
+
);
|
|
4908
|
+
if (settlement === null) {
|
|
4909
|
+
throw new Error("result apply settlement was not found");
|
|
4910
|
+
}
|
|
4911
|
+
const data = createSessionResultApplyReservationData(
|
|
4912
|
+
sessionId,
|
|
4913
|
+
applyId,
|
|
4914
|
+
review,
|
|
4915
|
+
settlement,
|
|
4916
|
+
sourceGit,
|
|
4917
|
+
transaction,
|
|
4918
|
+
);
|
|
4919
|
+
const prior = readVerifiedSessionExecutionLocationResultApply(
|
|
4920
|
+
sessionId,
|
|
4921
|
+
data.applyId,
|
|
4922
|
+
);
|
|
4923
|
+
if (prior !== null) {
|
|
4924
|
+
if (prior.reservation.reservationId !== data.reservationId) {
|
|
4925
|
+
throw new Error("result apply id is already bound to different inputs");
|
|
4926
|
+
}
|
|
4927
|
+
return Object.freeze({ ...prior, reservationAppended: false, recovered: true });
|
|
4928
|
+
}
|
|
4929
|
+
appendAuthorityEventIfHead(
|
|
4930
|
+
sessionId,
|
|
4931
|
+
SESSION_EXECUTION_LOCATION_RESULT_APPLY_RESERVATION_EVENT,
|
|
4932
|
+
data,
|
|
4933
|
+
settlement.settlementEventHash,
|
|
4934
|
+
);
|
|
4935
|
+
runSessionScaleFaultHook(
|
|
4936
|
+
"afterResultApplyReservationAppend",
|
|
4937
|
+
Object.freeze({ sessionId, applyId: data.applyId, reservationId: data.reservationId }),
|
|
4938
|
+
);
|
|
4939
|
+
const receipt = readVerifiedSessionExecutionLocationResultApply(
|
|
4940
|
+
sessionId,
|
|
4941
|
+
data.applyId,
|
|
4942
|
+
);
|
|
4943
|
+
if (
|
|
4944
|
+
receipt === null ||
|
|
4945
|
+
receipt.reservation.reservationId !== data.reservationId
|
|
4946
|
+
) {
|
|
4947
|
+
throw new Error("result apply reservation is not canonical");
|
|
4948
|
+
}
|
|
4949
|
+
return Object.freeze({ ...receipt, reservationAppended: true, recovered: false });
|
|
4950
|
+
}
|
|
4951
|
+
|
|
4952
|
+
export function settleSessionExecutionLocationResultApply(
|
|
4953
|
+
sessionId,
|
|
4954
|
+
applyIdInput,
|
|
4955
|
+
outcome,
|
|
4956
|
+
transaction,
|
|
4957
|
+
) {
|
|
4958
|
+
const applyId = normalizeSessionResultApplyId(applyIdInput);
|
|
4959
|
+
const prior = readVerifiedSessionExecutionLocationResultApply(sessionId, applyId);
|
|
4960
|
+
if (prior === null) {
|
|
4961
|
+
throw new Error("result apply reservation was not found");
|
|
4962
|
+
}
|
|
4963
|
+
const normalizedTransaction = normalizeSessionResultApplyTerminalTransaction(
|
|
4964
|
+
transaction,
|
|
4965
|
+
);
|
|
4966
|
+
if (prior.terminal !== null) {
|
|
4967
|
+
if (
|
|
4968
|
+
prior.status !== outcome ||
|
|
4969
|
+
canonicalJson(prior.transaction, "resultApplyTransaction") !==
|
|
4970
|
+
canonicalJson(normalizedTransaction, "resultApplyTransaction")
|
|
4971
|
+
) {
|
|
4972
|
+
throw new Error("result apply is already settled differently");
|
|
4973
|
+
}
|
|
4974
|
+
return Object.freeze({ ...prior, terminalAppended: false, recovered: true });
|
|
4975
|
+
}
|
|
4976
|
+
const current = getVerifiedSessionExecutionLocationAuthority(sessionId);
|
|
4977
|
+
const reservation = Object.freeze({
|
|
4978
|
+
applyId: prior.applyId,
|
|
4979
|
+
requestId: prior.requestId,
|
|
4980
|
+
reservationId: prior.reservation.reservationId,
|
|
4981
|
+
reviewDigest: prior.reviewDigest,
|
|
4982
|
+
settlementId: prior.settlementId,
|
|
4983
|
+
bundleDigest: prior.bundleDigest,
|
|
4984
|
+
diffDigest: prior.diffDigest,
|
|
4985
|
+
sourceGit: prior.sourceGit,
|
|
4986
|
+
});
|
|
4987
|
+
const data = createSessionResultApplyTerminalData(
|
|
4988
|
+
sessionId,
|
|
4989
|
+
reservation,
|
|
4990
|
+
{ headHash: current.headHash, eventCount: current.eventCount },
|
|
4991
|
+
outcome,
|
|
4992
|
+
normalizedTransaction,
|
|
4993
|
+
);
|
|
4994
|
+
try {
|
|
4995
|
+
appendAuthorityEventIfHead(
|
|
4996
|
+
sessionId,
|
|
4997
|
+
SESSION_EXECUTION_LOCATION_RESULT_APPLY_TERMINAL_EVENT,
|
|
4998
|
+
data,
|
|
4999
|
+
current.headHash,
|
|
5000
|
+
);
|
|
5001
|
+
} catch (error) {
|
|
5002
|
+
const raced = readVerifiedSessionExecutionLocationResultApply(
|
|
5003
|
+
sessionId,
|
|
5004
|
+
applyId,
|
|
5005
|
+
);
|
|
5006
|
+
if (
|
|
5007
|
+
raced?.status !== outcome ||
|
|
5008
|
+
canonicalJson(raced.transaction, "resultApplyTransaction") !==
|
|
5009
|
+
canonicalJson(normalizedTransaction, "resultApplyTransaction")
|
|
5010
|
+
) {
|
|
5011
|
+
throw error;
|
|
5012
|
+
}
|
|
5013
|
+
return Object.freeze({ ...raced, terminalAppended: false, recovered: true });
|
|
5014
|
+
}
|
|
5015
|
+
runSessionScaleFaultHook(
|
|
5016
|
+
"afterResultApplyTerminalAppend",
|
|
5017
|
+
Object.freeze({ sessionId, applyId, terminalId: data.terminalId }),
|
|
5018
|
+
);
|
|
5019
|
+
const receipt = readVerifiedSessionExecutionLocationResultApply(sessionId, applyId);
|
|
5020
|
+
if (receipt?.terminal?.terminalId !== data.terminalId) {
|
|
5021
|
+
throw new Error("result apply terminal is not canonical");
|
|
5022
|
+
}
|
|
5023
|
+
return Object.freeze({ ...receipt, terminalAppended: true, recovered: false });
|
|
5024
|
+
}
|
|
5025
|
+
|
|
3816
5026
|
/**
|
|
3817
5027
|
* Install one exact, source-verified transcript revision into an empty target
|
|
3818
5028
|
* session store. The target validates hash chain, transcript structure, exact
|