chainlesschain 0.166.21 → 0.166.24
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 +67 -9
- package/package.json +4 -3
- package/src/assets/web-panel/assets/{AIOps-BjMnsUci.js → AIOps-DR-MWcZc.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DdYFP03A.js → ActionButton-DT8B7sEb.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-Bb8TuuK_.js → Analytics-asjh3dQJ.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-Kn3TIOtk.js → AppLayout-DivQ491i.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-4IxpqI_b.js → Artifacts-DPH2uUmy.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-BOV2caqU.js → Audit-Bp2nLyc-.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-B86k-ay4.js → BackgroundAgents-CHS28khl.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-C5_ie1e3.js → Backup-CKeaFSfz.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-xpwg6QCW.js → BaseInput-CxwM9BAH.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CVZOcZau.js → Chat-DYLDwaCv.js} +4 -4
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-D8fPYhUu.js → ChatBubbleRenderer-DdBJDBP0.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-MKTq3zdP.js → Checkbox-uYTWOB8j.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-JUk3wzep.js → Codegen-CvYa_dwT.js} +1 -1
- package/src/assets/web-panel/assets/{Col-JPvTA0kC.js → Col-CanMAX4m.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Tqgl87NQ.js → Community-B4WaDtHw.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-BuAFYBmN.js → Compact-K93Uof_3.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CXS9WIPZ.js → Compliance-CKeDLgUW.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-Ds2bFHrr.js → Cowork-P93grAeB.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-C_dV_OeW.js → Cron-BSHnMtDn.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BsO6tIRo.js → Crosschain-epAOpUVJ.js} +1 -1
- package/src/assets/web-panel/assets/{DID-rNOFqBac.js → DID-ByjXfP7t.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C2fcKKVY.js → Dashboard-QztTU8tb.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-Y7Ndr0X_.js → Dropdown-DhUc9yhN.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DcP_uPmL.js → EmailListRenderer-C2sLhJJN.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Cwn3gDzk.js → FamilyGuardDashboard-CdfbWNDn.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-ClQuOsqb.js → Federation-CcF_R7NW.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-DfwtmlcK.js → FormItemContext-Cm_X2IBk.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-zNZhtbC5.js → GenericCardRenderer-DUi4NWlb.js} +1 -1
- package/src/assets/web-panel/assets/{Git-BZmdW-G5.js → Git-4Sq5FjBt.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-CqBk4lEn.js → Governance-Dx2_v4V6.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-Dbmt3ZXk.js → Inference-7Vr1xekR.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-hMTH6qf3.js → KnowledgeGraph-Cnd2XOzf.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-CkiYgiW2.js → Logs-B66QPVf-.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-BL1FElXg.js → MarkdownRenderer-PLsEvhly.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-CbB6wfin.js → Marketplace-BMIK9BmC.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BSwiFtte.js → McpTools-BDbyp3J_.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-B03PeHrz.js → Memory-CJdzfZGi.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CRGrnd-X.js → MobileBridge-C2TH5Y3-.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CE_5v2kO.js → MobileProjects-D1dYXkvV.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-Dp11QVx1.js → Mtc-B-4A1I1j.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-CYu-3JBu.js → MtcAudit-Bgcc9UOl.js} +5 -5
- package/src/assets/web-panel/assets/{Multisig-CGyJ0Xl3.js → Multisig-DqOe-etP.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-CoWi_ov1.js → NLProgramming-7VnhzE_6.js} +1 -1
- package/src/assets/web-panel/assets/Notes-BxawpeUQ.js +7 -0
- package/src/assets/web-panel/assets/{NotificationSettings-DX4I2b4W.js → NotificationSettings-Cr08G2aE.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Ce8bEGlK.js +1 -0
- package/src/assets/web-panel/assets/{Organization-oopLO_tk.js → Organization-BC7lveGv.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-BFVvjMyf.js → Overflow-CakOW-G0.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-CBy5t-Tk.js → P2P-Cf8CaOBZ.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser--YWJNsu6.js → PdhVaultBrowser-Dc7b98W9.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-C2dZ8scb.js → Permissions-DGJyMEfS.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-Bs3l7Hlx.js → PersonalDataHub-DNIwSdwu.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-DEBWbZuD.js → Pipeline-5B1S12wa.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CjHBb6NU.js → Privacy-CMB6Ke5t.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D2WipUz5.js → ProjectInit-D5PqTFiT.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B6WfnrGB.js → ProjectSettings-CbKNdSjV.js} +2 -2
- package/src/assets/web-panel/assets/Projects-ccXaHzYL.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CCv5M_Dv.js → Providers-CJF5_-Gs.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CGthxU54.js → QrScannerModal-CT6iEAdi.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-CnPmXPFb.js → QuickAsk-Ci0h9mJ_.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Df_tGEa9.js → Recommend-Da5mobZu.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-Z58N0Loe.js → RemoteSession-BaCY8eey.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CZTBQ2Vt.js → Reputation-CaITfTsI.js} +1 -1
- package/src/assets/web-panel/assets/{Row-CdK3YpCQ.js → Row-DtUDamyP.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CFMVT5sb.js → RssFeed-DX27gFpg.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DrF8RIvD.js → Search-DFL69osN.js} +1 -1
- package/src/assets/web-panel/assets/{Security-Ddk2f2DM.js → Security-BqGeoWv-.js} +3 -3
- package/src/assets/web-panel/assets/{Services-CCuK-VOo.js → Services-3z1WnEAc.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DxCpHzeM.js → Skeleton-C_OJQQ9Z.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-t2oTDgcv.js → Skills-BY7aT6Mo.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-Df63M9_R.js → Sla-BZv7DSaD.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-6lJKLhCn.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-COd_tgPp.js → SyncSettings-B6D7STlI.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CzDCcrik.js → Tasks-Co_FCZAO.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-D-vfxTGA.js → Templates-CnY-9fgz.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-BlpT_Gxc.js → Tenant-B71yXfZ8.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-D5rq52Hg.js → Terminal-Dd_P7awo.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-DdoMndkK.js → TimelineRenderer-CvIEMyli.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-BhgBsI6g.js → Tokens-DknFBGOi.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-DwwzoikZ.js → Trigger-D_4nJONB.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-HkTpzXFb.js → Trust-BNl21fa7.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-D9nk6Ehe.js → UkeySign-CFrCI7uK.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BKk0rfoy.js → VideoEditing-BVfY6JLg.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-IVWIU_Lq.js → Wallet-Cj9CAK0J.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-CFTCpfsG.js → WebAuthn-DcqZlzA3.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-Dnf4Obif.js → WorkflowEditor-Dfr_dMld.js} +1 -1
- package/src/assets/web-panel/assets/{chat-D2snERdj.js → chat-Yv6UF0AD.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DKEjK1N1.js → colors-CDW_-1fs.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BEDLwQdt.js → compact-item-BYOQvd-6.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DA9iW1a0.js → createContext-BCGO0BiP.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-H-kXSuf-.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-5l2xEcY9.js → hasIn-DY-70cfQ.js} +1 -1
- package/src/assets/web-panel/assets/{index-B7_W_rYd.js → index-366wfQBU.js} +1 -1
- package/src/assets/web-panel/assets/index-B0o4MeNK.js +1 -0
- package/src/assets/web-panel/assets/{index-CxEtQYdi.js → index-B9ZogJJM.js} +1 -1
- package/src/assets/web-panel/assets/{index-B00GeekA.js → index-B9m5QAMg.js} +1 -1
- package/src/assets/web-panel/assets/{index-C7sKbM5s.js → index-BBs2mv5M.js} +1 -1
- package/src/assets/web-panel/assets/{index-CX1x4AFn.js → index-BFv1hzF6.js} +1 -1
- package/src/assets/web-panel/assets/index-BVafOL_I.js +1 -0
- package/src/assets/web-panel/assets/{index-DU2TXJu-.js → index-BXlEx4UH.js} +1 -1
- package/src/assets/web-panel/assets/{index-e-e40id6.js → index-BayRTE5w.js} +1 -1
- package/src/assets/web-panel/assets/{index-DXet1xol.js → index-Bb9nyts1.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7z4zB_a.js → index-Bf_Va0S-.js} +1 -1
- package/src/assets/web-panel/assets/{index-fccZmC_h.js → index-Br3wQLVY.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bqc8tdIF.js → index-BvK4fjkk.js} +1 -1
- package/src/assets/web-panel/assets/{index-BO9dQjpt.js → index-C40UdtlS.js} +1 -1
- package/src/assets/web-panel/assets/{index-Csfb-7hw.js → index-C4UJA2ju.js} +1 -1
- package/src/assets/web-panel/assets/{index-Td8ZwyoC.js → index-CB_Iw73G.js} +1 -1
- package/src/assets/web-panel/assets/{index-BZ5lY2zx.js → index-CCwWp3mT.js} +1 -1
- package/src/assets/web-panel/assets/{index-DpqtbXdE.js → index-CFa2fPCk.js} +1 -1
- package/src/assets/web-panel/assets/{index-NJieh3T1.js → index-CIyHxV4u.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dbkghqn_.js → index-CUP-A2_h.js} +1 -1
- package/src/assets/web-panel/assets/{index-DqwPFbOb.js → index-CUo27q9J.js} +3 -3
- package/src/assets/web-panel/assets/{index-B4QYBliR.js → index-CaT8trvf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BgfImyZI.js → index-CnZNbcux.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dbd7eEex.js → index-Cy2NE6AO.js} +1 -1
- package/src/assets/web-panel/assets/{index-CbTPvp2_.js → index-CzeEEazr.js} +1 -1
- package/src/assets/web-panel/assets/{index-5pW4t1iD.js → index-D--TEyDj.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dg2a9owQ.js → index-DCtsjhhT.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_eCoZgW.js → index-DLOf7BSz.js} +1 -1
- package/src/assets/web-panel/assets/{index-7P1b8HZo.js → index-DM5c4pc-.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRPrHE7h.js → index-DRFC2Qt0.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bq5P3piS.js → index-DT_qVaaV.js} +1 -1
- package/src/assets/web-panel/assets/{index-CjWltbi_.js → index-DUDoRk9r.js} +1 -1
- package/src/assets/web-panel/assets/{index-CkMKuqUs.js → index-Dg-AQYDf.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLoalqRX.js → index-DuIPq5MX.js} +1 -1
- package/src/assets/web-panel/assets/{index-CGlotREA.js → index-NYVBUAVN.js} +1 -1
- package/src/assets/web-panel/assets/{index-yYEQXYaU.js → index-NaCESahy.js} +1 -1
- package/src/assets/web-panel/assets/{index-CmruhzFi.js → index-RjIMPG0u.js} +1 -1
- package/src/assets/web-panel/assets/{index-fgYk0QXO.js → index-Y9akzgFO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DvV03Ayk.js → index-hZ0Eyrrw.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CPrcB1TC.js → initDefaultProps-CG99CcR4.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BQ7mWRh_.js → motion-Z7MH0_0G.js} +1 -1
- package/src/assets/web-panel/assets/{move-CzOEq99p.js → move-BX67lOdq.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-BlQI5jrw.js → mtc-parser-CmAbG1fE.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DlW4gxmv.js → omit-DiU5tI1_.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BBYms5nP.js → pickAttrs-BGfvLrYL.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-az2MPJ_7.js → placementArrow-CggLEgaJ.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-D1-ibEol.js → responsiveObserve-t3nlghPZ.js} +1 -1
- package/src/assets/web-panel/assets/{slide-DHGqa4GA.js → slide-BkV4dL9s.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CYGDo6lD.js → statusUtils-qec1PUoC.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-Cl2EM9K6.js → styleChecker-ChjX6T8D.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-DdYhzuv1.js → useFlexGapSupport-B1jLoZcM.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-DWumPuBW.js → useFs-C3X53s4E.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DxAO-Aqi.js → usePersonalDataHub-DOvbbnkZ.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-CplsQf_N.js → vnode-Ie0TEVFT.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-Cw5HXNSG.js → zoom-CRUMVS8l.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 +18 -1
- package/src/commands/evolution-benchmark.js +72 -0
- package/src/commands/evolution.js +2 -0
- package/src/commands/governed-skill-marketplace.js +142 -0
- package/src/commands/marketplace.js +4 -1
- package/src/commands/serve.js +41 -0
- package/src/commands/skill.js +3 -0
- package/src/data/changelog.json +39 -0
- package/src/gateways/ws/ws-agent-handler.js +59 -2
- package/src/gateways/ws/ws-server.js +2 -0
- package/src/harness/golden-transcript.js +1 -0
- package/src/harness/prompt-compressor.js +51 -5
- package/src/harness/provider-backed-compaction.js +28 -1
- package/src/harness/remote-session-registry.js +15 -3
- package/src/index.js +30 -4
- package/src/lazy-dispatch.js +15 -1
- package/src/lib/advisor-runtime.js +55 -2
- package/src/lib/app-server/cli-agent-kernel-adapter.js +4 -0
- package/src/lib/app-server/graph-runtime.js +32 -0
- package/src/lib/app-server/server.js +45 -1
- package/src/lib/app-server/websocket-transport.js +23 -0
- package/src/lib/autonomous-agent.js +63 -13
- package/src/lib/cowork/ab-comparator-cli.js +4 -3
- package/src/lib/cowork/debate-review-cli.js +4 -3
- package/src/lib/cowork/decision-kb-cli.js +5 -0
- package/src/lib/cowork-adapter.js +38 -16
- package/src/lib/evolution/agent-evolution-ingress.js +95 -15
- package/src/lib/evolution/agent-evolution-runtime-composition.js +82 -0
- package/src/lib/evolution/agent-evolution-session-lifecycle.js +46 -0
- package/src/lib/evolution/agent-model-projection.js +217 -0
- package/src/lib/evolution/bounded-descriptor-read.js +29 -0
- package/src/lib/evolution/controlled-skill-pilot-ledger-adapter.js +551 -0
- package/src/lib/evolution/controlled-skill-production-pilot.js +308 -18
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +10 -1
- package/src/lib/evolution/evidence-json-text.js +236 -0
- package/src/lib/evolution/evolution-artifact-ports.js +202 -21
- package/src/lib/evolution/evolution-deployment-loader.js +369 -0
- package/src/lib/evolution/evolution-eval-child-evidence-ledger-adapter.js +373 -0
- package/src/lib/evolution/evolution-eval-gate.js +14 -1
- package/src/lib/evolution/evolution-eval-process-supervisor-worker.mjs +14 -0
- package/src/lib/evolution/evolution-eval-process-supervisor.js +607 -0
- package/src/lib/evolution/evolution-evidence-artifact-adapter.js +14 -1
- package/src/lib/evolution/evolution-evidence-projector.js +240 -37
- package/src/lib/evolution/evolution-file-witness.js +153 -30
- package/src/lib/evolution/evolution-ledger-ports.js +1027 -66
- package/src/lib/evolution/evolution-ledger.js +66 -2
- package/src/lib/evolution/evolution-raw-crypto-shred.js +29 -15
- package/src/lib/evolution/evolution-raw-deletion-ledger-adapter.js +865 -0
- package/src/lib/evolution/evolution-release-train-domain-stages.js +769 -0
- package/src/lib/evolution/evolution-release-train-ledger-adapter.js +335 -0
- package/src/lib/evolution/evolution-release-train-stage-output-ledger-adapter.js +333 -0
- package/src/lib/evolution/evolution-release-train.js +586 -0
- package/src/lib/evolution/evolution-workbench-batch-executor.js +101 -144
- package/src/lib/evolution/evolution-workbench-control-ports.js +203 -0
- package/src/lib/evolution/evolution-workbench-file-resources.js +403 -0
- package/src/lib/evolution/evolution-workbench-projection.js +152 -25
- package/src/lib/evolution/evolution-workbench-registry-source.js +482 -0
- package/src/lib/evolution/evolution-workbench-review-ledger-adapter.js +823 -0
- package/src/lib/evolution/evolution-workbench-review-protocol.js +157 -0
- package/src/lib/evolution/evolution-workbench-rollback-authorization.js +57 -0
- package/src/lib/evolution/evolution-workbench-rollback-ledger-adapter.js +1016 -0
- package/src/lib/evolution/evolution-workbench-runtime.js +133 -0
- package/src/lib/evolution/evolution-workbench-version-control.js +70 -36
- package/src/lib/evolution/evolvable-artifact-ledger-adapter.js +736 -0
- package/src/lib/evolution/governed-knowledge-artifact-lifecycle.js +364 -0
- package/src/lib/evolution/governed-knowledge-candidate-rejection.js +343 -0
- package/src/lib/evolution/governed-knowledge-dependency-authority.js +227 -44
- package/src/lib/evolution/governed-knowledge-dependency-ledger-executor.js +95 -83
- package/src/lib/evolution/governed-knowledge-merge-ledger-executor.js +29 -2
- package/src/lib/evolution/governed-knowledge-merge-publisher-authority.js +31 -3
- package/src/lib/evolution/governed-knowledge-record.js +148 -0
- package/src/lib/evolution/governed-knowledge-revocation-record.js +135 -0
- package/src/lib/evolution/governed-knowledge-skill-rollback.js +475 -0
- package/src/lib/evolution/governed-knowledge-sync-ledger-adapter.js +92 -6
- package/src/lib/evolution/governed-knowledge-sync-merge-publisher.js +57 -4
- package/src/lib/evolution/governed-knowledge-sync.js +332 -99
- package/src/lib/evolution/governed-knowledge-wiki-tombstone.js +462 -0
- package/src/lib/evolution/governed-skill-marketplace-badge.js +208 -0
- package/src/lib/evolution/governed-skill-marketplace-candidate.js +330 -0
- package/src/lib/evolution/governed-skill-marketplace-cli-host.js +308 -0
- package/src/lib/evolution/governed-skill-marketplace-ledger-adapter.js +420 -0
- package/src/lib/evolution/governed-skill-marketplace.js +288 -5
- package/src/lib/evolution/governed-wiki-pruning-journal.js +302 -0
- package/src/lib/evolution/governed-wiki-pruning-ledger-adapter.js +459 -0
- package/src/lib/evolution/governed-wiki-pruning-maintenance.js +576 -0
- package/src/lib/evolution/governed-wiki-pruning-plan-authority.js +169 -0
- package/src/lib/evolution/governed-wiki-pruning-raw-shred.js +207 -0
- package/src/lib/evolution/governed-wiki-pruning-retrieval.js +587 -0
- package/src/lib/evolution/governed-wiki-pruning-runtime.js +153 -0
- package/src/lib/evolution/governed-wiki-pruning-skill-rollback.js +360 -0
- package/src/lib/evolution/governed-wiki-pruning.js +322 -143
- package/src/lib/evolution/independent-skill-revocation-source.js +231 -0
- package/src/lib/evolution/knowledge-wiki-source-admission.js +124 -0
- package/src/lib/evolution/knowledge-wiki-source-provenance.js +359 -0
- package/src/lib/evolution/progressive-canary-external-watchdog.js +578 -0
- package/src/lib/evolution/progressive-canary-traffic-worker.js +628 -0
- package/src/lib/evolution/progressive-canary-watchdog-file-store.js +285 -0
- package/src/lib/evolution/progressive-canary-watchdog-node-pki.js +265 -0
- package/src/lib/evolution/skill-candidate-registry.js +22 -0
- package/src/lib/evolution/skill-promotion-controller.js +25 -0
- package/src/lib/evolution/skill-promotion-review-ledger-adapter.js +100 -0
- package/src/lib/evolution/skill-registry-transition-ledger-adapter.js +131 -2
- package/src/lib/evolution/skill-release-registry.js +25 -4
- package/src/lib/evolution/skill-retrieval-revocation-authority.js +361 -0
- package/src/lib/evolution/skill-retrieval-revocation-ledger-adapter.js +346 -0
- package/src/lib/evolution/skill-revocation-propagation.js +467 -0
- package/src/lib/evolution/skill-target-matrix-eval.js +162 -11
- package/src/lib/evolution/skill-wiki-reconciliation.js +985 -0
- package/src/lib/evolution/skill-writer-inventory-manifest.js +15 -12
- package/src/lib/evolution/statistical-progressive-canary.js +845 -0
- package/src/lib/evolution/structured-memory-agent-control-plane.js +120 -0
- package/src/lib/evolution/structured-memory-authority-ledger-adapter.js +5 -1
- package/src/lib/evolution/structured-memory-promotion-receipt-writer.js +126 -0
- package/src/lib/evolution/wiki-informed-skill-proposer.js +127 -21
- package/src/lib/evolution/wiki-maintainer-ledger-adapter.js +760 -100
- package/src/lib/evolution/wiki-revision-protocol.js +120 -0
- package/src/lib/evolution/wiki-skill-proposal-ledger-adapter.js +307 -0
- package/src/lib/evolution/wiki-target-tombstone-revision.js +101 -0
- package/src/lib/evolution/wikiskill-benchmark-cli-host.js +178 -0
- package/src/lib/evolution/wikiskill-benchmark-execution-host.js +702 -0
- package/src/lib/evolution/wikiskill-benchmark-ledger-adapter.js +613 -0
- package/src/lib/evolution/wikiskill-benchmark.js +574 -0
- package/src/lib/goal-assess.js +17 -10
- package/src/lib/interactive-planner.js +9 -1
- package/src/lib/iteration-budget.js +16 -2
- package/src/lib/micro-compact.js +4 -1
- package/src/lib/model-failure-policy.js +21 -0
- package/src/lib/process-execution-broker/index.js +1 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.dll +0 -0
- package/src/lib/process-execution-broker/windows-sandbox-helper.exe +0 -0
- package/src/lib/process-execution-broker/windows-sandbox.cs +33 -15
- package/src/lib/read-file-page.js +191 -0
- package/src/lib/runnable-provider.js +2 -1
- package/src/lib/session-host-lease.js +11 -16
- package/src/lib/skill-retrieval-router.js +22 -1
- package/src/repl/agent-repl.js +127 -33
- package/src/runtime/agent-core.js +224 -80
- package/src/runtime/agent-runtime.js +43 -0
- package/src/runtime/coding-agent-contract-shared.cjs +7 -1
- package/src/runtime/fallback-model.js +143 -62
- package/src/runtime/headless-runner.js +54 -10
- package/src/runtime/headless-stream.js +53 -6
- package/src/runtime/runtime-factory.js +41 -2
- package/src/assets/web-panel/assets/Notes-CgU9DDo9.js +0 -7
- package/src/assets/web-panel/assets/OrderTableRenderer-CwHc15Zs.js +0 -1
- package/src/assets/web-panel/assets/Projects-FF_thRi6.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-l7ox6KuX.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DyhgpXPf.js +0 -1
- package/src/assets/web-panel/assets/index-Ck1jhFE0.js +0 -1
- package/src/assets/web-panel/assets/index-c8jJEHVs.js +0 -1
|
@@ -0,0 +1,865 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { types as utilTypes } from "node:util";
|
|
3
|
+
|
|
4
|
+
import {
|
|
5
|
+
EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA,
|
|
6
|
+
isEvolutionLedgerArtifactResolver,
|
|
7
|
+
} from "./evolution-artifact-ports.js";
|
|
8
|
+
import {
|
|
9
|
+
EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA,
|
|
10
|
+
EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA,
|
|
11
|
+
EVOLUTION_LEDGER_MAX_EVENTS,
|
|
12
|
+
} from "./evolution-ledger.js";
|
|
13
|
+
import { capturePruningData } from "./governed-wiki-pruning-journal.js";
|
|
14
|
+
import { EVOLUTION_RAW_DELETION_TOMBSTONE_SCHEMA } from "./evolution-raw-crypto-shred.js";
|
|
15
|
+
|
|
16
|
+
export const EVOLUTION_RAW_DELETION_RECEIPT_SCHEMA =
|
|
17
|
+
"chainlesschain.evolution-raw-deletion-receipt/v1";
|
|
18
|
+
export const EVOLUTION_RAW_DELETION_LEDGER_RECORD_SCHEMA =
|
|
19
|
+
"chainlesschain.evolution-raw-deletion-ledger-record/v1";
|
|
20
|
+
export const EVOLUTION_RAW_DELETION_RESOLUTION_SCHEMA =
|
|
21
|
+
"chainlesschain.evolution-raw-deletion-resolution/v1";
|
|
22
|
+
export const EVOLUTION_RAW_TOMBSTONE_RESOLUTION_SCHEMA =
|
|
23
|
+
"chainlesschain.evolution-raw-tombstone-resolution/v1";
|
|
24
|
+
export const EVOLUTION_RAW_DELETION_RECEIPT_EVENT_TYPE =
|
|
25
|
+
"evolution.raw-deletion.receipt-retained";
|
|
26
|
+
export const EVOLUTION_RAW_DELETION_TOMBSTONE_EVENT_TYPE =
|
|
27
|
+
"evolution.raw-deletion.tombstone-retained";
|
|
28
|
+
export const EVOLUTION_RAW_DELETION_LEDGER_CORRUPT_CODE =
|
|
29
|
+
"CC_EVOLUTION_RAW_DELETION_LEDGER_CORRUPT";
|
|
30
|
+
|
|
31
|
+
const RECEIPT_ARTIFACT_TYPE = "evolution-raw-deletion-receipt";
|
|
32
|
+
const TOMBSTONE_ARTIFACT_TYPE = "evolution-raw-deletion-tombstone";
|
|
33
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
34
|
+
const READERS = new WeakMap();
|
|
35
|
+
const HEAD_KEYS = [
|
|
36
|
+
"epoch",
|
|
37
|
+
"ledgerId",
|
|
38
|
+
"identityDigest",
|
|
39
|
+
"sequence",
|
|
40
|
+
"headDigest",
|
|
41
|
+
];
|
|
42
|
+
|
|
43
|
+
export function captureRawDeletionLedgerReader(value, tenantId, streamId) {
|
|
44
|
+
const reader = READERS.get(value);
|
|
45
|
+
if (
|
|
46
|
+
!reader ||
|
|
47
|
+
Object.getPrototypeOf(value) !==
|
|
48
|
+
EvolutionRawDeletionLedgerAdapter.prototype ||
|
|
49
|
+
value.descriptor.tenantId !== tenantId ||
|
|
50
|
+
value.descriptor.streamId !== streamId
|
|
51
|
+
)
|
|
52
|
+
throw new TypeError("a same-scope branded Raw deletion ledger is required");
|
|
53
|
+
return reader;
|
|
54
|
+
}
|
|
55
|
+
const RECEIPT_KEYS = new Set([
|
|
56
|
+
"schema",
|
|
57
|
+
"tenantId",
|
|
58
|
+
"decision",
|
|
59
|
+
"evidenceRef",
|
|
60
|
+
"sourceDigest",
|
|
61
|
+
"artifactRef",
|
|
62
|
+
"rawArtifactRef",
|
|
63
|
+
"rawCipherDigest",
|
|
64
|
+
"keyRef",
|
|
65
|
+
"issuedAt",
|
|
66
|
+
"attestation",
|
|
67
|
+
"receiptDigest",
|
|
68
|
+
]);
|
|
69
|
+
const ATTESTATION_KEYS = new Set([
|
|
70
|
+
"algorithm",
|
|
71
|
+
"issuer",
|
|
72
|
+
"keyId",
|
|
73
|
+
"trustPolicyDigest",
|
|
74
|
+
"value",
|
|
75
|
+
]);
|
|
76
|
+
const TOMBSTONE_KEYS = new Set([
|
|
77
|
+
"schema",
|
|
78
|
+
"tenantId",
|
|
79
|
+
"pruningRequestDigest",
|
|
80
|
+
"destructionRequestDigest",
|
|
81
|
+
"destructionReceiptDigest",
|
|
82
|
+
"confirmationReceiptDigest",
|
|
83
|
+
"evidenceRef",
|
|
84
|
+
"rawArtifactRef",
|
|
85
|
+
"rawCipherDigest",
|
|
86
|
+
"deletionReceiptDigest",
|
|
87
|
+
"tombstoneDigest",
|
|
88
|
+
]);
|
|
89
|
+
const RECORD_KEYS = new Set([
|
|
90
|
+
"schema",
|
|
91
|
+
"tenantId",
|
|
92
|
+
"streamId",
|
|
93
|
+
"kind",
|
|
94
|
+
"logicalDigest",
|
|
95
|
+
"value",
|
|
96
|
+
]);
|
|
97
|
+
|
|
98
|
+
function canonical(value) {
|
|
99
|
+
if (value === null || typeof value !== "object") return JSON.stringify(value);
|
|
100
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
101
|
+
return `{${Object.keys(value)
|
|
102
|
+
.sort()
|
|
103
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
104
|
+
.join(",")}}`;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function hash(domain, value) {
|
|
108
|
+
return `sha256:${createHash("sha256")
|
|
109
|
+
.update(domain)
|
|
110
|
+
.update("\0")
|
|
111
|
+
.update(canonical(value))
|
|
112
|
+
.digest("hex")}`;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function freeze(value, seen = new WeakSet()) {
|
|
116
|
+
if (!value || typeof value !== "object" || seen.has(value)) return value;
|
|
117
|
+
seen.add(value);
|
|
118
|
+
for (const child of Object.values(value)) freeze(child, seen);
|
|
119
|
+
return Object.freeze(value);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
function corrupt(message, options) {
|
|
123
|
+
const error = new Error(message, options);
|
|
124
|
+
error.code = EVOLUTION_RAW_DELETION_LEDGER_CORRUPT_CODE;
|
|
125
|
+
throw error;
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
function exact(value, keys, label) {
|
|
129
|
+
if (
|
|
130
|
+
!value ||
|
|
131
|
+
typeof value !== "object" ||
|
|
132
|
+
Array.isArray(value) ||
|
|
133
|
+
utilTypes.isProxy(value) ||
|
|
134
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value))
|
|
135
|
+
) {
|
|
136
|
+
throw new TypeError(`${label} must be a plain record`);
|
|
137
|
+
}
|
|
138
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
139
|
+
if (
|
|
140
|
+
ownKeys.length !== keys.size ||
|
|
141
|
+
ownKeys.some((key) => typeof key !== "string" || !keys.has(key))
|
|
142
|
+
) {
|
|
143
|
+
throw new TypeError(`${label} must contain exactly the supported fields`);
|
|
144
|
+
}
|
|
145
|
+
for (const key of ownKeys) {
|
|
146
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
147
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
148
|
+
throw new TypeError(`${label}.${String(key)} is unsafe`);
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
function string(value, label, maximum = 1024) {
|
|
154
|
+
if (
|
|
155
|
+
typeof value !== "string" ||
|
|
156
|
+
value === "" ||
|
|
157
|
+
value.trim() !== value ||
|
|
158
|
+
Buffer.byteLength(value, "utf8") > maximum
|
|
159
|
+
) {
|
|
160
|
+
throw new TypeError(`${label} is invalid`);
|
|
161
|
+
}
|
|
162
|
+
return value;
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function digest(value, label) {
|
|
166
|
+
if (!DIGEST.test(value ?? "")) throw new TypeError(`${label} is invalid`);
|
|
167
|
+
return value;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
function timestamp(value, label) {
|
|
171
|
+
if (typeof value !== "string" || new Date(value).toISOString() !== value) {
|
|
172
|
+
throw new TypeError(`${label} is invalid`);
|
|
173
|
+
}
|
|
174
|
+
return value;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function capture(owner, method, label = method) {
|
|
178
|
+
if (typeof owner?.[method] !== "function") {
|
|
179
|
+
throw new TypeError(`${label} port is required`);
|
|
180
|
+
}
|
|
181
|
+
const captured = owner[method];
|
|
182
|
+
return (...args) => Reflect.apply(captured, owner, args);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function normalizeDescriptor(input) {
|
|
186
|
+
if (!Number.isSafeInteger(input?.revision) || input.revision < 1) {
|
|
187
|
+
throw new TypeError("revision must be a positive integer");
|
|
188
|
+
}
|
|
189
|
+
return Object.freeze({
|
|
190
|
+
tenantId: string(input.tenantId, "tenantId"),
|
|
191
|
+
artifactTenantId: string(input.artifactTenantId, "artifactTenantId"),
|
|
192
|
+
streamId: string(input.streamId, "streamId"),
|
|
193
|
+
audience: string(input.audience, "audience"),
|
|
194
|
+
purpose: string(input.purpose, "purpose"),
|
|
195
|
+
authorityId: string(input.authorityId, "authorityId"),
|
|
196
|
+
revision: input.revision,
|
|
197
|
+
handlerArtifactDigest: digest(
|
|
198
|
+
input.handlerArtifactDigest,
|
|
199
|
+
"handlerArtifactDigest",
|
|
200
|
+
),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
function normalizeAttestation(value) {
|
|
205
|
+
exact(value, ATTESTATION_KEYS, "raw deletion attestation");
|
|
206
|
+
return Object.freeze({
|
|
207
|
+
algorithm: string(value.algorithm, "attestation.algorithm", 64),
|
|
208
|
+
issuer: string(value.issuer, "attestation.issuer", 256),
|
|
209
|
+
keyId: string(value.keyId, "attestation.keyId", 512),
|
|
210
|
+
trustPolicyDigest: digest(
|
|
211
|
+
value.trustPolicyDigest,
|
|
212
|
+
"attestation.trustPolicyDigest",
|
|
213
|
+
),
|
|
214
|
+
value: string(value.value, "attestation.value", 4096),
|
|
215
|
+
});
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
export function digestEvolutionRawDeletionReceipt(input) {
|
|
219
|
+
const core = structuredClone(input);
|
|
220
|
+
delete core.receiptDigest;
|
|
221
|
+
return hash(EVOLUTION_RAW_DELETION_RECEIPT_SCHEMA, core);
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
function normalizeDeletionReceipt(input, tenantId) {
|
|
225
|
+
exact(input, RECEIPT_KEYS, "raw deletion receipt");
|
|
226
|
+
const receipt = {
|
|
227
|
+
schema: input.schema,
|
|
228
|
+
tenantId: string(input.tenantId, "deletion receipt tenantId"),
|
|
229
|
+
decision: input.decision,
|
|
230
|
+
evidenceRef: string(input.evidenceRef, "deletion receipt evidenceRef"),
|
|
231
|
+
sourceDigest: digest(input.sourceDigest, "deletion receipt sourceDigest"),
|
|
232
|
+
artifactRef: string(input.artifactRef, "deletion receipt artifactRef"),
|
|
233
|
+
rawArtifactRef: string(
|
|
234
|
+
input.rawArtifactRef,
|
|
235
|
+
"deletion receipt rawArtifactRef",
|
|
236
|
+
),
|
|
237
|
+
rawCipherDigest: digest(
|
|
238
|
+
input.rawCipherDigest,
|
|
239
|
+
"deletion receipt rawCipherDigest",
|
|
240
|
+
),
|
|
241
|
+
keyRef: string(input.keyRef, "deletion receipt keyRef"),
|
|
242
|
+
issuedAt: timestamp(input.issuedAt, "deletion receipt issuedAt"),
|
|
243
|
+
attestation: normalizeAttestation(input.attestation),
|
|
244
|
+
receiptDigest: digest(
|
|
245
|
+
input.receiptDigest,
|
|
246
|
+
"deletion receipt receiptDigest",
|
|
247
|
+
),
|
|
248
|
+
};
|
|
249
|
+
if (
|
|
250
|
+
receipt.schema !== EVOLUTION_RAW_DELETION_RECEIPT_SCHEMA ||
|
|
251
|
+
receipt.tenantId !== tenantId ||
|
|
252
|
+
receipt.decision !== "delete" ||
|
|
253
|
+
!receipt.rawArtifactRef.startsWith(`artifact://${tenantId}/raw/`) ||
|
|
254
|
+
!receipt.keyRef.startsWith(`kms://${tenantId}/`) ||
|
|
255
|
+
receipt.receiptDigest !== digestEvolutionRawDeletionReceipt(receipt)
|
|
256
|
+
) {
|
|
257
|
+
throw new TypeError("raw deletion receipt binding is invalid");
|
|
258
|
+
}
|
|
259
|
+
return freeze(receipt);
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
function normalizeTombstone(input, tenantId) {
|
|
263
|
+
exact(input, TOMBSTONE_KEYS, "raw deletion tombstone");
|
|
264
|
+
const tombstone = {
|
|
265
|
+
schema: input.schema,
|
|
266
|
+
tenantId: string(input.tenantId, "tombstone tenantId"),
|
|
267
|
+
pruningRequestDigest: digest(
|
|
268
|
+
input.pruningRequestDigest,
|
|
269
|
+
"tombstone pruningRequestDigest",
|
|
270
|
+
),
|
|
271
|
+
destructionRequestDigest: digest(
|
|
272
|
+
input.destructionRequestDigest,
|
|
273
|
+
"tombstone destructionRequestDigest",
|
|
274
|
+
),
|
|
275
|
+
destructionReceiptDigest: digest(
|
|
276
|
+
input.destructionReceiptDigest,
|
|
277
|
+
"tombstone destructionReceiptDigest",
|
|
278
|
+
),
|
|
279
|
+
confirmationReceiptDigest: digest(
|
|
280
|
+
input.confirmationReceiptDigest,
|
|
281
|
+
"tombstone confirmationReceiptDigest",
|
|
282
|
+
),
|
|
283
|
+
evidenceRef: string(input.evidenceRef, "tombstone evidenceRef"),
|
|
284
|
+
rawArtifactRef: string(input.rawArtifactRef, "tombstone rawArtifactRef"),
|
|
285
|
+
rawCipherDigest: digest(input.rawCipherDigest, "tombstone rawCipherDigest"),
|
|
286
|
+
deletionReceiptDigest: digest(
|
|
287
|
+
input.deletionReceiptDigest,
|
|
288
|
+
"tombstone deletionReceiptDigest",
|
|
289
|
+
),
|
|
290
|
+
tombstoneDigest: digest(input.tombstoneDigest, "tombstone tombstoneDigest"),
|
|
291
|
+
};
|
|
292
|
+
const core = { ...tombstone };
|
|
293
|
+
delete core.tombstoneDigest;
|
|
294
|
+
if (
|
|
295
|
+
tombstone.schema !== EVOLUTION_RAW_DELETION_TOMBSTONE_SCHEMA ||
|
|
296
|
+
tombstone.tenantId !== tenantId ||
|
|
297
|
+
!tombstone.rawArtifactRef.startsWith(`artifact://${tenantId}/raw/`) ||
|
|
298
|
+
tombstone.tombstoneDigest !==
|
|
299
|
+
hash(EVOLUTION_RAW_DELETION_TOMBSTONE_SCHEMA, core)
|
|
300
|
+
) {
|
|
301
|
+
throw new TypeError("raw deletion tombstone binding is invalid");
|
|
302
|
+
}
|
|
303
|
+
return freeze(tombstone);
|
|
304
|
+
}
|
|
305
|
+
|
|
306
|
+
function parseRecord(resolution, descriptor, expected) {
|
|
307
|
+
if (
|
|
308
|
+
resolution?.schema !== EVOLUTION_ARTIFACT_RESOLUTION_SCHEMA ||
|
|
309
|
+
resolution.authenticated !== true ||
|
|
310
|
+
resolution.found !== true ||
|
|
311
|
+
!DIGEST.test(resolution.digest ?? "") ||
|
|
312
|
+
!DIGEST.test(resolution.receiptDigest ?? "") ||
|
|
313
|
+
!Buffer.isBuffer(resolution.bytes)
|
|
314
|
+
) {
|
|
315
|
+
corrupt("raw deletion artifact resolution is incomplete");
|
|
316
|
+
}
|
|
317
|
+
let record;
|
|
318
|
+
try {
|
|
319
|
+
record = JSON.parse(resolution.bytes.toString("utf8"));
|
|
320
|
+
} catch {
|
|
321
|
+
corrupt("raw deletion artifact is not JSON");
|
|
322
|
+
}
|
|
323
|
+
if (
|
|
324
|
+
record?.schema !== EVOLUTION_DURABLE_ARTIFACT_RECORD_SCHEMA ||
|
|
325
|
+
record.tenantId !== descriptor.artifactTenantId ||
|
|
326
|
+
record.audience !== descriptor.audience ||
|
|
327
|
+
record.purpose !== descriptor.purpose ||
|
|
328
|
+
record.retention !== "ledger" ||
|
|
329
|
+
record.type !== expected.artifactType
|
|
330
|
+
) {
|
|
331
|
+
corrupt("raw deletion durable artifact binding is invalid");
|
|
332
|
+
}
|
|
333
|
+
const value = record.value;
|
|
334
|
+
try {
|
|
335
|
+
exact(value, RECORD_KEYS, "raw deletion ledger record");
|
|
336
|
+
} catch (cause) {
|
|
337
|
+
corrupt("raw deletion ledger record is invalid", { cause });
|
|
338
|
+
}
|
|
339
|
+
if (
|
|
340
|
+
value.schema !== EVOLUTION_RAW_DELETION_LEDGER_RECORD_SCHEMA ||
|
|
341
|
+
value.tenantId !== descriptor.tenantId ||
|
|
342
|
+
value.streamId !== descriptor.streamId ||
|
|
343
|
+
value.kind !== expected.kind ||
|
|
344
|
+
!DIGEST.test(value.logicalDigest ?? "")
|
|
345
|
+
) {
|
|
346
|
+
corrupt("raw deletion ledger record scope is invalid");
|
|
347
|
+
}
|
|
348
|
+
return value;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
export class EvolutionRawDeletionLedgerAdapter {
|
|
352
|
+
constructor({
|
|
353
|
+
descriptor: input,
|
|
354
|
+
artifactPorts,
|
|
355
|
+
ledger,
|
|
356
|
+
ledgerArtifactResolver,
|
|
357
|
+
deletionReceiptVerifier,
|
|
358
|
+
now = Date.now,
|
|
359
|
+
} = {}) {
|
|
360
|
+
this.descriptor = normalizeDescriptor(input);
|
|
361
|
+
this._put = capture(artifactPorts, "putCanonical");
|
|
362
|
+
this._read = capture(ledger, "read");
|
|
363
|
+
this._verifyLedger = capture(ledger, "verify");
|
|
364
|
+
this._append = capture(ledger, "appendDomainEvent");
|
|
365
|
+
this._verifyDeletionReceipt = capture(
|
|
366
|
+
deletionReceiptVerifier,
|
|
367
|
+
"verify",
|
|
368
|
+
"deletionReceiptVerifier.verify",
|
|
369
|
+
);
|
|
370
|
+
if (!isEvolutionLedgerArtifactResolver(ledgerArtifactResolver)) {
|
|
371
|
+
throw new TypeError(
|
|
372
|
+
"a branded EvolutionArtifactPorts ledger resolver is required",
|
|
373
|
+
);
|
|
374
|
+
}
|
|
375
|
+
if (typeof now !== "function")
|
|
376
|
+
throw new TypeError("now must be a function");
|
|
377
|
+
this._resolveArtifact = ledgerArtifactResolver;
|
|
378
|
+
this._now = now;
|
|
379
|
+
READERS.set(
|
|
380
|
+
this,
|
|
381
|
+
Object.freeze({
|
|
382
|
+
descriptor: this.descriptor,
|
|
383
|
+
head: () => this._verifyLedger(),
|
|
384
|
+
resolveDeletionReceipt: (input) => this.resolveDeletionReceipt(input),
|
|
385
|
+
resolveTombstone: (input) => this._resolvePruningTombstone(input),
|
|
386
|
+
cryptoShredPorts: (ports) => this.cryptoShredPorts(ports),
|
|
387
|
+
}),
|
|
388
|
+
);
|
|
389
|
+
Object.freeze(this);
|
|
390
|
+
}
|
|
391
|
+
|
|
392
|
+
async _resolvePruningTombstone(value) {
|
|
393
|
+
const input = capturePruningData(value);
|
|
394
|
+
exact(
|
|
395
|
+
input,
|
|
396
|
+
new Set(["tenantId", "tombstoneDigest", "context"]),
|
|
397
|
+
"pruning tombstone query",
|
|
398
|
+
);
|
|
399
|
+
exact(
|
|
400
|
+
input.context,
|
|
401
|
+
new Set(["mode", "checkpoint"]),
|
|
402
|
+
"pruning tombstone context",
|
|
403
|
+
);
|
|
404
|
+
const checkpoint = input.context.checkpoint;
|
|
405
|
+
exact(checkpoint, new Set(HEAD_KEYS), "pruning tombstone checkpoint");
|
|
406
|
+
const events = this._read({
|
|
407
|
+
afterSequence: 0,
|
|
408
|
+
limit: EVOLUTION_LEDGER_MAX_EVENTS,
|
|
409
|
+
});
|
|
410
|
+
const tail = events.at(-1);
|
|
411
|
+
// read() authenticates the complete chain. Resolve both immutable subjects
|
|
412
|
+
// from THIS snapshot, then verify the full current head again after the
|
|
413
|
+
// asynchronous privacy verifier. No authority result survives this call.
|
|
414
|
+
const head = tail
|
|
415
|
+
? { ...tail, headDigest: tail.eventDigest }
|
|
416
|
+
: this._verifyLedger();
|
|
417
|
+
if (
|
|
418
|
+
events.length !== head.sequence ||
|
|
419
|
+
events.some(
|
|
420
|
+
(event, index) =>
|
|
421
|
+
event.sequence !== index + 1 ||
|
|
422
|
+
["epoch", "ledgerId", "identityDigest"].some(
|
|
423
|
+
(key) => event[key] !== head[key],
|
|
424
|
+
),
|
|
425
|
+
)
|
|
426
|
+
)
|
|
427
|
+
corrupt("Raw deletion read is not the complete current ledger");
|
|
428
|
+
const at =
|
|
429
|
+
checkpoint.sequence === 0 ? null : events[checkpoint.sequence - 1];
|
|
430
|
+
if (
|
|
431
|
+
!["current", "checkpoint"].includes(input.context.mode) ||
|
|
432
|
+
!Number.isSafeInteger(checkpoint.sequence) ||
|
|
433
|
+
checkpoint.sequence < 0 ||
|
|
434
|
+
checkpoint.sequence > head.sequence ||
|
|
435
|
+
["epoch", "ledgerId", "identityDigest"].some(
|
|
436
|
+
(key) => checkpoint[key] !== head[key],
|
|
437
|
+
) ||
|
|
438
|
+
checkpoint.headDigest !== (at?.eventDigest ?? null) ||
|
|
439
|
+
(input.context.mode === "current" &&
|
|
440
|
+
HEAD_KEYS.some((key) => checkpoint[key] !== head[key]))
|
|
441
|
+
)
|
|
442
|
+
corrupt("Raw tombstone checkpoint is not authenticated by this ledger");
|
|
443
|
+
const event = this._event(
|
|
444
|
+
EVOLUTION_RAW_DELETION_TOMBSTONE_EVENT_TYPE,
|
|
445
|
+
input.tombstoneDigest,
|
|
446
|
+
events,
|
|
447
|
+
);
|
|
448
|
+
if (
|
|
449
|
+
!event ||
|
|
450
|
+
event.sequence > checkpoint.sequence ||
|
|
451
|
+
events[event.sequence - 1]?.eventDigest !== event.eventDigest
|
|
452
|
+
)
|
|
453
|
+
corrupt("Raw tombstone was not retained at this pruning checkpoint");
|
|
454
|
+
const resolved = this._resolvedTombstone(event, head);
|
|
455
|
+
const receiptEvent = this._event(
|
|
456
|
+
EVOLUTION_RAW_DELETION_RECEIPT_EVENT_TYPE,
|
|
457
|
+
resolved.tombstone.deletionReceiptDigest,
|
|
458
|
+
events,
|
|
459
|
+
);
|
|
460
|
+
if (
|
|
461
|
+
resolved.tombstone.tombstoneDigest !== input.tombstoneDigest ||
|
|
462
|
+
!receiptEvent ||
|
|
463
|
+
receiptEvent.sequence >= event.sequence ||
|
|
464
|
+
canonical(event.sourceRefs[0]) !== canonical(receiptEvent.subjectRef)
|
|
465
|
+
)
|
|
466
|
+
corrupt("Raw tombstone receipt lineage is invalid");
|
|
467
|
+
const { receipt } = await this._verifiedReceipt(
|
|
468
|
+
receiptEvent,
|
|
469
|
+
"resolve-tombstone",
|
|
470
|
+
head,
|
|
471
|
+
);
|
|
472
|
+
if (
|
|
473
|
+
receipt.receiptDigest !== resolved.tombstone.deletionReceiptDigest ||
|
|
474
|
+
receipt.evidenceRef !== resolved.tombstone.evidenceRef ||
|
|
475
|
+
receipt.rawArtifactRef !== resolved.tombstone.rawArtifactRef ||
|
|
476
|
+
receipt.rawCipherDigest !== resolved.tombstone.rawCipherDigest
|
|
477
|
+
)
|
|
478
|
+
corrupt("Raw tombstone target differs from its deletion receipt");
|
|
479
|
+
const fresh = this._verifyLedger();
|
|
480
|
+
if (HEAD_KEYS.some((key) => fresh[key] !== head[key]))
|
|
481
|
+
corrupt("Raw tombstone ledger changed during verification");
|
|
482
|
+
return freeze({
|
|
483
|
+
schema: EVOLUTION_RAW_TOMBSTONE_RESOLUTION_SCHEMA,
|
|
484
|
+
authenticated: true,
|
|
485
|
+
durable: true,
|
|
486
|
+
authorityId: this.descriptor.authorityId,
|
|
487
|
+
revision: this.descriptor.revision,
|
|
488
|
+
handlerArtifactDigest: this.descriptor.handlerArtifactDigest,
|
|
489
|
+
tenantId: this.descriptor.tenantId,
|
|
490
|
+
streamId: this.descriptor.streamId,
|
|
491
|
+
tombstoneDigest: input.tombstoneDigest,
|
|
492
|
+
tombstone: resolved.tombstone,
|
|
493
|
+
ledgerEventDigest: event.eventDigest,
|
|
494
|
+
ledgerHead: Object.fromEntries(HEAD_KEYS.map((key) => [key, head[key]])),
|
|
495
|
+
});
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
_events(type, snapshot = null) {
|
|
499
|
+
const events =
|
|
500
|
+
snapshot ??
|
|
501
|
+
this._read({
|
|
502
|
+
afterSequence: 0,
|
|
503
|
+
limit: EVOLUTION_LEDGER_MAX_EVENTS,
|
|
504
|
+
});
|
|
505
|
+
if (!Array.isArray(events)) {
|
|
506
|
+
corrupt("EvolutionLedger did not return an event array");
|
|
507
|
+
}
|
|
508
|
+
return events.filter(
|
|
509
|
+
(event) =>
|
|
510
|
+
event.schema === EVOLUTION_LEDGER_DOMAIN_EVENT_SCHEMA &&
|
|
511
|
+
event.type === type &&
|
|
512
|
+
event.tenantId === this.descriptor.tenantId &&
|
|
513
|
+
event.correlationId === this.descriptor.streamId,
|
|
514
|
+
);
|
|
515
|
+
}
|
|
516
|
+
|
|
517
|
+
_event(type, logicalDigest, snapshot = null) {
|
|
518
|
+
const eventId = `${type}.${logicalDigest.slice("sha256:".length)}`;
|
|
519
|
+
const matches = this._events(type, snapshot).filter(
|
|
520
|
+
(event) => event.eventId === eventId,
|
|
521
|
+
);
|
|
522
|
+
if (matches.length > 1) corrupt("raw deletion ledger event is ambiguous");
|
|
523
|
+
return matches[0] ?? null;
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
_resolveEvent(event, expected, snapshotHead = null) {
|
|
527
|
+
if (
|
|
528
|
+
event.artifactTenantId !== this.descriptor.artifactTenantId ||
|
|
529
|
+
event.decision !== expected.decision ||
|
|
530
|
+
event.skillName !== null ||
|
|
531
|
+
!Array.isArray(event.sourceRefs) ||
|
|
532
|
+
event.sourceRefs.length !== expected.sourceCount
|
|
533
|
+
) {
|
|
534
|
+
corrupt("raw deletion ledger event binding is invalid");
|
|
535
|
+
}
|
|
536
|
+
const identity = snapshotHead ?? this._verifyLedger();
|
|
537
|
+
const resolution = this._resolveArtifact({
|
|
538
|
+
epoch: identity.epoch,
|
|
539
|
+
ledgerId: identity.ledgerId,
|
|
540
|
+
ref: event.subjectRef,
|
|
541
|
+
tenantId: this.descriptor.artifactTenantId,
|
|
542
|
+
});
|
|
543
|
+
if (
|
|
544
|
+
resolution.ref !== event.subjectRef.ref ||
|
|
545
|
+
resolution.digest !== event.subjectRef.digest
|
|
546
|
+
) {
|
|
547
|
+
corrupt("raw deletion ledger subject was substituted");
|
|
548
|
+
}
|
|
549
|
+
return parseRecord(resolution, this.descriptor, expected);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
async _verifiedReceipt(event, source, snapshotHead = null) {
|
|
553
|
+
const record = this._resolveEvent(
|
|
554
|
+
event,
|
|
555
|
+
{
|
|
556
|
+
artifactType: RECEIPT_ARTIFACT_TYPE,
|
|
557
|
+
decision: "accepted",
|
|
558
|
+
kind: "deletion-receipt",
|
|
559
|
+
sourceCount: 0,
|
|
560
|
+
},
|
|
561
|
+
snapshotHead,
|
|
562
|
+
);
|
|
563
|
+
const receipt = normalizeDeletionReceipt(
|
|
564
|
+
record.value,
|
|
565
|
+
this.descriptor.tenantId,
|
|
566
|
+
);
|
|
567
|
+
if (
|
|
568
|
+
record.logicalDigest !== receipt.receiptDigest ||
|
|
569
|
+
(await this._verifyDeletionReceipt({
|
|
570
|
+
receipt,
|
|
571
|
+
tenantId: this.descriptor.tenantId,
|
|
572
|
+
streamId: this.descriptor.streamId,
|
|
573
|
+
source,
|
|
574
|
+
})) !== true
|
|
575
|
+
) {
|
|
576
|
+
corrupt("raw deletion receipt authentication failed");
|
|
577
|
+
}
|
|
578
|
+
return Object.freeze({ event, receipt });
|
|
579
|
+
}
|
|
580
|
+
|
|
581
|
+
_resolvedTombstone(event, snapshotHead = null) {
|
|
582
|
+
const record = this._resolveEvent(
|
|
583
|
+
event,
|
|
584
|
+
{
|
|
585
|
+
artifactType: TOMBSTONE_ARTIFACT_TYPE,
|
|
586
|
+
decision: "committed",
|
|
587
|
+
kind: "tombstone",
|
|
588
|
+
sourceCount: 1,
|
|
589
|
+
},
|
|
590
|
+
snapshotHead,
|
|
591
|
+
);
|
|
592
|
+
const tombstone = normalizeTombstone(
|
|
593
|
+
record.value,
|
|
594
|
+
this.descriptor.tenantId,
|
|
595
|
+
);
|
|
596
|
+
if (record.logicalDigest !== tombstone.tombstoneDigest) {
|
|
597
|
+
corrupt("raw deletion tombstone digest was substituted");
|
|
598
|
+
}
|
|
599
|
+
return Object.freeze({ event, tombstone });
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
_persist({
|
|
603
|
+
artifactType,
|
|
604
|
+
decision,
|
|
605
|
+
eventType,
|
|
606
|
+
kind,
|
|
607
|
+
logicalDigest,
|
|
608
|
+
reason,
|
|
609
|
+
sourceRefs,
|
|
610
|
+
timestamp: occurredAt,
|
|
611
|
+
value,
|
|
612
|
+
}) {
|
|
613
|
+
const head = this._verifyLedger();
|
|
614
|
+
const record = Object.freeze({
|
|
615
|
+
schema: EVOLUTION_RAW_DELETION_LEDGER_RECORD_SCHEMA,
|
|
616
|
+
tenantId: this.descriptor.tenantId,
|
|
617
|
+
streamId: this.descriptor.streamId,
|
|
618
|
+
kind,
|
|
619
|
+
logicalDigest,
|
|
620
|
+
value,
|
|
621
|
+
});
|
|
622
|
+
const published = this._put(artifactType, record, {
|
|
623
|
+
audience: this.descriptor.audience,
|
|
624
|
+
purpose: this.descriptor.purpose,
|
|
625
|
+
retention: "ledger",
|
|
626
|
+
});
|
|
627
|
+
if (
|
|
628
|
+
published?.receipt?.persisted !== true ||
|
|
629
|
+
published.receipt.readbackVerified !== true ||
|
|
630
|
+
published.receipt.integrityVerified !== true ||
|
|
631
|
+
published.receipt.retention !== "ledger"
|
|
632
|
+
) {
|
|
633
|
+
corrupt("raw deletion artifact persistence was not confirmed");
|
|
634
|
+
}
|
|
635
|
+
const eventId = `${eventType}.${logicalDigest.slice("sha256:".length)}`;
|
|
636
|
+
const ledgerReceipt = this._append(
|
|
637
|
+
{
|
|
638
|
+
artifactTenantId: this.descriptor.artifactTenantId,
|
|
639
|
+
correlationId: this.descriptor.streamId,
|
|
640
|
+
decision,
|
|
641
|
+
eventId,
|
|
642
|
+
reason,
|
|
643
|
+
skillName: null,
|
|
644
|
+
sourceRefs,
|
|
645
|
+
subjectRef: published.ref,
|
|
646
|
+
tenantId: this.descriptor.tenantId,
|
|
647
|
+
timestamp: occurredAt,
|
|
648
|
+
type: eventType,
|
|
649
|
+
},
|
|
650
|
+
{ expectedHeadDigest: head.headDigest, expectedSequence: head.sequence },
|
|
651
|
+
);
|
|
652
|
+
if (
|
|
653
|
+
ledgerReceipt?.authenticated !== true ||
|
|
654
|
+
ledgerReceipt.committed !== true ||
|
|
655
|
+
ledgerReceipt.durable !== true ||
|
|
656
|
+
ledgerReceipt.eventId !== eventId ||
|
|
657
|
+
!DIGEST.test(ledgerReceipt.eventDigest ?? "") ||
|
|
658
|
+
!DIGEST.test(ledgerReceipt.receiptDigest ?? "")
|
|
659
|
+
) {
|
|
660
|
+
corrupt("raw deletion ledger append was not durably confirmed");
|
|
661
|
+
}
|
|
662
|
+
return ledgerReceipt;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
async retainDeletionReceipt({ receipt: input } = {}) {
|
|
666
|
+
const receipt = normalizeDeletionReceipt(input, this.descriptor.tenantId);
|
|
667
|
+
if (
|
|
668
|
+
(await this._verifyDeletionReceipt({
|
|
669
|
+
receipt,
|
|
670
|
+
tenantId: this.descriptor.tenantId,
|
|
671
|
+
streamId: this.descriptor.streamId,
|
|
672
|
+
source: "retain",
|
|
673
|
+
})) !== true
|
|
674
|
+
) {
|
|
675
|
+
corrupt("raw deletion receipt signature verification failed");
|
|
676
|
+
}
|
|
677
|
+
const existing = this._event(
|
|
678
|
+
EVOLUTION_RAW_DELETION_RECEIPT_EVENT_TYPE,
|
|
679
|
+
receipt.receiptDigest,
|
|
680
|
+
);
|
|
681
|
+
if (existing) {
|
|
682
|
+
const recovered = await this._verifiedReceipt(existing, "recover");
|
|
683
|
+
if (canonical(recovered.receipt) !== canonical(receipt)) {
|
|
684
|
+
corrupt("raw deletion receipt id resolved substituted bytes");
|
|
685
|
+
}
|
|
686
|
+
return Object.freeze({
|
|
687
|
+
authenticated: true,
|
|
688
|
+
durable: true,
|
|
689
|
+
recovered: true,
|
|
690
|
+
receiptDigest: receipt.receiptDigest,
|
|
691
|
+
ledgerEventDigest: existing.eventDigest,
|
|
692
|
+
});
|
|
693
|
+
}
|
|
694
|
+
const persisted = this._persist({
|
|
695
|
+
artifactType: RECEIPT_ARTIFACT_TYPE,
|
|
696
|
+
decision: "accepted",
|
|
697
|
+
eventType: EVOLUTION_RAW_DELETION_RECEIPT_EVENT_TYPE,
|
|
698
|
+
kind: "deletion-receipt",
|
|
699
|
+
logicalDigest: receipt.receiptDigest,
|
|
700
|
+
reason: "authenticated privacy deletion receipt retained",
|
|
701
|
+
sourceRefs: [],
|
|
702
|
+
timestamp: receipt.issuedAt,
|
|
703
|
+
value: receipt,
|
|
704
|
+
});
|
|
705
|
+
return Object.freeze({
|
|
706
|
+
authenticated: true,
|
|
707
|
+
durable: true,
|
|
708
|
+
recovered: false,
|
|
709
|
+
receiptDigest: receipt.receiptDigest,
|
|
710
|
+
ledgerEventDigest: persisted.eventDigest,
|
|
711
|
+
ledgerReceiptDigest: persisted.receiptDigest,
|
|
712
|
+
});
|
|
713
|
+
}
|
|
714
|
+
|
|
715
|
+
async resolveDeletionReceipt({ tenantId, receiptDigest } = {}) {
|
|
716
|
+
if (tenantId !== this.descriptor.tenantId || !DIGEST.test(receiptDigest)) {
|
|
717
|
+
throw new TypeError("raw deletion receipt resolution request is invalid");
|
|
718
|
+
}
|
|
719
|
+
const event = this._event(
|
|
720
|
+
EVOLUTION_RAW_DELETION_RECEIPT_EVENT_TYPE,
|
|
721
|
+
receiptDigest,
|
|
722
|
+
);
|
|
723
|
+
if (!event) corrupt("raw deletion receipt is missing");
|
|
724
|
+
const resolved = await this._verifiedReceipt(event, "resolve");
|
|
725
|
+
if (resolved.receipt.receiptDigest !== receiptDigest) {
|
|
726
|
+
corrupt("raw deletion receipt digest was substituted");
|
|
727
|
+
}
|
|
728
|
+
const resolvedAtMs = Number(this._now());
|
|
729
|
+
if (!Number.isFinite(resolvedAtMs)) {
|
|
730
|
+
throw new TypeError("raw deletion ledger clock is invalid");
|
|
731
|
+
}
|
|
732
|
+
return freeze({
|
|
733
|
+
...resolved.receipt,
|
|
734
|
+
schema: EVOLUTION_RAW_DELETION_RESOLUTION_SCHEMA,
|
|
735
|
+
authenticated: true,
|
|
736
|
+
durable: true,
|
|
737
|
+
authorityId: this.descriptor.authorityId,
|
|
738
|
+
revision: this.descriptor.revision,
|
|
739
|
+
handlerArtifactDigest: this.descriptor.handlerArtifactDigest,
|
|
740
|
+
resolvedAt: new Date(resolvedAtMs).toISOString(),
|
|
741
|
+
});
|
|
742
|
+
}
|
|
743
|
+
|
|
744
|
+
async retainTombstone({ tombstone: input } = {}) {
|
|
745
|
+
const tombstone = normalizeTombstone(input, this.descriptor.tenantId);
|
|
746
|
+
const receiptEvent = this._event(
|
|
747
|
+
EVOLUTION_RAW_DELETION_RECEIPT_EVENT_TYPE,
|
|
748
|
+
tombstone.deletionReceiptDigest,
|
|
749
|
+
);
|
|
750
|
+
if (!receiptEvent) corrupt("raw deletion tombstone has no receipt event");
|
|
751
|
+
const { receipt } = await this._verifiedReceipt(receiptEvent, "tombstone");
|
|
752
|
+
if (
|
|
753
|
+
receipt.evidenceRef !== tombstone.evidenceRef ||
|
|
754
|
+
receipt.rawArtifactRef !== tombstone.rawArtifactRef ||
|
|
755
|
+
receipt.rawCipherDigest !== tombstone.rawCipherDigest
|
|
756
|
+
) {
|
|
757
|
+
corrupt("raw deletion tombstone is not bound to its deletion receipt");
|
|
758
|
+
}
|
|
759
|
+
const existing = this._event(
|
|
760
|
+
EVOLUTION_RAW_DELETION_TOMBSTONE_EVENT_TYPE,
|
|
761
|
+
tombstone.tombstoneDigest,
|
|
762
|
+
);
|
|
763
|
+
if (existing) {
|
|
764
|
+
const recovered = this._resolvedTombstone(existing);
|
|
765
|
+
if (
|
|
766
|
+
canonical(recovered.tombstone) !== canonical(tombstone) ||
|
|
767
|
+
canonical(existing.sourceRefs[0]) !== canonical(receiptEvent.subjectRef)
|
|
768
|
+
) {
|
|
769
|
+
corrupt("raw deletion tombstone id resolved substituted lineage");
|
|
770
|
+
}
|
|
771
|
+
return Object.freeze({
|
|
772
|
+
authenticated: true,
|
|
773
|
+
durable: true,
|
|
774
|
+
recovered: true,
|
|
775
|
+
tombstoneDigest: tombstone.tombstoneDigest,
|
|
776
|
+
receiptDigest: existing.eventDigest,
|
|
777
|
+
});
|
|
778
|
+
}
|
|
779
|
+
const persisted = this._persist({
|
|
780
|
+
artifactType: TOMBSTONE_ARTIFACT_TYPE,
|
|
781
|
+
decision: "committed",
|
|
782
|
+
eventType: EVOLUTION_RAW_DELETION_TOMBSTONE_EVENT_TYPE,
|
|
783
|
+
kind: "tombstone",
|
|
784
|
+
logicalDigest: tombstone.tombstoneDigest,
|
|
785
|
+
reason: "confirmed raw evidence crypto-shred tombstone retained",
|
|
786
|
+
sourceRefs: [receiptEvent.subjectRef],
|
|
787
|
+
timestamp: receipt.issuedAt,
|
|
788
|
+
value: tombstone,
|
|
789
|
+
});
|
|
790
|
+
return Object.freeze({
|
|
791
|
+
authenticated: true,
|
|
792
|
+
durable: true,
|
|
793
|
+
recovered: false,
|
|
794
|
+
tombstoneDigest: tombstone.tombstoneDigest,
|
|
795
|
+
receiptDigest: persisted.eventDigest,
|
|
796
|
+
ledgerReceiptDigest: persisted.receiptDigest,
|
|
797
|
+
});
|
|
798
|
+
}
|
|
799
|
+
|
|
800
|
+
async resolveTombstone({ tenantId, tombstoneDigest } = {}) {
|
|
801
|
+
if (
|
|
802
|
+
tenantId !== this.descriptor.tenantId ||
|
|
803
|
+
!DIGEST.test(tombstoneDigest)
|
|
804
|
+
) {
|
|
805
|
+
throw new TypeError(
|
|
806
|
+
"raw deletion tombstone resolution request is invalid",
|
|
807
|
+
);
|
|
808
|
+
}
|
|
809
|
+
const event = this._event(
|
|
810
|
+
EVOLUTION_RAW_DELETION_TOMBSTONE_EVENT_TYPE,
|
|
811
|
+
tombstoneDigest,
|
|
812
|
+
);
|
|
813
|
+
if (!event) corrupt("raw deletion tombstone is missing");
|
|
814
|
+
const resolved = this._resolvedTombstone(event);
|
|
815
|
+
if (resolved.tombstone.tombstoneDigest !== tombstoneDigest) {
|
|
816
|
+
corrupt("raw deletion tombstone digest was substituted");
|
|
817
|
+
}
|
|
818
|
+
const receiptEvent = this._event(
|
|
819
|
+
EVOLUTION_RAW_DELETION_RECEIPT_EVENT_TYPE,
|
|
820
|
+
resolved.tombstone.deletionReceiptDigest,
|
|
821
|
+
);
|
|
822
|
+
if (
|
|
823
|
+
!receiptEvent ||
|
|
824
|
+
canonical(event.sourceRefs[0]) !== canonical(receiptEvent.subjectRef)
|
|
825
|
+
) {
|
|
826
|
+
corrupt("raw deletion tombstone receipt lineage is invalid");
|
|
827
|
+
}
|
|
828
|
+
await this._verifiedReceipt(receiptEvent, "resolve-tombstone");
|
|
829
|
+
return freeze({
|
|
830
|
+
schema: EVOLUTION_RAW_TOMBSTONE_RESOLUTION_SCHEMA,
|
|
831
|
+
authenticated: true,
|
|
832
|
+
durable: true,
|
|
833
|
+
authorityId: this.descriptor.authorityId,
|
|
834
|
+
revision: this.descriptor.revision,
|
|
835
|
+
handlerArtifactDigest: this.descriptor.handlerArtifactDigest,
|
|
836
|
+
tenantId,
|
|
837
|
+
streamId: this.descriptor.streamId,
|
|
838
|
+
tombstoneDigest,
|
|
839
|
+
tombstone: resolved.tombstone,
|
|
840
|
+
ledgerEventDigest: event.eventDigest,
|
|
841
|
+
});
|
|
842
|
+
}
|
|
843
|
+
|
|
844
|
+
cryptoShredPorts({ destroyKey, confirmKeyDestroyed } = {}) {
|
|
845
|
+
if (
|
|
846
|
+
typeof destroyKey !== "function" ||
|
|
847
|
+
typeof confirmKeyDestroyed !== "function"
|
|
848
|
+
) {
|
|
849
|
+
throw new TypeError("KMS destroy and confirmation ports are required");
|
|
850
|
+
}
|
|
851
|
+
return Object.freeze({
|
|
852
|
+
verifyDeletionReceipt: (request) => this.resolveDeletionReceipt(request),
|
|
853
|
+
destroyKey: (...args) => Reflect.apply(destroyKey, undefined, args),
|
|
854
|
+
confirmKeyDestroyed: (...args) =>
|
|
855
|
+
Reflect.apply(confirmKeyDestroyed, undefined, args),
|
|
856
|
+
retainTombstone: (request) => this.retainTombstone(request),
|
|
857
|
+
});
|
|
858
|
+
}
|
|
859
|
+
}
|
|
860
|
+
|
|
861
|
+
export function createEvolutionRawDeletionLedgerAdapter(options) {
|
|
862
|
+
return new EvolutionRawDeletionLedgerAdapter(options);
|
|
863
|
+
}
|
|
864
|
+
|
|
865
|
+
Object.freeze(EvolutionRawDeletionLedgerAdapter.prototype);
|