chainlesschain 0.166.24 → 0.166.26
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 +52 -3
- package/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-DR-MWcZc.js → AIOps-Z8_dnLd8.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-DT8B7sEb.js → ActionButton-C4bKCISV.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-asjh3dQJ.js → Analytics-GztAv2jy.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DivQ491i.js → AppLayout-DEqNcuVx.js} +4 -4
- package/src/assets/web-panel/assets/{Artifacts-DPH2uUmy.js → Artifacts-D-R4Ehap.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-Bp2nLyc-.js → Audit-mzzdTIlM.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-CHS28khl.js → BackgroundAgents-DS2QupIC.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CKeaFSfz.js → Backup-CQSirC39.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CxwM9BAH.js → BaseInput-Bhuc-eOV.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-DYLDwaCv.js → Chat-B-RLVGnt.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-DdBJDBP0.js → ChatBubbleRenderer-CBbMoVuE.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-uYTWOB8j.js → Checkbox-DxwgBryW.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-CvYa_dwT.js → Codegen-Cwrm-7nh.js} +1 -1
- package/src/assets/web-panel/assets/{Col-CanMAX4m.js → Col-DrSCT-nF.js} +1 -1
- package/src/assets/web-panel/assets/{Community-B4WaDtHw.js → Community-DY2D9WNs.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-K93Uof_3.js → Compact-o-tV0URw.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-CKeDLgUW.js → Compliance-Bndh6S8f.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-P93grAeB.js → Cowork-CSNQODak.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-BSHnMtDn.js → Cron-CTgxRHdy.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-epAOpUVJ.js → Crosschain-BJoGQzDI.js} +1 -1
- package/src/assets/web-panel/assets/{DID-ByjXfP7t.js → DID-V0Ztm8ne.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-QztTU8tb.js → Dashboard-B-38THOj.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DhUc9yhN.js → Dropdown-B3FdOwMO.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-C2sLhJJN.js → EmailListRenderer-YQDz4mUF.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CdfbWNDn.js → FamilyGuardDashboard-DYE45IF9.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CcF_R7NW.js → Federation-DjBFjdRZ.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Cm_X2IBk.js → FormItemContext-CVTXEa0R.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DUi4NWlb.js → GenericCardRenderer-B6Tkke8X.js} +1 -1
- package/src/assets/web-panel/assets/{Git-4Sq5FjBt.js → Git-CD0hyAzT.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-Dx2_v4V6.js → Governance-CWOQQJr8.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-7Vr1xekR.js → Inference-lHYwUk-C.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-Cnd2XOzf.js → KnowledgeGraph-Cledxv7t.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-B66QPVf-.js → Logs-D45mt-rM.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-PLsEvhly.js → MarkdownRenderer-DJjPaOnM.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-BMIK9BmC.js → Marketplace-Yy30UZPw.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BDbyp3J_.js → McpTools-Cil5l-bh.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-CJdzfZGi.js → Memory-DdJcnyqy.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-C2TH5Y3-.js → MobileBridge-IrzFYHEv.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-D1dYXkvV.js → MobileProjects-D8q64LMd.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-B-4A1I1j.js → Mtc-CpdTJzW7.js} +5 -5
- package/src/assets/web-panel/assets/{MtcAudit-Bgcc9UOl.js → MtcAudit-C7Tvw2m6.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DqOe-etP.js → Multisig-Dmj9F5Kr.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-7VnhzE_6.js → NLProgramming-C9Xchob5.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BxawpeUQ.js → Notes-Bzq6Yry5.js} +4 -4
- package/src/assets/web-panel/assets/{NotificationSettings-Cr08G2aE.js → NotificationSettings-DxG9eKb4.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Ce8bEGlK.js → OrderTableRenderer-BS_IYoCe.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BC7lveGv.js → Organization-kazsRvcq.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CakOW-G0.js → Overflow-i4wP-hwn.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-Cf8CaOBZ.js → P2P-CfGeU3h-.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-Dc7b98W9.js → PdhVaultBrowser-CS-VhVUx.js} +5 -5
- package/src/assets/web-panel/assets/{Permissions-DGJyMEfS.js → Permissions-DnEHXs0I.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-DNIwSdwu.js → PersonalDataHub-DeD82qke.js} +6 -6
- package/src/assets/web-panel/assets/{Pipeline-5B1S12wa.js → Pipeline-CMGGLgBY.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-CMB6Ke5t.js → Privacy-CvHoFv32.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D5PqTFiT.js → ProjectInit-DnJapCc1.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CbKNdSjV.js → ProjectSettings-CqVdv3-g.js} +2 -2
- package/src/assets/web-panel/assets/Projects-B_o8vcs_.js +1 -0
- package/src/assets/web-panel/assets/{Providers-CJF5_-Gs.js → Providers-CPKseoDW.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-CT6iEAdi.js → QrScannerModal-_iBfKbPQ.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Ci0h9mJ_.js → QuickAsk-CMrlZ69a.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-Da5mobZu.js → Recommend-BwDtSZ0l.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BaCY8eey.js → RemoteSession-DomUAtn4.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-CaITfTsI.js → Reputation-Cuu2GCHr.js} +1 -1
- package/src/assets/web-panel/assets/{Row-DtUDamyP.js → Row-C7GVts31.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DX27gFpg.js → RssFeed-DRKvgEog.js} +3 -3
- package/src/assets/web-panel/assets/{Search-DFL69osN.js → Search-BGI9wOeA.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BqGeoWv-.js → Security-BlLaHy_L.js} +3 -3
- package/src/assets/web-panel/assets/{Services-3z1WnEAc.js → Services-DFqZbjmX.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C_OJQQ9Z.js → Skeleton-BCGxdooP.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-BY7aT6Mo.js → Skills-CwFKgcmm.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-BZv7DSaD.js → Sla-CiXXh9eS.js} +1 -1
- package/src/assets/web-panel/assets/SpeechSettings-WSx2CLqO.js +1 -0
- package/src/assets/web-panel/assets/{SyncSettings-B6D7STlI.js → SyncSettings-BBIqQOtW.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-Co_FCZAO.js → Tasks-D1BGLjO1.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-CnY-9fgz.js → Templates-CUIl9axA.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-B71yXfZ8.js → Tenant-BFZJ0hNz.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-Dd_P7awo.js → Terminal-Cw-3eYVn.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CvIEMyli.js → TimelineRenderer-bOVPB56L.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-DknFBGOi.js → Tokens-Czfyq2VY.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D_4nJONB.js → Trigger-C-o4uJY0.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BNl21fa7.js → Trust-BKq_S6iF.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CFrCI7uK.js → UkeySign-fKlWUvMx.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-BVfY6JLg.js → VideoEditing-DB5MLuS7.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-Cj9CAK0J.js → Wallet-WGXBn7IS.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-DcqZlzA3.js → WebAuthn-B8TC4EMF.js} +4 -4
- package/src/assets/web-panel/assets/{WorkflowEditor-Dfr_dMld.js → WorkflowEditor-DLY--KmM.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Yv6UF0AD.js → chat-Crw3XQaA.js} +1 -1
- package/src/assets/web-panel/assets/{colors-CDW_-1fs.js → colors-CxhWauPV.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BYOQvd-6.js → compact-item-Cp3ojtk5.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BCGO0BiP.js → createContext-CRuRXjSo.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-CKAQY2zn.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-DY-70cfQ.js → hasIn-XGW474dj.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9ZogJJM.js → index-38TRdZb6.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBs2mv5M.js → index-B45Vkh3T.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCwWp3mT.js → index-B5fJS-kn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUo27q9J.js → index-BElgeKJ0.js} +3 -3
- package/src/assets/web-panel/assets/{index-CFa2fPCk.js → index-BUWZ57T4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DCtsjhhT.js → index-BVmSfIkJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-NaCESahy.js → index-BW028Pwn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CaT8trvf.js → index-BXnNbbwa.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRFC2Qt0.js → index-BYkjs7eP.js} +1 -1
- package/src/assets/web-panel/assets/{index-Br3wQLVY.js → index-BetOkRLs.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuIPq5MX.js → index-BuVA26SD.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4UJA2ju.js → index-C73pqyDb.js} +1 -1
- package/src/assets/web-panel/assets/{index-BvK4fjkk.js → index-C8UOVaUH.js} +1 -1
- package/src/assets/web-panel/assets/{index-hZ0Eyrrw.js → index-CDIpH_8Q.js} +1 -1
- package/src/assets/web-panel/assets/{index-D--TEyDj.js → index-CPFam-me.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUP-A2_h.js → index-CTE32qol.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnZNbcux.js → index-CdlfrcC-.js} +1 -1
- package/src/assets/web-panel/assets/index-Cetfwq8j.js +1 -0
- package/src/assets/web-panel/assets/{index-C40UdtlS.js → index-Ctu98x57.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9m5QAMg.js → index-DBcBsJYg.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXlEx4UH.js → index-DHNixOg_.js} +1 -1
- package/src/assets/web-panel/assets/index-DOpcRO2-.js +1 -0
- package/src/assets/web-panel/assets/{index-Dg-AQYDf.js → index-DUSVsOGS.js} +1 -1
- package/src/assets/web-panel/assets/{index-CzeEEazr.js → index-De2FN0xN.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUDoRk9r.js → index-DfPLIA-f.js} +1 -1
- package/src/assets/web-panel/assets/{index-Y9akzgFO.js → index-DhomnuaB.js} +1 -1
- package/src/assets/web-panel/assets/{index-366wfQBU.js → index-DoUC5_ry.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bb9nyts1.js → index-Dp2nC5On.js} +1 -1
- package/src/assets/web-panel/assets/{index-CIyHxV4u.js → index-DxOtBFVy.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFv1hzF6.js → index-E-RSfImO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLOf7BSz.js → index-J_08R33H.js} +1 -1
- package/src/assets/web-panel/assets/{index-RjIMPG0u.js → index-QqAuH7-S.js} +1 -1
- package/src/assets/web-panel/assets/{index-CB_Iw73G.js → index-W8_0yAi_.js} +1 -1
- package/src/assets/web-panel/assets/{index-DM5c4pc-.js → index-WvNZXbIO.js} +1 -1
- package/src/assets/web-panel/assets/{index-DT_qVaaV.js → index-Yq3bFbYX.js} +1 -1
- package/src/assets/web-panel/assets/{index-NYVBUAVN.js → index-jrIcbPUa.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cy2NE6AO.js → index-nJR64pA_.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bf_Va0S-.js → index-qzmihx1d.js} +1 -1
- package/src/assets/web-panel/assets/{index-BayRTE5w.js → index-rsACoVT9.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-CG99CcR4.js → initDefaultProps-DAu-hgme.js} +1 -1
- package/src/assets/web-panel/assets/{motion-Z7MH0_0G.js → motion-Db8yk0Hu.js} +1 -1
- package/src/assets/web-panel/assets/{move-BX67lOdq.js → move-Cii2jOin.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-CmAbG1fE.js → mtc-parser-CnZBDkyZ.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DiU5tI1_.js → omit-Buzt1FTL.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-BGfvLrYL.js → pickAttrs-CpZ_NmE6.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-CggLEgaJ.js → placementArrow-mBrx3dYm.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-t3nlghPZ.js → responsiveObserve-DC_QzljB.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BkV4dL9s.js → slide-DT_UVED-.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-qec1PUoC.js → statusUtils-78t6eNLV.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-ChjX6T8D.js → styleChecker-CV_T1ULL.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-B1jLoZcM.js → useFlexGapSupport-s8edGuXD.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-C3X53s4E.js → useFs-Pk9dH2HC.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DOvbbnkZ.js → usePersonalDataHub-B_GqAm8c.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-Ie0TEVFT.js → vnode-Cxyss24q.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CRUMVS8l.js → zoom-0UY3cOuc.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/evolution-knowledge.js +40 -1
- package/src/commands/serve.js +11 -0
- package/src/data/changelog.json +29 -3
- package/src/generated/cc-agent-protocol.schema.json +3 -1
- package/src/lib/app-server/server.js +49 -0
- package/src/lib/app-server/websocket-transport.js +13 -0
- package/src/lib/evolution/agent-model-projection.js +252 -32
- package/src/lib/evolution/evidence-backed-wiki-maintainer.js +22 -9
- package/src/lib/evolution/evolution-artifact-ports.js +3 -0
- package/src/lib/evolution/evolution-deployment-loader.js +77 -0
- package/src/lib/evolution/evolution-evidence-projector.js +36 -5
- package/src/lib/evolution/evolution-ledger-ports.js +210 -18
- package/src/lib/evolution/governed-knowledge-dependency-inventory.js +392 -0
- package/src/lib/evolution/governed-knowledge-dependency-ledger-executor.js +123 -0
- package/src/lib/evolution/governed-knowledge-quarantine-release.js +1013 -0
- package/src/lib/evolution/governed-knowledge-revocation-host.js +59 -0
- package/src/lib/evolution/governed-knowledge-skill-rollback.js +62 -27
- package/src/lib/evolution/governed-knowledge-sync.js +164 -1
- package/src/lib/evolution/governed-knowledge-wiki-tombstone.js +88 -34
- package/src/lib/evolution/knowledge-wiki-source-admission.js +160 -1
- package/src/lib/evolution/knowledge-wiki-source-provenance.js +1 -0
- package/src/lib/evolution/skill-candidate-registry.js +21 -3
- package/src/lib/evolution/skill-release-registry.js +143 -0
- package/src/lib/evolution/wiki-maintainer-ledger-adapter.js +61 -0
- package/src/lib/evolution/wiki-target-tombstone-revision.js +15 -7
- package/src/lib/read-file-loop-guard.js +222 -0
- package/src/lib/read-file-page.js +55 -2
- package/src/repl/agent-repl.js +6 -1
- package/src/runtime/agent-core.js +177 -57
- package/src/assets/web-panel/assets/Projects-ccXaHzYL.js +0 -1
- package/src/assets/web-panel/assets/SpeechSettings-6lJKLhCn.js +0 -1
- package/src/assets/web-panel/assets/devWarning-H-kXSuf-.js +0 -1
- package/src/assets/web-panel/assets/index-B0o4MeNK.js +0 -1
- package/src/assets/web-panel/assets/index-BVafOL_I.js +0 -1
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { isGovernedKnowledgeSync } from "./governed-knowledge-sync.js";
|
|
2
|
+
|
|
3
|
+
const HOSTS = new WeakSet();
|
|
4
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
5
|
+
|
|
6
|
+
function freeze(value) {
|
|
7
|
+
if (value && typeof value === "object" && !Object.isFrozen(value)) {
|
|
8
|
+
Object.freeze(value);
|
|
9
|
+
for (const child of Object.values(value)) freeze(child);
|
|
10
|
+
}
|
|
11
|
+
return value;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
function clone(value) {
|
|
15
|
+
return structuredClone(value);
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function createGovernedKnowledgeRevocationHost({ sync } = {}) {
|
|
19
|
+
if (!isGovernedKnowledgeSync(sync)) {
|
|
20
|
+
throw new TypeError("a branded governed Knowledge sync is required");
|
|
21
|
+
}
|
|
22
|
+
const host = Object.freeze({
|
|
23
|
+
async prepare(record) {
|
|
24
|
+
const planned = await sync.planRevocation(record);
|
|
25
|
+
return freeze({
|
|
26
|
+
authenticated: true,
|
|
27
|
+
durable: true,
|
|
28
|
+
operationDigest: planned.operationDigest,
|
|
29
|
+
inventoryDigest: planned.inventory.inventoryDigest,
|
|
30
|
+
knowledge: clone(planned.knowledge),
|
|
31
|
+
});
|
|
32
|
+
},
|
|
33
|
+
async publish({ operationDigest } = {}) {
|
|
34
|
+
if (!DIGEST.test(operationDigest ?? "")) {
|
|
35
|
+
throw new TypeError("revocation operationDigest is invalid");
|
|
36
|
+
}
|
|
37
|
+
const planned = await sync.recoverPlannedRevocation({ operationDigest });
|
|
38
|
+
const result = await sync.publishPlanned(planned, {
|
|
39
|
+
operationId: `knowledge-revocation:${operationDigest.slice(7)}`,
|
|
40
|
+
});
|
|
41
|
+
return freeze({
|
|
42
|
+
authenticated: true,
|
|
43
|
+
durable: true,
|
|
44
|
+
recoveredPlan: true,
|
|
45
|
+
operationDigest,
|
|
46
|
+
envelopeDigest: result.envelope.envelopeDigest,
|
|
47
|
+
knowledgeId: planned.knowledge.knowledgeId,
|
|
48
|
+
contentDigest: planned.knowledge.contentDigest,
|
|
49
|
+
dependencyCount: planned.knowledge.dependencies.length,
|
|
50
|
+
});
|
|
51
|
+
},
|
|
52
|
+
});
|
|
53
|
+
HOSTS.add(host);
|
|
54
|
+
return host;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
export function isGovernedKnowledgeRevocationHost(value) {
|
|
58
|
+
return HOSTS.has(value);
|
|
59
|
+
}
|
|
@@ -22,6 +22,16 @@ import {
|
|
|
22
22
|
const ID = /^[A-Za-z0-9][A-Za-z0-9._:@/-]{0,255}$/u;
|
|
23
23
|
const VERIFICATION_SCHEMA =
|
|
24
24
|
"chainlesschain.knowledge-skill-rollback-verification/v1";
|
|
25
|
+
const QUARANTINE_VERIFICATION_SCHEMA =
|
|
26
|
+
"chainlesschain.knowledge-skill-quarantine-verification/v1";
|
|
27
|
+
const ROLLBACK = Object.freeze({
|
|
28
|
+
disposition: "rollback-active",
|
|
29
|
+
verificationSchema: VERIFICATION_SCHEMA,
|
|
30
|
+
});
|
|
31
|
+
const QUARANTINE = Object.freeze({
|
|
32
|
+
disposition: "quarantine",
|
|
33
|
+
verificationSchema: QUARANTINE_VERIFICATION_SCHEMA,
|
|
34
|
+
});
|
|
25
35
|
|
|
26
36
|
function fail(message) {
|
|
27
37
|
throw new Error(`knowledge Skill rollback: ${message}`);
|
|
@@ -117,12 +127,14 @@ function sameLedger(provider, verifier) {
|
|
|
117
127
|
fail("independent readers do not authenticate the same ledger");
|
|
118
128
|
}
|
|
119
129
|
|
|
120
|
-
function releasesFor(reader, request) {
|
|
130
|
+
function releasesFor(reader, request, configuration) {
|
|
121
131
|
if (
|
|
122
132
|
request.dependency.kind !== "active-skill" ||
|
|
123
|
-
request.dependency.disposition !==
|
|
133
|
+
request.dependency.disposition !== configuration.disposition
|
|
124
134
|
)
|
|
125
|
-
fail(
|
|
135
|
+
fail(
|
|
136
|
+
`this provider requires an active-skill / ${configuration.disposition} dependency`,
|
|
137
|
+
);
|
|
126
138
|
// This effect accepts an immutable release identity, never an ambiguous content
|
|
127
139
|
// digest or a caller-supplied Skill name. Other dependency kinds need their own effect.
|
|
128
140
|
const from = reader.registry.readRelease(request.dependency.digest);
|
|
@@ -175,8 +187,8 @@ function resolve(reader, request, from) {
|
|
|
175
187
|
}).result;
|
|
176
188
|
}
|
|
177
189
|
|
|
178
|
-
function committedProof(reader, request) {
|
|
179
|
-
const { from, sourceRef, wiki } = releasesFor(reader, request);
|
|
190
|
+
function committedProof(reader, request, configuration) {
|
|
191
|
+
const { from, sourceRef, wiki } = releasesFor(reader, request, configuration);
|
|
180
192
|
const result = resolve(reader, request, from);
|
|
181
193
|
if (!result) return null;
|
|
182
194
|
const { intent, previous, projection, finalizationEvidence } = result;
|
|
@@ -247,20 +259,21 @@ function authorizationData(value) {
|
|
|
247
259
|
|
|
248
260
|
// Real active-release effect with direct or historically authenticated Wiki
|
|
249
261
|
// provenance. Candidate rejection and quarantine require separate effects.
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
262
|
+
function createSkillDispositionAuthority(options = {}, configuration) {
|
|
263
|
+
const {
|
|
264
|
+
tenantId,
|
|
265
|
+
deviceId,
|
|
266
|
+
releaseRegistry,
|
|
267
|
+
transactionLedger,
|
|
268
|
+
rollbackProvider,
|
|
269
|
+
authorizationProvider,
|
|
270
|
+
verifierReleaseRegistry,
|
|
271
|
+
verifierTransactionLedger,
|
|
272
|
+
wikiLedgerAdapter = null,
|
|
273
|
+
verifierWikiLedgerAdapter = null,
|
|
274
|
+
providerDescriptor,
|
|
275
|
+
verifierDescriptor,
|
|
276
|
+
} = options;
|
|
264
277
|
if (
|
|
265
278
|
releaseRegistry === verifierReleaseRegistry ||
|
|
266
279
|
transactionLedger === verifierTransactionLedger
|
|
@@ -316,9 +329,13 @@ export function createGovernedKnowledgeSkillRollbackAuthority({
|
|
|
316
329
|
|
|
317
330
|
async function apply(request) {
|
|
318
331
|
sameLedger(providerReader, verifierReader);
|
|
319
|
-
let proof = committedProof(providerReader, request);
|
|
332
|
+
let proof = committedProof(providerReader, request, configuration);
|
|
320
333
|
if (!proof) {
|
|
321
|
-
const { from, sourceRef, wiki } = releasesFor(
|
|
334
|
+
const { from, sourceRef, wiki } = releasesFor(
|
|
335
|
+
providerReader,
|
|
336
|
+
request,
|
|
337
|
+
configuration,
|
|
338
|
+
);
|
|
322
339
|
const active = providerReader.registry.readActive(from.skillName);
|
|
323
340
|
if (!active || active.release.releaseDigest !== from.releaseDigest)
|
|
324
341
|
fail("dependent release is not currently active");
|
|
@@ -336,7 +353,11 @@ export function createGovernedKnowledgeSkillRollbackAuthority({
|
|
|
336
353
|
const independent = verifierReader.registry.readActive(from.skillName);
|
|
337
354
|
if (canonical(independent) !== canonical(active))
|
|
338
355
|
fail("independent active state differs");
|
|
339
|
-
const independentSource = releasesFor(
|
|
356
|
+
const independentSource = releasesFor(
|
|
357
|
+
verifierReader,
|
|
358
|
+
request,
|
|
359
|
+
configuration,
|
|
360
|
+
);
|
|
340
361
|
const independentTargetWiki = validateTarget(
|
|
341
362
|
verifierReader,
|
|
342
363
|
request,
|
|
@@ -388,7 +409,7 @@ export function createGovernedKnowledgeSkillRollbackAuthority({
|
|
|
388
409
|
fail("authority authorized a different transition");
|
|
389
410
|
sameLedger(providerReader, verifierReader);
|
|
390
411
|
if (
|
|
391
|
-
committedProof(providerReader, request) !== null ||
|
|
412
|
+
committedProof(providerReader, request, configuration) !== null ||
|
|
392
413
|
canonical(providerReader.registry.readActive(from.skillName)) !==
|
|
393
414
|
canonical(active)
|
|
394
415
|
)
|
|
@@ -397,7 +418,7 @@ export function createGovernedKnowledgeSkillRollbackAuthority({
|
|
|
397
418
|
authorization,
|
|
398
419
|
targetReleaseDigest: target.releaseDigest,
|
|
399
420
|
});
|
|
400
|
-
proof = committedProof(providerReader, request);
|
|
421
|
+
proof = committedProof(providerReader, request, configuration);
|
|
401
422
|
if (!proof) fail("rollback was not durably read back");
|
|
402
423
|
}
|
|
403
424
|
const core = {
|
|
@@ -436,8 +457,12 @@ export function createGovernedKnowledgeSkillRollbackAuthority({
|
|
|
436
457
|
verifier: Object.freeze({
|
|
437
458
|
async verify({ request, result }) {
|
|
438
459
|
sameLedger(providerReader, verifierReader);
|
|
439
|
-
const proof = committedProof(verifierReader, request);
|
|
440
|
-
const providerProof = committedProof(
|
|
460
|
+
const proof = committedProof(verifierReader, request, configuration);
|
|
461
|
+
const providerProof = committedProof(
|
|
462
|
+
providerReader,
|
|
463
|
+
request,
|
|
464
|
+
configuration,
|
|
465
|
+
);
|
|
441
466
|
if (!proof || canonical(proof) !== canonical(providerProof))
|
|
442
467
|
fail("independent durable rollback proof differs");
|
|
443
468
|
const { algorithm, keyId, value } =
|
|
@@ -460,7 +485,7 @@ export function createGovernedKnowledgeSkillRollbackAuthority({
|
|
|
460
485
|
providerRevision: providerIdentity.revision,
|
|
461
486
|
verifierAuthorityId: verifierIdentity.authorityId,
|
|
462
487
|
verifierRevision: verifierIdentity.revision,
|
|
463
|
-
verificationReceiptDigest: digest(
|
|
488
|
+
verificationReceiptDigest: digest(configuration.verificationSchema, {
|
|
464
489
|
tenantId,
|
|
465
490
|
deviceId,
|
|
466
491
|
requestDigest: request.requestDigest,
|
|
@@ -473,3 +498,13 @@ export function createGovernedKnowledgeSkillRollbackAuthority({
|
|
|
473
498
|
}),
|
|
474
499
|
});
|
|
475
500
|
}
|
|
501
|
+
|
|
502
|
+
export function createGovernedKnowledgeSkillRollbackAuthority(options = {}) {
|
|
503
|
+
return createSkillDispositionAuthority(options, ROLLBACK);
|
|
504
|
+
}
|
|
505
|
+
|
|
506
|
+
// Active quarantine performs the same safety rollback, while the separately
|
|
507
|
+
// typed durable dependency fence prevents this exact release from reactivation.
|
|
508
|
+
export function createGovernedKnowledgeSkillQuarantineAuthority(options = {}) {
|
|
509
|
+
return createSkillDispositionAuthority(options, QUARANTINE);
|
|
510
|
+
}
|
|
@@ -3,6 +3,10 @@ import { types as utilTypes } from "node:util";
|
|
|
3
3
|
|
|
4
4
|
import { isGovernedKnowledgeDependencyExecutor } from "./governed-knowledge-dependency-ledger-executor.js";
|
|
5
5
|
import { isGovernedKnowledgeArtifactLifecycle } from "./governed-knowledge-artifact-lifecycle.js";
|
|
6
|
+
import {
|
|
7
|
+
captureGovernedKnowledgeDependencyInventoryPlan,
|
|
8
|
+
isGovernedKnowledgeDependencyInventoryPlanner,
|
|
9
|
+
} from "./governed-knowledge-dependency-inventory.js";
|
|
6
10
|
|
|
7
11
|
import {
|
|
8
12
|
GOVERNED_KNOWLEDGE_SCOPE,
|
|
@@ -28,6 +32,7 @@ const ACTIONS = new Set(["upsert", "tombstone", "revoke"]);
|
|
|
28
32
|
const MAX_CIPHERTEXT_BYTES = 12 * 1024 * 1024;
|
|
29
33
|
const EXECUTION_RECORDS = new WeakSet();
|
|
30
34
|
const SYNCHRONIZERS = new WeakSet();
|
|
35
|
+
const PLANNED_REVOCATIONS = new WeakMap();
|
|
31
36
|
const ENVELOPE_KEYS = new Set([
|
|
32
37
|
"action",
|
|
33
38
|
"ciphertext",
|
|
@@ -244,6 +249,7 @@ export class GovernedKnowledgeSync {
|
|
|
244
249
|
deviceId,
|
|
245
250
|
ports,
|
|
246
251
|
dependencyExecutor = null,
|
|
252
|
+
dependencyPlanner = null,
|
|
247
253
|
artifactLifecycle,
|
|
248
254
|
clock = () => Date.now(),
|
|
249
255
|
} = {}) {
|
|
@@ -282,9 +288,106 @@ export class GovernedKnowledgeSync {
|
|
|
282
288
|
this._executeDependencies = dependencyExecutor
|
|
283
289
|
? capture(dependencyExecutor, "execute")
|
|
284
290
|
: null;
|
|
291
|
+
if (
|
|
292
|
+
dependencyPlanner !== null &&
|
|
293
|
+
(!isGovernedKnowledgeDependencyInventoryPlanner(dependencyPlanner) ||
|
|
294
|
+
dependencyExecutor === null)
|
|
295
|
+
) {
|
|
296
|
+
throw new TypeError(
|
|
297
|
+
"dependencyPlanner requires a branded inventory planner and executor",
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
this._dependencyPlanner = dependencyPlanner;
|
|
301
|
+
this._planDependencies = dependencyPlanner
|
|
302
|
+
? capture(dependencyPlanner, "plan")
|
|
303
|
+
: null;
|
|
304
|
+
this._prepareDependencies = dependencyPlanner
|
|
305
|
+
? capture(dependencyExecutor, "prepare")
|
|
306
|
+
: null;
|
|
307
|
+
this._readPreparedDependencies = dependencyPlanner
|
|
308
|
+
? capture(dependencyExecutor, "readPrepared")
|
|
309
|
+
: null;
|
|
310
|
+
this._readPreparedDependenciesForKnowledge = dependencyPlanner
|
|
311
|
+
? capture(dependencyExecutor, "readPreparedForKnowledge")
|
|
312
|
+
: null;
|
|
285
313
|
SYNCHRONIZERS.add(this);
|
|
286
314
|
}
|
|
287
315
|
|
|
316
|
+
async planRevocation(input) {
|
|
317
|
+
if (!this._planDependencies) {
|
|
318
|
+
throw new Error("knowledge dependency inventory planner is unavailable");
|
|
319
|
+
}
|
|
320
|
+
const planned = this._planDependencies(input);
|
|
321
|
+
captureGovernedKnowledgeDependencyInventoryPlan(
|
|
322
|
+
this._dependencyPlanner,
|
|
323
|
+
planned,
|
|
324
|
+
);
|
|
325
|
+
const knowledge = normalizeRecord(planned.knowledge, this, {
|
|
326
|
+
executionRecord: true,
|
|
327
|
+
});
|
|
328
|
+
if (knowledge.scope === "personal") {
|
|
329
|
+
throw new Error("personal knowledge cannot enter a shared sync channel");
|
|
330
|
+
}
|
|
331
|
+
await this._admit("publish", knowledge);
|
|
332
|
+
const prepared = await this._prepareDependencies(knowledge);
|
|
333
|
+
if (
|
|
334
|
+
prepared?.authenticated !== true ||
|
|
335
|
+
prepared.durable !== true ||
|
|
336
|
+
!DIGEST.test(prepared.operationDigest ?? "") ||
|
|
337
|
+
canonical(prepared.knowledge) !== canonical(knowledge)
|
|
338
|
+
) {
|
|
339
|
+
throw new Error("knowledge dependency plan was not durably prepared");
|
|
340
|
+
}
|
|
341
|
+
const result = freeze({
|
|
342
|
+
inventory: planned.inventory,
|
|
343
|
+
knowledge,
|
|
344
|
+
operationDigest: prepared.operationDigest,
|
|
345
|
+
recovered: false,
|
|
346
|
+
});
|
|
347
|
+
PLANNED_REVOCATIONS.set(result, this);
|
|
348
|
+
return result;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
async recoverPlannedRevocation({ operationDigest } = {}) {
|
|
352
|
+
if (
|
|
353
|
+
!this._readPreparedDependencies ||
|
|
354
|
+
!DIGEST.test(operationDigest ?? "")
|
|
355
|
+
) {
|
|
356
|
+
throw new TypeError(
|
|
357
|
+
"planned revocation recovery is unavailable or invalid",
|
|
358
|
+
);
|
|
359
|
+
}
|
|
360
|
+
const prepared = this._readPreparedDependencies({ operationDigest });
|
|
361
|
+
if (
|
|
362
|
+
prepared?.authenticated !== true ||
|
|
363
|
+
prepared.durable !== true ||
|
|
364
|
+
prepared.operationDigest !== operationDigest
|
|
365
|
+
) {
|
|
366
|
+
throw new Error("prepared knowledge revocation was not found");
|
|
367
|
+
}
|
|
368
|
+
const knowledge = normalizeRecord(prepared.knowledge, this, {
|
|
369
|
+
executionRecord: true,
|
|
370
|
+
});
|
|
371
|
+
await this._admit("publish", knowledge);
|
|
372
|
+
const result = freeze({
|
|
373
|
+
inventory: null,
|
|
374
|
+
knowledge,
|
|
375
|
+
operationDigest,
|
|
376
|
+
recovered: true,
|
|
377
|
+
});
|
|
378
|
+
PLANNED_REVOCATIONS.set(result, this);
|
|
379
|
+
return result;
|
|
380
|
+
}
|
|
381
|
+
|
|
382
|
+
async publishPlanned(plan, options = {}) {
|
|
383
|
+
if (PLANNED_REVOCATIONS.get(plan) !== this) {
|
|
384
|
+
throw new TypeError(
|
|
385
|
+
"a revocation plan prepared by this sync is required",
|
|
386
|
+
);
|
|
387
|
+
}
|
|
388
|
+
return this.publishWithArtifactEvidence(plan.knowledge, options);
|
|
389
|
+
}
|
|
390
|
+
|
|
288
391
|
async publish(input, options = {}) {
|
|
289
392
|
const result = await this.publishWithArtifactEvidence(input, options);
|
|
290
393
|
return result.envelope;
|
|
@@ -602,7 +705,8 @@ export class GovernedKnowledgeSync {
|
|
|
602
705
|
activate: binding.activate,
|
|
603
706
|
humanReviewed: binding.humanReviewed,
|
|
604
707
|
});
|
|
605
|
-
await this.
|
|
708
|
+
const dependencyKnowledge = await this._receivedDependencyPlan(knowledge);
|
|
709
|
+
await this._applyRevocationDependencies(dependencyKnowledge);
|
|
606
710
|
await this._persist(
|
|
607
711
|
knowledge,
|
|
608
712
|
envelope,
|
|
@@ -711,6 +815,65 @@ export class GovernedKnowledgeSync {
|
|
|
711
815
|
throw new Error("revocation dependencies were not durably applied");
|
|
712
816
|
}
|
|
713
817
|
}
|
|
818
|
+
|
|
819
|
+
async _receivedDependencyPlan(remoteKnowledge) {
|
|
820
|
+
if (
|
|
821
|
+
!["tombstone", "revoke"].includes(remoteKnowledge.action) ||
|
|
822
|
+
!this._planDependencies
|
|
823
|
+
) {
|
|
824
|
+
return remoteKnowledge;
|
|
825
|
+
}
|
|
826
|
+
const portable = (value) => {
|
|
827
|
+
const copy = clone(value);
|
|
828
|
+
delete copy.dependencies;
|
|
829
|
+
return copy;
|
|
830
|
+
};
|
|
831
|
+
const recovered =
|
|
832
|
+
this._readPreparedDependenciesForKnowledge(remoteKnowledge);
|
|
833
|
+
let localKnowledge;
|
|
834
|
+
if (recovered) {
|
|
835
|
+
if (
|
|
836
|
+
recovered.authenticated !== true ||
|
|
837
|
+
recovered.durable !== true ||
|
|
838
|
+
!DIGEST.test(recovered.operationDigest ?? "")
|
|
839
|
+
) {
|
|
840
|
+
throw new Error("received revocation local plan is unauthenticated");
|
|
841
|
+
}
|
|
842
|
+
localKnowledge = normalizeRecord(recovered.knowledge, this, {
|
|
843
|
+
executionRecord: true,
|
|
844
|
+
});
|
|
845
|
+
} else {
|
|
846
|
+
const draft = portable(remoteKnowledge);
|
|
847
|
+
delete draft.schema;
|
|
848
|
+
const planned = this._planDependencies(draft);
|
|
849
|
+
captureGovernedKnowledgeDependencyInventoryPlan(
|
|
850
|
+
this._dependencyPlanner,
|
|
851
|
+
planned,
|
|
852
|
+
);
|
|
853
|
+
localKnowledge = normalizeRecord(planned.knowledge, this, {
|
|
854
|
+
executionRecord: true,
|
|
855
|
+
});
|
|
856
|
+
}
|
|
857
|
+
if (
|
|
858
|
+
canonical(portable(localKnowledge)) !==
|
|
859
|
+
canonical(portable(remoteKnowledge))
|
|
860
|
+
) {
|
|
861
|
+
throw new Error(
|
|
862
|
+
"received revocation local plan changed signed knowledge",
|
|
863
|
+
);
|
|
864
|
+
}
|
|
865
|
+
const prepared = await this._prepareDependencies(localKnowledge);
|
|
866
|
+
if (
|
|
867
|
+
prepared?.authenticated !== true ||
|
|
868
|
+
prepared.durable !== true ||
|
|
869
|
+
canonical(prepared.knowledge) !== canonical(localKnowledge)
|
|
870
|
+
) {
|
|
871
|
+
throw new Error(
|
|
872
|
+
"received revocation local plan was not durably prepared",
|
|
873
|
+
);
|
|
874
|
+
}
|
|
875
|
+
return localKnowledge;
|
|
876
|
+
}
|
|
714
877
|
}
|
|
715
878
|
|
|
716
879
|
export function isGovernedKnowledgeSync(value) {
|
|
@@ -2,7 +2,7 @@ import { types } from "node:util";
|
|
|
2
2
|
import { captureWikiRevisionReader } from "./wiki-maintainer-ledger-adapter.js";
|
|
3
3
|
import { captureSkillReleaseOperationReader } from "./evolution-ledger-ports.js";
|
|
4
4
|
import { governedKnowledgeSourceRef } from "./governed-knowledge-skill-rollback.js";
|
|
5
|
-
import {
|
|
5
|
+
import { deriveWikiTargetDispositionRevision } from "./wiki-target-tombstone-revision.js";
|
|
6
6
|
import {
|
|
7
7
|
createGovernedKnowledgeDependencyAuthority,
|
|
8
8
|
GOVERNED_KNOWLEDGE_DEPENDENCY_RESULT_SCHEMA,
|
|
@@ -39,6 +39,36 @@ const MULTIHOP_RULES_DIGEST = digest(MULTIHOP_SCHEMA, {
|
|
|
39
39
|
schema: MULTIHOP_SCHEMA,
|
|
40
40
|
source: "authenticated-pinned-Wiki-exact-Knowledge-ancestry",
|
|
41
41
|
});
|
|
42
|
+
const QUARANTINE_SCHEMA = "chainlesschain.knowledge-wiki-quarantine/v1";
|
|
43
|
+
const QUARANTINE_RULES = Object.freeze({
|
|
44
|
+
...RULES,
|
|
45
|
+
schema: QUARANTINE_SCHEMA,
|
|
46
|
+
effect: "target-only-quarantine",
|
|
47
|
+
});
|
|
48
|
+
const QUARANTINE_RULES_DIGEST = digest(QUARANTINE_SCHEMA, QUARANTINE_RULES);
|
|
49
|
+
const QUARANTINE_MULTIHOP_SCHEMA =
|
|
50
|
+
"chainlesschain.knowledge-wiki-quarantine/v2";
|
|
51
|
+
const QUARANTINE_MULTIHOP_RULES_DIGEST = digest(QUARANTINE_MULTIHOP_SCHEMA, {
|
|
52
|
+
...QUARANTINE_RULES,
|
|
53
|
+
schema: QUARANTINE_MULTIHOP_SCHEMA,
|
|
54
|
+
source: "authenticated-pinned-Wiki-exact-Knowledge-ancestry",
|
|
55
|
+
});
|
|
56
|
+
const TOMBSTONE = Object.freeze({
|
|
57
|
+
disposition: "tombstone",
|
|
58
|
+
schema: SCHEMA,
|
|
59
|
+
rulesDigest: RULES_DIGEST,
|
|
60
|
+
multihopSchema: MULTIHOP_SCHEMA,
|
|
61
|
+
multihopRulesDigest: MULTIHOP_RULES_DIGEST,
|
|
62
|
+
model: "deterministic:knowledge-wiki-tombstone",
|
|
63
|
+
});
|
|
64
|
+
const QUARANTINE = Object.freeze({
|
|
65
|
+
disposition: "quarantine",
|
|
66
|
+
schema: QUARANTINE_SCHEMA,
|
|
67
|
+
rulesDigest: QUARANTINE_RULES_DIGEST,
|
|
68
|
+
multihopSchema: QUARANTINE_MULTIHOP_SCHEMA,
|
|
69
|
+
multihopRulesDigest: QUARANTINE_MULTIHOP_RULES_DIGEST,
|
|
70
|
+
model: "deterministic:knowledge-wiki-quarantine",
|
|
71
|
+
});
|
|
42
72
|
function fail(message) {
|
|
43
73
|
throw new Error(`Knowledge Wiki tombstone: ${message}`);
|
|
44
74
|
}
|
|
@@ -57,7 +87,7 @@ function bind(wikiAdapter, transactionLedger, tenantId) {
|
|
|
57
87
|
);
|
|
58
88
|
return Object.freeze({ wiki, operations });
|
|
59
89
|
}
|
|
60
|
-
function partsFor(source, request, provenance) {
|
|
90
|
+
function partsFor(source, request, provenance, configuration) {
|
|
61
91
|
const sourceRef = governedKnowledgeSourceRef(request);
|
|
62
92
|
const refs = new Set(
|
|
63
93
|
Object.values(source.state.evidence)
|
|
@@ -82,7 +112,7 @@ function partsFor(source, request, provenance) {
|
|
|
82
112
|
.sort();
|
|
83
113
|
const targetIds = provenance.affectedPatternIds;
|
|
84
114
|
const operations = targetIds.map((patternId) => ({
|
|
85
|
-
type:
|
|
115
|
+
type: configuration.disposition,
|
|
86
116
|
patternId,
|
|
87
117
|
reason: "governed-knowledge-revocation",
|
|
88
118
|
}));
|
|
@@ -93,7 +123,7 @@ function partsFor(source, request, provenance) {
|
|
|
93
123
|
// v2 contract, pinned to the original revision rather than today's head.
|
|
94
124
|
const sourceProofDigest = same(directIds, targetIds)
|
|
95
125
|
? null
|
|
96
|
-
: digest(`${
|
|
126
|
+
: digest(`${configuration.multihopSchema}/source`, {
|
|
97
127
|
revisionId: provenance.revisionId,
|
|
98
128
|
stateDigest: provenance.stateDigest,
|
|
99
129
|
checkpoint: provenance.checkpoint,
|
|
@@ -111,7 +141,7 @@ function partsFor(source, request, provenance) {
|
|
|
111
141
|
operations: batch,
|
|
112
142
|
...(sourceProofDigest ? { sourceProofDigest } : {}),
|
|
113
143
|
requestDigest: digest(
|
|
114
|
-
`${sourceProofDigest ?
|
|
144
|
+
`${sourceProofDigest ? configuration.multihopSchema : configuration.schema}/batch`,
|
|
115
145
|
{
|
|
116
146
|
requestDigest: request.requestDigest,
|
|
117
147
|
index,
|
|
@@ -123,8 +153,8 @@ function partsFor(source, request, provenance) {
|
|
|
123
153
|
};
|
|
124
154
|
});
|
|
125
155
|
}
|
|
126
|
-
function derive(reader, source, part, fence) {
|
|
127
|
-
return
|
|
156
|
+
function derive(reader, source, part, fence, configuration) {
|
|
157
|
+
return deriveWikiTargetDispositionRevision({
|
|
128
158
|
source,
|
|
129
159
|
operations: part.operations,
|
|
130
160
|
requestDigest: part.requestDigest,
|
|
@@ -132,24 +162,24 @@ function derive(reader, source, part, fence) {
|
|
|
132
162
|
descriptor: {
|
|
133
163
|
tenantId: reader.wiki.descriptor.tenantId,
|
|
134
164
|
evolutionRunId: reader.wiki.descriptor.evolutionRunId,
|
|
135
|
-
maintainerModel: part.sourceProofDigest
|
|
136
|
-
? "deterministic:knowledge-wiki-tombstone/v2"
|
|
137
|
-
: "deterministic:knowledge-wiki-tombstone/v1",
|
|
165
|
+
maintainerModel: `${configuration.model}/${part.sourceProofDigest ? "v2" : "v1"}`,
|
|
138
166
|
rulesDigest: part.sourceProofDigest
|
|
139
|
-
?
|
|
140
|
-
:
|
|
167
|
+
? configuration.multihopRulesDigest
|
|
168
|
+
: configuration.rulesDigest,
|
|
141
169
|
minCorroboratingSources: RULES.minCorroboratingSources,
|
|
142
170
|
decayHalfLifeDays: RULES.decayHalfLifeDays,
|
|
143
171
|
staleConfidenceFloor: RULES.staleConfidenceFloor,
|
|
144
172
|
},
|
|
145
173
|
});
|
|
146
174
|
}
|
|
147
|
-
async function prove(reader, request, context, original) {
|
|
175
|
+
async function prove(reader, request, context, original, configuration) {
|
|
148
176
|
if (
|
|
149
177
|
request.dependency.kind !== "wiki" ||
|
|
150
|
-
request.dependency.disposition !==
|
|
178
|
+
request.dependency.disposition !== configuration.disposition
|
|
151
179
|
)
|
|
152
|
-
fail(
|
|
180
|
+
fail(
|
|
181
|
+
`only an exact wiki / ${configuration.disposition} dependency is supported`,
|
|
182
|
+
);
|
|
153
183
|
const admission = reader.operations.resolveKnowledgeRevocation({
|
|
154
184
|
tenantId: request.tenantId,
|
|
155
185
|
operationDigest: request.operationDigest,
|
|
@@ -189,7 +219,7 @@ async function prove(reader, request, context, original) {
|
|
|
189
219
|
!matchHead(context.checkpoint, provenance.ledgerHead)
|
|
190
220
|
)
|
|
191
221
|
fail("Wiki ancestry does not bind the original state and current ledger");
|
|
192
|
-
const parts = partsFor(original, request, provenance);
|
|
222
|
+
const parts = partsFor(original, request, provenance, configuration);
|
|
193
223
|
const history = reader.wiki.resolveHistory({
|
|
194
224
|
tenantId: request.tenantId,
|
|
195
225
|
stateDigest: request.dependency.digest,
|
|
@@ -204,7 +234,13 @@ async function prove(reader, request, context, original) {
|
|
|
204
234
|
for (const [index, entry] of history.successors.entries()) {
|
|
205
235
|
if (entry.predecessorHead.sequence < fence.sequence)
|
|
206
236
|
fail("Wiki effect predates its prepared Knowledge authorization");
|
|
207
|
-
const expected = await derive(
|
|
237
|
+
const expected = await derive(
|
|
238
|
+
reader,
|
|
239
|
+
source,
|
|
240
|
+
parts[index],
|
|
241
|
+
fence,
|
|
242
|
+
configuration,
|
|
243
|
+
);
|
|
208
244
|
if (!same(expected, entry.revision))
|
|
209
245
|
fail("Wiki successor does not match the exact target-only tombstones");
|
|
210
246
|
source = {
|
|
@@ -228,17 +264,18 @@ async function prove(reader, request, context, original) {
|
|
|
228
264
|
});
|
|
229
265
|
}
|
|
230
266
|
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
267
|
+
function createWikiDispositionAuthority(options = {}, configuration) {
|
|
268
|
+
const {
|
|
269
|
+
tenantId,
|
|
270
|
+
deviceId,
|
|
271
|
+
wikiLedgerAdapter,
|
|
272
|
+
transactionLedger,
|
|
273
|
+
verifierWikiLedgerAdapter,
|
|
274
|
+
verifierTransactionLedger,
|
|
275
|
+
providerDescriptor,
|
|
276
|
+
verifierDescriptor,
|
|
277
|
+
additionalWikiTargets = [],
|
|
278
|
+
} = options;
|
|
242
279
|
if (
|
|
243
280
|
wikiLedgerAdapter === verifierWikiLedgerAdapter ||
|
|
244
281
|
transactionLedger === verifierTransactionLedger
|
|
@@ -354,12 +391,14 @@ export function createGovernedKnowledgeWikiTombstoneAuthority({
|
|
|
354
391
|
request,
|
|
355
392
|
context,
|
|
356
393
|
selected.original,
|
|
394
|
+
configuration,
|
|
357
395
|
);
|
|
358
396
|
const independent = await prove(
|
|
359
397
|
selected.binding.verifier,
|
|
360
398
|
request,
|
|
361
399
|
context,
|
|
362
400
|
selected.independentOriginal,
|
|
401
|
+
configuration,
|
|
363
402
|
);
|
|
364
403
|
if (!same(primary, independent))
|
|
365
404
|
fail("independent Wiki effect proof differs");
|
|
@@ -407,6 +446,7 @@ export function createGovernedKnowledgeWikiTombstoneAuthority({
|
|
|
407
446
|
proof.current,
|
|
408
447
|
proof.parts[done],
|
|
409
448
|
proof.fence,
|
|
449
|
+
configuration,
|
|
410
450
|
);
|
|
411
451
|
let commitError = null;
|
|
412
452
|
try {
|
|
@@ -449,14 +489,28 @@ export function createGovernedKnowledgeWikiTombstoneAuthority({
|
|
|
449
489
|
providerRevision: providerIdentity.revision,
|
|
450
490
|
verifierAuthorityId: verifierIdentity.authorityId,
|
|
451
491
|
verifierRevision: verifierIdentity.revision,
|
|
452
|
-
verificationReceiptDigest: digest(
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
492
|
+
verificationReceiptDigest: digest(
|
|
493
|
+
`${configuration.schema}/verification`,
|
|
494
|
+
{
|
|
495
|
+
requestDigest: request.requestDigest,
|
|
496
|
+
resultDigest: result.resultDigest,
|
|
497
|
+
proof,
|
|
498
|
+
verifierIdentity,
|
|
499
|
+
},
|
|
500
|
+
),
|
|
458
501
|
});
|
|
459
502
|
},
|
|
460
503
|
}),
|
|
461
504
|
});
|
|
462
505
|
}
|
|
506
|
+
|
|
507
|
+
export function createGovernedKnowledgeWikiTombstoneAuthority(options = {}) {
|
|
508
|
+
return createWikiDispositionAuthority(options, TOMBSTONE);
|
|
509
|
+
}
|
|
510
|
+
|
|
511
|
+
// Quarantine is a distinct non-deletion state. The generic Wiki maintainer
|
|
512
|
+
// refuses to rewrite quarantined patterns, so only a future separately governed
|
|
513
|
+
// release authority can make them actionable again.
|
|
514
|
+
export function createGovernedKnowledgeWikiQuarantineAuthority(options = {}) {
|
|
515
|
+
return createWikiDispositionAuthority(options, QUARANTINE);
|
|
516
|
+
}
|