@holoscript/core 6.0.3 → 7.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +40 -40
- package/dist/codebase/index.d.ts +25 -0
- package/dist/compiler/index.d.ts +82 -0
- package/dist/constants.d.ts +4 -0
- package/dist/coordinators/index.d.ts +189 -0
- package/dist/entries/interop.d.ts +9 -0
- package/dist/entries/scripting.d.ts +7 -0
- package/dist/index.d.ts +520 -19
- package/dist/paper-0c-spike/index.d.ts +29 -0
- package/dist/reconstruction/index.d.ts +78 -0
- package/dist/self-improvement/index.d.ts +0 -48
- package/dist/storage/index.d.ts +24 -0
- package/dist/tools/index.d.ts +33 -0
- package/dist/traitDocs/traitDocs.d.ts +69 -0
- package/dist/traits/index.d.ts +61 -0
- package/package.json +102 -19
- package/dist/GLTFPipeline-3KLWWUQO.cjs +0 -34
- package/dist/GLTFPipeline-LYII2ZVQ.js +0 -13
- package/dist/HoloScriptPlusParser-BZR5DELQ.js +0 -692
- package/dist/HoloScriptPlusParser-SBMYDNXO.cjs +0 -697
- package/dist/USDZExporter-MHEHXZB4.cjs +0 -709
- package/dist/USDZExporter-YA55ZS35.js +0 -707
- package/dist/chunk-26TLYBFD.js +0 -309
- package/dist/chunk-27LWW5FU.cjs +0 -410
- package/dist/chunk-2UX5LRAP.cjs +0 -833
- package/dist/chunk-32TWR3HE.js +0 -70
- package/dist/chunk-3FXV5S25.cjs +0 -633
- package/dist/chunk-3FYZOR7S.cjs +0 -69
- package/dist/chunk-3KEU5QYY.cjs +0 -175
- package/dist/chunk-4FCZDTD5.js +0 -610
- package/dist/chunk-4KJ2R7VP.cjs +0 -507
- package/dist/chunk-4SMUJFHL.js +0 -1213
- package/dist/chunk-54FHG2MX.js +0 -655
- package/dist/chunk-56IF4NTA.js +0 -56
- package/dist/chunk-5GLCTO44.js +0 -161
- package/dist/chunk-5TOFIR6L.js +0 -407
- package/dist/chunk-65RFOWZI.js +0 -765
- package/dist/chunk-6OQBLABR.js +0 -5240
- package/dist/chunk-6WNCRE6F.js +0 -126
- package/dist/chunk-74YCHHTE.js +0 -1872
- package/dist/chunk-7H5UNJZD.cjs +0 -1973
- package/dist/chunk-7KPI4EKH.cjs +0 -701
- package/dist/chunk-7LCYLPW2.cjs +0 -663
- package/dist/chunk-7N3JIJMT.js +0 -1395
- package/dist/chunk-7X2IEJIE.cjs +0 -2526
- package/dist/chunk-A6GO3DPZ.cjs +0 -1002
- package/dist/chunk-AC4BSHFV.js +0 -765
- package/dist/chunk-AIUXRS74.cjs +0 -3681
- package/dist/chunk-ARNKA274.cjs +0 -130
- package/dist/chunk-AW7WAELW.js +0 -975
- package/dist/chunk-BKIGPPVM.js +0 -629
- package/dist/chunk-BO2OKHIY.js +0 -6055
- package/dist/chunk-BU5ZAFMC.js +0 -115
- package/dist/chunk-BY3B7ZYV.cjs +0 -457
- package/dist/chunk-C2QHVHZF.js +0 -4066
- package/dist/chunk-C7BNX4XJ.js +0 -1043
- package/dist/chunk-CLYEIWA5.cjs +0 -408
- package/dist/chunk-CMYAWUX3.js +0 -4455
- package/dist/chunk-CN4NOESF.cjs +0 -416
- package/dist/chunk-CNVM7J3M.js +0 -883
- package/dist/chunk-CO2VM2DK.js +0 -1965
- package/dist/chunk-CQDOF3G7.cjs +0 -1404
- package/dist/chunk-DH5G2JUA.cjs +0 -614
- package/dist/chunk-DIEDKX5B.cjs +0 -660
- package/dist/chunk-DN7UFU63.cjs +0 -172
- package/dist/chunk-DXVCEFZB.js +0 -2027
- package/dist/chunk-EGIZHYJP.cjs +0 -85
- package/dist/chunk-EJA7G2C4.cjs +0 -428
- package/dist/chunk-ELLQPFAF.js +0 -830
- package/dist/chunk-EMO7HAKJ.cjs +0 -1875
- package/dist/chunk-ENV7K6XA.js +0 -282
- package/dist/chunk-EPWRXL6S.js +0 -2522
- package/dist/chunk-EUFLX2PI.js +0 -56956
- package/dist/chunk-F5LVGHNT.js +0 -449
- package/dist/chunk-FEFHPUEM.cjs +0 -6122
- package/dist/chunk-FF3Q7ADR.js +0 -380
- package/dist/chunk-GC3YU46J.js +0 -762
- package/dist/chunk-H6WMMLQK.cjs +0 -4492
- package/dist/chunk-H7XMORZI.js +0 -2731
- package/dist/chunk-HAN4V3PF.cjs +0 -2037
- package/dist/chunk-HBZYCASG.js +0 -4208
- package/dist/chunk-HF4OFY25.cjs +0 -4097
- package/dist/chunk-HHS6FMOU.cjs +0 -3813
- package/dist/chunk-HJJLD366.js +0 -1169
- package/dist/chunk-HKCVM6OK.cjs +0 -2237
- package/dist/chunk-HUFNKFA6.js +0 -698
- package/dist/chunk-I3XGTIHM.cjs +0 -1505
- package/dist/chunk-I6XZ5DZF.cjs +0 -488
- package/dist/chunk-IHOUYQIA.js +0 -406
- package/dist/chunk-ILRBGFVD.cjs +0 -72
- package/dist/chunk-KDB6BUMB.js +0 -3666
- package/dist/chunk-KUJRR4FJ.js +0 -657
- package/dist/chunk-KYM4XRFG.js +0 -421
- package/dist/chunk-L3Z2HIWJ.cjs +0 -793
- package/dist/chunk-LBPEZQAF.js +0 -2232
- package/dist/chunk-LER4WXW5.cjs +0 -286
- package/dist/chunk-LK5IAVH6.cjs +0 -1173
- package/dist/chunk-M6FU6S22.js +0 -2911
- package/dist/chunk-MWEFR6YQ.js +0 -1857
- package/dist/chunk-N5FTS757.cjs +0 -415
- package/dist/chunk-NCUHGRTZ.js +0 -752
- package/dist/chunk-NKRKT6V2.js +0 -69
- package/dist/chunk-NLPSZT4C.js +0 -630
- package/dist/chunk-NRUB55IT.cjs +0 -771
- package/dist/chunk-NTMZSDXM.cjs +0 -633
- package/dist/chunk-ODGMVILH.js +0 -9662
- package/dist/chunk-PBA6NXCT.cjs +0 -1216
- package/dist/chunk-PHENW4MQ.js +0 -65
- package/dist/chunk-PJMOXFPR.cjs +0 -1861
- package/dist/chunk-PLMYCCA4.js +0 -504
- package/dist/chunk-PPULB4GG.cjs +0 -9728
- package/dist/chunk-PQLGZKMC.cjs +0 -755
- package/dist/chunk-Q56TT7IL.js +0 -483
- package/dist/chunk-QHVVVN47.cjs +0 -2033
- package/dist/chunk-QWKUKVRE.js +0 -2026
- package/dist/chunk-RE3OKSYF.cjs +0 -424
- package/dist/chunk-RT7LJRSF.cjs +0 -57378
- package/dist/chunk-SPDELRRV.cjs +0 -319
- package/dist/chunk-SUCBB66F.js +0 -229
- package/dist/chunk-TSWTWZ42.cjs +0 -4214
- package/dist/chunk-UITWA6DV.cjs +0 -2829
- package/dist/chunk-UQW6SLM5.js +0 -172
- package/dist/chunk-V2ILLPHK.cjs +0 -237
- package/dist/chunk-V42NTCFH.js +0 -3645
- package/dist/chunk-VJ3L7CHT.cjs +0 -169
- package/dist/chunk-VJVCD5T5.cjs +0 -769
- package/dist/chunk-VK5AXKO3.js +0 -746
- package/dist/chunk-VSXOIUCF.cjs +0 -473
- package/dist/chunk-VZNKJZTT.cjs +0 -749
- package/dist/chunk-W76ETJTI.js +0 -678
- package/dist/chunk-WFJIDI2N.cjs +0 -424
- package/dist/chunk-WN3YF33G.cjs +0 -118
- package/dist/chunk-WUXIRGZP.cjs +0 -2915
- package/dist/chunk-WYH4GVZ5.js +0 -1488
- package/dist/chunk-X4YVN7H3.cjs +0 -888
- package/dist/chunk-X67XRI2T.js +0 -410
- package/dist/chunk-XDXZM3ZP.cjs +0 -1046
- package/dist/chunk-XH7SE4HH.cjs +0 -72
- package/dist/chunk-XNMEH2BI.js +0 -126
- package/dist/chunk-XSF76QRU.js +0 -468
- package/dist/chunk-XSUZMPVQ.cjs +0 -682
- package/dist/chunk-XUILI4KB.cjs +0 -430
- package/dist/chunk-Y5MUAYTO.js +0 -167
- package/dist/chunk-Y7VK5TH3.cjs +0 -129
- package/dist/chunk-YCMQQQ5U.cjs +0 -5244
- package/dist/chunk-YYXH45E2.js +0 -426
- package/dist/chunk-ZGTGVSTZ.js +0 -422
- package/dist/chunk-ZL6VJ6SN.js +0 -421
- package/dist/cli/holoscript-runner.cjs +0 -2258
- package/dist/cli/holoscript-runner.js +0 -2233
- package/dist/codebase/index.cjs +0 -336
- package/dist/codebase/index.js +0 -331
- package/dist/compiler/agent-inference.cjs +0 -29
- package/dist/compiler/agent-inference.js +0 -6
- package/dist/compiler/android-xr.cjs +0 -20
- package/dist/compiler/android-xr.js +0 -10
- package/dist/compiler/android.cjs +0 -21
- package/dist/compiler/android.js +0 -11
- package/dist/compiler/ar.cjs +0 -21
- package/dist/compiler/ar.js +0 -9
- package/dist/compiler/babylon.cjs +0 -18
- package/dist/compiler/babylon.js +0 -12
- package/dist/compiler/coco.cjs +0 -27
- package/dist/compiler/coco.js +0 -4
- package/dist/compiler/domain-block-utils.cjs +0 -595
- package/dist/compiler/domain-block-utils.js +0 -9
- package/dist/compiler/dtdl.cjs +0 -25
- package/dist/compiler/dtdl.js +0 -9
- package/dist/compiler/gltf-pipeline.cjs +0 -39
- package/dist/compiler/gltf-pipeline.js +0 -4
- package/dist/compiler/godot.cjs +0 -16
- package/dist/compiler/godot.js +0 -10
- package/dist/compiler/incremental.cjs +0 -30
- package/dist/compiler/incremental.js +0 -5
- package/dist/compiler/index.cjs +0 -1522
- package/dist/compiler/index.js +0 -1321
- package/dist/compiler/ios.cjs +0 -21
- package/dist/compiler/ios.js +0 -11
- package/dist/compiler/multi-layer.cjs +0 -27
- package/dist/compiler/multi-layer.js +0 -12
- package/dist/compiler/nodetoy.cjs +0 -23
- package/dist/compiler/nodetoy.js +0 -4
- package/dist/compiler/openxr.cjs +0 -16
- package/dist/compiler/openxr.js +0 -10
- package/dist/compiler/playcanvas.cjs +0 -17
- package/dist/compiler/playcanvas.js +0 -11
- package/dist/compiler/r3f.cjs +0 -35
- package/dist/compiler/r3f.js +0 -13
- package/dist/compiler/remotion.cjs +0 -23
- package/dist/compiler/remotion.js +0 -4
- package/dist/compiler/reproducibility.cjs +0 -39
- package/dist/compiler/reproducibility.js +0 -4
- package/dist/compiler/sdf.cjs +0 -22
- package/dist/compiler/sdf.js +0 -10
- package/dist/compiler/semantic-scene.cjs +0 -31
- package/dist/compiler/semantic-scene.js +0 -4
- package/dist/compiler/state.cjs +0 -18
- package/dist/compiler/state.js +0 -8
- package/dist/compiler/trait-composition.cjs +0 -27
- package/dist/compiler/trait-composition.js +0 -6
- package/dist/compiler/unity.cjs +0 -16
- package/dist/compiler/unity.js +0 -10
- package/dist/compiler/unreal.cjs +0 -20
- package/dist/compiler/unreal.js +0 -10
- package/dist/compiler/urdf.cjs +0 -46
- package/dist/compiler/urdf.js +0 -10
- package/dist/compiler/usd-physics.cjs +0 -24
- package/dist/compiler/usd-physics.js +0 -7
- package/dist/compiler/visionos.cjs +0 -16
- package/dist/compiler/visionos.js +0 -10
- package/dist/compiler/vrchat.cjs +0 -20
- package/dist/compiler/vrchat.js +0 -10
- package/dist/compiler/vrr.cjs +0 -22
- package/dist/compiler/vrr.js +0 -10
- package/dist/compiler/wasm.cjs +0 -34
- package/dist/compiler/wasm.js +0 -10
- package/dist/compiler/webgpu.cjs +0 -16
- package/dist/compiler/webgpu.js +0 -10
- package/dist/debugger.cjs +0 -21
- package/dist/debugger.js +0 -8
- package/dist/entries/interop.cjs +0 -62
- package/dist/entries/interop.js +0 -5
- package/dist/entries/scripting.cjs +0 -67
- package/dist/entries/scripting.js +0 -10
- package/dist/index.cjs +0 -61703
- package/dist/index.js +0 -58652
- package/dist/math/vec3.cjs +0 -57
- package/dist/math/vec3.js +0 -4
- package/dist/parser.cjs +0 -26
- package/dist/parser.js +0 -9
- package/dist/playwright-7DTEQCBD.cjs +0 -98673
- package/dist/playwright-BIZXMLD2.js +0 -98660
- package/dist/post-quantum-JTTAAGO3.cjs +0 -6
- package/dist/post-quantum-RVPVDEPI.js +0 -4
- package/dist/runtime.cjs +0 -16
- package/dist/runtime.js +0 -7
- package/dist/storage/index.cjs +0 -37
- package/dist/storage/index.js +0 -4
- package/dist/traits/index.cjs +0 -14331
- package/dist/traits/index.js +0 -12126
- package/dist/type-checker.cjs +0 -18
- package/dist/type-checker.js +0 -5
- package/dist/wot/index.cjs +0 -29
- package/dist/wot/index.js +0 -4
package/dist/chunk-V42NTCFH.js
DELETED
|
@@ -1,3645 +0,0 @@
|
|
|
1
|
-
import { __esm } from './chunk-32TWR3HE.js';
|
|
2
|
-
import * as crypto3 from 'crypto';
|
|
3
|
-
import { promisify } from 'util';
|
|
4
|
-
import jwt from 'jsonwebtoken';
|
|
5
|
-
import path from 'path';
|
|
6
|
-
|
|
7
|
-
function calculateJwkThumbprint(publicKeyPem) {
|
|
8
|
-
const keyObject = crypto3.createPublicKey(publicKeyPem);
|
|
9
|
-
const jwk = keyObject.export({ format: "jwk" });
|
|
10
|
-
const canonical = buildCanonicalJwk(jwk);
|
|
11
|
-
const json = JSON.stringify(canonical);
|
|
12
|
-
return crypto3.createHash("sha256").update(json).digest("base64url");
|
|
13
|
-
}
|
|
14
|
-
function buildCanonicalJwk(jwk) {
|
|
15
|
-
const kty = jwk.kty;
|
|
16
|
-
switch (kty) {
|
|
17
|
-
case "RSA": {
|
|
18
|
-
const e = jwk.e;
|
|
19
|
-
const n = jwk.n;
|
|
20
|
-
if (!e || !n) {
|
|
21
|
-
throw new Error("RSA JWK missing required members: e, n");
|
|
22
|
-
}
|
|
23
|
-
return { e, kty: "RSA", n };
|
|
24
|
-
}
|
|
25
|
-
case "EC": {
|
|
26
|
-
const crv = jwk.crv;
|
|
27
|
-
const x = jwk.x;
|
|
28
|
-
const y = jwk.y;
|
|
29
|
-
if (!crv || !x || !y) {
|
|
30
|
-
throw new Error("EC JWK missing required members: crv, x, y");
|
|
31
|
-
}
|
|
32
|
-
return { crv, kty: "EC", x, y };
|
|
33
|
-
}
|
|
34
|
-
case "OKP": {
|
|
35
|
-
const crv = jwk.crv;
|
|
36
|
-
const x = jwk.x;
|
|
37
|
-
if (!crv || !x) {
|
|
38
|
-
throw new Error("OKP JWK missing required members: crv, x");
|
|
39
|
-
}
|
|
40
|
-
return { crv, kty: "OKP", x };
|
|
41
|
-
}
|
|
42
|
-
default:
|
|
43
|
-
throw new Error(`Unsupported JWK key type: ${kty ?? "(undefined)"}`);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
var init_JwkThumbprint = __esm({
|
|
47
|
-
"src/compiler/identity/JwkThumbprint.ts"() {
|
|
48
|
-
}
|
|
49
|
-
});
|
|
50
|
-
function calculateAgentChecksum(config) {
|
|
51
|
-
const canonical = {
|
|
52
|
-
role: config.role,
|
|
53
|
-
name: config.name,
|
|
54
|
-
version: config.version,
|
|
55
|
-
prompt: config.prompt || "",
|
|
56
|
-
tools: (config.tools || []).sort(),
|
|
57
|
-
// Sort for determinism
|
|
58
|
-
configuration: config.configuration || {},
|
|
59
|
-
culturalProfile: config.culturalProfile || null
|
|
60
|
-
};
|
|
61
|
-
const serialized = JSON.stringify(canonical);
|
|
62
|
-
const hash = crypto3.createHash("sha256").update(serialized).digest("hex");
|
|
63
|
-
return {
|
|
64
|
-
hash,
|
|
65
|
-
algorithm: "sha256",
|
|
66
|
-
calculatedAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
67
|
-
label: `${config.role}:${config.name}:${config.version}`
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
async function generateAgentKeyPair(agentRole, timestamp) {
|
|
71
|
-
if (!generateKeyPairAsync) {
|
|
72
|
-
throw new Error(
|
|
73
|
-
"crypto.generateKeyPair is unavailable in this environment (browser). Key pair generation requires a Node.js runtime."
|
|
74
|
-
);
|
|
75
|
-
}
|
|
76
|
-
const { publicKey, privateKey } = await generateKeyPairAsync("ed25519", {
|
|
77
|
-
publicKeyEncoding: {
|
|
78
|
-
type: "spki",
|
|
79
|
-
format: "pem"
|
|
80
|
-
},
|
|
81
|
-
privateKeyEncoding: {
|
|
82
|
-
type: "pkcs8",
|
|
83
|
-
format: "pem"
|
|
84
|
-
}
|
|
85
|
-
});
|
|
86
|
-
const ts = /* @__PURE__ */ new Date();
|
|
87
|
-
const kid = `agent:${agentRole}#${ts.toISOString()}`;
|
|
88
|
-
const thumbprint = calculateJwkThumbprint(publicKey);
|
|
89
|
-
return {
|
|
90
|
-
publicKey,
|
|
91
|
-
privateKey,
|
|
92
|
-
kid,
|
|
93
|
-
thumbprint
|
|
94
|
-
};
|
|
95
|
-
}
|
|
96
|
-
function isValidWorkflowTransition(currentStep, nextStep) {
|
|
97
|
-
const validNextSteps = WORKFLOW_SEQUENCES[currentStep];
|
|
98
|
-
return validNextSteps.includes(nextStep);
|
|
99
|
-
}
|
|
100
|
-
function getDefaultPermissions(role) {
|
|
101
|
-
return [...ROLE_PERMISSIONS[role]];
|
|
102
|
-
}
|
|
103
|
-
var generateKeyPairAsync, AgentPermission, WorkflowStep, ROLE_PERMISSIONS, WORKFLOW_SEQUENCES;
|
|
104
|
-
var init_AgentIdentity = __esm({
|
|
105
|
-
"src/compiler/identity/AgentIdentity.ts"() {
|
|
106
|
-
init_JwkThumbprint();
|
|
107
|
-
generateKeyPairAsync = typeof crypto3.generateKeyPair === "function" ? promisify(crypto3.generateKeyPair) : null;
|
|
108
|
-
AgentPermission = /* @__PURE__ */ ((AgentPermission4) => {
|
|
109
|
-
AgentPermission4["READ_SOURCE"] = "read:source";
|
|
110
|
-
AgentPermission4["READ_CONFIG"] = "read:config";
|
|
111
|
-
AgentPermission4["READ_AST"] = "read:ast";
|
|
112
|
-
AgentPermission4["READ_IR"] = "read:ir";
|
|
113
|
-
AgentPermission4["READ_CODE"] = "read:code";
|
|
114
|
-
AgentPermission4["WRITE_AST"] = "write:ast";
|
|
115
|
-
AgentPermission4["WRITE_IR"] = "write:ir";
|
|
116
|
-
AgentPermission4["WRITE_CODE"] = "write:code";
|
|
117
|
-
AgentPermission4["WRITE_OUTPUT"] = "write:output";
|
|
118
|
-
AgentPermission4["TRANSFORM_AST"] = "transform:ast";
|
|
119
|
-
AgentPermission4["TRANSFORM_IR"] = "transform:ir";
|
|
120
|
-
AgentPermission4["EXECUTE_OPTIMIZATION"] = "execute:optimization";
|
|
121
|
-
AgentPermission4["EXECUTE_CODEGEN"] = "execute:codegen";
|
|
122
|
-
AgentPermission4["EXECUTE_EXPORT"] = "execute:export";
|
|
123
|
-
return AgentPermission4;
|
|
124
|
-
})(AgentPermission || {});
|
|
125
|
-
WorkflowStep = /* @__PURE__ */ ((WorkflowStep3) => {
|
|
126
|
-
WorkflowStep3["PARSE_TOKENS"] = "parse_tokens";
|
|
127
|
-
WorkflowStep3["BUILD_AST"] = "build_ast";
|
|
128
|
-
WorkflowStep3["ANALYZE_AST"] = "analyze_ast";
|
|
129
|
-
WorkflowStep3["APPLY_TRANSFORMS"] = "apply_transforms";
|
|
130
|
-
WorkflowStep3["SELECT_INSTRUCTIONS"] = "select_instructions";
|
|
131
|
-
WorkflowStep3["GENERATE_ASSEMBLY"] = "generate_assembly";
|
|
132
|
-
WorkflowStep3["FORMAT_OUTPUT"] = "format_output";
|
|
133
|
-
WorkflowStep3["SERIALIZE"] = "serialize";
|
|
134
|
-
return WorkflowStep3;
|
|
135
|
-
})(WorkflowStep || {});
|
|
136
|
-
ROLE_PERMISSIONS = {
|
|
137
|
-
["syntax_analyzer" /* SYNTAX_ANALYZER */]: [
|
|
138
|
-
"read:source" /* READ_SOURCE */,
|
|
139
|
-
"read:config" /* READ_CONFIG */,
|
|
140
|
-
"write:ast" /* WRITE_AST */
|
|
141
|
-
],
|
|
142
|
-
["ast_optimizer" /* AST_OPTIMIZER */]: [
|
|
143
|
-
"read:ast" /* READ_AST */,
|
|
144
|
-
"read:config" /* READ_CONFIG */,
|
|
145
|
-
"write:ast" /* WRITE_AST */,
|
|
146
|
-
"transform:ast" /* TRANSFORM_AST */,
|
|
147
|
-
"execute:optimization" /* EXECUTE_OPTIMIZATION */
|
|
148
|
-
],
|
|
149
|
-
["code_generator" /* CODE_GENERATOR */]: [
|
|
150
|
-
"read:ast" /* READ_AST */,
|
|
151
|
-
"read:ir" /* READ_IR */,
|
|
152
|
-
"read:config" /* READ_CONFIG */,
|
|
153
|
-
"write:ir" /* WRITE_IR */,
|
|
154
|
-
"write:code" /* WRITE_CODE */,
|
|
155
|
-
"transform:ir" /* TRANSFORM_IR */,
|
|
156
|
-
"execute:codegen" /* EXECUTE_CODEGEN */
|
|
157
|
-
],
|
|
158
|
-
["exporter" /* EXPORTER */]: [
|
|
159
|
-
"read:code" /* READ_CODE */,
|
|
160
|
-
"read:config" /* READ_CONFIG */,
|
|
161
|
-
"write:output" /* WRITE_OUTPUT */,
|
|
162
|
-
"execute:export" /* EXECUTE_EXPORT */
|
|
163
|
-
],
|
|
164
|
-
["orchestrator" /* ORCHESTRATOR */]: [
|
|
165
|
-
// Orchestrator has all permissions
|
|
166
|
-
...Object.values(AgentPermission)
|
|
167
|
-
]
|
|
168
|
-
};
|
|
169
|
-
WORKFLOW_SEQUENCES = {
|
|
170
|
-
["parse_tokens" /* PARSE_TOKENS */]: ["build_ast" /* BUILD_AST */],
|
|
171
|
-
["build_ast" /* BUILD_AST */]: ["analyze_ast" /* ANALYZE_AST */],
|
|
172
|
-
["analyze_ast" /* ANALYZE_AST */]: ["apply_transforms" /* APPLY_TRANSFORMS */],
|
|
173
|
-
["apply_transforms" /* APPLY_TRANSFORMS */]: ["select_instructions" /* SELECT_INSTRUCTIONS */],
|
|
174
|
-
["select_instructions" /* SELECT_INSTRUCTIONS */]: ["generate_assembly" /* GENERATE_ASSEMBLY */],
|
|
175
|
-
["generate_assembly" /* GENERATE_ASSEMBLY */]: ["format_output" /* FORMAT_OUTPUT */],
|
|
176
|
-
["format_output" /* FORMAT_OUTPUT */]: ["serialize" /* SERIALIZE */],
|
|
177
|
-
["serialize" /* SERIALIZE */]: []
|
|
178
|
-
// Terminal step
|
|
179
|
-
};
|
|
180
|
-
}
|
|
181
|
-
});
|
|
182
|
-
|
|
183
|
-
// src/traits/CultureTraits.ts
|
|
184
|
-
function getBuiltinNorm(id) {
|
|
185
|
-
return BUILTIN_NORMS.find((n) => n.id === id);
|
|
186
|
-
}
|
|
187
|
-
function normsByCategory(category) {
|
|
188
|
-
return BUILTIN_NORMS.filter((n) => n.category === category);
|
|
189
|
-
}
|
|
190
|
-
function criticalMassForChange(norm, populationSize) {
|
|
191
|
-
const percentages = { weak: 0.02, moderate: 0.25, strong: 0.5 };
|
|
192
|
-
return Math.ceil(populationSize * percentages[norm.strength]);
|
|
193
|
-
}
|
|
194
|
-
function getAllContradictoryNorms() {
|
|
195
|
-
return [...CONTRADICTORY_NORM_PAIRS, ...customContradictoryNorms];
|
|
196
|
-
}
|
|
197
|
-
function getFamilyCompatibility(familyA, familyB) {
|
|
198
|
-
if (familyA === familyB) {
|
|
199
|
-
return { rating: "compatible", reason: "Same cultural family." };
|
|
200
|
-
}
|
|
201
|
-
for (const entry of CULTURAL_FAMILY_COMPATIBILITY) {
|
|
202
|
-
if (entry.familyA === familyA && entry.familyB === familyB || entry.familyA === familyB && entry.familyB === familyA) {
|
|
203
|
-
return { rating: entry.rating, reason: entry.reason };
|
|
204
|
-
}
|
|
205
|
-
}
|
|
206
|
-
return { rating: "compatible", reason: "No known incompatibility between these families." };
|
|
207
|
-
}
|
|
208
|
-
var BUILTIN_NORMS, CULTURAL_FAMILY_COMPATIBILITY, CONTRADICTORY_NORM_PAIRS, customContradictoryNorms;
|
|
209
|
-
var init_CultureTraits = __esm({
|
|
210
|
-
"src/traits/CultureTraits.ts"() {
|
|
211
|
-
BUILTIN_NORMS = [
|
|
212
|
-
// Safety norms
|
|
213
|
-
{
|
|
214
|
-
id: "no_griefing",
|
|
215
|
-
name: "No Griefing",
|
|
216
|
-
category: "safety",
|
|
217
|
-
description: "Agents must not intentionally harm or obstruct others",
|
|
218
|
-
enforcement: "hard",
|
|
219
|
-
scope: "world",
|
|
220
|
-
activationThreshold: 0,
|
|
221
|
-
strength: "strong",
|
|
222
|
-
forbiddenEffects: ["agent:kill", "inventory:destroy", "physics:teleport"]
|
|
223
|
-
},
|
|
224
|
-
{
|
|
225
|
-
id: "resource_sharing",
|
|
226
|
-
name: "Resource Sharing",
|
|
227
|
-
category: "cooperation",
|
|
228
|
-
description: "Agents should share resources when others are in need",
|
|
229
|
-
enforcement: "soft",
|
|
230
|
-
scope: "zone",
|
|
231
|
-
activationThreshold: 0.5,
|
|
232
|
-
strength: "moderate",
|
|
233
|
-
requiredEffects: ["inventory:give"]
|
|
234
|
-
},
|
|
235
|
-
{
|
|
236
|
-
id: "zone_respect",
|
|
237
|
-
name: "Zone Respect",
|
|
238
|
-
category: "territory",
|
|
239
|
-
description: "Agents must request permission before entering owned zones",
|
|
240
|
-
enforcement: "soft",
|
|
241
|
-
scope: "zone",
|
|
242
|
-
activationThreshold: 0.3,
|
|
243
|
-
strength: "moderate",
|
|
244
|
-
requiredEffects: ["agent:communicate"],
|
|
245
|
-
forbiddenEffects: ["authority:zone"]
|
|
246
|
-
},
|
|
247
|
-
{
|
|
248
|
-
id: "fair_trade",
|
|
249
|
-
name: "Fair Trade",
|
|
250
|
-
category: "exchange",
|
|
251
|
-
description: "Trade exchanges must be mutually agreed upon",
|
|
252
|
-
enforcement: "hard",
|
|
253
|
-
scope: "world",
|
|
254
|
-
activationThreshold: 0,
|
|
255
|
-
strength: "strong",
|
|
256
|
-
requiredEffects: ["inventory:trade", "agent:communicate"]
|
|
257
|
-
},
|
|
258
|
-
{
|
|
259
|
-
id: "greeting_convention",
|
|
260
|
-
name: "Greeting Convention",
|
|
261
|
-
category: "communication",
|
|
262
|
-
description: "Agents should acknowledge each other when first meeting in a session",
|
|
263
|
-
enforcement: "advisory",
|
|
264
|
-
scope: "session",
|
|
265
|
-
activationThreshold: 0.6,
|
|
266
|
-
strength: "weak",
|
|
267
|
-
requiredEffects: ["agent:communicate"]
|
|
268
|
-
},
|
|
269
|
-
{
|
|
270
|
-
id: "noise_courtesy",
|
|
271
|
-
name: "Noise Courtesy",
|
|
272
|
-
category: "safety",
|
|
273
|
-
description: "Agents should not play global audio without zone permission",
|
|
274
|
-
enforcement: "soft",
|
|
275
|
-
scope: "zone",
|
|
276
|
-
activationThreshold: 0.4,
|
|
277
|
-
strength: "moderate",
|
|
278
|
-
forbiddenEffects: ["audio:global"]
|
|
279
|
-
},
|
|
280
|
-
{
|
|
281
|
-
id: "spawn_limits",
|
|
282
|
-
name: "Spawn Limits",
|
|
283
|
-
category: "cooperation",
|
|
284
|
-
description: "Agents should not spawn excessive objects in shared spaces",
|
|
285
|
-
enforcement: "hard",
|
|
286
|
-
scope: "zone",
|
|
287
|
-
activationThreshold: 0,
|
|
288
|
-
strength: "strong",
|
|
289
|
-
forbiddenEffects: ["render:spawn"]
|
|
290
|
-
// Catches excessive spawning via budget
|
|
291
|
-
},
|
|
292
|
-
{
|
|
293
|
-
id: "metanorm_enforcement",
|
|
294
|
-
name: "Meta-Norm: Enforce Norms",
|
|
295
|
-
category: "authority",
|
|
296
|
-
description: "Agents who witness norm violations should report them (norm about enforcing norms)",
|
|
297
|
-
enforcement: "advisory",
|
|
298
|
-
scope: "world",
|
|
299
|
-
activationThreshold: 0.7,
|
|
300
|
-
strength: "weak",
|
|
301
|
-
requiredEffects: ["agent:communicate", "agent:observe"]
|
|
302
|
-
}
|
|
303
|
-
];
|
|
304
|
-
CULTURAL_FAMILY_COMPATIBILITY = [
|
|
305
|
-
// Incompatible pairs
|
|
306
|
-
{
|
|
307
|
-
familyA: "competitive",
|
|
308
|
-
familyB: "cooperative",
|
|
309
|
-
rating: "incompatible",
|
|
310
|
-
reason: "Competitive agents pursue individual gain, cooperative agents pursue shared goals. Fundamental goal misalignment."
|
|
311
|
-
},
|
|
312
|
-
{
|
|
313
|
-
familyA: "hierarchical",
|
|
314
|
-
familyB: "egalitarian",
|
|
315
|
-
rating: "incompatible",
|
|
316
|
-
reason: "Hierarchical agents expect chain of command, egalitarian agents reject authority structures."
|
|
317
|
-
},
|
|
318
|
-
{
|
|
319
|
-
familyA: "isolationist",
|
|
320
|
-
familyB: "cooperative",
|
|
321
|
-
rating: "incompatible",
|
|
322
|
-
reason: "Isolationist agents refuse interaction, cooperative agents require mutual engagement."
|
|
323
|
-
},
|
|
324
|
-
// Cautious pairs (can work with mediation)
|
|
325
|
-
{
|
|
326
|
-
familyA: "competitive",
|
|
327
|
-
familyB: "egalitarian",
|
|
328
|
-
rating: "cautious",
|
|
329
|
-
reason: "Competitive ranking conflicts with equal-voice principles. Needs mediation."
|
|
330
|
-
},
|
|
331
|
-
{
|
|
332
|
-
familyA: "isolationist",
|
|
333
|
-
familyB: "ritualistic",
|
|
334
|
-
rating: "cautious",
|
|
335
|
-
reason: "Isolationist independence conflicts with group ceremony requirements. Needs mediation."
|
|
336
|
-
},
|
|
337
|
-
{
|
|
338
|
-
familyA: "mercantile",
|
|
339
|
-
familyB: "cooperative",
|
|
340
|
-
rating: "cautious",
|
|
341
|
-
reason: "Mercantile agents expect value exchange, cooperative agents share freely. Needs mediation."
|
|
342
|
-
},
|
|
343
|
-
{
|
|
344
|
-
familyA: "competitive",
|
|
345
|
-
familyB: "hierarchical",
|
|
346
|
-
rating: "cautious",
|
|
347
|
-
reason: "Competitive agents may challenge authority. Needs clear ranking rules."
|
|
348
|
-
},
|
|
349
|
-
{
|
|
350
|
-
familyA: "isolationist",
|
|
351
|
-
familyB: "hierarchical",
|
|
352
|
-
rating: "cautious",
|
|
353
|
-
reason: "Isolationist agents resist authority. Needs minimal supervision protocols."
|
|
354
|
-
}
|
|
355
|
-
];
|
|
356
|
-
CONTRADICTORY_NORM_PAIRS = [
|
|
357
|
-
{
|
|
358
|
-
normA: "resource_sharing",
|
|
359
|
-
normB: "spawn_limits",
|
|
360
|
-
reason: "Resource sharing may require spawning items, but spawn limits restrict it."
|
|
361
|
-
}
|
|
362
|
-
// Users can extend this set via registerContradictoryNorms()
|
|
363
|
-
];
|
|
364
|
-
customContradictoryNorms = [];
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
function getKeystore(config) {
|
|
368
|
-
if (!globalKeystore) {
|
|
369
|
-
const masterKeyHex = process.env.AGENT_KEYSTORE_MASTER_KEY;
|
|
370
|
-
const masterKey = masterKeyHex ? Buffer.from(masterKeyHex, "hex") : void 0;
|
|
371
|
-
globalKeystore = new AgentKeystore({
|
|
372
|
-
...config,
|
|
373
|
-
masterKey
|
|
374
|
-
});
|
|
375
|
-
}
|
|
376
|
-
return globalKeystore;
|
|
377
|
-
}
|
|
378
|
-
var DEFAULT_TOKEN_LIFETIME, ENCRYPTION_ALGORITHM, KEY_LENGTH, IV_LENGTH, SALT_LENGTH, AgentKeystore, globalKeystore;
|
|
379
|
-
var init_AgentKeystore = __esm({
|
|
380
|
-
"src/compiler/identity/AgentKeystore.ts"() {
|
|
381
|
-
init_AgentIdentity();
|
|
382
|
-
DEFAULT_TOKEN_LIFETIME = 24 * 60 * 60 * 1e3;
|
|
383
|
-
ENCRYPTION_ALGORITHM = "aes-256-gcm";
|
|
384
|
-
KEY_LENGTH = 32;
|
|
385
|
-
IV_LENGTH = 16;
|
|
386
|
-
SALT_LENGTH = 64;
|
|
387
|
-
AgentKeystore = class {
|
|
388
|
-
constructor(config = {}) {
|
|
389
|
-
/** In-memory credential cache (ephemeral, cleared on restart) */
|
|
390
|
-
this.credentialCache = /* @__PURE__ */ new Map();
|
|
391
|
-
/** Persistent encrypted storage (simulated with Map, replace with file/db in production) */
|
|
392
|
-
this.encryptedStorage = /* @__PURE__ */ new Map();
|
|
393
|
-
/** Secondary index: JWK thumbprint → AgentRole, for fast PoP key lookup */
|
|
394
|
-
this.thumbprintIndex = /* @__PURE__ */ new Map();
|
|
395
|
-
/** Audit log buffer */
|
|
396
|
-
this.auditLog = [];
|
|
397
|
-
this.masterKey = config.masterKey || crypto3.randomBytes(KEY_LENGTH);
|
|
398
|
-
this.tokenLifetime = config.tokenLifetime || DEFAULT_TOKEN_LIFETIME;
|
|
399
|
-
this.enableAuditLog = config.enableAuditLog ?? true;
|
|
400
|
-
this.auditLogPath = config.auditLogPath || "./agent-keystore.audit.log";
|
|
401
|
-
if (!config.masterKey && process.env.NODE_ENV === "production") {
|
|
402
|
-
console.warn(
|
|
403
|
-
"[KEYSTORE] Using generated master key. Set AGENT_KEYSTORE_MASTER_KEY environment variable in production."
|
|
404
|
-
);
|
|
405
|
-
}
|
|
406
|
-
}
|
|
407
|
-
/**
|
|
408
|
-
* Encrypt sensitive data using AES-256-GCM
|
|
409
|
-
*/
|
|
410
|
-
encrypt(plaintext) {
|
|
411
|
-
const iv = crypto3.randomBytes(IV_LENGTH);
|
|
412
|
-
const salt = crypto3.randomBytes(SALT_LENGTH);
|
|
413
|
-
const key = crypto3.pbkdf2Sync(this.masterKey, salt, 1e5, KEY_LENGTH, "sha256");
|
|
414
|
-
const cipher = crypto3.createCipheriv(ENCRYPTION_ALGORITHM, key, iv);
|
|
415
|
-
let ciphertext = cipher.update(plaintext, "utf8", "hex");
|
|
416
|
-
ciphertext += cipher.final("hex");
|
|
417
|
-
const authTag = cipher.getAuthTag();
|
|
418
|
-
return {
|
|
419
|
-
ciphertext,
|
|
420
|
-
iv: iv.toString("hex"),
|
|
421
|
-
authTag: authTag.toString("hex"),
|
|
422
|
-
salt: salt.toString("hex"),
|
|
423
|
-
algorithm: ENCRYPTION_ALGORITHM,
|
|
424
|
-
createdAt: (/* @__PURE__ */ new Date()).toISOString(),
|
|
425
|
-
expiresAt: new Date(Date.now() + this.tokenLifetime).toISOString()
|
|
426
|
-
};
|
|
427
|
-
}
|
|
428
|
-
/**
|
|
429
|
-
* Decrypt sensitive data
|
|
430
|
-
*/
|
|
431
|
-
decrypt(encrypted) {
|
|
432
|
-
const iv = Buffer.from(encrypted.iv, "hex");
|
|
433
|
-
const salt = Buffer.from(encrypted.salt, "hex");
|
|
434
|
-
const authTag = Buffer.from(encrypted.authTag, "hex");
|
|
435
|
-
const key = crypto3.pbkdf2Sync(this.masterKey, salt, 1e5, KEY_LENGTH, "sha256");
|
|
436
|
-
const decipher = crypto3.createDecipheriv(ENCRYPTION_ALGORITHM, key, iv);
|
|
437
|
-
decipher.setAuthTag(authTag);
|
|
438
|
-
let plaintext = decipher.update(encrypted.ciphertext, "hex", "utf8");
|
|
439
|
-
plaintext += decipher.final("utf8");
|
|
440
|
-
return plaintext;
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* Log audit event
|
|
444
|
-
*/
|
|
445
|
-
logAudit(entry) {
|
|
446
|
-
if (!this.enableAuditLog) return;
|
|
447
|
-
this.auditLog.push(entry);
|
|
448
|
-
if (process.env.NODE_ENV === "production") {
|
|
449
|
-
console.info(`[AUDIT] ${entry.event} - ${entry.agentRole} - ${entry.timestamp}`);
|
|
450
|
-
}
|
|
451
|
-
}
|
|
452
|
-
/**
|
|
453
|
-
* Store agent credential securely
|
|
454
|
-
*/
|
|
455
|
-
async storeCredential(credential) {
|
|
456
|
-
const existing = this.credentialCache.get(credential.role);
|
|
457
|
-
if (existing) {
|
|
458
|
-
this.thumbprintIndex.delete(existing.keyPair.thumbprint);
|
|
459
|
-
}
|
|
460
|
-
this.credentialCache.set(credential.role, credential);
|
|
461
|
-
this.thumbprintIndex.set(credential.keyPair.thumbprint, credential.role);
|
|
462
|
-
const serialized = JSON.stringify({
|
|
463
|
-
role: credential.role,
|
|
464
|
-
token: credential.token,
|
|
465
|
-
keyPair: credential.keyPair,
|
|
466
|
-
createdAt: credential.createdAt.toISOString(),
|
|
467
|
-
expiresAt: credential.expiresAt.toISOString()
|
|
468
|
-
});
|
|
469
|
-
const encrypted = this.encrypt(serialized);
|
|
470
|
-
this.encryptedStorage.set(credential.role, encrypted);
|
|
471
|
-
this.logAudit({
|
|
472
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
473
|
-
event: "key_generated",
|
|
474
|
-
agentRole: credential.role,
|
|
475
|
-
details: {
|
|
476
|
-
kid: credential.keyPair.kid,
|
|
477
|
-
expiresAt: credential.expiresAt.toISOString()
|
|
478
|
-
}
|
|
479
|
-
});
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* Retrieve agent credential
|
|
483
|
-
*
|
|
484
|
-
* Returns cached credential if valid, otherwise decrypts from storage.
|
|
485
|
-
* Automatically rotates if expired.
|
|
486
|
-
*/
|
|
487
|
-
async getCredential(role) {
|
|
488
|
-
const cached = this.credentialCache.get(role);
|
|
489
|
-
if (cached && cached.expiresAt > /* @__PURE__ */ new Date()) {
|
|
490
|
-
this.logAudit({
|
|
491
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
492
|
-
event: "key_accessed",
|
|
493
|
-
agentRole: role,
|
|
494
|
-
details: { source: "cache" }
|
|
495
|
-
});
|
|
496
|
-
return cached;
|
|
497
|
-
}
|
|
498
|
-
const encrypted = this.encryptedStorage.get(role);
|
|
499
|
-
if (!encrypted) {
|
|
500
|
-
return null;
|
|
501
|
-
}
|
|
502
|
-
if (new Date(encrypted.expiresAt) < /* @__PURE__ */ new Date()) {
|
|
503
|
-
this.logAudit({
|
|
504
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
505
|
-
event: "key_expired",
|
|
506
|
-
agentRole: role
|
|
507
|
-
});
|
|
508
|
-
await this.rotateCredential(role);
|
|
509
|
-
return this.getCredential(role);
|
|
510
|
-
}
|
|
511
|
-
const decrypted = this.decrypt(encrypted);
|
|
512
|
-
const parsed = JSON.parse(decrypted);
|
|
513
|
-
const credential = {
|
|
514
|
-
role: parsed.role,
|
|
515
|
-
token: parsed.token,
|
|
516
|
-
keyPair: parsed.keyPair,
|
|
517
|
-
createdAt: new Date(parsed.createdAt),
|
|
518
|
-
expiresAt: new Date(parsed.expiresAt)
|
|
519
|
-
};
|
|
520
|
-
this.credentialCache.set(role, credential);
|
|
521
|
-
this.logAudit({
|
|
522
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
523
|
-
event: "key_accessed",
|
|
524
|
-
agentRole: role,
|
|
525
|
-
details: { source: "storage" }
|
|
526
|
-
});
|
|
527
|
-
return credential;
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* Rotate agent credential (generate new keys and token)
|
|
531
|
-
*/
|
|
532
|
-
async rotateCredential(role) {
|
|
533
|
-
const keyPair = await generateAgentKeyPair(role);
|
|
534
|
-
const credential = {
|
|
535
|
-
role,
|
|
536
|
-
token: "",
|
|
537
|
-
// Placeholder, will be set by token issuer
|
|
538
|
-
keyPair,
|
|
539
|
-
createdAt: /* @__PURE__ */ new Date(),
|
|
540
|
-
expiresAt: new Date(Date.now() + this.tokenLifetime)
|
|
541
|
-
};
|
|
542
|
-
await this.storeCredential(credential);
|
|
543
|
-
this.logAudit({
|
|
544
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
545
|
-
event: "key_rotated",
|
|
546
|
-
agentRole: role,
|
|
547
|
-
details: {
|
|
548
|
-
oldKid: this.credentialCache.get(role)?.keyPair.kid,
|
|
549
|
-
newKid: keyPair.kid
|
|
550
|
-
}
|
|
551
|
-
});
|
|
552
|
-
return credential;
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* Retrieve credential by JWK thumbprint (for PoP token verification).
|
|
556
|
-
*
|
|
557
|
-
* Returns the credential whose key pair matches the given JWK SHA-256
|
|
558
|
-
* thumbprint, or null if no matching credential is found.
|
|
559
|
-
*
|
|
560
|
-
* Primary lookup uses the in-memory index; falls back to decrypting all
|
|
561
|
-
* stored credentials when the index doesn't contain the thumbprint (e.g.
|
|
562
|
-
* credentials stored before the index was introduced).
|
|
563
|
-
*/
|
|
564
|
-
async getCredentialByThumbprint(thumbprint) {
|
|
565
|
-
const role = this.thumbprintIndex.get(thumbprint);
|
|
566
|
-
if (role) {
|
|
567
|
-
return this.getCredential(role);
|
|
568
|
-
}
|
|
569
|
-
for (const [storedRole, encrypted] of this.encryptedStorage.entries()) {
|
|
570
|
-
if (new Date(encrypted.expiresAt) < /* @__PURE__ */ new Date()) {
|
|
571
|
-
continue;
|
|
572
|
-
}
|
|
573
|
-
const credential = await this.getCredential(storedRole);
|
|
574
|
-
if (credential) {
|
|
575
|
-
this.thumbprintIndex.set(credential.keyPair.thumbprint, storedRole);
|
|
576
|
-
if (credential.keyPair.thumbprint === thumbprint) {
|
|
577
|
-
return credential;
|
|
578
|
-
}
|
|
579
|
-
}
|
|
580
|
-
}
|
|
581
|
-
return null;
|
|
582
|
-
}
|
|
583
|
-
/**
|
|
584
|
-
* Delete agent credential
|
|
585
|
-
*/
|
|
586
|
-
async deleteCredential(role) {
|
|
587
|
-
const credential = this.credentialCache.get(role);
|
|
588
|
-
if (credential) {
|
|
589
|
-
this.thumbprintIndex.delete(credential.keyPair.thumbprint);
|
|
590
|
-
}
|
|
591
|
-
this.credentialCache.delete(role);
|
|
592
|
-
this.encryptedStorage.delete(role);
|
|
593
|
-
this.logAudit({
|
|
594
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
595
|
-
event: "key_deleted",
|
|
596
|
-
agentRole: role
|
|
597
|
-
});
|
|
598
|
-
}
|
|
599
|
-
/**
|
|
600
|
-
* List all stored credentials (metadata only)
|
|
601
|
-
*/
|
|
602
|
-
listCredentials() {
|
|
603
|
-
return Array.from(this.encryptedStorage.entries()).map(([role, encrypted]) => ({
|
|
604
|
-
role,
|
|
605
|
-
createdAt: encrypted.createdAt,
|
|
606
|
-
expiresAt: encrypted.expiresAt,
|
|
607
|
-
isExpired: new Date(encrypted.expiresAt) < /* @__PURE__ */ new Date()
|
|
608
|
-
}));
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* Get audit log
|
|
612
|
-
*/
|
|
613
|
-
getAuditLog() {
|
|
614
|
-
return [...this.auditLog];
|
|
615
|
-
}
|
|
616
|
-
/**
|
|
617
|
-
* Clear all credentials (use with caution)
|
|
618
|
-
*/
|
|
619
|
-
clearAll() {
|
|
620
|
-
this.credentialCache.clear();
|
|
621
|
-
this.encryptedStorage.clear();
|
|
622
|
-
this.thumbprintIndex.clear();
|
|
623
|
-
this.logAudit({
|
|
624
|
-
timestamp: (/* @__PURE__ */ new Date()).toISOString(),
|
|
625
|
-
event: "key_deleted",
|
|
626
|
-
agentRole: "orchestrator" /* ORCHESTRATOR */,
|
|
627
|
-
details: { action: "clear_all" }
|
|
628
|
-
});
|
|
629
|
-
}
|
|
630
|
-
};
|
|
631
|
-
globalKeystore = null;
|
|
632
|
-
}
|
|
633
|
-
});
|
|
634
|
-
|
|
635
|
-
// src/compiler/identity/CapabilityToken.ts
|
|
636
|
-
var HOLOSCRIPT_RESOURCE_SCHEME, HOLOSCRIPT_RESOURCE_ALL, CapabilityActions, PERMISSION_TO_ACTION;
|
|
637
|
-
var init_CapabilityToken = __esm({
|
|
638
|
-
"src/compiler/identity/CapabilityToken.ts"() {
|
|
639
|
-
HOLOSCRIPT_RESOURCE_SCHEME = "holoscript://";
|
|
640
|
-
HOLOSCRIPT_RESOURCE_ALL = "holoscript://*";
|
|
641
|
-
CapabilityActions = {
|
|
642
|
-
// Source
|
|
643
|
-
SOURCE_READ: "source/read",
|
|
644
|
-
// Config
|
|
645
|
-
CONFIG_READ: "config/read",
|
|
646
|
-
// AST
|
|
647
|
-
AST_READ: "ast/read",
|
|
648
|
-
AST_WRITE: "ast/write",
|
|
649
|
-
AST_TRANSFORM: "ast/transform",
|
|
650
|
-
// IR
|
|
651
|
-
IR_READ: "ir/read",
|
|
652
|
-
IR_WRITE: "ir/write",
|
|
653
|
-
IR_TRANSFORM: "ir/transform",
|
|
654
|
-
// Code
|
|
655
|
-
CODE_READ: "code/read",
|
|
656
|
-
CODE_WRITE: "code/write",
|
|
657
|
-
// Output
|
|
658
|
-
OUTPUT_WRITE: "output/write",
|
|
659
|
-
// Execution
|
|
660
|
-
EXECUTE_OPTIMIZATION: "execute/optimization",
|
|
661
|
-
EXECUTE_CODEGEN: "execute/codegen",
|
|
662
|
-
EXECUTE_EXPORT: "execute/export",
|
|
663
|
-
// Proof-of-Play (computation attestation)
|
|
664
|
-
PROOF_OF_PLAY_WRITE: "proof_of_play/write",
|
|
665
|
-
PROOF_OF_PLAY_READ: "proof_of_play/read",
|
|
666
|
-
PROOF_OF_PLAY_VERIFY: "proof_of_play/verify",
|
|
667
|
-
// Wildcard (orchestrator only)
|
|
668
|
-
ALL: "*"
|
|
669
|
-
};
|
|
670
|
-
PERMISSION_TO_ACTION = {
|
|
671
|
-
["read:source" /* READ_SOURCE */]: CapabilityActions.SOURCE_READ,
|
|
672
|
-
["read:config" /* READ_CONFIG */]: CapabilityActions.CONFIG_READ,
|
|
673
|
-
["read:ast" /* READ_AST */]: CapabilityActions.AST_READ,
|
|
674
|
-
["read:ir" /* READ_IR */]: CapabilityActions.IR_READ,
|
|
675
|
-
["read:code" /* READ_CODE */]: CapabilityActions.CODE_READ,
|
|
676
|
-
["write:ast" /* WRITE_AST */]: CapabilityActions.AST_WRITE,
|
|
677
|
-
["write:ir" /* WRITE_IR */]: CapabilityActions.IR_WRITE,
|
|
678
|
-
["write:code" /* WRITE_CODE */]: CapabilityActions.CODE_WRITE,
|
|
679
|
-
["write:output" /* WRITE_OUTPUT */]: CapabilityActions.OUTPUT_WRITE,
|
|
680
|
-
["transform:ast" /* TRANSFORM_AST */]: CapabilityActions.AST_TRANSFORM,
|
|
681
|
-
["transform:ir" /* TRANSFORM_IR */]: CapabilityActions.IR_TRANSFORM,
|
|
682
|
-
["execute:optimization" /* EXECUTE_OPTIMIZATION */]: CapabilityActions.EXECUTE_OPTIMIZATION,
|
|
683
|
-
["execute:codegen" /* EXECUTE_CODEGEN */]: CapabilityActions.EXECUTE_CODEGEN,
|
|
684
|
-
["execute:export" /* EXECUTE_EXPORT */]: CapabilityActions.EXECUTE_EXPORT
|
|
685
|
-
};
|
|
686
|
-
Object.fromEntries(
|
|
687
|
-
Object.entries(PERMISSION_TO_ACTION).map(([perm, action]) => [action, perm])
|
|
688
|
-
);
|
|
689
|
-
}
|
|
690
|
-
});
|
|
691
|
-
function base64urlEncode(data) {
|
|
692
|
-
const buf = typeof data === "string" ? Buffer.from(data, "utf-8") : data;
|
|
693
|
-
return buf.toString("base64url");
|
|
694
|
-
}
|
|
695
|
-
function base64urlDecode(str) {
|
|
696
|
-
return Buffer.from(str, "base64url");
|
|
697
|
-
}
|
|
698
|
-
function getCapabilityTokenIssuer(config) {
|
|
699
|
-
if (!globalCapabilityIssuer) {
|
|
700
|
-
globalCapabilityIssuer = new CapabilityTokenIssuer(config);
|
|
701
|
-
}
|
|
702
|
-
return globalCapabilityIssuer;
|
|
703
|
-
}
|
|
704
|
-
var HoloScriptCapabilitySemantics, CapabilityTokenIssuer, globalCapabilityIssuer;
|
|
705
|
-
var init_CapabilityTokenIssuer = __esm({
|
|
706
|
-
"src/compiler/identity/CapabilityTokenIssuer.ts"() {
|
|
707
|
-
init_AgentIdentity();
|
|
708
|
-
init_CapabilityToken();
|
|
709
|
-
HoloScriptCapabilitySemantics = class {
|
|
710
|
-
/**
|
|
711
|
-
* Check whether `child` is a valid attenuation (subset) of `parent`.
|
|
712
|
-
*/
|
|
713
|
-
isSubsetOf(child, parent) {
|
|
714
|
-
if (parent.can !== CapabilityActions.ALL && parent.can !== child.can) {
|
|
715
|
-
return false;
|
|
716
|
-
}
|
|
717
|
-
if (parent.with === HOLOSCRIPT_RESOURCE_ALL) {
|
|
718
|
-
return child.with.startsWith(HOLOSCRIPT_RESOURCE_SCHEME);
|
|
719
|
-
}
|
|
720
|
-
if (child.with === parent.with) {
|
|
721
|
-
return true;
|
|
722
|
-
}
|
|
723
|
-
const parentNormalized = parent.with.endsWith("/") ? parent.with : parent.with + "/";
|
|
724
|
-
if (child.with.startsWith(parentNormalized)) {
|
|
725
|
-
return true;
|
|
726
|
-
}
|
|
727
|
-
return false;
|
|
728
|
-
}
|
|
729
|
-
/**
|
|
730
|
-
* Check if `capability` authorises the given resource + action.
|
|
731
|
-
*/
|
|
732
|
-
canAccess(capability, resource, action) {
|
|
733
|
-
if (capability.can !== CapabilityActions.ALL && capability.can !== action) {
|
|
734
|
-
return false;
|
|
735
|
-
}
|
|
736
|
-
if (capability.with === HOLOSCRIPT_RESOURCE_ALL) {
|
|
737
|
-
return resource.startsWith(HOLOSCRIPT_RESOURCE_SCHEME);
|
|
738
|
-
}
|
|
739
|
-
if (capability.with === resource) {
|
|
740
|
-
return true;
|
|
741
|
-
}
|
|
742
|
-
const capNormalized = capability.with.endsWith("/") ? capability.with : capability.with + "/";
|
|
743
|
-
return resource.startsWith(capNormalized);
|
|
744
|
-
}
|
|
745
|
-
/**
|
|
746
|
-
* Convert a legacy AgentPermission into a Capability.
|
|
747
|
-
*/
|
|
748
|
-
fromPermission(permission, scope) {
|
|
749
|
-
const action = PERMISSION_TO_ACTION[permission] || permission;
|
|
750
|
-
const resource = scope ? `${HOLOSCRIPT_RESOURCE_SCHEME}${scope}` : HOLOSCRIPT_RESOURCE_ALL;
|
|
751
|
-
return {
|
|
752
|
-
with: resource,
|
|
753
|
-
can: action
|
|
754
|
-
};
|
|
755
|
-
}
|
|
756
|
-
};
|
|
757
|
-
CapabilityTokenIssuer = class {
|
|
758
|
-
constructor(config = {}) {
|
|
759
|
-
/** Token store for proof resolution */
|
|
760
|
-
this.tokenStore = /* @__PURE__ */ new Map();
|
|
761
|
-
/** Nonce set for replay detection */
|
|
762
|
-
this.usedNonces = /* @__PURE__ */ new Set();
|
|
763
|
-
this.defaultLifetimeSec = config.defaultLifetimeSec ?? 86400;
|
|
764
|
-
this.maxDelegationDepth = config.maxDelegationDepth ?? 10;
|
|
765
|
-
this.semantics = config.semantics ?? new HoloScriptCapabilitySemantics();
|
|
766
|
-
this.strictExpiration = config.strictExpiration ?? true;
|
|
767
|
-
}
|
|
768
|
-
// -----------------------------------------------------------------------
|
|
769
|
-
// Root token issuance
|
|
770
|
-
// -----------------------------------------------------------------------
|
|
771
|
-
/**
|
|
772
|
-
* Issue a root capability token (no parent proofs).
|
|
773
|
-
*
|
|
774
|
-
* Root tokens are typically issued by the orchestrator or a top-level
|
|
775
|
-
* identity provider to grant initial capabilities.
|
|
776
|
-
*
|
|
777
|
-
* @param options Token creation options
|
|
778
|
-
* @param keyPair Ed25519 key pair of the issuer (used for signing)
|
|
779
|
-
* @returns Signed CapabilityToken
|
|
780
|
-
*/
|
|
781
|
-
async issueRoot(options, keyPair) {
|
|
782
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
783
|
-
const lifetime = options.lifetimeSec ?? this.defaultLifetimeSec;
|
|
784
|
-
const nonce = crypto3.randomUUID();
|
|
785
|
-
const payload = {
|
|
786
|
-
iss: options.issuer,
|
|
787
|
-
aud: options.audience,
|
|
788
|
-
att: options.capabilities,
|
|
789
|
-
prf: [],
|
|
790
|
-
// root — no proofs
|
|
791
|
-
exp: now + lifetime,
|
|
792
|
-
nbf: options.notBeforeOffsetSec != null ? now + options.notBeforeOffsetSec : void 0,
|
|
793
|
-
nnc: nonce,
|
|
794
|
-
fct: options.facts
|
|
795
|
-
};
|
|
796
|
-
const token = this.sign(payload, keyPair);
|
|
797
|
-
this.tokenStore.set(nonce, token);
|
|
798
|
-
return token;
|
|
799
|
-
}
|
|
800
|
-
// -----------------------------------------------------------------------
|
|
801
|
-
// Delegation with attenuation
|
|
802
|
-
// -----------------------------------------------------------------------
|
|
803
|
-
/**
|
|
804
|
-
* Delegate (attenuate) an existing capability token to a new audience.
|
|
805
|
-
*
|
|
806
|
-
* Enforces:
|
|
807
|
-
* 1. Every capability in the child MUST be a subset of at least one
|
|
808
|
-
* capability in the parent.
|
|
809
|
-
* 2. Child expiration MUST NOT exceed parent expiration.
|
|
810
|
-
* 3. Delegation depth MUST NOT exceed `maxDelegationDepth`.
|
|
811
|
-
*
|
|
812
|
-
* @param options Delegation options including the parent token
|
|
813
|
-
* @param keyPair Ed25519 key pair of the delegator (current holder)
|
|
814
|
-
* @returns New signed CapabilityToken
|
|
815
|
-
* @throws Error if attenuation invariants are violated
|
|
816
|
-
*/
|
|
817
|
-
async delegate(options, keyPair) {
|
|
818
|
-
const { parentToken, audience, capabilities, lifetimeSec, facts } = options;
|
|
819
|
-
const parentPayload = parentToken.payload;
|
|
820
|
-
for (const childCap of capabilities) {
|
|
821
|
-
const covered = parentPayload.att.some(
|
|
822
|
-
(parentCap) => this.semantics.isSubsetOf(childCap, parentCap)
|
|
823
|
-
);
|
|
824
|
-
if (!covered) {
|
|
825
|
-
throw new Error(
|
|
826
|
-
`Attenuation violation: capability {with: "${childCap.with}", can: "${childCap.can}"} is not a subset of any parent capability. Delegations can only narrow scope.`
|
|
827
|
-
);
|
|
828
|
-
}
|
|
829
|
-
}
|
|
830
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
831
|
-
const requestedLifetime = lifetimeSec ?? this.defaultLifetimeSec;
|
|
832
|
-
const childExp = now + requestedLifetime;
|
|
833
|
-
if (this.strictExpiration && childExp > parentPayload.exp) {
|
|
834
|
-
throw new Error(
|
|
835
|
-
`Expiration violation: delegated token expires at ${childExp} but parent expires at ${parentPayload.exp}. Child tokens cannot outlive their parents.`
|
|
836
|
-
);
|
|
837
|
-
}
|
|
838
|
-
const effectiveExp = Math.min(childExp, parentPayload.exp);
|
|
839
|
-
const currentDepth = parentPayload.prf.length + 1;
|
|
840
|
-
if (currentDepth > this.maxDelegationDepth) {
|
|
841
|
-
throw new Error(
|
|
842
|
-
`Delegation depth ${currentDepth} exceeds maximum of ${this.maxDelegationDepth}.`
|
|
843
|
-
);
|
|
844
|
-
}
|
|
845
|
-
const proofs = [...parentPayload.prf, parentPayload.nnc];
|
|
846
|
-
const nonce = crypto3.randomUUID();
|
|
847
|
-
const payload = {
|
|
848
|
-
iss: parentPayload.aud,
|
|
849
|
-
// delegator is the audience of the parent
|
|
850
|
-
aud: audience,
|
|
851
|
-
att: capabilities,
|
|
852
|
-
prf: proofs,
|
|
853
|
-
exp: effectiveExp,
|
|
854
|
-
nbf: now,
|
|
855
|
-
nnc: nonce,
|
|
856
|
-
fct: facts
|
|
857
|
-
};
|
|
858
|
-
const token = this.sign(payload, keyPair);
|
|
859
|
-
this.tokenStore.set(nonce, token);
|
|
860
|
-
return token;
|
|
861
|
-
}
|
|
862
|
-
// -----------------------------------------------------------------------
|
|
863
|
-
// Signing
|
|
864
|
-
// -----------------------------------------------------------------------
|
|
865
|
-
/**
|
|
866
|
-
* Sign a capability token payload with an Ed25519 key pair.
|
|
867
|
-
*
|
|
868
|
-
* Produces a JWT-like structure: base64url(header).base64url(payload).base64url(sig)
|
|
869
|
-
*/
|
|
870
|
-
sign(payload, keyPair) {
|
|
871
|
-
const header = {
|
|
872
|
-
alg: "EdDSA",
|
|
873
|
-
typ: "JWT",
|
|
874
|
-
ucv: "0.10.0"
|
|
875
|
-
};
|
|
876
|
-
const headerB64 = base64urlEncode(JSON.stringify(header));
|
|
877
|
-
const payloadB64 = base64urlEncode(JSON.stringify(payload));
|
|
878
|
-
const signingInput = `${headerB64}.${payloadB64}`;
|
|
879
|
-
const privateKeyObj = crypto3.createPrivateKey(keyPair.privateKey);
|
|
880
|
-
const signatureBuffer = crypto3.sign(null, Buffer.from(signingInput, "utf-8"), privateKeyObj);
|
|
881
|
-
const signatureB64 = signatureBuffer.toString("base64url");
|
|
882
|
-
const raw = `${headerB64}.${payloadB64}.${signatureB64}`;
|
|
883
|
-
return {
|
|
884
|
-
header,
|
|
885
|
-
payload,
|
|
886
|
-
signature: signatureB64,
|
|
887
|
-
raw
|
|
888
|
-
};
|
|
889
|
-
}
|
|
890
|
-
// -----------------------------------------------------------------------
|
|
891
|
-
// Verification
|
|
892
|
-
// -----------------------------------------------------------------------
|
|
893
|
-
/**
|
|
894
|
-
* Verify a capability token.
|
|
895
|
-
*
|
|
896
|
-
* Checks:
|
|
897
|
-
* 1. Structural validity (three-part JWT)
|
|
898
|
-
* 2. Ed25519 signature
|
|
899
|
-
* 3. Expiration / not-before
|
|
900
|
-
* 4. Replay (nonce uniqueness)
|
|
901
|
-
* 5. Proof chain integrity (attenuation invariants)
|
|
902
|
-
*
|
|
903
|
-
* @param raw The raw JWT string (or a CapabilityToken object)
|
|
904
|
-
* @param publicKey PEM-encoded Ed25519 public key of the issuer
|
|
905
|
-
* @returns Verification result
|
|
906
|
-
*/
|
|
907
|
-
verify(raw, publicKey) {
|
|
908
|
-
const rawStr = typeof raw === "string" ? raw : raw.raw;
|
|
909
|
-
const parts = rawStr.split(".");
|
|
910
|
-
if (parts.length !== 3) {
|
|
911
|
-
return {
|
|
912
|
-
valid: false,
|
|
913
|
-
error: "Malformed token: expected 3 parts",
|
|
914
|
-
errorCode: "INVALID_SIGNATURE"
|
|
915
|
-
};
|
|
916
|
-
}
|
|
917
|
-
const [headerB64, payloadB64, signatureB64] = parts;
|
|
918
|
-
try {
|
|
919
|
-
const pubKeyObj = crypto3.createPublicKey(publicKey);
|
|
920
|
-
const signingInput = `${headerB64}.${payloadB64}`;
|
|
921
|
-
const signatureBuffer = base64urlDecode(signatureB64);
|
|
922
|
-
const isValid = crypto3.verify(
|
|
923
|
-
null,
|
|
924
|
-
Buffer.from(signingInput, "utf-8"),
|
|
925
|
-
pubKeyObj,
|
|
926
|
-
signatureBuffer
|
|
927
|
-
);
|
|
928
|
-
if (!isValid) {
|
|
929
|
-
return {
|
|
930
|
-
valid: false,
|
|
931
|
-
error: "Invalid Ed25519 signature",
|
|
932
|
-
errorCode: "INVALID_SIGNATURE"
|
|
933
|
-
};
|
|
934
|
-
}
|
|
935
|
-
} catch {
|
|
936
|
-
return {
|
|
937
|
-
valid: false,
|
|
938
|
-
error: "Signature verification failed",
|
|
939
|
-
errorCode: "INVALID_SIGNATURE"
|
|
940
|
-
};
|
|
941
|
-
}
|
|
942
|
-
let payload;
|
|
943
|
-
try {
|
|
944
|
-
payload = JSON.parse(base64urlDecode(payloadB64).toString("utf-8"));
|
|
945
|
-
} catch {
|
|
946
|
-
return {
|
|
947
|
-
valid: false,
|
|
948
|
-
error: "Malformed payload",
|
|
949
|
-
errorCode: "INVALID_SIGNATURE"
|
|
950
|
-
};
|
|
951
|
-
}
|
|
952
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
953
|
-
if (payload.exp <= now) {
|
|
954
|
-
return {
|
|
955
|
-
valid: false,
|
|
956
|
-
payload,
|
|
957
|
-
error: "Token expired",
|
|
958
|
-
errorCode: "EXPIRED"
|
|
959
|
-
};
|
|
960
|
-
}
|
|
961
|
-
if (payload.nbf != null && payload.nbf > now) {
|
|
962
|
-
return {
|
|
963
|
-
valid: false,
|
|
964
|
-
payload,
|
|
965
|
-
error: `Token not yet valid (nbf: ${payload.nbf}, now: ${now})`,
|
|
966
|
-
errorCode: "NOT_YET_VALID"
|
|
967
|
-
};
|
|
968
|
-
}
|
|
969
|
-
if (this.usedNonces.has(payload.nnc)) {
|
|
970
|
-
return {
|
|
971
|
-
valid: false,
|
|
972
|
-
payload,
|
|
973
|
-
error: "Nonce already used (replay detected)",
|
|
974
|
-
errorCode: "REPLAY_DETECTED"
|
|
975
|
-
};
|
|
976
|
-
}
|
|
977
|
-
this.usedNonces.add(payload.nnc);
|
|
978
|
-
const chainResult = this.resolveChain(payload);
|
|
979
|
-
return {
|
|
980
|
-
valid: true,
|
|
981
|
-
payload,
|
|
982
|
-
chain: chainResult
|
|
983
|
-
};
|
|
984
|
-
}
|
|
985
|
-
// -----------------------------------------------------------------------
|
|
986
|
-
// Proof chain resolution
|
|
987
|
-
// -----------------------------------------------------------------------
|
|
988
|
-
/**
|
|
989
|
-
* Resolve and verify the proof chain for a token payload.
|
|
990
|
-
*
|
|
991
|
-
* Walks back through `prf` references, checking attenuation invariants
|
|
992
|
-
* at each step.
|
|
993
|
-
*/
|
|
994
|
-
resolveChain(payload) {
|
|
995
|
-
if (payload.prf.length === 0) {
|
|
996
|
-
return {
|
|
997
|
-
links: [
|
|
998
|
-
{
|
|
999
|
-
tokenId: payload.nnc,
|
|
1000
|
-
issuer: payload.iss,
|
|
1001
|
-
audience: payload.aud,
|
|
1002
|
-
capabilities: payload.att,
|
|
1003
|
-
issuedAt: payload.nbf ?? Math.floor(Date.now() / 1e3),
|
|
1004
|
-
expiresAt: payload.exp
|
|
1005
|
-
}
|
|
1006
|
-
],
|
|
1007
|
-
rootAuthority: payload.iss,
|
|
1008
|
-
verified: true,
|
|
1009
|
-
verifiedAt: (/* @__PURE__ */ new Date()).toISOString()
|
|
1010
|
-
};
|
|
1011
|
-
}
|
|
1012
|
-
const links = [];
|
|
1013
|
-
for (const proofNonce of payload.prf) {
|
|
1014
|
-
const parentToken = this.tokenStore.get(proofNonce);
|
|
1015
|
-
if (!parentToken) {
|
|
1016
|
-
return {
|
|
1017
|
-
links,
|
|
1018
|
-
rootAuthority: links.length > 0 ? links[0].issuer : payload.iss,
|
|
1019
|
-
verified: false
|
|
1020
|
-
};
|
|
1021
|
-
}
|
|
1022
|
-
links.push({
|
|
1023
|
-
tokenId: parentToken.payload.nnc,
|
|
1024
|
-
issuer: parentToken.payload.iss,
|
|
1025
|
-
audience: parentToken.payload.aud,
|
|
1026
|
-
capabilities: parentToken.payload.att,
|
|
1027
|
-
issuedAt: parentToken.payload.nbf ?? 0,
|
|
1028
|
-
expiresAt: parentToken.payload.exp
|
|
1029
|
-
});
|
|
1030
|
-
}
|
|
1031
|
-
links.push({
|
|
1032
|
-
tokenId: payload.nnc,
|
|
1033
|
-
issuer: payload.iss,
|
|
1034
|
-
audience: payload.aud,
|
|
1035
|
-
capabilities: payload.att,
|
|
1036
|
-
issuedAt: payload.nbf ?? 0,
|
|
1037
|
-
expiresAt: payload.exp
|
|
1038
|
-
});
|
|
1039
|
-
let chainValid = true;
|
|
1040
|
-
for (let i = 1; i < links.length; i++) {
|
|
1041
|
-
const parent = links[i - 1];
|
|
1042
|
-
const child = links[i];
|
|
1043
|
-
if (child.issuer !== parent.audience) {
|
|
1044
|
-
chainValid = false;
|
|
1045
|
-
break;
|
|
1046
|
-
}
|
|
1047
|
-
for (const childCap of child.capabilities) {
|
|
1048
|
-
const covered = parent.capabilities.some(
|
|
1049
|
-
(parentCap) => this.semantics.isSubsetOf(childCap, parentCap)
|
|
1050
|
-
);
|
|
1051
|
-
if (!covered) {
|
|
1052
|
-
chainValid = false;
|
|
1053
|
-
break;
|
|
1054
|
-
}
|
|
1055
|
-
}
|
|
1056
|
-
if (!chainValid) break;
|
|
1057
|
-
if (child.expiresAt > parent.expiresAt) {
|
|
1058
|
-
chainValid = false;
|
|
1059
|
-
break;
|
|
1060
|
-
}
|
|
1061
|
-
}
|
|
1062
|
-
return {
|
|
1063
|
-
links,
|
|
1064
|
-
rootAuthority: links[0].issuer,
|
|
1065
|
-
verified: chainValid,
|
|
1066
|
-
verifiedAt: chainValid ? (/* @__PURE__ */ new Date()).toISOString() : void 0
|
|
1067
|
-
};
|
|
1068
|
-
}
|
|
1069
|
-
// -----------------------------------------------------------------------
|
|
1070
|
-
// Convenience: issue from AgentRole
|
|
1071
|
-
// -----------------------------------------------------------------------
|
|
1072
|
-
/**
|
|
1073
|
-
* Issue a root capability token for a given AgentRole.
|
|
1074
|
-
*
|
|
1075
|
-
* Automatically maps role permissions to capabilities using the bridge
|
|
1076
|
-
* mappings defined in CapabilityToken.ts.
|
|
1077
|
-
*
|
|
1078
|
-
* @param role Agent role
|
|
1079
|
-
* @param audience Audience identifier
|
|
1080
|
-
* @param keyPair Ed25519 key pair
|
|
1081
|
-
* @param scope Optional resource scope restriction
|
|
1082
|
-
* @returns Signed root CapabilityToken
|
|
1083
|
-
*/
|
|
1084
|
-
async issueForRole(role, audience, keyPair, scope) {
|
|
1085
|
-
const permissions = getDefaultPermissions(role);
|
|
1086
|
-
const capabilities = permissions.map((perm) => this.semantics.fromPermission(perm, scope));
|
|
1087
|
-
const issuer = `agent:${role}`;
|
|
1088
|
-
return this.issueRoot(
|
|
1089
|
-
{
|
|
1090
|
-
issuer,
|
|
1091
|
-
audience,
|
|
1092
|
-
capabilities
|
|
1093
|
-
},
|
|
1094
|
-
keyPair
|
|
1095
|
-
);
|
|
1096
|
-
}
|
|
1097
|
-
// -----------------------------------------------------------------------
|
|
1098
|
-
// Capability query
|
|
1099
|
-
// -----------------------------------------------------------------------
|
|
1100
|
-
/**
|
|
1101
|
-
* Check whether a token grants access to a specific resource + action.
|
|
1102
|
-
*
|
|
1103
|
-
* Does NOT verify the signature — call `verify()` first if the token
|
|
1104
|
-
* has not been verified yet.
|
|
1105
|
-
*/
|
|
1106
|
-
hasCapability(token, resource, action) {
|
|
1107
|
-
return token.payload.att.some((cap) => this.semantics.canAccess(cap, resource, action));
|
|
1108
|
-
}
|
|
1109
|
-
// -----------------------------------------------------------------------
|
|
1110
|
-
// Store management
|
|
1111
|
-
// -----------------------------------------------------------------------
|
|
1112
|
-
/**
|
|
1113
|
-
* Retrieve a stored token by its nonce (for proof resolution).
|
|
1114
|
-
*/
|
|
1115
|
-
getStoredToken(nonce) {
|
|
1116
|
-
return this.tokenStore.get(nonce);
|
|
1117
|
-
}
|
|
1118
|
-
/**
|
|
1119
|
-
* Store an externally-created token (e.g. received from another agent).
|
|
1120
|
-
*/
|
|
1121
|
-
storeToken(token) {
|
|
1122
|
-
this.tokenStore.set(token.payload.nnc, token);
|
|
1123
|
-
}
|
|
1124
|
-
/**
|
|
1125
|
-
* Clear all stored tokens and nonces (for testing).
|
|
1126
|
-
*/
|
|
1127
|
-
reset() {
|
|
1128
|
-
this.tokenStore.clear();
|
|
1129
|
-
this.usedNonces.clear();
|
|
1130
|
-
}
|
|
1131
|
-
/**
|
|
1132
|
-
* Get the semantics engine used by this issuer.
|
|
1133
|
-
*/
|
|
1134
|
-
getSemantics() {
|
|
1135
|
-
return this.semantics;
|
|
1136
|
-
}
|
|
1137
|
-
};
|
|
1138
|
-
globalCapabilityIssuer = null;
|
|
1139
|
-
}
|
|
1140
|
-
});
|
|
1141
|
-
function getTokenIssuer(config) {
|
|
1142
|
-
if (!globalIssuer) {
|
|
1143
|
-
globalIssuer = new AgentTokenIssuer({
|
|
1144
|
-
...config,
|
|
1145
|
-
jwtSecret: process.env.AGENT_JWT_SECRET
|
|
1146
|
-
});
|
|
1147
|
-
}
|
|
1148
|
-
return globalIssuer;
|
|
1149
|
-
}
|
|
1150
|
-
var DEFAULT_ISSUER, DEFAULT_JWT_SECRET, DEFAULT_TOKEN_EXPIRATION, AgentTokenIssuer, globalIssuer;
|
|
1151
|
-
var init_AgentTokenIssuer = __esm({
|
|
1152
|
-
"src/compiler/identity/AgentTokenIssuer.ts"() {
|
|
1153
|
-
init_AgentIdentity();
|
|
1154
|
-
init_AgentKeystore();
|
|
1155
|
-
init_CapabilityToken();
|
|
1156
|
-
init_CapabilityTokenIssuer();
|
|
1157
|
-
DEFAULT_ISSUER = "holoscript-orchestrator";
|
|
1158
|
-
DEFAULT_JWT_SECRET = process.env.AGENT_JWT_SECRET || "dev-secret-change-in-production";
|
|
1159
|
-
DEFAULT_TOKEN_EXPIRATION = "24h";
|
|
1160
|
-
AgentTokenIssuer = class {
|
|
1161
|
-
constructor(config = {}) {
|
|
1162
|
-
/** Active workflow state (for validation) */
|
|
1163
|
-
this.workflowState = /* @__PURE__ */ new Map();
|
|
1164
|
-
this.issuer = config.issuer || DEFAULT_ISSUER;
|
|
1165
|
-
this.jwtSecret = config.jwtSecret || DEFAULT_JWT_SECRET;
|
|
1166
|
-
this.tokenExpiration = config.tokenExpiration || DEFAULT_TOKEN_EXPIRATION;
|
|
1167
|
-
this.strictWorkflowValidation = config.strictWorkflowValidation ?? true;
|
|
1168
|
-
if (this.jwtSecret === DEFAULT_JWT_SECRET && process.env.NODE_ENV === "production") {
|
|
1169
|
-
console.error(
|
|
1170
|
-
"[TOKEN_ISSUER] Using default JWT secret in production! Set AGENT_JWT_SECRET environment variable."
|
|
1171
|
-
);
|
|
1172
|
-
}
|
|
1173
|
-
}
|
|
1174
|
-
/**
|
|
1175
|
-
* Issue intent token for agent
|
|
1176
|
-
*
|
|
1177
|
-
* Creates a signed JWT with:
|
|
1178
|
-
* - Standard claims (iss, sub, aud, exp, iat, jti)
|
|
1179
|
-
* - Agent identity (role, checksum)
|
|
1180
|
-
* - Permissions (RBAC)
|
|
1181
|
-
* - Intent metadata (workflow context)
|
|
1182
|
-
* - PoP binding (JWK thumbprint)
|
|
1183
|
-
*/
|
|
1184
|
-
async issueToken(request) {
|
|
1185
|
-
const {
|
|
1186
|
-
agentConfig,
|
|
1187
|
-
workflowStep,
|
|
1188
|
-
workflowId,
|
|
1189
|
-
initiatedBy,
|
|
1190
|
-
delegationChain = [],
|
|
1191
|
-
executionContext = {},
|
|
1192
|
-
keyPair
|
|
1193
|
-
} = request;
|
|
1194
|
-
if (this.strictWorkflowValidation) {
|
|
1195
|
-
const currentStep = this.workflowState.get(workflowId);
|
|
1196
|
-
if (currentStep && !isValidWorkflowTransition(currentStep, workflowStep)) {
|
|
1197
|
-
throw new Error(
|
|
1198
|
-
`Invalid workflow transition: ${currentStep} \u2192 ${workflowStep} in workflow ${workflowId}`
|
|
1199
|
-
);
|
|
1200
|
-
}
|
|
1201
|
-
}
|
|
1202
|
-
const agentChecksum = calculateAgentChecksum(agentConfig);
|
|
1203
|
-
const permissions = getDefaultPermissions(agentConfig.role);
|
|
1204
|
-
const updatedDelegationChain = [...delegationChain, agentConfig.role];
|
|
1205
|
-
const now = Math.floor(Date.now() / 1e3);
|
|
1206
|
-
const payload = {
|
|
1207
|
-
// Standard JWT claims
|
|
1208
|
-
iss: this.issuer,
|
|
1209
|
-
sub: `agent:${agentConfig.role}:${agentConfig.name}`,
|
|
1210
|
-
aud: "holoscript-compiler",
|
|
1211
|
-
exp: typeof this.tokenExpiration === "string" ? now + this.parseExpiration(this.tokenExpiration) : now + this.tokenExpiration,
|
|
1212
|
-
iat: now,
|
|
1213
|
-
jti: crypto3.randomUUID(),
|
|
1214
|
-
// Agent-specific claims
|
|
1215
|
-
agent_role: agentConfig.role,
|
|
1216
|
-
agent_checksum: agentChecksum,
|
|
1217
|
-
permissions,
|
|
1218
|
-
scope: agentConfig.scope,
|
|
1219
|
-
// Intent claims
|
|
1220
|
-
intent: {
|
|
1221
|
-
workflow_id: workflowId,
|
|
1222
|
-
workflow_step: workflowStep,
|
|
1223
|
-
executed_by: agentConfig.role,
|
|
1224
|
-
initiated_by: initiatedBy,
|
|
1225
|
-
delegation_chain: updatedDelegationChain,
|
|
1226
|
-
execution_context: executionContext
|
|
1227
|
-
},
|
|
1228
|
-
// Proof-of-Possession (PoP) confirmation
|
|
1229
|
-
cnf: {
|
|
1230
|
-
jkt: keyPair.thumbprint
|
|
1231
|
-
},
|
|
1232
|
-
// Ed25519 public key for HTTP Message Signature verification
|
|
1233
|
-
publicKey: keyPair.publicKey
|
|
1234
|
-
};
|
|
1235
|
-
const token = jwt.sign(payload, this.jwtSecret, {
|
|
1236
|
-
algorithm: "HS256"
|
|
1237
|
-
});
|
|
1238
|
-
this.workflowState.set(workflowId, workflowStep);
|
|
1239
|
-
const keystore = getKeystore();
|
|
1240
|
-
await keystore.storeCredential({
|
|
1241
|
-
role: agentConfig.role,
|
|
1242
|
-
token,
|
|
1243
|
-
keyPair,
|
|
1244
|
-
createdAt: new Date(now * 1e3),
|
|
1245
|
-
expiresAt: new Date(payload.exp * 1e3)
|
|
1246
|
-
});
|
|
1247
|
-
return token;
|
|
1248
|
-
}
|
|
1249
|
-
/**
|
|
1250
|
-
* Verify agent token
|
|
1251
|
-
*
|
|
1252
|
-
* Validates:
|
|
1253
|
-
* - Signature authenticity
|
|
1254
|
-
* - Token expiration
|
|
1255
|
-
* - Claims structure
|
|
1256
|
-
* - Workflow step sequence (if strict mode)
|
|
1257
|
-
*/
|
|
1258
|
-
verifyToken(token) {
|
|
1259
|
-
try {
|
|
1260
|
-
const decoded = jwt.verify(token, this.jwtSecret, {
|
|
1261
|
-
issuer: this.issuer,
|
|
1262
|
-
audience: "holoscript-compiler"
|
|
1263
|
-
});
|
|
1264
|
-
if (!decoded.agent_role || !decoded.agent_checksum || !decoded.intent) {
|
|
1265
|
-
return {
|
|
1266
|
-
valid: false,
|
|
1267
|
-
error: "Missing required claims",
|
|
1268
|
-
errorCode: "INVALID_CLAIMS"
|
|
1269
|
-
};
|
|
1270
|
-
}
|
|
1271
|
-
if (this.strictWorkflowValidation) {
|
|
1272
|
-
const currentStep = this.workflowState.get(decoded.intent.workflow_id);
|
|
1273
|
-
if (currentStep && currentStep !== decoded.intent.workflow_step) {
|
|
1274
|
-
return {
|
|
1275
|
-
valid: false,
|
|
1276
|
-
error: `Workflow step mismatch: expected ${currentStep}, got ${decoded.intent.workflow_step}`,
|
|
1277
|
-
errorCode: "WORKFLOW_VIOLATION"
|
|
1278
|
-
};
|
|
1279
|
-
}
|
|
1280
|
-
}
|
|
1281
|
-
return {
|
|
1282
|
-
valid: true,
|
|
1283
|
-
payload: decoded
|
|
1284
|
-
};
|
|
1285
|
-
} catch (error) {
|
|
1286
|
-
if (error instanceof Error && error.name === "TokenExpiredError") {
|
|
1287
|
-
return {
|
|
1288
|
-
valid: false,
|
|
1289
|
-
error: "Token expired",
|
|
1290
|
-
errorCode: "EXPIRED"
|
|
1291
|
-
};
|
|
1292
|
-
} else if (error instanceof Error && error.name === "JsonWebTokenError") {
|
|
1293
|
-
return {
|
|
1294
|
-
valid: false,
|
|
1295
|
-
error: "Invalid signature or malformed token",
|
|
1296
|
-
errorCode: "INVALID_SIGNATURE"
|
|
1297
|
-
};
|
|
1298
|
-
}
|
|
1299
|
-
return {
|
|
1300
|
-
valid: false,
|
|
1301
|
-
error: error instanceof Error ? error.message : String(error),
|
|
1302
|
-
errorCode: "INVALID_CLAIMS"
|
|
1303
|
-
};
|
|
1304
|
-
}
|
|
1305
|
-
}
|
|
1306
|
-
/**
|
|
1307
|
-
* Extract token from Authorization header
|
|
1308
|
-
*/
|
|
1309
|
-
extractToken(authHeader) {
|
|
1310
|
-
if (!authHeader) return null;
|
|
1311
|
-
if (authHeader.startsWith("Bearer ")) {
|
|
1312
|
-
return authHeader.substring(7);
|
|
1313
|
-
}
|
|
1314
|
-
return authHeader;
|
|
1315
|
-
}
|
|
1316
|
-
/**
|
|
1317
|
-
* Verify agent has required permission
|
|
1318
|
-
*/
|
|
1319
|
-
hasPermission(token, required) {
|
|
1320
|
-
const result = this.verifyToken(token);
|
|
1321
|
-
if (!result.valid || !result.payload) return false;
|
|
1322
|
-
return result.payload.permissions.includes(required);
|
|
1323
|
-
}
|
|
1324
|
-
/**
|
|
1325
|
-
* Check if agent can perform operation
|
|
1326
|
-
*/
|
|
1327
|
-
canPerformOperation(token, requiredPermission, expectedWorkflowStep) {
|
|
1328
|
-
const result = this.verifyToken(token);
|
|
1329
|
-
if (!result.valid || !result.payload) return false;
|
|
1330
|
-
if (!result.payload.permissions.includes(requiredPermission)) {
|
|
1331
|
-
return false;
|
|
1332
|
-
}
|
|
1333
|
-
if (expectedWorkflowStep && result.payload.intent.workflow_step !== expectedWorkflowStep) {
|
|
1334
|
-
return false;
|
|
1335
|
-
}
|
|
1336
|
-
return true;
|
|
1337
|
-
}
|
|
1338
|
-
// ---------------------------------------------------------------------------
|
|
1339
|
-
// UCAN Capability Token Methods (migration bridge)
|
|
1340
|
-
// ---------------------------------------------------------------------------
|
|
1341
|
-
/**
|
|
1342
|
-
* Issue a UCAN capability token for an agent.
|
|
1343
|
-
*
|
|
1344
|
-
* Maps the agent's role to capabilities using the PERMISSION_TO_ACTION bridge
|
|
1345
|
-
* constants defined in CapabilityToken.ts. This enables agents that currently
|
|
1346
|
-
* use JWT tokens to obtain equivalent UCAN capability tokens for the gradual
|
|
1347
|
-
* migration to capability-based authorization.
|
|
1348
|
-
*
|
|
1349
|
-
* @param options Capability token issuance options
|
|
1350
|
-
* @returns Signed UCAN CapabilityToken
|
|
1351
|
-
*/
|
|
1352
|
-
async issueCapabilityToken(options) {
|
|
1353
|
-
const { agentConfig, audience, keyPair, scope, lifetimeSec, facts } = options;
|
|
1354
|
-
const capIssuer = this.getCapabilityTokenIssuer();
|
|
1355
|
-
const permissions = getDefaultPermissions(agentConfig.role);
|
|
1356
|
-
const capabilities = permissions.map((perm) => {
|
|
1357
|
-
const action = PERMISSION_TO_ACTION[perm] || perm;
|
|
1358
|
-
const resource = scope ? `${HOLOSCRIPT_RESOURCE_SCHEME}${scope}` : HOLOSCRIPT_RESOURCE_ALL;
|
|
1359
|
-
return { with: resource, can: action };
|
|
1360
|
-
});
|
|
1361
|
-
const issuer = `agent:${agentConfig.role}:${agentConfig.name}`;
|
|
1362
|
-
return capIssuer.issueRoot(
|
|
1363
|
-
{
|
|
1364
|
-
issuer,
|
|
1365
|
-
audience,
|
|
1366
|
-
capabilities,
|
|
1367
|
-
lifetimeSec,
|
|
1368
|
-
facts: {
|
|
1369
|
-
...facts,
|
|
1370
|
-
agent_version: agentConfig.version,
|
|
1371
|
-
agent_role: agentConfig.role
|
|
1372
|
-
}
|
|
1373
|
-
},
|
|
1374
|
-
keyPair
|
|
1375
|
-
);
|
|
1376
|
-
}
|
|
1377
|
-
/**
|
|
1378
|
-
* Issue both a JWT token and a UCAN capability token for the same agent
|
|
1379
|
-
* and intent context.
|
|
1380
|
-
*
|
|
1381
|
-
* This method enables gradual migration from JWT-only authorization to
|
|
1382
|
-
* UCAN capability-based authorization. Consuming services can validate
|
|
1383
|
-
* either token during the transition period.
|
|
1384
|
-
*
|
|
1385
|
-
* @param request Standard JWT token request parameters
|
|
1386
|
-
* @param capabilityOptions Additional options for the capability token
|
|
1387
|
-
* (audience defaults to 'holoscript-compiler')
|
|
1388
|
-
* @returns HybridTokenResult with both tokens
|
|
1389
|
-
*/
|
|
1390
|
-
async issueHybridToken(request, capabilityOptions) {
|
|
1391
|
-
const jwtToken = await this.issueToken(request);
|
|
1392
|
-
const audience = capabilityOptions?.audience ?? "holoscript-compiler";
|
|
1393
|
-
const capabilityToken = await this.issueCapabilityToken({
|
|
1394
|
-
agentConfig: request.agentConfig,
|
|
1395
|
-
audience,
|
|
1396
|
-
keyPair: request.keyPair,
|
|
1397
|
-
scope: capabilityOptions?.scope ?? request.agentConfig.scope,
|
|
1398
|
-
lifetimeSec: capabilityOptions?.lifetimeSec,
|
|
1399
|
-
facts: {
|
|
1400
|
-
...capabilityOptions?.facts,
|
|
1401
|
-
workflow_id: request.workflowId,
|
|
1402
|
-
workflow_step: request.workflowStep,
|
|
1403
|
-
initiated_by: request.initiatedBy
|
|
1404
|
-
}
|
|
1405
|
-
});
|
|
1406
|
-
const permissions = getDefaultPermissions(request.agentConfig.role);
|
|
1407
|
-
const scope = capabilityOptions?.scope ?? request.agentConfig.scope;
|
|
1408
|
-
const capabilities = permissions.map((perm) => {
|
|
1409
|
-
const action = PERMISSION_TO_ACTION[perm] || perm;
|
|
1410
|
-
const resource = scope ? `${HOLOSCRIPT_RESOURCE_SCHEME}${scope}` : HOLOSCRIPT_RESOURCE_ALL;
|
|
1411
|
-
return { with: resource, can: action };
|
|
1412
|
-
});
|
|
1413
|
-
return {
|
|
1414
|
-
jwt: jwtToken,
|
|
1415
|
-
capabilityToken,
|
|
1416
|
-
agentRole: request.agentConfig.role,
|
|
1417
|
-
capabilities,
|
|
1418
|
-
issuedAt: Math.floor(Date.now() / 1e3)
|
|
1419
|
-
};
|
|
1420
|
-
}
|
|
1421
|
-
/**
|
|
1422
|
-
* Delegate (attenuate) an existing UCAN capability token to a target agent.
|
|
1423
|
-
*
|
|
1424
|
-
* Creates a new UCAN token with a subset of the parent token's capabilities,
|
|
1425
|
-
* enforcing UCAN attenuation invariants:
|
|
1426
|
-
* - Every capability in the child MUST be a subset of the parent's capabilities
|
|
1427
|
-
* - Child expiration MUST NOT exceed parent expiration
|
|
1428
|
-
* - Delegation depth MUST NOT exceed the configured maximum
|
|
1429
|
-
*
|
|
1430
|
-
* @param parentToken The parent UCAN capability token to delegate from
|
|
1431
|
-
* @param targetDID DID or agent identifier of the delegatee
|
|
1432
|
-
* @param attenuatedCapabilities Capabilities to grant (must be subsets of parent)
|
|
1433
|
-
* @param keyPair Delegator's Ed25519 key pair for signing
|
|
1434
|
-
* @param lifetimeSec Optional lifetime in seconds
|
|
1435
|
-
* @param facts Optional metadata
|
|
1436
|
-
* @returns New signed CapabilityToken (attenuated delegation)
|
|
1437
|
-
* @throws Error if attenuation invariants are violated
|
|
1438
|
-
*/
|
|
1439
|
-
async delegateCapability(parentToken, targetDID, attenuatedCapabilities, keyPair, lifetimeSec, facts) {
|
|
1440
|
-
const capIssuer = this.getCapabilityTokenIssuer();
|
|
1441
|
-
capIssuer.storeToken(parentToken);
|
|
1442
|
-
if (!keyPair) {
|
|
1443
|
-
throw new Error(
|
|
1444
|
-
"A key pair is required to sign the delegated capability token. Pass the delegator's AgentKeyPair."
|
|
1445
|
-
);
|
|
1446
|
-
}
|
|
1447
|
-
return capIssuer.delegate(
|
|
1448
|
-
{
|
|
1449
|
-
parentToken,
|
|
1450
|
-
audience: targetDID,
|
|
1451
|
-
capabilities: attenuatedCapabilities,
|
|
1452
|
-
lifetimeSec,
|
|
1453
|
-
facts
|
|
1454
|
-
},
|
|
1455
|
-
keyPair
|
|
1456
|
-
);
|
|
1457
|
-
}
|
|
1458
|
-
// ---------------------------------------------------------------------------
|
|
1459
|
-
// Internal helpers
|
|
1460
|
-
// ---------------------------------------------------------------------------
|
|
1461
|
-
/**
|
|
1462
|
-
* Get or create the CapabilityTokenIssuer instance used by this issuer.
|
|
1463
|
-
* @internal
|
|
1464
|
-
*/
|
|
1465
|
-
getCapabilityTokenIssuer() {
|
|
1466
|
-
return getCapabilityTokenIssuer();
|
|
1467
|
-
}
|
|
1468
|
-
/**
|
|
1469
|
-
* Get workflow state
|
|
1470
|
-
*/
|
|
1471
|
-
getWorkflowState(workflowId) {
|
|
1472
|
-
return this.workflowState.get(workflowId);
|
|
1473
|
-
}
|
|
1474
|
-
/**
|
|
1475
|
-
* Reset workflow state (for testing)
|
|
1476
|
-
*/
|
|
1477
|
-
resetWorkflowState(workflowId) {
|
|
1478
|
-
if (workflowId) {
|
|
1479
|
-
this.workflowState.delete(workflowId);
|
|
1480
|
-
} else {
|
|
1481
|
-
this.workflowState.clear();
|
|
1482
|
-
}
|
|
1483
|
-
}
|
|
1484
|
-
/**
|
|
1485
|
-
* Parse expiration string (e.g., '24h', '7d')
|
|
1486
|
-
*/
|
|
1487
|
-
parseExpiration(exp) {
|
|
1488
|
-
const match = exp.match(/^(\d+)([smhd])$/);
|
|
1489
|
-
if (!match) {
|
|
1490
|
-
throw new Error(`Invalid expiration format: ${exp}`);
|
|
1491
|
-
}
|
|
1492
|
-
const value = parseInt(match[1], 10);
|
|
1493
|
-
const unit = match[2];
|
|
1494
|
-
const multipliers = {
|
|
1495
|
-
s: 1,
|
|
1496
|
-
m: 60,
|
|
1497
|
-
h: 60 * 60,
|
|
1498
|
-
d: 60 * 60 * 24
|
|
1499
|
-
};
|
|
1500
|
-
return value * multipliers[unit];
|
|
1501
|
-
}
|
|
1502
|
-
};
|
|
1503
|
-
globalIssuer = null;
|
|
1504
|
-
}
|
|
1505
|
-
});
|
|
1506
|
-
|
|
1507
|
-
// src/compiler/CulturalCompatibilityChecker.ts
|
|
1508
|
-
var DEFAULT_CONFIG, CODES, CulturalCompatibilityChecker;
|
|
1509
|
-
var init_CulturalCompatibilityChecker = __esm({
|
|
1510
|
-
"src/compiler/CulturalCompatibilityChecker.ts"() {
|
|
1511
|
-
init_CultureTraits();
|
|
1512
|
-
DEFAULT_CONFIG = {
|
|
1513
|
-
cooperationThreshold: 0.5,
|
|
1514
|
-
checkDialects: true,
|
|
1515
|
-
validateNormReferences: true,
|
|
1516
|
-
warnOnCautious: true
|
|
1517
|
-
};
|
|
1518
|
-
CODES = {
|
|
1519
|
-
COOPERATION_OUT_OF_RANGE: "CULT001",
|
|
1520
|
-
COOPERATION_MISMATCH: "CULT002",
|
|
1521
|
-
FAMILY_INCOMPATIBLE: "CULT003",
|
|
1522
|
-
FAMILY_CAUTIOUS: "CULT004",
|
|
1523
|
-
DIALECT_MISMATCH: "CULT005",
|
|
1524
|
-
NORM_CONTRADICTION: "CULT006",
|
|
1525
|
-
NORM_UNKNOWN: "CULT007"
|
|
1526
|
-
};
|
|
1527
|
-
CulturalCompatibilityChecker = class {
|
|
1528
|
-
constructor(config) {
|
|
1529
|
-
this.config = { ...DEFAULT_CONFIG, ...config };
|
|
1530
|
-
}
|
|
1531
|
-
/**
|
|
1532
|
-
* Update checker configuration.
|
|
1533
|
-
*/
|
|
1534
|
-
setConfig(config) {
|
|
1535
|
-
this.config = { ...this.config, ...config };
|
|
1536
|
-
}
|
|
1537
|
-
/**
|
|
1538
|
-
* Get current checker configuration.
|
|
1539
|
-
*/
|
|
1540
|
-
getConfig() {
|
|
1541
|
-
return { ...this.config };
|
|
1542
|
-
}
|
|
1543
|
-
/**
|
|
1544
|
-
* Check cultural compatibility of a set of agents in a composition.
|
|
1545
|
-
*
|
|
1546
|
-
* Performs pairwise checks across all four dimensions:
|
|
1547
|
-
* 1. Validates individual profiles (cooperation_index range, norm references)
|
|
1548
|
-
* 2. Checks cooperation_index deltas between all pairs
|
|
1549
|
-
* 3. Checks cultural_family compatibility between all pairs
|
|
1550
|
-
* 4. Checks prompt_dialect compatibility between all pairs
|
|
1551
|
-
* 5. Checks for contradictory norms across the full composition
|
|
1552
|
-
*
|
|
1553
|
-
* @param agents Array of agent entries with their cultural profiles
|
|
1554
|
-
* @returns Complete compatibility result with diagnostics
|
|
1555
|
-
*/
|
|
1556
|
-
check(agents) {
|
|
1557
|
-
const diagnostics = [];
|
|
1558
|
-
for (const agent of agents) {
|
|
1559
|
-
diagnostics.push(...this.validateProfile(agent));
|
|
1560
|
-
}
|
|
1561
|
-
let pairsChecked = 0;
|
|
1562
|
-
for (let i = 0; i < agents.length; i++) {
|
|
1563
|
-
for (let j = i + 1; j < agents.length; j++) {
|
|
1564
|
-
const a = agents[i];
|
|
1565
|
-
const b = agents[j];
|
|
1566
|
-
pairsChecked++;
|
|
1567
|
-
diagnostics.push(...this.checkCooperationIndex(a, b));
|
|
1568
|
-
diagnostics.push(...this.checkCulturalFamily(a, b));
|
|
1569
|
-
if (this.config.checkDialects) {
|
|
1570
|
-
diagnostics.push(...this.checkPromptDialect(a, b));
|
|
1571
|
-
}
|
|
1572
|
-
}
|
|
1573
|
-
}
|
|
1574
|
-
diagnostics.push(...this.checkNormContradictions(agents));
|
|
1575
|
-
const errors = diagnostics.filter((d) => d.severity === "error");
|
|
1576
|
-
const warnings = diagnostics.filter((d) => d.severity === "warning");
|
|
1577
|
-
return {
|
|
1578
|
-
compatible: errors.length === 0,
|
|
1579
|
-
diagnostics,
|
|
1580
|
-
errors,
|
|
1581
|
-
warnings,
|
|
1582
|
-
pairsChecked
|
|
1583
|
-
};
|
|
1584
|
-
}
|
|
1585
|
-
/**
|
|
1586
|
-
* Quick check — returns true if the composition is compatible (no errors).
|
|
1587
|
-
* Use `check()` for full diagnostics.
|
|
1588
|
-
*/
|
|
1589
|
-
isCompatible(agents) {
|
|
1590
|
-
return this.check(agents).compatible;
|
|
1591
|
-
}
|
|
1592
|
-
// ===========================================================================
|
|
1593
|
-
// INDIVIDUAL PROFILE VALIDATION
|
|
1594
|
-
// ===========================================================================
|
|
1595
|
-
validateProfile(agent) {
|
|
1596
|
-
const diagnostics = [];
|
|
1597
|
-
const { profile, name } = agent;
|
|
1598
|
-
if (profile.cooperation_index < 0 || profile.cooperation_index > 1) {
|
|
1599
|
-
diagnostics.push({
|
|
1600
|
-
code: CODES.COOPERATION_OUT_OF_RANGE,
|
|
1601
|
-
severity: "error",
|
|
1602
|
-
category: "cooperation_out_of_range",
|
|
1603
|
-
message: `Agent "${name}" has cooperation_index ${profile.cooperation_index} which is outside the valid range [0, 1].`,
|
|
1604
|
-
agents: [name, name],
|
|
1605
|
-
suggestion: "Set cooperation_index to a value between 0.0 and 1.0."
|
|
1606
|
-
});
|
|
1607
|
-
}
|
|
1608
|
-
if (this.config.validateNormReferences) {
|
|
1609
|
-
const builtinIds = new Set(BUILTIN_NORMS.map((n) => n.id));
|
|
1610
|
-
for (const normId of profile.norm_set) {
|
|
1611
|
-
if (!builtinIds.has(normId)) {
|
|
1612
|
-
diagnostics.push({
|
|
1613
|
-
code: CODES.NORM_UNKNOWN,
|
|
1614
|
-
severity: "warning",
|
|
1615
|
-
category: "norm_unknown",
|
|
1616
|
-
message: `Agent "${name}" references unknown norm "${normId}". It may be a custom norm not yet registered.`,
|
|
1617
|
-
agents: [name, name],
|
|
1618
|
-
suggestion: `Register the norm "${normId}" via BUILTIN_NORMS or ensure it exists in your custom norm registry.`
|
|
1619
|
-
});
|
|
1620
|
-
}
|
|
1621
|
-
}
|
|
1622
|
-
}
|
|
1623
|
-
return diagnostics;
|
|
1624
|
-
}
|
|
1625
|
-
// ===========================================================================
|
|
1626
|
-
// COOPERATION INDEX CHECK
|
|
1627
|
-
// ===========================================================================
|
|
1628
|
-
checkCooperationIndex(a, b) {
|
|
1629
|
-
const delta = Math.abs(a.profile.cooperation_index - b.profile.cooperation_index);
|
|
1630
|
-
if (delta > this.config.cooperationThreshold) {
|
|
1631
|
-
return [
|
|
1632
|
-
{
|
|
1633
|
-
code: CODES.COOPERATION_MISMATCH,
|
|
1634
|
-
severity: "error",
|
|
1635
|
-
category: "cooperation_mismatch",
|
|
1636
|
-
message: `Agents "${a.name}" (cooperation_index: ${a.profile.cooperation_index}) and "${b.name}" (cooperation_index: ${b.profile.cooperation_index}) have a cooperation delta of ${delta.toFixed(2)} which exceeds the threshold of ${this.config.cooperationThreshold}. These agents are unlikely to cooperate effectively.`,
|
|
1637
|
-
agents: [a.name, b.name],
|
|
1638
|
-
suggestion: `Adjust cooperation_index values to be within ${this.config.cooperationThreshold} of each other, or add a mediator agent with a middle cooperation_index.`
|
|
1639
|
-
}
|
|
1640
|
-
];
|
|
1641
|
-
}
|
|
1642
|
-
return [];
|
|
1643
|
-
}
|
|
1644
|
-
// ===========================================================================
|
|
1645
|
-
// CULTURAL FAMILY CHECK
|
|
1646
|
-
// ===========================================================================
|
|
1647
|
-
checkCulturalFamily(a, b) {
|
|
1648
|
-
const { rating, reason } = getFamilyCompatibility(
|
|
1649
|
-
a.profile.cultural_family,
|
|
1650
|
-
b.profile.cultural_family
|
|
1651
|
-
);
|
|
1652
|
-
if (rating === "incompatible") {
|
|
1653
|
-
return [
|
|
1654
|
-
{
|
|
1655
|
-
code: CODES.FAMILY_INCOMPATIBLE,
|
|
1656
|
-
severity: "error",
|
|
1657
|
-
category: "family_incompatible",
|
|
1658
|
-
message: `Agents "${a.name}" (family: ${a.profile.cultural_family}) and "${b.name}" (family: ${b.profile.cultural_family}) belong to incompatible cultural families. ` + reason,
|
|
1659
|
-
agents: [a.name, b.name],
|
|
1660
|
-
suggestion: `Change one agent's cultural_family to a compatible type, or separate them into different compositions/zones.`
|
|
1661
|
-
}
|
|
1662
|
-
];
|
|
1663
|
-
}
|
|
1664
|
-
if (rating === "cautious" && this.config.warnOnCautious) {
|
|
1665
|
-
return [
|
|
1666
|
-
{
|
|
1667
|
-
code: CODES.FAMILY_CAUTIOUS,
|
|
1668
|
-
severity: "warning",
|
|
1669
|
-
category: "family_cautious",
|
|
1670
|
-
message: `Agents "${a.name}" (family: ${a.profile.cultural_family}) and "${b.name}" (family: ${b.profile.cultural_family}) have cautious cultural compatibility. ` + reason,
|
|
1671
|
-
agents: [a.name, b.name],
|
|
1672
|
-
suggestion: "Consider adding a mediator agent or defining explicit interaction protocols."
|
|
1673
|
-
}
|
|
1674
|
-
];
|
|
1675
|
-
}
|
|
1676
|
-
return [];
|
|
1677
|
-
}
|
|
1678
|
-
// ===========================================================================
|
|
1679
|
-
// PROMPT DIALECT CHECK
|
|
1680
|
-
// ===========================================================================
|
|
1681
|
-
checkPromptDialect(a, b) {
|
|
1682
|
-
if (a.profile.prompt_dialect !== b.profile.prompt_dialect) {
|
|
1683
|
-
return [
|
|
1684
|
-
{
|
|
1685
|
-
code: CODES.DIALECT_MISMATCH,
|
|
1686
|
-
severity: "warning",
|
|
1687
|
-
category: "dialect_mismatch",
|
|
1688
|
-
message: `Agents "${a.name}" (dialect: ${a.profile.prompt_dialect}) and "${b.name}" (dialect: ${b.profile.prompt_dialect}) use different prompt dialects. Inter-agent communication may be less efficient.`,
|
|
1689
|
-
agents: [a.name, b.name],
|
|
1690
|
-
suggestion: "Align prompt_dialect values for agents that need frequent communication, or add a translator agent that bridges both dialects."
|
|
1691
|
-
}
|
|
1692
|
-
];
|
|
1693
|
-
}
|
|
1694
|
-
return [];
|
|
1695
|
-
}
|
|
1696
|
-
// ===========================================================================
|
|
1697
|
-
// NORM CONTRADICTION CHECK
|
|
1698
|
-
// ===========================================================================
|
|
1699
|
-
/**
|
|
1700
|
-
* Check for contradictory norms across the entire composition.
|
|
1701
|
-
* This is an N-way check (not just pairwise) because norms from
|
|
1702
|
-
* different agents can contradict each other.
|
|
1703
|
-
*/
|
|
1704
|
-
checkNormContradictions(agents) {
|
|
1705
|
-
const diagnostics = [];
|
|
1706
|
-
const contradictions = getAllContradictoryNorms();
|
|
1707
|
-
const normAgentMap = /* @__PURE__ */ new Map();
|
|
1708
|
-
for (const agent of agents) {
|
|
1709
|
-
for (const normId of agent.profile.norm_set) {
|
|
1710
|
-
if (!normAgentMap.has(normId)) {
|
|
1711
|
-
normAgentMap.set(normId, []);
|
|
1712
|
-
}
|
|
1713
|
-
normAgentMap.get(normId).push(agent.name);
|
|
1714
|
-
}
|
|
1715
|
-
}
|
|
1716
|
-
for (const { normA, normB, reason } of contradictions) {
|
|
1717
|
-
const agentsWithA = normAgentMap.get(normA) || [];
|
|
1718
|
-
const agentsWithB = normAgentMap.get(normB) || [];
|
|
1719
|
-
if (agentsWithA.length > 0 && agentsWithB.length > 0) {
|
|
1720
|
-
for (const agentA of agentsWithA) {
|
|
1721
|
-
for (const agentB of agentsWithB) {
|
|
1722
|
-
if (agentA !== agentB) {
|
|
1723
|
-
diagnostics.push({
|
|
1724
|
-
code: CODES.NORM_CONTRADICTION,
|
|
1725
|
-
severity: "error",
|
|
1726
|
-
category: "norm_contradiction",
|
|
1727
|
-
message: `Norm contradiction: agent "${agentA}" subscribes to "${normA}" and agent "${agentB}" subscribes to "${normB}". ${reason}`,
|
|
1728
|
-
agents: [agentA, agentB],
|
|
1729
|
-
suggestion: `Remove one of the contradictory norms, or separate agents "${agentA}" and "${agentB}" into different compositions.`
|
|
1730
|
-
});
|
|
1731
|
-
}
|
|
1732
|
-
if (agentA === agentB) {
|
|
1733
|
-
diagnostics.push({
|
|
1734
|
-
code: CODES.NORM_CONTRADICTION,
|
|
1735
|
-
severity: "error",
|
|
1736
|
-
category: "norm_contradiction",
|
|
1737
|
-
message: `Agent "${agentA}" subscribes to contradictory norms "${normA}" and "${normB}". ${reason}`,
|
|
1738
|
-
agents: [agentA, agentA],
|
|
1739
|
-
suggestion: `Remove one of the contradictory norms from agent "${agentA}".`
|
|
1740
|
-
});
|
|
1741
|
-
}
|
|
1742
|
-
}
|
|
1743
|
-
}
|
|
1744
|
-
}
|
|
1745
|
-
}
|
|
1746
|
-
return diagnostics;
|
|
1747
|
-
}
|
|
1748
|
-
};
|
|
1749
|
-
}
|
|
1750
|
-
});
|
|
1751
|
-
|
|
1752
|
-
// src/compiler/identity/ConfabulationValidator.ts
|
|
1753
|
-
function getConfabulationValidator(config) {
|
|
1754
|
-
if (!globalConfabulationValidator) {
|
|
1755
|
-
globalConfabulationValidator = new ConfabulationValidator(config);
|
|
1756
|
-
}
|
|
1757
|
-
return globalConfabulationValidator;
|
|
1758
|
-
}
|
|
1759
|
-
var BUILT_IN_TRAIT_SCHEMAS, ConfabulationValidator, globalConfabulationValidator;
|
|
1760
|
-
var init_ConfabulationValidator = __esm({
|
|
1761
|
-
"src/compiler/identity/ConfabulationValidator.ts"() {
|
|
1762
|
-
BUILT_IN_TRAIT_SCHEMAS = [
|
|
1763
|
-
// =========================================================================
|
|
1764
|
-
// INTERACTION TRAITS
|
|
1765
|
-
// =========================================================================
|
|
1766
|
-
{
|
|
1767
|
-
name: "grabbable",
|
|
1768
|
-
category: "interaction",
|
|
1769
|
-
properties: [
|
|
1770
|
-
{
|
|
1771
|
-
name: "snap_to_hand",
|
|
1772
|
-
type: "boolean",
|
|
1773
|
-
defaultValue: true,
|
|
1774
|
-
description: "Snap object to hand when grabbed"
|
|
1775
|
-
},
|
|
1776
|
-
{
|
|
1777
|
-
name: "two_handed",
|
|
1778
|
-
type: "boolean",
|
|
1779
|
-
defaultValue: false,
|
|
1780
|
-
description: "Require two hands to grab"
|
|
1781
|
-
},
|
|
1782
|
-
{
|
|
1783
|
-
name: "haptic_on_grab",
|
|
1784
|
-
type: "number",
|
|
1785
|
-
defaultValue: 0.5,
|
|
1786
|
-
min: 0,
|
|
1787
|
-
max: 1,
|
|
1788
|
-
description: "Haptic intensity on grab"
|
|
1789
|
-
},
|
|
1790
|
-
{
|
|
1791
|
-
name: "grab_points",
|
|
1792
|
-
type: "array",
|
|
1793
|
-
defaultValue: [],
|
|
1794
|
-
description: "Specific grab point positions"
|
|
1795
|
-
},
|
|
1796
|
-
{
|
|
1797
|
-
name: "preserve_rotation",
|
|
1798
|
-
type: "boolean",
|
|
1799
|
-
defaultValue: false,
|
|
1800
|
-
description: "Preserve rotation on grab"
|
|
1801
|
-
},
|
|
1802
|
-
{
|
|
1803
|
-
name: "highlight",
|
|
1804
|
-
type: "boolean",
|
|
1805
|
-
defaultValue: true,
|
|
1806
|
-
description: "Highlight when in grab range"
|
|
1807
|
-
}
|
|
1808
|
-
]
|
|
1809
|
-
},
|
|
1810
|
-
{
|
|
1811
|
-
name: "throwable",
|
|
1812
|
-
category: "interaction",
|
|
1813
|
-
requires: ["grabbable"],
|
|
1814
|
-
properties: [
|
|
1815
|
-
{
|
|
1816
|
-
name: "velocity_multiplier",
|
|
1817
|
-
type: "number",
|
|
1818
|
-
defaultValue: 1,
|
|
1819
|
-
min: 0,
|
|
1820
|
-
max: 100,
|
|
1821
|
-
description: "Multiplier for throw velocity"
|
|
1822
|
-
},
|
|
1823
|
-
{
|
|
1824
|
-
name: "gravity",
|
|
1825
|
-
type: "boolean",
|
|
1826
|
-
defaultValue: true,
|
|
1827
|
-
description: "Apply gravity after throw"
|
|
1828
|
-
},
|
|
1829
|
-
{
|
|
1830
|
-
name: "max_velocity",
|
|
1831
|
-
type: "number",
|
|
1832
|
-
defaultValue: 50,
|
|
1833
|
-
min: 0,
|
|
1834
|
-
description: "Maximum throw velocity"
|
|
1835
|
-
},
|
|
1836
|
-
{ name: "spin", type: "boolean", defaultValue: true, description: "Apply spin on throw" },
|
|
1837
|
-
{ name: "bounce", type: "boolean", defaultValue: false, description: "Bounce on impact" }
|
|
1838
|
-
]
|
|
1839
|
-
},
|
|
1840
|
-
{
|
|
1841
|
-
name: "holdable",
|
|
1842
|
-
category: "interaction",
|
|
1843
|
-
requires: ["grabbable"],
|
|
1844
|
-
properties: [
|
|
1845
|
-
{
|
|
1846
|
-
name: "offset",
|
|
1847
|
-
type: "array",
|
|
1848
|
-
defaultValue: [0, 0, 0],
|
|
1849
|
-
description: "Position offset when held"
|
|
1850
|
-
},
|
|
1851
|
-
{
|
|
1852
|
-
name: "rotation",
|
|
1853
|
-
type: "array",
|
|
1854
|
-
defaultValue: [0, 0, 0],
|
|
1855
|
-
description: "Rotation offset when held"
|
|
1856
|
-
}
|
|
1857
|
-
]
|
|
1858
|
-
},
|
|
1859
|
-
{
|
|
1860
|
-
name: "clickable",
|
|
1861
|
-
category: "interaction",
|
|
1862
|
-
properties: [
|
|
1863
|
-
{ name: "highlight", type: "boolean", defaultValue: true, description: "Highlight on hover" },
|
|
1864
|
-
{
|
|
1865
|
-
name: "debounce",
|
|
1866
|
-
type: "number",
|
|
1867
|
-
defaultValue: 200,
|
|
1868
|
-
min: 0,
|
|
1869
|
-
description: "Debounce time in ms"
|
|
1870
|
-
}
|
|
1871
|
-
]
|
|
1872
|
-
},
|
|
1873
|
-
{
|
|
1874
|
-
name: "hoverable",
|
|
1875
|
-
category: "interaction",
|
|
1876
|
-
properties: [
|
|
1877
|
-
{
|
|
1878
|
-
name: "highlight_color",
|
|
1879
|
-
type: "string",
|
|
1880
|
-
defaultValue: "#ffffff",
|
|
1881
|
-
description: "Color when hovered"
|
|
1882
|
-
},
|
|
1883
|
-
{
|
|
1884
|
-
name: "scale_on_hover",
|
|
1885
|
-
type: "number",
|
|
1886
|
-
defaultValue: 1.1,
|
|
1887
|
-
min: 0,
|
|
1888
|
-
description: "Scale multiplier on hover"
|
|
1889
|
-
},
|
|
1890
|
-
{
|
|
1891
|
-
name: "show_tooltip",
|
|
1892
|
-
type: "boolean",
|
|
1893
|
-
defaultValue: false,
|
|
1894
|
-
description: "Show tooltip on hover"
|
|
1895
|
-
},
|
|
1896
|
-
{
|
|
1897
|
-
name: "tooltip_offset",
|
|
1898
|
-
type: "array",
|
|
1899
|
-
defaultValue: [0, 0.2, 0],
|
|
1900
|
-
description: "Tooltip offset from object"
|
|
1901
|
-
},
|
|
1902
|
-
{ name: "glow", type: "boolean", defaultValue: false, description: "Glow effect on hover" }
|
|
1903
|
-
]
|
|
1904
|
-
},
|
|
1905
|
-
{
|
|
1906
|
-
name: "draggable",
|
|
1907
|
-
category: "interaction",
|
|
1908
|
-
properties: [
|
|
1909
|
-
{
|
|
1910
|
-
name: "axis",
|
|
1911
|
-
type: "enum",
|
|
1912
|
-
enumValues: ["x", "y", "z", "xy", "xz", "yz", "all"],
|
|
1913
|
-
defaultValue: "all",
|
|
1914
|
-
description: "Constrain to axis"
|
|
1915
|
-
},
|
|
1916
|
-
{ name: "bounds", type: "object", description: "Movement bounds" }
|
|
1917
|
-
]
|
|
1918
|
-
},
|
|
1919
|
-
{
|
|
1920
|
-
name: "pointable",
|
|
1921
|
-
category: "interaction",
|
|
1922
|
-
properties: [
|
|
1923
|
-
{
|
|
1924
|
-
name: "highlight_on_point",
|
|
1925
|
-
type: "boolean",
|
|
1926
|
-
defaultValue: true,
|
|
1927
|
-
description: "Highlight when pointed at"
|
|
1928
|
-
},
|
|
1929
|
-
{
|
|
1930
|
-
name: "highlight_color",
|
|
1931
|
-
type: "string",
|
|
1932
|
-
defaultValue: "#00ff00",
|
|
1933
|
-
description: "Highlight color"
|
|
1934
|
-
},
|
|
1935
|
-
{
|
|
1936
|
-
name: "cursor_style",
|
|
1937
|
-
type: "enum",
|
|
1938
|
-
enumValues: ["pointer", "crosshair", "grab", "default"],
|
|
1939
|
-
defaultValue: "pointer",
|
|
1940
|
-
description: "Cursor style"
|
|
1941
|
-
}
|
|
1942
|
-
]
|
|
1943
|
-
},
|
|
1944
|
-
{
|
|
1945
|
-
name: "scalable",
|
|
1946
|
-
category: "interaction",
|
|
1947
|
-
properties: [
|
|
1948
|
-
{
|
|
1949
|
-
name: "min_scale",
|
|
1950
|
-
type: "number",
|
|
1951
|
-
defaultValue: 0.1,
|
|
1952
|
-
min: 0,
|
|
1953
|
-
description: "Minimum scale"
|
|
1954
|
-
},
|
|
1955
|
-
{ name: "max_scale", type: "number", defaultValue: 10, min: 0, description: "Maximum scale" },
|
|
1956
|
-
{ name: "uniform", type: "boolean", defaultValue: true, description: "Uniform scaling" },
|
|
1957
|
-
{ name: "pivot", type: "array", defaultValue: [0, 0, 0], description: "Scale pivot point" }
|
|
1958
|
-
]
|
|
1959
|
-
},
|
|
1960
|
-
{
|
|
1961
|
-
name: "rotatable",
|
|
1962
|
-
category: "interaction",
|
|
1963
|
-
properties: [
|
|
1964
|
-
{
|
|
1965
|
-
name: "axis",
|
|
1966
|
-
type: "enum",
|
|
1967
|
-
enumValues: ["x", "y", "z", "all"],
|
|
1968
|
-
defaultValue: "all",
|
|
1969
|
-
description: "Rotation axis constraint"
|
|
1970
|
-
},
|
|
1971
|
-
{ name: "snap_angles", type: "array", defaultValue: [], description: "Snap rotation angles" },
|
|
1972
|
-
{
|
|
1973
|
-
name: "speed",
|
|
1974
|
-
type: "number",
|
|
1975
|
-
defaultValue: 1,
|
|
1976
|
-
min: 0,
|
|
1977
|
-
description: "Rotation speed multiplier"
|
|
1978
|
-
}
|
|
1979
|
-
]
|
|
1980
|
-
},
|
|
1981
|
-
{
|
|
1982
|
-
name: "snappable",
|
|
1983
|
-
category: "interaction",
|
|
1984
|
-
properties: [
|
|
1985
|
-
{
|
|
1986
|
-
name: "snap_points",
|
|
1987
|
-
type: "array",
|
|
1988
|
-
defaultValue: [],
|
|
1989
|
-
description: "Snap target positions"
|
|
1990
|
-
},
|
|
1991
|
-
{
|
|
1992
|
-
name: "snap_distance",
|
|
1993
|
-
type: "number",
|
|
1994
|
-
defaultValue: 0.3,
|
|
1995
|
-
min: 0,
|
|
1996
|
-
description: "Snap activation distance"
|
|
1997
|
-
},
|
|
1998
|
-
{
|
|
1999
|
-
name: "snap_rotation",
|
|
2000
|
-
type: "boolean",
|
|
2001
|
-
defaultValue: false,
|
|
2002
|
-
description: "Snap rotation as well"
|
|
2003
|
-
},
|
|
2004
|
-
{
|
|
2005
|
-
name: "magnetic",
|
|
2006
|
-
type: "boolean",
|
|
2007
|
-
defaultValue: false,
|
|
2008
|
-
description: "Magnetic snap effect"
|
|
2009
|
-
}
|
|
2010
|
-
]
|
|
2011
|
-
},
|
|
2012
|
-
// =========================================================================
|
|
2013
|
-
// PHYSICS TRAITS
|
|
2014
|
-
// =========================================================================
|
|
2015
|
-
{
|
|
2016
|
-
name: "collidable",
|
|
2017
|
-
category: "physics",
|
|
2018
|
-
properties: [
|
|
2019
|
-
{
|
|
2020
|
-
name: "shape",
|
|
2021
|
-
type: "enum",
|
|
2022
|
-
enumValues: ["box", "sphere", "capsule", "mesh", "auto"],
|
|
2023
|
-
defaultValue: "auto",
|
|
2024
|
-
description: "Collision shape"
|
|
2025
|
-
},
|
|
2026
|
-
{ name: "layer", type: "string", defaultValue: "default", description: "Collision layer" },
|
|
2027
|
-
{ name: "trigger", type: "boolean", defaultValue: false, description: "Is trigger collider" }
|
|
2028
|
-
]
|
|
2029
|
-
},
|
|
2030
|
-
{
|
|
2031
|
-
name: "physics",
|
|
2032
|
-
category: "physics",
|
|
2033
|
-
properties: [
|
|
2034
|
-
{ name: "mass", type: "number", defaultValue: 1, min: 0, description: "Object mass in kg" },
|
|
2035
|
-
{
|
|
2036
|
-
name: "restitution",
|
|
2037
|
-
type: "number",
|
|
2038
|
-
defaultValue: 0.5,
|
|
2039
|
-
min: 0,
|
|
2040
|
-
max: 1,
|
|
2041
|
-
description: "Bounciness (0-1)"
|
|
2042
|
-
},
|
|
2043
|
-
{
|
|
2044
|
-
name: "friction",
|
|
2045
|
-
type: "number",
|
|
2046
|
-
defaultValue: 0.5,
|
|
2047
|
-
min: 0,
|
|
2048
|
-
max: 1,
|
|
2049
|
-
description: "Surface friction (0-1)"
|
|
2050
|
-
},
|
|
2051
|
-
{ name: "gravity", type: "boolean", defaultValue: true, description: "Affected by gravity" },
|
|
2052
|
-
{
|
|
2053
|
-
name: "linear_damping",
|
|
2054
|
-
type: "number",
|
|
2055
|
-
defaultValue: 0,
|
|
2056
|
-
min: 0,
|
|
2057
|
-
max: 1,
|
|
2058
|
-
description: "Linear velocity damping"
|
|
2059
|
-
},
|
|
2060
|
-
{
|
|
2061
|
-
name: "angular_damping",
|
|
2062
|
-
type: "number",
|
|
2063
|
-
defaultValue: 0.05,
|
|
2064
|
-
min: 0,
|
|
2065
|
-
max: 1,
|
|
2066
|
-
description: "Angular velocity damping"
|
|
2067
|
-
}
|
|
2068
|
-
]
|
|
2069
|
-
},
|
|
2070
|
-
{
|
|
2071
|
-
name: "rigid",
|
|
2072
|
-
category: "physics",
|
|
2073
|
-
properties: [
|
|
2074
|
-
{
|
|
2075
|
-
name: "type",
|
|
2076
|
-
type: "enum",
|
|
2077
|
-
enumValues: ["dynamic", "static", "kinematic"],
|
|
2078
|
-
defaultValue: "dynamic",
|
|
2079
|
-
description: "Rigid body type"
|
|
2080
|
-
},
|
|
2081
|
-
{ name: "mass", type: "number", defaultValue: 1, min: 0, description: "Mass in kg" }
|
|
2082
|
-
]
|
|
2083
|
-
},
|
|
2084
|
-
{
|
|
2085
|
-
name: "kinematic",
|
|
2086
|
-
category: "physics",
|
|
2087
|
-
properties: [
|
|
2088
|
-
{
|
|
2089
|
-
name: "interpolation",
|
|
2090
|
-
type: "boolean",
|
|
2091
|
-
defaultValue: true,
|
|
2092
|
-
description: "Interpolate movement"
|
|
2093
|
-
}
|
|
2094
|
-
]
|
|
2095
|
-
},
|
|
2096
|
-
{
|
|
2097
|
-
name: "trigger",
|
|
2098
|
-
category: "physics",
|
|
2099
|
-
properties: [
|
|
2100
|
-
{
|
|
2101
|
-
name: "shape",
|
|
2102
|
-
type: "enum",
|
|
2103
|
-
enumValues: ["box", "sphere", "capsule"],
|
|
2104
|
-
defaultValue: "box",
|
|
2105
|
-
description: "Trigger zone shape"
|
|
2106
|
-
},
|
|
2107
|
-
{ name: "size", type: "array", description: "Trigger zone size" }
|
|
2108
|
-
]
|
|
2109
|
-
},
|
|
2110
|
-
{
|
|
2111
|
-
name: "gravity",
|
|
2112
|
-
category: "physics",
|
|
2113
|
-
properties: [
|
|
2114
|
-
{ name: "strength", type: "number", defaultValue: 9.81, description: "Gravity strength" },
|
|
2115
|
-
{
|
|
2116
|
-
name: "direction",
|
|
2117
|
-
type: "array",
|
|
2118
|
-
defaultValue: [0, -1, 0],
|
|
2119
|
-
description: "Gravity direction vector"
|
|
2120
|
-
}
|
|
2121
|
-
]
|
|
2122
|
-
},
|
|
2123
|
-
// =========================================================================
|
|
2124
|
-
// VISUAL TRAITS
|
|
2125
|
-
// =========================================================================
|
|
2126
|
-
{
|
|
2127
|
-
name: "glowing",
|
|
2128
|
-
category: "visual",
|
|
2129
|
-
properties: [
|
|
2130
|
-
{ name: "color", type: "string", defaultValue: "#ffffff", description: "Glow color" },
|
|
2131
|
-
{ name: "intensity", type: "number", defaultValue: 1, min: 0, description: "Glow intensity" },
|
|
2132
|
-
{ name: "radius", type: "number", defaultValue: 1, min: 0, description: "Glow radius" }
|
|
2133
|
-
]
|
|
2134
|
-
},
|
|
2135
|
-
{
|
|
2136
|
-
name: "emissive",
|
|
2137
|
-
category: "visual",
|
|
2138
|
-
properties: [
|
|
2139
|
-
{ name: "color", type: "string", defaultValue: "#ffffff", description: "Emissive color" },
|
|
2140
|
-
{
|
|
2141
|
-
name: "intensity",
|
|
2142
|
-
type: "number",
|
|
2143
|
-
defaultValue: 1,
|
|
2144
|
-
min: 0,
|
|
2145
|
-
description: "Emission intensity"
|
|
2146
|
-
}
|
|
2147
|
-
]
|
|
2148
|
-
},
|
|
2149
|
-
{
|
|
2150
|
-
name: "transparent",
|
|
2151
|
-
category: "visual",
|
|
2152
|
-
properties: [
|
|
2153
|
-
{
|
|
2154
|
-
name: "opacity",
|
|
2155
|
-
type: "number",
|
|
2156
|
-
defaultValue: 0.5,
|
|
2157
|
-
min: 0,
|
|
2158
|
-
max: 1,
|
|
2159
|
-
description: "Opacity value (0-1)"
|
|
2160
|
-
}
|
|
2161
|
-
]
|
|
2162
|
-
},
|
|
2163
|
-
{
|
|
2164
|
-
name: "reflective",
|
|
2165
|
-
category: "visual",
|
|
2166
|
-
properties: [
|
|
2167
|
-
{
|
|
2168
|
-
name: "roughness",
|
|
2169
|
-
type: "number",
|
|
2170
|
-
defaultValue: 0.1,
|
|
2171
|
-
min: 0,
|
|
2172
|
-
max: 1,
|
|
2173
|
-
description: "Surface roughness (0-1)"
|
|
2174
|
-
},
|
|
2175
|
-
{
|
|
2176
|
-
name: "metalness",
|
|
2177
|
-
type: "number",
|
|
2178
|
-
defaultValue: 1,
|
|
2179
|
-
min: 0,
|
|
2180
|
-
max: 1,
|
|
2181
|
-
description: "Metalness (0-1)"
|
|
2182
|
-
}
|
|
2183
|
-
]
|
|
2184
|
-
},
|
|
2185
|
-
{
|
|
2186
|
-
name: "animated",
|
|
2187
|
-
category: "visual",
|
|
2188
|
-
properties: [
|
|
2189
|
-
{ name: "clip", type: "string", description: "Animation clip name" },
|
|
2190
|
-
{ name: "loop", type: "boolean", defaultValue: true, description: "Loop animation" },
|
|
2191
|
-
{ name: "speed", type: "number", defaultValue: 1, min: 0, description: "Playback speed" },
|
|
2192
|
-
{ name: "autoplay", type: "boolean", defaultValue: true, description: "Auto-play on load" }
|
|
2193
|
-
]
|
|
2194
|
-
},
|
|
2195
|
-
{
|
|
2196
|
-
name: "billboard",
|
|
2197
|
-
category: "visual",
|
|
2198
|
-
properties: [
|
|
2199
|
-
{
|
|
2200
|
-
name: "axis",
|
|
2201
|
-
type: "enum",
|
|
2202
|
-
enumValues: ["all", "y"],
|
|
2203
|
-
defaultValue: "all",
|
|
2204
|
-
description: "Billboard axis constraint"
|
|
2205
|
-
}
|
|
2206
|
-
]
|
|
2207
|
-
},
|
|
2208
|
-
{
|
|
2209
|
-
name: "color",
|
|
2210
|
-
category: "visual",
|
|
2211
|
-
properties: [
|
|
2212
|
-
{ name: "value", type: "string", description: "Color value (hex, named, or rgb)" }
|
|
2213
|
-
]
|
|
2214
|
-
},
|
|
2215
|
-
{
|
|
2216
|
-
name: "material",
|
|
2217
|
-
category: "visual",
|
|
2218
|
-
properties: [
|
|
2219
|
-
{
|
|
2220
|
-
name: "type",
|
|
2221
|
-
type: "enum",
|
|
2222
|
-
enumValues: ["pbr", "standard", "unlit", "transparent", "volumetric", "custom", "neural"],
|
|
2223
|
-
defaultValue: "pbr",
|
|
2224
|
-
description: "Material type"
|
|
2225
|
-
},
|
|
2226
|
-
{ name: "color", type: "string", description: "Base color" },
|
|
2227
|
-
{
|
|
2228
|
-
name: "metallic",
|
|
2229
|
-
type: "number",
|
|
2230
|
-
defaultValue: 0,
|
|
2231
|
-
min: 0,
|
|
2232
|
-
max: 1,
|
|
2233
|
-
description: "Metalness (0-1)"
|
|
2234
|
-
},
|
|
2235
|
-
{
|
|
2236
|
-
name: "roughness",
|
|
2237
|
-
type: "number",
|
|
2238
|
-
defaultValue: 0.5,
|
|
2239
|
-
min: 0,
|
|
2240
|
-
max: 1,
|
|
2241
|
-
description: "Roughness (0-1)"
|
|
2242
|
-
},
|
|
2243
|
-
{
|
|
2244
|
-
name: "opacity",
|
|
2245
|
-
type: "number",
|
|
2246
|
-
defaultValue: 1,
|
|
2247
|
-
min: 0,
|
|
2248
|
-
max: 1,
|
|
2249
|
-
description: "Opacity (0-1)"
|
|
2250
|
-
},
|
|
2251
|
-
{ name: "emissive", type: "string", description: "Emissive color" },
|
|
2252
|
-
{
|
|
2253
|
-
name: "emissive_intensity",
|
|
2254
|
-
type: "number",
|
|
2255
|
-
defaultValue: 0,
|
|
2256
|
-
min: 0,
|
|
2257
|
-
description: "Emissive intensity"
|
|
2258
|
-
}
|
|
2259
|
-
]
|
|
2260
|
-
},
|
|
2261
|
-
{
|
|
2262
|
-
name: "texture",
|
|
2263
|
-
category: "visual",
|
|
2264
|
-
properties: [
|
|
2265
|
-
{ name: "path", type: "string", required: true, description: "Texture file path or URL" },
|
|
2266
|
-
{
|
|
2267
|
-
name: "channel",
|
|
2268
|
-
type: "enum",
|
|
2269
|
-
enumValues: [
|
|
2270
|
-
"baseColor",
|
|
2271
|
-
"normalMap",
|
|
2272
|
-
"roughnessMap",
|
|
2273
|
-
"metallicMap",
|
|
2274
|
-
"ambientOcclusionMap",
|
|
2275
|
-
"emissionMap",
|
|
2276
|
-
"heightMap",
|
|
2277
|
-
"displacementMap"
|
|
2278
|
-
],
|
|
2279
|
-
defaultValue: "baseColor",
|
|
2280
|
-
description: "Texture channel"
|
|
2281
|
-
},
|
|
2282
|
-
{ name: "scale", type: "object", description: "UV tiling scale" },
|
|
2283
|
-
{ name: "offset", type: "object", description: "UV offset" }
|
|
2284
|
-
]
|
|
2285
|
-
},
|
|
2286
|
-
// =========================================================================
|
|
2287
|
-
// NETWORKING TRAITS
|
|
2288
|
-
// =========================================================================
|
|
2289
|
-
{
|
|
2290
|
-
name: "networked",
|
|
2291
|
-
category: "networking",
|
|
2292
|
-
properties: [
|
|
2293
|
-
{
|
|
2294
|
-
name: "mode",
|
|
2295
|
-
type: "enum",
|
|
2296
|
-
enumValues: ["owner", "shared", "server"],
|
|
2297
|
-
defaultValue: "owner",
|
|
2298
|
-
description: "Sync authority mode"
|
|
2299
|
-
},
|
|
2300
|
-
{ name: "syncProperties", type: "array", description: "Properties to synchronize" },
|
|
2301
|
-
{
|
|
2302
|
-
name: "syncRate",
|
|
2303
|
-
type: "number",
|
|
2304
|
-
defaultValue: 20,
|
|
2305
|
-
min: 1,
|
|
2306
|
-
max: 120,
|
|
2307
|
-
description: "Sync rate in Hz"
|
|
2308
|
-
},
|
|
2309
|
-
{
|
|
2310
|
-
name: "interpolation",
|
|
2311
|
-
type: "boolean",
|
|
2312
|
-
defaultValue: true,
|
|
2313
|
-
description: "Enable interpolation"
|
|
2314
|
-
},
|
|
2315
|
-
{
|
|
2316
|
-
name: "channel",
|
|
2317
|
-
type: "enum",
|
|
2318
|
-
enumValues: ["reliable", "unreliable", "ordered"],
|
|
2319
|
-
defaultValue: "reliable",
|
|
2320
|
-
description: "Network channel"
|
|
2321
|
-
}
|
|
2322
|
-
]
|
|
2323
|
-
},
|
|
2324
|
-
{
|
|
2325
|
-
name: "synced",
|
|
2326
|
-
category: "networking",
|
|
2327
|
-
properties: [
|
|
2328
|
-
{ name: "properties", type: "array", description: "Properties to sync" },
|
|
2329
|
-
{ name: "rate", type: "number", defaultValue: 30, min: 1, description: "Sync rate" }
|
|
2330
|
-
]
|
|
2331
|
-
},
|
|
2332
|
-
{
|
|
2333
|
-
name: "persistent",
|
|
2334
|
-
category: "networking",
|
|
2335
|
-
properties: [
|
|
2336
|
-
{
|
|
2337
|
-
name: "storage",
|
|
2338
|
-
type: "enum",
|
|
2339
|
-
enumValues: ["local", "cloud", "blockchain"],
|
|
2340
|
-
defaultValue: "local",
|
|
2341
|
-
description: "Persistence backend"
|
|
2342
|
-
},
|
|
2343
|
-
{ name: "key", type: "string", description: "Storage key" }
|
|
2344
|
-
]
|
|
2345
|
-
},
|
|
2346
|
-
{
|
|
2347
|
-
name: "owned",
|
|
2348
|
-
category: "networking",
|
|
2349
|
-
properties: [
|
|
2350
|
-
{
|
|
2351
|
-
name: "transferable",
|
|
2352
|
-
type: "boolean",
|
|
2353
|
-
defaultValue: true,
|
|
2354
|
-
description: "Can ownership be transferred"
|
|
2355
|
-
}
|
|
2356
|
-
]
|
|
2357
|
-
},
|
|
2358
|
-
{
|
|
2359
|
-
name: "host_only",
|
|
2360
|
-
category: "networking",
|
|
2361
|
-
properties: []
|
|
2362
|
-
},
|
|
2363
|
-
// =========================================================================
|
|
2364
|
-
// BEHAVIOR TRAITS
|
|
2365
|
-
// =========================================================================
|
|
2366
|
-
{
|
|
2367
|
-
name: "stackable",
|
|
2368
|
-
category: "behavior",
|
|
2369
|
-
properties: [
|
|
2370
|
-
{
|
|
2371
|
-
name: "stack_axis",
|
|
2372
|
-
type: "enum",
|
|
2373
|
-
enumValues: ["x", "y", "z"],
|
|
2374
|
-
defaultValue: "y",
|
|
2375
|
-
description: "Stacking axis"
|
|
2376
|
-
},
|
|
2377
|
-
{
|
|
2378
|
-
name: "stack_offset",
|
|
2379
|
-
type: "number",
|
|
2380
|
-
defaultValue: 0,
|
|
2381
|
-
description: "Offset between stacked objects"
|
|
2382
|
-
},
|
|
2383
|
-
{
|
|
2384
|
-
name: "max_stack",
|
|
2385
|
-
type: "number",
|
|
2386
|
-
defaultValue: 10,
|
|
2387
|
-
min: 1,
|
|
2388
|
-
description: "Maximum stack height"
|
|
2389
|
-
},
|
|
2390
|
-
{
|
|
2391
|
-
name: "snap_distance",
|
|
2392
|
-
type: "number",
|
|
2393
|
-
defaultValue: 0.5,
|
|
2394
|
-
min: 0,
|
|
2395
|
-
description: "Snap distance for stacking"
|
|
2396
|
-
}
|
|
2397
|
-
]
|
|
2398
|
-
},
|
|
2399
|
-
{
|
|
2400
|
-
name: "attachable",
|
|
2401
|
-
category: "behavior",
|
|
2402
|
-
properties: [
|
|
2403
|
-
{ name: "attach_point", type: "string", description: "Named attachment point" },
|
|
2404
|
-
{ name: "detachable", type: "boolean", defaultValue: true, description: "Can be detached" }
|
|
2405
|
-
]
|
|
2406
|
-
},
|
|
2407
|
-
{
|
|
2408
|
-
name: "equippable",
|
|
2409
|
-
category: "behavior",
|
|
2410
|
-
requires: ["grabbable"],
|
|
2411
|
-
properties: [
|
|
2412
|
-
{
|
|
2413
|
-
name: "slot",
|
|
2414
|
-
type: "enum",
|
|
2415
|
-
enumValues: ["head", "hand_left", "hand_right", "body", "back", "hip"],
|
|
2416
|
-
description: "Equipment slot"
|
|
2417
|
-
},
|
|
2418
|
-
{ name: "offset", type: "array", description: "Position offset when equipped" },
|
|
2419
|
-
{ name: "rotation", type: "array", description: "Rotation offset when equipped" }
|
|
2420
|
-
]
|
|
2421
|
-
},
|
|
2422
|
-
{
|
|
2423
|
-
name: "consumable",
|
|
2424
|
-
category: "behavior",
|
|
2425
|
-
properties: [
|
|
2426
|
-
{ name: "uses", type: "number", defaultValue: 1, min: 1, description: "Number of uses" },
|
|
2427
|
-
{
|
|
2428
|
-
name: "destroy_on_use",
|
|
2429
|
-
type: "boolean",
|
|
2430
|
-
defaultValue: true,
|
|
2431
|
-
description: "Destroy after last use"
|
|
2432
|
-
}
|
|
2433
|
-
]
|
|
2434
|
-
},
|
|
2435
|
-
{
|
|
2436
|
-
name: "destructible",
|
|
2437
|
-
category: "behavior",
|
|
2438
|
-
properties: [
|
|
2439
|
-
{ name: "health", type: "number", defaultValue: 100, min: 0, description: "Hit points" },
|
|
2440
|
-
{
|
|
2441
|
-
name: "fragments",
|
|
2442
|
-
type: "number",
|
|
2443
|
-
defaultValue: 8,
|
|
2444
|
-
min: 1,
|
|
2445
|
-
description: "Number of fragments"
|
|
2446
|
-
}
|
|
2447
|
-
]
|
|
2448
|
-
},
|
|
2449
|
-
{
|
|
2450
|
-
name: "breakable",
|
|
2451
|
-
category: "behavior",
|
|
2452
|
-
properties: [
|
|
2453
|
-
{
|
|
2454
|
-
name: "break_velocity",
|
|
2455
|
-
type: "number",
|
|
2456
|
-
defaultValue: 5,
|
|
2457
|
-
min: 0,
|
|
2458
|
-
description: "Velocity threshold to break"
|
|
2459
|
-
},
|
|
2460
|
-
{
|
|
2461
|
-
name: "fragments",
|
|
2462
|
-
type: "number",
|
|
2463
|
-
defaultValue: 8,
|
|
2464
|
-
min: 1,
|
|
2465
|
-
description: "Number of fragments"
|
|
2466
|
-
},
|
|
2467
|
-
{ name: "fragment_mesh", type: "string", description: "Custom fragment mesh" },
|
|
2468
|
-
{ name: "sound_on_break", type: "string", description: "Sound effect on break" },
|
|
2469
|
-
{ name: "respawn", type: "boolean", defaultValue: false, description: "Respawn after break" },
|
|
2470
|
-
{
|
|
2471
|
-
name: "respawn_time",
|
|
2472
|
-
type: "number",
|
|
2473
|
-
defaultValue: 5,
|
|
2474
|
-
min: 0,
|
|
2475
|
-
description: "Respawn delay in seconds"
|
|
2476
|
-
}
|
|
2477
|
-
]
|
|
2478
|
-
},
|
|
2479
|
-
{
|
|
2480
|
-
name: "character",
|
|
2481
|
-
category: "behavior",
|
|
2482
|
-
properties: [
|
|
2483
|
-
{
|
|
2484
|
-
name: "height",
|
|
2485
|
-
type: "number",
|
|
2486
|
-
defaultValue: 1.8,
|
|
2487
|
-
min: 0,
|
|
2488
|
-
description: "Character height"
|
|
2489
|
-
},
|
|
2490
|
-
{ name: "speed", type: "number", defaultValue: 5, min: 0, description: "Movement speed" }
|
|
2491
|
-
]
|
|
2492
|
-
},
|
|
2493
|
-
// =========================================================================
|
|
2494
|
-
// SPATIAL TRAITS
|
|
2495
|
-
// =========================================================================
|
|
2496
|
-
{
|
|
2497
|
-
name: "anchor",
|
|
2498
|
-
category: "spatial",
|
|
2499
|
-
properties: [
|
|
2500
|
-
{
|
|
2501
|
-
name: "type",
|
|
2502
|
-
type: "enum",
|
|
2503
|
-
enumValues: ["plane", "point", "image", "face", "body"],
|
|
2504
|
-
defaultValue: "plane",
|
|
2505
|
-
description: "Anchor type"
|
|
2506
|
-
},
|
|
2507
|
-
{
|
|
2508
|
-
name: "tracking",
|
|
2509
|
-
type: "boolean",
|
|
2510
|
-
defaultValue: true,
|
|
2511
|
-
description: "Enable tracking updates"
|
|
2512
|
-
}
|
|
2513
|
-
]
|
|
2514
|
-
},
|
|
2515
|
-
{
|
|
2516
|
-
name: "tracked",
|
|
2517
|
-
category: "spatial",
|
|
2518
|
-
properties: [
|
|
2519
|
-
{
|
|
2520
|
-
name: "source",
|
|
2521
|
-
type: "enum",
|
|
2522
|
-
enumValues: ["hand", "head", "controller", "eye", "body"],
|
|
2523
|
-
description: "Tracking source"
|
|
2524
|
-
}
|
|
2525
|
-
]
|
|
2526
|
-
},
|
|
2527
|
-
{
|
|
2528
|
-
name: "world_locked",
|
|
2529
|
-
category: "spatial",
|
|
2530
|
-
properties: [
|
|
2531
|
-
{
|
|
2532
|
-
name: "drift_correction",
|
|
2533
|
-
type: "boolean",
|
|
2534
|
-
defaultValue: true,
|
|
2535
|
-
description: "Correct tracking drift"
|
|
2536
|
-
}
|
|
2537
|
-
]
|
|
2538
|
-
},
|
|
2539
|
-
{
|
|
2540
|
-
name: "hand_tracked",
|
|
2541
|
-
category: "spatial",
|
|
2542
|
-
properties: [
|
|
2543
|
-
{
|
|
2544
|
-
name: "hand",
|
|
2545
|
-
type: "enum",
|
|
2546
|
-
enumValues: ["left", "right", "both"],
|
|
2547
|
-
defaultValue: "both",
|
|
2548
|
-
description: "Which hand to track"
|
|
2549
|
-
},
|
|
2550
|
-
{ name: "joint", type: "string", description: "Specific hand joint to track" }
|
|
2551
|
-
]
|
|
2552
|
-
},
|
|
2553
|
-
{
|
|
2554
|
-
name: "eye_tracked",
|
|
2555
|
-
category: "spatial",
|
|
2556
|
-
properties: [
|
|
2557
|
-
{
|
|
2558
|
-
name: "dwell_time",
|
|
2559
|
-
type: "number",
|
|
2560
|
-
defaultValue: 1,
|
|
2561
|
-
min: 0,
|
|
2562
|
-
description: "Dwell activation time in seconds"
|
|
2563
|
-
},
|
|
2564
|
-
{ name: "highlight", type: "boolean", defaultValue: true, description: "Highlight on gaze" }
|
|
2565
|
-
]
|
|
2566
|
-
},
|
|
2567
|
-
{
|
|
2568
|
-
name: "position",
|
|
2569
|
-
category: "spatial",
|
|
2570
|
-
properties: [
|
|
2571
|
-
{ name: "x", type: "number", defaultValue: 0, description: "X position" },
|
|
2572
|
-
{ name: "y", type: "number", defaultValue: 0, description: "Y position" },
|
|
2573
|
-
{ name: "z", type: "number", defaultValue: 0, description: "Z position" }
|
|
2574
|
-
]
|
|
2575
|
-
},
|
|
2576
|
-
{
|
|
2577
|
-
name: "rotation",
|
|
2578
|
-
category: "spatial",
|
|
2579
|
-
properties: [
|
|
2580
|
-
{ name: "x", type: "number", defaultValue: 0, description: "X rotation (degrees)" },
|
|
2581
|
-
{ name: "y", type: "number", defaultValue: 0, description: "Y rotation (degrees)" },
|
|
2582
|
-
{ name: "z", type: "number", defaultValue: 0, description: "Z rotation (degrees)" }
|
|
2583
|
-
]
|
|
2584
|
-
},
|
|
2585
|
-
{
|
|
2586
|
-
name: "scale",
|
|
2587
|
-
category: "spatial",
|
|
2588
|
-
properties: [
|
|
2589
|
-
{ name: "x", type: "number", defaultValue: 1, min: 0, description: "X scale" },
|
|
2590
|
-
{ name: "y", type: "number", defaultValue: 1, min: 0, description: "Y scale" },
|
|
2591
|
-
{ name: "z", type: "number", defaultValue: 1, min: 0, description: "Z scale" }
|
|
2592
|
-
]
|
|
2593
|
-
},
|
|
2594
|
-
// =========================================================================
|
|
2595
|
-
// AUDIO TRAITS
|
|
2596
|
-
// =========================================================================
|
|
2597
|
-
{
|
|
2598
|
-
name: "spatial_audio",
|
|
2599
|
-
category: "audio",
|
|
2600
|
-
properties: [
|
|
2601
|
-
{ name: "src", type: "string", description: "Audio source file" },
|
|
2602
|
-
{
|
|
2603
|
-
name: "volume",
|
|
2604
|
-
type: "number",
|
|
2605
|
-
defaultValue: 1,
|
|
2606
|
-
min: 0,
|
|
2607
|
-
max: 1,
|
|
2608
|
-
description: "Volume (0-1)"
|
|
2609
|
-
},
|
|
2610
|
-
{
|
|
2611
|
-
name: "rolloff",
|
|
2612
|
-
type: "enum",
|
|
2613
|
-
enumValues: ["linear", "logarithmic", "inverse"],
|
|
2614
|
-
defaultValue: "logarithmic",
|
|
2615
|
-
description: "Distance rolloff model"
|
|
2616
|
-
},
|
|
2617
|
-
{
|
|
2618
|
-
name: "refDistance",
|
|
2619
|
-
type: "number",
|
|
2620
|
-
defaultValue: 1,
|
|
2621
|
-
min: 0,
|
|
2622
|
-
description: "Reference distance"
|
|
2623
|
-
},
|
|
2624
|
-
{
|
|
2625
|
-
name: "maxDistance",
|
|
2626
|
-
type: "number",
|
|
2627
|
-
defaultValue: 100,
|
|
2628
|
-
min: 0,
|
|
2629
|
-
description: "Max audible distance"
|
|
2630
|
-
}
|
|
2631
|
-
]
|
|
2632
|
-
},
|
|
2633
|
-
{
|
|
2634
|
-
name: "ambient",
|
|
2635
|
-
category: "audio",
|
|
2636
|
-
properties: [
|
|
2637
|
-
{ name: "src", type: "string", description: "Audio source file" },
|
|
2638
|
-
{
|
|
2639
|
-
name: "volume",
|
|
2640
|
-
type: "number",
|
|
2641
|
-
defaultValue: 0.5,
|
|
2642
|
-
min: 0,
|
|
2643
|
-
max: 1,
|
|
2644
|
-
description: "Volume (0-1)"
|
|
2645
|
-
},
|
|
2646
|
-
{ name: "loop", type: "boolean", defaultValue: true, description: "Loop playback" }
|
|
2647
|
-
]
|
|
2648
|
-
},
|
|
2649
|
-
{
|
|
2650
|
-
name: "voice_activated",
|
|
2651
|
-
category: "audio",
|
|
2652
|
-
properties: [
|
|
2653
|
-
{
|
|
2654
|
-
name: "threshold",
|
|
2655
|
-
type: "number",
|
|
2656
|
-
defaultValue: 0.3,
|
|
2657
|
-
min: 0,
|
|
2658
|
-
max: 1,
|
|
2659
|
-
description: "Voice activation threshold"
|
|
2660
|
-
},
|
|
2661
|
-
{ name: "keyword", type: "string", description: "Activation keyword" }
|
|
2662
|
-
]
|
|
2663
|
-
},
|
|
2664
|
-
{
|
|
2665
|
-
name: "sound",
|
|
2666
|
-
category: "audio",
|
|
2667
|
-
properties: [
|
|
2668
|
-
{ name: "src", type: "string", description: "Sound file path" },
|
|
2669
|
-
{ name: "volume", type: "number", defaultValue: 1, min: 0, max: 1, description: "Volume" },
|
|
2670
|
-
{ name: "loop", type: "boolean", defaultValue: false, description: "Loop playback" }
|
|
2671
|
-
]
|
|
2672
|
-
},
|
|
2673
|
-
// =========================================================================
|
|
2674
|
-
// STATE TRAITS
|
|
2675
|
-
// =========================================================================
|
|
2676
|
-
{
|
|
2677
|
-
name: "state",
|
|
2678
|
-
category: "state",
|
|
2679
|
-
properties: [{ name: "initial", type: "object", description: "Initial state values" }]
|
|
2680
|
-
},
|
|
2681
|
-
{
|
|
2682
|
-
name: "reactive",
|
|
2683
|
-
category: "state",
|
|
2684
|
-
properties: [{ name: "bindings", type: "array", description: "Data bindings" }]
|
|
2685
|
-
},
|
|
2686
|
-
{
|
|
2687
|
-
name: "observable",
|
|
2688
|
-
category: "state",
|
|
2689
|
-
properties: [{ name: "properties", type: "array", description: "Observable property names" }]
|
|
2690
|
-
},
|
|
2691
|
-
{
|
|
2692
|
-
name: "computed",
|
|
2693
|
-
category: "state",
|
|
2694
|
-
properties: [
|
|
2695
|
-
{ name: "expression", type: "string", description: "Computed expression" },
|
|
2696
|
-
{ name: "dependencies", type: "array", description: "Dependency property names" }
|
|
2697
|
-
]
|
|
2698
|
-
},
|
|
2699
|
-
// =========================================================================
|
|
2700
|
-
// ADVANCED TRAITS
|
|
2701
|
-
// =========================================================================
|
|
2702
|
-
{
|
|
2703
|
-
name: "teleport",
|
|
2704
|
-
category: "advanced",
|
|
2705
|
-
properties: [
|
|
2706
|
-
{ name: "target", type: "string", description: "Teleport target position/name" },
|
|
2707
|
-
{
|
|
2708
|
-
name: "fade_duration",
|
|
2709
|
-
type: "number",
|
|
2710
|
-
defaultValue: 0.3,
|
|
2711
|
-
min: 0,
|
|
2712
|
-
description: "Fade transition duration"
|
|
2713
|
-
}
|
|
2714
|
-
]
|
|
2715
|
-
},
|
|
2716
|
-
{
|
|
2717
|
-
name: "ui_panel",
|
|
2718
|
-
category: "advanced",
|
|
2719
|
-
properties: [
|
|
2720
|
-
{
|
|
2721
|
-
name: "width",
|
|
2722
|
-
type: "number",
|
|
2723
|
-
defaultValue: 1,
|
|
2724
|
-
min: 0,
|
|
2725
|
-
description: "Panel width in meters"
|
|
2726
|
-
},
|
|
2727
|
-
{
|
|
2728
|
-
name: "height",
|
|
2729
|
-
type: "number",
|
|
2730
|
-
defaultValue: 0.75,
|
|
2731
|
-
min: 0,
|
|
2732
|
-
description: "Panel height in meters"
|
|
2733
|
-
},
|
|
2734
|
-
{ name: "curved", type: "boolean", defaultValue: false, description: "Curved panel" }
|
|
2735
|
-
]
|
|
2736
|
-
},
|
|
2737
|
-
{
|
|
2738
|
-
name: "particle_system",
|
|
2739
|
-
category: "advanced",
|
|
2740
|
-
properties: [
|
|
2741
|
-
{ name: "count", type: "number", defaultValue: 100, min: 1, description: "Particle count" },
|
|
2742
|
-
{
|
|
2743
|
-
name: "lifetime",
|
|
2744
|
-
type: "number",
|
|
2745
|
-
defaultValue: 2,
|
|
2746
|
-
min: 0,
|
|
2747
|
-
description: "Particle lifetime in seconds"
|
|
2748
|
-
},
|
|
2749
|
-
{ name: "speed", type: "number", defaultValue: 1, min: 0, description: "Emission speed" },
|
|
2750
|
-
{ name: "color", type: "string", defaultValue: "#ffffff", description: "Particle color" },
|
|
2751
|
-
{
|
|
2752
|
-
name: "shape",
|
|
2753
|
-
type: "enum",
|
|
2754
|
-
enumValues: ["point", "sphere", "cone", "box"],
|
|
2755
|
-
defaultValue: "point",
|
|
2756
|
-
description: "Emitter shape"
|
|
2757
|
-
}
|
|
2758
|
-
]
|
|
2759
|
-
},
|
|
2760
|
-
{
|
|
2761
|
-
name: "weather",
|
|
2762
|
-
category: "advanced",
|
|
2763
|
-
properties: [
|
|
2764
|
-
{
|
|
2765
|
-
name: "type",
|
|
2766
|
-
type: "enum",
|
|
2767
|
-
enumValues: ["rain", "snow", "fog", "wind", "storm"],
|
|
2768
|
-
description: "Weather type"
|
|
2769
|
-
},
|
|
2770
|
-
{
|
|
2771
|
-
name: "intensity",
|
|
2772
|
-
type: "number",
|
|
2773
|
-
defaultValue: 0.5,
|
|
2774
|
-
min: 0,
|
|
2775
|
-
max: 1,
|
|
2776
|
-
description: "Weather intensity (0-1)"
|
|
2777
|
-
}
|
|
2778
|
-
]
|
|
2779
|
-
},
|
|
2780
|
-
{
|
|
2781
|
-
name: "day_night",
|
|
2782
|
-
category: "advanced",
|
|
2783
|
-
properties: [
|
|
2784
|
-
{
|
|
2785
|
-
name: "cycle_duration",
|
|
2786
|
-
type: "number",
|
|
2787
|
-
defaultValue: 300,
|
|
2788
|
-
min: 1,
|
|
2789
|
-
description: "Full cycle duration in seconds"
|
|
2790
|
-
},
|
|
2791
|
-
{
|
|
2792
|
-
name: "start_time",
|
|
2793
|
-
type: "number",
|
|
2794
|
-
defaultValue: 0.5,
|
|
2795
|
-
min: 0,
|
|
2796
|
-
max: 1,
|
|
2797
|
-
description: "Start time (0=midnight, 0.5=noon)"
|
|
2798
|
-
}
|
|
2799
|
-
]
|
|
2800
|
-
},
|
|
2801
|
-
{
|
|
2802
|
-
name: "lod",
|
|
2803
|
-
category: "advanced",
|
|
2804
|
-
properties: [
|
|
2805
|
-
{ name: "distances", type: "array", description: "LOD distance thresholds" },
|
|
2806
|
-
{ name: "meshes", type: "array", description: "Mesh paths for each LOD level" }
|
|
2807
|
-
]
|
|
2808
|
-
},
|
|
2809
|
-
{
|
|
2810
|
-
name: "hand_tracking",
|
|
2811
|
-
category: "advanced",
|
|
2812
|
-
properties: [
|
|
2813
|
-
{
|
|
2814
|
-
name: "gesture_recognition",
|
|
2815
|
-
type: "boolean",
|
|
2816
|
-
defaultValue: true,
|
|
2817
|
-
description: "Enable gesture recognition"
|
|
2818
|
-
},
|
|
2819
|
-
{
|
|
2820
|
-
name: "mesh_visualization",
|
|
2821
|
-
type: "boolean",
|
|
2822
|
-
defaultValue: false,
|
|
2823
|
-
description: "Show hand mesh"
|
|
2824
|
-
}
|
|
2825
|
-
]
|
|
2826
|
-
},
|
|
2827
|
-
{
|
|
2828
|
-
name: "haptic",
|
|
2829
|
-
category: "advanced",
|
|
2830
|
-
properties: [
|
|
2831
|
-
{
|
|
2832
|
-
name: "intensity",
|
|
2833
|
-
type: "number",
|
|
2834
|
-
defaultValue: 0.5,
|
|
2835
|
-
min: 0,
|
|
2836
|
-
max: 1,
|
|
2837
|
-
description: "Haptic intensity (0-1)"
|
|
2838
|
-
},
|
|
2839
|
-
{
|
|
2840
|
-
name: "duration",
|
|
2841
|
-
type: "number",
|
|
2842
|
-
defaultValue: 100,
|
|
2843
|
-
min: 0,
|
|
2844
|
-
description: "Duration in milliseconds"
|
|
2845
|
-
},
|
|
2846
|
-
{
|
|
2847
|
-
name: "pattern",
|
|
2848
|
-
type: "enum",
|
|
2849
|
-
enumValues: ["pulse", "buzz", "click", "custom"],
|
|
2850
|
-
defaultValue: "pulse",
|
|
2851
|
-
description: "Haptic pattern"
|
|
2852
|
-
}
|
|
2853
|
-
]
|
|
2854
|
-
},
|
|
2855
|
-
{
|
|
2856
|
-
name: "portal",
|
|
2857
|
-
category: "advanced",
|
|
2858
|
-
properties: [
|
|
2859
|
-
{
|
|
2860
|
-
name: "destination",
|
|
2861
|
-
type: "string",
|
|
2862
|
-
required: true,
|
|
2863
|
-
description: "Target scene/composition"
|
|
2864
|
-
},
|
|
2865
|
-
{
|
|
2866
|
-
name: "size",
|
|
2867
|
-
type: "number",
|
|
2868
|
-
defaultValue: 2,
|
|
2869
|
-
min: 0,
|
|
2870
|
-
description: "Portal size in meters"
|
|
2871
|
-
},
|
|
2872
|
-
{
|
|
2873
|
-
name: "shape",
|
|
2874
|
-
type: "enum",
|
|
2875
|
-
enumValues: ["circle", "rectangle"],
|
|
2876
|
-
defaultValue: "circle",
|
|
2877
|
-
description: "Portal shape"
|
|
2878
|
-
}
|
|
2879
|
-
]
|
|
2880
|
-
},
|
|
2881
|
-
{
|
|
2882
|
-
name: "mirror",
|
|
2883
|
-
category: "advanced",
|
|
2884
|
-
properties: [
|
|
2885
|
-
{ name: "size", type: "number", defaultValue: 2, min: 0, description: "Mirror plane size" },
|
|
2886
|
-
{ name: "tint", type: "string", defaultValue: "#ffffff", description: "Reflection tint" },
|
|
2887
|
-
{
|
|
2888
|
-
name: "orientation",
|
|
2889
|
-
type: "enum",
|
|
2890
|
-
enumValues: ["vertical", "horizontal", "face_camera"],
|
|
2891
|
-
defaultValue: "vertical",
|
|
2892
|
-
description: "Mirror orientation"
|
|
2893
|
-
}
|
|
2894
|
-
]
|
|
2895
|
-
}
|
|
2896
|
-
];
|
|
2897
|
-
ConfabulationValidator = class {
|
|
2898
|
-
constructor(config = {}) {
|
|
2899
|
-
this.config = {
|
|
2900
|
-
riskThreshold: config.riskThreshold ?? 50,
|
|
2901
|
-
unknownPropertySeverity: config.unknownPropertySeverity ?? "warning",
|
|
2902
|
-
validatePrerequisites: config.validatePrerequisites ?? true,
|
|
2903
|
-
validateConflicts: config.validateConflicts ?? true,
|
|
2904
|
-
validateRanges: config.validateRanges ?? true,
|
|
2905
|
-
customSchemas: config.customSchemas ?? [],
|
|
2906
|
-
strict: config.strict ?? false
|
|
2907
|
-
};
|
|
2908
|
-
this.schemaRegistry = /* @__PURE__ */ new Map();
|
|
2909
|
-
for (const schema of BUILT_IN_TRAIT_SCHEMAS) {
|
|
2910
|
-
this.schemaRegistry.set(schema.name, schema);
|
|
2911
|
-
}
|
|
2912
|
-
for (const schema of this.config.customSchemas) {
|
|
2913
|
-
this.schemaRegistry.set(schema.name, schema);
|
|
2914
|
-
}
|
|
2915
|
-
}
|
|
2916
|
-
// =========================================================================
|
|
2917
|
-
// PUBLIC API
|
|
2918
|
-
// =========================================================================
|
|
2919
|
-
/**
|
|
2920
|
-
* Validate an entire HoloComposition against trait schemas.
|
|
2921
|
-
*
|
|
2922
|
-
* Iterates over all objects in the composition, extracts their traits
|
|
2923
|
-
* and properties, and validates against the schema registry.
|
|
2924
|
-
*/
|
|
2925
|
-
validateComposition(composition) {
|
|
2926
|
-
const startTime = Date.now();
|
|
2927
|
-
const errors = [];
|
|
2928
|
-
const warnings = [];
|
|
2929
|
-
let traitsChecked = 0;
|
|
2930
|
-
let propertiesChecked = 0;
|
|
2931
|
-
for (const obj of composition.objects || []) {
|
|
2932
|
-
const objResult = this.validateObject(obj);
|
|
2933
|
-
errors.push(...objResult.errors);
|
|
2934
|
-
warnings.push(...objResult.warnings);
|
|
2935
|
-
traitsChecked += objResult.traitsChecked;
|
|
2936
|
-
propertiesChecked += objResult.propertiesChecked;
|
|
2937
|
-
}
|
|
2938
|
-
if (composition.traitDefinitions) {
|
|
2939
|
-
for (const traitDef of composition.traitDefinitions) {
|
|
2940
|
-
if (traitDef.base) {
|
|
2941
|
-
const baseSchema = this.schemaRegistry.get(traitDef.base);
|
|
2942
|
-
if (!baseSchema) {
|
|
2943
|
-
warnings.push({
|
|
2944
|
-
code: "CONFAB_UNKNOWN_BASE_TRAIT",
|
|
2945
|
-
message: `Trait "${traitDef.name}" extends unknown base trait "${traitDef.base}"`,
|
|
2946
|
-
traitName: traitDef.name,
|
|
2947
|
-
riskContribution: 10
|
|
2948
|
-
});
|
|
2949
|
-
}
|
|
2950
|
-
}
|
|
2951
|
-
}
|
|
2952
|
-
}
|
|
2953
|
-
const riskScore = this.calculateRiskScore(errors, warnings);
|
|
2954
|
-
const valid = this.config.strict ? errors.length === 0 && warnings.length === 0 && riskScore <= this.config.riskThreshold : errors.length === 0 && riskScore <= this.config.riskThreshold;
|
|
2955
|
-
return {
|
|
2956
|
-
valid,
|
|
2957
|
-
riskScore,
|
|
2958
|
-
errors,
|
|
2959
|
-
warnings,
|
|
2960
|
-
traitsChecked,
|
|
2961
|
-
propertiesChecked,
|
|
2962
|
-
validationTimeMs: Date.now() - startTime
|
|
2963
|
-
};
|
|
2964
|
-
}
|
|
2965
|
-
/**
|
|
2966
|
-
* Validate a single trait's properties against its schema.
|
|
2967
|
-
*
|
|
2968
|
-
* @param traitName - Trait name (without @ prefix)
|
|
2969
|
-
* @param properties - Property key-value pairs to validate
|
|
2970
|
-
* @param objectName - Optional object context for error messages
|
|
2971
|
-
*/
|
|
2972
|
-
validateTraitProperties(traitName, properties, objectName) {
|
|
2973
|
-
const errors = [];
|
|
2974
|
-
const warnings = [];
|
|
2975
|
-
const normalizedName = traitName.startsWith("@") ? traitName.slice(1) : traitName;
|
|
2976
|
-
const schema = this.schemaRegistry.get(normalizedName);
|
|
2977
|
-
if (!schema) {
|
|
2978
|
-
warnings.push({
|
|
2979
|
-
code: "CONFAB_UNKNOWN_TRAIT" /* UNKNOWN_TRAIT */,
|
|
2980
|
-
message: `Trait "@${normalizedName}" not found in schema registry (${this.schemaRegistry.size} schemas loaded)`,
|
|
2981
|
-
objectName,
|
|
2982
|
-
traitName: normalizedName,
|
|
2983
|
-
riskContribution: 5
|
|
2984
|
-
});
|
|
2985
|
-
return { errors, warnings };
|
|
2986
|
-
}
|
|
2987
|
-
for (const [key, value] of Object.entries(properties)) {
|
|
2988
|
-
const propSchema = schema.properties.find((p) => p.name === key);
|
|
2989
|
-
if (!propSchema) {
|
|
2990
|
-
const entry = {
|
|
2991
|
-
code: "CONFAB_UNKNOWN_PROPERTY" /* UNKNOWN_PROPERTY */,
|
|
2992
|
-
message: `Unknown property "${key}" on trait "@${normalizedName}". Known properties: ${schema.properties.map((p) => p.name).join(", ")}`,
|
|
2993
|
-
objectName,
|
|
2994
|
-
traitName: normalizedName,
|
|
2995
|
-
propertyName: key,
|
|
2996
|
-
riskContribution: 15
|
|
2997
|
-
};
|
|
2998
|
-
if (this.config.unknownPropertySeverity === "error") {
|
|
2999
|
-
errors.push({ ...entry, suggestion: `Remove "${key}" or check spelling` });
|
|
3000
|
-
} else {
|
|
3001
|
-
warnings.push(entry);
|
|
3002
|
-
}
|
|
3003
|
-
continue;
|
|
3004
|
-
}
|
|
3005
|
-
const typeError = this.validatePropertyType(propSchema, value, normalizedName, objectName);
|
|
3006
|
-
if (typeError) {
|
|
3007
|
-
errors.push(typeError);
|
|
3008
|
-
continue;
|
|
3009
|
-
}
|
|
3010
|
-
if (this.config.validateRanges) {
|
|
3011
|
-
const rangeError = this.validatePropertyRange(
|
|
3012
|
-
propSchema,
|
|
3013
|
-
value,
|
|
3014
|
-
normalizedName,
|
|
3015
|
-
objectName
|
|
3016
|
-
);
|
|
3017
|
-
if (rangeError) {
|
|
3018
|
-
errors.push(rangeError);
|
|
3019
|
-
}
|
|
3020
|
-
}
|
|
3021
|
-
if (propSchema.type === "enum" && propSchema.enumValues) {
|
|
3022
|
-
if (typeof value === "string" && !propSchema.enumValues.includes(value)) {
|
|
3023
|
-
errors.push({
|
|
3024
|
-
code: "CONFAB_INVALID_ENUM_VALUE" /* INVALID_ENUM_VALUE */,
|
|
3025
|
-
message: `Invalid value "${value}" for property "${key}" on trait "@${normalizedName}". Allowed values: ${propSchema.enumValues.join(", ")}`,
|
|
3026
|
-
objectName,
|
|
3027
|
-
traitName: normalizedName,
|
|
3028
|
-
propertyName: key,
|
|
3029
|
-
suggestion: `Use one of: ${propSchema.enumValues.join(", ")}`,
|
|
3030
|
-
riskContribution: 20
|
|
3031
|
-
});
|
|
3032
|
-
}
|
|
3033
|
-
}
|
|
3034
|
-
}
|
|
3035
|
-
for (const propSchema of schema.properties) {
|
|
3036
|
-
if (propSchema.required && !(propSchema.name in properties)) {
|
|
3037
|
-
errors.push({
|
|
3038
|
-
code: "CONFAB_MISSING_REQUIRED_PROPERTY" /* MISSING_REQUIRED_PROPERTY */,
|
|
3039
|
-
message: `Missing required property "${propSchema.name}" on trait "@${normalizedName}"`,
|
|
3040
|
-
objectName,
|
|
3041
|
-
traitName: normalizedName,
|
|
3042
|
-
propertyName: propSchema.name,
|
|
3043
|
-
suggestion: `Add property "${propSchema.name}" (${propSchema.type})`,
|
|
3044
|
-
riskContribution: 20
|
|
3045
|
-
});
|
|
3046
|
-
}
|
|
3047
|
-
}
|
|
3048
|
-
return { errors, warnings };
|
|
3049
|
-
}
|
|
3050
|
-
/**
|
|
3051
|
-
* Check if a trait name is in the schema registry.
|
|
3052
|
-
*/
|
|
3053
|
-
isKnownTrait(traitName) {
|
|
3054
|
-
const normalized = traitName.startsWith("@") ? traitName.slice(1) : traitName;
|
|
3055
|
-
return this.schemaRegistry.has(normalized);
|
|
3056
|
-
}
|
|
3057
|
-
/**
|
|
3058
|
-
* Get the schema for a trait.
|
|
3059
|
-
*/
|
|
3060
|
-
getTraitSchema(traitName) {
|
|
3061
|
-
const normalized = traitName.startsWith("@") ? traitName.slice(1) : traitName;
|
|
3062
|
-
return this.schemaRegistry.get(normalized);
|
|
3063
|
-
}
|
|
3064
|
-
/**
|
|
3065
|
-
* Get all registered trait names.
|
|
3066
|
-
*/
|
|
3067
|
-
getRegisteredTraits() {
|
|
3068
|
-
return Array.from(this.schemaRegistry.keys());
|
|
3069
|
-
}
|
|
3070
|
-
/**
|
|
3071
|
-
* Get the number of registered schemas.
|
|
3072
|
-
*/
|
|
3073
|
-
get schemaCount() {
|
|
3074
|
-
return this.schemaRegistry.size;
|
|
3075
|
-
}
|
|
3076
|
-
/**
|
|
3077
|
-
* Register additional trait schemas at runtime.
|
|
3078
|
-
*/
|
|
3079
|
-
registerSchema(schema) {
|
|
3080
|
-
this.schemaRegistry.set(schema.name, schema);
|
|
3081
|
-
}
|
|
3082
|
-
/**
|
|
3083
|
-
* Register multiple trait schemas at runtime.
|
|
3084
|
-
*/
|
|
3085
|
-
registerSchemas(schemas) {
|
|
3086
|
-
for (const schema of schemas) {
|
|
3087
|
-
this.schemaRegistry.set(schema.name, schema);
|
|
3088
|
-
}
|
|
3089
|
-
}
|
|
3090
|
-
// =========================================================================
|
|
3091
|
-
// PRIVATE METHODS
|
|
3092
|
-
// =========================================================================
|
|
3093
|
-
/**
|
|
3094
|
-
* Validate a single object's traits.
|
|
3095
|
-
*/
|
|
3096
|
-
validateObject(obj) {
|
|
3097
|
-
const errors = [];
|
|
3098
|
-
const warnings = [];
|
|
3099
|
-
let traitsChecked = 0;
|
|
3100
|
-
let propertiesChecked = 0;
|
|
3101
|
-
const objectTraitNames = [];
|
|
3102
|
-
const authority = obj.provenance?.context?.authority;
|
|
3103
|
-
if (authority === "system" || authority === "verified") {
|
|
3104
|
-
return { errors, warnings, traitsChecked: 0, propertiesChecked: 0 };
|
|
3105
|
-
}
|
|
3106
|
-
if (obj.traits) {
|
|
3107
|
-
for (const trait of obj.traits) {
|
|
3108
|
-
traitsChecked++;
|
|
3109
|
-
const traitName = trait.name.startsWith("@") ? trait.name.slice(1) : trait.name;
|
|
3110
|
-
objectTraitNames.push(traitName);
|
|
3111
|
-
const properties = {};
|
|
3112
|
-
const traitExt = trait;
|
|
3113
|
-
if (traitExt.args) {
|
|
3114
|
-
for (const arg of traitExt.args) {
|
|
3115
|
-
properties[arg.key] = arg.value;
|
|
3116
|
-
propertiesChecked++;
|
|
3117
|
-
}
|
|
3118
|
-
} else if (trait.config) {
|
|
3119
|
-
for (const [key, value] of Object.entries(trait.config)) {
|
|
3120
|
-
properties[key] = value;
|
|
3121
|
-
propertiesChecked++;
|
|
3122
|
-
}
|
|
3123
|
-
}
|
|
3124
|
-
const result = this.validateTraitProperties(traitName, properties, obj.name);
|
|
3125
|
-
errors.push(...result.errors);
|
|
3126
|
-
warnings.push(...result.warnings);
|
|
3127
|
-
}
|
|
3128
|
-
}
|
|
3129
|
-
if (this.config.validatePrerequisites) {
|
|
3130
|
-
for (const traitName of objectTraitNames) {
|
|
3131
|
-
const schema = this.schemaRegistry.get(traitName);
|
|
3132
|
-
if (schema?.requires) {
|
|
3133
|
-
for (const req of schema.requires) {
|
|
3134
|
-
if (!objectTraitNames.includes(req)) {
|
|
3135
|
-
errors.push({
|
|
3136
|
-
code: "CONFAB_MISSING_REQUIRED_TRAIT" /* MISSING_REQUIRED_TRAIT */,
|
|
3137
|
-
message: `Trait "@${traitName}" requires "@${req}" but it is not present on object "${obj.name}"`,
|
|
3138
|
-
objectName: obj.name,
|
|
3139
|
-
traitName,
|
|
3140
|
-
suggestion: `Add @${req} to object "${obj.name}"`,
|
|
3141
|
-
riskContribution: 15
|
|
3142
|
-
});
|
|
3143
|
-
}
|
|
3144
|
-
}
|
|
3145
|
-
}
|
|
3146
|
-
}
|
|
3147
|
-
}
|
|
3148
|
-
if (this.config.validateConflicts) {
|
|
3149
|
-
for (const traitName of objectTraitNames) {
|
|
3150
|
-
const schema = this.schemaRegistry.get(traitName);
|
|
3151
|
-
if (schema?.conflictsWith) {
|
|
3152
|
-
for (const conflict of schema.conflictsWith) {
|
|
3153
|
-
if (objectTraitNames.includes(conflict)) {
|
|
3154
|
-
errors.push({
|
|
3155
|
-
code: "CONFAB_CONFLICTING_TRAITS" /* CONFLICTING_TRAITS */,
|
|
3156
|
-
message: `Traits "@${traitName}" and "@${conflict}" are mutually exclusive on object "${obj.name}"`,
|
|
3157
|
-
objectName: obj.name,
|
|
3158
|
-
traitName,
|
|
3159
|
-
suggestion: `Remove either @${traitName} or @${conflict}`,
|
|
3160
|
-
riskContribution: 25
|
|
3161
|
-
});
|
|
3162
|
-
}
|
|
3163
|
-
}
|
|
3164
|
-
}
|
|
3165
|
-
}
|
|
3166
|
-
}
|
|
3167
|
-
if (obj.children) {
|
|
3168
|
-
for (const child of obj.children) {
|
|
3169
|
-
const childResult = this.validateObject(child);
|
|
3170
|
-
errors.push(...childResult.errors);
|
|
3171
|
-
warnings.push(...childResult.warnings);
|
|
3172
|
-
traitsChecked += childResult.traitsChecked;
|
|
3173
|
-
propertiesChecked += childResult.propertiesChecked;
|
|
3174
|
-
}
|
|
3175
|
-
}
|
|
3176
|
-
return { errors, warnings, traitsChecked, propertiesChecked };
|
|
3177
|
-
}
|
|
3178
|
-
/**
|
|
3179
|
-
* Validate that a property value matches its expected type.
|
|
3180
|
-
*/
|
|
3181
|
-
validatePropertyType(propSchema, value, traitName, objectName) {
|
|
3182
|
-
if (value === null || value === void 0) return null;
|
|
3183
|
-
if (propSchema.type === "any") return null;
|
|
3184
|
-
const actualType = typeof value;
|
|
3185
|
-
switch (propSchema.type) {
|
|
3186
|
-
case "string":
|
|
3187
|
-
case "color":
|
|
3188
|
-
if (actualType !== "string") {
|
|
3189
|
-
return {
|
|
3190
|
-
code: "CONFAB_TYPE_MISMATCH" /* TYPE_MISMATCH */,
|
|
3191
|
-
message: `Property "${propSchema.name}" on "@${traitName}" expects ${propSchema.type} but got ${actualType}`,
|
|
3192
|
-
objectName,
|
|
3193
|
-
traitName,
|
|
3194
|
-
propertyName: propSchema.name,
|
|
3195
|
-
suggestion: `Convert value to a string`,
|
|
3196
|
-
riskContribution: 20
|
|
3197
|
-
};
|
|
3198
|
-
}
|
|
3199
|
-
break;
|
|
3200
|
-
case "number":
|
|
3201
|
-
if (actualType !== "number") {
|
|
3202
|
-
return {
|
|
3203
|
-
code: "CONFAB_TYPE_MISMATCH" /* TYPE_MISMATCH */,
|
|
3204
|
-
message: `Property "${propSchema.name}" on "@${traitName}" expects number but got ${actualType}`,
|
|
3205
|
-
objectName,
|
|
3206
|
-
traitName,
|
|
3207
|
-
propertyName: propSchema.name,
|
|
3208
|
-
suggestion: `Use a numeric value`,
|
|
3209
|
-
riskContribution: 20
|
|
3210
|
-
};
|
|
3211
|
-
}
|
|
3212
|
-
break;
|
|
3213
|
-
case "boolean":
|
|
3214
|
-
if (actualType !== "boolean") {
|
|
3215
|
-
return {
|
|
3216
|
-
code: "CONFAB_TYPE_MISMATCH" /* TYPE_MISMATCH */,
|
|
3217
|
-
message: `Property "${propSchema.name}" on "@${traitName}" expects boolean but got ${actualType}`,
|
|
3218
|
-
objectName,
|
|
3219
|
-
traitName,
|
|
3220
|
-
propertyName: propSchema.name,
|
|
3221
|
-
suggestion: `Use true or false`,
|
|
3222
|
-
riskContribution: 20
|
|
3223
|
-
};
|
|
3224
|
-
}
|
|
3225
|
-
break;
|
|
3226
|
-
case "array":
|
|
3227
|
-
case "vector3":
|
|
3228
|
-
if (!Array.isArray(value)) {
|
|
3229
|
-
return {
|
|
3230
|
-
code: "CONFAB_TYPE_MISMATCH" /* TYPE_MISMATCH */,
|
|
3231
|
-
message: `Property "${propSchema.name}" on "@${traitName}" expects ${propSchema.type} but got ${actualType}`,
|
|
3232
|
-
objectName,
|
|
3233
|
-
traitName,
|
|
3234
|
-
propertyName: propSchema.name,
|
|
3235
|
-
suggestion: `Use an array value, e.g., [0, 0, 0]`,
|
|
3236
|
-
riskContribution: 20
|
|
3237
|
-
};
|
|
3238
|
-
}
|
|
3239
|
-
break;
|
|
3240
|
-
case "object":
|
|
3241
|
-
if (actualType !== "object" || Array.isArray(value)) {
|
|
3242
|
-
return {
|
|
3243
|
-
code: "CONFAB_TYPE_MISMATCH" /* TYPE_MISMATCH */,
|
|
3244
|
-
message: `Property "${propSchema.name}" on "@${traitName}" expects object but got ${Array.isArray(value) ? "array" : actualType}`,
|
|
3245
|
-
objectName,
|
|
3246
|
-
traitName,
|
|
3247
|
-
propertyName: propSchema.name,
|
|
3248
|
-
suggestion: `Use an object value, e.g., { key: value }`,
|
|
3249
|
-
riskContribution: 20
|
|
3250
|
-
};
|
|
3251
|
-
}
|
|
3252
|
-
break;
|
|
3253
|
-
case "enum":
|
|
3254
|
-
if (actualType !== "string") {
|
|
3255
|
-
return {
|
|
3256
|
-
code: "CONFAB_TYPE_MISMATCH" /* TYPE_MISMATCH */,
|
|
3257
|
-
message: `Property "${propSchema.name}" on "@${traitName}" expects enum (string) but got ${actualType}`,
|
|
3258
|
-
objectName,
|
|
3259
|
-
traitName,
|
|
3260
|
-
propertyName: propSchema.name,
|
|
3261
|
-
suggestion: propSchema.enumValues ? `Use one of: ${propSchema.enumValues.join(", ")}` : `Use a string value`,
|
|
3262
|
-
riskContribution: 20
|
|
3263
|
-
};
|
|
3264
|
-
}
|
|
3265
|
-
break;
|
|
3266
|
-
}
|
|
3267
|
-
return null;
|
|
3268
|
-
}
|
|
3269
|
-
/**
|
|
3270
|
-
* Validate that a numeric property value is within its allowed range.
|
|
3271
|
-
*/
|
|
3272
|
-
validatePropertyRange(propSchema, value, traitName, objectName) {
|
|
3273
|
-
if (typeof value !== "number") return null;
|
|
3274
|
-
if (propSchema.min !== void 0 && value < propSchema.min) {
|
|
3275
|
-
return {
|
|
3276
|
-
code: "CONFAB_VALUE_OUT_OF_RANGE" /* VALUE_OUT_OF_RANGE */,
|
|
3277
|
-
message: `Property "${propSchema.name}" on "@${traitName}" has value ${value} but minimum is ${propSchema.min}`,
|
|
3278
|
-
objectName,
|
|
3279
|
-
traitName,
|
|
3280
|
-
propertyName: propSchema.name,
|
|
3281
|
-
suggestion: `Use a value >= ${propSchema.min}`,
|
|
3282
|
-
riskContribution: 15
|
|
3283
|
-
};
|
|
3284
|
-
}
|
|
3285
|
-
if (propSchema.max !== void 0 && value > propSchema.max) {
|
|
3286
|
-
return {
|
|
3287
|
-
code: "CONFAB_VALUE_OUT_OF_RANGE" /* VALUE_OUT_OF_RANGE */,
|
|
3288
|
-
message: `Property "${propSchema.name}" on "@${traitName}" has value ${value} but maximum is ${propSchema.max}`,
|
|
3289
|
-
objectName,
|
|
3290
|
-
traitName,
|
|
3291
|
-
propertyName: propSchema.name,
|
|
3292
|
-
suggestion: `Use a value <= ${propSchema.max}`,
|
|
3293
|
-
riskContribution: 15
|
|
3294
|
-
};
|
|
3295
|
-
}
|
|
3296
|
-
return null;
|
|
3297
|
-
}
|
|
3298
|
-
/**
|
|
3299
|
-
* Calculate the overall confabulation risk score.
|
|
3300
|
-
*/
|
|
3301
|
-
calculateRiskScore(errors, warnings) {
|
|
3302
|
-
let score = 0;
|
|
3303
|
-
for (const error of errors) {
|
|
3304
|
-
score += error.riskContribution;
|
|
3305
|
-
}
|
|
3306
|
-
for (const warning of warnings) {
|
|
3307
|
-
score += warning.riskContribution;
|
|
3308
|
-
}
|
|
3309
|
-
return Math.min(100, score);
|
|
3310
|
-
}
|
|
3311
|
-
};
|
|
3312
|
-
globalConfabulationValidator = null;
|
|
3313
|
-
}
|
|
3314
|
-
});
|
|
3315
|
-
function getRBAC(tokenIssuer) {
|
|
3316
|
-
if (!globalRBAC) {
|
|
3317
|
-
globalRBAC = new AgentRBAC(tokenIssuer);
|
|
3318
|
-
}
|
|
3319
|
-
return globalRBAC;
|
|
3320
|
-
}
|
|
3321
|
-
var RESOURCE_PERMISSION_MAP, AgentRBAC, globalRBAC;
|
|
3322
|
-
var init_AgentRBAC = __esm({
|
|
3323
|
-
"src/compiler/identity/AgentRBAC.ts"() {
|
|
3324
|
-
init_AgentIdentity();
|
|
3325
|
-
init_AgentTokenIssuer();
|
|
3326
|
-
init_CulturalCompatibilityChecker();
|
|
3327
|
-
init_ConfabulationValidator();
|
|
3328
|
-
RESOURCE_PERMISSION_MAP = {
|
|
3329
|
-
["source_file" /* SOURCE_FILE */]: {
|
|
3330
|
-
read: "read:source" /* READ_SOURCE */,
|
|
3331
|
-
write: "write:ast" /* WRITE_AST */,
|
|
3332
|
-
// Source modification creates AST
|
|
3333
|
-
execute: "execute:optimization" /* EXECUTE_OPTIMIZATION */,
|
|
3334
|
-
// Not applicable
|
|
3335
|
-
transform: "transform:ast" /* TRANSFORM_AST */
|
|
3336
|
-
// Not applicable
|
|
3337
|
-
},
|
|
3338
|
-
["ast" /* AST */]: {
|
|
3339
|
-
read: "read:ast" /* READ_AST */,
|
|
3340
|
-
write: "write:ast" /* WRITE_AST */,
|
|
3341
|
-
execute: "execute:optimization" /* EXECUTE_OPTIMIZATION */,
|
|
3342
|
-
transform: "transform:ast" /* TRANSFORM_AST */
|
|
3343
|
-
},
|
|
3344
|
-
["ir" /* IR */]: {
|
|
3345
|
-
read: "read:ir" /* READ_IR */,
|
|
3346
|
-
write: "write:ir" /* WRITE_IR */,
|
|
3347
|
-
execute: "execute:codegen" /* EXECUTE_CODEGEN */,
|
|
3348
|
-
transform: "transform:ir" /* TRANSFORM_IR */
|
|
3349
|
-
},
|
|
3350
|
-
["code" /* CODE */]: {
|
|
3351
|
-
read: "read:code" /* READ_CODE */,
|
|
3352
|
-
write: "write:code" /* WRITE_CODE */,
|
|
3353
|
-
execute: "execute:codegen" /* EXECUTE_CODEGEN */,
|
|
3354
|
-
transform: "transform:ir" /* TRANSFORM_IR */
|
|
3355
|
-
// Not applicable
|
|
3356
|
-
},
|
|
3357
|
-
["output" /* OUTPUT */]: {
|
|
3358
|
-
read: "read:code" /* READ_CODE */,
|
|
3359
|
-
write: "write:output" /* WRITE_OUTPUT */,
|
|
3360
|
-
execute: "execute:export" /* EXECUTE_EXPORT */,
|
|
3361
|
-
transform: "write:output" /* WRITE_OUTPUT */
|
|
3362
|
-
// Not applicable
|
|
3363
|
-
},
|
|
3364
|
-
["config" /* CONFIG */]: {
|
|
3365
|
-
read: "read:config" /* READ_CONFIG */,
|
|
3366
|
-
write: "write:ast" /* WRITE_AST */,
|
|
3367
|
-
// Config changes trigger rebuild
|
|
3368
|
-
execute: "execute:optimization" /* EXECUTE_OPTIMIZATION */,
|
|
3369
|
-
// Not applicable
|
|
3370
|
-
transform: "transform:ast" /* TRANSFORM_AST */
|
|
3371
|
-
// Not applicable
|
|
3372
|
-
}
|
|
3373
|
-
};
|
|
3374
|
-
AgentRBAC = class {
|
|
3375
|
-
constructor(tokenIssuer) {
|
|
3376
|
-
/** Package scope restrictions (role → allowed paths) */
|
|
3377
|
-
this.scopeRestrictions = /* @__PURE__ */ new Map();
|
|
3378
|
-
/** Workflow step restrictions (role → allowed steps) */
|
|
3379
|
-
this.workflowRestrictions = /* @__PURE__ */ new Map();
|
|
3380
|
-
this.tokenIssuer = tokenIssuer || getTokenIssuer();
|
|
3381
|
-
this.initializeWorkflowRestrictions();
|
|
3382
|
-
}
|
|
3383
|
-
/**
|
|
3384
|
-
* Initialize default workflow step restrictions for each role
|
|
3385
|
-
*/
|
|
3386
|
-
initializeWorkflowRestrictions() {
|
|
3387
|
-
this.workflowRestrictions.set("syntax_analyzer" /* SYNTAX_ANALYZER */, [
|
|
3388
|
-
"parse_tokens" /* PARSE_TOKENS */,
|
|
3389
|
-
"build_ast" /* BUILD_AST */
|
|
3390
|
-
]);
|
|
3391
|
-
this.workflowRestrictions.set("ast_optimizer" /* AST_OPTIMIZER */, [
|
|
3392
|
-
"analyze_ast" /* ANALYZE_AST */,
|
|
3393
|
-
"apply_transforms" /* APPLY_TRANSFORMS */
|
|
3394
|
-
]);
|
|
3395
|
-
this.workflowRestrictions.set("code_generator" /* CODE_GENERATOR */, [
|
|
3396
|
-
"select_instructions" /* SELECT_INSTRUCTIONS */,
|
|
3397
|
-
"generate_assembly" /* GENERATE_ASSEMBLY */
|
|
3398
|
-
]);
|
|
3399
|
-
this.workflowRestrictions.set("exporter" /* EXPORTER */, [
|
|
3400
|
-
"format_output" /* FORMAT_OUTPUT */,
|
|
3401
|
-
"serialize" /* SERIALIZE */
|
|
3402
|
-
]);
|
|
3403
|
-
this.workflowRestrictions.set("orchestrator" /* ORCHESTRATOR */, Object.values(WorkflowStep));
|
|
3404
|
-
}
|
|
3405
|
-
/**
|
|
3406
|
-
* Set scope restriction for an agent role
|
|
3407
|
-
*
|
|
3408
|
-
* Example: Restrict syntax analyzer to only process files in 'packages/core'
|
|
3409
|
-
*/
|
|
3410
|
-
setScopeRestriction(role, allowedPaths) {
|
|
3411
|
-
this.scopeRestrictions.set(role, allowedPaths);
|
|
3412
|
-
}
|
|
3413
|
-
/**
|
|
3414
|
-
* Check if agent can access resource
|
|
3415
|
-
*/
|
|
3416
|
-
checkAccess(request) {
|
|
3417
|
-
const { token, resourceType, operation, resourcePath, expectedWorkflowStep } = request;
|
|
3418
|
-
const verificationResult = this.tokenIssuer.verifyToken(token);
|
|
3419
|
-
if (!verificationResult.valid) {
|
|
3420
|
-
return {
|
|
3421
|
-
allowed: false,
|
|
3422
|
-
reason: `Token verification failed: ${verificationResult.error}`
|
|
3423
|
-
};
|
|
3424
|
-
}
|
|
3425
|
-
const payload = verificationResult.payload;
|
|
3426
|
-
const requiredPermission = RESOURCE_PERMISSION_MAP[resourceType][operation];
|
|
3427
|
-
if (!payload.permissions.includes(requiredPermission)) {
|
|
3428
|
-
return {
|
|
3429
|
-
allowed: false,
|
|
3430
|
-
reason: `Missing required permission: ${requiredPermission}`,
|
|
3431
|
-
requiredPermission,
|
|
3432
|
-
agentRole: payload.agent_role
|
|
3433
|
-
};
|
|
3434
|
-
}
|
|
3435
|
-
if (resourcePath) {
|
|
3436
|
-
const scopeAllowed = this.validateScope(payload, resourcePath);
|
|
3437
|
-
if (!scopeAllowed) {
|
|
3438
|
-
return {
|
|
3439
|
-
allowed: false,
|
|
3440
|
-
reason: `Resource path '${resourcePath}' is outside agent scope: ${payload.scope || "unrestricted"}`,
|
|
3441
|
-
agentRole: payload.agent_role
|
|
3442
|
-
};
|
|
3443
|
-
}
|
|
3444
|
-
}
|
|
3445
|
-
if (expectedWorkflowStep) {
|
|
3446
|
-
const currentStep = payload.intent.workflow_step;
|
|
3447
|
-
if (currentStep !== expectedWorkflowStep) {
|
|
3448
|
-
return {
|
|
3449
|
-
allowed: false,
|
|
3450
|
-
reason: `Workflow step mismatch: expected ${expectedWorkflowStep}, agent is at ${currentStep}`,
|
|
3451
|
-
agentRole: payload.agent_role
|
|
3452
|
-
};
|
|
3453
|
-
}
|
|
3454
|
-
}
|
|
3455
|
-
const allowedSteps = this.workflowRestrictions.get(payload.agent_role);
|
|
3456
|
-
if (allowedSteps && !allowedSteps.includes(payload.intent.workflow_step)) {
|
|
3457
|
-
return {
|
|
3458
|
-
allowed: false,
|
|
3459
|
-
reason: `Role ${payload.agent_role} cannot execute workflow step ${payload.intent.workflow_step}`,
|
|
3460
|
-
agentRole: payload.agent_role
|
|
3461
|
-
};
|
|
3462
|
-
}
|
|
3463
|
-
return {
|
|
3464
|
-
allowed: true,
|
|
3465
|
-
agentRole: payload.agent_role
|
|
3466
|
-
};
|
|
3467
|
-
}
|
|
3468
|
-
/**
|
|
3469
|
-
* Validate resource path is within agent's scope
|
|
3470
|
-
*/
|
|
3471
|
-
validateScope(payload, resourcePath) {
|
|
3472
|
-
if (!payload.scope) {
|
|
3473
|
-
return true;
|
|
3474
|
-
}
|
|
3475
|
-
const normalizedResource = path.normalize(resourcePath);
|
|
3476
|
-
const normalizedScope = path.normalize(payload.scope);
|
|
3477
|
-
return normalizedResource.startsWith(normalizedScope);
|
|
3478
|
-
}
|
|
3479
|
-
/**
|
|
3480
|
-
* Convenience method: Check if agent can read source file
|
|
3481
|
-
*/
|
|
3482
|
-
canReadSource(token, filePath) {
|
|
3483
|
-
return this.checkAccess({
|
|
3484
|
-
token,
|
|
3485
|
-
resourceType: "source_file" /* SOURCE_FILE */,
|
|
3486
|
-
operation: "read",
|
|
3487
|
-
resourcePath: filePath
|
|
3488
|
-
});
|
|
3489
|
-
}
|
|
3490
|
-
/**
|
|
3491
|
-
* Convenience method: Check if agent can modify AST
|
|
3492
|
-
*/
|
|
3493
|
-
canModifyAST(token, expectedWorkflowStep) {
|
|
3494
|
-
return this.checkAccess({
|
|
3495
|
-
token,
|
|
3496
|
-
resourceType: "ast" /* AST */,
|
|
3497
|
-
operation: "write",
|
|
3498
|
-
expectedWorkflowStep
|
|
3499
|
-
});
|
|
3500
|
-
}
|
|
3501
|
-
/**
|
|
3502
|
-
* Convenience method: Check if agent can generate code
|
|
3503
|
-
*/
|
|
3504
|
-
canGenerateCode(token) {
|
|
3505
|
-
return this.checkAccess({
|
|
3506
|
-
token,
|
|
3507
|
-
resourceType: "code" /* CODE */,
|
|
3508
|
-
operation: "write",
|
|
3509
|
-
expectedWorkflowStep: "generate_assembly" /* GENERATE_ASSEMBLY */
|
|
3510
|
-
});
|
|
3511
|
-
}
|
|
3512
|
-
/**
|
|
3513
|
-
* Convenience method: Check if agent can export to output path
|
|
3514
|
-
*/
|
|
3515
|
-
canExport(token, outputPath) {
|
|
3516
|
-
return this.checkAccess({
|
|
3517
|
-
token,
|
|
3518
|
-
resourceType: "output" /* OUTPUT */,
|
|
3519
|
-
operation: "write",
|
|
3520
|
-
resourcePath: outputPath,
|
|
3521
|
-
expectedWorkflowStep: "serialize" /* SERIALIZE */
|
|
3522
|
-
});
|
|
3523
|
-
}
|
|
3524
|
-
/**
|
|
3525
|
-
* Extract agent role from token (without full verification)
|
|
3526
|
-
*/
|
|
3527
|
-
extractRole(token) {
|
|
3528
|
-
const result = this.tokenIssuer.verifyToken(token);
|
|
3529
|
-
return result.valid && result.payload ? result.payload.agent_role : null;
|
|
3530
|
-
}
|
|
3531
|
-
/**
|
|
3532
|
-
* Get agent's current workflow step
|
|
3533
|
-
*/
|
|
3534
|
-
getWorkflowStep(token) {
|
|
3535
|
-
const result = this.tokenIssuer.verifyToken(token);
|
|
3536
|
-
return result.valid && result.payload ? result.payload.intent.workflow_step : null;
|
|
3537
|
-
}
|
|
3538
|
-
// ===========================================================================
|
|
3539
|
-
// CONFABULATION RISK LAYER (v1.1.0)
|
|
3540
|
-
// ===========================================================================
|
|
3541
|
-
/**
|
|
3542
|
-
* Check access with confabulation gate.
|
|
3543
|
-
*
|
|
3544
|
-
* This is the primary enforcement point for AI-generated content. It chains:
|
|
3545
|
-
* 1. Standard RBAC permission check (token, role, scope, workflow)
|
|
3546
|
-
* 2. Confabulation schema validation (trait properties against 1,800+ schemas)
|
|
3547
|
-
*
|
|
3548
|
-
* If the RBAC check fails, the confabulation check is skipped (no point
|
|
3549
|
-
* validating content from an unauthorized agent).
|
|
3550
|
-
*
|
|
3551
|
-
* @param request - Standard resource access request
|
|
3552
|
-
* @param composition - The HoloComposition to validate for confabulation
|
|
3553
|
-
* @param confabConfig - Optional confabulation validator configuration
|
|
3554
|
-
* @returns Extended access decision with confabulation validation results
|
|
3555
|
-
*/
|
|
3556
|
-
checkAccessWithConfabulationGate(request, composition, confabConfig) {
|
|
3557
|
-
const rbacDecision = this.checkAccess(request);
|
|
3558
|
-
if (!rbacDecision.allowed) {
|
|
3559
|
-
return rbacDecision;
|
|
3560
|
-
}
|
|
3561
|
-
const validator = confabConfig ? new ConfabulationValidator(confabConfig) : getConfabulationValidator();
|
|
3562
|
-
const confabResult = validator.validateComposition(composition);
|
|
3563
|
-
if (!confabResult.valid) {
|
|
3564
|
-
return {
|
|
3565
|
-
allowed: false,
|
|
3566
|
-
reason: `Confabulation detected (risk score: ${confabResult.riskScore}/100, ${confabResult.errors.length} error(s)): ` + confabResult.errors.map((e) => e.message).join("; "),
|
|
3567
|
-
agentRole: rbacDecision.agentRole,
|
|
3568
|
-
confabulation: confabResult
|
|
3569
|
-
};
|
|
3570
|
-
}
|
|
3571
|
-
return {
|
|
3572
|
-
...rbacDecision,
|
|
3573
|
-
confabulation: confabResult
|
|
3574
|
-
};
|
|
3575
|
-
}
|
|
3576
|
-
/**
|
|
3577
|
-
* Validate a composition for confabulation risk WITHOUT requiring an RBAC token.
|
|
3578
|
-
*
|
|
3579
|
-
* This is useful for the validate_holoscript MCP tool and the ai-validator
|
|
3580
|
-
* package which may not have an agent token but still need to check for
|
|
3581
|
-
* confabulated trait properties.
|
|
3582
|
-
*
|
|
3583
|
-
* @param composition - The HoloComposition to validate
|
|
3584
|
-
* @param confabConfig - Optional confabulation validator configuration
|
|
3585
|
-
* @returns Confabulation validation result
|
|
3586
|
-
*/
|
|
3587
|
-
validateConfabulation(composition, confabConfig) {
|
|
3588
|
-
const validator = confabConfig ? new ConfabulationValidator(confabConfig) : getConfabulationValidator();
|
|
3589
|
-
return validator.validateComposition(composition);
|
|
3590
|
-
}
|
|
3591
|
-
// ===========================================================================
|
|
3592
|
-
// CULTURAL PROFILE INTEGRATION
|
|
3593
|
-
// ===========================================================================
|
|
3594
|
-
/**
|
|
3595
|
-
* Extract cultural profile metadata from an agent's JWT token.
|
|
3596
|
-
*
|
|
3597
|
-
* @param token - Agent JWT token
|
|
3598
|
-
* @returns The cultural profile if present, or null
|
|
3599
|
-
*/
|
|
3600
|
-
extractCulturalProfile(token) {
|
|
3601
|
-
const result = this.tokenIssuer.verifyToken(token);
|
|
3602
|
-
if (!result.valid || !result.payload) return null;
|
|
3603
|
-
return result.payload.cultural_profile ?? null;
|
|
3604
|
-
}
|
|
3605
|
-
/**
|
|
3606
|
-
* Validate cultural compatibility across multiple agent tokens.
|
|
3607
|
-
*
|
|
3608
|
-
* Extracts cultural profiles from each provided token and runs them
|
|
3609
|
-
* through the CulturalCompatibilityChecker. Agents whose tokens
|
|
3610
|
-
* do not contain cultural profiles are silently skipped.
|
|
3611
|
-
*
|
|
3612
|
-
* @param agentTokens - Map of agent name to JWT token
|
|
3613
|
-
* @param normSets - Optional map of agent name to norm_set arrays
|
|
3614
|
-
* (norms are composition-level, not token-level)
|
|
3615
|
-
* @returns Cultural compatibility result, or null if fewer than 2 agents
|
|
3616
|
-
* have cultural profiles
|
|
3617
|
-
*/
|
|
3618
|
-
validateCulturalCompatibility(agentTokens, normSets) {
|
|
3619
|
-
const entries = [];
|
|
3620
|
-
for (const [name, token] of agentTokens) {
|
|
3621
|
-
const profile = this.extractCulturalProfile(token);
|
|
3622
|
-
if (profile) {
|
|
3623
|
-
entries.push({
|
|
3624
|
-
name,
|
|
3625
|
-
profile: {
|
|
3626
|
-
cooperation_index: profile.cooperation_index,
|
|
3627
|
-
cultural_family: profile.cultural_family,
|
|
3628
|
-
prompt_dialect: profile.prompt_dialect,
|
|
3629
|
-
norm_set: normSets?.get(name) ?? []
|
|
3630
|
-
}
|
|
3631
|
-
});
|
|
3632
|
-
}
|
|
3633
|
-
}
|
|
3634
|
-
if (entries.length < 2) return null;
|
|
3635
|
-
const checker = new CulturalCompatibilityChecker();
|
|
3636
|
-
return checker.check(entries);
|
|
3637
|
-
}
|
|
3638
|
-
};
|
|
3639
|
-
globalRBAC = null;
|
|
3640
|
-
}
|
|
3641
|
-
});
|
|
3642
|
-
|
|
3643
|
-
export { BUILTIN_NORMS, HOLOSCRIPT_RESOURCE_SCHEME, HoloScriptCapabilitySemantics, criticalMassForChange, getBuiltinNorm, getCapabilityTokenIssuer, getRBAC, getTokenIssuer, init_AgentRBAC, init_AgentTokenIssuer, init_CapabilityToken, init_CapabilityTokenIssuer, init_CultureTraits, normsByCategory };
|
|
3644
|
-
//# sourceMappingURL=chunk-V42NTCFH.js.map
|
|
3645
|
-
//# sourceMappingURL=chunk-V42NTCFH.js.map
|