chainlesschain 0.166.6 → 0.166.9
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 +21 -0
- package/package.json +5 -1
- package/src/assets/web-panel/.build-hash +1 -1
- package/src/assets/web-panel/assets/{AIOps-CVnFjTfG.js → AIOps-DJvpifGx.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-BxkwuuQC.js → ActionButton-D2UhuF_A.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-C2670q6z.js → Analytics-C9ho9obu.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CU_rylW6.js → AppLayout-BvRCpFK3.js} +3 -3
- package/src/assets/web-panel/assets/{Artifacts-DGJmYqnj.js → Artifacts-jxrySvpk.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BZOQbINJ.js → Audit-ovEw0ZYl.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-DghB4QwF.js → BackgroundAgents-D7H5z6zS.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-l0mwPbta.js → Backup-BuXob8za.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-Bv3WSZOh.js → BaseInput-CtnszuQ2.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-s88nBdvt.js → Chat-B_mYE8fJ.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-Z8CBuB1a.js → ChatBubbleRenderer-DaiA6CsX.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-B5icasEs.js → Checkbox-ierdtcJD.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CsUFqNud.js → Codegen-3VKPJD_B.js} +1 -1
- package/src/assets/web-panel/assets/{Col-DlBtClaW.js → Col-1EdMyf5P.js} +1 -1
- package/src/assets/web-panel/assets/{Community-xRn1IdLB.js → Community-D6H7UA8K.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-naIr8a_o.js → Compact-BBAZvYIm.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-Dp9esfFE.js → Compliance-CgsTrAoj.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-DQlMYJB-.js → Cowork-tnZgLoTE.js} +4 -4
- package/src/assets/web-panel/assets/{Cron-Cd0oNLzJ.js → Cron-CPpZw2Nh.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BtDIx3XX.js → Crosschain-BymBcp5z.js} +1 -1
- package/src/assets/web-panel/assets/{DID-BOlpzEwg.js → DID-DKPxS_K1.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-DV15Axk1.js → Dashboard-DvJhEmH9.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-COXrewN1.js → Dropdown-b8iQyQIZ.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-EjIt0Cm7.js → EmailListRenderer--0-A-zKb.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-DJlhwb-R.js → FamilyGuardDashboard-C12iDN06.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-BMiFl82k.js → Federation-BRhaE2Z8.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-BUcDQyxn.js → FormItemContext-C4dnq7yf.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-C25uFxvK.js → GenericCardRenderer-CGAdbR5n.js} +1 -1
- package/src/assets/web-panel/assets/{Git-D20uaEUU.js → Git-4eA2fYzL.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CQxYJjCX.js → Governance-BJuY9Y-9.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-m-sczpS5.js → Inference-DZ5Dy4up.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CBsIlU0S.js → KnowledgeGraph-BMTjRs4A.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-D0-5bqeu.js → Logs-BKEeQEfJ.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-B05DgASC.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-CwDGFu2Q.js → Marketplace-Dhho4fEg.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-7FxJ3omT.js → McpTools-BW6xxSlU.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-DOVyb59U.js → Memory-mPqlpSkq.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-DZXl-Hje.js → MobileBridge-Cb9N_DQI.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-DlZ8tRXt.js → MobileProjects-BNs8tah_.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-D7Pjx1s_.js → Mtc-CaxBt8tn.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-BND7lX8p.js → MtcAudit-DRPQbp3t.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BknS7B-p.js → Multisig-CRm-d8bK.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-7C2-KPHt.js → NLProgramming-BCCk3LPs.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-DNWdTndN.js → Notes-Cv8SN8gN.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-DCm4KcJZ.js → NotificationSettings-CggIvTh5.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-DyVwwjJx.js → OrderTableRenderer-BW3_bV12.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-Dl2O_qJ9.js → Organization-BuRE-VCO.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BOFCvk9Q.js → Overflow-DBrm1gju.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-DgdVowY1.js → P2P-CWVnDYgS.js} +2 -2
- package/src/assets/web-panel/assets/PdhVaultBrowser-8RKUIpte.js +7 -0
- package/src/assets/web-panel/assets/{Permissions-BHNEUUwa.js → Permissions-tDUAxogW.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-CaZbrOdz.js → PersonalDataHub-Dv2-CFis.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-DJDnoXmE.js → Pipeline-DM6kvFni.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CBQr2eX8.js → Privacy-DzK-yL0d.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-Yghqa06z.js → ProjectInit-B5UrNpkj.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-HBAtJi8U.js → ProjectSettings-CxJD43oW.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Z2Orm8Ma.js +1 -0
- package/src/assets/web-panel/assets/{Providers-uJTz77GI.js → Providers-CYl4jRYK.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-k3M5ouTp.js → QrScannerModal-DeH2T0fH.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CMji45PH.js → QuickAsk-Bw9k_kTk.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-DyoZYPls.js → Recommend-Bl_jGwoi.js} +1 -1
- package/src/assets/web-panel/assets/RemoteSession-d6u01Kq0.js +5 -0
- package/src/assets/web-panel/assets/{Reputation-D4hIs4vV.js → Reputation-Ds_Dfr-k.js} +1 -1
- package/src/assets/web-panel/assets/{Row-mzE-ElTg.js → Row-BpQUQTNj.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-cg7J3hI6.js → RssFeed-BatpZBGt.js} +3 -3
- package/src/assets/web-panel/assets/{Search-6M0TkGSZ.js → Search-D7hOObzi.js} +1 -1
- package/src/assets/web-panel/assets/{Security-B1GQ67qh.js → Security-dXQ4FKNt.js} +4 -4
- package/src/assets/web-panel/assets/{Services-D_RwU_5S.js → Services-D8wInGPa.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-TZjk-dsW.js → Skeleton-DXQCoYpM.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CG6FcaCV.js → Skills-D3oLRIVn.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BI190QDv.js → Sla-BmP4-LnJ.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-BWmxF2Wu.js → SpeechSettings-DLj-xzro.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-CwPiGw6L.js → SyncSettings-8KKaaRMr.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-BIXgCeSk.js → Tasks-GyK42I7C.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CQFgGCoK.js → Templates-n1y_8UBG.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-DAelEdkL.js → Tenant-B39nBph8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BbqWK6qh.js → Terminal-DCQoOKXe.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-cmG3zvY5.js → TimelineRenderer-BkhbDfXk.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-C8444NKU.js → Tokens-BeHIIU8D.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-C1Rpnz0I.js → Trigger-BHvWXVOb.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-u4koPiFD.js → Trust-y2WaOSto.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-oPWKn80Z.js → UkeySign-DBFeJBzt.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-D0CUUY_5.js → VideoEditing-BEOWitC-.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-fu9pIAbt.js → Wallet-BITedTe6.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Bc5ciuOx.js → WebAuthn-DMwlJVin.js} +2 -2
- package/src/assets/web-panel/assets/{WorkflowEditor-BCin4_4N.js → WorkflowEditor-CKfGFEu1.js} +1 -1
- package/src/assets/web-panel/assets/{chat-B2jbM-XN.js → chat-DR6gnBGF.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CUVoUQ_2.js → colors-C_Hw5NCn.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-DgOGpkRH.js → compact-item-B8IPwsEu.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DIxU6eKI.js → createContext-D-u4JVnJ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-Cq6lSd_q.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DoKRKMav.js → hasIn-CZubdS4D.js} +1 -1
- package/src/assets/web-panel/assets/{index-ByjrulIZ.js → index-11ASqx-A.js} +1 -1
- package/src/assets/web-panel/assets/index-BQ3213fz.js +1 -0
- package/src/assets/web-panel/assets/{index-BwYofQJg.js → index-BXS6wYJZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CLdpHe6w.js → index-Bi21Etg4.js} +1 -1
- package/src/assets/web-panel/assets/{index-2flsPFIX.js → index-Bizm87cX.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXb-Smmm.js → index-Bv2132PO.js} +1 -1
- package/src/assets/web-panel/assets/{index-B5ySiGYy.js → index-BzoFanEQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-CWbL1-N0.js → index-C25rOz7O.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cj-us-D_.js → index-C2VmtNaQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-C9TsO9T9.js → index-Cbm8F0M2.js} +1 -1
- package/src/assets/web-panel/assets/{index-eTWPaeBI.js → index-CfniPP5p.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2yo6ast.js → index-Cg2bCeol.js} +1 -1
- package/src/assets/web-panel/assets/{index-CPXdBnGi.js → index-CiXkhOkY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BCLeNqIL.js → index-Cl5RpreD.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtSPhEyC.js → index-CqmLw8cs.js} +1 -1
- package/src/assets/web-panel/assets/{index-eYxUASSG.js → index-Ctje8Vl3.js} +1 -1
- package/src/assets/web-panel/assets/{index-i5MB455u.js → index-D1w96gg9.js} +1 -1
- package/src/assets/web-panel/assets/{index-CpvyOt5Z.js → index-D47jt8ET.js} +1 -1
- package/src/assets/web-panel/assets/{index-CeWSw-z5.js → index-DJ6pG79m.js} +1 -1
- package/src/assets/web-panel/assets/{index-B3F_p8NA.js → index-DTosx2Wu.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9mSYovv.js → index-DY6MHo9D.js} +1 -1
- package/src/assets/web-panel/assets/{index-DJMHnbmu.js → index-DcFjRT-K.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-ufbAJB.js → index-DfnzrUxU.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFUprhNd.js → index-DjRrqooR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co4lDEk-.js → index-DmRcgiYT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGTZdZOE.js → index-DpjHpRoq.js} +3 -3
- package/src/assets/web-panel/assets/{index-DHugFl3v.js → index-Dt-w3xQ7.js} +1 -1
- package/src/assets/web-panel/assets/{index-B-f6l4Vm.js → index-DuOU5apg.js} +1 -1
- package/src/assets/web-panel/assets/{index-DtyAuGOm.js → index-LvjAKDSl.js} +1 -1
- package/src/assets/web-panel/assets/{index-be8SonCh.js → index-_nL79NT8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BRMEO2Tl.js → index-auyNYjLo.js} +1 -1
- package/src/assets/web-panel/assets/{index-C88m9lsi.js → index-cVqbas5C.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqlwIjJx.js → index-ffe7bvqP.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpTFx8Xx.js → index-idZKyADQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cskz--fd.js → index-k1Xa5iw1.js} +1 -1
- package/src/assets/web-panel/assets/{index-CF80xxPG.js → index-mYZJxGH6.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ds8r3Fzb.js → index-rYBHSDcJ.js} +1 -1
- package/src/assets/web-panel/assets/index-vJagfET2.js +1 -0
- package/src/assets/web-panel/assets/{index-C846lPGD.js → index-xoNssgz_.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-B4chl7iR.js → initDefaultProps-lcU_dT2r.js} +1 -1
- package/src/assets/web-panel/assets/{motion-DruN9h96.js → motion-Dc7UNXZ1.js} +1 -1
- package/src/assets/web-panel/assets/{move-Cl0UtCgU.js → move-Cll8ZXaL.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-FX2ttw70.js → mtc-parser-CAb_yLIM.js} +1 -1
- package/src/assets/web-panel/assets/{omit-BDCneY46.js → omit-DurYMyTe.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-DycsEg8b.js → pickAttrs-BITQyOlw.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-Bc-dBuMv.js → placementArrow-Dg1rH91i.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve--Wwaf8lu.js → responsiveObserve-D_EWIeac.js} +1 -1
- package/src/assets/web-panel/assets/{slide-vDmHQqHH.js → slide-lK4d3zsh.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-9c52yv3G.js → statusUtils-Bflq-Git.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BT4BiO6_.js → styleChecker-Ccp0I-wt.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-C7XxWPcP.js → useFlexGapSupport-CYZbByYA.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-BHoMqh4i.js → useFs-B_x0nxFD.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-BOLxvsAG.js → usePersonalDataHub-DW55rL85.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CA7poeeP.js → vnode-Ca6MH3W8.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-B_sAn-co.js → zoom-NdHelOog.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/command-help-index.json +1 -1
- package/src/commands/graph.js +215 -5
- package/src/commands/orchestrate.js +61 -9
- package/src/commands/team-distributed.js +342 -2
- package/src/commands/team.js +169 -7
- package/src/data/changelog.json +46 -0
- package/src/gateways/ws/message-dispatcher.js +4 -0
- package/src/gateways/ws/session-protocol.js +89 -11
- package/src/gateways/ws/ws-agent-handler.js +65 -9
- package/src/gateways/ws/ws-approval-gate.js +181 -16
- package/src/gateways/ws/ws-server.js +16 -6
- package/src/generated/cc-agent-protocol.schema.json +154 -3
- package/src/lib/agent-team/task-lease.js +487 -3
- package/src/lib/agent-team/team-agent-stream.js +16 -0
- package/src/lib/agent-team/team-distributed-graph-bridge.js +257 -0
- package/src/lib/agent-team/team-distributed-graph-writer.js +523 -0
- package/src/lib/agent-team/team-distributed-queue.js +251 -0
- package/src/lib/agent-team/team-graph-runtime-adapter.js +1918 -0
- package/src/lib/agent-team/team-runner.js +285 -3
- package/src/lib/app-server/graph-runtime.js +1078 -0
- package/src/lib/app-server/rollout-store.js +32 -0
- package/src/lib/app-server/server.js +200 -0
- package/src/lib/approval-grant-ledger.js +69 -0
- package/src/lib/autonomous-agent.js +11 -0
- package/src/lib/codex-app-server-adapter.js +11 -20
- package/src/lib/cowork-graph-authority-adapter.js +455 -0
- package/src/lib/dynamic-workflow-facade.js +83 -16
- package/src/lib/graph-kernel/adapters.js +93 -20
- package/src/lib/graph-kernel/authority.js +324 -0
- package/src/lib/graph-kernel/compiler.js +67 -21
- package/src/lib/graph-kernel/cutover-authority-resolver.js +245 -0
- package/src/lib/graph-kernel/cutover-ledger.js +692 -0
- package/src/lib/graph-kernel/event-store.js +15 -1
- package/src/lib/graph-kernel/graph-runtime-surfaces.json +1427 -0
- package/src/lib/graph-kernel/index.js +4 -0
- package/src/lib/graph-kernel/migration-saga.js +309 -0
- package/src/lib/graph-kernel/retirement-evidence.js +567 -0
- package/src/lib/graph-kernel/runtime-surface-manifest.js +481 -0
- package/src/lib/graph-kernel/runtime.js +737 -38
- package/src/lib/graph-kernel/store-cutover-evidence.js +354 -0
- package/src/lib/graph-kernel/trace-reducer.js +6 -0
- package/src/lib/graph-kernel/trigger-adapter.js +60 -3
- package/src/lib/interaction-adapter.js +61 -9
- package/src/lib/legacy-runtime-authority.js +160 -0
- package/src/lib/orchestrator.js +28 -0
- package/src/lib/policy-decision-event.js +149 -0
- package/src/lib/process-execution-broker/platform-sandbox.js +15 -1
- package/src/lib/record-replay/index.js +1 -0
- package/src/lib/record-replay/playwright-ui-driver.js +327 -0
- package/src/lib/scheduler-kernel/graph-authority-adapter.js +512 -0
- package/src/lib/scheduler-kernel/runtime.js +75 -2
- package/src/lib/webhook-security.js +484 -36
- package/src/runtime/coding-agent-events.cjs +13 -11
- package/src/runtime/headless-runner.js +17 -1
- package/src/runtime/headless-stream.js +66 -3
- package/src/runtime/session-slash-commands.js +57 -6
- package/src/assets/web-panel/assets/MarkdownRenderer-BwH414Ms.js +0 -1
- package/src/assets/web-panel/assets/PdhVaultBrowser-BiaZfQIM.js +0 -7
- package/src/assets/web-panel/assets/Projects-DiCGnMjz.js +0 -1
- package/src/assets/web-panel/assets/RemoteSession-s1gR38IO.js +0 -5
- package/src/assets/web-panel/assets/devWarning-DiSlgCC4.js +0 -1
- package/src/assets/web-panel/assets/index-9WIQEHvv.js +0 -1
- package/src/assets/web-panel/assets/index-B7mDobAl.js +0 -1
|
@@ -1,4 +1,9 @@
|
|
|
1
1
|
import { graphDigest } from "./compiler.js";
|
|
2
|
+
import {
|
|
3
|
+
GRAPH_AUTHORITY_MODES,
|
|
4
|
+
GraphRunAuthorityRegistry,
|
|
5
|
+
createGraphAuthorityBinding,
|
|
6
|
+
} from "./authority.js";
|
|
2
7
|
|
|
3
8
|
export const GRAPH_RUNTIME_SURFACES = Object.freeze([
|
|
4
9
|
"cli_team",
|
|
@@ -22,8 +27,16 @@ function contractError(code, message, details = {}) {
|
|
|
22
27
|
|
|
23
28
|
export function validateRuntimeClaims(claims) {
|
|
24
29
|
const errors = [];
|
|
25
|
-
|
|
26
|
-
|
|
30
|
+
const originSurface = claims?.originSurface || claims?.surface;
|
|
31
|
+
if (!GRAPH_RUNTIME_SURFACES.includes(originSurface)) {
|
|
32
|
+
errors.push("originSurface must identify a known execution plane");
|
|
33
|
+
}
|
|
34
|
+
if (
|
|
35
|
+
claims?.originSurface &&
|
|
36
|
+
claims?.surface &&
|
|
37
|
+
claims.originSurface !== claims.surface
|
|
38
|
+
) {
|
|
39
|
+
errors.push("surface compatibility alias must match originSurface");
|
|
27
40
|
}
|
|
28
41
|
if (!new Set(["real", "simulated", "planned"]).has(claims?.execution)) {
|
|
29
42
|
errors.push("execution must be real, simulated, or planned");
|
|
@@ -37,7 +50,21 @@ export function validateRuntimeClaims(claims) {
|
|
|
37
50
|
if (typeof claims?.terminalEvidence !== "boolean") {
|
|
38
51
|
errors.push("terminalEvidence must be explicit");
|
|
39
52
|
}
|
|
40
|
-
if (
|
|
53
|
+
if (
|
|
54
|
+
!Array.isArray(claims?.authorityModes) ||
|
|
55
|
+
claims.authorityModes.length === 0 ||
|
|
56
|
+
claims.authorityModes.some((mode) => !GRAPH_AUTHORITY_MODES.includes(mode))
|
|
57
|
+
) {
|
|
58
|
+
errors.push(
|
|
59
|
+
"authorityModes must declare supported per-run authority modes",
|
|
60
|
+
);
|
|
61
|
+
}
|
|
62
|
+
if (claims?.authoritative === true) {
|
|
63
|
+
errors.push(
|
|
64
|
+
"authoritative is not a surface claim; authority must be bound per GraphRun",
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
if (originSurface === "browser") {
|
|
41
68
|
if (
|
|
42
69
|
claims.persistence !== "non_durable" &&
|
|
43
70
|
claims.restartHydration !== true
|
|
@@ -49,13 +76,13 @@ export function validateRuntimeClaims(claims) {
|
|
|
49
76
|
}
|
|
50
77
|
}
|
|
51
78
|
if (
|
|
52
|
-
claims?.
|
|
79
|
+
claims?.authorityModes?.includes("canonical") &&
|
|
53
80
|
(claims.execution !== "real" ||
|
|
54
81
|
claims.persistence !== "durable" ||
|
|
55
82
|
claims.terminalEvidence !== true)
|
|
56
83
|
) {
|
|
57
84
|
errors.push(
|
|
58
|
-
"
|
|
85
|
+
"canonical authority requires real durable evidence-bound execution",
|
|
59
86
|
);
|
|
60
87
|
}
|
|
61
88
|
return Object.freeze({
|
|
@@ -65,9 +92,9 @@ export function validateRuntimeClaims(claims) {
|
|
|
65
92
|
}
|
|
66
93
|
|
|
67
94
|
export class GraphRuntimeAdapterRegistry {
|
|
68
|
-
constructor() {
|
|
95
|
+
constructor({ authorityRegistry = new GraphRunAuthorityRegistry() } = {}) {
|
|
69
96
|
this.adapters = new Map();
|
|
70
|
-
this.
|
|
97
|
+
this.authorityRegistry = authorityRegistry;
|
|
71
98
|
}
|
|
72
99
|
|
|
73
100
|
register(adapter) {
|
|
@@ -78,6 +105,8 @@ export class GraphRuntimeAdapterRegistry {
|
|
|
78
105
|
);
|
|
79
106
|
}
|
|
80
107
|
const claims = clone(adapter.runtimeClaims());
|
|
108
|
+
claims.originSurface ||= claims.surface;
|
|
109
|
+
claims.surface ||= claims.originSurface;
|
|
81
110
|
const validation = validateRuntimeClaims(claims);
|
|
82
111
|
if (!validation.valid) {
|
|
83
112
|
throw contractError(
|
|
@@ -86,23 +115,17 @@ export class GraphRuntimeAdapterRegistry {
|
|
|
86
115
|
{ errors: validation.errors },
|
|
87
116
|
);
|
|
88
117
|
}
|
|
89
|
-
if (claims.
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
)
|
|
94
|
-
throw contractError(
|
|
95
|
-
"CC_GRAPH_MULTIPLE_AUTHORITATIVE_WRITERS",
|
|
96
|
-
"only one Graph Kernel adapter may write authoritative run state",
|
|
97
|
-
);
|
|
98
|
-
}
|
|
99
|
-
this.authoritativeSurface = claims.surface;
|
|
118
|
+
if (this.adapters.has(claims.originSurface)) {
|
|
119
|
+
throw contractError(
|
|
120
|
+
"CC_GRAPH_ADAPTER_ALREADY_REGISTERED",
|
|
121
|
+
`graph runtime adapter is already registered: ${claims.originSurface}`,
|
|
122
|
+
);
|
|
100
123
|
}
|
|
101
|
-
this.adapters.set(claims.
|
|
124
|
+
this.adapters.set(claims.originSurface, {
|
|
102
125
|
adapter,
|
|
103
126
|
claims: Object.freeze(claims),
|
|
104
127
|
});
|
|
105
|
-
return this.claims(claims.
|
|
128
|
+
return this.claims(claims.originSurface);
|
|
106
129
|
}
|
|
107
130
|
|
|
108
131
|
claims(surface) {
|
|
@@ -121,6 +144,56 @@ export class GraphRuntimeAdapterRegistry {
|
|
|
121
144
|
adapter(surface) {
|
|
122
145
|
return this.adapters.get(surface)?.adapter || null;
|
|
123
146
|
}
|
|
147
|
+
|
|
148
|
+
bindRunAuthority(originSurface, input, options = {}) {
|
|
149
|
+
const claims = this.claims(originSurface);
|
|
150
|
+
if (!claims) {
|
|
151
|
+
throw contractError(
|
|
152
|
+
"CC_GRAPH_ADAPTER_NOT_REGISTERED",
|
|
153
|
+
`graph runtime adapter is not registered: ${originSurface}`,
|
|
154
|
+
);
|
|
155
|
+
}
|
|
156
|
+
const authorityMode = String(input?.authorityMode || "");
|
|
157
|
+
if (!claims.authorityModes.includes(authorityMode)) {
|
|
158
|
+
throw contractError(
|
|
159
|
+
"CC_GRAPH_AUTHORITY_MODE_UNSUPPORTED",
|
|
160
|
+
`${originSurface} does not support ${authorityMode} authority`,
|
|
161
|
+
);
|
|
162
|
+
}
|
|
163
|
+
if (originSurface === "browser" && authorityMode === "canonical") {
|
|
164
|
+
throw contractError(
|
|
165
|
+
"CC_GRAPH_BROWSER_NON_DURABLE",
|
|
166
|
+
"browser runtime cannot acquire canonical authority while non-durable",
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
const authoritySource =
|
|
170
|
+
authorityMode === "canonical"
|
|
171
|
+
? "graph_kernel"
|
|
172
|
+
: authorityMode === "shadow"
|
|
173
|
+
? "graph_kernel_shadow"
|
|
174
|
+
: "legacy_runtime";
|
|
175
|
+
const binding = createGraphAuthorityBinding({
|
|
176
|
+
...input,
|
|
177
|
+
originSurface,
|
|
178
|
+
authorityMode,
|
|
179
|
+
authoritySource,
|
|
180
|
+
});
|
|
181
|
+
return this.authorityRegistry.bind(binding, options);
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
runAuthority(logicalRunId) {
|
|
185
|
+
return this.authorityRegistry.get(logicalRunId);
|
|
186
|
+
}
|
|
187
|
+
|
|
188
|
+
transitionSurface(originSurface, stage) {
|
|
189
|
+
if (!this.adapters.has(originSurface)) {
|
|
190
|
+
throw contractError(
|
|
191
|
+
"CC_GRAPH_ADAPTER_NOT_REGISTERED",
|
|
192
|
+
`graph runtime adapter is not registered: ${originSurface}`,
|
|
193
|
+
);
|
|
194
|
+
}
|
|
195
|
+
return this.authorityRegistry.transition(originSurface, stage);
|
|
196
|
+
}
|
|
124
197
|
}
|
|
125
198
|
|
|
126
199
|
function terminalProjection(value) {
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
export const GRAPH_AUTHORITY_SCHEMA = "chainlesschain.graph-authority/v1";
|
|
2
|
+
export const GRAPH_PROJECTION_VERSION = 1;
|
|
3
|
+
export const GRAPH_AUTHORITY_MODES = Object.freeze([
|
|
4
|
+
"legacy",
|
|
5
|
+
"shadow",
|
|
6
|
+
"canonical",
|
|
7
|
+
]);
|
|
8
|
+
export const GRAPH_CUTOVER_STAGES = Object.freeze([
|
|
9
|
+
"legacy",
|
|
10
|
+
"shadow",
|
|
11
|
+
"canary",
|
|
12
|
+
"canonical",
|
|
13
|
+
"legacy_read_only",
|
|
14
|
+
]);
|
|
15
|
+
|
|
16
|
+
const AUTHORITY_SOURCES = new Set([
|
|
17
|
+
"legacy_runtime",
|
|
18
|
+
"graph_kernel_shadow",
|
|
19
|
+
"graph_kernel",
|
|
20
|
+
]);
|
|
21
|
+
|
|
22
|
+
function authorityError(code, message, details = {}) {
|
|
23
|
+
const error = new Error(message);
|
|
24
|
+
error.name = "GraphAuthorityError";
|
|
25
|
+
error.code = code;
|
|
26
|
+
Object.assign(error, details);
|
|
27
|
+
return error;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function clone(value) {
|
|
31
|
+
return value == null ? value : JSON.parse(JSON.stringify(value));
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function identifier(value, label) {
|
|
35
|
+
const output = String(value || "").trim();
|
|
36
|
+
if (!/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$/u.test(output)) {
|
|
37
|
+
throw authorityError("CC_GRAPH_AUTHORITY_INVALID", `${label} is invalid`, {
|
|
38
|
+
field: label,
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
return output;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
function eventHead(value) {
|
|
45
|
+
if (value == null) return null;
|
|
46
|
+
const output = String(value);
|
|
47
|
+
if (!/^sha256:[a-f0-9]{64}$/u.test(output)) {
|
|
48
|
+
throw authorityError(
|
|
49
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
50
|
+
"eventHead must be a sha256 digest or null",
|
|
51
|
+
{ field: "eventHead" },
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
return output;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function leaseExpiry(value) {
|
|
58
|
+
if (value == null) return null;
|
|
59
|
+
const output = String(value);
|
|
60
|
+
const milliseconds = Date.parse(output);
|
|
61
|
+
if (!Number.isFinite(milliseconds)) {
|
|
62
|
+
throw authorityError(
|
|
63
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
64
|
+
"writerLeaseExpiresAt must be an ISO timestamp",
|
|
65
|
+
{ field: "writerLeaseExpiresAt" },
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
return new Date(milliseconds).toISOString();
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
export function createGraphAuthorityBinding(input = {}) {
|
|
72
|
+
const authorityMode = String(input.authorityMode || "").trim();
|
|
73
|
+
if (!GRAPH_AUTHORITY_MODES.includes(authorityMode)) {
|
|
74
|
+
throw authorityError(
|
|
75
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
76
|
+
"authorityMode must be legacy, shadow, or canonical",
|
|
77
|
+
{ field: "authorityMode" },
|
|
78
|
+
);
|
|
79
|
+
}
|
|
80
|
+
const authoritySource = String(input.authoritySource || "").trim();
|
|
81
|
+
if (!AUTHORITY_SOURCES.has(authoritySource)) {
|
|
82
|
+
throw authorityError(
|
|
83
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
84
|
+
"authoritySource is not recognized",
|
|
85
|
+
{ field: "authoritySource" },
|
|
86
|
+
);
|
|
87
|
+
}
|
|
88
|
+
if (
|
|
89
|
+
(authorityMode === "canonical" && authoritySource !== "graph_kernel") ||
|
|
90
|
+
(authorityMode === "shadow" && authoritySource !== "graph_kernel_shadow") ||
|
|
91
|
+
(authorityMode === "legacy" && authoritySource !== "legacy_runtime")
|
|
92
|
+
) {
|
|
93
|
+
throw authorityError(
|
|
94
|
+
"CC_GRAPH_AUTHORITY_SOURCE_MISMATCH",
|
|
95
|
+
"authoritySource does not match authorityMode",
|
|
96
|
+
);
|
|
97
|
+
}
|
|
98
|
+
const authorityGeneration = Number(input.authorityGeneration);
|
|
99
|
+
if (!Number.isSafeInteger(authorityGeneration) || authorityGeneration < 1) {
|
|
100
|
+
throw authorityError(
|
|
101
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
102
|
+
"authorityGeneration must be a positive safe integer",
|
|
103
|
+
{ field: "authorityGeneration" },
|
|
104
|
+
);
|
|
105
|
+
}
|
|
106
|
+
const projectionVersion = Number(
|
|
107
|
+
input.projectionVersion ?? GRAPH_PROJECTION_VERSION,
|
|
108
|
+
);
|
|
109
|
+
if (!Number.isSafeInteger(projectionVersion) || projectionVersion < 1) {
|
|
110
|
+
throw authorityError(
|
|
111
|
+
"CC_GRAPH_AUTHORITY_INVALID",
|
|
112
|
+
"projectionVersion must be a positive safe integer",
|
|
113
|
+
{ field: "projectionVersion" },
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const binding = {
|
|
117
|
+
schema: GRAPH_AUTHORITY_SCHEMA,
|
|
118
|
+
logicalRunId: identifier(input.logicalRunId, "logicalRunId"),
|
|
119
|
+
originSurface: identifier(input.originSurface, "originSurface"),
|
|
120
|
+
authorityMode,
|
|
121
|
+
authoritySource,
|
|
122
|
+
authorityGeneration,
|
|
123
|
+
writerId: identifier(input.writerId, "writerId"),
|
|
124
|
+
writerLeaseId: identifier(input.writerLeaseId, "writerLeaseId"),
|
|
125
|
+
writerLeaseExpiresAt: leaseExpiry(input.writerLeaseExpiresAt),
|
|
126
|
+
eventHead: eventHead(input.eventHead),
|
|
127
|
+
projectionVersion,
|
|
128
|
+
};
|
|
129
|
+
if (authorityMode === "canonical" && !binding.writerLeaseExpiresAt) {
|
|
130
|
+
throw authorityError(
|
|
131
|
+
"CC_GRAPH_WRITER_LEASE_REQUIRED",
|
|
132
|
+
"canonical authority requires an expiring writer lease",
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
return Object.freeze(binding);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
export function assertGraphAuthorityWriter(
|
|
139
|
+
binding,
|
|
140
|
+
writer,
|
|
141
|
+
{
|
|
142
|
+
now = Date.now(),
|
|
143
|
+
expectedEventHead = undefined,
|
|
144
|
+
requireCanonical = true,
|
|
145
|
+
} = {},
|
|
146
|
+
) {
|
|
147
|
+
const current = createGraphAuthorityBinding(binding);
|
|
148
|
+
if (requireCanonical && current.authorityMode !== "canonical") {
|
|
149
|
+
throw authorityError(
|
|
150
|
+
"CC_GRAPH_NON_CANONICAL_WRITER",
|
|
151
|
+
"only canonical authority may mutate canonical Graph state",
|
|
152
|
+
);
|
|
153
|
+
}
|
|
154
|
+
if (
|
|
155
|
+
current.authoritySource !== writer?.authoritySource ||
|
|
156
|
+
current.authorityGeneration !== Number(writer?.authorityGeneration) ||
|
|
157
|
+
current.writerId !== writer?.writerId ||
|
|
158
|
+
current.writerLeaseId !== writer?.writerLeaseId
|
|
159
|
+
) {
|
|
160
|
+
throw authorityError(
|
|
161
|
+
"CC_GRAPH_STALE_WRITER",
|
|
162
|
+
"writer identity, generation, or lease does not own this GraphRun",
|
|
163
|
+
{
|
|
164
|
+
authorityGeneration: current.authorityGeneration,
|
|
165
|
+
writerId: current.writerId,
|
|
166
|
+
},
|
|
167
|
+
);
|
|
168
|
+
}
|
|
169
|
+
if (
|
|
170
|
+
current.writerLeaseExpiresAt &&
|
|
171
|
+
Date.parse(current.writerLeaseExpiresAt) <= Number(now)
|
|
172
|
+
) {
|
|
173
|
+
throw authorityError(
|
|
174
|
+
"CC_GRAPH_WRITER_LEASE_EXPIRED",
|
|
175
|
+
"GraphRun writer lease has expired",
|
|
176
|
+
);
|
|
177
|
+
}
|
|
178
|
+
if (
|
|
179
|
+
expectedEventHead !== undefined &&
|
|
180
|
+
current.eventHead !== expectedEventHead
|
|
181
|
+
) {
|
|
182
|
+
throw authorityError(
|
|
183
|
+
"CC_GRAPH_EVENT_HEAD_CONFLICT",
|
|
184
|
+
"GraphRun event head changed before mutation",
|
|
185
|
+
{ expectedEventHead, actualEventHead: current.eventHead },
|
|
186
|
+
);
|
|
187
|
+
}
|
|
188
|
+
return current;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const CUTOVER_TRANSITIONS = Object.freeze({
|
|
192
|
+
legacy: new Set(["shadow"]),
|
|
193
|
+
shadow: new Set(["legacy", "canary"]),
|
|
194
|
+
canary: new Set(["shadow", "canonical"]),
|
|
195
|
+
canonical: new Set(["canary", "legacy_read_only"]),
|
|
196
|
+
legacy_read_only: new Set(["canonical"]),
|
|
197
|
+
});
|
|
198
|
+
|
|
199
|
+
export function assertGraphCutoverTransition(from, to) {
|
|
200
|
+
if (
|
|
201
|
+
!GRAPH_CUTOVER_STAGES.includes(from) ||
|
|
202
|
+
!GRAPH_CUTOVER_STAGES.includes(to)
|
|
203
|
+
) {
|
|
204
|
+
throw authorityError(
|
|
205
|
+
"CC_GRAPH_CUTOVER_STAGE_INVALID",
|
|
206
|
+
"Graph cutover stage is invalid",
|
|
207
|
+
);
|
|
208
|
+
}
|
|
209
|
+
if (from === to) return to;
|
|
210
|
+
if (!CUTOVER_TRANSITIONS[from].has(to)) {
|
|
211
|
+
throw authorityError(
|
|
212
|
+
"CC_GRAPH_CUTOVER_TRANSITION_INVALID",
|
|
213
|
+
`Graph cutover cannot transition from ${from} to ${to}`,
|
|
214
|
+
);
|
|
215
|
+
}
|
|
216
|
+
return to;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
export class GraphRunAuthorityRegistry {
|
|
220
|
+
constructor({ now = Date.now } = {}) {
|
|
221
|
+
this.now = now;
|
|
222
|
+
this.runs = new Map();
|
|
223
|
+
this.cutovers = new Map();
|
|
224
|
+
}
|
|
225
|
+
|
|
226
|
+
bind(input, { replace = false } = {}) {
|
|
227
|
+
const next = createGraphAuthorityBinding(input);
|
|
228
|
+
const previous = this.runs.get(next.logicalRunId);
|
|
229
|
+
if (previous) {
|
|
230
|
+
if (next.authorityGeneration < previous.authorityGeneration) {
|
|
231
|
+
throw authorityError(
|
|
232
|
+
"CC_GRAPH_STALE_GENERATION",
|
|
233
|
+
"authority generation cannot move backwards",
|
|
234
|
+
);
|
|
235
|
+
}
|
|
236
|
+
if (next.authorityGeneration === previous.authorityGeneration) {
|
|
237
|
+
const sameOwner =
|
|
238
|
+
next.authoritySource === previous.authoritySource &&
|
|
239
|
+
next.authorityMode === previous.authorityMode &&
|
|
240
|
+
next.writerId === previous.writerId &&
|
|
241
|
+
next.writerLeaseId === previous.writerLeaseId;
|
|
242
|
+
if (!sameOwner) {
|
|
243
|
+
throw authorityError(
|
|
244
|
+
"CC_GRAPH_MULTIPLE_AUTHORITATIVE_WRITERS",
|
|
245
|
+
"one logical GraphRun cannot have two writers in one generation",
|
|
246
|
+
);
|
|
247
|
+
}
|
|
248
|
+
} else {
|
|
249
|
+
if (!replace) {
|
|
250
|
+
throw authorityError(
|
|
251
|
+
"CC_GRAPH_AUTHORITY_REPLACEMENT_REQUIRED",
|
|
252
|
+
"a higher writer generation requires an explicit replacement",
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
if (next.eventHead !== previous.eventHead) {
|
|
256
|
+
throw authorityError(
|
|
257
|
+
"CC_GRAPH_EVENT_HEAD_CONFLICT",
|
|
258
|
+
"writer replacement must bind the exact persisted event head",
|
|
259
|
+
);
|
|
260
|
+
}
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
this.runs.set(next.logicalRunId, next);
|
|
264
|
+
return this.get(next.logicalRunId);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
assertWriter(logicalRunId, writer, options = {}) {
|
|
268
|
+
const current = this.runs.get(identifier(logicalRunId, "logicalRunId"));
|
|
269
|
+
if (!current) {
|
|
270
|
+
throw authorityError(
|
|
271
|
+
"CC_GRAPH_AUTHORITY_NOT_FOUND",
|
|
272
|
+
"GraphRun has no registered authority",
|
|
273
|
+
);
|
|
274
|
+
}
|
|
275
|
+
return assertGraphAuthorityWriter(current, writer, {
|
|
276
|
+
now: this.now(),
|
|
277
|
+
...options,
|
|
278
|
+
});
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
advanceEventHead(
|
|
282
|
+
logicalRunId,
|
|
283
|
+
writer,
|
|
284
|
+
{ expectedEventHead, eventHead: next },
|
|
285
|
+
) {
|
|
286
|
+
const current = this.assertWriter(logicalRunId, writer, {
|
|
287
|
+
expectedEventHead,
|
|
288
|
+
});
|
|
289
|
+
const updated = createGraphAuthorityBinding({
|
|
290
|
+
...current,
|
|
291
|
+
eventHead: next,
|
|
292
|
+
});
|
|
293
|
+
this.runs.set(current.logicalRunId, updated);
|
|
294
|
+
return this.get(current.logicalRunId);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
transition(originSurface, to) {
|
|
298
|
+
const surface = identifier(originSurface, "originSurface");
|
|
299
|
+
const from = this.cutovers.get(surface) || "legacy";
|
|
300
|
+
this.cutovers.set(surface, assertGraphCutoverTransition(from, to));
|
|
301
|
+
return Object.freeze({ originSurface: surface, from, to });
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
cutoverStage(originSurface) {
|
|
305
|
+
return (
|
|
306
|
+
this.cutovers.get(identifier(originSurface, "originSurface")) || "legacy"
|
|
307
|
+
);
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
get(logicalRunId) {
|
|
311
|
+
const value = this.runs.get(identifier(logicalRunId, "logicalRunId"));
|
|
312
|
+
return value ? Object.freeze(clone(value)) : null;
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
list() {
|
|
316
|
+
return Object.freeze(
|
|
317
|
+
[...this.runs.values()]
|
|
318
|
+
.map(clone)
|
|
319
|
+
.sort((left, right) =>
|
|
320
|
+
left.logicalRunId.localeCompare(right.logicalRunId),
|
|
321
|
+
),
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
}
|
|
@@ -1,19 +1,14 @@
|
|
|
1
1
|
import { createHash } from "node:crypto";
|
|
2
|
-
import
|
|
2
|
+
import graphProtocolSchema from "../../generated/cc-agent-protocol.schema.json" with { type: "json" };
|
|
3
3
|
import { validate } from "../json-schema-validate.js";
|
|
4
4
|
|
|
5
|
-
const graphProtocolSchema = JSON.parse(
|
|
6
|
-
readFileSync(
|
|
7
|
-
new URL("../../generated/cc-agent-protocol.schema.json", import.meta.url),
|
|
8
|
-
"utf8",
|
|
9
|
-
),
|
|
10
|
-
);
|
|
11
|
-
|
|
12
5
|
export const GRAPH_DEFINITION_VERSION = 1;
|
|
13
6
|
export const GRAPH_DEFINITION_MIN_VERSION = Math.max(
|
|
14
7
|
0,
|
|
15
8
|
GRAPH_DEFINITION_VERSION - 1,
|
|
16
9
|
);
|
|
10
|
+
export const GRAPH_DEFINITION_MIGRATION_EVIDENCE_SCHEMA =
|
|
11
|
+
"chainlesschain.graph-definition-migration/v1";
|
|
17
12
|
export const GRAPH_COMPILE_ERROR = "CC_GRAPH_COMPILE_FAILED";
|
|
18
13
|
|
|
19
14
|
const compiledGraphs = new WeakSet();
|
|
@@ -1292,6 +1287,22 @@ export function compileGraphDefinition(input, options = {}) {
|
|
|
1292
1287
|
definition,
|
|
1293
1288
|
`cc.graph.definition/${definition.schemaVersion}`,
|
|
1294
1289
|
);
|
|
1290
|
+
const migrationBackup =
|
|
1291
|
+
migrated.migratedFrom == null ? null : deepFreeze(stableValue(input));
|
|
1292
|
+
const definitionMigration =
|
|
1293
|
+
migrationBackup == null
|
|
1294
|
+
? null
|
|
1295
|
+
: deepFreeze({
|
|
1296
|
+
schema: GRAPH_DEFINITION_MIGRATION_EVIDENCE_SCHEMA,
|
|
1297
|
+
fromVersion: migrated.migratedFrom,
|
|
1298
|
+
toVersion: definition.schemaVersion,
|
|
1299
|
+
revisionDigest,
|
|
1300
|
+
backupDefinition: migrationBackup,
|
|
1301
|
+
rollbackDigest: graphDigest(
|
|
1302
|
+
migrationBackup,
|
|
1303
|
+
`cc.graph.definition-backup/${migrated.migratedFrom}`,
|
|
1304
|
+
),
|
|
1305
|
+
});
|
|
1295
1306
|
const compiled = {
|
|
1296
1307
|
schema: "chainlesschain.compiled-graph/v1",
|
|
1297
1308
|
schemaVersion: definition.schemaVersion,
|
|
@@ -1300,6 +1311,7 @@ export function compileGraphDefinition(input, options = {}) {
|
|
|
1300
1311
|
revision: definition.revision,
|
|
1301
1312
|
revisionDigest,
|
|
1302
1313
|
migratedFrom: migrated.migratedFrom,
|
|
1314
|
+
definitionMigration,
|
|
1303
1315
|
nodes: deepFreeze(
|
|
1304
1316
|
Object.fromEntries([...nodes].map(([id, value]) => [id, value])),
|
|
1305
1317
|
),
|
|
@@ -1376,25 +1388,59 @@ export function assertCompiledGraph(value) {
|
|
|
1376
1388
|
}
|
|
1377
1389
|
|
|
1378
1390
|
export function migrateGraphDefinition(input, options = {}) {
|
|
1379
|
-
const
|
|
1380
|
-
const
|
|
1381
|
-
const backupDefinition =
|
|
1382
|
-
migratedFrom == null ? null : deepFreeze(stableValue(input));
|
|
1391
|
+
const compiled = compileGraphDefinition(input, options);
|
|
1392
|
+
const migration = compiled.definitionMigration;
|
|
1383
1393
|
return Object.freeze({
|
|
1384
1394
|
dryRun: options.dryRun !== false,
|
|
1385
|
-
fromVersion:
|
|
1395
|
+
fromVersion: migration?.fromVersion ?? compiled.schemaVersion,
|
|
1386
1396
|
toVersion: compiled.schemaVersion,
|
|
1387
1397
|
definition: compiled.definition,
|
|
1388
1398
|
revisionDigest: compiled.revisionDigest,
|
|
1389
|
-
backupRequired:
|
|
1399
|
+
backupRequired: migration != null,
|
|
1400
|
+
backupDefinition: migration?.backupDefinition || null,
|
|
1401
|
+
rollbackDigest: migration?.rollbackDigest || null,
|
|
1402
|
+
});
|
|
1403
|
+
}
|
|
1404
|
+
|
|
1405
|
+
export function validateGraphDefinitionMigrationEvidence(value) {
|
|
1406
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
1407
|
+
const error = new TypeError(
|
|
1408
|
+
"graph definition migration evidence is required",
|
|
1409
|
+
);
|
|
1410
|
+
error.code = "CC_GRAPH_MIGRATION_EVIDENCE_INVALID";
|
|
1411
|
+
throw error;
|
|
1412
|
+
}
|
|
1413
|
+
if (
|
|
1414
|
+
value.schema !== GRAPH_DEFINITION_MIGRATION_EVIDENCE_SCHEMA ||
|
|
1415
|
+
Number(value.fromVersion) !== GRAPH_DEFINITION_VERSION - 1 ||
|
|
1416
|
+
Number(value.toVersion) !== GRAPH_DEFINITION_VERSION ||
|
|
1417
|
+
!/^sha256:[a-f0-9]{64}$/u.test(String(value.revisionDigest || ""))
|
|
1418
|
+
) {
|
|
1419
|
+
const error = new TypeError(
|
|
1420
|
+
"graph definition migration evidence has an invalid schema or version",
|
|
1421
|
+
);
|
|
1422
|
+
error.code = "CC_GRAPH_MIGRATION_EVIDENCE_INVALID";
|
|
1423
|
+
throw error;
|
|
1424
|
+
}
|
|
1425
|
+
const backupDefinition = restoreGraphDefinitionBackup(
|
|
1426
|
+
value.backupDefinition,
|
|
1427
|
+
value.rollbackDigest,
|
|
1428
|
+
);
|
|
1429
|
+
const replay = compileGraphDefinition(backupDefinition);
|
|
1430
|
+
if (replay.revisionDigest !== value.revisionDigest) {
|
|
1431
|
+
const error = new TypeError(
|
|
1432
|
+
"graph definition migration replay does not match its canonical revision",
|
|
1433
|
+
);
|
|
1434
|
+
error.code = "CC_GRAPH_MIGRATION_REPLAY_MISMATCH";
|
|
1435
|
+
throw error;
|
|
1436
|
+
}
|
|
1437
|
+
return deepFreeze({
|
|
1438
|
+
schema: GRAPH_DEFINITION_MIGRATION_EVIDENCE_SCHEMA,
|
|
1439
|
+
fromVersion: GRAPH_DEFINITION_VERSION - 1,
|
|
1440
|
+
toVersion: GRAPH_DEFINITION_VERSION,
|
|
1441
|
+
revisionDigest: value.revisionDigest,
|
|
1390
1442
|
backupDefinition,
|
|
1391
|
-
rollbackDigest:
|
|
1392
|
-
backupDefinition == null
|
|
1393
|
-
? null
|
|
1394
|
-
: graphDigest(
|
|
1395
|
-
backupDefinition,
|
|
1396
|
-
`cc.graph.definition-backup/${migratedFrom}`,
|
|
1397
|
-
),
|
|
1443
|
+
rollbackDigest: value.rollbackDigest,
|
|
1398
1444
|
});
|
|
1399
1445
|
}
|
|
1400
1446
|
|