chainlesschain 0.166.68 → 0.166.70

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.
Files changed (177) hide show
  1. package/README.md +24 -5
  2. package/package.json +1 -1
  3. package/src/assets/web-panel/assets/{AIOps-CXkSNOGY.js → AIOps-BBxGVjAo.js} +1 -1
  4. package/src/assets/web-panel/assets/{ActionButton-ysMR6gTs.js → ActionButton-SrT9X1LG.js} +1 -1
  5. package/src/assets/web-panel/assets/{Analytics-WGZ0sWuw.js → Analytics-D0MPWFct.js} +3 -3
  6. package/src/assets/web-panel/assets/{AppLayout-Cs2iRlQG.js → AppLayout-DlmlYhUp.js} +5 -5
  7. package/src/assets/web-panel/assets/{Artifacts-5IdfxWz0.js → Artifacts-BzLV8tLT.js} +1 -1
  8. package/src/assets/web-panel/assets/{Audit-U9V434QX.js → Audit-BWfARNeo.js} +1 -1
  9. package/src/assets/web-panel/assets/{BackgroundAgents-BvFwxPlC.js → BackgroundAgents-AT_lu-OI.js} +1 -1
  10. package/src/assets/web-panel/assets/{Backup-C9yTr9hO.js → Backup-6pH5UJRI.js} +1 -1
  11. package/src/assets/web-panel/assets/{BaseInput-BdsSwUgE.js → BaseInput-CccGGr8I.js} +1 -1
  12. package/src/assets/web-panel/assets/{Chat-BB_2oBgH.js → Chat-B6aQ-lXU.js} +6 -6
  13. package/src/assets/web-panel/assets/ChatBubbleRenderer-cKmA5EAa.js +1 -0
  14. package/src/assets/web-panel/assets/{Checkbox-v6M5m7dK.js → Checkbox-Dc_dMjlV.js} +1 -1
  15. package/src/assets/web-panel/assets/{Codegen-CtouWSIz.js → Codegen-CHm0YK-0.js} +1 -1
  16. package/src/assets/web-panel/assets/{Col-CqQJ4ORW.js → Col-IaBwOtml.js} +1 -1
  17. package/src/assets/web-panel/assets/{Community-BO__QCOy.js → Community-U5N0EakJ.js} +1 -1
  18. package/src/assets/web-panel/assets/{Compact-D0Kq4xlH.js → Compact-D6bK2hw-.js} +1 -1
  19. package/src/assets/web-panel/assets/{Compliance-BSLKKBjA.js → Compliance-B0G1zA62.js} +1 -1
  20. package/src/assets/web-panel/assets/{Cowork-VsujXW5o.js → Cowork-BvJxGzAT.js} +3 -3
  21. package/src/assets/web-panel/assets/{Cron-j8DbLGi5.js → Cron-N5JOZWe9.js} +2 -2
  22. package/src/assets/web-panel/assets/{Crosschain-DWpYH1yN.js → Crosschain-CgnzS-_7.js} +1 -1
  23. package/src/assets/web-panel/assets/{DID-mLaRxLQh.js → DID-BTMEilVf.js} +2 -2
  24. package/src/assets/web-panel/assets/{Dashboard-Cff033Jr.js → Dashboard-Bc-1wTPH.js} +2 -2
  25. package/src/assets/web-panel/assets/{Dropdown-B1Upt6fP.js → Dropdown-DfJLRkz2.js} +1 -1
  26. package/src/assets/web-panel/assets/{EmailListRenderer-CPtb8joV.js → EmailListRenderer-DOkzpgap.js} +1 -1
  27. package/src/assets/web-panel/assets/{EvolutionSettings-CVh4Uv4g.js → EvolutionSettings-23ZdCcyg.js} +1 -1
  28. package/src/assets/web-panel/assets/{FamilyGuardDashboard-CrD1PhbF.js → FamilyGuardDashboard-mBhA1oWh.js} +1 -1
  29. package/src/assets/web-panel/assets/{Federation-ftxrvqW5.js → Federation-C9Kmj_hs.js} +1 -1
  30. package/src/assets/web-panel/assets/{FormItemContext-9O80slC1.js → FormItemContext-CeU7fnW_.js} +1 -1
  31. package/src/assets/web-panel/assets/{GenericCardRenderer-DaYvYIj9.js → GenericCardRenderer-s-QOculU.js} +1 -1
  32. package/src/assets/web-panel/assets/{Git-BKZh0YE5.js → Git-BbePEFdx.js} +2 -2
  33. package/src/assets/web-panel/assets/{Governance-vWbN873j.js → Governance-PnVQJUn7.js} +1 -1
  34. package/src/assets/web-panel/assets/{Inference-BN6RR-l8.js → Inference-sCcd1Foj.js} +1 -1
  35. package/src/assets/web-panel/assets/{KnowledgeGraph-x49x9m7Q.js → KnowledgeGraph-DdM6cJOh.js} +1 -1
  36. package/src/assets/web-panel/assets/Logs-Dznmdibo.js +2 -0
  37. package/src/assets/web-panel/assets/MarkdownRenderer-nFgRqRUW.js +1 -0
  38. package/src/assets/web-panel/assets/{Marketplace-DpPu6XQp.js → Marketplace-DQ76qwhE.js} +1 -1
  39. package/src/assets/web-panel/assets/{McpTools-BR0ksiax.js → McpTools-CZqTYtmV.js} +3 -3
  40. package/src/assets/web-panel/assets/{Memory-BXznJ5-C.js → Memory-CWtnaJCd.js} +2 -2
  41. package/src/assets/web-panel/assets/{MobileBridge-BHSOpfv7.js → MobileBridge-C3Ngpr63.js} +1 -1
  42. package/src/assets/web-panel/assets/{MobileProjects-DdWmgIup.js → MobileProjects-CpJPlABd.js} +1 -1
  43. package/src/assets/web-panel/assets/{Mtc-D9Rk_IGT.js → Mtc-CKL_fDu2.js} +4 -4
  44. package/src/assets/web-panel/assets/{MtcAudit--i8q1lKc.js → MtcAudit-CIDSj87F.js} +2 -2
  45. package/src/assets/web-panel/assets/{Multisig-BHnNG7R9.js → Multisig-BoLpIo5g.js} +3 -3
  46. package/src/assets/web-panel/assets/{NLProgramming-Duo1ij2_.js → NLProgramming-CWJX8SH5.js} +1 -1
  47. package/src/assets/web-panel/assets/{Notes-B44Le73p.js → Notes-CdGvaOEe.js} +3 -3
  48. package/src/assets/web-panel/assets/{NotificationSettings-C3oy_7Gf.js → NotificationSettings-C067lOY0.js} +1 -1
  49. package/src/assets/web-panel/assets/{OrderTableRenderer-Da_73SI5.js → OrderTableRenderer-Bkdj8JZF.js} +1 -1
  50. package/src/assets/web-panel/assets/{Organization-ChsSwKxT.js → Organization-CwhP3jqH.js} +4 -4
  51. package/src/assets/web-panel/assets/{Overflow-DR5G_cCn.js → Overflow-Ks7pF8mI.js} +1 -1
  52. package/src/assets/web-panel/assets/{P2P-yfaobqow.js → P2P-BytzAo-_.js} +2 -2
  53. package/src/assets/web-panel/assets/PdhVaultBrowser-f7PUa-As.js +7 -0
  54. package/src/assets/web-panel/assets/{Permissions-DhinFvtE.js → Permissions-DYgQYc6c.js} +4 -4
  55. package/src/assets/web-panel/assets/{PersonalDataHub-CfeNVic1.js → PersonalDataHub-xa4C85B5.js} +3 -3
  56. package/src/assets/web-panel/assets/{Pipeline-CGKO26Nk.js → Pipeline-Ci4P4D_9.js} +1 -1
  57. package/src/assets/web-panel/assets/{Privacy-CxxfYEJh.js → Privacy-Bc0i4kUv.js} +1 -1
  58. package/src/assets/web-panel/assets/{ProjectInit-CZsaAab9.js → ProjectInit-BNQNNbq1.js} +2 -2
  59. package/src/assets/web-panel/assets/{ProjectSettings-BUm_6clQ.js → ProjectSettings-C9a52UVV.js} +2 -2
  60. package/src/assets/web-panel/assets/Projects-DoqbdOhN.js +1 -0
  61. package/src/assets/web-panel/assets/{Providers-D28VqPja.js → Providers-aqNSVXqu.js} +1 -1
  62. package/src/assets/web-panel/assets/{QrScannerModal-Cj200vUb.js → QrScannerModal-BhiK-alo.js} +1 -1
  63. package/src/assets/web-panel/assets/{QuickAsk-BGpnEiam.js → QuickAsk-DqiqZt1A.js} +1 -1
  64. package/src/assets/web-panel/assets/{Recommend-Ix79Tpni.js → Recommend-c0WOkaCq.js} +1 -1
  65. package/src/assets/web-panel/assets/{RemoteSession-BdGAFbIk.js → RemoteSession-Cf_4L-X3.js} +2 -2
  66. package/src/assets/web-panel/assets/{Reputation-B1Lis0Wk.js → Reputation-BVFrZQ_z.js} +1 -1
  67. package/src/assets/web-panel/assets/{Row-Ba_okwOW.js → Row-CZ1AwkDl.js} +1 -1
  68. package/src/assets/web-panel/assets/{RssFeed-DDbEuI-m.js → RssFeed--WyTTgfC.js} +3 -3
  69. package/src/assets/web-panel/assets/{Search-D89wAkMy.js → Search-BgxZ24St.js} +1 -1
  70. package/src/assets/web-panel/assets/{Security-CJKCKAU-.js → Security-DVkmHsXI.js} +2 -2
  71. package/src/assets/web-panel/assets/{Services-mitEc1XV.js → Services-CTZQQWlI.js} +2 -2
  72. package/src/assets/web-panel/assets/{Skeleton-CnBjLDfX.js → Skeleton-DWwUMTlS.js} +1 -1
  73. package/src/assets/web-panel/assets/{Skills-DSzDYvH3.js → Skills-D6iyc72U.js} +1 -1
  74. package/src/assets/web-panel/assets/{Sla-CglJ_4p3.js → Sla-ChMCfgKV.js} +1 -1
  75. package/src/assets/web-panel/assets/SpeechSettings-CtwWxhK7.js +1 -0
  76. package/src/assets/web-panel/assets/{SyncSettings-Cq7o6fmr.js → SyncSettings-DAbLxMOM.js} +2 -2
  77. package/src/assets/web-panel/assets/Tasks-Dvm355ug.js +1 -0
  78. package/src/assets/web-panel/assets/{Templates-bY0wSbQM.js → Templates-Dig8IEP-.js} +1 -1
  79. package/src/assets/web-panel/assets/{Tenant-BAyyl0qX.js → Tenant-DeR5U47w.js} +1 -1
  80. package/src/assets/web-panel/assets/{Terminal-BGBhSpqc.js → Terminal-CHXg-gsD.js} +2 -2
  81. package/src/assets/web-panel/assets/{TimelineRenderer-BvW5lXYz.js → TimelineRenderer-Bi4GJgwI.js} +1 -1
  82. package/src/assets/web-panel/assets/{Tokens-Ua_LIx8-.js → Tokens-D6ubE4ut.js} +1 -1
  83. package/src/assets/web-panel/assets/{Trigger-BGwb2KL1.js → Trigger-CUQI4HlL.js} +1 -1
  84. package/src/assets/web-panel/assets/{Trust-CD2IEHvj.js → Trust-CgTAWXd7.js} +1 -1
  85. package/src/assets/web-panel/assets/{UkeySign-D5LetK6P.js → UkeySign-R2bAawIX.js} +1 -1
  86. package/src/assets/web-panel/assets/{VideoEditing-oP7ehFgR.js → VideoEditing-46u-3sdP.js} +1 -1
  87. package/src/assets/web-panel/assets/{Wallet-BBtu4-xa.js → Wallet-DdrACErK.js} +2 -2
  88. package/src/assets/web-panel/assets/{WebAuthn-iSPRU4Ht.js → WebAuthn-Cq266Ihg.js} +2 -2
  89. package/src/assets/web-panel/assets/{WorkflowEditor-DuEDhQmB.js → WorkflowEditor-DV0ES1wc.js} +1 -1
  90. package/src/assets/web-panel/assets/{chat-DGDgqvvm.js → chat-D5xy9-vl.js} +1 -1
  91. package/src/assets/web-panel/assets/{colors-DGQMWa1-.js → colors-BBs5Knx_.js} +1 -1
  92. package/src/assets/web-panel/assets/{compact-item-COVznBL4.js → compact-item-BuFzMOeP.js} +1 -1
  93. package/src/assets/web-panel/assets/{createContext-DIxVeHXI.js → createContext-D6gC8UX1.js} +1 -1
  94. package/src/assets/web-panel/assets/devWarning-jGzCD1Og.js +1 -0
  95. package/src/assets/web-panel/assets/{hasIn-DkxZO3E9.js → hasIn-kBeod51t.js} +1 -1
  96. package/src/assets/web-panel/assets/{index-DV0H83eS.js → index-43tYtngc.js} +1 -1
  97. package/src/assets/web-panel/assets/{index-BAL2p7YC.js → index-8LcW9fNg.js} +1 -1
  98. package/src/assets/web-panel/assets/{index-BgM-3a1w.js → index-AVkVBAgT.js} +1 -1
  99. package/src/assets/web-panel/assets/{index-BQm7ntcn.js → index-B9sYKnfE.js} +1 -1
  100. package/src/assets/web-panel/assets/{index-BOTshZNx.js → index-BEipvyo3.js} +1 -1
  101. package/src/assets/web-panel/assets/{index-CV0KnNqR.js → index-BJtaYRSM.js} +1 -1
  102. package/src/assets/web-panel/assets/{index-b2_M6o20.js → index-BNgGahh_.js} +1 -1
  103. package/src/assets/web-panel/assets/{index-jo7DbU0w.js → index-BPfLeT9D.js} +1 -1
  104. package/src/assets/web-panel/assets/{index-CpZxDiVK.js → index-BrmMhNQe.js} +1 -1
  105. package/src/assets/web-panel/assets/{index-BBw2MLIe.js → index-C61TSHk7.js} +1 -1
  106. package/src/assets/web-panel/assets/{index-usmG13jq.js → index-C9RbA1u6.js} +1 -1
  107. package/src/assets/web-panel/assets/{index-DaWQSp5a.js → index-CDc8ZBhw.js} +1 -1
  108. package/src/assets/web-panel/assets/{index-b_0qTo8O.js → index-CSR6G5y_.js} +1 -1
  109. package/src/assets/web-panel/assets/{index-Ci34vbh0.js → index-Cc0nr-mJ.js} +1 -1
  110. package/src/assets/web-panel/assets/{index-vXrktF3e.js → index-CdXTYNGI.js} +1 -1
  111. package/src/assets/web-panel/assets/{index-C3bN6751.js → index-CoF4d2sR.js} +1 -1
  112. package/src/assets/web-panel/assets/{index-DU1ArKl5.js → index-Cy8WOPIM.js} +1 -1
  113. package/src/assets/web-panel/assets/{index-BY6MSbWT.js → index-D5w7mVUz.js} +1 -1
  114. package/src/assets/web-panel/assets/{index-CcNGQWum.js → index-D8i4RtvF.js} +1 -1
  115. package/src/assets/web-panel/assets/{index-DDwPBGdA.js → index-D8vRjV35.js} +1 -1
  116. package/src/assets/web-panel/assets/{index-BY9Ossof.js → index-DLO3EJ28.js} +1 -1
  117. package/src/assets/web-panel/assets/{index-BHH95jcm.js → index-DP74sxrD.js} +1 -1
  118. package/src/assets/web-panel/assets/{index-Bv0_u0ze.js → index-DT8dVo6h.js} +1 -1
  119. package/src/assets/web-panel/assets/{index-CNRRrP3-.js → index-DVY9bZaC.js} +1 -1
  120. package/src/assets/web-panel/assets/index-DVuuRGW6.js +1 -0
  121. package/src/assets/web-panel/assets/{index-BAlrovUm.js → index-DWpwO1tg.js} +1 -1
  122. package/src/assets/web-panel/assets/{index-ZcqTvPnt.js → index-Db_4IGgr.js} +1 -1
  123. package/src/assets/web-panel/assets/{index-dfYkGovV.js → index-DiEf8pdZ.js} +1 -1
  124. package/src/assets/web-panel/assets/{index-C3XeNS82.js → index-DjJD0ItG.js} +3 -3
  125. package/src/assets/web-panel/assets/index-DjkHUbjO.js +1 -0
  126. package/src/assets/web-panel/assets/{index-BUqwlzc8.js → index-DkcAtMWM.js} +1 -1
  127. package/src/assets/web-panel/assets/{index-CyMHF2Bi.js → index-Dn4FQfDW.js} +1 -1
  128. package/src/assets/web-panel/assets/{index-2JZizEPc.js → index-DuFsuweQ.js} +1 -1
  129. package/src/assets/web-panel/assets/{index-DmduvOYT.js → index-WMRvzqet.js} +1 -1
  130. package/src/assets/web-panel/assets/{index-Cligb-Dl.js → index-Xmeq1989.js} +1 -1
  131. package/src/assets/web-panel/assets/{index-ECoDhyH3.js → index-ZMxLi0bZ.js} +1 -1
  132. package/src/assets/web-panel/assets/{index-CokrhbY2.js → index-_j1YrDlh.js} +1 -1
  133. package/src/assets/web-panel/assets/{index-ClQVcrFt.js → index-qXVSh34h.js} +1 -1
  134. package/src/assets/web-panel/assets/{index-0ToBFsvW.js → index-slOdrjUJ.js} +1 -1
  135. package/src/assets/web-panel/assets/{initDefaultProps-CkSeiBwL.js → initDefaultProps-CdcTIUHj.js} +1 -1
  136. package/src/assets/web-panel/assets/{motion-CSzhDP0s.js → motion-DMIDKmqt.js} +1 -1
  137. package/src/assets/web-panel/assets/{move-mgCt4iC6.js → move-DRq4Pk0-.js} +1 -1
  138. package/src/assets/web-panel/assets/{mtc-parser-BEZBLcKt.js → mtc-parser-SYFo5WKx.js} +1 -1
  139. package/src/assets/web-panel/assets/{omit-BsHctMEr.js → omit-B_X6VxfU.js} +1 -1
  140. package/src/assets/web-panel/assets/{pickAttrs-1BHamnGW.js → pickAttrs-DnuDKnw_.js} +1 -1
  141. package/src/assets/web-panel/assets/{placementArrow--Vb4Bd7l.js → placementArrow-DBFRmoTN.js} +1 -1
  142. package/src/assets/web-panel/assets/{responsiveObserve-DD33SqCm.js → responsiveObserve-BaUVjf33.js} +1 -1
  143. package/src/assets/web-panel/assets/{slide-DfrLtxgK.js → slide-rLCDXDVC.js} +1 -1
  144. package/src/assets/web-panel/assets/{statusUtils-D9Pe_gXW.js → statusUtils-CzNprwdC.js} +1 -1
  145. package/src/assets/web-panel/assets/{styleChecker-0NY5iMun.js → styleChecker-DsaDdSa9.js} +1 -1
  146. package/src/assets/web-panel/assets/{useFlexGapSupport-DSsZstwg.js → useFlexGapSupport-BKHgNy2p.js} +1 -1
  147. package/src/assets/web-panel/assets/{useFs-BU8HyH59.js → useFs-C_OQYo_E.js} +1 -1
  148. package/src/assets/web-panel/assets/{usePersonalDataHub-D_xttink.js → usePersonalDataHub-CiGRKQ5k.js} +1 -1
  149. package/src/assets/web-panel/assets/{vnode-39VhX2lM.js → vnode-C9-ch6HP.js} +1 -1
  150. package/src/assets/web-panel/assets/{zoom-D5KQ8Pks.js → zoom-HoUcoyA4.js} +1 -1
  151. package/src/assets/web-panel/index.html +1 -1
  152. package/src/command-help-index.json +1 -1
  153. package/src/commands/agent.js +84 -0
  154. package/src/data/changelog.json +26 -0
  155. package/src/lib/decision-layer/benchmark.js +164 -0
  156. package/src/lib/decision-layer/contracts.js +377 -0
  157. package/src/lib/decision-layer/provider-authority.js +44 -0
  158. package/src/lib/decision-layer/runtime.js +238 -0
  159. package/src/lib/decision-layer/typesafe-provider.js +74 -0
  160. package/src/lib/evolution/evolution-deployment-loader.js +39 -0
  161. package/src/lib/evolution/skill-writer-inventory-manifest.js +0 -39
  162. package/src/lib/evolution/volcengine-function-execution-authority.js +2949 -0
  163. package/src/lib/evolution/volcengine-function-process-executor.js +615 -0
  164. package/src/lib/evolution/volcengine-function-replay-store.js +836 -0
  165. package/src/lib/evolution/volcengine-function-revocation-status-floor-store.js +480 -0
  166. package/src/runtime/agent-core.js +49 -0
  167. package/src/runtime/headless-runner.js +79 -0
  168. package/src/assets/web-panel/assets/ChatBubbleRenderer-Bpf1hDUl.js +0 -1
  169. package/src/assets/web-panel/assets/Logs-Co2EPLsJ.js +0 -2
  170. package/src/assets/web-panel/assets/MarkdownRenderer-D7wIB-c7.js +0 -1
  171. package/src/assets/web-panel/assets/PdhVaultBrowser-DgimH6Jp.js +0 -7
  172. package/src/assets/web-panel/assets/Projects-Capr8bVq.js +0 -1
  173. package/src/assets/web-panel/assets/SpeechSettings-BicWJS7f.js +0 -1
  174. package/src/assets/web-panel/assets/Tasks-DOxFOBpU.js +0 -1
  175. package/src/assets/web-panel/assets/devWarning-CjR9h-Z_.js +0 -1
  176. package/src/assets/web-panel/assets/index-D_nxBMX5.js +0 -1
  177. package/src/assets/web-panel/assets/index-z_cTUMX-.js +0 -1
