chainlesschain 0.166.15 → 0.166.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/package.json +1 -1
- package/src/assets/web-panel/assets/{AIOps-To-6rimH.js → AIOps-CTxa2Wbq.js} +1 -1
- package/src/assets/web-panel/assets/{ActionButton-CpdCnTv3.js → ActionButton-DHrQyYhy.js} +1 -1
- package/src/assets/web-panel/assets/{Analytics-DK7VNES_.js → Analytics-DQiUqcNl.js} +3 -3
- package/src/assets/web-panel/assets/{AppLayout-NZ5FvhCx.js → AppLayout-_Iz4r6wt.js} +5 -5
- package/src/assets/web-panel/assets/{Artifacts-NXceQPmN.js → Artifacts-BNs63YHo.js} +1 -1
- package/src/assets/web-panel/assets/{Audit-B2d64DH2.js → Audit-BgHIqRLn.js} +1 -1
- package/src/assets/web-panel/assets/{BackgroundAgents-ByYgvEVY.js → BackgroundAgents-DUQ5axBB.js} +1 -1
- package/src/assets/web-panel/assets/{Backup-BXvQLDvN.js → Backup-CJ51E9Vw.js} +1 -1
- package/src/assets/web-panel/assets/{BaseInput-C4GZk-As.js → BaseInput-o-5toA_R.js} +1 -1
- package/src/assets/web-panel/assets/{Chat-CvPuohL8.js → Chat-Cu7a-x1L.js} +6 -6
- package/src/assets/web-panel/assets/{ChatBubbleRenderer-DTftcclX.js → ChatBubbleRenderer-BUyYkAXr.js} +1 -1
- package/src/assets/web-panel/assets/{Checkbox-C8dQGIqD.js → Checkbox-DwdmZ71L.js} +1 -1
- package/src/assets/web-panel/assets/{Codegen-DRM6S1W4.js → Codegen-BrH2eYiP.js} +1 -1
- package/src/assets/web-panel/assets/{Col-BDM8l-r5.js → Col-BVJQEP2j.js} +1 -1
- package/src/assets/web-panel/assets/{Community-Bvmfi1fX.js → Community-FGO3vZPq.js} +1 -1
- package/src/assets/web-panel/assets/{Compact-DGQTCima.js → Compact-DYGAFVnT.js} +1 -1
- package/src/assets/web-panel/assets/{Compliance-D_0C-2P6.js → Compliance-CRvc8Bdt.js} +1 -1
- package/src/assets/web-panel/assets/{Cowork-3C_q99ok.js → Cowork-D6Ah2m7A.js} +3 -3
- package/src/assets/web-panel/assets/{Cron-CIiMQ1Hl.js → Cron-AXbU2ifR.js} +2 -2
- package/src/assets/web-panel/assets/{Crosschain-peebGnES.js → Crosschain-C5DXgEFd.js} +1 -1
- package/src/assets/web-panel/assets/{DID-OkX4KB9T.js → DID-Bxh9QV9v.js} +2 -2
- package/src/assets/web-panel/assets/{Dashboard-D9lm0Wxa.js → Dashboard-B-ZHEta-.js} +2 -2
- package/src/assets/web-panel/assets/{Dropdown-CitActXx.js → Dropdown-66Ik1jqa.js} +1 -1
- package/src/assets/web-panel/assets/{EmailListRenderer-DSmFkNKV.js → EmailListRenderer-CCWk1BIM.js} +1 -1
- package/src/assets/web-panel/assets/{FamilyGuardDashboard-CBWAi8XL.js → FamilyGuardDashboard--9faIULK.js} +1 -1
- package/src/assets/web-panel/assets/{Federation-afj8jDcp.js → Federation-CejW9CgX.js} +1 -1
- package/src/assets/web-panel/assets/{FormItemContext-Dabt59KY.js → FormItemContext-acHgcXki.js} +1 -1
- package/src/assets/web-panel/assets/{GenericCardRenderer-BQpXA9kj.js → GenericCardRenderer-D2ghd_K4.js} +1 -1
- package/src/assets/web-panel/assets/{Git-D2p2Moo1.js → Git-BOe1YJrV.js} +2 -2
- package/src/assets/web-panel/assets/{Governance-DkFfPykv.js → Governance-BjgzJsof.js} +1 -1
- package/src/assets/web-panel/assets/{Inference-C1DKpeN2.js → Inference-CXCD5rnP.js} +1 -1
- package/src/assets/web-panel/assets/{KnowledgeGraph-CjfVg4oQ.js → KnowledgeGraph-CHA8QgJT.js} +1 -1
- package/src/assets/web-panel/assets/{Logs-D-zMvdSf.js → Logs-DORPMcL6.js} +2 -2
- package/src/assets/web-panel/assets/{MarkdownRenderer-jzEpGkbc.js → MarkdownRenderer-CPPHz01z.js} +1 -1
- package/src/assets/web-panel/assets/{Marketplace-DfAjJLyS.js → Marketplace-BCFlo1Yx.js} +1 -1
- package/src/assets/web-panel/assets/{McpTools-BGDHQES1.js → McpTools-Dl_uZAKh.js} +3 -3
- package/src/assets/web-panel/assets/{Memory-BYqrGAPS.js → Memory-DupHamwz.js} +2 -2
- package/src/assets/web-panel/assets/{MobileBridge-CQ6FEtty.js → MobileBridge-BRSMPJxW.js} +1 -1
- package/src/assets/web-panel/assets/{MobileProjects-BpMvh5JW.js → MobileProjects-BHpuzsDl.js} +1 -1
- package/src/assets/web-panel/assets/{Mtc-CWH25SrU.js → Mtc-Ch0jOQfZ.js} +2 -2
- package/src/assets/web-panel/assets/{MtcAudit-D6DiLmei.js → MtcAudit-qzwQrDi7.js} +2 -2
- package/src/assets/web-panel/assets/{Multisig-BSxRN4jD.js → Multisig-B5wHzUcm.js} +3 -3
- package/src/assets/web-panel/assets/{NLProgramming-C0FDPKT4.js → NLProgramming-Hy9uAiA0.js} +1 -1
- package/src/assets/web-panel/assets/{Notes-VKR78bH-.js → Notes-DkuchMC7.js} +3 -3
- package/src/assets/web-panel/assets/{NotificationSettings-DLSklSZB.js → NotificationSettings-CYZhD7Pi.js} +1 -1
- package/src/assets/web-panel/assets/{OrderTableRenderer-Dpj7D6tC.js → OrderTableRenderer-DKOoqajt.js} +1 -1
- package/src/assets/web-panel/assets/{Organization-BB3pB27e.js → Organization-D9AXn6j8.js} +4 -4
- package/src/assets/web-panel/assets/{Overflow-Cr7bzwcs.js → Overflow-Bg15J6hX.js} +1 -1
- package/src/assets/web-panel/assets/{P2P-D1fkMMzI.js → P2P--B54HoQn.js} +2 -2
- package/src/assets/web-panel/assets/{PdhVaultBrowser-BiDEbLNA.js → PdhVaultBrowser-Cz9Kk2Nb.js} +3 -3
- package/src/assets/web-panel/assets/{Permissions-c3Ijv0v4.js → Permissions-DHx38eS1.js} +4 -4
- package/src/assets/web-panel/assets/{PersonalDataHub-BJwbh3P2.js → PersonalDataHub-Dw8i2hAs.js} +4 -4
- package/src/assets/web-panel/assets/{Pipeline-C4fhXafB.js → Pipeline-B2o6Ur2G.js} +1 -1
- package/src/assets/web-panel/assets/{Privacy-DzSx3CD-.js → Privacy-8g-h2fnu.js} +1 -1
- package/src/assets/web-panel/assets/{ProjectInit-D9fL5fED.js → ProjectInit-DuVTcINx.js} +2 -2
- package/src/assets/web-panel/assets/{ProjectSettings-CB5FVrOR.js → ProjectSettings-C8njvdZX.js} +2 -2
- package/src/assets/web-panel/assets/Projects-Ca9BAfu7.js +1 -0
- package/src/assets/web-panel/assets/{Providers-B9ZH4faS.js → Providers-wFqgod_W.js} +1 -1
- package/src/assets/web-panel/assets/{QrScannerModal-BLKDHT8_.js → QrScannerModal-9NCXrpmA.js} +1 -1
- package/src/assets/web-panel/assets/{QuickAsk-D1oYUcSY.js → QuickAsk-WUTNvFkY.js} +1 -1
- package/src/assets/web-panel/assets/{Recommend-CC2nmrOD.js → Recommend-xT4nYmju.js} +1 -1
- package/src/assets/web-panel/assets/{RemoteSession-qW9QF4-r.js → RemoteSession-fak1PBGC.js} +2 -2
- package/src/assets/web-panel/assets/{Reputation-BDWqfzcr.js → Reputation-D1AkQvD-.js} +1 -1
- package/src/assets/web-panel/assets/{Row-BBV2iCjT.js → Row-DVfm6xGt.js} +1 -1
- package/src/assets/web-panel/assets/{RssFeed-CcwrNwZB.js → RssFeed-BDunoLSE.js} +3 -3
- package/src/assets/web-panel/assets/{Search-Dr6fZ0D_.js → Search-OPycRoU3.js} +1 -1
- package/src/assets/web-panel/assets/{Security-BPzaoCU6.js → Security-C8-Fm3Dt.js} +4 -4
- package/src/assets/web-panel/assets/{Services-BoKUU1I_.js → Services-qM_sMpMl.js} +2 -2
- package/src/assets/web-panel/assets/{Skeleton-C8lT8GUg.js → Skeleton-D3HBJjVF.js} +1 -1
- package/src/assets/web-panel/assets/{Skills-DPpWeicz.js → Skills-jr67X-tP.js} +1 -1
- package/src/assets/web-panel/assets/{Sla-UiijzpMU.js → Sla-CS3ggyCg.js} +1 -1
- package/src/assets/web-panel/assets/{SpeechSettings-DoofrLwS.js → SpeechSettings-CTOCYxOi.js} +1 -1
- package/src/assets/web-panel/assets/{SyncSettings-DXnyfTDw.js → SyncSettings-D3s3cLT5.js} +2 -2
- package/src/assets/web-panel/assets/{Tasks-g_WHjKeg.js → Tasks-CdfoJ25m.js} +1 -1
- package/src/assets/web-panel/assets/{Templates-DRuCh9g2.js → Templates-Drb4AI8X.js} +1 -1
- package/src/assets/web-panel/assets/{Tenant-QHIq1pH1.js → Tenant-DzwR3Qkz.js} +1 -1
- package/src/assets/web-panel/assets/{Terminal-G0fuI216.js → Terminal-D-ESq7xp.js} +2 -2
- package/src/assets/web-panel/assets/{TimelineRenderer-4MT7SpGk.js → TimelineRenderer-BK-AUuws.js} +1 -1
- package/src/assets/web-panel/assets/{Tokens-B5xT5umA.js → Tokens-xGTouuNp.js} +1 -1
- package/src/assets/web-panel/assets/{Trigger-D7HPbNgc.js → Trigger-BvZj-v2H.js} +1 -1
- package/src/assets/web-panel/assets/{Trust-CxH69dU5.js → Trust-BLC9CGmc.js} +1 -1
- package/src/assets/web-panel/assets/{UkeySign-CPPosveH.js → UkeySign-BSuCXpmE.js} +1 -1
- package/src/assets/web-panel/assets/{VideoEditing-Du5lGwAt.js → VideoEditing-DT3A-_Ql.js} +1 -1
- package/src/assets/web-panel/assets/{Wallet-BBIGNESK.js → Wallet-c1OXao85.js} +4 -4
- package/src/assets/web-panel/assets/{WebAuthn-Cc3HSGmv.js → WebAuthn-CuA-F7KJ.js} +5 -5
- package/src/assets/web-panel/assets/{WorkflowEditor-DBoVPNCh.js → WorkflowEditor-MANZrf82.js} +1 -1
- package/src/assets/web-panel/assets/{chat-DHcjgiem.js → chat-D4Y4Ey0O.js} +1 -1
- package/src/assets/web-panel/assets/{colors-DrRrvJIV.js → colors-DDH06hKO.js} +1 -1
- package/src/assets/web-panel/assets/{compact-item-BuY_sAoN.js → compact-item-Cym756Xj.js} +1 -1
- package/src/assets/web-panel/assets/{createContext-CepH1Fha.js → createContext-By4Nb1k-.js} +1 -1
- package/src/assets/web-panel/assets/devWarning-KO3pAGeO.js +1 -0
- package/src/assets/web-panel/assets/{hasIn-Dh80Ot6o.js → hasIn-Ch7OY258.js} +1 -1
- package/src/assets/web-panel/assets/{index-BW9Pycxh.js → index-6-2eYBXr.js} +1 -1
- package/src/assets/web-panel/assets/{index-D7lstbTh.js → index-6CpOV3Pn.js} +1 -1
- package/src/assets/web-panel/assets/{index-CUnd5hyp.js → index-ArMrnx0v.js} +1 -1
- package/src/assets/web-panel/assets/{index-B0rvJjId.js → index-B51otVoZ.js} +1 -1
- package/src/assets/web-panel/assets/{index-D6tOVlq-.js → index-BBBUn5v7.js} +1 -1
- package/src/assets/web-panel/assets/{index-NS9dW1F1.js → index-BFydNU6a.js} +1 -1
- package/src/assets/web-panel/assets/{index-CiUx-tkV.js → index-BIrRX-ra.js} +1 -1
- package/src/assets/web-panel/assets/{index-By0qqC3S.js → index-BZB9q-Lp.js} +1 -1
- package/src/assets/web-panel/assets/index-Bh4Rgkg2.js +1 -0
- package/src/assets/web-panel/assets/{index-CNQK9DIr.js → index-Bo20BfdS.js} +1 -1
- package/src/assets/web-panel/assets/{index-C10033eO.js → index-CF3Lhyns.js} +1 -1
- package/src/assets/web-panel/assets/{index-DRy3_beb.js → index-CGsvEbbq.js} +1 -1
- package/src/assets/web-panel/assets/{index-DWANFMlq.js → index-CJPks33Y.js} +1 -1
- package/src/assets/web-panel/assets/{index-CnRK8_Dd.js → index-CT-3FYwd.js} +1 -1
- package/src/assets/web-panel/assets/{index-BPDEOOlA.js → index-CUSUzaB8.js} +1 -1
- package/src/assets/web-panel/assets/{index-DYN49m7k.js → index-CV1UC4zo.js} +1 -1
- package/src/assets/web-panel/assets/{index-C5vhNRqS.js → index-CV8qXTvb.js} +1 -1
- package/src/assets/web-panel/assets/{index-9crgJ3Id.js → index-CZn6dmZe.js} +1 -1
- package/src/assets/web-panel/assets/{index-DkZP_QaB.js → index-CjNUTBwe.js} +1 -1
- package/src/assets/web-panel/assets/{index-BoRy2yup.js → index-CpudmDhf.js} +1 -1
- package/src/assets/web-panel/assets/{index-Ca5d64IH.js → index-CykROEJA.js} +1 -1
- package/src/assets/web-panel/assets/{index-A5lVwYVq.js → index-D5sADPGY.js} +1 -1
- package/src/assets/web-panel/assets/{index-BnVIvc15.js → index-D9le0-dc.js} +1 -1
- package/src/assets/web-panel/assets/{index-Cx21_p3m.js → index-DAkk1M7x.js} +1 -1
- package/src/assets/web-panel/assets/{index-0TYLnd11.js → index-DNEJzc0r.js} +1 -1
- package/src/assets/web-panel/assets/{index-B9Gh-SOn.js → index-DNlxihs8.js} +1 -1
- package/src/assets/web-panel/assets/{index-BtqigRzf.js → index-DiewptTL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CW_23-gU.js → index-DjwgJ5Jd.js} +1 -1
- package/src/assets/web-panel/assets/index-Dox_coTY.js +1 -0
- package/src/assets/web-panel/assets/{index-LBkSOwky.js → index-DtGValNi.js} +1 -1
- package/src/assets/web-panel/assets/{index-D5_K3GKu.js → index-DvnywwUj.js} +1 -1
- package/src/assets/web-panel/assets/{index-BiZQooWK.js → index-OU8DZ9BL.js} +1 -1
- package/src/assets/web-panel/assets/{index-CYydOga6.js → index-XGeQMvWK.js} +1 -1
- package/src/assets/web-panel/assets/{index-hYaigdGm.js → index-ZY2Qs_Sn.js} +1 -1
- package/src/assets/web-panel/assets/{index-zGH9zH3w.js → index-jx7kr6mB.js} +3 -3
- package/src/assets/web-panel/assets/{index-DuRYBWrj.js → index-mL3nOcH6.js} +1 -1
- package/src/assets/web-panel/assets/{index-DuSUCH7h.js → index-oBsfUbyH.js} +1 -1
- package/src/assets/web-panel/assets/{index-CEfVkKIY.js → index-q-s04OKn.js} +1 -1
- package/src/assets/web-panel/assets/{index-DUNyTmkS.js → index-tZ5BUdad.js} +1 -1
- package/src/assets/web-panel/assets/{initDefaultProps-nI_X3wKl.js → initDefaultProps-DGcX9iPP.js} +1 -1
- package/src/assets/web-panel/assets/{motion-LUHbQu_R.js → motion-2SeL1D8A.js} +1 -1
- package/src/assets/web-panel/assets/{move-DHI_KvJt.js → move-3cYbQCpS.js} +1 -1
- package/src/assets/web-panel/assets/{mtc-parser-AYdL_7Mo.js → mtc-parser-IDdxfw0z.js} +1 -1
- package/src/assets/web-panel/assets/{omit-CtV3HRKa.js → omit-BNswdKO6.js} +1 -1
- package/src/assets/web-panel/assets/{pickAttrs-CcJLTOu4.js → pickAttrs-BwCnem2I.js} +1 -1
- package/src/assets/web-panel/assets/{placementArrow-DHbiLUps.js → placementArrow-B9PtZ5rq.js} +1 -1
- package/src/assets/web-panel/assets/{responsiveObserve-BC2DGkWP.js → responsiveObserve-CPB6iSzV.js} +1 -1
- package/src/assets/web-panel/assets/{slide-B4ga4pPY.js → slide-DZgyblZa.js} +1 -1
- package/src/assets/web-panel/assets/{statusUtils-hzphgKfH.js → statusUtils-D82IBdsx.js} +1 -1
- package/src/assets/web-panel/assets/{styleChecker-IfN9Bxoi.js → styleChecker-qSHtosM-.js} +1 -1
- package/src/assets/web-panel/assets/{useFlexGapSupport-pcGKJ4pT.js → useFlexGapSupport-CmWO7h0I.js} +1 -1
- package/src/assets/web-panel/assets/{useFs-COXhQpTG.js → useFs-yLrs_ub4.js} +1 -1
- package/src/assets/web-panel/assets/{usePersonalDataHub-xp9F9szv.js → usePersonalDataHub-CJ1VW6rh.js} +1 -1
- package/src/assets/web-panel/assets/{vnode-BdSQy1Ve.js → vnode-CzY_moQ4.js} +1 -1
- package/src/assets/web-panel/assets/{zoom-CHCt5P55.js → zoom-DAa7rEY5.js} +1 -1
- package/src/assets/web-panel/index.html +1 -1
- package/src/commands/learning.js +71 -1
- package/src/commands/team.js +5 -0
- package/src/data/changelog.json +15 -2
- package/src/lib/agent-team/task-lease.js +12 -1
- package/src/lib/capability-manifest.js +212 -1
- package/src/lib/evolution/evolution-artifact-ports.js +3277 -0
- package/src/lib/evolution/evolution-eval-gate.js +6442 -0
- package/src/lib/evolution/evolution-evidence-projector.js +3786 -0
- package/src/lib/evolution/evolution-ledger-ports.js +2689 -0
- package/src/lib/evolution/evolution-ledger.js +4280 -0
- package/src/lib/evolution/skill-candidate-registry.js +2258 -0
- package/src/lib/evolution/skill-execution-manifest.js +942 -0
- package/src/lib/evolution/skill-mutation-authority.js +1677 -0
- package/src/lib/evolution/skill-promotion-controller.js +506 -0
- package/src/lib/evolution/skill-release-registry.js +3277 -0
- package/src/lib/evolution/skill-target-matrix-eval.js +3233 -0
- package/src/lib/evolution/skill-writer-inventory-manifest.js +998 -0
- package/src/lib/evolution/skill-writer-inventory-validator.js +816 -0
- package/src/lib/formal-quality-eval-runtime.js +100 -0
- package/src/lib/graph-kernel/cutover-contract.js +7 -0
- package/src/lib/graph-kernel/cutover-ledger.js +8 -7
- package/src/lib/graph-kernel/evidence-digest.js +47 -0
- package/src/lib/graph-kernel/graph-runtime-surfaces.json +8 -1
- package/src/lib/graph-kernel/production-cutover-evidence.js +342 -15
- package/src/lib/graph-kernel/production-source-evidence.js +1599 -0
- package/src/lib/graph-kernel/retirement-evidence.js +15 -5
- package/src/lib/graph-kernel/runtime-surface-manifest.js +67 -2
- package/src/lib/headless-manifest.js +3 -1
- package/src/lib/learning/skill-improver.js +311 -43
- package/src/lib/learning/skill-synthesizer.js +236 -16
- package/src/lib/secure-fs.js +20 -0
- package/src/assets/web-panel/assets/Projects-DWhwdgfY.js +0 -1
- package/src/assets/web-panel/assets/devWarning-DIb8j04q.js +0 -1
- package/src/assets/web-panel/assets/index-BJc3t4PC.js +0 -1
- package/src/assets/web-panel/assets/index-CkksSUnI.js +0 -1
|
@@ -0,0 +1,942 @@
|
|
|
1
|
+
import { Buffer } from "node:buffer";
|
|
2
|
+
import { createHash } from "node:crypto";
|
|
3
|
+
import { types as utilTypes } from "node:util";
|
|
4
|
+
|
|
5
|
+
export const SKILL_DEPENDENCY_LOCK_SCHEMA =
|
|
6
|
+
"chainlesschain.skill-dependency-lock/v2";
|
|
7
|
+
export const SKILL_RUNTIME_MANIFEST_SCHEMA =
|
|
8
|
+
"chainlesschain.skill-runtime-manifest/v1";
|
|
9
|
+
export const SKILL_TARGET_MATRIX_SCHEMA =
|
|
10
|
+
"chainlesschain.skill-target-matrix/v1";
|
|
11
|
+
|
|
12
|
+
export const SKILL_EXECUTION_MANIFEST_INVALID_CODE =
|
|
13
|
+
"CC_SKILL_EXECUTION_MANIFEST_INVALID";
|
|
14
|
+
|
|
15
|
+
const LEGACY_DEPENDENCY_LOCK_DOMAIN = "chainlesschain.skill-dependency-lock/v1";
|
|
16
|
+
const LEGACY_MUTATION_REQUEST_INVALID_CODE =
|
|
17
|
+
"CC_SKILL_MUTATION_REQUEST_INVALID";
|
|
18
|
+
const DIGEST_PATTERN = /^sha256:[a-f0-9]{64}$/u;
|
|
19
|
+
const IDENTIFIER_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._:/-]{0,255}$/u;
|
|
20
|
+
const RUNTIME_ID_PATTERN = /^[a-z][a-z0-9]*(?:[._:-][a-z0-9]+)*$/u;
|
|
21
|
+
const MAX_CANONICAL_DEPTH = 20;
|
|
22
|
+
const MAX_CANONICAL_NODES = 4096;
|
|
23
|
+
const MAX_CANONICAL_BYTES = 1024 * 1024;
|
|
24
|
+
const MAX_ARRAY_ENTRIES = 2048;
|
|
25
|
+
const MAX_OBJECT_FIELDS = 2048;
|
|
26
|
+
const MAX_KEY_CHARS = 256;
|
|
27
|
+
const MAX_STRING_CHARS = 16_384;
|
|
28
|
+
const MAX_RUNTIME_ENTRIES = 64;
|
|
29
|
+
const MAX_TARGET_CELLS = 64;
|
|
30
|
+
|
|
31
|
+
const DEPENDENCY_LOCK_INPUT_KEYS = new Set(["lock", "tenantId"]);
|
|
32
|
+
const DEPENDENCY_LOCK_KEYS = new Set([
|
|
33
|
+
"schema",
|
|
34
|
+
"tenantId",
|
|
35
|
+
"lock",
|
|
36
|
+
"lockDigest",
|
|
37
|
+
"dependencyLockDigest",
|
|
38
|
+
]);
|
|
39
|
+
const RUNTIME_MANIFEST_INPUT_KEYS = new Set(["runtimes", "tenantId"]);
|
|
40
|
+
const RUNTIME_MANIFEST_KEYS = new Set([
|
|
41
|
+
"schema",
|
|
42
|
+
"tenantId",
|
|
43
|
+
"runtimes",
|
|
44
|
+
"runtimeManifestDigest",
|
|
45
|
+
]);
|
|
46
|
+
const RUNTIME_ENTRY_KEYS = new Set(["descriptor", "runtimeId"]);
|
|
47
|
+
const TARGET_MATRIX_INPUT_KEYS = new Set([
|
|
48
|
+
"cells",
|
|
49
|
+
"dependencyLock",
|
|
50
|
+
"runtimeManifest",
|
|
51
|
+
"tenantId",
|
|
52
|
+
]);
|
|
53
|
+
const TARGET_MATRIX_KEYS = new Set([
|
|
54
|
+
"schema",
|
|
55
|
+
"tenantId",
|
|
56
|
+
"dependencyLockDigest",
|
|
57
|
+
"runtimeManifestDigest",
|
|
58
|
+
"cells",
|
|
59
|
+
"targetRuntimes",
|
|
60
|
+
"targetMatrixRoot",
|
|
61
|
+
]);
|
|
62
|
+
const TARGET_MATRIX_VERIFY_CONTEXT_KEYS = new Set([
|
|
63
|
+
"dependencyLock",
|
|
64
|
+
"expectedEnvironmentBindings",
|
|
65
|
+
"expectedTargetMatrixRoot",
|
|
66
|
+
"runtimeManifest",
|
|
67
|
+
]);
|
|
68
|
+
const TARGET_CELL_KEYS = new Set([
|
|
69
|
+
"cellId",
|
|
70
|
+
"runtimeId",
|
|
71
|
+
"targetEnvironmentRef",
|
|
72
|
+
"environmentDigest",
|
|
73
|
+
]);
|
|
74
|
+
|
|
75
|
+
export class SkillExecutionManifestError extends Error {
|
|
76
|
+
constructor(code, message, details = {}) {
|
|
77
|
+
super(message, details.cause ? { cause: details.cause } : undefined);
|
|
78
|
+
this.name = "SkillExecutionManifestError";
|
|
79
|
+
this.code = code;
|
|
80
|
+
for (const [key, value] of Object.entries(details)) {
|
|
81
|
+
if (key !== "cause") this[key] = value;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
function manifestError(
|
|
87
|
+
message,
|
|
88
|
+
details = {},
|
|
89
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
90
|
+
) {
|
|
91
|
+
return new SkillExecutionManifestError(code, message, details);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
function rejectProxy(
|
|
95
|
+
value,
|
|
96
|
+
label,
|
|
97
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
98
|
+
) {
|
|
99
|
+
if (
|
|
100
|
+
value !== null &&
|
|
101
|
+
(typeof value === "object" || typeof value === "function") &&
|
|
102
|
+
utilTypes.isProxy(value)
|
|
103
|
+
) {
|
|
104
|
+
throw manifestError(`${label} must not be a Proxy`, {}, code);
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
function isPlainRecord(value) {
|
|
109
|
+
rejectProxy(value, "record");
|
|
110
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
const prototype = Object.getPrototypeOf(value);
|
|
114
|
+
return prototype === Object.prototype || prototype === null;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
function assertExactRecord(
|
|
118
|
+
value,
|
|
119
|
+
expectedKeys,
|
|
120
|
+
label,
|
|
121
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
122
|
+
) {
|
|
123
|
+
rejectProxy(value, label, code);
|
|
124
|
+
if (!value || typeof value !== "object" || Array.isArray(value)) {
|
|
125
|
+
throw manifestError(`${label} must be a plain object`, {}, code);
|
|
126
|
+
}
|
|
127
|
+
const prototype = Object.getPrototypeOf(value);
|
|
128
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
129
|
+
throw manifestError(`${label} must be a plain object`, {}, code);
|
|
130
|
+
}
|
|
131
|
+
const keys = Reflect.ownKeys(value);
|
|
132
|
+
if (
|
|
133
|
+
keys.length !== expectedKeys.size ||
|
|
134
|
+
keys.some((key) => typeof key !== "string" || !expectedKeys.has(key))
|
|
135
|
+
) {
|
|
136
|
+
throw manifestError(
|
|
137
|
+
`${label} must contain exactly the supported fields`,
|
|
138
|
+
{},
|
|
139
|
+
code,
|
|
140
|
+
);
|
|
141
|
+
}
|
|
142
|
+
for (const key of keys) {
|
|
143
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
144
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
145
|
+
throw manifestError(
|
|
146
|
+
`${label}.${String(key)} must be an enumerable own data property`,
|
|
147
|
+
{},
|
|
148
|
+
code,
|
|
149
|
+
);
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function ownData(value, key, label) {
|
|
155
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
156
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
157
|
+
throw manifestError(
|
|
158
|
+
`${label}.${key} must be an enumerable own data property`,
|
|
159
|
+
);
|
|
160
|
+
}
|
|
161
|
+
return descriptor.value;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
function addCanonicalBytes(
|
|
165
|
+
state,
|
|
166
|
+
fragment,
|
|
167
|
+
label,
|
|
168
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
169
|
+
) {
|
|
170
|
+
const byteLength = Buffer.byteLength(fragment, "utf8");
|
|
171
|
+
if (state.bytes > MAX_CANONICAL_BYTES - byteLength) {
|
|
172
|
+
throw manifestError(`${label} exceeds the canonical byte budget`, {}, code);
|
|
173
|
+
}
|
|
174
|
+
state.bytes += byteLength;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function updateCanonicalHash(hash, value, state, label, code) {
|
|
178
|
+
const update = (fragment) => {
|
|
179
|
+
addCanonicalBytes(state, fragment, label, code);
|
|
180
|
+
hash.update(fragment, "utf8");
|
|
181
|
+
};
|
|
182
|
+
if (value === null || typeof value !== "object") {
|
|
183
|
+
const serialized = JSON.stringify(value);
|
|
184
|
+
if (typeof serialized !== "string") {
|
|
185
|
+
throw manifestError(`${label} must be canonical JSON`, {}, code);
|
|
186
|
+
}
|
|
187
|
+
update(serialized);
|
|
188
|
+
return;
|
|
189
|
+
}
|
|
190
|
+
rejectProxy(value, label, code);
|
|
191
|
+
if (Array.isArray(value)) {
|
|
192
|
+
if (Object.getPrototypeOf(value) !== Array.prototype) {
|
|
193
|
+
throw manifestError(`${label} must use a standard array`, {}, code);
|
|
194
|
+
}
|
|
195
|
+
update("[");
|
|
196
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
197
|
+
if (index > 0) update(",");
|
|
198
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
199
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
200
|
+
throw manifestError(
|
|
201
|
+
`${label}[${index}] must be an enumerable own data property`,
|
|
202
|
+
{},
|
|
203
|
+
code,
|
|
204
|
+
);
|
|
205
|
+
}
|
|
206
|
+
updateCanonicalHash(hash, descriptor.value, state, label, code);
|
|
207
|
+
}
|
|
208
|
+
update("]");
|
|
209
|
+
return;
|
|
210
|
+
}
|
|
211
|
+
const prototype = Object.getPrototypeOf(value);
|
|
212
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
213
|
+
throw manifestError(`${label} must use plain objects`, {}, code);
|
|
214
|
+
}
|
|
215
|
+
const keys = Reflect.ownKeys(value);
|
|
216
|
+
if (keys.some((key) => typeof key !== "string")) {
|
|
217
|
+
throw manifestError(`${label} has unsafe keys`, {}, code);
|
|
218
|
+
}
|
|
219
|
+
keys.sort();
|
|
220
|
+
update("{");
|
|
221
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
222
|
+
if (index > 0) update(",");
|
|
223
|
+
const key = keys[index];
|
|
224
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
225
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
226
|
+
throw manifestError(
|
|
227
|
+
`${label}.${key} must be an enumerable own data property`,
|
|
228
|
+
{},
|
|
229
|
+
code,
|
|
230
|
+
);
|
|
231
|
+
}
|
|
232
|
+
update(JSON.stringify(key));
|
|
233
|
+
update(":");
|
|
234
|
+
updateCanonicalHash(hash, descriptor.value, state, label, code);
|
|
235
|
+
}
|
|
236
|
+
update("}");
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
function domainDigest(
|
|
240
|
+
domain,
|
|
241
|
+
value,
|
|
242
|
+
label,
|
|
243
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
244
|
+
) {
|
|
245
|
+
const hash = createHash("sha256").update(domain, "utf8").update("\0", "utf8");
|
|
246
|
+
updateCanonicalHash(hash, value, { bytes: 0 }, label, code);
|
|
247
|
+
return `sha256:${hash.digest("hex")}`;
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
function deepFreeze(value, seen = new WeakSet()) {
|
|
251
|
+
if (!value || typeof value !== "object" || seen.has(value)) return value;
|
|
252
|
+
seen.add(value);
|
|
253
|
+
for (const key of Reflect.ownKeys(value)) {
|
|
254
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
255
|
+
if (descriptor && "value" in descriptor) deepFreeze(descriptor.value, seen);
|
|
256
|
+
}
|
|
257
|
+
return Object.freeze(value);
|
|
258
|
+
}
|
|
259
|
+
|
|
260
|
+
function normalizeBoundedString(
|
|
261
|
+
value,
|
|
262
|
+
label,
|
|
263
|
+
maximum = MAX_STRING_CHARS,
|
|
264
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
265
|
+
) {
|
|
266
|
+
if (
|
|
267
|
+
typeof value !== "string" ||
|
|
268
|
+
value.length < 1 ||
|
|
269
|
+
value.length > maximum ||
|
|
270
|
+
value.trim() !== value ||
|
|
271
|
+
[...value].some((character) => {
|
|
272
|
+
const point = character.codePointAt(0);
|
|
273
|
+
return point < 0x20 || point === 0x7f;
|
|
274
|
+
})
|
|
275
|
+
) {
|
|
276
|
+
throw manifestError(
|
|
277
|
+
`${label} must be a non-empty bounded string without control characters`,
|
|
278
|
+
{},
|
|
279
|
+
code,
|
|
280
|
+
);
|
|
281
|
+
}
|
|
282
|
+
return value;
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
function normalizeIdentifier(value, label) {
|
|
286
|
+
const normalized = normalizeBoundedString(value, label, 256);
|
|
287
|
+
if (!IDENTIFIER_PATTERN.test(normalized)) {
|
|
288
|
+
throw manifestError(`${label} must be a canonical identifier`);
|
|
289
|
+
}
|
|
290
|
+
return normalized;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
function normalizeRuntimeId(value, label) {
|
|
294
|
+
const normalized = normalizeBoundedString(value, label, 128);
|
|
295
|
+
if (!RUNTIME_ID_PATTERN.test(normalized)) {
|
|
296
|
+
throw manifestError(`${label} must be a lowercase namespaced identifier`);
|
|
297
|
+
}
|
|
298
|
+
return normalized;
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
function normalizeDigest(value, label) {
|
|
302
|
+
if (typeof value !== "string" || !DIGEST_PATTERN.test(value)) {
|
|
303
|
+
throw manifestError(`${label} must be a lowercase SHA-256 digest`);
|
|
304
|
+
}
|
|
305
|
+
return value;
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
function normalizeCanonicalJson(
|
|
309
|
+
value,
|
|
310
|
+
label,
|
|
311
|
+
depth = 0,
|
|
312
|
+
state = { nodes: 0, bytes: 0, ancestors: new WeakSet() },
|
|
313
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
314
|
+
) {
|
|
315
|
+
rejectProxy(value, label, code);
|
|
316
|
+
state.nodes += 1;
|
|
317
|
+
if (depth > MAX_CANONICAL_DEPTH || state.nodes > MAX_CANONICAL_NODES) {
|
|
318
|
+
throw manifestError(
|
|
319
|
+
`${label} exceeds the canonical JSON structure budget`,
|
|
320
|
+
{},
|
|
321
|
+
code,
|
|
322
|
+
);
|
|
323
|
+
}
|
|
324
|
+
if (value === null || typeof value === "boolean") {
|
|
325
|
+
addCanonicalBytes(state, JSON.stringify(value), label, code);
|
|
326
|
+
return value;
|
|
327
|
+
}
|
|
328
|
+
if (typeof value === "number") {
|
|
329
|
+
if (!Number.isSafeInteger(value) || value < 0 || Object.is(value, -0)) {
|
|
330
|
+
throw manifestError(
|
|
331
|
+
`${label} numbers must be non-negative safe integers`,
|
|
332
|
+
{},
|
|
333
|
+
code,
|
|
334
|
+
);
|
|
335
|
+
}
|
|
336
|
+
addCanonicalBytes(state, JSON.stringify(value), label, code);
|
|
337
|
+
return value;
|
|
338
|
+
}
|
|
339
|
+
if (typeof value === "string") {
|
|
340
|
+
const normalized = normalizeBoundedString(
|
|
341
|
+
value,
|
|
342
|
+
label,
|
|
343
|
+
MAX_STRING_CHARS,
|
|
344
|
+
code,
|
|
345
|
+
);
|
|
346
|
+
addCanonicalBytes(state, JSON.stringify(normalized), label, code);
|
|
347
|
+
return normalized;
|
|
348
|
+
}
|
|
349
|
+
if (!value || typeof value !== "object") {
|
|
350
|
+
throw manifestError(`${label} must be canonical JSON`, {}, code);
|
|
351
|
+
}
|
|
352
|
+
if (state.ancestors.has(value)) {
|
|
353
|
+
throw manifestError(
|
|
354
|
+
code === LEGACY_MUTATION_REQUEST_INVALID_CODE
|
|
355
|
+
? `${label} exceeds the canonical JSON structure budget`
|
|
356
|
+
: `${label} must not contain cycles`,
|
|
357
|
+
{},
|
|
358
|
+
code,
|
|
359
|
+
);
|
|
360
|
+
}
|
|
361
|
+
state.ancestors.add(value);
|
|
362
|
+
try {
|
|
363
|
+
if (Array.isArray(value)) {
|
|
364
|
+
if (Object.getPrototypeOf(value) !== Array.prototype) {
|
|
365
|
+
throw manifestError(`${label} must use a standard array`, {}, code);
|
|
366
|
+
}
|
|
367
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
368
|
+
if (
|
|
369
|
+
value.length > MAX_ARRAY_ENTRIES ||
|
|
370
|
+
ownKeys.length !== value.length + 1 ||
|
|
371
|
+
ownKeys.some(
|
|
372
|
+
(key) =>
|
|
373
|
+
typeof key !== "string" ||
|
|
374
|
+
(key !== "length" && !/^(?:0|[1-9]\d*)$/u.test(key)),
|
|
375
|
+
)
|
|
376
|
+
) {
|
|
377
|
+
throw manifestError(
|
|
378
|
+
code === LEGACY_MUTATION_REQUEST_INVALID_CODE
|
|
379
|
+
? `${label} must be a dense bounded array`
|
|
380
|
+
: `${label} must be a dense bounded standard array`,
|
|
381
|
+
{},
|
|
382
|
+
code,
|
|
383
|
+
);
|
|
384
|
+
}
|
|
385
|
+
addCanonicalBytes(state, "[", label, code);
|
|
386
|
+
const output = [];
|
|
387
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
388
|
+
if (index > 0) addCanonicalBytes(state, ",", label, code);
|
|
389
|
+
const descriptor = Object.getOwnPropertyDescriptor(
|
|
390
|
+
value,
|
|
391
|
+
String(index),
|
|
392
|
+
);
|
|
393
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
394
|
+
throw manifestError(
|
|
395
|
+
`${label}[${index}] must be an enumerable own data property`,
|
|
396
|
+
{},
|
|
397
|
+
code,
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
const normalizedEntry = normalizeCanonicalJson(
|
|
401
|
+
descriptor.value,
|
|
402
|
+
`${label}[${index}]`,
|
|
403
|
+
depth + 1,
|
|
404
|
+
state,
|
|
405
|
+
code,
|
|
406
|
+
);
|
|
407
|
+
Object.defineProperty(output, String(index), {
|
|
408
|
+
value: normalizedEntry,
|
|
409
|
+
enumerable: true,
|
|
410
|
+
configurable: false,
|
|
411
|
+
writable: false,
|
|
412
|
+
});
|
|
413
|
+
}
|
|
414
|
+
addCanonicalBytes(state, "]", label, code);
|
|
415
|
+
return output;
|
|
416
|
+
}
|
|
417
|
+
const prototype = Object.getPrototypeOf(value);
|
|
418
|
+
if (prototype !== Object.prototype && prototype !== null) {
|
|
419
|
+
throw manifestError(`${label} must use plain objects`, {}, code);
|
|
420
|
+
}
|
|
421
|
+
const keys = Reflect.ownKeys(value);
|
|
422
|
+
if (
|
|
423
|
+
keys.length > MAX_OBJECT_FIELDS ||
|
|
424
|
+
keys.some(
|
|
425
|
+
(key) =>
|
|
426
|
+
typeof key !== "string" ||
|
|
427
|
+
key.length < 1 ||
|
|
428
|
+
key.length > MAX_KEY_CHARS,
|
|
429
|
+
)
|
|
430
|
+
) {
|
|
431
|
+
throw manifestError(`${label} has unsafe keys`, {}, code);
|
|
432
|
+
}
|
|
433
|
+
const output = Object.create(null);
|
|
434
|
+
keys.sort();
|
|
435
|
+
addCanonicalBytes(state, "{", label, code);
|
|
436
|
+
for (let index = 0; index < keys.length; index += 1) {
|
|
437
|
+
if (index > 0) addCanonicalBytes(state, ",", label, code);
|
|
438
|
+
const key = keys[index];
|
|
439
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, key);
|
|
440
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
441
|
+
throw manifestError(
|
|
442
|
+
`${label}.${key} must be an enumerable own data property`,
|
|
443
|
+
{},
|
|
444
|
+
code,
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
addCanonicalBytes(state, JSON.stringify(key), label, code);
|
|
448
|
+
addCanonicalBytes(state, ":", label, code);
|
|
449
|
+
Object.defineProperty(output, key, {
|
|
450
|
+
value: normalizeCanonicalJson(
|
|
451
|
+
descriptor.value,
|
|
452
|
+
`${label}.${key}`,
|
|
453
|
+
depth + 1,
|
|
454
|
+
state,
|
|
455
|
+
code,
|
|
456
|
+
),
|
|
457
|
+
enumerable: true,
|
|
458
|
+
configurable: false,
|
|
459
|
+
writable: false,
|
|
460
|
+
});
|
|
461
|
+
}
|
|
462
|
+
addCanonicalBytes(state, "}", label, code);
|
|
463
|
+
return output;
|
|
464
|
+
} finally {
|
|
465
|
+
state.ancestors.delete(value);
|
|
466
|
+
}
|
|
467
|
+
}
|
|
468
|
+
|
|
469
|
+
function normalizeCanonicalObject(
|
|
470
|
+
value,
|
|
471
|
+
label,
|
|
472
|
+
code = SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
473
|
+
state = { nodes: 0, bytes: 0, ancestors: new WeakSet() },
|
|
474
|
+
) {
|
|
475
|
+
const normalized = normalizeCanonicalJson(value, label, 0, state, code);
|
|
476
|
+
if (!isPlainRecord(normalized)) {
|
|
477
|
+
throw manifestError(`${label} must be an object`, {}, code);
|
|
478
|
+
}
|
|
479
|
+
return normalized;
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
/**
|
|
483
|
+
* Legacy v1 dependency-lock digest retained for the current mutation schemas.
|
|
484
|
+
* New tenant-scoped flows must use buildSkillDependencyLock instead.
|
|
485
|
+
*/
|
|
486
|
+
export function digestSkillMutationDependencyLock(value) {
|
|
487
|
+
const normalized = normalizeCanonicalObject(
|
|
488
|
+
value,
|
|
489
|
+
"dependencyLock",
|
|
490
|
+
LEGACY_MUTATION_REQUEST_INVALID_CODE,
|
|
491
|
+
);
|
|
492
|
+
return domainDigest(
|
|
493
|
+
LEGACY_DEPENDENCY_LOCK_DOMAIN,
|
|
494
|
+
normalized,
|
|
495
|
+
"dependencyLock",
|
|
496
|
+
LEGACY_MUTATION_REQUEST_INVALID_CODE,
|
|
497
|
+
);
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
export function buildSkillDependencyLock(input) {
|
|
501
|
+
assertExactRecord(input, DEPENDENCY_LOCK_INPUT_KEYS, "dependency lock input");
|
|
502
|
+
const tenantId = normalizeIdentifier(
|
|
503
|
+
ownData(input, "tenantId", "dependency lock input"),
|
|
504
|
+
"dependency lock tenantId",
|
|
505
|
+
);
|
|
506
|
+
const lock = normalizeCanonicalObject(
|
|
507
|
+
ownData(input, "lock", "dependency lock input"),
|
|
508
|
+
"dependency lock value",
|
|
509
|
+
);
|
|
510
|
+
const core = {
|
|
511
|
+
schema: SKILL_DEPENDENCY_LOCK_SCHEMA,
|
|
512
|
+
tenantId,
|
|
513
|
+
lock,
|
|
514
|
+
lockDigest: digestSkillMutationDependencyLock(lock),
|
|
515
|
+
};
|
|
516
|
+
const dependencyLockDigest = domainDigest(
|
|
517
|
+
SKILL_DEPENDENCY_LOCK_SCHEMA,
|
|
518
|
+
core,
|
|
519
|
+
"tenant-bound dependency lock",
|
|
520
|
+
);
|
|
521
|
+
return deepFreeze({ ...core, dependencyLockDigest });
|
|
522
|
+
}
|
|
523
|
+
|
|
524
|
+
export function verifySkillDependencyLock(value) {
|
|
525
|
+
assertExactRecord(value, DEPENDENCY_LOCK_KEYS, "dependency lock");
|
|
526
|
+
if (
|
|
527
|
+
ownData(value, "schema", "dependency lock") !== SKILL_DEPENDENCY_LOCK_SCHEMA
|
|
528
|
+
) {
|
|
529
|
+
throw manifestError("dependency lock schema is invalid");
|
|
530
|
+
}
|
|
531
|
+
const normalized = buildSkillDependencyLock({
|
|
532
|
+
tenantId: ownData(value, "tenantId", "dependency lock"),
|
|
533
|
+
lock: ownData(value, "lock", "dependency lock"),
|
|
534
|
+
});
|
|
535
|
+
if (
|
|
536
|
+
ownData(value, "lockDigest", "dependency lock") !== normalized.lockDigest ||
|
|
537
|
+
ownData(value, "dependencyLockDigest", "dependency lock") !==
|
|
538
|
+
normalized.dependencyLockDigest
|
|
539
|
+
) {
|
|
540
|
+
throw manifestError("dependency lock digest verification failed");
|
|
541
|
+
}
|
|
542
|
+
return normalized;
|
|
543
|
+
}
|
|
544
|
+
|
|
545
|
+
export function digestSkillDependencyLock(input) {
|
|
546
|
+
return buildSkillDependencyLock(input).dependencyLockDigest;
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
function normalizeRuntimeEntries(value) {
|
|
550
|
+
rejectProxy(value, "runtime manifest runtimes");
|
|
551
|
+
if (
|
|
552
|
+
!Array.isArray(value) ||
|
|
553
|
+
Object.getPrototypeOf(value) !== Array.prototype
|
|
554
|
+
) {
|
|
555
|
+
throw manifestError("runtime manifest runtimes must be a standard array");
|
|
556
|
+
}
|
|
557
|
+
if (value.length < 1 || value.length > MAX_RUNTIME_ENTRIES) {
|
|
558
|
+
throw manifestError(
|
|
559
|
+
`runtime manifest must contain from 1 to ${MAX_RUNTIME_ENTRIES} runtimes`,
|
|
560
|
+
);
|
|
561
|
+
}
|
|
562
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
563
|
+
if (
|
|
564
|
+
ownKeys.length !== value.length + 1 ||
|
|
565
|
+
ownKeys.some(
|
|
566
|
+
(key) =>
|
|
567
|
+
typeof key !== "string" ||
|
|
568
|
+
(key !== "length" && !/^(?:0|[1-9]\d*)$/u.test(key)),
|
|
569
|
+
)
|
|
570
|
+
) {
|
|
571
|
+
throw manifestError("runtime manifest runtimes must be dense");
|
|
572
|
+
}
|
|
573
|
+
const entries = [];
|
|
574
|
+
const descriptorBudget = {
|
|
575
|
+
nodes: 0,
|
|
576
|
+
bytes: 0,
|
|
577
|
+
ancestors: new WeakSet(),
|
|
578
|
+
};
|
|
579
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
580
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
581
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
582
|
+
throw manifestError(
|
|
583
|
+
`runtime manifest runtimes[${index}] must be an enumerable own data property`,
|
|
584
|
+
);
|
|
585
|
+
}
|
|
586
|
+
const entry = descriptor.value;
|
|
587
|
+
assertExactRecord(
|
|
588
|
+
entry,
|
|
589
|
+
RUNTIME_ENTRY_KEYS,
|
|
590
|
+
`runtime manifest runtimes[${index}]`,
|
|
591
|
+
);
|
|
592
|
+
entries.push({
|
|
593
|
+
runtimeId: normalizeRuntimeId(
|
|
594
|
+
ownData(entry, "runtimeId", `runtime manifest runtimes[${index}]`),
|
|
595
|
+
`runtime manifest runtimes[${index}].runtimeId`,
|
|
596
|
+
),
|
|
597
|
+
descriptor: normalizeCanonicalObject(
|
|
598
|
+
ownData(entry, "descriptor", `runtime manifest runtimes[${index}]`),
|
|
599
|
+
`runtime manifest runtimes[${index}].descriptor`,
|
|
600
|
+
SKILL_EXECUTION_MANIFEST_INVALID_CODE,
|
|
601
|
+
descriptorBudget,
|
|
602
|
+
),
|
|
603
|
+
});
|
|
604
|
+
}
|
|
605
|
+
if (
|
|
606
|
+
new Set(entries.map((entry) => entry.runtimeId)).size !== entries.length
|
|
607
|
+
) {
|
|
608
|
+
throw manifestError("runtime manifest runtimeId values must be unique");
|
|
609
|
+
}
|
|
610
|
+
entries.sort((left, right) =>
|
|
611
|
+
left.runtimeId < right.runtimeId
|
|
612
|
+
? -1
|
|
613
|
+
: left.runtimeId > right.runtimeId
|
|
614
|
+
? 1
|
|
615
|
+
: 0,
|
|
616
|
+
);
|
|
617
|
+
return entries;
|
|
618
|
+
}
|
|
619
|
+
|
|
620
|
+
export function buildSkillRuntimeManifest(input) {
|
|
621
|
+
assertExactRecord(
|
|
622
|
+
input,
|
|
623
|
+
RUNTIME_MANIFEST_INPUT_KEYS,
|
|
624
|
+
"runtime manifest input",
|
|
625
|
+
);
|
|
626
|
+
const core = {
|
|
627
|
+
schema: SKILL_RUNTIME_MANIFEST_SCHEMA,
|
|
628
|
+
tenantId: normalizeIdentifier(
|
|
629
|
+
ownData(input, "tenantId", "runtime manifest input"),
|
|
630
|
+
"runtime manifest tenantId",
|
|
631
|
+
),
|
|
632
|
+
runtimes: normalizeRuntimeEntries(
|
|
633
|
+
ownData(input, "runtimes", "runtime manifest input"),
|
|
634
|
+
),
|
|
635
|
+
};
|
|
636
|
+
const runtimeManifestDigest = domainDigest(
|
|
637
|
+
SKILL_RUNTIME_MANIFEST_SCHEMA,
|
|
638
|
+
core,
|
|
639
|
+
"runtime manifest",
|
|
640
|
+
);
|
|
641
|
+
return deepFreeze({ ...core, runtimeManifestDigest });
|
|
642
|
+
}
|
|
643
|
+
|
|
644
|
+
export function verifySkillRuntimeManifest(value) {
|
|
645
|
+
assertExactRecord(value, RUNTIME_MANIFEST_KEYS, "runtime manifest");
|
|
646
|
+
if (
|
|
647
|
+
ownData(value, "schema", "runtime manifest") !==
|
|
648
|
+
SKILL_RUNTIME_MANIFEST_SCHEMA
|
|
649
|
+
) {
|
|
650
|
+
throw manifestError("runtime manifest schema is invalid");
|
|
651
|
+
}
|
|
652
|
+
const normalized = buildSkillRuntimeManifest({
|
|
653
|
+
tenantId: ownData(value, "tenantId", "runtime manifest"),
|
|
654
|
+
runtimes: ownData(value, "runtimes", "runtime manifest"),
|
|
655
|
+
});
|
|
656
|
+
if (
|
|
657
|
+
ownData(value, "runtimeManifestDigest", "runtime manifest") !==
|
|
658
|
+
normalized.runtimeManifestDigest
|
|
659
|
+
) {
|
|
660
|
+
throw manifestError("runtime manifest digest verification failed");
|
|
661
|
+
}
|
|
662
|
+
return normalized;
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
export function digestSkillRuntimeManifest(input) {
|
|
666
|
+
return buildSkillRuntimeManifest(input).runtimeManifestDigest;
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
function normalizeTargetCells(
|
|
670
|
+
value,
|
|
671
|
+
runtimeIds,
|
|
672
|
+
label = "target matrix cells",
|
|
673
|
+
) {
|
|
674
|
+
rejectProxy(value, label);
|
|
675
|
+
if (
|
|
676
|
+
!Array.isArray(value) ||
|
|
677
|
+
Object.getPrototypeOf(value) !== Array.prototype
|
|
678
|
+
) {
|
|
679
|
+
throw manifestError(`${label} must be a standard array`);
|
|
680
|
+
}
|
|
681
|
+
if (value.length < 1 || value.length > MAX_TARGET_CELLS) {
|
|
682
|
+
throw manifestError(
|
|
683
|
+
`${label} must contain from 1 to ${MAX_TARGET_CELLS} cells`,
|
|
684
|
+
);
|
|
685
|
+
}
|
|
686
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
687
|
+
if (
|
|
688
|
+
ownKeys.length !== value.length + 1 ||
|
|
689
|
+
ownKeys.some(
|
|
690
|
+
(key) =>
|
|
691
|
+
typeof key !== "string" ||
|
|
692
|
+
(key !== "length" && !/^(?:0|[1-9]\d*)$/u.test(key)),
|
|
693
|
+
)
|
|
694
|
+
) {
|
|
695
|
+
throw manifestError(`${label} must be dense`);
|
|
696
|
+
}
|
|
697
|
+
const cells = [];
|
|
698
|
+
const cellIds = new Set();
|
|
699
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
700
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
701
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
702
|
+
throw manifestError(
|
|
703
|
+
`${label}[${index}] must be an enumerable own data property`,
|
|
704
|
+
);
|
|
705
|
+
}
|
|
706
|
+
const cell = descriptor.value;
|
|
707
|
+
assertExactRecord(cell, TARGET_CELL_KEYS, `${label}[${index}]`);
|
|
708
|
+
const normalized = {
|
|
709
|
+
cellId: normalizeRuntimeId(
|
|
710
|
+
ownData(cell, "cellId", `${label}[${index}]`),
|
|
711
|
+
`${label}[${index}].cellId`,
|
|
712
|
+
),
|
|
713
|
+
runtimeId: normalizeRuntimeId(
|
|
714
|
+
ownData(cell, "runtimeId", `${label}[${index}]`),
|
|
715
|
+
`${label}[${index}].runtimeId`,
|
|
716
|
+
),
|
|
717
|
+
targetEnvironmentRef: normalizeIdentifier(
|
|
718
|
+
ownData(cell, "targetEnvironmentRef", `${label}[${index}]`),
|
|
719
|
+
`${label}[${index}].targetEnvironmentRef`,
|
|
720
|
+
),
|
|
721
|
+
environmentDigest: normalizeDigest(
|
|
722
|
+
ownData(cell, "environmentDigest", `${label}[${index}]`),
|
|
723
|
+
`${label}[${index}].environmentDigest`,
|
|
724
|
+
),
|
|
725
|
+
};
|
|
726
|
+
if (!runtimeIds.has(normalized.runtimeId)) {
|
|
727
|
+
throw manifestError(
|
|
728
|
+
`${label} runtime is absent from the runtime manifest: ${normalized.runtimeId}`,
|
|
729
|
+
);
|
|
730
|
+
}
|
|
731
|
+
if (cellIds.has(normalized.cellId)) {
|
|
732
|
+
throw manifestError(`${label} cellId values must be unique`);
|
|
733
|
+
}
|
|
734
|
+
cellIds.add(normalized.cellId);
|
|
735
|
+
cells.push(normalized);
|
|
736
|
+
}
|
|
737
|
+
cells.sort((left, right) =>
|
|
738
|
+
left.cellId < right.cellId ? -1 : left.cellId > right.cellId ? 1 : 0,
|
|
739
|
+
);
|
|
740
|
+
return cells;
|
|
741
|
+
}
|
|
742
|
+
|
|
743
|
+
function deriveTargetRuntimes(cells) {
|
|
744
|
+
const runtimeIds = new Set();
|
|
745
|
+
for (const cell of cells) runtimeIds.add(cell.runtimeId);
|
|
746
|
+
const targetRuntimes = [...runtimeIds];
|
|
747
|
+
targetRuntimes.sort((left, right) =>
|
|
748
|
+
left < right ? -1 : left > right ? 1 : 0,
|
|
749
|
+
);
|
|
750
|
+
return targetRuntimes;
|
|
751
|
+
}
|
|
752
|
+
|
|
753
|
+
function equalStringArrays(left, right) {
|
|
754
|
+
if (left.length !== right.length) return false;
|
|
755
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
756
|
+
if (left[index] !== right[index]) return false;
|
|
757
|
+
}
|
|
758
|
+
return true;
|
|
759
|
+
}
|
|
760
|
+
|
|
761
|
+
function equalTargetCells(left, right) {
|
|
762
|
+
if (left.length !== right.length) return false;
|
|
763
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
764
|
+
for (const key of TARGET_CELL_KEYS) {
|
|
765
|
+
if (left[index][key] !== right[index][key]) return false;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
return true;
|
|
769
|
+
}
|
|
770
|
+
|
|
771
|
+
function normalizeTargetRuntimes(value) {
|
|
772
|
+
rejectProxy(value, "target matrix targetRuntimes");
|
|
773
|
+
if (
|
|
774
|
+
!Array.isArray(value) ||
|
|
775
|
+
Object.getPrototypeOf(value) !== Array.prototype
|
|
776
|
+
) {
|
|
777
|
+
throw manifestError(
|
|
778
|
+
"target matrix targetRuntimes must be a standard array",
|
|
779
|
+
);
|
|
780
|
+
}
|
|
781
|
+
if (value.length < 1 || value.length > MAX_TARGET_CELLS) {
|
|
782
|
+
throw manifestError(
|
|
783
|
+
`target matrix targetRuntimes must contain from 1 to ${MAX_TARGET_CELLS} entries`,
|
|
784
|
+
);
|
|
785
|
+
}
|
|
786
|
+
const ownKeys = Reflect.ownKeys(value);
|
|
787
|
+
if (
|
|
788
|
+
ownKeys.length !== value.length + 1 ||
|
|
789
|
+
ownKeys.some(
|
|
790
|
+
(key) =>
|
|
791
|
+
typeof key !== "string" ||
|
|
792
|
+
(key !== "length" && !/^(?:0|[1-9]\d*)$/u.test(key)),
|
|
793
|
+
)
|
|
794
|
+
) {
|
|
795
|
+
throw manifestError("target matrix targetRuntimes must be dense");
|
|
796
|
+
}
|
|
797
|
+
const runtimes = [];
|
|
798
|
+
for (let index = 0; index < value.length; index += 1) {
|
|
799
|
+
const descriptor = Object.getOwnPropertyDescriptor(value, String(index));
|
|
800
|
+
if (!descriptor || !("value" in descriptor) || !descriptor.enumerable) {
|
|
801
|
+
throw manifestError(
|
|
802
|
+
`target matrix targetRuntimes[${index}] must be an enumerable own data property`,
|
|
803
|
+
);
|
|
804
|
+
}
|
|
805
|
+
runtimes.push(
|
|
806
|
+
normalizeRuntimeId(
|
|
807
|
+
descriptor.value,
|
|
808
|
+
`target matrix targetRuntimes[${index}]`,
|
|
809
|
+
),
|
|
810
|
+
);
|
|
811
|
+
}
|
|
812
|
+
if (new Set(runtimes).size !== runtimes.length) {
|
|
813
|
+
throw manifestError("target matrix targetRuntimes must be unique");
|
|
814
|
+
}
|
|
815
|
+
return runtimes;
|
|
816
|
+
}
|
|
817
|
+
|
|
818
|
+
export function buildSkillTargetMatrix(input) {
|
|
819
|
+
assertExactRecord(input, TARGET_MATRIX_INPUT_KEYS, "target matrix input");
|
|
820
|
+
const tenantId = normalizeIdentifier(
|
|
821
|
+
ownData(input, "tenantId", "target matrix input"),
|
|
822
|
+
"target matrix tenantId",
|
|
823
|
+
);
|
|
824
|
+
const dependencyLock = verifySkillDependencyLock(
|
|
825
|
+
ownData(input, "dependencyLock", "target matrix input"),
|
|
826
|
+
);
|
|
827
|
+
const runtimeManifest = verifySkillRuntimeManifest(
|
|
828
|
+
ownData(input, "runtimeManifest", "target matrix input"),
|
|
829
|
+
);
|
|
830
|
+
if (
|
|
831
|
+
dependencyLock.tenantId !== tenantId ||
|
|
832
|
+
runtimeManifest.tenantId !== tenantId
|
|
833
|
+
) {
|
|
834
|
+
throw manifestError(
|
|
835
|
+
"target matrix, dependency lock, and runtime manifest must belong to the same tenant",
|
|
836
|
+
);
|
|
837
|
+
}
|
|
838
|
+
const runtimeIds = new Set();
|
|
839
|
+
for (const entry of runtimeManifest.runtimes) {
|
|
840
|
+
runtimeIds.add(entry.runtimeId);
|
|
841
|
+
}
|
|
842
|
+
const cells = normalizeTargetCells(
|
|
843
|
+
ownData(input, "cells", "target matrix input"),
|
|
844
|
+
runtimeIds,
|
|
845
|
+
);
|
|
846
|
+
const core = {
|
|
847
|
+
schema: SKILL_TARGET_MATRIX_SCHEMA,
|
|
848
|
+
tenantId,
|
|
849
|
+
dependencyLockDigest: dependencyLock.dependencyLockDigest,
|
|
850
|
+
runtimeManifestDigest: runtimeManifest.runtimeManifestDigest,
|
|
851
|
+
cells,
|
|
852
|
+
targetRuntimes: deriveTargetRuntimes(cells),
|
|
853
|
+
};
|
|
854
|
+
const targetMatrixRoot = domainDigest(
|
|
855
|
+
SKILL_TARGET_MATRIX_SCHEMA,
|
|
856
|
+
core,
|
|
857
|
+
"target matrix",
|
|
858
|
+
);
|
|
859
|
+
return deepFreeze({ ...core, targetMatrixRoot });
|
|
860
|
+
}
|
|
861
|
+
|
|
862
|
+
export function verifySkillTargetMatrix(value, context) {
|
|
863
|
+
assertExactRecord(value, TARGET_MATRIX_KEYS, "target matrix");
|
|
864
|
+
assertExactRecord(
|
|
865
|
+
context,
|
|
866
|
+
TARGET_MATRIX_VERIFY_CONTEXT_KEYS,
|
|
867
|
+
"target matrix verification context",
|
|
868
|
+
);
|
|
869
|
+
if (
|
|
870
|
+
ownData(value, "schema", "target matrix") !== SKILL_TARGET_MATRIX_SCHEMA
|
|
871
|
+
) {
|
|
872
|
+
throw manifestError("target matrix schema is invalid");
|
|
873
|
+
}
|
|
874
|
+
const runtimeManifest = verifySkillRuntimeManifest(
|
|
875
|
+
ownData(context, "runtimeManifest", "target matrix verification context"),
|
|
876
|
+
);
|
|
877
|
+
const dependencyLock = verifySkillDependencyLock(
|
|
878
|
+
ownData(context, "dependencyLock", "target matrix verification context"),
|
|
879
|
+
);
|
|
880
|
+
const expectedTargetMatrixRoot = normalizeDigest(
|
|
881
|
+
ownData(
|
|
882
|
+
context,
|
|
883
|
+
"expectedTargetMatrixRoot",
|
|
884
|
+
"target matrix verification context",
|
|
885
|
+
),
|
|
886
|
+
"target matrix verification context.expectedTargetMatrixRoot",
|
|
887
|
+
);
|
|
888
|
+
const runtimeIds = new Set();
|
|
889
|
+
for (const entry of runtimeManifest.runtimes) {
|
|
890
|
+
runtimeIds.add(entry.runtimeId);
|
|
891
|
+
}
|
|
892
|
+
const expectedEnvironmentBindings = normalizeTargetCells(
|
|
893
|
+
ownData(
|
|
894
|
+
context,
|
|
895
|
+
"expectedEnvironmentBindings",
|
|
896
|
+
"target matrix verification context",
|
|
897
|
+
),
|
|
898
|
+
runtimeIds,
|
|
899
|
+
"target matrix verification context.expectedEnvironmentBindings",
|
|
900
|
+
);
|
|
901
|
+
const targetRuntimes = normalizeTargetRuntimes(
|
|
902
|
+
ownData(value, "targetRuntimes", "target matrix"),
|
|
903
|
+
);
|
|
904
|
+
const normalized = buildSkillTargetMatrix({
|
|
905
|
+
tenantId: ownData(value, "tenantId", "target matrix"),
|
|
906
|
+
dependencyLock,
|
|
907
|
+
runtimeManifest,
|
|
908
|
+
cells: ownData(value, "cells", "target matrix"),
|
|
909
|
+
});
|
|
910
|
+
if (
|
|
911
|
+
ownData(value, "dependencyLockDigest", "target matrix") !==
|
|
912
|
+
normalized.dependencyLockDigest ||
|
|
913
|
+
ownData(value, "runtimeManifestDigest", "target matrix") !==
|
|
914
|
+
normalized.runtimeManifestDigest
|
|
915
|
+
) {
|
|
916
|
+
throw manifestError(
|
|
917
|
+
"target matrix dependency or runtime manifest binding is invalid",
|
|
918
|
+
);
|
|
919
|
+
}
|
|
920
|
+
if (!equalStringArrays(targetRuntimes, normalized.targetRuntimes)) {
|
|
921
|
+
throw manifestError("target matrix targetRuntimes are not canonical");
|
|
922
|
+
}
|
|
923
|
+
if (
|
|
924
|
+
ownData(value, "targetMatrixRoot", "target matrix") !==
|
|
925
|
+
normalized.targetMatrixRoot
|
|
926
|
+
) {
|
|
927
|
+
throw manifestError("target matrix digest verification failed");
|
|
928
|
+
}
|
|
929
|
+
if (!equalTargetCells(expectedEnvironmentBindings, normalized.cells)) {
|
|
930
|
+
throw manifestError(
|
|
931
|
+
"target matrix environment bindings differ from trusted expectations",
|
|
932
|
+
);
|
|
933
|
+
}
|
|
934
|
+
if (normalized.targetMatrixRoot !== expectedTargetMatrixRoot) {
|
|
935
|
+
throw manifestError("target matrix root differs from trusted expectation");
|
|
936
|
+
}
|
|
937
|
+
return normalized;
|
|
938
|
+
}
|
|
939
|
+
|
|
940
|
+
export function digestSkillTargetMatrix(input) {
|
|
941
|
+
return buildSkillTargetMatrix(input).targetMatrixRoot;
|
|
942
|
+
}
|