chainlesschain 0.166.92 → 0.166.94
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 +16 -7
- package/package.json +3 -3
- package/src/assets/linux-subreaper/linux-arm64/manifest.json +1 -1
- package/src/assets/linux-subreaper/linux-x64/manifest.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-C74YzqwJ.js → AIOps-CzxfrB7_.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-TFef1hOE.js → ActionButton-6a4WFIb0.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-CYsWpkkU.js → Analytics-O3Hv5QVR.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-CFf9kjwu.js → AppLayout-D96Jtyrz.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-TQqa94YO.js → Artifacts-BxbCrGsv.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-B79ayqfS.js → Audit-Dvhj3ev4.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-pjkHfLP9.js → BackgroundAgents-zgrU13eK.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-CE6A-t_r.js → Backup-B3ePsQ8z.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-CwcgWMBY.js → BaseInput-CemgxVZi.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-BIkDNesY.js → Chat-BNxuigZo.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-DgaokYts.js → ChatBubbleRenderer-DE73IMLf.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-MbypIy5V.js → Checkbox-BvHaZkOM.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DiFHWDnt.js → Codegen--DNXNLnq.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BNMlYMso.js → Col-C8xvHu-3.js} +1 -1
- package/src/assets/web-panel/assets/{Community-B3HVyHOX.js → Community-v19Cxqtl.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-C7hlAubb.js → Compact-BdQ659sW.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-PaXZu6sE.js → Compliance-CE0-97Ph.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-BGiojbm-.js → Cowork-YCuhzIZE.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-Bmr-1QAx.js → Cron-C5xa6iEB.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-BwUvWCVd.js → Crosschain-CmsyQp8f.js} +1 -1
- package/src/assets/web-panel/assets/{DID-k_4QZocW.js → DID-FY-oN652.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-_ieRo2C5.js → Dashboard-CFJD_yB7.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-DYHh6T27.js → Dropdown-QM5qyalT.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-BNlQcWQX.js → EmailListRenderer-BbA-SPX0.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-DIkZ6U2D.js → EvolutionSettings-BGH3oR71.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-Dq7qSr0P.js → FamilyGuardDashboard-C4s2LeR4.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-C64e3Cbx.js → Federation-Cfb8190f.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-D-GE2vUa.js → FormItemContext-DFVYcD2A.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-DO3B2gis.js → GenericCardRenderer-CU-yqT1M.js} +1 -1
- package/src/assets/web-panel/assets/{Git-0ETirIQH.js → Git-tYiQuWYO.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-C9fnRygX.js → Governance-DRH8tKKy.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-CLJ9RTsK.js → Inference-v2GbRYb4.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-D3C_GxrN.js → KnowledgeGraph-B5Ff0wSA.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-C5ctGbkN.js → Logs-mcHQsQZC.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-Ce-eWK3j.js → MarkdownRenderer-rk-aXvLV.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-GF_t6hJ_.js → Marketplace-LUstH49t.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BGsGzgQs.js → McpTools-kFFP54H9.js} +2 -2
- package/src/assets/web-panel/assets/{Memory-CcrY2A0j.js → Memory--KBUL4b_.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-Bi4T0RlS.js → MobileBridge-CQL_xVyD.js} +1 -1
- package/src/assets/web-panel/assets/MobileProjects-DoIR8HA0.js +1 -0
- package/src/assets/web-panel/assets/{Mtc-DL77Vf-k.js → Mtc-BrUPLX-C.js} +6 -6
- package/src/assets/web-panel/assets/{MtcAudit-CDy_Uswb.js → MtcAudit-46jjW0Ne.js} +4 -4
- package/src/assets/web-panel/assets/{Multisig-DL0BAO_c.js → Multisig-3XX8crha.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-B-woh5IR.js → NLProgramming-C53SRk52.js} +1 -1
- package/src/assets/web-panel/assets/Notes-RxpNEOb6.js +7 -0
- package/src/assets/web-panel/assets/{NotificationSettings-BqPPMuAP.js → NotificationSettings-C2R6A0rD.js} +1 -1
- package/src/assets/web-panel/assets/OrderTableRenderer-Bhhp4H-K.js +1 -0
- package/src/assets/web-panel/assets/{Organization-B1gX8jlr.js → Organization-B48YmG99.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-CeMxuUZy.js → Overflow-BYPoJ7Qo.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-B5aIRWwJ.js → P2P-CI9F_5Xz.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-6rYgejd4.js → PdhVaultBrowser-C50vLFTe.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-CqCp2SIl.js → Permissions-CKMhcV4D.js} +3 -3
- package/src/assets/web-panel/assets/{PersonalDataHub-BsA7DJWW.js → PersonalDataHub-CFwVht-l.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-CiW6HeZh.js → Pipeline-BQliRCrn.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DckUOLYq.js → Privacy-z-9F-MIF.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-CZppOOYR.js → ProjectInit-DAuaSe48.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-B9QPzhDU.js → ProjectSettings-BpCCZLAx.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-BErjjGha.js → Projects-CguDJz4k.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DehU6Qiz.js → Providers-DOXv8vOy.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-E1SUvv1m.js → QrScannerModal-BiMsPToH.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-COWFxyH3.js → QuickAsk-Dxjfq39w.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-D26pWKxX.js → Recommend-Y5kQ_a2f.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-DCOIaId3.js → RemoteSession-BSIDk0es.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-DT_AHGAR.js → Reputation-BLjwaybi.js} +1 -1
- package/src/assets/web-panel/assets/{Row-B50S-1nl.js → Row-7geSc2GW.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-BaBnHg3Q.js → RssFeed-BophPGWk.js} +3 -3
- package/src/assets/web-panel/assets/{Search-BVdnLuuS.js → Search-iBXsRvIQ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BnacH74J.js → Security-sM5aX0dn.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CxM08Zch.js → Services-8n708_pG.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-DE7CIc1N.js → Skeleton-D2rl_ikr.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CGI0SJmf.js → Skills-DJpknGnz.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DpEzPcqc.js → Sla-mA8eEXRj.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-CTmnmMHn.js → SpeechSettings-BVrmiTgd.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-Dxgrd9hd.js → SyncSettings-Cd-KRX72.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-CW4slS0A.js → Tasks-DYAvmen_.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DxvGWDgB.js → Templates-DPdlYX7S.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-_Q0o2tNK.js → Tenant-wfSNgGDT.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-BTZn8pow.js → Terminal-BqJDIQEC.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-CauL0KFe.js → TimelineRenderer-eeuMKufC.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-CDoM2qeT.js → Tokens-DW9xE5CY.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-B-QYGEU7.js → Trigger-BBniBnCp.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-BD6XJHT-.js → Trust-C7fZAxYI.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-x4TFwCy0.js → UkeySign-X_cT1LN_.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-t3imBK_0.js → VideoEditing-C95qSEAg.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BCfkWwNC.js → Wallet-_Y76V1eI.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-WH314Mdm.js → WebAuthn-CUpi7QWI.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-jUlcjrUg.js → WorkflowEditor-CdTwu4JZ.js} +1 -1
- package/src/assets/web-panel/assets/{chat-Dg3VASTL.js → chat-D2hW7s3x.js} +1 -1
- package/src/assets/web-panel/assets/{colors-BNvmBRKE.js → colors-Cxes7tn4.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BGOfoqf4.js → compact-item-BuLnefA8.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-BNQeqKAs.js → createContext-DSJr7jrZ.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BHLx7Ctv.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Bg3AjCrq.js → hasIn-CPtCYTi-.js} +1 -1
- package/src/assets/web-panel/assets/{index-2D04Zltx.js → index--J0mLXrw.js} +3 -3
- package/src/assets/web-panel/assets/{index-COol3xfA.js → index--gm5GIKK.js} +1 -1
- package/src/assets/web-panel/assets/{index-DcCnO0RU.js → index-5Vtfy09g.js} +1 -1
- package/src/assets/web-panel/assets/{index-fOwii3LP.js → index-B5GXCqB0.js} +1 -1
- package/src/assets/web-panel/assets/{index-OUFoxUgH.js → index-BC-FDx0Y.js} +1 -1
- package/src/assets/web-panel/assets/{index-Bkz1tgFR.js → index-BDaNLJss.js} +1 -1
- package/src/assets/web-panel/assets/{index-DLwEXRrb.js → index-BOKMxs4C.js} +1 -1
- package/src/assets/web-panel/assets/{index-BBCMulQ-.js → index-BOXgWdJY.js} +1 -1
- package/src/assets/web-panel/assets/{index-B_JmInC0.js → index-BSHkOFqM.js} +1 -1
- package/src/assets/web-panel/assets/{index-pVdQieac.js → index-B_mChW9O.js} +1 -1
- package/src/assets/web-panel/assets/{index-BmTacaQV.js → index-Bq-CMI2h.js} +1 -1
- package/src/assets/web-panel/assets/{index-Wo0f2iqb.js → index-BudaM8zA.js} +1 -1
- package/src/assets/web-panel/assets/{index-B--0QM0S.js → index-C2qdbxEw.js} +1 -1
- package/src/assets/web-panel/assets/{index-BaPvEvB4.js → index-C6jDeixf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dkp-okWa.js → index-C88mhge1.js} +1 -1
- package/src/assets/web-panel/assets/{index-BSNhW95G.js → index-C8xMmdFz.js} +1 -1
- package/src/assets/web-panel/assets/{index-7QJUWemf.js → index-CCI2rS5G.js} +1 -1
- package/src/assets/web-panel/assets/{index-xzaUx19r.js → index-CFTO4avR.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cbp-wp-U.js → index-CVgzXcvk.js} +1 -1
- package/src/assets/web-panel/assets/{index-Co_LnCWD.js → index-C_RLdbKl.js} +1 -1
- package/src/assets/web-panel/assets/{index-CY8cRKHR.js → index-CighFQgt.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0mgngoB.js → index-CmV_i-tY.js} +1 -1
- package/src/assets/web-panel/assets/{index-ZD5Kd8tx.js → index-Ct9hZUrk.js} +1 -1
- package/src/assets/web-panel/assets/{index-uH2LnAs_.js → index-D4YILZTK.js} +1 -1
- package/src/assets/web-panel/assets/{index-CCFZN66A.js → index-DDSmCL8t.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYn5DnDk.js → index-DFSJeXBu.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx2EXRfr.js → index-DGIumCxN.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6UqK83L.js → index-DIkV-pwg.js} +1 -1
- package/src/assets/web-panel/assets/{index-DO0VlNtc.js → index-DTtVX2yD.js} +1 -1
- package/src/assets/web-panel/assets/{index-D_O2ZjPk.js → index-Dz6h62uC.js} +1 -1
- package/src/assets/web-panel/assets/{index-D-mSvCQK.js → index-PyLgXmQZ.js} +1 -1
- package/src/assets/web-panel/assets/index-V4IYxvvE.js +1 -0
- package/src/assets/web-panel/assets/{index--I3UF5t1.js → index-_AYMw6sF.js} +1 -1
- package/src/assets/web-panel/assets/{index-hG7jXGEW.js → index-ePTIQg1n.js} +1 -1
- package/src/assets/web-panel/assets/{index-60AnjUTX.js → index-f1fHG0MC.js} +1 -1
- package/src/assets/web-panel/assets/{index-DS04wRll.js → index-lOl7QbP4.js} +1 -1
- package/src/assets/web-panel/assets/{index-DF_FKSVH.js → index-vsUYvuDU.js} +1 -1
- package/src/assets/web-panel/assets/index-y4vqXg0S.js +1 -0
- package/src/assets/web-panel/assets/{index-D072oLjp.js → index-ystQEkV4.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-B8PN9AxJ.js → initDefaultProps-CAxtYUKo.js} +1 -1
- package/src/assets/web-panel/assets/{motion-BHivfw5Q.js → motion-CgPmr4vy.js} +1 -1
- package/src/assets/web-panel/assets/{move-B0QU5nDd.js → move-XGK3_B35.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-DRwRM3PE.js → mtc-parser-C6Vfqz8e.js} +1 -1
- package/src/assets/web-panel/assets/{omit-SHt2rV2p.js → omit-DquSN-3H.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CcmDlEb2.js → pickAttrs-BH-ir5eD.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DYatmXDS.js → placementArrow-Drf-QXk8.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-B7qrsXq5.js → responsiveObserve-BUBMbJsH.js} +1 -1
- package/src/assets/web-panel/assets/{slide-BRGhlOWd.js → slide-BCqinMKC.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-CT-7NXsQ.js → statusUtils-CAp3-0Ss.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-rZdw_Yyp.js → styleChecker-DIuQh0dB.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-D8YNIP4P.js → useFlexGapSupport-CWXPAfZR.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-B8pt0Gu-.js → useFs-905ulWWY.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-VMmYM1tt.js → usePersonalDataHub-DajnovG6.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-UNDuoPoq.js → vnode-BE_Yg3pz.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-dN-u667S.js → zoom-BLndEna7.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/data/changelog.json +26 -0
- package/src/lib/artifact-store.js +51 -3
- package/src/lib/bounded-artifact-file-read.js +131 -0
- package/src/lib/evolution/evolution-artifact-ports.js +209 -129
- package/src/lib/evolution/rrsi-history-ledger-adapter.js +25 -0
- package/src/lib/evolution/rrsi-installation-route-contracts.js +275 -0
- package/src/lib/evolution/rrsi-installation-route-reader.js +282 -0
- package/src/lib/evolution/rrsi-observed-text-index.js +978 -0
- package/src/lib/evolution/rrsi-registry-runtime-policy.js +648 -0
- package/src/lib/evolution/rrsi-registry-store-policy.js +95 -15
- package/src/lib/evolution/rrsi-tenant-index-anchor-contracts.js +223 -0
- package/src/lib/evolution/rrsi-tenant-index-anchor-history.js +157 -0
- package/src/lib/evolution/skill-release-registry.js +20 -5
- package/src/lib/process-execution-broker/windows-native-evaluator-capabilities.js +291 -30
- package/src/lib/process-execution-broker/windows-native-evaluator.js +247 -28
- 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 +140 -6
- package/src/lib/remote-read-loop-guard.js +227 -24
- package/src/lib/settings-loader.cjs +10 -1
- package/src/lib/task-progress-tracker.js +6 -1
- package/src/lib/with-file-lock.js +86 -16
- package/src/runtime/agent-core.js +71 -23
- package/src/assets/web-panel/assets/MobileProjects-DvjEGyvf.js +0 -1
- package/src/assets/web-panel/assets/Notes-CEFVCxk7.js +0 -7
- package/src/assets/web-panel/assets/OrderTableRenderer-GUKQ1xwp.js +0 -1
- package/src/assets/web-panel/assets/devWarning-B7_ypN1G.js +0 -1
- package/src/assets/web-panel/assets/index-B-jSKJK6.js +0 -1
- package/src/assets/web-panel/assets/index-P4FXZJqI.js +0 -1
|
@@ -33,6 +33,7 @@ import {
|
|
|
33
33
|
import { deriveSkillCandidateTenantKey } from "./skill-candidate-registry.js";
|
|
34
34
|
import { deriveSkillReleaseTenantKey } from "./skill-release-registry.js";
|
|
35
35
|
import { captureSkillReleaseOperationReader } from "./evolution-ledger-ports.js";
|
|
36
|
+
import { captureRrsiRegistryRuntimePolicy } from "./rrsi-registry-runtime-policy.js";
|
|
36
37
|
import {
|
|
37
38
|
snapshotRrsiData,
|
|
38
39
|
rrsiExact,
|
|
@@ -129,7 +130,13 @@ function assertPrivateParent(expected) {
|
|
|
129
130
|
assertDirectory(expected);
|
|
130
131
|
const permission = inspectPrivatePath(expected.path);
|
|
131
132
|
if (permission?.ok !== true || permission.exists !== true)
|
|
132
|
-
hold(
|
|
133
|
+
hold(
|
|
134
|
+
"provisioning parent must have verified owner-only permissions",
|
|
135
|
+
new Error(
|
|
136
|
+
permission?.error ||
|
|
137
|
+
"owner-only permission inspection was not successful",
|
|
138
|
+
),
|
|
139
|
+
);
|
|
133
140
|
assertDirectory(expected);
|
|
134
141
|
}
|
|
135
142
|
function syncDirectory(value) {
|
|
@@ -950,20 +957,32 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
950
957
|
const policy = Object.freeze({
|
|
951
958
|
descriptor,
|
|
952
959
|
bindComponent(input) {
|
|
953
|
-
|
|
954
|
-
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
|
|
960
|
+
if (
|
|
961
|
+
!input ||
|
|
962
|
+
isProxy(input) ||
|
|
963
|
+
Object.getPrototypeOf(input) !== Object.prototype
|
|
964
|
+
)
|
|
965
|
+
hold("Registry component binding requires plain own fields");
|
|
966
|
+
const names = ["operationId", "component"];
|
|
967
|
+
if (Object.hasOwn(input ?? {}, "runtimePolicy"))
|
|
968
|
+
names.push("runtimePolicy");
|
|
969
|
+
const request = ownOptions(input, names);
|
|
959
970
|
rrsiId(request.operationId, "provision operation ID");
|
|
960
971
|
if (!["candidate", "release"].includes(request.component))
|
|
961
972
|
rrsiFail("Registry binding component is invalid");
|
|
962
973
|
// Do not take a policy operation lock or repair any Registry path. The
|
|
963
974
|
// retained head and both physical markers bookend this read-only open.
|
|
964
|
-
let original
|
|
975
|
+
let original,
|
|
976
|
+
runtime = null;
|
|
977
|
+
if (request.runtimePolicy !== undefined) {
|
|
978
|
+
runtime = captureRrsiRegistryRuntimePolicy(request.runtimePolicy);
|
|
979
|
+
if (!runtime.matchesPolicy(policy))
|
|
980
|
+
hold("runtime attachment requires the original store policy");
|
|
981
|
+
}
|
|
965
982
|
try {
|
|
966
|
-
original = status(load(), request.operationId
|
|
983
|
+
original = status(load(), request.operationId, {
|
|
984
|
+
boundaryOnly: runtime !== null,
|
|
985
|
+
});
|
|
967
986
|
} catch (cause) {
|
|
968
987
|
if (["ENOENT", "ENOTDIR"].includes(cause?.code))
|
|
969
988
|
hold("an authenticated Registry binding boundary is missing", cause);
|
|
@@ -976,6 +995,7 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
976
995
|
const store = prepared[component];
|
|
977
996
|
const peer =
|
|
978
997
|
prepared[component === "candidate" ? "release" : "candidate"];
|
|
998
|
+
const runtimeOriginal = runtime?.read(request.operationId) ?? null;
|
|
979
999
|
const componentDescriptor = freezeRrsiData({
|
|
980
1000
|
schema: "chainlesschain.rrsi-registry-component-binding/v1",
|
|
981
1001
|
operationId: request.operationId,
|
|
@@ -986,7 +1006,10 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
986
1006
|
journalIdentity: prepared.journalIdentity,
|
|
987
1007
|
committedRecordDigest: original.records.at(-1).recordDigest,
|
|
988
1008
|
writerFloor: RRSI_REGISTRY_STORE_WRITER_FLOOR,
|
|
989
|
-
registryRuntimeMode:
|
|
1009
|
+
registryRuntimeMode: runtime
|
|
1010
|
+
? "authenticated-empty-read-only"
|
|
1011
|
+
: "uninitialized-read-only",
|
|
1012
|
+
runtimeRecordDigest: runtimeOriginal?.committedRecordDigest ?? null,
|
|
990
1013
|
persistentStoreIdentityAuthenticated: true,
|
|
991
1014
|
originCutoverAuthenticated: false,
|
|
992
1015
|
originClassificationAvailable: false,
|
|
@@ -994,7 +1017,8 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
994
1017
|
});
|
|
995
1018
|
function recheckUnchecked() {
|
|
996
1019
|
// Invalid existing physical state needs no journal recovery or locks.
|
|
997
|
-
|
|
1020
|
+
if (runtime) runtime.read(request.operationId);
|
|
1021
|
+
else assertLayout(prepared, [true, true]);
|
|
998
1022
|
if (!equal(markerProof(prepared, true), original.markers))
|
|
999
1023
|
hold("Registry marker identity changed after capture");
|
|
1000
1024
|
const result = status(load(), request.operationId, {
|
|
@@ -1007,9 +1031,17 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
1007
1031
|
!equal(result.records, original.records)
|
|
1008
1032
|
)
|
|
1009
1033
|
hold("Registry component binding changed after capture");
|
|
1010
|
-
//
|
|
1011
|
-
//
|
|
1012
|
-
|
|
1034
|
+
// An explicit runtime attachment authenticates only its empty layout.
|
|
1035
|
+
// Unknown content remains HOLD, with no adoption or cleanup.
|
|
1036
|
+
if (runtime) {
|
|
1037
|
+
const current = runtime.read(request.operationId);
|
|
1038
|
+
if (
|
|
1039
|
+
!equal(current.directories, runtimeOriginal.directories) ||
|
|
1040
|
+
current.committedRecordDigest !==
|
|
1041
|
+
runtimeOriginal.committedRecordDigest
|
|
1042
|
+
)
|
|
1043
|
+
hold("runtime attachment changed after component capture");
|
|
1044
|
+
} else assertLayout(prepared, [true, true]);
|
|
1013
1045
|
if (!equal(markerProof(prepared, true), original.markers))
|
|
1014
1046
|
hold("Registry markers changed during uninitialized inventory read");
|
|
1015
1047
|
if (!equal(result.currentHead, headData(methods.verify())))
|
|
@@ -1047,10 +1079,15 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
1047
1079
|
identity: original.markers[component].identity,
|
|
1048
1080
|
marker: markerFor(prepared, component),
|
|
1049
1081
|
}),
|
|
1082
|
+
runtimeDirectories:
|
|
1083
|
+
component === "release"
|
|
1084
|
+
? (runtimeOriginal?.directories ?? null)
|
|
1085
|
+
: null,
|
|
1050
1086
|
recheck,
|
|
1051
1087
|
recheckForOpen() {
|
|
1052
1088
|
try {
|
|
1053
1089
|
assertPrivateParent(prepared.parent);
|
|
1090
|
+
runtime?.verifyPrivateDirectories(request.operationId);
|
|
1054
1091
|
return recheck();
|
|
1055
1092
|
} catch (cause) {
|
|
1056
1093
|
if (["ENOENT", "ENOTDIR"].includes(cause?.code))
|
|
@@ -1084,7 +1121,7 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
1084
1121
|
},
|
|
1085
1122
|
assertMutationAllowed() {
|
|
1086
1123
|
hold(
|
|
1087
|
-
"Registry origin admission and
|
|
1124
|
+
"Registry origin admission and business mutation are not implemented",
|
|
1088
1125
|
);
|
|
1089
1126
|
},
|
|
1090
1127
|
}),
|
|
@@ -1145,6 +1182,49 @@ export function createRrsiRegistryStorePolicy(input) {
|
|
|
1145
1182
|
matchesArtifactPorts: (value) => value === options.artifactPorts,
|
|
1146
1183
|
matchesArtifactResolver: (value) => value === resolver,
|
|
1147
1184
|
read: policy.read,
|
|
1185
|
+
captureCommittedBoundary(operationId) {
|
|
1186
|
+
rrsiId(operationId, "provision operation ID");
|
|
1187
|
+
try {
|
|
1188
|
+
const state = load();
|
|
1189
|
+
const result = status(state, operationId, {
|
|
1190
|
+
boundaryOnly: true,
|
|
1191
|
+
verifyPermissions: false,
|
|
1192
|
+
});
|
|
1193
|
+
if (!result.freshPhysicalPairProvisioningCommitted)
|
|
1194
|
+
hold("runtime requires committed store provisioning");
|
|
1195
|
+
return Object.freeze({
|
|
1196
|
+
snapshot: result,
|
|
1197
|
+
recheck() {
|
|
1198
|
+
// Reuse only this authenticated immutable history at its exact
|
|
1199
|
+
// captured head. No caller-supplied state or newer head is used.
|
|
1200
|
+
try {
|
|
1201
|
+
return status(state, operationId, {
|
|
1202
|
+
boundaryOnly: true,
|
|
1203
|
+
verifyPermissions: false,
|
|
1204
|
+
});
|
|
1205
|
+
} catch (cause) {
|
|
1206
|
+
if (["ENOENT", "ENOTDIR"].includes(cause?.code))
|
|
1207
|
+
hold("an authenticated store boundary is missing", cause);
|
|
1208
|
+
throw cause;
|
|
1209
|
+
}
|
|
1210
|
+
},
|
|
1211
|
+
});
|
|
1212
|
+
} catch (cause) {
|
|
1213
|
+
if (["ENOENT", "ENOTDIR"].includes(cause?.code))
|
|
1214
|
+
hold("an authenticated store boundary is missing", cause);
|
|
1215
|
+
throw cause;
|
|
1216
|
+
}
|
|
1217
|
+
},
|
|
1218
|
+
maintain(operation) {
|
|
1219
|
+
if (typeof operation !== "function" || isProxy(operation))
|
|
1220
|
+
hold("runtime maintenance requires an original synchronous callback");
|
|
1221
|
+
return locked((assertOwnership) => {
|
|
1222
|
+
const result = operation(assertOwnership);
|
|
1223
|
+
if (result && typeof result.then === "function")
|
|
1224
|
+
hold("runtime maintenance cannot return a Promise");
|
|
1225
|
+
return result;
|
|
1226
|
+
});
|
|
1227
|
+
},
|
|
1148
1228
|
}),
|
|
1149
1229
|
);
|
|
1150
1230
|
return policy;
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
/** Signed anchor declarations. A valid signature is never tenant authority. */
|
|
2
|
+
import { createHash, createPublicKey, verify } from "node:crypto";
|
|
3
|
+
import {
|
|
4
|
+
rrsiCanonical,
|
|
5
|
+
rrsiHash,
|
|
6
|
+
rrsiExact,
|
|
7
|
+
rrsiId,
|
|
8
|
+
rrsiDigest,
|
|
9
|
+
rrsiInteger,
|
|
10
|
+
rrsiEnvelope,
|
|
11
|
+
verifyRrsiEnvelope,
|
|
12
|
+
snapshotRrsiData,
|
|
13
|
+
rrsiFail,
|
|
14
|
+
} from "./rrsi-data.js";
|
|
15
|
+
|
|
16
|
+
export const RRSI_TENANT_INDEX_ANCHOR_SCHEMA =
|
|
17
|
+
"chainlesschain.rrsi-tenant-index-anchor/v1";
|
|
18
|
+
export const RRSI_TENANT_INDEX_ANCHOR_SIGNATURE_SCHEMA =
|
|
19
|
+
"chainlesschain.rrsi-tenant-index-anchor-signature-check/v1";
|
|
20
|
+
export const RRSI_TENANT_INDEX_ANCHOR_HOLD_CODE =
|
|
21
|
+
"CC_RRSI_TENANT_INDEX_ANCHOR_HOLD";
|
|
22
|
+
const SIGNATURE_DOMAIN = "chainlesschain.rrsi-tenant-index-anchor-signature/v1";
|
|
23
|
+
const INPUT_KEYS = [
|
|
24
|
+
"deploymentId",
|
|
25
|
+
"tenantId",
|
|
26
|
+
"routingScope",
|
|
27
|
+
"indexId",
|
|
28
|
+
"ledgerIdentity",
|
|
29
|
+
"artifactScope",
|
|
30
|
+
"storageGraphDigest",
|
|
31
|
+
"rootPublicKeyDigest",
|
|
32
|
+
"revision",
|
|
33
|
+
"previousAnchorDigest",
|
|
34
|
+
"checkpoint",
|
|
35
|
+
"restrictionHistory",
|
|
36
|
+
];
|
|
37
|
+
const sha = (bytes) =>
|
|
38
|
+
`sha256:${createHash("sha256").update(bytes).digest("hex")}`;
|
|
39
|
+
const same = (a, b) => rrsiCanonical(a) === rrsiCanonical(b);
|
|
40
|
+
function hold(message) {
|
|
41
|
+
rrsiFail(message, RRSI_TENANT_INDEX_ANCHOR_HOLD_CODE);
|
|
42
|
+
}
|
|
43
|
+
function ledgerId(value, label) {
|
|
44
|
+
if (
|
|
45
|
+
typeof value !== "string" ||
|
|
46
|
+
!/^[A-Za-z0-9][A-Za-z0-9._:/-]{0,159}$/u.test(value)
|
|
47
|
+
)
|
|
48
|
+
hold(`${label} is not a Ledger identifier`);
|
|
49
|
+
}
|
|
50
|
+
function journalIdentity(value) {
|
|
51
|
+
rrsiExact(
|
|
52
|
+
value,
|
|
53
|
+
["ledgerId", "identityDigest", "epoch"],
|
|
54
|
+
"anchor journal identity",
|
|
55
|
+
);
|
|
56
|
+
ledgerId(value.ledgerId, "ledgerId");
|
|
57
|
+
ledgerId(value.epoch, "epoch");
|
|
58
|
+
rrsiDigest(value.identityDigest, "identity digest");
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export function buildRrsiTenantIndexAnchor(input) {
|
|
62
|
+
const value = snapshotRrsiData(input);
|
|
63
|
+
rrsiExact(value, INPUT_KEYS, "tenant index anchor input");
|
|
64
|
+
rrsiId(value.deploymentId, "deployment ID");
|
|
65
|
+
rrsiId(value.tenantId, "tenant ID");
|
|
66
|
+
if (!["installation", "shared-tenant-authority"].includes(value.routingScope))
|
|
67
|
+
hold("anchor routing scope must be explicit");
|
|
68
|
+
const expectedIndex = `rrsi-text.${rrsiHash("chainlesschain.rrsi-observed-text-index/v1", value.tenantId).slice(7)}`;
|
|
69
|
+
if (value.indexId !== expectedIndex)
|
|
70
|
+
hold("anchor index ID must derive only from tenant");
|
|
71
|
+
journalIdentity(value.ledgerIdentity);
|
|
72
|
+
rrsiExact(
|
|
73
|
+
value.artifactScope,
|
|
74
|
+
["artifactTenantId", "audience", "purpose"],
|
|
75
|
+
"anchor artifact scope",
|
|
76
|
+
);
|
|
77
|
+
for (const [name, entry] of Object.entries(value.artifactScope))
|
|
78
|
+
rrsiId(entry, name);
|
|
79
|
+
if (value.artifactScope.purpose !== "evolution-ledger")
|
|
80
|
+
hold("anchor requires original Ledger retention purpose");
|
|
81
|
+
rrsiDigest(value.storageGraphDigest, "storage graph digest");
|
|
82
|
+
rrsiDigest(value.rootPublicKeyDigest, "declared root public key digest");
|
|
83
|
+
rrsiInteger(value.revision, "anchor revision", 1, 2 ** 31 - 1);
|
|
84
|
+
if (value.revision === 1) {
|
|
85
|
+
if (value.previousAnchorDigest !== null)
|
|
86
|
+
hold("first anchor must not claim a predecessor");
|
|
87
|
+
} else rrsiDigest(value.previousAnchorDigest, "previous anchor digest");
|
|
88
|
+
rrsiExact(
|
|
89
|
+
value.checkpoint,
|
|
90
|
+
["ledgerId", "identityDigest", "epoch", "sequence", "headDigest"],
|
|
91
|
+
"anchor checkpoint",
|
|
92
|
+
);
|
|
93
|
+
const checkpointIdentity = Object.fromEntries(
|
|
94
|
+
["ledgerId", "identityDigest", "epoch"].map((name) => [
|
|
95
|
+
name,
|
|
96
|
+
value.checkpoint[name],
|
|
97
|
+
]),
|
|
98
|
+
);
|
|
99
|
+
if (!same(checkpointIdentity, value.ledgerIdentity))
|
|
100
|
+
hold("anchor checkpoint belongs to another journal");
|
|
101
|
+
rrsiInteger(value.checkpoint.sequence, "checkpoint sequence", 0);
|
|
102
|
+
rrsiDigest(value.checkpoint.headDigest, "checkpoint head digest");
|
|
103
|
+
rrsiExact(
|
|
104
|
+
value.restrictionHistory,
|
|
105
|
+
["recordCount", "tailRecordDigest", "restrictionsDigest"],
|
|
106
|
+
"anchor restriction history",
|
|
107
|
+
);
|
|
108
|
+
rrsiInteger(
|
|
109
|
+
value.restrictionHistory.recordCount,
|
|
110
|
+
"restriction record count",
|
|
111
|
+
0,
|
|
112
|
+
256,
|
|
113
|
+
);
|
|
114
|
+
if (value.restrictionHistory.recordCount > value.checkpoint.sequence)
|
|
115
|
+
hold("restriction count exceeds the declared journal checkpoint");
|
|
116
|
+
if (value.restrictionHistory.recordCount === 0) {
|
|
117
|
+
if (value.restrictionHistory.tailRecordDigest !== null)
|
|
118
|
+
hold("empty restriction history must have no tail");
|
|
119
|
+
} else
|
|
120
|
+
rrsiDigest(
|
|
121
|
+
value.restrictionHistory.tailRecordDigest,
|
|
122
|
+
"restriction tail digest",
|
|
123
|
+
);
|
|
124
|
+
rrsiDigest(
|
|
125
|
+
value.restrictionHistory.restrictionsDigest,
|
|
126
|
+
"restriction set digest",
|
|
127
|
+
);
|
|
128
|
+
return rrsiEnvelope(RRSI_TENANT_INDEX_ANCHOR_SCHEMA, "anchorDigest", value);
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
export function verifyRrsiTenantIndexAnchor(input) {
|
|
132
|
+
return verifyRrsiEnvelope(
|
|
133
|
+
input,
|
|
134
|
+
RRSI_TENANT_INDEX_ANCHOR_SCHEMA,
|
|
135
|
+
"anchorDigest",
|
|
136
|
+
INPUT_KEYS,
|
|
137
|
+
buildRrsiTenantIndexAnchor,
|
|
138
|
+
);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
/** Exact domain-separated bytes for an external signer; no signer default. */
|
|
142
|
+
export function serializeRrsiTenantIndexAnchorSignatureMessage(anchor) {
|
|
143
|
+
const checked = verifyRrsiTenantIndexAnchor(anchor);
|
|
144
|
+
return Buffer.from(`${SIGNATURE_DOMAIN}\0${rrsiCanonical(checked)}`, "utf8");
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
/**
|
|
148
|
+
* Mathematical verification against an explicitly supplied public key only.
|
|
149
|
+
* This deliberately creates no trusted-root brand, pin store or routing grant.
|
|
150
|
+
*/
|
|
151
|
+
export function verifyRrsiTenantIndexAnchorSignature(input) {
|
|
152
|
+
const value = snapshotRrsiData(input);
|
|
153
|
+
rrsiExact(
|
|
154
|
+
value,
|
|
155
|
+
["anchor", "publicKeySpki", "signature"],
|
|
156
|
+
"anchor signature input",
|
|
157
|
+
);
|
|
158
|
+
const anchor = verifyRrsiTenantIndexAnchor(value.anchor);
|
|
159
|
+
if (
|
|
160
|
+
typeof value.publicKeySpki !== "string" ||
|
|
161
|
+
value.publicKeySpki.length > 128
|
|
162
|
+
)
|
|
163
|
+
hold("anchor public key must be bounded canonical Ed25519 SPKI");
|
|
164
|
+
const publicBytes = Buffer.from(value.publicKeySpki, "base64url");
|
|
165
|
+
if (
|
|
166
|
+
publicBytes.length !== 44 ||
|
|
167
|
+
publicBytes.toString("base64url") !== value.publicKeySpki
|
|
168
|
+
)
|
|
169
|
+
hold("anchor public key SPKI encoding differs");
|
|
170
|
+
let publicKey;
|
|
171
|
+
try {
|
|
172
|
+
publicKey = createPublicKey({
|
|
173
|
+
key: publicBytes,
|
|
174
|
+
format: "der",
|
|
175
|
+
type: "spki",
|
|
176
|
+
});
|
|
177
|
+
} catch {
|
|
178
|
+
hold("anchor public key SPKI cannot be parsed");
|
|
179
|
+
}
|
|
180
|
+
if (
|
|
181
|
+
publicKey.asymmetricKeyType !== "ed25519" ||
|
|
182
|
+
!publicKey.export({ format: "der", type: "spki" }).equals(publicBytes)
|
|
183
|
+
)
|
|
184
|
+
hold("anchor public key must be exact Ed25519 SPKI");
|
|
185
|
+
if (sha(publicBytes) !== anchor.rootPublicKeyDigest)
|
|
186
|
+
hold("anchor public key differs from the declared root digest");
|
|
187
|
+
if (typeof value.signature !== "string" || value.signature.length !== 86)
|
|
188
|
+
hold("anchor signature must be bounded canonical Ed25519 bytes");
|
|
189
|
+
const signatureBytes = Buffer.from(value.signature, "base64url");
|
|
190
|
+
if (
|
|
191
|
+
signatureBytes.length !== 64 ||
|
|
192
|
+
signatureBytes.toString("base64url") !== value.signature
|
|
193
|
+
)
|
|
194
|
+
hold("anchor signature encoding differs");
|
|
195
|
+
if (
|
|
196
|
+
!verify(
|
|
197
|
+
null,
|
|
198
|
+
serializeRrsiTenantIndexAnchorSignatureMessage(anchor),
|
|
199
|
+
publicKey,
|
|
200
|
+
signatureBytes,
|
|
201
|
+
)
|
|
202
|
+
)
|
|
203
|
+
hold("anchor signature was rejected");
|
|
204
|
+
return rrsiEnvelope(
|
|
205
|
+
RRSI_TENANT_INDEX_ANCHOR_SIGNATURE_SCHEMA,
|
|
206
|
+
"signatureCheckDigest",
|
|
207
|
+
{
|
|
208
|
+
anchorDigest: anchor.anchorDigest,
|
|
209
|
+
publicKeyDigest: anchor.rootPublicKeyDigest,
|
|
210
|
+
declaredDeploymentId: anchor.deploymentId,
|
|
211
|
+
declaredTenantId: anchor.tenantId,
|
|
212
|
+
declaredRoutingScope: anchor.routingScope,
|
|
213
|
+
signatureVerifiedRelativeToKey: true,
|
|
214
|
+
rootAuthorityVerified: false,
|
|
215
|
+
routingPinVerified: false,
|
|
216
|
+
historyTransferVerified: false,
|
|
217
|
+
tenantWideIndexAuthorityVerified: false,
|
|
218
|
+
generationProvenanceVerified: false,
|
|
219
|
+
grantsMutationOrPromotionAuthority: false,
|
|
220
|
+
decision: "HOLD",
|
|
221
|
+
},
|
|
222
|
+
);
|
|
223
|
+
}
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
/** Real local history prefixes. Installation/root/routing authority remains HOLD. */
|
|
2
|
+
import { isProxy } from "node:util/types";
|
|
3
|
+
import { captureRrsiObservedTextIndex } from "./rrsi-observed-text-index.js";
|
|
4
|
+
import { verifyRrsiTenantIndexAnchorSignature } from "./rrsi-tenant-index-anchor-contracts.js";
|
|
5
|
+
import { rrsiCanonical, rrsiEnvelope, snapshotRrsiData } from "./rrsi-data.js";
|
|
6
|
+
|
|
7
|
+
export const RRSI_TENANT_INDEX_ANCHOR_HISTORY_HOLD_CODE =
|
|
8
|
+
"CC_RRSI_ANCHOR_HISTORY_HOLD";
|
|
9
|
+
const same = (a, b) => rrsiCanonical(a) === rrsiCanonical(b);
|
|
10
|
+
const FIXED_KEYS = [
|
|
11
|
+
"deploymentId",
|
|
12
|
+
"tenantId",
|
|
13
|
+
"routingScope",
|
|
14
|
+
"indexId",
|
|
15
|
+
"ledgerIdentity",
|
|
16
|
+
"artifactScope",
|
|
17
|
+
"storageGraphDigest",
|
|
18
|
+
"rootPublicKeyDigest",
|
|
19
|
+
];
|
|
20
|
+
function hold(message, cause) {
|
|
21
|
+
throw Object.assign(new Error(message, cause ? { cause } : undefined), {
|
|
22
|
+
code: RRSI_TENANT_INDEX_ANCHOR_HISTORY_HOLD_CODE,
|
|
23
|
+
});
|
|
24
|
+
}
|
|
25
|
+
function guard(operation) {
|
|
26
|
+
try {
|
|
27
|
+
return operation();
|
|
28
|
+
} catch (cause) {
|
|
29
|
+
if (cause?.code === RRSI_TENANT_INDEX_ANCHOR_HISTORY_HOLD_CODE) throw cause;
|
|
30
|
+
hold(
|
|
31
|
+
"anchor history could not authenticate the original local prefix",
|
|
32
|
+
cause,
|
|
33
|
+
);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
function own(value, names) {
|
|
37
|
+
if (
|
|
38
|
+
!value ||
|
|
39
|
+
isProxy(value) ||
|
|
40
|
+
Object.getPrototypeOf(value) !== Object.prototype ||
|
|
41
|
+
Reflect.ownKeys(value).length !== names.length
|
|
42
|
+
)
|
|
43
|
+
hold("anchor history requires exact plain own fields");
|
|
44
|
+
return Object.fromEntries(
|
|
45
|
+
names.map((name) => {
|
|
46
|
+
const field = Object.getOwnPropertyDescriptor(value, name);
|
|
47
|
+
if (!field?.enumerable || !("value" in field))
|
|
48
|
+
hold("anchor history cannot use accessors");
|
|
49
|
+
return [name, field.value];
|
|
50
|
+
}),
|
|
51
|
+
);
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
export function inspectRrsiTenantIndexHistory(input) {
|
|
55
|
+
return guard(() => {
|
|
56
|
+
const request = own(input, ["observedTextIndex"]);
|
|
57
|
+
const captured = captureRrsiObservedTextIndex(request.observedTextIndex);
|
|
58
|
+
const history = captured.captureHistoryCheckpoints({ checkpoints: [] });
|
|
59
|
+
history.recheck();
|
|
60
|
+
return history.snapshot;
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
export function verifyRrsiTenantIndexAnchorHistory(input) {
|
|
65
|
+
return guard(() => {
|
|
66
|
+
const request = own(input, ["observedTextIndex", "previous", "current"]);
|
|
67
|
+
const index = captureRrsiObservedTextIndex(request.observedTextIndex);
|
|
68
|
+
const data = snapshotRrsiData({
|
|
69
|
+
previous: request.previous,
|
|
70
|
+
current: request.current,
|
|
71
|
+
});
|
|
72
|
+
verifyRrsiTenantIndexAnchorSignature(data.previous);
|
|
73
|
+
verifyRrsiTenantIndexAnchorSignature(data.current);
|
|
74
|
+
const previous = data.previous.anchor,
|
|
75
|
+
current = data.current.anchor;
|
|
76
|
+
if (
|
|
77
|
+
previous.routingScope !== "installation" ||
|
|
78
|
+
current.routingScope !== "installation"
|
|
79
|
+
)
|
|
80
|
+
hold("local history verification requires installation scope");
|
|
81
|
+
if (data.previous.publicKeySpki !== data.current.publicKeySpki)
|
|
82
|
+
hold("local anchor history cannot change root key");
|
|
83
|
+
for (const key of FIXED_KEYS)
|
|
84
|
+
if (!same(previous[key], current[key]))
|
|
85
|
+
hold(`local anchor history cannot change ${key}`);
|
|
86
|
+
if (current.revision === previous.revision) {
|
|
87
|
+
if (current.anchorDigest !== previous.anchorDigest)
|
|
88
|
+
hold("same revision has a different history anchor");
|
|
89
|
+
} else if (
|
|
90
|
+
current.revision !== previous.revision + 1 ||
|
|
91
|
+
current.previousAnchorDigest !== previous.anchorDigest
|
|
92
|
+
)
|
|
93
|
+
hold("local history anchor must be the exact declared successor");
|
|
94
|
+
for (const anchor of [previous, current]) {
|
|
95
|
+
if (
|
|
96
|
+
anchor.tenantId !== index.descriptor.tenantId ||
|
|
97
|
+
anchor.indexId !== index.descriptor.indexId ||
|
|
98
|
+
!same(anchor.ledgerIdentity, index.descriptor.ledgerIdentity) ||
|
|
99
|
+
!same(anchor.artifactScope, {
|
|
100
|
+
artifactTenantId: index.descriptor.artifactTenantId,
|
|
101
|
+
audience: index.descriptor.audience,
|
|
102
|
+
purpose: index.descriptor.purpose,
|
|
103
|
+
})
|
|
104
|
+
)
|
|
105
|
+
hold("history anchor differs from the original observed index scope");
|
|
106
|
+
}
|
|
107
|
+
if (previous.checkpoint.sequence > current.checkpoint.sequence)
|
|
108
|
+
hold("local history anchor cannot move its checkpoint backward");
|
|
109
|
+
const history = index.captureHistoryCheckpoints({
|
|
110
|
+
checkpoints: [previous.checkpoint, current.checkpoint],
|
|
111
|
+
});
|
|
112
|
+
const snapshot = history.snapshot;
|
|
113
|
+
if (!same(current.checkpoint, snapshot.current.checkpoint))
|
|
114
|
+
hold("current anchor is not the actual captured journal head");
|
|
115
|
+
for (const [anchor, prefix] of [
|
|
116
|
+
[previous, snapshot.prefixes[0]],
|
|
117
|
+
[current, snapshot.prefixes[1]],
|
|
118
|
+
])
|
|
119
|
+
if (!same(anchor.restrictionHistory, prefix.restrictionHistory))
|
|
120
|
+
hold(
|
|
121
|
+
"anchor restriction declaration differs from retained prefix history",
|
|
122
|
+
);
|
|
123
|
+
history.recheck();
|
|
124
|
+
return rrsiEnvelope(
|
|
125
|
+
"chainlesschain.rrsi-tenant-index-anchor-history-check/v1",
|
|
126
|
+
"historyCheckDigest",
|
|
127
|
+
{
|
|
128
|
+
previousAnchorDigest: previous.anchorDigest,
|
|
129
|
+
currentAnchorDigest: current.anchorDigest,
|
|
130
|
+
indexDescriptorDigest: snapshot.indexDescriptorDigest,
|
|
131
|
+
localCompositionDigest: snapshot.localCompositionDigest,
|
|
132
|
+
artifactStoreDirectoryBoundaryDigest:
|
|
133
|
+
snapshot.artifactStoreDirectoryBoundaryDigest,
|
|
134
|
+
artifactStoreDirectoryBoundaryRechecked: true,
|
|
135
|
+
artifactStoreBoundaryScope: "root-and-files-directories",
|
|
136
|
+
previous: snapshot.prefixes[0],
|
|
137
|
+
current: snapshot.current,
|
|
138
|
+
signaturesVerifiedRelativeToExplicitKey: true,
|
|
139
|
+
localJournalPrefixVerified: true,
|
|
140
|
+
localRestrictionPrefixVerified: true,
|
|
141
|
+
localRetainedHistoryReplayed: true,
|
|
142
|
+
selectedContextOnly: true,
|
|
143
|
+
storageGraphDigestVerified: false,
|
|
144
|
+
rootAuthorityVerified: false,
|
|
145
|
+
installationBindingSignatureVerified: false,
|
|
146
|
+
routingPinVerified: false,
|
|
147
|
+
crossProcessRollbackProtectionVerified: false,
|
|
148
|
+
historyTransferVerified: false,
|
|
149
|
+
originCutoverAuthenticated: false,
|
|
150
|
+
tenantWideIndexAuthorityVerified: false,
|
|
151
|
+
generationProvenanceVerified: false,
|
|
152
|
+
grantsMutationOrPromotionAuthority: false,
|
|
153
|
+
decision: "HOLD",
|
|
154
|
+
},
|
|
155
|
+
);
|
|
156
|
+
});
|
|
157
|
+
}
|
|
@@ -2775,7 +2775,9 @@ export class SkillReleaseRegistry {
|
|
|
2775
2775
|
// Authenticate the original port object before reading any caller method.
|
|
2776
2776
|
this.#storeBinding.assertTransactionLedger(transactionLedger);
|
|
2777
2777
|
this.#storeBinding.recheckForOpen();
|
|
2778
|
-
this.#runtimeMode =
|
|
2778
|
+
this.#runtimeMode = this.#storeBinding.runtimeDirectories
|
|
2779
|
+
? "authenticated-empty-read-only"
|
|
2780
|
+
: "uninitialized";
|
|
2779
2781
|
} else assertOutsideRrsiRegistryNamespace(requestedBase);
|
|
2780
2782
|
if (
|
|
2781
2783
|
!transactionLedger ||
|
|
@@ -2832,7 +2834,8 @@ export class SkillReleaseRegistry {
|
|
|
2832
2834
|
this.#rootIdentity = this.#boundaries.tenantRoot.identity;
|
|
2833
2835
|
this.#markerPath = path.join(this.rootDir, TENANT_MARKER_FILE);
|
|
2834
2836
|
this.#markerIdentity = this.#storeBinding.marker.identity;
|
|
2835
|
-
this.#directories =
|
|
2837
|
+
this.#directories =
|
|
2838
|
+
this.#storeBinding.runtimeDirectories ?? deepFreeze({});
|
|
2836
2839
|
this.#assertBoundary();
|
|
2837
2840
|
} else {
|
|
2838
2841
|
const base = this.#initializeDirectory(requestedBase, {
|
|
@@ -3972,7 +3975,11 @@ export class SkillReleaseRegistry {
|
|
|
3972
3975
|
|
|
3973
3976
|
#readRelease(releaseDigest) {
|
|
3974
3977
|
const expected = digest(releaseDigest, "releaseDigest");
|
|
3975
|
-
if (
|
|
3978
|
+
if (
|
|
3979
|
+
["uninitialized", "authenticated-empty-read-only"].includes(
|
|
3980
|
+
this.#runtimeMode,
|
|
3981
|
+
)
|
|
3982
|
+
) {
|
|
3976
3983
|
this.#assertBoundary();
|
|
3977
3984
|
throw failure("SKILL_RELEASE_NOT_FOUND", "release was not found");
|
|
3978
3985
|
}
|
|
@@ -4011,7 +4018,11 @@ export class SkillReleaseRegistry {
|
|
|
4011
4018
|
|
|
4012
4019
|
#readStateRaw(name) {
|
|
4013
4020
|
const normalizedName = skillName(name);
|
|
4014
|
-
if (
|
|
4021
|
+
if (
|
|
4022
|
+
["uninitialized", "authenticated-empty-read-only"].includes(
|
|
4023
|
+
this.#runtimeMode,
|
|
4024
|
+
)
|
|
4025
|
+
) {
|
|
4015
4026
|
this.#assertBoundary();
|
|
4016
4027
|
return initialState(normalizedName, this.tenantId);
|
|
4017
4028
|
}
|
|
@@ -4190,7 +4201,11 @@ export class SkillReleaseRegistry {
|
|
|
4190
4201
|
|
|
4191
4202
|
#readInventory() {
|
|
4192
4203
|
this.#assertBoundary();
|
|
4193
|
-
if (
|
|
4204
|
+
if (
|
|
4205
|
+
["uninitialized", "authenticated-empty-read-only"].includes(
|
|
4206
|
+
this.#runtimeMode,
|
|
4207
|
+
)
|
|
4208
|
+
)
|
|
4194
4209
|
return deepFreeze({ active: [], releases: [] });
|
|
4195
4210
|
const releasePattern = /^[a-f0-9]{64}\.json$/u;
|
|
4196
4211
|
const statePattern = /^[a-z][a-z0-9]*(?:-[a-z0-9]+)*\.json$/u;
|