@@ -0,0 +1,2949 @@
1
+ import {
2
+ createHash,
3
+ createPrivateKey,
4
+ createPublicKey,
5
+ verify as verifySignature,
6
+ } from "node:crypto";
7
+ import { types } from "node:util";
8
+
9
+ import {
10
+ VOLCENGINE_FUNCTION_REPLAY_MODE,
11
+ VOLCENGINE_FUNCTION_REPLAY_RESERVATION_SCHEMA,
12
+ VOLCENGINE_FUNCTION_REPLAY_STORE_SCHEMA,
13
+ VOLCENGINE_FUNCTION_REVOCATION_MODE,
14
+ VOLCENGINE_FUNCTION_REVOCATION_SCHEMA,
15
+ captureVolcengineFunctionReplayStore,
16
+ } from "./volcengine-function-replay-store.js";
17
+ import {
18
+ VOLCENGINE_FUNCTION_PROCESS_EVIDENCE_SCHEMA,
19
+ captureVolcengineFunctionProcessResult,
20
+ inspectVolcengineFunctionProcessExecutor,
21
+ } from "./volcengine-function-process-executor.js";
22
+ import {
23
+ VOLCENGINE_FUNCTION_REVOCATION_STATUS_ACK_SCHEMA,
24
+ VOLCENGINE_FUNCTION_REVOCATION_STATUS_SNAPSHOT_SCHEMA,
25
+ captureVolcengineFunctionRevocationStatusFloorStore,
26
+ inspectVolcengineFunctionRevocationStatusFloorStore,
27
+ } from "./volcengine-function-revocation-status-floor-store.js";
28
+
29
+ export const VOLCENGINE_FUNCTION_AUTHORITY_SCHEMA =
30
+ "chainlesschain.volcengine-function-authority/v6";
31
+ export const VOLCENGINE_FUNCTION_REQUEST_SCHEMA =
32
+ "chainlesschain.volcengine-function-request/v6";
33
+ export const VOLCENGINE_FUNCTION_RECEIPT_SCHEMA =
34
+ "chainlesschain.volcengine-function-receipt/v6";
35
+ export const VOLCENGINE_FUNCTION_AUDIT_EVIDENCE_SCHEMA =
36
+ "chainlesschain.volcengine-function-audit-evidence/v6";
37
+ export const VOLCENGINE_FUNCTION_PROCESS_AUTHORITY_SCHEMA =
38
+ "chainlesschain.volcengine-function-authority/v7";
39
+ export const VOLCENGINE_FUNCTION_PROCESS_RECEIPT_SCHEMA =
40
+ "chainlesschain.volcengine-function-receipt/v7";
41
+ export const VOLCENGINE_FUNCTION_PROCESS_ISOLATION = "process-hard-termination";
42
+ export const VOLCENGINE_FUNCTION_PURPOSE = "model-tool-execution";
43
+ export const VOLCENGINE_FUNCTION_AUDIT_MODE = "authenticated-durable-readback";
44
+ export const VOLCENGINE_FUNCTION_EXECUTOR_TYPE = "capability";
45
+ export const VOLCENGINE_FUNCTION_REVOCATION_AUTHORITY_SCHEMA =
46
+ "chainlesschain.volcengine-function-revocation-authority/v2";
47
+ export const VOLCENGINE_FUNCTION_REVOCATION_REQUEST_SCHEMA =
48
+ "chainlesschain.volcengine-function-revocation-request/v1";
49
+ export const VOLCENGINE_FUNCTION_REVOCATION_RESULT_SCHEMA =
50
+ "chainlesschain.volcengine-function-revocation-result/v2";
51
+ export const VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_RESOLVER_SCHEMA =
52
+ "chainlesschain.volcengine-function-revocation-evidence-resolver/v5";
53
+ export const VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_REQUEST_SCHEMA =
54
+ "chainlesschain.volcengine-function-revocation-evidence-request/v1";
55
+ export const VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_READBACK_SCHEMA =
56
+ "chainlesschain.volcengine-function-revocation-evidence-readback/v2";
57
+ export const VOLCENGINE_FUNCTION_REVOCATION_AUTHORIZATION_EVIDENCE_SCHEMA =
58
+ "chainlesschain.volcengine-function-revocation-authorization-evidence/v1";
59
+ export const VOLCENGINE_FUNCTION_REVOCATION_SIGNER_CERTIFICATE_SCHEMA =
60
+ "chainlesschain.volcengine-function-revocation-signer-certificate/v1";
61
+ export const VOLCENGINE_FUNCTION_REVOCATION_SIGNER_REVOCATIONS_SCHEMA =
62
+ "chainlesschain.volcengine-function-revocation-signer-revocations/v1";
63
+ export const VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_MODE =
64
+ "digest-bound-exact-bytes";
65
+ export const VOLCENGINE_FUNCTION_REVOCATION_SIGNATURE_MODE =
66
+ "ed25519-certified-signer";
67
+ export const VOLCENGINE_FUNCTION_REVOCATION_CERTIFICATE_MODE =
68
+ "ed25519-root-signed-leaf";
69
+ export const VOLCENGINE_FUNCTION_REVOCATION_CERTIFICATE_STATUS_MODE =
70
+ "ed25519-root-signed-revocation-snapshot";
71
+ export const VOLCENGINE_FUNCTION_REVOCATION_PURPOSE =
72
+ "revoke-model-tool-execution";
73
+ export const VOLCENGINE_FUNCTION_REVOCATION_APPROVAL_MODE = "operator-signed";
74
+
75
+ const MAX_ARGUMENT_BYTES = 64 * 1024;
76
+ const MAX_RESULT_BYTES = 256 * 1024;
77
+ const MAX_JSON_DEPTH = 8;
78
+ const MAX_JSON_FIELDS = 512;
79
+ const MAX_POLICY_ARGUMENT_KEYS = 64;
80
+ const MAX_EXECUTION_MS = 120_000;
81
+ const MAX_REQUEST_AGE_MS = 60_000;
82
+ const MAX_CLOCK_SKEW_MS = 5_000;
83
+ const MAX_REPLAY_ENTRIES = 4_096;
84
+ const REPLAY_RETENTION_MS = MAX_REQUEST_AGE_MS + MAX_CLOCK_SKEW_MS;
85
+ const DIGEST = /^sha256:[a-f0-9]{64}$/u;
86
+ const ID = /^[^\p{Cc}]{1,512}$/u;
87
+ const BUILTIN_FUNCTIONS = Object.freeze([
88
+ "create_note",
89
+ "delete_note",
90
+ "get_note",
91
+ "get_system_info",
92
+ "list_files",
93
+ "read_file",
94
+ "search_notes",
95
+ "send_p2p_message",
96
+ "update_note",
97
+ ]);
98
+ const BUILTIN_FUNCTION_SET = new Set(BUILTIN_FUNCTIONS);
99
+ const authorities = new WeakMap();
100
+ const revocationAuthorities = new WeakMap();
101
+ const revocationEvidenceResolvers = new WeakMap();
102
+
103
+ function canonical(value) {
104
+ if (value === null || typeof value !== "object") {
105
+ return JSON.stringify(value);
106
+ }
107
+ if (Array.isArray(value)) {
108
+ return `[${value.map(canonical).join(",")}]`;
109
+ }
110
+ return `{${Object.keys(value)
111
+ .sort()
112
+ .map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`)
113
+ .join(",")}}`;
114
+ }
115
+
116
+ function digest(domain, value) {
117
+ return `sha256:${createHash("sha256")
118
+ .update(`${domain}\0`)
119
+ .update(canonical(value))
120
+ .digest("hex")}`;
121
+ }
122
+
123
+ function digestBytes(value) {
124
+ return `sha256:${createHash("sha256").update(value).digest("hex")}`;
125
+ }
126
+
127
+ function exactData(value, keys, label) {
128
+ if (
129
+ !value ||
130
+ typeof value !== "object" ||
131
+ Array.isArray(value) ||
132
+ types.isProxy(value) ||
133
+ ![Object.prototype, null].includes(Object.getPrototypeOf(value)) ||
134
+ Reflect.ownKeys(value).length !== keys.length ||
135
+ keys.some((key) => {
136
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
137
+ return !descriptor?.enumerable || !Object.hasOwn(descriptor, "value");
138
+ })
139
+ ) {
140
+ throw new TypeError(`${label} has unexpected or accessor fields`);
141
+ }
142
+ }
143
+
144
+ function ownData(owner, name, label) {
145
+ const descriptor = Object.getOwnPropertyDescriptor(owner, name);
146
+ if (!descriptor || !Object.hasOwn(descriptor, "value")) {
147
+ throw new TypeError(`${label} must be plain data`);
148
+ }
149
+ return descriptor.value;
150
+ }
151
+
152
+ function directArrayValues(value, label, maxLength) {
153
+ if (
154
+ !Array.isArray(value) ||
155
+ types.isProxy(value) ||
156
+ value.length > maxLength
157
+ ) {
158
+ throw new TypeError(`${label} is invalid`);
159
+ }
160
+ const keys = Reflect.ownKeys(value);
161
+ if (
162
+ keys.length !== value.length + 1 ||
163
+ keys.some((key) => {
164
+ if (key === "length") return false;
165
+ if (typeof key !== "string" || !/^(?:0|[1-9]\d*)$/u.test(key)) {
166
+ return true;
167
+ }
168
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
169
+ const index = Number(key);
170
+ return (
171
+ !Number.isSafeInteger(index) ||
172
+ index >= value.length ||
173
+ !descriptor?.enumerable ||
174
+ !Object.hasOwn(descriptor, "value")
175
+ );
176
+ })
177
+ ) {
178
+ throw new TypeError(`${label} is invalid`);
179
+ }
180
+ return Array.from({ length: value.length }, (_unused, index) =>
181
+ ownData(value, String(index), label),
182
+ );
183
+ }
184
+
185
+ function cloneJson(value, label, state, depth) {
186
+ if (value === null || typeof value === "boolean") return value;
187
+ if (typeof value === "string") {
188
+ if (value.length > MAX_RESULT_BYTES || value.includes("\u0000")) {
189
+ throw new TypeError(`${label} contains an invalid string`);
190
+ }
191
+ return value;
192
+ }
193
+ if (typeof value === "number") {
194
+ if (!Number.isFinite(value)) {
195
+ throw new TypeError(`${label} contains an invalid number`);
196
+ }
197
+ return value;
198
+ }
199
+ if (typeof value !== "object" || types.isProxy(value)) {
200
+ throw new TypeError(`${label} is not JSON data`);
201
+ }
202
+ if (depth >= MAX_JSON_DEPTH || state.ancestors.has(value)) {
203
+ throw new TypeError(`${label} is too deep or cyclic`);
204
+ }
205
+ state.ancestors.add(value);
206
+ try {
207
+ if (Array.isArray(value)) {
208
+ const entries = directArrayValues(value, label, MAX_JSON_FIELDS);
209
+ state.fields += entries.length;
210
+ if (state.fields > MAX_JSON_FIELDS) {
211
+ throw new TypeError(`${label} has too many fields`);
212
+ }
213
+ return Object.freeze(
214
+ entries.map((entry) => cloneJson(entry, label, state, depth + 1)),
215
+ );
216
+ }
217
+ if (![Object.prototype, null].includes(Object.getPrototypeOf(value))) {
218
+ throw new TypeError(`${label} is not plain JSON data`);
219
+ }
220
+ const keys = Reflect.ownKeys(value);
221
+ state.fields += keys.length;
222
+ if (state.fields > MAX_JSON_FIELDS) {
223
+ throw new TypeError(`${label} has too many fields`);
224
+ }
225
+ const projected = {};
226
+ for (const key of keys) {
227
+ const descriptor = Object.getOwnPropertyDescriptor(value, key);
228
+ if (
229
+ typeof key !== "string" ||
230
+ key.length < 1 ||
231
+ key.length > 256 ||
232
+ /\p{Cc}/u.test(key) ||
233
+ ["__proto__", "constructor", "prototype"].includes(key) ||
234
+ !descriptor?.enumerable ||
235
+ !Object.hasOwn(descriptor, "value")
236
+ ) {
237
+ throw new TypeError(`${label} has unexpected or accessor fields`);
238
+ }
239
+ projected[key] = cloneJson(descriptor.value, label, state, depth + 1);
240
+ }
241
+ return Object.freeze(projected);
242
+ } finally {
243
+ state.ancestors.delete(value);
244
+ }
245
+ }
246
+
247
+ function normalizeJson(value, label, maxBytes) {
248
+ const normalized = cloneJson(
249
+ value,
250
+ label,
251
+ { ancestors: new Set(), fields: 0 },
252
+ 0,
253
+ );
254
+ if (Buffer.byteLength(JSON.stringify(normalized), "utf8") > maxBytes) {
255
+ throw new TypeError(`${label} is too large`);
256
+ }
257
+ return normalized;
258
+ }
259
+
260
+ export function digestVolcengineFunctionResult(value) {
261
+ return digest(
262
+ "chainlesschain.volcengine-function-result/v1",
263
+ normalizeJson(value, "Volcengine function result", MAX_RESULT_BYTES),
264
+ );
265
+ }
266
+
267
+ function normalizeAllowedFunctions(value) {
268
+ const names = directArrayValues(
269
+ value,
270
+ "Volcengine function authority allowlist",
271
+ BUILTIN_FUNCTIONS.length,
272
+ );
273
+ if (
274
+ names.some((name) => !BUILTIN_FUNCTION_SET.has(name)) ||
275
+ new Set(names).size !== names.length ||
276
+ [...names].sort().some((name, index) => name !== names[index])
277
+ ) {
278
+ throw new TypeError("Volcengine function authority allowlist is invalid");
279
+ }
280
+ return Object.freeze([...names]);
281
+ }
282
+
283
+ function normalizeArgumentKeys(value, label) {
284
+ const keys = directArrayValues(value, label, MAX_POLICY_ARGUMENT_KEYS);
285
+ if (
286
+ keys.some(
287
+ (key) =>
288
+ typeof key !== "string" ||
289
+ key.length < 1 ||
290
+ key.length > 256 ||
291
+ /\p{Cc}/u.test(key) ||
292
+ ["__proto__", "constructor", "prototype"].includes(key),
293
+ ) ||
294
+ new Set(keys).size !== keys.length ||
295
+ [...keys].sort().some((key, index) => key !== keys[index])
296
+ ) {
297
+ throw new TypeError(`${label} is invalid`);
298
+ }
299
+ return Object.freeze([...keys]);
300
+ }
301
+
302
+ function normalizeFunctionPolicies(value, allowedFunctions) {
303
+ const entries = directArrayValues(
304
+ value,
305
+ "Volcengine function policies",
306
+ BUILTIN_FUNCTIONS.length,
307
+ );
308
+ const policies = entries.map((entry) => {
309
+ exactData(
310
+ entry,
311
+ [
312
+ "functionName",
313
+ "allowedArgumentKeys",
314
+ "maxArgumentBytes",
315
+ "maxResultBytes",
316
+ "maxExecutionMs",
317
+ ],
318
+ "Volcengine function policy",
319
+ );
320
+ const policy = Object.freeze({
321
+ functionName: ownData(
322
+ entry,
323
+ "functionName",
324
+ "Volcengine function policy name",
325
+ ),
326
+ allowedArgumentKeys: normalizeArgumentKeys(
327
+ ownData(
328
+ entry,
329
+ "allowedArgumentKeys",
330
+ "Volcengine function policy argument keys",
331
+ ),
332
+ "Volcengine function policy argument keys",
333
+ ),
334
+ maxArgumentBytes: ownData(
335
+ entry,
336
+ "maxArgumentBytes",
337
+ "Volcengine function policy argument budget",
338
+ ),
339
+ maxResultBytes: ownData(
340
+ entry,
341
+ "maxResultBytes",
342
+ "Volcengine function policy result budget",
343
+ ),
344
+ maxExecutionMs: ownData(
345
+ entry,
346
+ "maxExecutionMs",
347
+ "Volcengine function policy execution deadline",
348
+ ),
349
+ });
350
+ if (
351
+ !BUILTIN_FUNCTION_SET.has(policy.functionName) ||
352
+ !Number.isSafeInteger(policy.maxArgumentBytes) ||
353
+ policy.maxArgumentBytes < 2 ||
354
+ policy.maxArgumentBytes > MAX_ARGUMENT_BYTES ||
355
+ !Number.isSafeInteger(policy.maxResultBytes) ||
356
+ policy.maxResultBytes < 1 ||
357
+ policy.maxResultBytes > MAX_RESULT_BYTES ||
358
+ !Number.isSafeInteger(policy.maxExecutionMs) ||
359
+ policy.maxExecutionMs < 1 ||
360
+ policy.maxExecutionMs > MAX_EXECUTION_MS
361
+ ) {
362
+ throw new TypeError("Volcengine function policy is invalid");
363
+ }
364
+ return policy;
365
+ });
366
+ if (
367
+ policies.length !== allowedFunctions.length ||
368
+ policies.some(
369
+ (policy, index) => policy.functionName !== allowedFunctions[index],
370
+ )
371
+ ) {
372
+ throw new TypeError(
373
+ "Volcengine function policies must exactly cover the allowlist",
374
+ );
375
+ }
376
+ return Object.freeze(policies);
377
+ }
378
+
379
+ function functionPolicy(descriptor, functionName) {
380
+ return descriptor.functionPolicies.find(
381
+ (policy) => policy.functionName === functionName,
382
+ );
383
+ }
384
+
385
+ function digestFunctionPolicy(policy) {
386
+ return digest("chainlesschain.volcengine-function-policy/v1", policy);
387
+ }
388
+
389
+ function validatePolicyArguments(value, policy) {
390
+ if (
391
+ value === null ||
392
+ typeof value !== "object" ||
393
+ Array.isArray(value) ||
394
+ Object.keys(value).some((key) => !policy.allowedArgumentKeys.includes(key))
395
+ ) {
396
+ throw new TypeError("Volcengine function arguments violate policy");
397
+ }
398
+ }
399
+
400
+ function normalizeDescriptor(value) {
401
+ exactData(
402
+ value,
403
+ [
404
+ "schema",
405
+ "authorityId",
406
+ "revocationAuthorityId",
407
+ "tenantId",
408
+ "handlerArtifactDigest",
409
+ "policyRevision",
410
+ "replayStoreId",
411
+ "replayRetentionMs",
412
+ "replayMode",
413
+ "revocationMode",
414
+ "purpose",
415
+ "allowedFunctions",
416
+ "functionPolicies",
417
+ "auditMode",
418
+ ],
419
+ "Volcengine function authority descriptor",
420
+ );
421
+ const allowedFunctions = normalizeAllowedFunctions(
422
+ ownData(
423
+ value,
424
+ "allowedFunctions",
425
+ "Volcengine function authority allowlist",
426
+ ),
427
+ );
428
+ const descriptor = Object.freeze({
429
+ schema: ownData(value, "schema", "Volcengine function authority schema"),
430
+ authorityId: ownData(
431
+ value,
432
+ "authorityId",
433
+ "Volcengine function authority identifier",
434
+ ),
435
+ revocationAuthorityId: ownData(
436
+ value,
437
+ "revocationAuthorityId",
438
+ "Volcengine function revocation authority identifier",
439
+ ),
440
+ tenantId: ownData(
441
+ value,
442
+ "tenantId",
443
+ "Volcengine function authority tenant",
444
+ ),
445
+ handlerArtifactDigest: ownData(
446
+ value,
447
+ "handlerArtifactDigest",
448
+ "Volcengine function authority artifact digest",
449
+ ),
450
+ policyRevision: ownData(
451
+ value,
452
+ "policyRevision",
453
+ "Volcengine function authority policy revision",
454
+ ),
455
+ replayStoreId: ownData(
456
+ value,
457
+ "replayStoreId",
458
+ "Volcengine function replay store identifier",
459
+ ),
460
+ replayRetentionMs: ownData(
461
+ value,
462
+ "replayRetentionMs",
463
+ "Volcengine function replay retention",
464
+ ),
465
+ replayMode: ownData(value, "replayMode", "Volcengine function replay mode"),
466
+ revocationMode: ownData(
467
+ value,
468
+ "revocationMode",
469
+ "Volcengine function revocation mode",
470
+ ),
471
+ purpose: ownData(value, "purpose", "Volcengine function authority purpose"),
472
+ allowedFunctions,
473
+ functionPolicies: normalizeFunctionPolicies(
474
+ ownData(
475
+ value,
476
+ "functionPolicies",
477
+ "Volcengine function authority policies",
478
+ ),
479
+ allowedFunctions,
480
+ ),
481
+ auditMode: ownData(
482
+ value,
483
+ "auditMode",
484
+ "Volcengine function authority audit mode",
485
+ ),
486
+ });
487
+ if (
488
+ descriptor.schema !== VOLCENGINE_FUNCTION_AUTHORITY_SCHEMA ||
489
+ !ID.test(descriptor.authorityId) ||
490
+ !ID.test(descriptor.revocationAuthorityId) ||
491
+ !ID.test(descriptor.tenantId) ||
492
+ !DIGEST.test(descriptor.handlerArtifactDigest) ||
493
+ !ID.test(descriptor.policyRevision) ||
494
+ !ID.test(descriptor.replayStoreId) ||
495
+ !Number.isSafeInteger(descriptor.replayRetentionMs) ||
496
+ descriptor.replayRetentionMs < REPLAY_RETENTION_MS ||
497
+ descriptor.replayRetentionMs > 24 * 60 * 60 * 1000 ||
498
+ descriptor.replayMode !== VOLCENGINE_FUNCTION_REPLAY_MODE ||
499
+ descriptor.revocationMode !== VOLCENGINE_FUNCTION_REVOCATION_MODE ||
500
+ descriptor.purpose !== VOLCENGINE_FUNCTION_PURPOSE ||
501
+ descriptor.auditMode !== VOLCENGINE_FUNCTION_AUDIT_MODE
502
+ ) {
503
+ throw new TypeError("Volcengine function authority descriptor is invalid");
504
+ }
505
+ return descriptor;
506
+ }
507
+
508
+ function normalizeProcessDescriptor(value) {
509
+ const baseKeys = [
510
+ "authorityId",
511
+ "revocationAuthorityId",
512
+ "tenantId",
513
+ "handlerArtifactDigest",
514
+ "policyRevision",
515
+ "replayStoreId",
516
+ "replayRetentionMs",
517
+ "replayMode",
518
+ "revocationMode",
519
+ "purpose",
520
+ "allowedFunctions",
521
+ "functionPolicies",
522
+ "auditMode",
523
+ ];
524
+ exactData(
525
+ value,
526
+ [
527
+ "schema",
528
+ ...baseKeys,
529
+ "executionIsolation",
530
+ "processTargetDigest",
531
+ "processTargetAuthorityDigest",
532
+ "processSupervisorAuthorityDigest",
533
+ ],
534
+ "Volcengine process function authority descriptor",
535
+ );
536
+ if (
537
+ ownData(value, "schema", "Volcengine process authority schema") !==
538
+ VOLCENGINE_FUNCTION_PROCESS_AUTHORITY_SCHEMA
539
+ ) {
540
+ throw new TypeError(
541
+ "Volcengine process function authority descriptor is invalid",
542
+ );
543
+ }
544
+ const baseInput = { schema: VOLCENGINE_FUNCTION_AUTHORITY_SCHEMA };
545
+ for (const key of baseKeys) {
546
+ baseInput[key] = ownData(value, key, `Volcengine process authority ${key}`);
547
+ }
548
+ const base = normalizeDescriptor(baseInput);
549
+ const descriptor = Object.freeze({
550
+ ...base,
551
+ schema: VOLCENGINE_FUNCTION_PROCESS_AUTHORITY_SCHEMA,
552
+ executionIsolation: ownData(
553
+ value,
554
+ "executionIsolation",
555
+ "Volcengine function execution isolation",
556
+ ),
557
+ processTargetDigest: ownData(
558
+ value,
559
+ "processTargetDigest",
560
+ "Volcengine function process target digest",
561
+ ),
562
+ processTargetAuthorityDigest: ownData(
563
+ value,
564
+ "processTargetAuthorityDigest",
565
+ "Volcengine function process target authority digest",
566
+ ),
567
+ processSupervisorAuthorityDigest: ownData(
568
+ value,
569
+ "processSupervisorAuthorityDigest",
570
+ "Volcengine function process supervisor authority digest",
571
+ ),
572
+ });
573
+ if (
574
+ descriptor.executionIsolation !== VOLCENGINE_FUNCTION_PROCESS_ISOLATION ||
575
+ !DIGEST.test(descriptor.processTargetDigest) ||
576
+ !DIGEST.test(descriptor.processTargetAuthorityDigest) ||
577
+ !DIGEST.test(descriptor.processSupervisorAuthorityDigest)
578
+ ) {
579
+ throw new TypeError(
580
+ "Volcengine process function authority descriptor is invalid",
581
+ );
582
+ }
583
+ return descriptor;
584
+ }
585
+
586
+ function normalizeRequest(value, descriptor, nowMs) {
587
+ exactData(
588
+ value,
589
+ [
590
+ "schema",
591
+ "authorityId",
592
+ "revocationAuthorityId",
593
+ "tenantId",
594
+ "handlerArtifactDigest",
595
+ "policyRevision",
596
+ "replayStoreId",
597
+ "revocationMode",
598
+ "actorDid",
599
+ "purpose",
600
+ "requestId",
601
+ "senderId",
602
+ "executorType",
603
+ "functionName",
604
+ "functionPolicyDigest",
605
+ "arguments",
606
+ "argumentsDigest",
607
+ "requestedAt",
608
+ "deadlineAt",
609
+ "requestDigest",
610
+ ],
611
+ "Volcengine function request",
612
+ );
613
+ const requestedFunctionName = ownData(
614
+ value,
615
+ "functionName",
616
+ "Volcengine function name",
617
+ );
618
+ const policy = functionPolicy(descriptor, requestedFunctionName);
619
+ if (!policy) {
620
+ throw new TypeError("Volcengine function request is invalid");
621
+ }
622
+ const normalizedArguments = normalizeJson(
623
+ ownData(value, "arguments", "Volcengine function arguments"),
624
+ "Volcengine function arguments",
625
+ policy.maxArgumentBytes,
626
+ );
627
+ validatePolicyArguments(normalizedArguments, policy);
628
+ const core = Object.freeze({
629
+ schema: ownData(value, "schema", "Volcengine function request schema"),
630
+ authorityId: ownData(
631
+ value,
632
+ "authorityId",
633
+ "Volcengine function request authority",
634
+ ),
635
+ revocationAuthorityId: ownData(
636
+ value,
637
+ "revocationAuthorityId",
638
+ "Volcengine function request revocation authority",
639
+ ),
640
+ tenantId: ownData(value, "tenantId", "Volcengine function request tenant"),
641
+ handlerArtifactDigest: ownData(
642
+ value,
643
+ "handlerArtifactDigest",
644
+ "Volcengine function request artifact digest",
645
+ ),
646
+ policyRevision: ownData(
647
+ value,
648
+ "policyRevision",
649
+ "Volcengine function request policy revision",
650
+ ),
651
+ replayStoreId: ownData(
652
+ value,
653
+ "replayStoreId",
654
+ "Volcengine function request replay store",
655
+ ),
656
+ revocationMode: ownData(
657
+ value,
658
+ "revocationMode",
659
+ "Volcengine function request revocation mode",
660
+ ),
661
+ actorDid: ownData(value, "actorDid", "Volcengine function request actor"),
662
+ purpose: ownData(value, "purpose", "Volcengine function request purpose"),
663
+ requestId: ownData(
664
+ value,
665
+ "requestId",
666
+ "Volcengine function request identifier",
667
+ ),
668
+ senderId: ownData(value, "senderId", "Volcengine function request sender"),
669
+ executorType: ownData(
670
+ value,
671
+ "executorType",
672
+ "Volcengine function executor type",
673
+ ),
674
+ functionName: requestedFunctionName,
675
+ functionPolicyDigest: ownData(
676
+ value,
677
+ "functionPolicyDigest",
678
+ "Volcengine function policy digest",
679
+ ),
680
+ arguments: normalizedArguments,
681
+ argumentsDigest: ownData(
682
+ value,
683
+ "argumentsDigest",
684
+ "Volcengine function arguments digest",
685
+ ),
686
+ requestedAt: ownData(
687
+ value,
688
+ "requestedAt",
689
+ "Volcengine function request time",
690
+ ),
691
+ deadlineAt: ownData(
692
+ value,
693
+ "deadlineAt",
694
+ "Volcengine function request deadline",
695
+ ),
696
+ });
697
+ const requestDigest = ownData(
698
+ value,
699
+ "requestDigest",
700
+ "Volcengine function request digest",
701
+ );
702
+ const requestedAtMs = Date.parse(core.requestedAt);
703
+ const deadlineAtMs = Date.parse(core.deadlineAt);
704
+ if (
705
+ core.schema !== VOLCENGINE_FUNCTION_REQUEST_SCHEMA ||
706
+ core.authorityId !== descriptor.authorityId ||
707
+ core.revocationAuthorityId !== descriptor.revocationAuthorityId ||
708
+ core.tenantId !== descriptor.tenantId ||
709
+ core.handlerArtifactDigest !== descriptor.handlerArtifactDigest ||
710
+ core.policyRevision !== descriptor.policyRevision ||
711
+ core.replayStoreId !== descriptor.replayStoreId ||
712
+ core.revocationMode !== descriptor.revocationMode ||
713
+ !ID.test(core.actorDid) ||
714
+ core.purpose !== VOLCENGINE_FUNCTION_PURPOSE ||
715
+ !ID.test(core.requestId) ||
716
+ !Number.isSafeInteger(core.senderId) ||
717
+ core.senderId < 0 ||
718
+ core.executorType !== VOLCENGINE_FUNCTION_EXECUTOR_TYPE ||
719
+ !descriptor.allowedFunctions.includes(core.functionName) ||
720
+ core.functionPolicyDigest !== digestFunctionPolicy(policy) ||
721
+ core.argumentsDigest !==
722
+ digest(
723
+ "chainlesschain.volcengine-function-arguments/v1",
724
+ normalizedArguments,
725
+ ) ||
726
+ !Number.isFinite(requestedAtMs) ||
727
+ new Date(requestedAtMs).toISOString() !== core.requestedAt ||
728
+ requestedAtMs < nowMs - MAX_REQUEST_AGE_MS ||
729
+ requestedAtMs > nowMs + MAX_CLOCK_SKEW_MS ||
730
+ !Number.isFinite(deadlineAtMs) ||
731
+ new Date(deadlineAtMs).toISOString() !== core.deadlineAt ||
732
+ deadlineAtMs <= nowMs ||
733
+ deadlineAtMs <= requestedAtMs ||
734
+ deadlineAtMs > requestedAtMs + policy.maxExecutionMs ||
735
+ requestDigest !==
736
+ digest("chainlesschain.volcengine-function-request/v6", core)
737
+ ) {
738
+ throw new TypeError("Volcengine function request is invalid");
739
+ }
740
+ return Object.freeze({
741
+ ...core,
742
+ requestDigest,
743
+ requestedAtMs,
744
+ deadlineAtMs,
745
+ });
746
+ }
747
+
748
+ function createReplayReservation(request, descriptor) {
749
+ const core = Object.freeze({
750
+ schema: VOLCENGINE_FUNCTION_REPLAY_RESERVATION_SCHEMA,
751
+ replayStoreId: descriptor.replayStoreId,
752
+ authorityId: descriptor.authorityId,
753
+ tenantId: descriptor.tenantId,
754
+ handlerArtifactDigest: descriptor.handlerArtifactDigest,
755
+ policyRevision: descriptor.policyRevision,
756
+ requestId: request.requestId,
757
+ requestDigest: request.requestDigest,
758
+ expiresAt: new Date(
759
+ request.deadlineAtMs + descriptor.replayRetentionMs,
760
+ ).toISOString(),
761
+ });
762
+ return Object.freeze({
763
+ ...core,
764
+ reservationDigest: digest(
765
+ VOLCENGINE_FUNCTION_REPLAY_RESERVATION_SCHEMA,
766
+ core,
767
+ ),
768
+ });
769
+ }
770
+
771
+ function validateReplayReservationAck(value, reservation) {
772
+ exactData(
773
+ value,
774
+ ["reservationDigest", "durable", "readbackVerified"],
775
+ "Volcengine function replay reservation acknowledgement",
776
+ );
777
+ if (
778
+ ownData(
779
+ value,
780
+ "reservationDigest",
781
+ "Volcengine function replay acknowledgement digest",
782
+ ) !== reservation.reservationDigest ||
783
+ ownData(
784
+ value,
785
+ "durable",
786
+ "Volcengine function replay acknowledgement durability",
787
+ ) !== true ||
788
+ ownData(
789
+ value,
790
+ "readbackVerified",
791
+ "Volcengine function replay acknowledgement readback",
792
+ ) !== true
793
+ ) {
794
+ throw new TypeError(
795
+ "Volcengine function replay reservation acknowledgement is invalid",
796
+ );
797
+ }
798
+ }
799
+
800
+ function validateAuditEvidence(
801
+ value,
802
+ request,
803
+ descriptor,
804
+ resultDigest,
805
+ nowMs,
806
+ ) {
807
+ exactData(
808
+ value,
809
+ [
810
+ "schema",
811
+ "authorityId",
812
+ "tenantId",
813
+ "handlerArtifactDigest",
814
+ "policyRevision",
815
+ "requestId",
816
+ "requestDigest",
817
+ "functionPolicyDigest",
818
+ "replayReservationDigest",
819
+ "deadlineAt",
820
+ "resultDigest",
821
+ "auditEventDigest",
822
+ "durabilityReceiptDigest",
823
+ "authenticated",
824
+ "durable",
825
+ "readbackVerified",
826
+ "completedAt",
827
+ ],
828
+ "Volcengine function audit evidence",
829
+ );
830
+ const completedAt = ownData(
831
+ value,
832
+ "completedAt",
833
+ "Volcengine function completion time",
834
+ );
835
+ const completedAtMs = Date.parse(completedAt);
836
+ if (
837
+ ownData(value, "schema", "Volcengine function audit schema") !==
838
+ VOLCENGINE_FUNCTION_AUDIT_EVIDENCE_SCHEMA ||
839
+ ownData(value, "authorityId", "Volcengine function audit authority") !==
840
+ descriptor.authorityId ||
841
+ ownData(value, "tenantId", "Volcengine function audit tenant") !==
842
+ descriptor.tenantId ||
843
+ ownData(
844
+ value,
845
+ "handlerArtifactDigest",
846
+ "Volcengine function audit artifact digest",
847
+ ) !== descriptor.handlerArtifactDigest ||
848
+ ownData(
849
+ value,
850
+ "policyRevision",
851
+ "Volcengine function audit policy revision",
852
+ ) !== descriptor.policyRevision ||
853
+ ownData(value, "requestId", "Volcengine function audit request") !==
854
+ request.requestId ||
855
+ ownData(
856
+ value,
857
+ "requestDigest",
858
+ "Volcengine function audit request digest",
859
+ ) !== request.requestDigest ||
860
+ ownData(
861
+ value,
862
+ "functionPolicyDigest",
863
+ "Volcengine function audit policy digest",
864
+ ) !== request.functionPolicyDigest ||
865
+ ownData(
866
+ value,
867
+ "replayReservationDigest",
868
+ "Volcengine function audit replay reservation digest",
869
+ ) !== request.replayReservationDigest ||
870
+ ownData(value, "deadlineAt", "Volcengine function audit deadline") !==
871
+ request.deadlineAt ||
872
+ ownData(
873
+ value,
874
+ "resultDigest",
875
+ "Volcengine function audit result digest",
876
+ ) !== resultDigest ||
877
+ !DIGEST.test(
878
+ ownData(
879
+ value,
880
+ "auditEventDigest",
881
+ "Volcengine function audit event digest",
882
+ ),
883
+ ) ||
884
+ !DIGEST.test(
885
+ ownData(
886
+ value,
887
+ "durabilityReceiptDigest",
888
+ "Volcengine function durability receipt digest",
889
+ ),
890
+ ) ||
891
+ ownData(
892
+ value,
893
+ "authenticated",
894
+ "Volcengine function audit authentication",
895
+ ) !== true ||
896
+ ownData(value, "durable", "Volcengine function audit durability") !==
897
+ true ||
898
+ ownData(value, "readbackVerified", "Volcengine function audit readback") !==
899
+ true ||
900
+ !Number.isFinite(completedAtMs) ||
901
+ new Date(completedAtMs).toISOString() !== completedAt ||
902
+ completedAtMs < request.requestedAtMs ||
903
+ completedAtMs > request.deadlineAtMs ||
904
+ completedAtMs > nowMs + MAX_CLOCK_SKEW_MS
905
+ ) {
906
+ throw new TypeError("Volcengine function audit evidence is invalid");
907
+ }
908
+ return Object.freeze({
909
+ auditEventDigest: value.auditEventDigest,
910
+ durabilityReceiptDigest: value.durabilityReceiptDigest,
911
+ completedAt,
912
+ });
913
+ }
914
+
915
+ function reserveRequest(captured, request, nowMs) {
916
+ for (const [requestId, entry] of captured.requests) {
917
+ if (entry.expiresAtMs < nowMs) captured.requests.delete(requestId);
918
+ }
919
+ if (captured.requests.has(request.requestId)) {
920
+ throw new TypeError("Volcengine function request was replayed");
921
+ }
922
+ if (captured.requests.size >= MAX_REPLAY_ENTRIES) {
923
+ throw new Error("Volcengine function request replay fence is full");
924
+ }
925
+ captured.requests.set(
926
+ request.requestId,
927
+ Object.freeze({
928
+ requestDigest: request.requestDigest,
929
+ expiresAtMs: request.deadlineAtMs + captured.descriptor.replayRetentionMs,
930
+ }),
931
+ );
932
+ }
933
+
934
+ function normalizeRevocationEvidenceResolverDescriptor(value) {
935
+ exactData(
936
+ value,
937
+ [
938
+ "schema",
939
+ "resolverId",
940
+ "tenantId",
941
+ "handlerArtifactDigest",
942
+ "policyRevision",
943
+ "mode",
944
+ "signatureMode",
945
+ "certificateMode",
946
+ "certificateStatusMode",
947
+ "trustRootDigest",
948
+ "rootKeyId",
949
+ "signerKeyId",
950
+ "signerCertificateDigest",
951
+ "signerRevocationsDigest",
952
+ "signerRevocationsRevision",
953
+ "statusFloorStoreDigest",
954
+ "revocationAuthorityId",
955
+ "maxEvidenceBytes",
956
+ ],
957
+ "Volcengine function revocation evidence resolver descriptor",
958
+ );
959
+ const descriptor = Object.freeze({
960
+ schema: ownData(
961
+ value,
962
+ "schema",
963
+ "Volcengine function revocation evidence resolver schema",
964
+ ),
965
+ resolverId: ownData(
966
+ value,
967
+ "resolverId",
968
+ "Volcengine function revocation evidence resolver identifier",
969
+ ),
970
+ tenantId: ownData(
971
+ value,
972
+ "tenantId",
973
+ "Volcengine function revocation evidence resolver tenant",
974
+ ),
975
+ handlerArtifactDigest: ownData(
976
+ value,
977
+ "handlerArtifactDigest",
978
+ "Volcengine function revocation evidence resolver artifact digest",
979
+ ),
980
+ policyRevision: ownData(
981
+ value,
982
+ "policyRevision",
983
+ "Volcengine function revocation evidence resolver policy revision",
984
+ ),
985
+ mode: ownData(
986
+ value,
987
+ "mode",
988
+ "Volcengine function revocation evidence resolver mode",
989
+ ),
990
+ signatureMode: ownData(
991
+ value,
992
+ "signatureMode",
993
+ "Volcengine function revocation evidence signature mode",
994
+ ),
995
+ certificateMode: ownData(
996
+ value,
997
+ "certificateMode",
998
+ "Volcengine function revocation evidence certificate mode",
999
+ ),
1000
+ certificateStatusMode: ownData(
1001
+ value,
1002
+ "certificateStatusMode",
1003
+ "Volcengine function revocation evidence certificate status mode",
1004
+ ),
1005
+ trustRootDigest: ownData(
1006
+ value,
1007
+ "trustRootDigest",
1008
+ "Volcengine function revocation evidence trust root digest",
1009
+ ),
1010
+ rootKeyId: ownData(
1011
+ value,
1012
+ "rootKeyId",
1013
+ "Volcengine function revocation evidence root key identifier",
1014
+ ),
1015
+ signerKeyId: ownData(
1016
+ value,
1017
+ "signerKeyId",
1018
+ "Volcengine function revocation evidence signer key identifier",
1019
+ ),
1020
+ signerCertificateDigest: ownData(
1021
+ value,
1022
+ "signerCertificateDigest",
1023
+ "Volcengine function revocation signer certificate digest",
1024
+ ),
1025
+ signerRevocationsDigest: ownData(
1026
+ value,
1027
+ "signerRevocationsDigest",
1028
+ "Volcengine function revocation signer revocations digest",
1029
+ ),
1030
+ signerRevocationsRevision: ownData(
1031
+ value,
1032
+ "signerRevocationsRevision",
1033
+ "Volcengine function revocation signer revocations revision",
1034
+ ),
1035
+ statusFloorStoreDigest: ownData(
1036
+ value,
1037
+ "statusFloorStoreDigest",
1038
+ "Volcengine function revocation status floor store digest",
1039
+ ),
1040
+ revocationAuthorityId: ownData(
1041
+ value,
1042
+ "revocationAuthorityId",
1043
+ "Volcengine function revocation evidence authority identifier",
1044
+ ),
1045
+ maxEvidenceBytes: ownData(
1046
+ value,
1047
+ "maxEvidenceBytes",
1048
+ "Volcengine function revocation evidence byte limit",
1049
+ ),
1050
+ });
1051
+ if (
1052
+ descriptor.schema !==
1053
+ VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_RESOLVER_SCHEMA ||
1054
+ !ID.test(descriptor.resolverId) ||
1055
+ !ID.test(descriptor.tenantId) ||
1056
+ !DIGEST.test(descriptor.handlerArtifactDigest) ||
1057
+ !ID.test(descriptor.policyRevision) ||
1058
+ descriptor.mode !== VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_MODE ||
1059
+ descriptor.signatureMode !==
1060
+ VOLCENGINE_FUNCTION_REVOCATION_SIGNATURE_MODE ||
1061
+ descriptor.certificateMode !==
1062
+ VOLCENGINE_FUNCTION_REVOCATION_CERTIFICATE_MODE ||
1063
+ descriptor.certificateStatusMode !==
1064
+ VOLCENGINE_FUNCTION_REVOCATION_CERTIFICATE_STATUS_MODE ||
1065
+ !DIGEST.test(descriptor.trustRootDigest) ||
1066
+ !ID.test(descriptor.rootKeyId) ||
1067
+ !ID.test(descriptor.signerKeyId) ||
1068
+ !DIGEST.test(descriptor.signerCertificateDigest) ||
1069
+ !DIGEST.test(descriptor.signerRevocationsDigest) ||
1070
+ !Number.isSafeInteger(descriptor.signerRevocationsRevision) ||
1071
+ descriptor.signerRevocationsRevision < 1 ||
1072
+ !DIGEST.test(descriptor.statusFloorStoreDigest) ||
1073
+ !ID.test(descriptor.revocationAuthorityId) ||
1074
+ !Number.isSafeInteger(descriptor.maxEvidenceBytes) ||
1075
+ descriptor.maxEvidenceBytes < 1 ||
1076
+ descriptor.maxEvidenceBytes > 1024 * 1024
1077
+ ) {
1078
+ throw new TypeError(
1079
+ "Volcengine function revocation evidence resolver descriptor is invalid",
1080
+ );
1081
+ }
1082
+ return descriptor;
1083
+ }
1084
+
1085
+ export function digestVolcengineFunctionRevocationEvidenceResolverDescriptor(
1086
+ value,
1087
+ ) {
1088
+ return digest(
1089
+ VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_RESOLVER_SCHEMA,
1090
+ normalizeRevocationEvidenceResolverDescriptor(value),
1091
+ );
1092
+ }
1093
+
1094
+ function copyEvidenceBytes(value, label, maxEvidenceBytes) {
1095
+ if (
1096
+ types.isProxy(value) ||
1097
+ (!Buffer.isBuffer(value) && !(value instanceof Uint8Array)) ||
1098
+ value.byteLength < 1 ||
1099
+ value.byteLength > maxEvidenceBytes
1100
+ ) {
1101
+ throw new TypeError(`${label} bytes are invalid`);
1102
+ }
1103
+ return Buffer.from(value);
1104
+ }
1105
+
1106
+ function parseCanonicalJsonBytes(value, keys, label) {
1107
+ const text = value.toString("utf8");
1108
+ if (!Buffer.from(text, "utf8").equals(value)) {
1109
+ throw new TypeError(`${label} is invalid`);
1110
+ }
1111
+ let parsed;
1112
+ try {
1113
+ parsed = JSON.parse(text);
1114
+ } catch {
1115
+ throw new TypeError(`${label} is invalid`);
1116
+ }
1117
+ exactData(parsed, keys, label);
1118
+ if (!Buffer.from(canonical(parsed), "utf8").equals(value)) {
1119
+ throw new TypeError(`${label} is invalid`);
1120
+ }
1121
+ return parsed;
1122
+ }
1123
+
1124
+ function decodeCanonicalBase64(value, label, maxBytes) {
1125
+ if (
1126
+ typeof value !== "string" ||
1127
+ value.length === 0 ||
1128
+ !/^[A-Za-z0-9+/]+={0,2}$/u.test(value)
1129
+ ) {
1130
+ throw new TypeError(`${label} is invalid`);
1131
+ }
1132
+ const bytes = Buffer.from(value, "base64");
1133
+ if (
1134
+ bytes.length < 1 ||
1135
+ bytes.length > maxBytes ||
1136
+ bytes.toString("base64") !== value
1137
+ ) {
1138
+ throw new TypeError(`${label} is invalid`);
1139
+ }
1140
+ return bytes;
1141
+ }
1142
+
1143
+ function verifyRevocationSignerCertificate(
1144
+ descriptor,
1145
+ trustRootPublicKey,
1146
+ signerCertificateBytes,
1147
+ ) {
1148
+ if (
1149
+ digestBytes(signerCertificateBytes) !== descriptor.signerCertificateDigest
1150
+ ) {
1151
+ throw new TypeError(
1152
+ "Volcengine function revocation signer certificate is invalid",
1153
+ );
1154
+ }
1155
+ const value = parseCanonicalJsonBytes(
1156
+ signerCertificateBytes,
1157
+ [
1158
+ "schema",
1159
+ "trustRootDigest",
1160
+ "issuerKeyId",
1161
+ "subjectKeyId",
1162
+ "subjectPublicKey",
1163
+ "tenantId",
1164
+ "revocationAuthorityId",
1165
+ "usage",
1166
+ "notBefore",
1167
+ "notAfter",
1168
+ "signature",
1169
+ ],
1170
+ "Volcengine function revocation signer certificate",
1171
+ );
1172
+ const core = Object.freeze({
1173
+ schema: ownData(
1174
+ value,
1175
+ "schema",
1176
+ "Volcengine function revocation signer certificate schema",
1177
+ ),
1178
+ trustRootDigest: ownData(
1179
+ value,
1180
+ "trustRootDigest",
1181
+ "Volcengine function revocation signer certificate trust root",
1182
+ ),
1183
+ issuerKeyId: ownData(
1184
+ value,
1185
+ "issuerKeyId",
1186
+ "Volcengine function revocation signer certificate issuer",
1187
+ ),
1188
+ subjectKeyId: ownData(
1189
+ value,
1190
+ "subjectKeyId",
1191
+ "Volcengine function revocation signer certificate subject",
1192
+ ),
1193
+ subjectPublicKey: ownData(
1194
+ value,
1195
+ "subjectPublicKey",
1196
+ "Volcengine function revocation signer certificate public key",
1197
+ ),
1198
+ tenantId: ownData(
1199
+ value,
1200
+ "tenantId",
1201
+ "Volcengine function revocation signer certificate tenant",
1202
+ ),
1203
+ revocationAuthorityId: ownData(
1204
+ value,
1205
+ "revocationAuthorityId",
1206
+ "Volcengine function revocation signer certificate authority",
1207
+ ),
1208
+ usage: ownData(
1209
+ value,
1210
+ "usage",
1211
+ "Volcengine function revocation signer certificate usage",
1212
+ ),
1213
+ notBefore: ownData(
1214
+ value,
1215
+ "notBefore",
1216
+ "Volcengine function revocation signer certificate start",
1217
+ ),
1218
+ notAfter: ownData(
1219
+ value,
1220
+ "notAfter",
1221
+ "Volcengine function revocation signer certificate expiry",
1222
+ ),
1223
+ });
1224
+ const signature = decodeCanonicalBase64(
1225
+ ownData(
1226
+ value,
1227
+ "signature",
1228
+ "Volcengine function revocation signer certificate signature",
1229
+ ),
1230
+ "Volcengine function revocation signer certificate signature",
1231
+ 64,
1232
+ );
1233
+ const notBeforeMs = Date.parse(core.notBefore);
1234
+ const notAfterMs = Date.parse(core.notAfter);
1235
+ if (
1236
+ core.schema !== VOLCENGINE_FUNCTION_REVOCATION_SIGNER_CERTIFICATE_SCHEMA ||
1237
+ core.trustRootDigest !== descriptor.trustRootDigest ||
1238
+ core.issuerKeyId !== descriptor.rootKeyId ||
1239
+ core.subjectKeyId !== descriptor.signerKeyId ||
1240
+ core.tenantId !== descriptor.tenantId ||
1241
+ core.revocationAuthorityId !== descriptor.revocationAuthorityId ||
1242
+ core.usage !== VOLCENGINE_FUNCTION_REVOCATION_PURPOSE ||
1243
+ !Number.isFinite(notBeforeMs) ||
1244
+ new Date(notBeforeMs).toISOString() !== core.notBefore ||
1245
+ !Number.isFinite(notAfterMs) ||
1246
+ new Date(notAfterMs).toISOString() !== core.notAfter ||
1247
+ notAfterMs <= notBeforeMs ||
1248
+ notAfterMs > notBeforeMs + 366 * 24 * 60 * 60 * 1000 ||
1249
+ signature.length !== 64 ||
1250
+ !verifySignature(
1251
+ null,
1252
+ Buffer.from(
1253
+ `${VOLCENGINE_FUNCTION_REVOCATION_SIGNER_CERTIFICATE_SCHEMA}\0${canonical(core)}`,
1254
+ "utf8",
1255
+ ),
1256
+ trustRootPublicKey,
1257
+ signature,
1258
+ )
1259
+ ) {
1260
+ throw new TypeError(
1261
+ "Volcengine function revocation signer certificate signature rejected",
1262
+ );
1263
+ }
1264
+ const subjectPublicKeyBytes = decodeCanonicalBase64(
1265
+ core.subjectPublicKey,
1266
+ "Volcengine function revocation signer certificate public key",
1267
+ 16 * 1024,
1268
+ );
1269
+ let subjectPublicKey;
1270
+ try {
1271
+ subjectPublicKey = createPublicKey({
1272
+ key: subjectPublicKeyBytes,
1273
+ format: "der",
1274
+ type: "spki",
1275
+ });
1276
+ } catch {
1277
+ throw new TypeError(
1278
+ "Volcengine function revocation signer certificate public key is invalid",
1279
+ );
1280
+ }
1281
+ if (subjectPublicKey.asymmetricKeyType !== "ed25519") {
1282
+ throw new TypeError(
1283
+ "Volcengine function revocation signer certificate public key is invalid",
1284
+ );
1285
+ }
1286
+ return Object.freeze({ subjectPublicKey, notBeforeMs, notAfterMs });
1287
+ }
1288
+
1289
+ function verifyRevocationSignerRevocations(
1290
+ descriptor,
1291
+ trustRootPublicKey,
1292
+ signerRevocationsBytes,
1293
+ ) {
1294
+ if (
1295
+ digestBytes(signerRevocationsBytes) !== descriptor.signerRevocationsDigest
1296
+ ) {
1297
+ throw new TypeError(
1298
+ "Volcengine function revocation signer status is invalid",
1299
+ );
1300
+ }
1301
+ const value = parseCanonicalJsonBytes(
1302
+ signerRevocationsBytes,
1303
+ [
1304
+ "schema",
1305
+ "trustRootDigest",
1306
+ "issuerKeyId",
1307
+ "tenantId",
1308
+ "revocationAuthorityId",
1309
+ "revision",
1310
+ "issuedAt",
1311
+ "nextUpdate",
1312
+ "revokedCertificateDigests",
1313
+ "signature",
1314
+ ],
1315
+ "Volcengine function revocation signer status",
1316
+ );
1317
+ const revokedCertificateDigests = Object.freeze(
1318
+ directArrayValues(
1319
+ ownData(
1320
+ value,
1321
+ "revokedCertificateDigests",
1322
+ "Volcengine function revoked signer certificates",
1323
+ ),
1324
+ "Volcengine function revoked signer certificates",
1325
+ 4096,
1326
+ ),
1327
+ );
1328
+ const core = Object.freeze({
1329
+ schema: ownData(
1330
+ value,
1331
+ "schema",
1332
+ "Volcengine function revocation signer status schema",
1333
+ ),
1334
+ trustRootDigest: ownData(
1335
+ value,
1336
+ "trustRootDigest",
1337
+ "Volcengine function revocation signer status trust root",
1338
+ ),
1339
+ issuerKeyId: ownData(
1340
+ value,
1341
+ "issuerKeyId",
1342
+ "Volcengine function revocation signer status issuer",
1343
+ ),
1344
+ tenantId: ownData(
1345
+ value,
1346
+ "tenantId",
1347
+ "Volcengine function revocation signer status tenant",
1348
+ ),
1349
+ revocationAuthorityId: ownData(
1350
+ value,
1351
+ "revocationAuthorityId",
1352
+ "Volcengine function revocation signer status authority",
1353
+ ),
1354
+ revision: ownData(
1355
+ value,
1356
+ "revision",
1357
+ "Volcengine function revocation signer status revision",
1358
+ ),
1359
+ issuedAt: ownData(
1360
+ value,
1361
+ "issuedAt",
1362
+ "Volcengine function revocation signer status issue time",
1363
+ ),
1364
+ nextUpdate: ownData(
1365
+ value,
1366
+ "nextUpdate",
1367
+ "Volcengine function revocation signer status next update",
1368
+ ),
1369
+ revokedCertificateDigests,
1370
+ });
1371
+ const signature = decodeCanonicalBase64(
1372
+ ownData(
1373
+ value,
1374
+ "signature",
1375
+ "Volcengine function revocation signer status signature",
1376
+ ),
1377
+ "Volcengine function revocation signer status signature",
1378
+ 64,
1379
+ );
1380
+ const issuedAtMs = Date.parse(core.issuedAt);
1381
+ const nextUpdateMs = Date.parse(core.nextUpdate);
1382
+ if (
1383
+ core.schema !== VOLCENGINE_FUNCTION_REVOCATION_SIGNER_REVOCATIONS_SCHEMA ||
1384
+ core.trustRootDigest !== descriptor.trustRootDigest ||
1385
+ core.issuerKeyId !== descriptor.rootKeyId ||
1386
+ core.tenantId !== descriptor.tenantId ||
1387
+ core.revocationAuthorityId !== descriptor.revocationAuthorityId ||
1388
+ core.revision !== descriptor.signerRevocationsRevision ||
1389
+ !Number.isSafeInteger(core.revision) ||
1390
+ core.revision < 1 ||
1391
+ revokedCertificateDigests.some(
1392
+ (entry, index) =>
1393
+ !DIGEST.test(entry) ||
1394
+ (index > 0 && entry <= revokedCertificateDigests[index - 1]),
1395
+ ) ||
1396
+ !Number.isFinite(issuedAtMs) ||
1397
+ new Date(issuedAtMs).toISOString() !== core.issuedAt ||
1398
+ !Number.isFinite(nextUpdateMs) ||
1399
+ new Date(nextUpdateMs).toISOString() !== core.nextUpdate ||
1400
+ nextUpdateMs <= issuedAtMs ||
1401
+ nextUpdateMs > issuedAtMs + 24 * 60 * 60 * 1000 ||
1402
+ signature.length !== 64 ||
1403
+ !verifySignature(
1404
+ null,
1405
+ Buffer.from(
1406
+ `${VOLCENGINE_FUNCTION_REVOCATION_SIGNER_REVOCATIONS_SCHEMA}\0${canonical(core)}`,
1407
+ "utf8",
1408
+ ),
1409
+ trustRootPublicKey,
1410
+ signature,
1411
+ )
1412
+ ) {
1413
+ throw new TypeError(
1414
+ "Volcengine function revocation signer status signature rejected",
1415
+ );
1416
+ }
1417
+ if (revokedCertificateDigests.includes(descriptor.signerCertificateDigest)) {
1418
+ throw new TypeError(
1419
+ "Volcengine function revocation signer certificate was revoked",
1420
+ );
1421
+ }
1422
+ return Object.freeze({
1423
+ issuedAt: core.issuedAt,
1424
+ issuedAtMs,
1425
+ nextUpdate: core.nextUpdate,
1426
+ nextUpdateMs,
1427
+ });
1428
+ }
1429
+
1430
+ export function createVolcengineFunctionRevocationEvidenceResolver(options) {
1431
+ exactData(
1432
+ options,
1433
+ [
1434
+ "descriptor",
1435
+ "resolve",
1436
+ "trustRootBytes",
1437
+ "signerCertificateBytes",
1438
+ "signerRevocationsBytes",
1439
+ "statusFloorStore",
1440
+ ],
1441
+ "Volcengine function revocation evidence resolver",
1442
+ );
1443
+ const descriptor = normalizeRevocationEvidenceResolverDescriptor(
1444
+ ownData(
1445
+ options,
1446
+ "descriptor",
1447
+ "Volcengine function revocation evidence resolver descriptor",
1448
+ ),
1449
+ );
1450
+ const resolve = ownData(
1451
+ options,
1452
+ "resolve",
1453
+ "Volcengine function revocation evidence resolution port",
1454
+ );
1455
+ if (typeof resolve !== "function" || types.isProxy(resolve)) {
1456
+ throw new TypeError(
1457
+ "Volcengine function revocation evidence resolution port is invalid",
1458
+ );
1459
+ }
1460
+ const trustRootBytes = copyEvidenceBytes(
1461
+ ownData(
1462
+ options,
1463
+ "trustRootBytes",
1464
+ "Volcengine function revocation evidence trust root",
1465
+ ),
1466
+ "Volcengine function revocation evidence trust root",
1467
+ 64 * 1024,
1468
+ );
1469
+ if (digestBytes(trustRootBytes) !== descriptor.trustRootDigest) {
1470
+ throw new TypeError(
1471
+ "Volcengine function revocation evidence trust root is invalid",
1472
+ );
1473
+ }
1474
+ let containsPrivateKey = false;
1475
+ try {
1476
+ createPrivateKey(trustRootBytes);
1477
+ containsPrivateKey = true;
1478
+ } catch {
1479
+ // A public trust root must not contain private key material.
1480
+ }
1481
+ let publicKey;
1482
+ try {
1483
+ publicKey = createPublicKey(trustRootBytes);
1484
+ } catch {
1485
+ throw new TypeError(
1486
+ "Volcengine function revocation evidence trust root is invalid",
1487
+ );
1488
+ }
1489
+ if (containsPrivateKey || publicKey.asymmetricKeyType !== "ed25519") {
1490
+ throw new TypeError(
1491
+ "Volcengine function revocation evidence trust root is invalid",
1492
+ );
1493
+ }
1494
+ const signerCertificateBytes = copyEvidenceBytes(
1495
+ ownData(
1496
+ options,
1497
+ "signerCertificateBytes",
1498
+ "Volcengine function revocation signer certificate",
1499
+ ),
1500
+ "Volcengine function revocation signer certificate",
1501
+ 64 * 1024,
1502
+ );
1503
+ const signerCertificate = verifyRevocationSignerCertificate(
1504
+ descriptor,
1505
+ publicKey,
1506
+ signerCertificateBytes,
1507
+ );
1508
+ const signerRevocationsBytes = copyEvidenceBytes(
1509
+ ownData(
1510
+ options,
1511
+ "signerRevocationsBytes",
1512
+ "Volcengine function revocation signer status",
1513
+ ),
1514
+ "Volcengine function revocation signer status",
1515
+ 1024 * 1024,
1516
+ );
1517
+ const signerStatus = verifyRevocationSignerRevocations(
1518
+ descriptor,
1519
+ publicKey,
1520
+ signerRevocationsBytes,
1521
+ );
1522
+ const statusFloorStore = ownData(
1523
+ options,
1524
+ "statusFloorStore",
1525
+ "Volcengine function revocation status floor store",
1526
+ );
1527
+ const statusFloorStoreDescriptor =
1528
+ inspectVolcengineFunctionRevocationStatusFloorStore(statusFloorStore);
1529
+ if (
1530
+ statusFloorStoreDescriptor.descriptorDigest !==
1531
+ descriptor.statusFloorStoreDigest ||
1532
+ statusFloorStoreDescriptor.descriptor.tenantId !== descriptor.tenantId ||
1533
+ statusFloorStoreDescriptor.descriptor.handlerArtifactDigest !==
1534
+ descriptor.handlerArtifactDigest ||
1535
+ statusFloorStoreDescriptor.descriptor.revocationAuthorityId !==
1536
+ descriptor.revocationAuthorityId ||
1537
+ statusFloorStoreDescriptor.descriptor.trustRootDigest !==
1538
+ descriptor.trustRootDigest
1539
+ ) {
1540
+ throw new TypeError(
1541
+ "Volcengine function revocation status floor store does not match resolver",
1542
+ );
1543
+ }
1544
+ const statusFloor =
1545
+ captureVolcengineFunctionRevocationStatusFloorStore(statusFloorStore);
1546
+ const statusAcknowledgement = statusFloor.acceptSnapshot(
1547
+ Object.freeze({
1548
+ schema: VOLCENGINE_FUNCTION_REVOCATION_STATUS_SNAPSHOT_SCHEMA,
1549
+ storeId: statusFloor.descriptor.storeId,
1550
+ tenantId: descriptor.tenantId,
1551
+ handlerArtifactDigest: descriptor.handlerArtifactDigest,
1552
+ revocationAuthorityId: descriptor.revocationAuthorityId,
1553
+ trustRootDigest: descriptor.trustRootDigest,
1554
+ revision: descriptor.signerRevocationsRevision,
1555
+ snapshotDigest: descriptor.signerRevocationsDigest,
1556
+ issuedAt: signerStatus.issuedAt,
1557
+ nextUpdate: signerStatus.nextUpdate,
1558
+ }),
1559
+ );
1560
+ exactData(
1561
+ statusAcknowledgement,
1562
+ [
1563
+ "schema",
1564
+ "storeId",
1565
+ "revision",
1566
+ "snapshotDigest",
1567
+ "headDigest",
1568
+ "durable",
1569
+ "readbackVerified",
1570
+ ],
1571
+ "Volcengine function revocation status floor acknowledgement",
1572
+ );
1573
+ if (
1574
+ statusAcknowledgement.schema !==
1575
+ VOLCENGINE_FUNCTION_REVOCATION_STATUS_ACK_SCHEMA ||
1576
+ statusAcknowledgement.storeId !== statusFloor.descriptor.storeId ||
1577
+ statusAcknowledgement.revision !== descriptor.signerRevocationsRevision ||
1578
+ statusAcknowledgement.snapshotDigest !==
1579
+ descriptor.signerRevocationsDigest ||
1580
+ !DIGEST.test(statusAcknowledgement.headDigest) ||
1581
+ statusAcknowledgement.durable !== true ||
1582
+ statusAcknowledgement.readbackVerified !== true
1583
+ ) {
1584
+ throw new TypeError(
1585
+ "Volcengine function revocation status floor acknowledgement is invalid",
1586
+ );
1587
+ }
1588
+ const resolver = Object.freeze({});
1589
+ revocationEvidenceResolvers.set(resolver, {
1590
+ descriptor,
1591
+ descriptorDigest: digest(
1592
+ VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_RESOLVER_SCHEMA,
1593
+ descriptor,
1594
+ ),
1595
+ resolve,
1596
+ publicKey: signerCertificate.subjectPublicKey,
1597
+ signerNotBeforeMs: signerCertificate.notBeforeMs,
1598
+ signerNotAfterMs: signerCertificate.notAfterMs,
1599
+ signerStatusIssuedAtMs: signerStatus.issuedAtMs,
1600
+ signerStatusNextUpdateMs: signerStatus.nextUpdateMs,
1601
+ statusFloorHeadDigest: statusAcknowledgement.headDigest,
1602
+ });
1603
+ return resolver;
1604
+ }
1605
+
1606
+ export function inspectVolcengineFunctionRevocationEvidenceResolver(value) {
1607
+ const captured = revocationEvidenceResolvers.get(value);
1608
+ if (!captured) {
1609
+ throw new TypeError(
1610
+ "A branded Volcengine function revocation evidence resolver is required",
1611
+ );
1612
+ }
1613
+ return Object.freeze({
1614
+ descriptor: captured.descriptor,
1615
+ descriptorDigest: captured.descriptorDigest,
1616
+ });
1617
+ }
1618
+
1619
+ function verifyRevocationAuthorizationEvidence(
1620
+ captured,
1621
+ authorityDescriptor,
1622
+ request,
1623
+ decision,
1624
+ authorizationEvidenceBytes,
1625
+ ) {
1626
+ const value = parseCanonicalJsonBytes(
1627
+ authorizationEvidenceBytes,
1628
+ [
1629
+ "schema",
1630
+ "trustRootDigest",
1631
+ "signerKeyId",
1632
+ "tenantId",
1633
+ "revocationAuthorityId",
1634
+ "authorizationRequestDigest",
1635
+ "decision",
1636
+ "authorizedAt",
1637
+ "validUntil",
1638
+ "signature",
1639
+ ],
1640
+ "Volcengine function revocation authorization evidence",
1641
+ );
1642
+ const core = Object.freeze({
1643
+ schema: ownData(
1644
+ value,
1645
+ "schema",
1646
+ "Volcengine function revocation authorization evidence schema",
1647
+ ),
1648
+ trustRootDigest: ownData(
1649
+ value,
1650
+ "trustRootDigest",
1651
+ "Volcengine function revocation authorization evidence trust root",
1652
+ ),
1653
+ signerKeyId: ownData(
1654
+ value,
1655
+ "signerKeyId",
1656
+ "Volcengine function revocation authorization evidence signer",
1657
+ ),
1658
+ tenantId: ownData(
1659
+ value,
1660
+ "tenantId",
1661
+ "Volcengine function revocation authorization evidence tenant",
1662
+ ),
1663
+ revocationAuthorityId: ownData(
1664
+ value,
1665
+ "revocationAuthorityId",
1666
+ "Volcengine function revocation authorization evidence authority",
1667
+ ),
1668
+ authorizationRequestDigest: ownData(
1669
+ value,
1670
+ "authorizationRequestDigest",
1671
+ "Volcengine function revocation authorization evidence request",
1672
+ ),
1673
+ decision: ownData(
1674
+ value,
1675
+ "decision",
1676
+ "Volcengine function revocation authorization evidence decision",
1677
+ ),
1678
+ authorizedAt: ownData(
1679
+ value,
1680
+ "authorizedAt",
1681
+ "Volcengine function revocation authorization evidence time",
1682
+ ),
1683
+ validUntil: ownData(
1684
+ value,
1685
+ "validUntil",
1686
+ "Volcengine function revocation authorization evidence expiry",
1687
+ ),
1688
+ });
1689
+ const signatureBytes = decodeCanonicalBase64(
1690
+ ownData(
1691
+ value,
1692
+ "signature",
1693
+ "Volcengine function revocation authorization evidence signature",
1694
+ ),
1695
+ "Volcengine function revocation authorization evidence signature",
1696
+ 64,
1697
+ );
1698
+ const authorizedAtMs = Date.parse(core.authorizedAt);
1699
+ const validUntilMs = Date.parse(core.validUntil);
1700
+ if (
1701
+ core.schema !==
1702
+ VOLCENGINE_FUNCTION_REVOCATION_AUTHORIZATION_EVIDENCE_SCHEMA ||
1703
+ core.trustRootDigest !== captured.descriptor.trustRootDigest ||
1704
+ core.signerKeyId !== captured.descriptor.signerKeyId ||
1705
+ core.tenantId !== authorityDescriptor.tenantId ||
1706
+ core.revocationAuthorityId !== authorityDescriptor.authorityId ||
1707
+ core.authorizationRequestDigest !== request.requestDigest ||
1708
+ core.decision !== "allow" ||
1709
+ core.authorizedAt !== decision.authorizedAt ||
1710
+ core.validUntil !== decision.validUntil ||
1711
+ !Number.isFinite(authorizedAtMs) ||
1712
+ authorizedAtMs < captured.signerNotBeforeMs ||
1713
+ authorizedAtMs < captured.signerStatusIssuedAtMs ||
1714
+ !Number.isFinite(validUntilMs) ||
1715
+ validUntilMs > captured.signerNotAfterMs ||
1716
+ validUntilMs > captured.signerStatusNextUpdateMs
1717
+ ) {
1718
+ throw new TypeError(
1719
+ "Volcengine function revocation authorization evidence is invalid",
1720
+ );
1721
+ }
1722
+ if (
1723
+ signatureBytes.length !== 64 ||
1724
+ !verifySignature(
1725
+ null,
1726
+ Buffer.from(
1727
+ `${VOLCENGINE_FUNCTION_REVOCATION_AUTHORIZATION_EVIDENCE_SCHEMA}\0${canonical(core)}`,
1728
+ "utf8",
1729
+ ),
1730
+ captured.publicKey,
1731
+ signatureBytes,
1732
+ )
1733
+ ) {
1734
+ throw new TypeError(
1735
+ "Volcengine function revocation authorization evidence signature rejected",
1736
+ );
1737
+ }
1738
+ }
1739
+
1740
+ async function resolveRevocationDecisionEvidence(
1741
+ resolver,
1742
+ authorityDescriptor,
1743
+ request,
1744
+ decision,
1745
+ ) {
1746
+ const captured = revocationEvidenceResolvers.get(resolver);
1747
+ if (!captured) {
1748
+ throw new TypeError(
1749
+ "A branded Volcengine function revocation evidence resolver is required",
1750
+ );
1751
+ }
1752
+ const requestCore = Object.freeze({
1753
+ schema: VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_REQUEST_SCHEMA,
1754
+ resolverId: captured.descriptor.resolverId,
1755
+ tenantId: authorityDescriptor.tenantId,
1756
+ handlerArtifactDigest: authorityDescriptor.handlerArtifactDigest,
1757
+ resolverPolicyRevision: captured.descriptor.policyRevision,
1758
+ revocationAuthorityId: authorityDescriptor.authorityId,
1759
+ authorizationRequestDigest: request.requestDigest,
1760
+ authorizationEvidenceDigest: decision.authorizationEvidenceDigest,
1761
+ auditEventDigest: decision.auditEventDigest,
1762
+ durabilityReceiptDigest: decision.durabilityReceiptDigest,
1763
+ });
1764
+ const resolutionRequest = Object.freeze({
1765
+ ...requestCore,
1766
+ requestDigest: digest(
1767
+ VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_REQUEST_SCHEMA,
1768
+ requestCore,
1769
+ ),
1770
+ });
1771
+ const value = await Reflect.apply(captured.resolve, undefined, [
1772
+ resolutionRequest,
1773
+ ]);
1774
+ exactData(
1775
+ value,
1776
+ ["authorizationEvidenceBytes", "auditEventBytes", "durabilityReceiptBytes"],
1777
+ "Volcengine function revocation evidence readback",
1778
+ );
1779
+ const authorizationEvidenceBytes = copyEvidenceBytes(
1780
+ ownData(
1781
+ value,
1782
+ "authorizationEvidenceBytes",
1783
+ "Volcengine function revocation authorization evidence",
1784
+ ),
1785
+ "Volcengine function revocation authorization evidence",
1786
+ captured.descriptor.maxEvidenceBytes,
1787
+ );
1788
+ const auditEventBytes = copyEvidenceBytes(
1789
+ ownData(
1790
+ value,
1791
+ "auditEventBytes",
1792
+ "Volcengine function revocation audit event",
1793
+ ),
1794
+ "Volcengine function revocation audit event",
1795
+ captured.descriptor.maxEvidenceBytes,
1796
+ );
1797
+ const durabilityReceiptBytes = copyEvidenceBytes(
1798
+ ownData(
1799
+ value,
1800
+ "durabilityReceiptBytes",
1801
+ "Volcengine function revocation durability receipt",
1802
+ ),
1803
+ "Volcengine function revocation durability receipt",
1804
+ captured.descriptor.maxEvidenceBytes,
1805
+ );
1806
+ if (
1807
+ digestBytes(authorizationEvidenceBytes) !==
1808
+ decision.authorizationEvidenceDigest ||
1809
+ digestBytes(auditEventBytes) !== decision.auditEventDigest ||
1810
+ digestBytes(durabilityReceiptBytes) !== decision.durabilityReceiptDigest
1811
+ ) {
1812
+ throw new TypeError(
1813
+ "Volcengine function revocation evidence readback is invalid",
1814
+ );
1815
+ }
1816
+ verifyRevocationAuthorizationEvidence(
1817
+ captured,
1818
+ authorityDescriptor,
1819
+ request,
1820
+ decision,
1821
+ authorizationEvidenceBytes,
1822
+ );
1823
+ const readbackCore = Object.freeze({
1824
+ schema: VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_READBACK_SCHEMA,
1825
+ evidenceResolverDigest: captured.descriptorDigest,
1826
+ statusFloorHeadDigest: captured.statusFloorHeadDigest,
1827
+ resolutionRequestDigest: resolutionRequest.requestDigest,
1828
+ authorizationEvidenceDigest: decision.authorizationEvidenceDigest,
1829
+ auditEventDigest: decision.auditEventDigest,
1830
+ durabilityReceiptDigest: decision.durabilityReceiptDigest,
1831
+ exactBytesVerified: true,
1832
+ });
1833
+ return Object.freeze({
1834
+ ...readbackCore,
1835
+ evidenceReadbackDigest: digest(
1836
+ VOLCENGINE_FUNCTION_REVOCATION_EVIDENCE_READBACK_SCHEMA,
1837
+ readbackCore,
1838
+ ),
1839
+ });
1840
+ }
1841
+
1842
+ function normalizeRevocationAuthorityDescriptor(value) {
1843
+ exactData(
1844
+ value,
1845
+ [
1846
+ "schema",
1847
+ "authorityId",
1848
+ "tenantId",
1849
+ "handlerArtifactDigest",
1850
+ "policyRevision",
1851
+ "targetAuthorityId",
1852
+ "targetReplayStoreId",
1853
+ "targetPolicyRevision",
1854
+ "maxGrantTtlMs",
1855
+ "approvalMode",
1856
+ "auditMode",
1857
+ "evidenceResolverDigest",
1858
+ ],
1859
+ "Volcengine function revocation authority descriptor",
1860
+ );
1861
+ const descriptor = Object.freeze({
1862
+ schema: ownData(
1863
+ value,
1864
+ "schema",
1865
+ "Volcengine function revocation authority schema",
1866
+ ),
1867
+ authorityId: ownData(
1868
+ value,
1869
+ "authorityId",
1870
+ "Volcengine function revocation authority identifier",
1871
+ ),
1872
+ tenantId: ownData(
1873
+ value,
1874
+ "tenantId",
1875
+ "Volcengine function revocation authority tenant",
1876
+ ),
1877
+ handlerArtifactDigest: ownData(
1878
+ value,
1879
+ "handlerArtifactDigest",
1880
+ "Volcengine function revocation authority artifact digest",
1881
+ ),
1882
+ policyRevision: ownData(
1883
+ value,
1884
+ "policyRevision",
1885
+ "Volcengine function revocation policy revision",
1886
+ ),
1887
+ targetAuthorityId: ownData(
1888
+ value,
1889
+ "targetAuthorityId",
1890
+ "Volcengine function revocation target authority",
1891
+ ),
1892
+ targetReplayStoreId: ownData(
1893
+ value,
1894
+ "targetReplayStoreId",
1895
+ "Volcengine function revocation target replay store",
1896
+ ),
1897
+ targetPolicyRevision: ownData(
1898
+ value,
1899
+ "targetPolicyRevision",
1900
+ "Volcengine function revocation target policy revision",
1901
+ ),
1902
+ maxGrantTtlMs: ownData(
1903
+ value,
1904
+ "maxGrantTtlMs",
1905
+ "Volcengine function revocation grant TTL",
1906
+ ),
1907
+ approvalMode: ownData(
1908
+ value,
1909
+ "approvalMode",
1910
+ "Volcengine function revocation approval mode",
1911
+ ),
1912
+ auditMode: ownData(
1913
+ value,
1914
+ "auditMode",
1915
+ "Volcengine function revocation audit mode",
1916
+ ),
1917
+ evidenceResolverDigest: ownData(
1918
+ value,
1919
+ "evidenceResolverDigest",
1920
+ "Volcengine function revocation evidence resolver digest",
1921
+ ),
1922
+ });
1923
+ if (
1924
+ descriptor.schema !== VOLCENGINE_FUNCTION_REVOCATION_AUTHORITY_SCHEMA ||
1925
+ !ID.test(descriptor.authorityId) ||
1926
+ !ID.test(descriptor.tenantId) ||
1927
+ !DIGEST.test(descriptor.handlerArtifactDigest) ||
1928
+ !ID.test(descriptor.policyRevision) ||
1929
+ !ID.test(descriptor.targetAuthorityId) ||
1930
+ !ID.test(descriptor.targetReplayStoreId) ||
1931
+ !ID.test(descriptor.targetPolicyRevision) ||
1932
+ !Number.isSafeInteger(descriptor.maxGrantTtlMs) ||
1933
+ descriptor.maxGrantTtlMs < 1 ||
1934
+ descriptor.maxGrantTtlMs > 60_000 ||
1935
+ descriptor.approvalMode !== VOLCENGINE_FUNCTION_REVOCATION_APPROVAL_MODE ||
1936
+ descriptor.auditMode !== VOLCENGINE_FUNCTION_AUDIT_MODE ||
1937
+ !DIGEST.test(descriptor.evidenceResolverDigest)
1938
+ ) {
1939
+ throw new TypeError(
1940
+ "Volcengine function revocation authority descriptor is invalid",
1941
+ );
1942
+ }
1943
+ return descriptor;
1944
+ }
1945
+
1946
+ function assertRevocationTargetBinding(target, descriptor) {
1947
+ if (
1948
+ target.authorityId !== descriptor.targetAuthorityId ||
1949
+ target.revocationAuthorityId !== descriptor.authorityId ||
1950
+ target.tenantId !== descriptor.tenantId ||
1951
+ target.handlerArtifactDigest !== descriptor.handlerArtifactDigest ||
1952
+ target.policyRevision !== descriptor.targetPolicyRevision ||
1953
+ target.replayStoreId !== descriptor.targetReplayStoreId
1954
+ ) {
1955
+ throw new TypeError(
1956
+ "Volcengine function revocation target does not match authority",
1957
+ );
1958
+ }
1959
+ }
1960
+
1961
+ function normalizeRevocationRequest(value, descriptor, nowMs) {
1962
+ exactData(
1963
+ value,
1964
+ [
1965
+ "schema",
1966
+ "requestId",
1967
+ "actorDid",
1968
+ "tenantId",
1969
+ "purpose",
1970
+ "reasonDigest",
1971
+ "authorization",
1972
+ "requestedAt",
1973
+ ],
1974
+ "Volcengine function revocation request",
1975
+ );
1976
+ const authorization = normalizeJson(
1977
+ ownData(
1978
+ value,
1979
+ "authorization",
1980
+ "Volcengine function revocation authorization",
1981
+ ),
1982
+ "Volcengine function revocation authorization",
1983
+ 16 * 1024,
1984
+ );
1985
+ const requestedAt = ownData(
1986
+ value,
1987
+ "requestedAt",
1988
+ "Volcengine function revocation request time",
1989
+ );
1990
+ const requestedAtMs = Date.parse(requestedAt);
1991
+ const core = Object.freeze({
1992
+ schema: ownData(
1993
+ value,
1994
+ "schema",
1995
+ "Volcengine function revocation request schema",
1996
+ ),
1997
+ authorityId: descriptor.authorityId,
1998
+ tenantId: ownData(
1999
+ value,
2000
+ "tenantId",
2001
+ "Volcengine function revocation request tenant",
2002
+ ),
2003
+ handlerArtifactDigest: descriptor.handlerArtifactDigest,
2004
+ policyRevision: descriptor.policyRevision,
2005
+ targetAuthorityId: descriptor.targetAuthorityId,
2006
+ targetReplayStoreId: descriptor.targetReplayStoreId,
2007
+ targetPolicyRevision: descriptor.targetPolicyRevision,
2008
+ actorDid: ownData(
2009
+ value,
2010
+ "actorDid",
2011
+ "Volcengine function revocation actor",
2012
+ ),
2013
+ purpose: ownData(
2014
+ value,
2015
+ "purpose",
2016
+ "Volcengine function revocation purpose",
2017
+ ),
2018
+ requestId: ownData(
2019
+ value,
2020
+ "requestId",
2021
+ "Volcengine function revocation request identifier",
2022
+ ),
2023
+ reasonDigest: ownData(
2024
+ value,
2025
+ "reasonDigest",
2026
+ "Volcengine function revocation reason digest",
2027
+ ),
2028
+ authorizationDigest: digest(
2029
+ "chainlesschain.volcengine-function-revocation-authorization/v1",
2030
+ authorization,
2031
+ ),
2032
+ requestedAt,
2033
+ });
2034
+ if (
2035
+ core.schema !== VOLCENGINE_FUNCTION_REVOCATION_REQUEST_SCHEMA ||
2036
+ core.tenantId !== descriptor.tenantId ||
2037
+ !ID.test(core.actorDid) ||
2038
+ core.purpose !== VOLCENGINE_FUNCTION_REVOCATION_PURPOSE ||
2039
+ !ID.test(core.requestId) ||
2040
+ !DIGEST.test(core.reasonDigest) ||
2041
+ !Number.isFinite(requestedAtMs) ||
2042
+ new Date(requestedAtMs).toISOString() !== core.requestedAt ||
2043
+ requestedAtMs < nowMs - MAX_REQUEST_AGE_MS ||
2044
+ requestedAtMs > nowMs + MAX_CLOCK_SKEW_MS
2045
+ ) {
2046
+ throw new TypeError("Volcengine function revocation request is invalid");
2047
+ }
2048
+ return Object.freeze({
2049
+ ...core,
2050
+ requestDigest: digest(VOLCENGINE_FUNCTION_REVOCATION_REQUEST_SCHEMA, core),
2051
+ authorization,
2052
+ });
2053
+ }
2054
+
2055
+ function normalizeRevocationDecision(value, request, descriptor, nowMs) {
2056
+ if (
2057
+ !value ||
2058
+ typeof value !== "object" ||
2059
+ Array.isArray(value) ||
2060
+ types.isProxy(value) ||
2061
+ ![Object.prototype, null].includes(Object.getPrototypeOf(value))
2062
+ ) {
2063
+ throw new TypeError("Volcengine function revocation decision is invalid");
2064
+ }
2065
+ const decision = ownData(
2066
+ value,
2067
+ "decision",
2068
+ "Volcengine function revocation decision",
2069
+ );
2070
+ if (decision === "deny") {
2071
+ exactData(value, ["decision"], "Volcengine function revocation denial");
2072
+ return Object.freeze({ decision });
2073
+ }
2074
+ exactData(
2075
+ value,
2076
+ [
2077
+ "decision",
2078
+ "requestDigest",
2079
+ "authorizationEvidenceDigest",
2080
+ "auditEventDigest",
2081
+ "durabilityReceiptDigest",
2082
+ "authenticated",
2083
+ "durable",
2084
+ "readbackVerified",
2085
+ "authorizedAt",
2086
+ "validUntil",
2087
+ ],
2088
+ "Volcengine function revocation decision",
2089
+ );
2090
+ const validUntil = ownData(
2091
+ value,
2092
+ "validUntil",
2093
+ "Volcengine function revocation decision expiry",
2094
+ );
2095
+ const authorizedAt = ownData(
2096
+ value,
2097
+ "authorizedAt",
2098
+ "Volcengine function revocation authorization time",
2099
+ );
2100
+ const authorizedAtMs = Date.parse(authorizedAt);
2101
+ const validUntilMs = Date.parse(validUntil);
2102
+ const normalized = Object.freeze({
2103
+ decision,
2104
+ requestDigest: ownData(
2105
+ value,
2106
+ "requestDigest",
2107
+ "Volcengine function revocation decision request digest",
2108
+ ),
2109
+ authorizationEvidenceDigest: ownData(
2110
+ value,
2111
+ "authorizationEvidenceDigest",
2112
+ "Volcengine function revocation authorization evidence digest",
2113
+ ),
2114
+ auditEventDigest: ownData(
2115
+ value,
2116
+ "auditEventDigest",
2117
+ "Volcengine function revocation audit event digest",
2118
+ ),
2119
+ durabilityReceiptDigest: ownData(
2120
+ value,
2121
+ "durabilityReceiptDigest",
2122
+ "Volcengine function revocation durability receipt digest",
2123
+ ),
2124
+ authenticated: ownData(
2125
+ value,
2126
+ "authenticated",
2127
+ "Volcengine function revocation authentication status",
2128
+ ),
2129
+ durable: ownData(
2130
+ value,
2131
+ "durable",
2132
+ "Volcengine function revocation durability status",
2133
+ ),
2134
+ readbackVerified: ownData(
2135
+ value,
2136
+ "readbackVerified",
2137
+ "Volcengine function revocation readback status",
2138
+ ),
2139
+ authorizedAt,
2140
+ authorizedAtMs,
2141
+ validUntil,
2142
+ validUntilMs,
2143
+ });
2144
+ if (
2145
+ normalized.decision !== "allow" ||
2146
+ normalized.requestDigest !== request.requestDigest ||
2147
+ !DIGEST.test(normalized.authorizationEvidenceDigest) ||
2148
+ !DIGEST.test(normalized.auditEventDigest) ||
2149
+ !DIGEST.test(normalized.durabilityReceiptDigest) ||
2150
+ normalized.authenticated !== true ||
2151
+ normalized.durable !== true ||
2152
+ normalized.readbackVerified !== true ||
2153
+ !Number.isFinite(authorizedAtMs) ||
2154
+ new Date(authorizedAtMs).toISOString() !== authorizedAt ||
2155
+ authorizedAtMs < Date.parse(request.requestedAt) ||
2156
+ authorizedAtMs > nowMs + MAX_CLOCK_SKEW_MS ||
2157
+ !Number.isFinite(validUntilMs) ||
2158
+ new Date(validUntilMs).toISOString() !== validUntil ||
2159
+ validUntilMs <= authorizedAtMs ||
2160
+ validUntilMs > authorizedAtMs + descriptor.maxGrantTtlMs
2161
+ ) {
2162
+ throw new TypeError("Volcengine function revocation decision is invalid");
2163
+ }
2164
+ return normalized;
2165
+ }
2166
+
2167
+ function revokedError() {
2168
+ const error = new Error(
2169
+ "Volcengine function execution authority was revoked",
2170
+ );
2171
+ error.code = "CC_VOLCENGINE_FUNCTION_AUTHORITY_REVOKED";
2172
+ return error;
2173
+ }
2174
+
2175
+ function revocationStatusError(cause) {
2176
+ const error = new Error(
2177
+ "Volcengine function authority revocation status is unavailable",
2178
+ { cause },
2179
+ );
2180
+ error.code = "CC_VOLCENGINE_FUNCTION_REVOCATION_STATUS_UNAVAILABLE";
2181
+ return error;
2182
+ }
2183
+
2184
+ function markAuthorityRevoked(captured) {
2185
+ if (captured.revoked) return false;
2186
+ captured.revoked = true;
2187
+ for (const controller of captured.activeExecutions) {
2188
+ controller.abort(revokedError());
2189
+ }
2190
+ return true;
2191
+ }
2192
+
2193
+ function synchronizeDurableRevocation(captured) {
2194
+ let revocation;
2195
+ try {
2196
+ revocation = Reflect.apply(captured.readRevocation, undefined, []);
2197
+ } catch (cause) {
2198
+ throw revocationStatusError(cause);
2199
+ }
2200
+ if (revocation === null) return false;
2201
+ exactData(
2202
+ revocation,
2203
+ [
2204
+ "schema",
2205
+ "replayStoreId",
2206
+ "authorityId",
2207
+ "revocationAuthorityId",
2208
+ "tenantId",
2209
+ "handlerArtifactDigest",
2210
+ "policyRevision",
2211
+ "revocationId",
2212
+ "reasonDigest",
2213
+ "authorizationRequestDigest",
2214
+ "authorizationEvidenceDigest",
2215
+ "auditEventDigest",
2216
+ "durabilityReceiptDigest",
2217
+ "evidenceResolverDigest",
2218
+ "evidenceReadbackDigest",
2219
+ "revokedAt",
2220
+ "revocationDigest",
2221
+ ],
2222
+ "Volcengine function authority revocation record",
2223
+ );
2224
+ if (
2225
+ revocation.schema !== VOLCENGINE_FUNCTION_REVOCATION_SCHEMA ||
2226
+ revocation.replayStoreId !== captured.descriptor.replayStoreId ||
2227
+ revocation.authorityId !== captured.descriptor.authorityId ||
2228
+ revocation.revocationAuthorityId !==
2229
+ captured.descriptor.revocationAuthorityId ||
2230
+ revocation.tenantId !== captured.descriptor.tenantId ||
2231
+ revocation.handlerArtifactDigest !==
2232
+ captured.descriptor.handlerArtifactDigest ||
2233
+ revocation.policyRevision !== captured.descriptor.policyRevision ||
2234
+ !DIGEST.test(revocation.authorizationRequestDigest) ||
2235
+ !DIGEST.test(revocation.evidenceResolverDigest) ||
2236
+ !DIGEST.test(revocation.evidenceReadbackDigest) ||
2237
+ !DIGEST.test(revocation.revocationDigest)
2238
+ ) {
2239
+ throw revocationStatusError();
2240
+ }
2241
+ markAuthorityRevoked(captured);
2242
+ return true;
2243
+ }
2244
+
2245
+ function assertAuthorityActive(captured) {
2246
+ if (captured.revoked) throw revokedError();
2247
+ }
2248
+
2249
+ async function executeWithinDeadline(captured, request) {
2250
+ assertAuthorityActive(captured);
2251
+ const controller = new AbortController();
2252
+ const deadlineError = new Error(
2253
+ "Volcengine function execution deadline exceeded",
2254
+ );
2255
+ deadlineError.code = "CC_VOLCENGINE_FUNCTION_DEADLINE_EXCEEDED";
2256
+ const remainingMs = request.deadlineAtMs - captured.now();
2257
+ if (!Number.isFinite(remainingMs) || remainingMs <= 0) {
2258
+ controller.abort(deadlineError);
2259
+ throw deadlineError;
2260
+ }
2261
+ captured.activeExecutions.add(controller);
2262
+ try {
2263
+ synchronizeDurableRevocation(captured);
2264
+ assertAuthorityActive(captured);
2265
+ } catch (cause) {
2266
+ captured.activeExecutions.delete(controller);
2267
+ if (!controller.signal.aborted) controller.abort(cause);
2268
+ throw cause;
2269
+ }
2270
+ let timer;
2271
+ let revocationPoll;
2272
+ let rejectCancellation;
2273
+ const cancellation = new Promise((_resolve, reject) => {
2274
+ rejectCancellation = reject;
2275
+ });
2276
+ const onAbort = () => rejectCancellation(controller.signal.reason);
2277
+ controller.signal.addEventListener("abort", onAbort, { once: true });
2278
+ timer = setTimeout(() => controller.abort(deadlineError), remainingMs);
2279
+ revocationPoll = setInterval(() => {
2280
+ try {
2281
+ synchronizeDurableRevocation(captured);
2282
+ } catch (cause) {
2283
+ if (!controller.signal.aborted) {
2284
+ controller.abort(cause);
2285
+ }
2286
+ }
2287
+ }, 50);
2288
+ const context = Object.freeze({
2289
+ signal: controller.signal,
2290
+ deadlineAt: request.deadlineAt,
2291
+ functionPolicyDigest: request.functionPolicyDigest,
2292
+ replayReservationDigest: request.replayReservationDigest,
2293
+ });
2294
+ try {
2295
+ const response = await Promise.race([
2296
+ Promise.resolve().then(() => captured.execute(request, context)),
2297
+ cancellation,
2298
+ ]);
2299
+ synchronizeDurableRevocation(captured);
2300
+ assertAuthorityActive(captured);
2301
+ return response;
2302
+ } finally {
2303
+ clearTimeout(timer);
2304
+ clearInterval(revocationPoll);
2305
+ controller.signal.removeEventListener("abort", onAbort);
2306
+ captured.activeExecutions.delete(controller);
2307
+ }
2308
+ }
2309
+
2310
+ export function createVolcengineFunctionExecutionAuthority({
2311
+ descriptor,
2312
+ execute,
2313
+ replayStore,
2314
+ now = () => Date.now(),
2315
+ } = {}) {
2316
+ const normalizedDescriptor = normalizeDescriptor(descriptor);
2317
+ if (typeof execute !== "function" || types.isProxy(execute)) {
2318
+ throw new TypeError("Volcengine function execution port is invalid");
2319
+ }
2320
+ if (typeof now !== "function" || types.isProxy(now)) {
2321
+ throw new TypeError("Volcengine function authority clock is invalid");
2322
+ }
2323
+ const replayPort = captureVolcengineFunctionReplayStore(replayStore);
2324
+ exactData(
2325
+ replayPort,
2326
+ ["descriptor", "readRevocation", "revoke", "reserve"],
2327
+ "Volcengine function replay store port",
2328
+ );
2329
+ const replayDescriptor = ownData(
2330
+ replayPort,
2331
+ "descriptor",
2332
+ "Volcengine function replay store descriptor",
2333
+ );
2334
+ exactData(
2335
+ replayDescriptor,
2336
+ [
2337
+ "schema",
2338
+ "replayStoreId",
2339
+ "authorityId",
2340
+ "revocationAuthorityId",
2341
+ "tenantId",
2342
+ "handlerArtifactDigest",
2343
+ "policyRevision",
2344
+ "retentionMs",
2345
+ "mode",
2346
+ "revocationMode",
2347
+ ],
2348
+ "Volcengine function replay store descriptor",
2349
+ );
2350
+ if (
2351
+ replayDescriptor.schema !== VOLCENGINE_FUNCTION_REPLAY_STORE_SCHEMA ||
2352
+ replayDescriptor.replayStoreId !== normalizedDescriptor.replayStoreId ||
2353
+ replayDescriptor.authorityId !== normalizedDescriptor.authorityId ||
2354
+ replayDescriptor.revocationAuthorityId !==
2355
+ normalizedDescriptor.revocationAuthorityId ||
2356
+ replayDescriptor.tenantId !== normalizedDescriptor.tenantId ||
2357
+ replayDescriptor.handlerArtifactDigest !==
2358
+ normalizedDescriptor.handlerArtifactDigest ||
2359
+ replayDescriptor.policyRevision !== normalizedDescriptor.policyRevision ||
2360
+ replayDescriptor.retentionMs !== normalizedDescriptor.replayRetentionMs ||
2361
+ replayDescriptor.mode !== normalizedDescriptor.replayMode ||
2362
+ replayDescriptor.revocationMode !== normalizedDescriptor.revocationMode
2363
+ ) {
2364
+ throw new TypeError(
2365
+ "Volcengine function replay store binding does not match authority",
2366
+ );
2367
+ }
2368
+ const reserveReplay = ownData(
2369
+ replayPort,
2370
+ "reserve",
2371
+ "Volcengine function replay reservation port",
2372
+ );
2373
+ if (typeof reserveReplay !== "function" || types.isProxy(reserveReplay)) {
2374
+ throw new TypeError(
2375
+ "Volcengine function replay reservation port is invalid",
2376
+ );
2377
+ }
2378
+ const readRevocation = ownData(
2379
+ replayPort,
2380
+ "readRevocation",
2381
+ "Volcengine function revocation reader",
2382
+ );
2383
+ const persistRevocation = ownData(
2384
+ replayPort,
2385
+ "revoke",
2386
+ "Volcengine function durable revocation writer",
2387
+ );
2388
+ if (
2389
+ typeof readRevocation !== "function" ||
2390
+ types.isProxy(readRevocation) ||
2391
+ typeof persistRevocation !== "function" ||
2392
+ types.isProxy(persistRevocation)
2393
+ ) {
2394
+ throw new TypeError("Volcengine function revocation store port is invalid");
2395
+ }
2396
+ const authority = Object.freeze({});
2397
+ authorities.set(authority, {
2398
+ descriptor: normalizedDescriptor,
2399
+ execute,
2400
+ processExecutor: null,
2401
+ now,
2402
+ reserveReplay,
2403
+ readRevocation,
2404
+ persistRevocation,
2405
+ requests: new Map(),
2406
+ revoked: false,
2407
+ activeExecutions: new Set(),
2408
+ });
2409
+ return authority;
2410
+ }
2411
+
2412
+ export function createVolcengineFunctionProcessExecutionAuthority({
2413
+ descriptor,
2414
+ execute,
2415
+ replayStore,
2416
+ now = () => Date.now(),
2417
+ } = {}) {
2418
+ const normalizedDescriptor = normalizeProcessDescriptor(descriptor);
2419
+ const executorDescriptor = inspectVolcengineFunctionProcessExecutor(execute);
2420
+ if (
2421
+ executorDescriptor.mode !== "process" ||
2422
+ executorDescriptor.targetDigest !==
2423
+ normalizedDescriptor.processTargetDigest ||
2424
+ executorDescriptor.targetAuthorityDigest !==
2425
+ normalizedDescriptor.processTargetAuthorityDigest ||
2426
+ executorDescriptor.supervisorAuthorityDigest !==
2427
+ normalizedDescriptor.processSupervisorAuthorityDigest ||
2428
+ executorDescriptor.handlerArtifactDigest !==
2429
+ normalizedDescriptor.handlerArtifactDigest
2430
+ ) {
2431
+ throw new TypeError(
2432
+ "Volcengine function process executor binding does not match authority",
2433
+ );
2434
+ }
2435
+ const baseDescriptor = {
2436
+ schema: VOLCENGINE_FUNCTION_AUTHORITY_SCHEMA,
2437
+ authorityId: normalizedDescriptor.authorityId,
2438
+ revocationAuthorityId: normalizedDescriptor.revocationAuthorityId,
2439
+ tenantId: normalizedDescriptor.tenantId,
2440
+ handlerArtifactDigest: normalizedDescriptor.handlerArtifactDigest,
2441
+ policyRevision: normalizedDescriptor.policyRevision,
2442
+ replayStoreId: normalizedDescriptor.replayStoreId,
2443
+ replayRetentionMs: normalizedDescriptor.replayRetentionMs,
2444
+ replayMode: normalizedDescriptor.replayMode,
2445
+ revocationMode: normalizedDescriptor.revocationMode,
2446
+ purpose: normalizedDescriptor.purpose,
2447
+ allowedFunctions: normalizedDescriptor.allowedFunctions,
2448
+ functionPolicies: normalizedDescriptor.functionPolicies,
2449
+ auditMode: normalizedDescriptor.auditMode,
2450
+ };
2451
+ const authority = createVolcengineFunctionExecutionAuthority({
2452
+ descriptor: baseDescriptor,
2453
+ execute,
2454
+ replayStore,
2455
+ now,
2456
+ });
2457
+ const captured = authorities.get(authority);
2458
+ captured.descriptor = normalizedDescriptor;
2459
+ captured.processExecutor = Object.freeze({
2460
+ execute,
2461
+ descriptor: executorDescriptor,
2462
+ });
2463
+ return authority;
2464
+ }
2465
+
2466
+ export function revokeVolcengineFunctionExecutionAuthority(value) {
2467
+ const captured = authorities.get(value);
2468
+ if (!captured) {
2469
+ throw new TypeError(
2470
+ "A branded Volcengine function execution authority is required",
2471
+ );
2472
+ }
2473
+ return markAuthorityRevoked(captured);
2474
+ }
2475
+
2476
+ async function persistVolcengineFunctionExecutionAuthorityRevocation(
2477
+ value,
2478
+ evidence,
2479
+ ) {
2480
+ const captured = authorities.get(value);
2481
+ if (!captured) {
2482
+ throw new TypeError(
2483
+ "A branded Volcengine function execution authority is required",
2484
+ );
2485
+ }
2486
+ exactData(
2487
+ evidence,
2488
+ [
2489
+ "revocationId",
2490
+ "reasonDigest",
2491
+ "revocationAuthorityId",
2492
+ "authorizationRequestDigest",
2493
+ "authorizationEvidenceDigest",
2494
+ "auditEventDigest",
2495
+ "durabilityReceiptDigest",
2496
+ "evidenceResolverDigest",
2497
+ "evidenceReadbackDigest",
2498
+ "revokedAt",
2499
+ ],
2500
+ "Volcengine function revocation evidence",
2501
+ );
2502
+ const core = Object.freeze({
2503
+ schema: VOLCENGINE_FUNCTION_REVOCATION_SCHEMA,
2504
+ replayStoreId: captured.descriptor.replayStoreId,
2505
+ authorityId: captured.descriptor.authorityId,
2506
+ tenantId: captured.descriptor.tenantId,
2507
+ handlerArtifactDigest: captured.descriptor.handlerArtifactDigest,
2508
+ policyRevision: captured.descriptor.policyRevision,
2509
+ revocationAuthorityId: ownData(
2510
+ evidence,
2511
+ "revocationAuthorityId",
2512
+ "Volcengine function revocation decision authority",
2513
+ ),
2514
+ revocationId: ownData(
2515
+ evidence,
2516
+ "revocationId",
2517
+ "Volcengine function revocation identifier",
2518
+ ),
2519
+ reasonDigest: ownData(
2520
+ evidence,
2521
+ "reasonDigest",
2522
+ "Volcengine function revocation reason digest",
2523
+ ),
2524
+ authorizationRequestDigest: ownData(
2525
+ evidence,
2526
+ "authorizationRequestDigest",
2527
+ "Volcengine function revocation authorization request digest",
2528
+ ),
2529
+ authorizationEvidenceDigest: ownData(
2530
+ evidence,
2531
+ "authorizationEvidenceDigest",
2532
+ "Volcengine function revocation authorization evidence digest",
2533
+ ),
2534
+ auditEventDigest: ownData(
2535
+ evidence,
2536
+ "auditEventDigest",
2537
+ "Volcengine function revocation audit event digest",
2538
+ ),
2539
+ durabilityReceiptDigest: ownData(
2540
+ evidence,
2541
+ "durabilityReceiptDigest",
2542
+ "Volcengine function revocation durability receipt digest",
2543
+ ),
2544
+ evidenceResolverDigest: ownData(
2545
+ evidence,
2546
+ "evidenceResolverDigest",
2547
+ "Volcengine function revocation evidence resolver digest",
2548
+ ),
2549
+ evidenceReadbackDigest: ownData(
2550
+ evidence,
2551
+ "evidenceReadbackDigest",
2552
+ "Volcengine function revocation evidence readback digest",
2553
+ ),
2554
+ revokedAt: ownData(
2555
+ evidence,
2556
+ "revokedAt",
2557
+ "Volcengine function revocation time",
2558
+ ),
2559
+ });
2560
+ const revokedAtMs = Date.parse(core.revokedAt);
2561
+ const nowMs = captured.now();
2562
+ if (
2563
+ !ID.test(core.revocationId) ||
2564
+ core.revocationAuthorityId !== captured.descriptor.revocationAuthorityId ||
2565
+ !DIGEST.test(core.reasonDigest) ||
2566
+ !DIGEST.test(core.authorizationRequestDigest) ||
2567
+ !DIGEST.test(core.authorizationEvidenceDigest) ||
2568
+ !DIGEST.test(core.auditEventDigest) ||
2569
+ !DIGEST.test(core.durabilityReceiptDigest) ||
2570
+ !DIGEST.test(core.evidenceResolverDigest) ||
2571
+ !DIGEST.test(core.evidenceReadbackDigest) ||
2572
+ !Number.isFinite(revokedAtMs) ||
2573
+ new Date(revokedAtMs).toISOString() !== core.revokedAt ||
2574
+ !Number.isFinite(nowMs) ||
2575
+ revokedAtMs > nowMs + MAX_CLOCK_SKEW_MS
2576
+ ) {
2577
+ throw new TypeError("Volcengine function revocation evidence is invalid");
2578
+ }
2579
+ const revocation = Object.freeze({
2580
+ ...core,
2581
+ revocationDigest: digest(VOLCENGINE_FUNCTION_REVOCATION_SCHEMA, core),
2582
+ });
2583
+ markAuthorityRevoked(captured);
2584
+ const acknowledgement = await Reflect.apply(
2585
+ captured.persistRevocation,
2586
+ undefined,
2587
+ [revocation],
2588
+ );
2589
+ exactData(
2590
+ acknowledgement,
2591
+ ["revocationDigest", "durable", "readbackVerified"],
2592
+ "Volcengine function revocation acknowledgement",
2593
+ );
2594
+ if (
2595
+ acknowledgement.revocationDigest !== revocation.revocationDigest ||
2596
+ acknowledgement.durable !== true ||
2597
+ acknowledgement.readbackVerified !== true
2598
+ ) {
2599
+ throw new TypeError(
2600
+ "Volcengine function revocation acknowledgement is invalid",
2601
+ );
2602
+ }
2603
+ return Object.freeze({
2604
+ revoked: true,
2605
+ revocationDigest: revocation.revocationDigest,
2606
+ durable: true,
2607
+ readbackVerified: true,
2608
+ });
2609
+ }
2610
+
2611
+ export function createVolcengineFunctionRevocationAuthority(options) {
2612
+ exactData(
2613
+ options,
2614
+ ["descriptor", "authorize", "evidenceResolver", "now"],
2615
+ "Volcengine function revocation authority",
2616
+ );
2617
+ const descriptor = normalizeRevocationAuthorityDescriptor(
2618
+ ownData(
2619
+ options,
2620
+ "descriptor",
2621
+ "Volcengine function revocation authority descriptor",
2622
+ ),
2623
+ );
2624
+ const authorize = ownData(
2625
+ options,
2626
+ "authorize",
2627
+ "Volcengine function revocation authorization port",
2628
+ );
2629
+ const evidenceResolver = ownData(
2630
+ options,
2631
+ "evidenceResolver",
2632
+ "Volcengine function revocation evidence resolver",
2633
+ );
2634
+ const now = ownData(
2635
+ options,
2636
+ "now",
2637
+ "Volcengine function revocation authority clock",
2638
+ );
2639
+ if (typeof authorize !== "function" || types.isProxy(authorize)) {
2640
+ throw new TypeError(
2641
+ "Volcengine function revocation authorization port is invalid",
2642
+ );
2643
+ }
2644
+ if (typeof now !== "function" || types.isProxy(now)) {
2645
+ throw new TypeError("Volcengine function revocation clock is invalid");
2646
+ }
2647
+ const evidenceResolverDescriptor =
2648
+ inspectVolcengineFunctionRevocationEvidenceResolver(evidenceResolver);
2649
+ if (
2650
+ evidenceResolverDescriptor.descriptorDigest !==
2651
+ descriptor.evidenceResolverDigest ||
2652
+ evidenceResolverDescriptor.descriptor.tenantId !== descriptor.tenantId ||
2653
+ evidenceResolverDescriptor.descriptor.revocationAuthorityId !==
2654
+ descriptor.authorityId ||
2655
+ evidenceResolverDescriptor.descriptor.handlerArtifactDigest !==
2656
+ descriptor.handlerArtifactDigest
2657
+ ) {
2658
+ throw new TypeError(
2659
+ "Volcengine function revocation evidence resolver does not match authority",
2660
+ );
2661
+ }
2662
+ const authority = Object.freeze({});
2663
+ revocationAuthorities.set(authority, {
2664
+ descriptor,
2665
+ authorize,
2666
+ evidenceResolver,
2667
+ now,
2668
+ });
2669
+ return authority;
2670
+ }
2671
+
2672
+ export function captureVolcengineFunctionRevocationAuthority(value) {
2673
+ const captured = revocationAuthorities.get(value);
2674
+ if (!captured) {
2675
+ throw new TypeError(
2676
+ "A branded Volcengine function revocation authority is required",
2677
+ );
2678
+ }
2679
+ return Object.freeze({
2680
+ descriptor: captured.descriptor,
2681
+ revokeAuthority: async (targetAuthority, value) => {
2682
+ const target = authorities.get(targetAuthority);
2683
+ if (!target) {
2684
+ throw new TypeError(
2685
+ "A branded Volcengine function execution authority is required",
2686
+ );
2687
+ }
2688
+ assertRevocationTargetBinding(target.descriptor, captured.descriptor);
2689
+ const nowMs = captured.now();
2690
+ if (!Number.isFinite(nowMs)) {
2691
+ throw new TypeError("Volcengine function revocation clock is invalid");
2692
+ }
2693
+ const request = normalizeRevocationRequest(
2694
+ value,
2695
+ captured.descriptor,
2696
+ nowMs,
2697
+ );
2698
+ const decision = normalizeRevocationDecision(
2699
+ await Reflect.apply(captured.authorize, undefined, [request]),
2700
+ request,
2701
+ captured.descriptor,
2702
+ nowMs,
2703
+ );
2704
+ if (decision.decision === "deny") {
2705
+ const error = new Error("Volcengine function revocation was denied");
2706
+ error.code = "CC_VOLCENGINE_FUNCTION_REVOCATION_DENIED";
2707
+ throw error;
2708
+ }
2709
+ const evidenceReadback = await resolveRevocationDecisionEvidence(
2710
+ captured.evidenceResolver,
2711
+ captured.descriptor,
2712
+ request,
2713
+ decision,
2714
+ );
2715
+ const revokedAtMs = captured.now();
2716
+ if (
2717
+ !Number.isFinite(revokedAtMs) ||
2718
+ revokedAtMs >= decision.validUntilMs
2719
+ ) {
2720
+ const error = new Error(
2721
+ "Volcengine function revocation grant expired before execution",
2722
+ );
2723
+ error.code = "CC_VOLCENGINE_FUNCTION_REVOCATION_GRANT_EXPIRED";
2724
+ throw error;
2725
+ }
2726
+ const revokedAt = decision.authorizedAt;
2727
+ const acknowledgement =
2728
+ await persistVolcengineFunctionExecutionAuthorityRevocation(
2729
+ targetAuthority,
2730
+ Object.freeze({
2731
+ revocationId: request.requestId,
2732
+ reasonDigest: request.reasonDigest,
2733
+ revocationAuthorityId: captured.descriptor.authorityId,
2734
+ authorizationRequestDigest: request.requestDigest,
2735
+ authorizationEvidenceDigest: decision.authorizationEvidenceDigest,
2736
+ auditEventDigest: decision.auditEventDigest,
2737
+ durabilityReceiptDigest: decision.durabilityReceiptDigest,
2738
+ evidenceResolverDigest: evidenceReadback.evidenceResolverDigest,
2739
+ evidenceReadbackDigest: evidenceReadback.evidenceReadbackDigest,
2740
+ revokedAt,
2741
+ }),
2742
+ );
2743
+ const resultCore = Object.freeze({
2744
+ schema: VOLCENGINE_FUNCTION_REVOCATION_RESULT_SCHEMA,
2745
+ authorityId: captured.descriptor.authorityId,
2746
+ tenantId: captured.descriptor.tenantId,
2747
+ handlerArtifactDigest: captured.descriptor.handlerArtifactDigest,
2748
+ policyRevision: captured.descriptor.policyRevision,
2749
+ targetAuthorityId: captured.descriptor.targetAuthorityId,
2750
+ targetReplayStoreId: captured.descriptor.targetReplayStoreId,
2751
+ targetPolicyRevision: captured.descriptor.targetPolicyRevision,
2752
+ requestId: request.requestId,
2753
+ requestDigest: request.requestDigest,
2754
+ revocationDigest: acknowledgement.revocationDigest,
2755
+ authorizationEvidenceDigest: decision.authorizationEvidenceDigest,
2756
+ auditEventDigest: decision.auditEventDigest,
2757
+ durabilityReceiptDigest: decision.durabilityReceiptDigest,
2758
+ evidenceResolverDigest: evidenceReadback.evidenceResolverDigest,
2759
+ evidenceReadbackDigest: evidenceReadback.evidenceReadbackDigest,
2760
+ revokedAt,
2761
+ status: "revoked",
2762
+ authenticated: true,
2763
+ durable: acknowledgement.durable,
2764
+ readbackVerified: acknowledgement.readbackVerified,
2765
+ });
2766
+ return Object.freeze({
2767
+ ...resultCore,
2768
+ resultDigest: digest(
2769
+ VOLCENGINE_FUNCTION_REVOCATION_RESULT_SCHEMA,
2770
+ resultCore,
2771
+ ),
2772
+ });
2773
+ },
2774
+ });
2775
+ }
2776
+
2777
+ export function captureVolcengineFunctionExecutionAuthority(value) {
2778
+ const captured = authorities.get(value);
2779
+ if (!captured) {
2780
+ throw new TypeError(
2781
+ "A branded Volcengine function execution authority is required",
2782
+ );
2783
+ }
2784
+ return Object.freeze({
2785
+ descriptor: captured.descriptor,
2786
+ executeFunction: async (value) => {
2787
+ assertAuthorityActive(captured);
2788
+ synchronizeDurableRevocation(captured);
2789
+ assertAuthorityActive(captured);
2790
+ const nowMs = captured.now();
2791
+ if (!Number.isFinite(nowMs)) {
2792
+ throw new TypeError("Volcengine function authority clock is invalid");
2793
+ }
2794
+ const request = normalizeRequest(value, captured.descriptor, nowMs);
2795
+ reserveRequest(captured, request, nowMs);
2796
+ const reservation = createReplayReservation(request, captured.descriptor);
2797
+ const reservationAck = await Reflect.apply(
2798
+ captured.reserveReplay,
2799
+ undefined,
2800
+ [reservation],
2801
+ );
2802
+ validateReplayReservationAck(reservationAck, reservation);
2803
+ const executionRequest = Object.freeze({
2804
+ ...request,
2805
+ replayReservationDigest: reservation.reservationDigest,
2806
+ });
2807
+ const response = await executeWithinDeadline(captured, executionRequest);
2808
+ let processEvidence = null;
2809
+ if (captured.processExecutor !== null) {
2810
+ processEvidence = captureVolcengineFunctionProcessResult(
2811
+ captured.processExecutor.execute,
2812
+ response,
2813
+ );
2814
+ exactData(
2815
+ processEvidence,
2816
+ [
2817
+ "schema",
2818
+ "requestDigest",
2819
+ "targetDigest",
2820
+ "targetAuthorityDigest",
2821
+ "supervisorAuthorityDigest",
2822
+ "supervisionReceiptDigest",
2823
+ "targetInvocationDigest",
2824
+ "revocationDigest",
2825
+ "completedAt",
2826
+ "isolation",
2827
+ "hardDeadlineEnforced",
2828
+ "lateSideEffectsPrevented",
2829
+ "evidenceDigest",
2830
+ ],
2831
+ "Volcengine function process evidence",
2832
+ );
2833
+ const { evidenceDigest, ...evidenceCore } = processEvidence;
2834
+ const processCompletedAtMs = Date.parse(processEvidence.completedAt);
2835
+ if (
2836
+ processEvidence.schema !==
2837
+ VOLCENGINE_FUNCTION_PROCESS_EVIDENCE_SCHEMA ||
2838
+ processEvidence.requestDigest !== executionRequest.requestDigest ||
2839
+ processEvidence.targetDigest !==
2840
+ captured.descriptor.processTargetDigest ||
2841
+ processEvidence.targetAuthorityDigest !==
2842
+ captured.descriptor.processTargetAuthorityDigest ||
2843
+ processEvidence.supervisorAuthorityDigest !==
2844
+ captured.descriptor.processSupervisorAuthorityDigest ||
2845
+ !DIGEST.test(processEvidence.supervisionReceiptDigest) ||
2846
+ !DIGEST.test(processEvidence.targetInvocationDigest) ||
2847
+ !DIGEST.test(processEvidence.revocationDigest) ||
2848
+ !Number.isFinite(processCompletedAtMs) ||
2849
+ new Date(processCompletedAtMs).toISOString() !==
2850
+ processEvidence.completedAt ||
2851
+ processCompletedAtMs < executionRequest.requestedAtMs ||
2852
+ processCompletedAtMs > executionRequest.deadlineAtMs ||
2853
+ processEvidence.isolation !== "process" ||
2854
+ processEvidence.hardDeadlineEnforced !== true ||
2855
+ processEvidence.lateSideEffectsPrevented !== true ||
2856
+ evidenceDigest !==
2857
+ digest(VOLCENGINE_FUNCTION_PROCESS_EVIDENCE_SCHEMA, evidenceCore)
2858
+ ) {
2859
+ throw new TypeError(
2860
+ "Volcengine function process evidence is invalid",
2861
+ );
2862
+ }
2863
+ }
2864
+ exactData(
2865
+ response,
2866
+ ["toolResult", "auditEvidence"],
2867
+ "Volcengine function execution response",
2868
+ );
2869
+ const policy = functionPolicy(captured.descriptor, request.functionName);
2870
+ const toolResult = normalizeJson(
2871
+ ownData(response, "toolResult", "Volcengine function execution result"),
2872
+ "Volcengine function result",
2873
+ policy.maxResultBytes,
2874
+ );
2875
+ const resultDigest = digest(
2876
+ "chainlesschain.volcengine-function-result/v1",
2877
+ toolResult,
2878
+ );
2879
+ const audit = validateAuditEvidence(
2880
+ ownData(
2881
+ response,
2882
+ "auditEvidence",
2883
+ "Volcengine function audit evidence",
2884
+ ),
2885
+ executionRequest,
2886
+ captured.descriptor,
2887
+ resultDigest,
2888
+ captured.now(),
2889
+ );
2890
+ if (
2891
+ processEvidence !== null &&
2892
+ Date.parse(audit.completedAt) > Date.parse(processEvidence.completedAt)
2893
+ ) {
2894
+ throw new TypeError(
2895
+ "Volcengine function audit completed after process supervision",
2896
+ );
2897
+ }
2898
+ return Object.freeze({
2899
+ toolResult,
2900
+ receipt: Object.freeze({
2901
+ schema:
2902
+ processEvidence === null
2903
+ ? VOLCENGINE_FUNCTION_RECEIPT_SCHEMA
2904
+ : VOLCENGINE_FUNCTION_PROCESS_RECEIPT_SCHEMA,
2905
+ authorityId: captured.descriptor.authorityId,
2906
+ tenantId: captured.descriptor.tenantId,
2907
+ handlerArtifactDigest: captured.descriptor.handlerArtifactDigest,
2908
+ policyRevision: captured.descriptor.policyRevision,
2909
+ replayStoreId: captured.descriptor.replayStoreId,
2910
+ revocationAuthorityId: captured.descriptor.revocationAuthorityId,
2911
+ revocationMode: captured.descriptor.revocationMode,
2912
+ actorDid: request.actorDid,
2913
+ purpose: VOLCENGINE_FUNCTION_PURPOSE,
2914
+ requestId: executionRequest.requestId,
2915
+ senderId: executionRequest.senderId,
2916
+ functionName: executionRequest.functionName,
2917
+ functionPolicyDigest: executionRequest.functionPolicyDigest,
2918
+ replayReservationDigest: executionRequest.replayReservationDigest,
2919
+ deadlineAt: executionRequest.deadlineAt,
2920
+ requestDigest: executionRequest.requestDigest,
2921
+ resultDigest,
2922
+ auditMode: VOLCENGINE_FUNCTION_AUDIT_MODE,
2923
+ auditEventDigest: audit.auditEventDigest,
2924
+ durabilityReceiptDigest: audit.durabilityReceiptDigest,
2925
+ authenticated: true,
2926
+ durable: true,
2927
+ readbackVerified: true,
2928
+ completedAt:
2929
+ processEvidence === null
2930
+ ? audit.completedAt
2931
+ : processEvidence.completedAt,
2932
+ ...(processEvidence === null
2933
+ ? {}
2934
+ : {
2935
+ executionIsolation: captured.descriptor.executionIsolation,
2936
+ processTargetDigest: processEvidence.targetDigest,
2937
+ processTargetAuthorityDigest:
2938
+ processEvidence.targetAuthorityDigest,
2939
+ processSupervisorAuthorityDigest:
2940
+ processEvidence.supervisorAuthorityDigest,
2941
+ processSupervisionReceiptDigest:
2942
+ processEvidence.supervisionReceiptDigest,
2943
+ processEvidenceDigest: processEvidence.evidenceDigest,
2944
+ }),
2945
+ }),
2946
+ });
2947
+ },
2948
+ });
2949
+ }