chainlesschain 0.166.65 → 0.166.69
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 +20 -12
- package/package.json +4 -4
- package/src/assets/web-panel/assets/{AIOps-Byz17CTN.js → AIOps-FhevRfL6.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-C5LiW2-J.js → ActionButton-rOeOykx5.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-D1INcvZF.js → Analytics-BK_wYlfz.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-DZzHO1VV.js → AppLayout-_2cCtZKV.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-WfYQL6Ia.js → Artifacts-D5MSvVzk.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-DohBoGWO.js → Audit-yd-Ah-A3.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-Chtk-Hde.js → BackgroundAgents-yCaw_Gu_.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-B813PuMz.js → Backup-G3ADD4N-.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-DaDdWWgK.js → BaseInput-ByDhkLbF.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-D4pJ6oZ7.js → Chat-BMrc7qjz.js} +4 -4
- package/src/assets/web-panel/assets/ChatBubbleRenderer-nA7n0I6S.js +1 -0
- package/src/assets/web-panel/assets/{Checkbox-Clo9TvO6.js → Checkbox-BHYgyZWA.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-uejLg8Ih.js → Codegen-DJfcy0jC.js} +1 -1
- package/src/assets/web-panel/assets/{Col-B7nbx-iJ.js → Col-C27zROxc.js} +1 -1
- package/src/assets/web-panel/assets/{Community-FEyjPK1j.js → Community-CuS5tq_1.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-B6Fk0Kn6.js → Compact-BrYJNe7Q.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-BQG8goUl.js → Compliance-8hfahYHT.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-CbBeEfHp.js → Cowork-DdE0n2lp.js} +2 -2
- package/src/assets/web-panel/assets/{Cron-DPzlFcEZ.js → Cron-CUq3aSiX.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-B8pWJrbg.js → Crosschain-BM4XSPWG.js} +1 -1
- package/src/assets/web-panel/assets/{DID-gGQHUlFN.js → DID-CdaBY57N.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-C2TMFHrn.js → Dashboard-Cwtd52So.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-BVPxGbll.js → Dropdown-BvlObh6U.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-CNPxs0hd.js → EmailListRenderer-e3fLhjnX.js} +1 -1
- package/src/assets/web-panel/assets/{EvolutionSettings-_XTiB7q1.js → EvolutionSettings-CTtk1Zo8.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-UyE3VWtI.js → FamilyGuardDashboard-BpPJUnCU.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-CLt6FHK-.js → Federation-vzjZ6_nQ.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-CdNQPRPw.js → FormItemContext-DEDNLhkE.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BJ0AMhrh.js → GenericCardRenderer-DEl2Te5f.js} +1 -1
- package/src/assets/web-panel/assets/{Git-CQnvMfOM.js → Git-BzsYQnCq.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-deYsHC-o.js → Governance-zxJs6Y8s.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-qaSck43z.js → Inference-5JUsrmF1.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-De0aJ3Ls.js → KnowledgeGraph-Br8b5Htz.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-ZtS98jCm.js → Logs-D-tubDMJ.js} +2 -2
- package/src/assets/web-panel/assets/MarkdownRenderer-In4itZX2.js +1 -0
- package/src/assets/web-panel/assets/{Marketplace-Byz3xCBN.js → Marketplace-s8MmWkS9.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-DOZUUW6z.js → McpTools-Wu-WRg4M.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-C33wC2hA.js → Memory-B_i-eX9w.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-zZe-T_6M.js → MobileBridge-Ca64kjVx.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-CRnUIume.js → MobileProjects-Cq9AFiO4.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-C1xlRVAN.js → Mtc-DKvGmG3y.js} +4 -4
- package/src/assets/web-panel/assets/{MtcAudit-D0U07bIi.js → MtcAudit-BVvWx8pF.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-DF8uvV3h.js → Multisig-wqeJ2O9x.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-bBPGAFlt.js → NLProgramming-DX87ysYu.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-BHAaOsgg.js → Notes-ChenGdu0.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-Cl0fG_rA.js → NotificationSettings-BZRa68-x.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-BEPAs8Zv.js → OrderTableRenderer-DZ6xG1M6.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BAxSwgk5.js → Organization-BWJp4VPX.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-D68KubAu.js → Overflow-BoM4bYt5.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-bhdT17zk.js → P2P-Cvi8YV09.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-DqaO6wgH.js → PdhVaultBrowser-CNVC1NIj.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-Bq8fvkak.js → Permissions-DNd1MRjW.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BYd2JEic.js → PersonalDataHub-DGSBYZ5-.js} +5 -5
- package/src/assets/web-panel/assets/{Pipeline-Csg_ja69.js → Pipeline-DkcoGMBo.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-lwxwLj4M.js → Privacy-DltwvMAW.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-BdBZkH8z.js → ProjectInit-ChYbpHg8.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-ClWgFy-K.js → ProjectSettings-B8FWiHTJ.js} +2 -2
- package/src/assets/web-panel/assets/{Projects-Bu-qj8N1.js → Projects-DuyhtSm4.js} +1 -1
- package/src/assets/web-panel/assets/{Providers-DEjxrxw3.js → Providers-Bo18Tx_6.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-eccy-8Vi.js → QrScannerModal-6W85KlsG.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-Vx3uDvFg.js → QuickAsk-DznRUedP.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CfUivNps.js → Recommend-CQDN3_p-.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-BU4gk7GI.js → RemoteSession-CiJgokEj.js} +3 -3
- package/src/assets/web-panel/assets/{Reputation-CbPzdZ0C.js → Reputation-DexzGH7E.js} +1 -1
- package/src/assets/web-panel/assets/{Row-CYLrgfKA.js → Row-BgZOIvSi.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-DbY1oyuv.js → RssFeed-BWIZJ_Jr.js} +3 -3
- package/src/assets/web-panel/assets/{Search-QeW41K5r.js → Search-B376EwWJ.js} +1 -1
- package/src/assets/web-panel/assets/{Security-CJxf1kLZ.js → Security-92mUR5OD.js} +4 -4
- package/src/assets/web-panel/assets/{Services-CFO9ySZc.js → Services-ClSEAOHk.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-CQFjeQN0.js → Skeleton-DVhLbv99.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-CLLB4INW.js → Skills-JTcXs_xI.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-DxeLIJk0.js → Sla-DnKY9zy9.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-D4FA9KYI.js → SpeechSettings-GO1JefAH.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-C6NOkcQK.js → SyncSettings-jX5tB2St.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-LmVPWDfQ.js → Tasks-BxRBzhUc.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-BdEfUoVB.js → Templates-CAVkbTG1.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-IUlESacN.js → Tenant-5Y7sHBkz.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-B9pDe7sn.js → Terminal-CbbLShYb.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-ZCwB-Pki.js → TimelineRenderer-2HptWihL.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-4qk16LX1.js → Tokens-B-jGxzHl.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-jXNyargn.js → Trigger-9DGa90DT.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-D13PydtT.js → Trust-BSJEkEOO.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-yPgws6mS.js → UkeySign-C807So5R.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-B329WjpG.js → VideoEditing-ByiieAv-.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-T8VM-Ttm.js → Wallet-BixbIOUv.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-XuRibrpP.js → WebAuthn-z7akhor4.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-D1Gwz3YR.js → WorkflowEditor-KvijuUuR.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DjydtnT-.js → chat-BYKoh0YG.js} +1 -1
- package/src/assets/web-panel/assets/{colors-gFtBvPrr.js → colors-CLT8IYBt.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-CndxhGfx.js → compact-item-DlBIyYHF.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-DnfGpd0L.js → createContext-5XmAnNLr.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-BmcCIHwY.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-CmT5hRVW.js → hasIn-rPdRhm7K.js} +1 -1
- package/src/assets/web-panel/assets/{index-DoBKSzqu.js → index-8un-eUDI.js} +1 -1
- package/src/assets/web-panel/assets/{index-DGbKeg8G.js → index-B-0nAxf5.js} +1 -1
- package/src/assets/web-panel/assets/{index-DreYqebI.js → index-B1VfBUPB.js} +1 -1
- package/src/assets/web-panel/assets/{index-zQf599Uq.js → index-BBt2CSAx.js} +1 -1
- package/src/assets/web-panel/assets/{index-BlTcxT_L.js → index-BDtlwjSr.js} +1 -1
- package/src/assets/web-panel/assets/{index-CqpR0Des.js → index-BIRl2Ii5.js} +1 -1
- package/src/assets/web-panel/assets/{index-C3HvYeA3.js → index-BgevTkUv.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0WFjxWs.js → index-Bve7Wsgf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BNHdO6Jr.js → index-Bzd0sFkp.js} +1 -1
- package/src/assets/web-panel/assets/{index-DV2PR3Fa.js → index-C2sFDVb_.js} +1 -1
- package/src/assets/web-panel/assets/{index-D2d7358Y.js → index-CErvHCDe.js} +1 -1
- package/src/assets/web-panel/assets/{index-DaEPE2DC.js → index-CM_a9spK.js} +1 -1
- package/src/assets/web-panel/assets/{index-DKyuE_Y2.js → index-CY6TMc2m.js} +1 -1
- package/src/assets/web-panel/assets/{index-BVM_w30N.js → index-ChlzaTV3.js} +1 -1
- package/src/assets/web-panel/assets/{index-CZLDbPTa.js → index-CsnbOKdI.js} +1 -1
- package/src/assets/web-panel/assets/{index-HHP1zzo7.js → index-D3-NL-x-.js} +1 -1
- package/src/assets/web-panel/assets/{index-BFif4Cev.js → index-D3f9Jzx2.js} +1 -1
- package/src/assets/web-panel/assets/{index-C14jryXi.js → index-DCDSycWo.js} +1 -1
- package/src/assets/web-panel/assets/{index-CB27echm.js → index-DIVrVGvf.js} +1 -1
- package/src/assets/web-panel/assets/{index-BGlmPbl_.js → index-DI_tYFBe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BsRKmb6k.js → index-DPS4mWnI.js} +1 -1
- package/src/assets/web-panel/assets/{index-BXNUTiW8.js → index-DTslLzPJ.js} +1 -1
- package/src/assets/web-panel/assets/{index-Dbpk75MO.js → index-DW8vozBS.js} +1 -1
- package/src/assets/web-panel/assets/index-DY8rmd6x.js +1 -0
- package/src/assets/web-panel/assets/{index-DjY-3sMA.js → index-DZiSMYoD.js} +3 -3
- package/src/assets/web-panel/assets/{index-DV6NrfJx.js → index-DZjGcIGU.js} +1 -1
- package/src/assets/web-panel/assets/{index-ktN-K1Tf.js → index-Dea32nOK.js} +1 -1
- package/src/assets/web-panel/assets/{index-DjcR-CwS.js → index-Djd7uqwM.js} +1 -1
- package/src/assets/web-panel/assets/{index-CuOx4Pbe.js → index-Dntid6oj.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW3nWiu0.js → index-DqZU4_7J.js} +1 -1
- package/src/assets/web-panel/assets/{index-C4Mqhmas.js → index-DuvweiCz.js} +1 -1
- package/src/assets/web-panel/assets/{index-CRqz8TtI.js → index-DzExCCLS.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5na0B7G.js → index-LKT-Ol0A.js} +1 -1
- package/src/assets/web-panel/assets/{index-_-wGLtAg.js → index-akwXS-FF.js} +1 -1
- package/src/assets/web-panel/assets/{index-CgMKElUh.js → index-b-rQCMkx.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUlubR4l.js → index-eHbr3f5I.js} +1 -1
- package/src/assets/web-panel/assets/{index-D88-8bsB.js → index-kx6zDWew.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuAvYTmY.js → index-rRuCGdKW.js} +1 -1
- package/src/assets/web-panel/assets/index-sbwcUeRS.js +1 -0
- package/src/assets/web-panel/assets/{initDefaultProps-KV3V-PNH.js → initDefaultProps-a8411LiK.js} +1 -1
- package/src/assets/web-panel/assets/{motion-PFGQg7_X.js → motion-oVcQdpCm.js} +1 -1
- package/src/assets/web-panel/assets/{move-Dnl79wq4.js → move-B-eyzzzL.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-Bwl5JH9V.js → mtc-parser-BCYIxuG7.js} +1 -1
- package/src/assets/web-panel/assets/{omit-DCcTtM1l.js → omit-DuFtWiYh.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-Cl6BjjDf.js → pickAttrs-CVAoJhGu.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-fdqhyo42.js → placementArrow-Y2iub2bO.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-DYQpmcDW.js → responsiveObserve-BHenWIVD.js} +1 -1
- package/src/assets/web-panel/assets/{slide-C4l-VfO4.js → slide-CKrMaL29.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-DYDw_dyZ.js → statusUtils-w8eb_1da.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-BEsubSMu.js → styleChecker-CCVi_Ww3.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-Cj82ggQ_.js → useFlexGapSupport-BsmR_q0r.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-B7L1eJ0V.js → useFs-a8GMBjnc.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-DVlJVD4d.js → usePersonalDataHub-BMUYSPn-.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BBAbRN_Y.js → vnode-DL2pI31V.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-BYn48q-I.js → zoom-Cbi8fISi.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/data/changelog.json +33 -7
- package/src/lib/dependency-install-policy.js +1 -1
- package/src/lib/evolution/browser-download-action-authority.js +747 -0
- package/src/lib/evolution/browser-download-artifact-disposal-authority.js +436 -0
- package/src/lib/evolution/browser-filesystem-quarantine-custody.js +2453 -0
- package/src/lib/evolution/browser-filesystem-quarantine-disposal.js +36 -0
- package/src/lib/evolution/browser-keyboard-action-authority.js +560 -0
- package/src/lib/evolution/browser-navigation-action-authority.js +546 -0
- package/src/lib/evolution/browser-quarantine-lock-maintenance-authority.js +573 -0
- package/src/lib/evolution/browser-quarantine-operator-revocation-authority.js +442 -0
- package/src/lib/evolution/browser-quarantine-retention-authority.js +503 -0
- package/src/lib/evolution/browser-quarantine-retention-scheduler.js +207 -0
- package/src/lib/evolution/browser-quarantined-download-executor.js +525 -0
- package/src/lib/evolution/browser-tab-open-action-authority.js +491 -0
- package/src/lib/evolution/browser-vision-action-authority.js +444 -0
- package/src/lib/evolution/browser-vision-observation-authority.js +304 -0
- package/src/lib/evolution/evolution-deployment-loader.js +241 -1
- package/src/lib/evolution/evolution-eval-child-evidence-ledger-adapter.js +5 -0
- package/src/lib/evolution/evolution-eval-gate.js +2 -1
- package/src/lib/evolution/evolution-eval-process-supervisor-worker.mjs +71 -9
- package/src/lib/evolution/evolution-eval-process-supervisor.js +276 -9
- package/src/lib/evolution/evolution-workbench-metrics.js +81 -21
- package/src/lib/evolution/pm-exploration-benchmark.js +747 -0
- package/src/lib/evolution/pm-exploration-budget-executor.js +106 -9
- package/src/lib/evolution/pm-exploration-egress-authority.js +382 -0
- package/src/lib/evolution/pm-exploration-evidence-bundle.js +149 -44
- package/src/lib/evolution/pm-exploration-execution-host.js +1254 -8
- package/src/lib/evolution/pm-exploration-process-grader.js +458 -0
- package/src/lib/evolution/pm-exploration-process-reviewer.js +456 -0
- package/src/lib/evolution/pm-exploration-process-runner.js +500 -0
- package/src/lib/evolution/pm-exploration-receipts.js +211 -11
- package/src/lib/evolution/pm-exploration-recovery-snapshot-store.js +465 -46
- package/src/lib/evolution/pm-exploration-transition-committer.js +185 -34
- package/src/lib/evolution/skill-outcome-index-authority.js +7 -3
- package/src/lib/evolution/skill-writer-inventory-manifest.js +0 -39
- package/src/lib/evolution/volcengine-function-execution-authority.js +2949 -0
- package/src/lib/evolution/volcengine-function-process-executor.js +615 -0
- package/src/lib/evolution/volcengine-function-replay-store.js +836 -0
- package/src/lib/evolution/volcengine-function-revocation-status-floor-store.js +480 -0
- package/src/lib/governance-coverage.js +1 -1
- package/src/lib/headless-manifest.js +1 -1
- package/src/lib/protocol-replay.js +1 -1
- package/src/lib/skill-outcome-transcript-authority.js +45 -5
- package/src/runtime/agent-core.js +17 -0
- package/src/assets/web-panel/assets/ChatBubbleRenderer-Cf3LLgDc.js +0 -1
- package/src/assets/web-panel/assets/MarkdownRenderer-CTsYo9NN.js +0 -1
- package/src/assets/web-panel/assets/devWarning-D60SbiD-.js +0 -1
- package/src/assets/web-panel/assets/index-C0yR4_7h.js +0 -1
- package/src/assets/web-panel/assets/index-D4xuvo03.js +0 -1
|
@@ -0,0 +1,546 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { types } from "node:util";
|
|
3
|
+
|
|
4
|
+
export const BROWSER_NAVIGATION_ACTION_AUTHORITY_DESCRIPTOR_SCHEMA =
|
|
5
|
+
"chainlesschain.browser-navigation-action-authority-descriptor/v1";
|
|
6
|
+
export const BROWSER_NAVIGATION_ACTION_REQUEST_SCHEMA =
|
|
7
|
+
"chainlesschain.browser-navigation-action-request/v3";
|
|
8
|
+
export const BROWSER_NAVIGATION_ACTION_RECEIPT_SCHEMA =
|
|
9
|
+
"chainlesschain.browser-navigation-action-receipt/v3";
|
|
10
|
+
export const BROWSER_NAVIGATION_ACTION_OUTCOME_REQUEST_SCHEMA =
|
|
11
|
+
"chainlesschain.browser-navigation-action-outcome-request/v2";
|
|
12
|
+
export const BROWSER_NAVIGATION_ACTION_OUTCOME_ACK_SCHEMA =
|
|
13
|
+
"chainlesschain.browser-navigation-action-outcome-ack/v1";
|
|
14
|
+
|
|
15
|
+
const DIGEST = /^sha256:[a-f0-9]{64}$/u;
|
|
16
|
+
const ID = /^[A-Za-z0-9._:-]{1,128}$/u;
|
|
17
|
+
const WAIT_UNTIL = new Set(["load", "domcontentloaded", "networkidle"]);
|
|
18
|
+
const OPERATIONS = new Set(["navigate", "back", "forward", "refresh"]);
|
|
19
|
+
const authorities = new WeakMap();
|
|
20
|
+
|
|
21
|
+
function canonical(value) {
|
|
22
|
+
if (value === null || typeof value === "boolean")
|
|
23
|
+
return JSON.stringify(value);
|
|
24
|
+
if (typeof value === "number" && Number.isFinite(value))
|
|
25
|
+
return JSON.stringify(value);
|
|
26
|
+
if (typeof value === "string") return JSON.stringify(value);
|
|
27
|
+
if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`;
|
|
28
|
+
return `{${Object.keys(value)
|
|
29
|
+
.sort()
|
|
30
|
+
.map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
|
|
31
|
+
.join(",")}}`;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
function digest(domain, value) {
|
|
35
|
+
return `sha256:${createHash("sha256")
|
|
36
|
+
.update(`${domain}\0`)
|
|
37
|
+
.update(canonical(value))
|
|
38
|
+
.digest("hex")}`;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
function exactObject(value, keys, label) {
|
|
42
|
+
if (
|
|
43
|
+
!value ||
|
|
44
|
+
typeof value !== "object" ||
|
|
45
|
+
Array.isArray(value) ||
|
|
46
|
+
types.isProxy(value) ||
|
|
47
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value)) ||
|
|
48
|
+
Object.keys(value).sort().join("\0") !== [...keys].sort().join("\0")
|
|
49
|
+
) {
|
|
50
|
+
throw new TypeError(`${label} has an invalid shape`);
|
|
51
|
+
}
|
|
52
|
+
for (const key of keys) {
|
|
53
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
54
|
+
if (!descriptor?.enumerable || !("value" in descriptor))
|
|
55
|
+
throw new TypeError(`${label} must contain plain data`);
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
function snapshotJson(value, label) {
|
|
60
|
+
let nodes = 0;
|
|
61
|
+
const visit = (entry, depth) => {
|
|
62
|
+
if (++nodes > 2048 || depth > 12)
|
|
63
|
+
throw new TypeError(`${label} exceeds its structure budget`);
|
|
64
|
+
if (
|
|
65
|
+
entry === null ||
|
|
66
|
+
typeof entry === "boolean" ||
|
|
67
|
+
(typeof entry === "number" && Number.isFinite(entry)) ||
|
|
68
|
+
typeof entry === "string"
|
|
69
|
+
) {
|
|
70
|
+
return entry;
|
|
71
|
+
}
|
|
72
|
+
if (
|
|
73
|
+
!entry ||
|
|
74
|
+
typeof entry !== "object" ||
|
|
75
|
+
types.isProxy(entry) ||
|
|
76
|
+
![Object.prototype, null, Array.prototype].includes(
|
|
77
|
+
Object.getPrototypeOf(entry),
|
|
78
|
+
)
|
|
79
|
+
) {
|
|
80
|
+
throw new TypeError(`${label} must be finite plain JSON data`);
|
|
81
|
+
}
|
|
82
|
+
if (Array.isArray(entry))
|
|
83
|
+
return Object.freeze(entry.map((item) => visit(item, depth + 1)));
|
|
84
|
+
const output = {};
|
|
85
|
+
for (const key of Object.keys(entry)) {
|
|
86
|
+
const descriptor = Object.getOwnPropertyDescriptor(entry, key);
|
|
87
|
+
if (!descriptor?.enumerable || !("value" in descriptor))
|
|
88
|
+
throw new TypeError(`${label} must contain plain data`);
|
|
89
|
+
output[key] = visit(descriptor.value, depth + 1);
|
|
90
|
+
}
|
|
91
|
+
return Object.freeze(output);
|
|
92
|
+
};
|
|
93
|
+
const snapshot = visit(value, 0);
|
|
94
|
+
if (Buffer.byteLength(canonical(snapshot), "utf8") > 16 * 1024)
|
|
95
|
+
throw new TypeError(`${label} exceeds its byte budget`);
|
|
96
|
+
return snapshot;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
function normalizeUrl(value) {
|
|
100
|
+
if (typeof value !== "string" || value.length < 1 || value.length > 16 * 1024)
|
|
101
|
+
throw new TypeError("browser navigation destination is invalid");
|
|
102
|
+
let parsed;
|
|
103
|
+
try {
|
|
104
|
+
parsed = new URL(value);
|
|
105
|
+
} catch {
|
|
106
|
+
throw new TypeError("browser navigation destination is invalid");
|
|
107
|
+
}
|
|
108
|
+
if (
|
|
109
|
+
!["http:", "https:"].includes(parsed.protocol) ||
|
|
110
|
+
parsed.username !== "" ||
|
|
111
|
+
parsed.password !== "" ||
|
|
112
|
+
parsed.href.length > 16 * 1024
|
|
113
|
+
) {
|
|
114
|
+
throw new TypeError("browser navigation destination is invalid");
|
|
115
|
+
}
|
|
116
|
+
return parsed.href;
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
function normalizeRedirectOrigins(value, destinationUrl) {
|
|
120
|
+
if (
|
|
121
|
+
!Array.isArray(value) ||
|
|
122
|
+
types.isProxy(value) ||
|
|
123
|
+
value.length < 1 ||
|
|
124
|
+
value.length > 16
|
|
125
|
+
) {
|
|
126
|
+
throw new TypeError("browser navigation redirect origins are invalid");
|
|
127
|
+
}
|
|
128
|
+
const origins = value.map((entry) => {
|
|
129
|
+
if (typeof entry !== "string" || entry.length > 2048)
|
|
130
|
+
throw new TypeError("browser navigation redirect origins are invalid");
|
|
131
|
+
let parsed;
|
|
132
|
+
try {
|
|
133
|
+
parsed = new URL(entry);
|
|
134
|
+
} catch {
|
|
135
|
+
throw new TypeError("browser navigation redirect origins are invalid");
|
|
136
|
+
}
|
|
137
|
+
if (
|
|
138
|
+
!["http:", "https:"].includes(parsed.protocol) ||
|
|
139
|
+
parsed.username !== "" ||
|
|
140
|
+
parsed.password !== "" ||
|
|
141
|
+
entry !== parsed.origin
|
|
142
|
+
) {
|
|
143
|
+
throw new TypeError("browser navigation redirect origins are invalid");
|
|
144
|
+
}
|
|
145
|
+
return parsed.origin;
|
|
146
|
+
});
|
|
147
|
+
const normalized = [...new Set(origins)].sort();
|
|
148
|
+
if (
|
|
149
|
+
normalized.length !== origins.length ||
|
|
150
|
+
(destinationUrl !== null &&
|
|
151
|
+
!normalized.includes(new URL(destinationUrl).origin))
|
|
152
|
+
) {
|
|
153
|
+
throw new TypeError("browser navigation redirect origins are invalid");
|
|
154
|
+
}
|
|
155
|
+
return Object.freeze(normalized);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
function normalizeDescriptor(value) {
|
|
159
|
+
exactObject(
|
|
160
|
+
value,
|
|
161
|
+
[
|
|
162
|
+
"schema",
|
|
163
|
+
"authorityId",
|
|
164
|
+
"tenantId",
|
|
165
|
+
"handlerArtifactDigest",
|
|
166
|
+
"policyRevision",
|
|
167
|
+
"maxGrantTtlMs",
|
|
168
|
+
"approvalMode",
|
|
169
|
+
"auditMode",
|
|
170
|
+
],
|
|
171
|
+
"browser navigation action authority descriptor",
|
|
172
|
+
);
|
|
173
|
+
if (
|
|
174
|
+
value.schema !== BROWSER_NAVIGATION_ACTION_AUTHORITY_DESCRIPTOR_SCHEMA ||
|
|
175
|
+
!ID.test(value.authorityId) ||
|
|
176
|
+
!ID.test(value.tenantId) ||
|
|
177
|
+
!DIGEST.test(value.handlerArtifactDigest) ||
|
|
178
|
+
!ID.test(value.policyRevision) ||
|
|
179
|
+
!Number.isSafeInteger(value.maxGrantTtlMs) ||
|
|
180
|
+
value.maxGrantTtlMs < 1 ||
|
|
181
|
+
value.maxGrantTtlMs > 30_000 ||
|
|
182
|
+
value.approvalMode !== "interactive" ||
|
|
183
|
+
value.auditMode !== "authenticated-durable-readback"
|
|
184
|
+
) {
|
|
185
|
+
throw new TypeError(
|
|
186
|
+
"browser navigation action authority descriptor is invalid",
|
|
187
|
+
);
|
|
188
|
+
}
|
|
189
|
+
return Object.freeze({ ...value });
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
function normalizeRequest(value) {
|
|
193
|
+
exactObject(
|
|
194
|
+
value,
|
|
195
|
+
[
|
|
196
|
+
"schema",
|
|
197
|
+
"requestId",
|
|
198
|
+
"targetId",
|
|
199
|
+
"operation",
|
|
200
|
+
"senderId",
|
|
201
|
+
"frameUrlDigest",
|
|
202
|
+
"destinationUrl",
|
|
203
|
+
"allowedRedirectOrigins",
|
|
204
|
+
"waitUntil",
|
|
205
|
+
"timeout",
|
|
206
|
+
"inputDigest",
|
|
207
|
+
"authorization",
|
|
208
|
+
"requestedAt",
|
|
209
|
+
],
|
|
210
|
+
"browser navigation action request",
|
|
211
|
+
);
|
|
212
|
+
const destinationUrl =
|
|
213
|
+
value.operation === "navigate" ? normalizeUrl(value.destinationUrl) : null;
|
|
214
|
+
if (value.operation !== "navigate" && value.destinationUrl !== null) {
|
|
215
|
+
throw new TypeError("browser navigation destination is invalid");
|
|
216
|
+
}
|
|
217
|
+
const allowedRedirectOrigins = normalizeRedirectOrigins(
|
|
218
|
+
value.allowedRedirectOrigins,
|
|
219
|
+
destinationUrl,
|
|
220
|
+
);
|
|
221
|
+
const requestedAtMs = Date.parse(value.requestedAt);
|
|
222
|
+
const inputCore = Object.freeze({
|
|
223
|
+
targetId: value.targetId,
|
|
224
|
+
operation: value.operation,
|
|
225
|
+
destinationUrl,
|
|
226
|
+
allowedRedirectOrigins,
|
|
227
|
+
waitUntil: value.waitUntil,
|
|
228
|
+
timeout: value.timeout,
|
|
229
|
+
});
|
|
230
|
+
if (
|
|
231
|
+
value.schema !== BROWSER_NAVIGATION_ACTION_REQUEST_SCHEMA ||
|
|
232
|
+
!ID.test(value.requestId) ||
|
|
233
|
+
typeof value.targetId !== "string" ||
|
|
234
|
+
value.targetId.length < 1 ||
|
|
235
|
+
value.targetId.length > 512 ||
|
|
236
|
+
!OPERATIONS.has(value.operation) ||
|
|
237
|
+
!Number.isSafeInteger(value.senderId) ||
|
|
238
|
+
value.senderId < 1 ||
|
|
239
|
+
!DIGEST.test(value.frameUrlDigest) ||
|
|
240
|
+
!WAIT_UNTIL.has(value.waitUntil) ||
|
|
241
|
+
!Number.isSafeInteger(value.timeout) ||
|
|
242
|
+
value.timeout < 1 ||
|
|
243
|
+
value.timeout > 120_000 ||
|
|
244
|
+
value.inputDigest !==
|
|
245
|
+
digest("chainlesschain.browser-navigation-action-input/v3", inputCore) ||
|
|
246
|
+
!Number.isFinite(requestedAtMs)
|
|
247
|
+
) {
|
|
248
|
+
throw new TypeError("browser navigation action request is invalid");
|
|
249
|
+
}
|
|
250
|
+
return Object.freeze({
|
|
251
|
+
...value,
|
|
252
|
+
destinationUrl,
|
|
253
|
+
allowedRedirectOrigins,
|
|
254
|
+
authorization: snapshotJson(
|
|
255
|
+
value.authorization,
|
|
256
|
+
"browser navigation action authorization",
|
|
257
|
+
),
|
|
258
|
+
inputCore,
|
|
259
|
+
requestedAtMs,
|
|
260
|
+
});
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
function requestEvidence(request) {
|
|
264
|
+
const authorizationDigest = digest(
|
|
265
|
+
"chainlesschain.browser-navigation-action-authorization/v1",
|
|
266
|
+
request.authorization,
|
|
267
|
+
);
|
|
268
|
+
const core = {
|
|
269
|
+
schema: request.schema,
|
|
270
|
+
requestId: request.requestId,
|
|
271
|
+
targetId: request.targetId,
|
|
272
|
+
operation: request.operation,
|
|
273
|
+
senderId: request.senderId,
|
|
274
|
+
frameUrlDigest: request.frameUrlDigest,
|
|
275
|
+
destinationDigest:
|
|
276
|
+
request.destinationUrl === null
|
|
277
|
+
? null
|
|
278
|
+
: digest(
|
|
279
|
+
"chainlesschain.browser-navigation-action-destination/v1",
|
|
280
|
+
request.destinationUrl,
|
|
281
|
+
),
|
|
282
|
+
redirectOriginsDigest: digest(
|
|
283
|
+
"chainlesschain.browser-navigation-action-redirect-origins/v1",
|
|
284
|
+
request.allowedRedirectOrigins,
|
|
285
|
+
),
|
|
286
|
+
waitUntil: request.waitUntil,
|
|
287
|
+
timeout: request.timeout,
|
|
288
|
+
inputDigest: request.inputDigest,
|
|
289
|
+
authorizationDigest,
|
|
290
|
+
requestedAt: request.requestedAt,
|
|
291
|
+
};
|
|
292
|
+
return Object.freeze({
|
|
293
|
+
...core,
|
|
294
|
+
requestDigest: digest(
|
|
295
|
+
"chainlesschain.browser-navigation-action-request/v3",
|
|
296
|
+
core,
|
|
297
|
+
),
|
|
298
|
+
});
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function normalizeDecision(value) {
|
|
302
|
+
if (
|
|
303
|
+
!value ||
|
|
304
|
+
typeof value !== "object" ||
|
|
305
|
+
Array.isArray(value) ||
|
|
306
|
+
types.isProxy(value) ||
|
|
307
|
+
![Object.prototype, null].includes(Object.getPrototypeOf(value))
|
|
308
|
+
) {
|
|
309
|
+
throw new TypeError("browser navigation action decision is invalid");
|
|
310
|
+
}
|
|
311
|
+
const direct = Object.getOwnPropertyDescriptor(value, "decision");
|
|
312
|
+
if (!direct?.enumerable || !("value" in direct))
|
|
313
|
+
throw new TypeError(
|
|
314
|
+
"browser navigation action decision must be plain data",
|
|
315
|
+
);
|
|
316
|
+
if (direct.value === "deny") {
|
|
317
|
+
const keys = Object.hasOwn(value, "reason")
|
|
318
|
+
? ["decision", "reason"]
|
|
319
|
+
: ["decision"];
|
|
320
|
+
exactObject(value, keys, "browser navigation action decision");
|
|
321
|
+
const reason = Object.hasOwn(value, "reason") ? value.reason : null;
|
|
322
|
+
if (reason !== null && (typeof reason !== "string" || reason.length > 512))
|
|
323
|
+
throw new TypeError("browser navigation action denial reason is invalid");
|
|
324
|
+
return Object.freeze({ decision: "deny", reason });
|
|
325
|
+
}
|
|
326
|
+
exactObject(
|
|
327
|
+
value,
|
|
328
|
+
["decision", "approvalEvidenceRef", "validUntil"],
|
|
329
|
+
"browser navigation action decision",
|
|
330
|
+
);
|
|
331
|
+
if (direct.value !== "allow")
|
|
332
|
+
throw new TypeError("browser navigation action decision is invalid");
|
|
333
|
+
return Object.freeze({
|
|
334
|
+
decision: "allow",
|
|
335
|
+
approvalEvidenceRef: value.approvalEvidenceRef,
|
|
336
|
+
validUntil: value.validUntil,
|
|
337
|
+
});
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
function normalizeOutcomeRequest(value) {
|
|
341
|
+
exactObject(
|
|
342
|
+
value,
|
|
343
|
+
[
|
|
344
|
+
"schema",
|
|
345
|
+
"actionReceiptDigest",
|
|
346
|
+
"requestDigest",
|
|
347
|
+
"targetId",
|
|
348
|
+
"operation",
|
|
349
|
+
"inputDigest",
|
|
350
|
+
"status",
|
|
351
|
+
"resultDigest",
|
|
352
|
+
"recordedAt",
|
|
353
|
+
],
|
|
354
|
+
"browser navigation action outcome request",
|
|
355
|
+
);
|
|
356
|
+
if (
|
|
357
|
+
value.schema !== BROWSER_NAVIGATION_ACTION_OUTCOME_REQUEST_SCHEMA ||
|
|
358
|
+
!DIGEST.test(value.actionReceiptDigest) ||
|
|
359
|
+
!DIGEST.test(value.requestDigest) ||
|
|
360
|
+
typeof value.targetId !== "string" ||
|
|
361
|
+
value.targetId.length < 1 ||
|
|
362
|
+
value.targetId.length > 512 ||
|
|
363
|
+
!OPERATIONS.has(value.operation) ||
|
|
364
|
+
!DIGEST.test(value.inputDigest) ||
|
|
365
|
+
!["succeeded", "failed"].includes(value.status) ||
|
|
366
|
+
!DIGEST.test(value.resultDigest) ||
|
|
367
|
+
!Number.isFinite(Date.parse(value.recordedAt))
|
|
368
|
+
) {
|
|
369
|
+
throw new TypeError("browser navigation action outcome request is invalid");
|
|
370
|
+
}
|
|
371
|
+
const core = Object.freeze({ ...value });
|
|
372
|
+
return Object.freeze({
|
|
373
|
+
...core,
|
|
374
|
+
outcomeRequestDigest: digest(
|
|
375
|
+
"chainlesschain.browser-navigation-action-outcome-request/v2",
|
|
376
|
+
core,
|
|
377
|
+
),
|
|
378
|
+
});
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
function normalizeOutcomeAck(value, descriptor, request) {
|
|
382
|
+
exactObject(
|
|
383
|
+
value,
|
|
384
|
+
[
|
|
385
|
+
"schema",
|
|
386
|
+
"authorityId",
|
|
387
|
+
"tenantId",
|
|
388
|
+
"handlerArtifactDigest",
|
|
389
|
+
"actionReceiptDigest",
|
|
390
|
+
"outcomeRequestDigest",
|
|
391
|
+
"auditEventDigest",
|
|
392
|
+
"durabilityReceiptDigest",
|
|
393
|
+
"authenticated",
|
|
394
|
+
"durable",
|
|
395
|
+
"readbackVerified",
|
|
396
|
+
"qualifiesForPromotion",
|
|
397
|
+
],
|
|
398
|
+
"browser navigation action outcome acknowledgement",
|
|
399
|
+
);
|
|
400
|
+
if (
|
|
401
|
+
value.schema !== BROWSER_NAVIGATION_ACTION_OUTCOME_ACK_SCHEMA ||
|
|
402
|
+
value.authorityId !== descriptor.authorityId ||
|
|
403
|
+
value.tenantId !== descriptor.tenantId ||
|
|
404
|
+
value.handlerArtifactDigest !== descriptor.handlerArtifactDigest ||
|
|
405
|
+
value.actionReceiptDigest !== request.actionReceiptDigest ||
|
|
406
|
+
value.outcomeRequestDigest !== request.outcomeRequestDigest ||
|
|
407
|
+
!DIGEST.test(value.auditEventDigest) ||
|
|
408
|
+
!DIGEST.test(value.durabilityReceiptDigest) ||
|
|
409
|
+
value.authenticated !== true ||
|
|
410
|
+
value.durable !== true ||
|
|
411
|
+
value.readbackVerified !== true ||
|
|
412
|
+
value.qualifiesForPromotion !== false
|
|
413
|
+
) {
|
|
414
|
+
throw new Error(
|
|
415
|
+
"browser navigation action outcome acknowledgement is invalid",
|
|
416
|
+
);
|
|
417
|
+
}
|
|
418
|
+
return Object.freeze({ ...value });
|
|
419
|
+
}
|
|
420
|
+
|
|
421
|
+
export function createBrowserNavigationActionAuthority({
|
|
422
|
+
descriptor,
|
|
423
|
+
authorize,
|
|
424
|
+
recordOutcome,
|
|
425
|
+
now = () => Date.now(),
|
|
426
|
+
} = {}) {
|
|
427
|
+
const normalizedDescriptor = normalizeDescriptor(descriptor);
|
|
428
|
+
if (typeof authorize !== "function" || types.isProxy(authorize))
|
|
429
|
+
throw new TypeError("browser navigation action authorize port is invalid");
|
|
430
|
+
if (typeof recordOutcome !== "function" || types.isProxy(recordOutcome))
|
|
431
|
+
throw new TypeError("browser navigation action outcome port is invalid");
|
|
432
|
+
if (typeof now !== "function" || types.isProxy(now))
|
|
433
|
+
throw new TypeError("browser navigation action clock is invalid");
|
|
434
|
+
const authority = Object.freeze({});
|
|
435
|
+
authorities.set(authority, {
|
|
436
|
+
descriptor: normalizedDescriptor,
|
|
437
|
+
authorize,
|
|
438
|
+
recordOutcome,
|
|
439
|
+
now,
|
|
440
|
+
issued: new Map(),
|
|
441
|
+
});
|
|
442
|
+
return authority;
|
|
443
|
+
}
|
|
444
|
+
|
|
445
|
+
export function captureBrowserNavigationActionAuthority(value) {
|
|
446
|
+
const captured = authorities.get(value);
|
|
447
|
+
if (!captured)
|
|
448
|
+
throw new TypeError(
|
|
449
|
+
"A branded browser navigation action authority is required",
|
|
450
|
+
);
|
|
451
|
+
return Object.freeze({
|
|
452
|
+
descriptor: captured.descriptor,
|
|
453
|
+
authorizeAction: async (value) => {
|
|
454
|
+
const request = normalizeRequest(value);
|
|
455
|
+
const evidence = requestEvidence(request);
|
|
456
|
+
const decision = normalizeDecision(
|
|
457
|
+
await captured.authorize(
|
|
458
|
+
Object.freeze({ ...request, requestDigest: evidence.requestDigest }),
|
|
459
|
+
),
|
|
460
|
+
);
|
|
461
|
+
if (decision.decision !== "allow") {
|
|
462
|
+
const error = new Error(
|
|
463
|
+
decision.reason ?? "Browser navigation action was denied",
|
|
464
|
+
);
|
|
465
|
+
error.code = "BROWSER_NAVIGATION_ACTION_DENIED";
|
|
466
|
+
throw error;
|
|
467
|
+
}
|
|
468
|
+
const nowMs = captured.now();
|
|
469
|
+
const validUntilMs = Date.parse(decision.validUntil);
|
|
470
|
+
if (
|
|
471
|
+
typeof decision.approvalEvidenceRef !== "string" ||
|
|
472
|
+
decision.approvalEvidenceRef.length < 1 ||
|
|
473
|
+
decision.approvalEvidenceRef.length > 512 ||
|
|
474
|
+
!Number.isFinite(nowMs) ||
|
|
475
|
+
!Number.isFinite(validUntilMs) ||
|
|
476
|
+
validUntilMs <= nowMs ||
|
|
477
|
+
validUntilMs > nowMs + captured.descriptor.maxGrantTtlMs
|
|
478
|
+
) {
|
|
479
|
+
throw new Error("Browser navigation action decision is invalid");
|
|
480
|
+
}
|
|
481
|
+
const core = {
|
|
482
|
+
schema: BROWSER_NAVIGATION_ACTION_RECEIPT_SCHEMA,
|
|
483
|
+
authorityId: captured.descriptor.authorityId,
|
|
484
|
+
tenantId: captured.descriptor.tenantId,
|
|
485
|
+
policyRevision: captured.descriptor.policyRevision,
|
|
486
|
+
handlerArtifactDigest: captured.descriptor.handlerArtifactDigest,
|
|
487
|
+
approvalMode: captured.descriptor.approvalMode,
|
|
488
|
+
requestId: request.requestId,
|
|
489
|
+
targetId: request.targetId,
|
|
490
|
+
operation: request.operation,
|
|
491
|
+
senderId: request.senderId,
|
|
492
|
+
frameUrlDigest: request.frameUrlDigest,
|
|
493
|
+
destinationDigest: evidence.destinationDigest,
|
|
494
|
+
redirectOriginsDigest: evidence.redirectOriginsDigest,
|
|
495
|
+
waitUntil: request.waitUntil,
|
|
496
|
+
timeout: request.timeout,
|
|
497
|
+
inputDigest: request.inputDigest,
|
|
498
|
+
authorizationDigest: evidence.authorizationDigest,
|
|
499
|
+
requestDigest: evidence.requestDigest,
|
|
500
|
+
approvalEvidenceRef: decision.approvalEvidenceRef,
|
|
501
|
+
authorizedAt: new Date(nowMs).toISOString(),
|
|
502
|
+
validUntil: new Date(validUntilMs).toISOString(),
|
|
503
|
+
};
|
|
504
|
+
const receipt = Object.freeze({
|
|
505
|
+
...core,
|
|
506
|
+
receiptDigest: digest(
|
|
507
|
+
"chainlesschain.browser-navigation-action-receipt/v3",
|
|
508
|
+
core,
|
|
509
|
+
),
|
|
510
|
+
});
|
|
511
|
+
captured.issued.set(receipt.receiptDigest, {
|
|
512
|
+
requestDigest: receipt.requestDigest,
|
|
513
|
+
targetId: receipt.targetId,
|
|
514
|
+
operation: receipt.operation,
|
|
515
|
+
inputDigest: receipt.inputDigest,
|
|
516
|
+
outcomeRequestDigest: null,
|
|
517
|
+
});
|
|
518
|
+
return receipt;
|
|
519
|
+
},
|
|
520
|
+
recordActionOutcome: async (value) => {
|
|
521
|
+
const request = normalizeOutcomeRequest(value);
|
|
522
|
+
const issued = captured.issued.get(request.actionReceiptDigest);
|
|
523
|
+
if (
|
|
524
|
+
!issued ||
|
|
525
|
+
issued.requestDigest !== request.requestDigest ||
|
|
526
|
+
issued.targetId !== request.targetId ||
|
|
527
|
+
issued.operation !== request.operation ||
|
|
528
|
+
issued.inputDigest !== request.inputDigest ||
|
|
529
|
+
(issued.outcomeRequestDigest !== null &&
|
|
530
|
+
issued.outcomeRequestDigest !== request.outcomeRequestDigest)
|
|
531
|
+
) {
|
|
532
|
+
throw new Error(
|
|
533
|
+
"browser navigation action outcome differs from its authorization",
|
|
534
|
+
);
|
|
535
|
+
}
|
|
536
|
+
issued.outcomeRequestDigest = request.outcomeRequestDigest;
|
|
537
|
+
const acknowledgement = normalizeOutcomeAck(
|
|
538
|
+
await captured.recordOutcome(request),
|
|
539
|
+
captured.descriptor,
|
|
540
|
+
request,
|
|
541
|
+
);
|
|
542
|
+
captured.issued.delete(request.actionReceiptDigest);
|
|
543
|
+
return acknowledgement;
|
|
544
|
+
},
|
|
545
|
+
});
|
|
546
|
+
}
|