@fabricorg/platform 1.10.0 → 1.10.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (209) hide show
  1. package/CHANGELOG.md +54 -0
  2. package/README.md +32 -3
  3. package/dist/actions/index.cjs +45 -26
  4. package/dist/actions/index.cjs.map +1 -1
  5. package/dist/actions/index.d.cts +225 -226
  6. package/dist/actions/index.d.ts +225 -226
  7. package/dist/actions/index.js +41 -2
  8. package/dist/actions/index.js.map +1 -1
  9. package/dist/adapters/index.cjs +696 -66
  10. package/dist/adapters/index.cjs.map +1 -1
  11. package/dist/adapters/index.d.cts +367 -365
  12. package/dist/adapters/index.d.ts +367 -365
  13. package/dist/adapters/index.js +682 -2
  14. package/dist/adapters/index.js.map +1 -1
  15. package/dist/agent-hitl/index.cjs +21 -10
  16. package/dist/agent-hitl/index.cjs.map +1 -1
  17. package/dist/agent-hitl/index.d.cts +30 -30
  18. package/dist/agent-hitl/index.d.ts +30 -30
  19. package/dist/agent-hitl/index.js +21 -2
  20. package/dist/agent-hitl/index.js.map +1 -1
  21. package/dist/certification/index.cjs +109 -24
  22. package/dist/certification/index.cjs.map +1 -1
  23. package/dist/certification/index.d.cts +33 -39
  24. package/dist/certification/index.d.ts +33 -39
  25. package/dist/certification/index.js +107 -8
  26. package/dist/certification/index.js.map +1 -1
  27. package/dist/discovery/index.cjs +12 -10
  28. package/dist/discovery/index.cjs.map +1 -1
  29. package/dist/discovery/index.d.cts +2 -10
  30. package/dist/discovery/index.d.ts +2 -10
  31. package/dist/discovery/index.js +12 -2
  32. package/dist/discovery/index.js.map +1 -1
  33. package/dist/engine-B4csEOEc.js +223 -0
  34. package/dist/engine-B4csEOEc.js.map +1 -0
  35. package/dist/engine-BqScuhrT.cjs +246 -0
  36. package/dist/engine-BqScuhrT.cjs.map +1 -0
  37. package/dist/events/index.cjs +39 -10
  38. package/dist/events/index.cjs.map +1 -1
  39. package/dist/events/index.d.cts +43 -43
  40. package/dist/events/index.d.ts +43 -43
  41. package/dist/events/index.js +39 -2
  42. package/dist/events/index.js.map +1 -1
  43. package/dist/evidence/index.cjs +12 -50
  44. package/dist/evidence/index.d.cts +2 -229
  45. package/dist/evidence/index.d.ts +2 -229
  46. package/dist/evidence/index.js +1 -5
  47. package/dist/evidence-BuCICb0c.js +516 -0
  48. package/dist/evidence-BuCICb0c.js.map +1 -0
  49. package/dist/evidence-Cq48eDvA.cjs +575 -0
  50. package/dist/evidence-Cq48eDvA.cjs.map +1 -0
  51. package/dist/governance/index.cjs +24 -18
  52. package/dist/governance/index.cjs.map +1 -1
  53. package/dist/governance/index.d.cts +80 -83
  54. package/dist/governance/index.d.ts +80 -83
  55. package/dist/governance/index.js +22 -2
  56. package/dist/governance/index.js.map +1 -1
  57. package/dist/ids/index.cjs +52 -22
  58. package/dist/ids/index.cjs.map +1 -1
  59. package/dist/ids/index.d.cts +17 -17
  60. package/dist/ids/index.d.ts +17 -17
  61. package/dist/ids/index.js +49 -2
  62. package/dist/ids/index.js.map +1 -1
  63. package/dist/index-9jasmw76.d.cts +124 -0
  64. package/dist/index-BXpeFdk2.d.cts +190 -0
  65. package/dist/index-BXpeFdk2.d.ts +190 -0
  66. package/dist/index-BnbsKZsT.d.cts +231 -0
  67. package/dist/index-CIl1rYRv.d.cts +11 -0
  68. package/dist/index-CIl1rYRv.d.ts +11 -0
  69. package/dist/index-CVHA1ypT.d.cts +262 -0
  70. package/dist/index-DZ4mnNb7.d.cts +78 -0
  71. package/dist/index-DZ4mnNb7.d.ts +78 -0
  72. package/dist/index-IqcDvl69.d.ts +124 -0
  73. package/dist/index-fmUiRBXu.d.cts +57 -0
  74. package/dist/index-fmUiRBXu.d.ts +57 -0
  75. package/dist/index-sPUPs8pr.d.ts +262 -0
  76. package/dist/index-z9-CYOIo.d.ts +231 -0
  77. package/dist/index.cjs +111 -393
  78. package/dist/index.d.cts +18 -17
  79. package/dist/index.d.ts +18 -17
  80. package/dist/index.js +19 -20
  81. package/dist/manifest/index.cjs +224 -35
  82. package/dist/manifest/index.cjs.map +1 -1
  83. package/dist/manifest/index.d.cts +130 -131
  84. package/dist/manifest/index.d.ts +130 -131
  85. package/dist/manifest/index.js +219 -7
  86. package/dist/manifest/index.js.map +1 -1
  87. package/dist/modules/index.cjs +281 -42
  88. package/dist/modules/index.cjs.map +1 -1
  89. package/dist/modules/index.d.cts +157 -159
  90. package/dist/modules/index.d.ts +157 -159
  91. package/dist/modules/index.js +274 -6
  92. package/dist/modules/index.js.map +1 -1
  93. package/dist/objects/index.cjs +355 -22
  94. package/dist/objects/index.cjs.map +1 -1
  95. package/dist/objects/index.d.cts +2 -77
  96. package/dist/objects/index.d.ts +2 -77
  97. package/dist/objects/index.js +352 -2
  98. package/dist/objects/index.js.map +1 -1
  99. package/dist/policies/index.cjs +14 -56
  100. package/dist/policies/index.d.cts +2 -261
  101. package/dist/policies/index.d.ts +2 -261
  102. package/dist/policies/index.js +1 -3
  103. package/dist/policies-DH_GCXQ-.js +627 -0
  104. package/dist/policies-DH_GCXQ-.js.map +1 -0
  105. package/dist/policies-Nxbp1CH8.cjs +698 -0
  106. package/dist/policies-Nxbp1CH8.cjs.map +1 -0
  107. package/dist/privacy/index.cjs +26 -43
  108. package/dist/privacy/index.cjs.map +1 -1
  109. package/dist/privacy/index.d.cts +2 -189
  110. package/dist/privacy/index.d.ts +2 -189
  111. package/dist/privacy/index.js +18 -3
  112. package/dist/privacy/index.js.map +1 -1
  113. package/dist/projections/index.cjs +241 -23
  114. package/dist/projections/index.cjs.map +1 -1
  115. package/dist/projections/index.d.cts +2 -125
  116. package/dist/projections/index.d.ts +2 -125
  117. package/dist/projections/index.js +238 -3
  118. package/dist/projections/index.js.map +1 -1
  119. package/dist/state-machines/index.cjs +76 -18
  120. package/dist/state-machines/index.cjs.map +1 -1
  121. package/dist/state-machines/index.d.cts +2 -55
  122. package/dist/state-machines/index.d.ts +2 -55
  123. package/dist/state-machines/index.js +74 -2
  124. package/dist/state-machines/index.js.map +1 -1
  125. package/dist/testing/index.cjs +27 -19
  126. package/dist/testing/index.cjs.map +1 -1
  127. package/dist/testing/index.d.cts +17 -19
  128. package/dist/testing/index.d.ts +17 -19
  129. package/dist/testing/index.js +25 -3
  130. package/dist/testing/index.js.map +1 -1
  131. package/package.json +6 -5
  132. package/dist/chunk-2AE6TMAX.cjs +0 -44
  133. package/dist/chunk-2AE6TMAX.cjs.map +0 -1
  134. package/dist/chunk-6HY35TKB.cjs +0 -491
  135. package/dist/chunk-6HY35TKB.cjs.map +0 -1
  136. package/dist/chunk-6UGEIDLC.cjs +0 -26
  137. package/dist/chunk-6UGEIDLC.cjs.map +0 -1
  138. package/dist/chunk-7GAWSUOG.js +0 -64
  139. package/dist/chunk-7GAWSUOG.js.map +0 -1
  140. package/dist/chunk-A42JJIPL.cjs +0 -699
  141. package/dist/chunk-A42JJIPL.cjs.map +0 -1
  142. package/dist/chunk-AFXKSIVI.cjs +0 -540
  143. package/dist/chunk-AFXKSIVI.cjs.map +0 -1
  144. package/dist/chunk-B5DOGDPG.js +0 -42
  145. package/dist/chunk-B5DOGDPG.js.map +0 -1
  146. package/dist/chunk-BJGZE3GE.js +0 -20
  147. package/dist/chunk-BJGZE3GE.js.map +0 -1
  148. package/dist/chunk-CRZXTZ36.cjs +0 -258
  149. package/dist/chunk-CRZXTZ36.cjs.map +0 -1
  150. package/dist/chunk-D4SWRBUH.cjs +0 -22
  151. package/dist/chunk-D4SWRBUH.cjs.map +0 -1
  152. package/dist/chunk-DBTAUI6C.cjs +0 -395
  153. package/dist/chunk-DBTAUI6C.cjs.map +0 -1
  154. package/dist/chunk-EMSAFNPX.js +0 -98
  155. package/dist/chunk-EMSAFNPX.js.map +0 -1
  156. package/dist/chunk-F3E5SXPN.cjs +0 -28
  157. package/dist/chunk-F3E5SXPN.cjs.map +0 -1
  158. package/dist/chunk-HEYMMVDP.js +0 -480
  159. package/dist/chunk-HEYMMVDP.js.map +0 -1
  160. package/dist/chunk-IFW43ELT.cjs +0 -331
  161. package/dist/chunk-IFW43ELT.cjs.map +0 -1
  162. package/dist/chunk-LFE74IJX.js +0 -20
  163. package/dist/chunk-LFE74IJX.js.map +0 -1
  164. package/dist/chunk-LZSE6QGQ.cjs +0 -60
  165. package/dist/chunk-LZSE6QGQ.cjs.map +0 -1
  166. package/dist/chunk-MCWSUGB3.cjs +0 -102
  167. package/dist/chunk-MCWSUGB3.cjs.map +0 -1
  168. package/dist/chunk-MLBALEUR.js +0 -290
  169. package/dist/chunk-MLBALEUR.js.map +0 -1
  170. package/dist/chunk-NNXQZPB3.cjs +0 -31
  171. package/dist/chunk-NNXQZPB3.cjs.map +0 -1
  172. package/dist/chunk-OFCCZ27Z.js +0 -26
  173. package/dist/chunk-OFCCZ27Z.js.map +0 -1
  174. package/dist/chunk-PDN5DOLQ.js +0 -242
  175. package/dist/chunk-PDN5DOLQ.js.map +0 -1
  176. package/dist/chunk-PIDZQAEL.js +0 -50
  177. package/dist/chunk-PIDZQAEL.js.map +0 -1
  178. package/dist/chunk-PXD7NG6X.js +0 -686
  179. package/dist/chunk-PXD7NG6X.js.map +0 -1
  180. package/dist/chunk-Q4Q4JPR3.js +0 -524
  181. package/dist/chunk-Q4Q4JPR3.js.map +0 -1
  182. package/dist/chunk-RALMUSOX.js +0 -55
  183. package/dist/chunk-RALMUSOX.js.map +0 -1
  184. package/dist/chunk-SNTV45LH.cjs +0 -295
  185. package/dist/chunk-SNTV45LH.cjs.map +0 -1
  186. package/dist/chunk-TBS2S5AX.cjs +0 -40
  187. package/dist/chunk-TBS2S5AX.cjs.map +0 -1
  188. package/dist/chunk-TYNIFC7J.js +0 -253
  189. package/dist/chunk-TYNIFC7J.js.map +0 -1
  190. package/dist/chunk-UGWGHTNC.cjs +0 -56
  191. package/dist/chunk-UGWGHTNC.cjs.map +0 -1
  192. package/dist/chunk-WI7CWNYI.cjs +0 -68
  193. package/dist/chunk-WI7CWNYI.cjs.map +0 -1
  194. package/dist/chunk-WNZP53GI.js +0 -386
  195. package/dist/chunk-WNZP53GI.js.map +0 -1
  196. package/dist/chunk-WQ3BYI7T.cjs +0 -249
  197. package/dist/chunk-WQ3BYI7T.cjs.map +0 -1
  198. package/dist/chunk-Y2PJLRIY.js +0 -36
  199. package/dist/chunk-Y2PJLRIY.js.map +0 -1
  200. package/dist/chunk-ZAEVQSB5.js +0 -326
  201. package/dist/chunk-ZAEVQSB5.js.map +0 -1
  202. package/dist/chunk-ZMQTV5OJ.js +0 -27
  203. package/dist/chunk-ZMQTV5OJ.js.map +0 -1
  204. package/dist/evidence/index.cjs.map +0 -1
  205. package/dist/evidence/index.js.map +0 -1
  206. package/dist/index.cjs.map +0 -1
  207. package/dist/index.js.map +0 -1
  208. package/dist/policies/index.cjs.map +0 -1
  209. package/dist/policies/index.js.map +0 -1
@@ -0,0 +1,698 @@
1
+ //#region policies/reconciliation-required.ts
2
+ /** A possibly committed domain effect requiring an operator decision at the handler transaction boundary. */
3
+ var ReconciliationRequiredError = class extends Error {
4
+ name = "ReconciliationRequiredError";
5
+ code = "EXECUTION_RECONCILIATION_REQUIRED";
6
+ constructor(message, options) {
7
+ super(message, options);
8
+ }
9
+ };
10
+ /**
11
+ * Recognise a ReconciliationRequiredError, including one constructed by a second
12
+ * package copy (for example ESM and CommonJS builds loaded side by side).
13
+ */
14
+ function isReconciliationRequiredError(error) {
15
+ if (error instanceof ReconciliationRequiredError) return true;
16
+ return typeof error === "object" && error !== null && error.name === "ReconciliationRequiredError" && error.code === "EXECUTION_RECONCILIATION_REQUIRED";
17
+ }
18
+ //#endregion
19
+ //#region policies/retryable-execution.ts
20
+ /** A transient execution dependency failure; the host decides whether retry is safe. */
21
+ var RetryableExecutionError = class extends Error {
22
+ name = "RetryableExecutionError";
23
+ code = "EXECUTION_RETRYABLE";
24
+ constructor(message, options) {
25
+ super(message, options);
26
+ }
27
+ };
28
+ /**
29
+ * Recognise a RetryableExecutionError, including one constructed by a second
30
+ * package copy (for example ESM and CommonJS builds loaded side by side).
31
+ */
32
+ function isRetryableExecutionError(error) {
33
+ if (error instanceof RetryableExecutionError) return true;
34
+ return typeof error === "object" && error !== null && error.name === "RetryableExecutionError" && error.code === "EXECUTION_RETRYABLE";
35
+ }
36
+ //#endregion
37
+ //#region policies/index.ts
38
+ function assertPolicyId(policyId) {
39
+ if (!/^[a-z][a-z0-9_-]*(\.[a-z][a-z0-9_-]*)*\.v[0-9]+$/.test(policyId)) throw new Error(`Invalid policy ID: ${policyId}`);
40
+ }
41
+ function validatePolicyGuidance(guidance) {
42
+ const errors = [];
43
+ if (!isPlainRecord(guidance)) return {
44
+ valid: false,
45
+ errors: ["guidance must be an object"]
46
+ };
47
+ if (guidance.summary !== void 0 && typeof guidance.summary !== "string") errors.push("guidance.summary must be a string when present");
48
+ if (!Array.isArray(guidance.factsUsed)) errors.push("guidance.factsUsed must be an array");
49
+ else guidance.factsUsed.forEach((fact, index) => {
50
+ if (!isPlainRecord(fact)) {
51
+ errors.push(`guidance.factsUsed[${index}] must be an object`);
52
+ return;
53
+ }
54
+ if (typeof fact.name !== "string" || fact.name.length === 0) errors.push(`guidance.factsUsed[${index}].name must be a non-empty string`);
55
+ if (fact.label !== void 0 && typeof fact.label !== "string") errors.push(`guidance.factsUsed[${index}].label must be a string when present`);
56
+ });
57
+ if (!Array.isArray(guidance.correctiveActions)) errors.push("guidance.correctiveActions must be an array");
58
+ else guidance.correctiveActions.forEach((action, index) => {
59
+ errors.push(...validatePolicyCorrectiveAction(action, index));
60
+ });
61
+ return {
62
+ valid: errors.length === 0,
63
+ errors
64
+ };
65
+ }
66
+ function validatePolicyCorrectiveAction(action, index) {
67
+ const errors = [];
68
+ const prefix = `guidance.correctiveActions[${index}]`;
69
+ if (!isPlainRecord(action)) return [`${prefix} must be an object`];
70
+ if (action.kind !== "invoke_action" && action.kind !== "navigate" && action.kind !== "manual") errors.push(`${prefix}.kind must be "invoke_action" | "navigate" | "manual"`);
71
+ if (typeof action.label !== "string" || action.label.length === 0) errors.push(`${prefix}.label must be a non-empty string`);
72
+ if (action.description !== void 0 && typeof action.description !== "string") errors.push(`${prefix}.description must be a string when present`);
73
+ if (action.requiresConfirmation !== void 0 && typeof action.requiresConfirmation !== "boolean") errors.push(`${prefix}.requiresConfirmation must be a boolean when present`);
74
+ if (action.requiresRole !== void 0) {
75
+ if (!Array.isArray(action.requiresRole)) errors.push(`${prefix}.requiresRole must be an array when present`);
76
+ else if (action.requiresRole.some((role) => typeof role !== "string" || role.length === 0)) errors.push(`${prefix}.requiresRole must contain only non-empty strings`);
77
+ }
78
+ if (action.kind === "invoke_action") {
79
+ if (typeof action.actionId !== "string" || action.actionId.length === 0) errors.push(`${prefix}.actionId must be a non-empty string for invoke_action`);
80
+ if (action.parameters !== void 0 && !isPlainRecord(action.parameters)) errors.push(`${prefix}.parameters must be an object when present`);
81
+ }
82
+ if (action.kind === "navigate") {
83
+ if (action.route !== void 0 && typeof action.route !== "string") errors.push(`${prefix}.route must be a string when present`);
84
+ if (action.target !== void 0 && !isPlainRecord(action.target)) errors.push(`${prefix}.target must be an object when present`);
85
+ }
86
+ return errors;
87
+ }
88
+ function isPlainRecord(value) {
89
+ return value !== null && typeof value === "object" && !Array.isArray(value);
90
+ }
91
+ const DATA_POLICY_MAX_DEPTH = 5;
92
+ const DATA_POLICY_MAX_CONDITIONS_PER_NODE = 20;
93
+ const DATA_POLICY_MAX_TOTAL_CONDITIONS = 100;
94
+ const DATA_POLICY_MAX_PATH_SEGMENTS = 12;
95
+ const DATA_POLICY_MAX_STRING_LENGTH = 500;
96
+ const DATA_POLICY_CONTEXT_PATHS = Object.freeze([
97
+ "tenantId",
98
+ "spaceId",
99
+ "actionInvocationId",
100
+ "actionId",
101
+ "mode"
102
+ ]);
103
+ const DATA_POLICY_COMPARISON_OPERATORS = Object.freeze([
104
+ "exists",
105
+ "equals",
106
+ "notEquals",
107
+ "gt",
108
+ "gte",
109
+ "lt",
110
+ "lte"
111
+ ]);
112
+ const POLICY_RESULTS = Object.freeze([
113
+ "pass",
114
+ "warn",
115
+ "block"
116
+ ]);
117
+ function createPolicyRegistry(evaluators = []) {
118
+ const policies = /* @__PURE__ */ new Map();
119
+ const register = (evaluator) => {
120
+ assertPolicyId(evaluator.policyId);
121
+ const existing = policies.get(evaluator.policyId);
122
+ if (existing && existing !== evaluator) throw new Error(`Conflicting policy registration for "${evaluator.policyId}". A different evaluator is already registered.`);
123
+ policies.set(evaluator.policyId, evaluator);
124
+ };
125
+ for (const evaluator of evaluators) register(evaluator);
126
+ return {
127
+ register,
128
+ registerIfMissing(evaluator) {
129
+ const existing = policies.get(evaluator.policyId);
130
+ if (!existing) register(evaluator);
131
+ else if (existing !== evaluator) throw new Error(`Conflicting policy registration for "${evaluator.policyId}". A different evaluator is already registered.`);
132
+ },
133
+ resolve: (policyId) => policies.get(policyId),
134
+ ids: () => Array.from(policies.keys())
135
+ };
136
+ }
137
+ async function evaluateRegisteredPolicies(policyIds, ctx) {
138
+ return evaluatePolicyDefinitions(policyIds.map((policyId) => ({
139
+ policyId,
140
+ policyVersion: parsePolicyVersion(policyId),
141
+ kind: "code",
142
+ codeEvaluatorPolicyId: policyId
143
+ })), ctx);
144
+ }
145
+ async function evaluatePolicyDefinitions(policies, ctx) {
146
+ const outcomes = [];
147
+ for (const policy of policies) {
148
+ assertPolicyId(policy.policyId);
149
+ outcomes.push(await evaluatePolicyDefinition(policy, ctx));
150
+ }
151
+ return outcomes;
152
+ }
153
+ async function evaluatePolicyDefinition(policy, ctx) {
154
+ const authority = policy.authority ? { ...policy.authority } : void 0;
155
+ const outcome = policy.kind === "data" ? await evaluateDataPolicy(policy, ctx) : policy.kind === "code" ? await evaluateCodePolicy(policy, ctx) : await evaluateHybridPolicy(policy, ctx);
156
+ if (!authority) return outcome;
157
+ return {
158
+ ...outcome,
159
+ dispatchEvidence: {
160
+ ...outcome.dispatchEvidence ?? {
161
+ policyKind: policy.kind,
162
+ policyId: policy.policyId,
163
+ policyVersion: policy.policyVersion,
164
+ dispatchPath: []
165
+ },
166
+ authority
167
+ }
168
+ };
169
+ }
170
+ async function evaluateCodePolicy(policy, ctx) {
171
+ const codeEvaluatorPolicyId = policy.codeEvaluatorPolicyId ?? policy.policyId;
172
+ const evaluator = ctx.resolveCodePolicy?.(codeEvaluatorPolicyId);
173
+ if (!evaluator) return {
174
+ policyId: policy.policyId,
175
+ policyVersion: policy.policyVersion,
176
+ policyKind: policy.kind,
177
+ result: "block",
178
+ reason: `No evaluator registered for policy ${codeEvaluatorPolicyId}`,
179
+ metadata: { missingCodeEvaluatorPolicyId: codeEvaluatorPolicyId },
180
+ dispatchEvidence: {
181
+ policyKind: policy.kind,
182
+ policyId: policy.policyId,
183
+ policyVersion: policy.policyVersion,
184
+ dispatchPath: ["code"],
185
+ code: {
186
+ requestedPolicyId: codeEvaluatorPolicyId,
187
+ policyId: codeEvaluatorPolicyId,
188
+ registered: false
189
+ }
190
+ }
191
+ };
192
+ if (ctx.mode === "preview" && evaluator.previewSafe !== true) {
193
+ const skipReason = `Policy ${evaluator.policyId} skipped in preview mode (evaluator is not declared previewSafe)`;
194
+ return {
195
+ policyId: policy.policyId,
196
+ policyVersion: policy.policyVersion,
197
+ policyKind: policy.kind,
198
+ result: "warn",
199
+ reason: skipReason,
200
+ metadata: {
201
+ codePolicyId: evaluator.policyId,
202
+ codePolicyVersion: evaluator.version,
203
+ previewSkipped: true
204
+ },
205
+ dispatchEvidence: {
206
+ policyKind: policy.kind,
207
+ policyId: policy.policyId,
208
+ policyVersion: policy.policyVersion,
209
+ dispatchPath: ["code"],
210
+ code: {
211
+ requestedPolicyId: codeEvaluatorPolicyId,
212
+ policyId: evaluator.policyId,
213
+ version: evaluator.version,
214
+ registered: true,
215
+ skipped: true,
216
+ skipReason
217
+ }
218
+ }
219
+ };
220
+ }
221
+ return normalizeOutcome(policy, await evaluator.evaluate(ctx), {
222
+ policyKind: policy.kind,
223
+ policyId: policy.policyId,
224
+ policyVersion: policy.policyVersion,
225
+ dispatchPath: ["code"],
226
+ code: {
227
+ requestedPolicyId: codeEvaluatorPolicyId,
228
+ policyId: evaluator.policyId,
229
+ version: evaluator.version,
230
+ registered: true
231
+ }
232
+ });
233
+ }
234
+ async function evaluateHybridPolicy(policy, ctx) {
235
+ const dataOutcome = evaluateDataPolicy(policy, ctx);
236
+ const fallback = policy.fallback;
237
+ const fallbackDecision = fallback ? resolveFallbackDecision(policy, dataOutcome, fallback) : {
238
+ shouldFallback: false,
239
+ trigger: "not_triggered"
240
+ };
241
+ if (!fallback || !fallbackDecision.shouldFallback) {
242
+ if (fallback && dataOutcome.dispatchEvidence) return {
243
+ ...dataOutcome,
244
+ dispatchEvidence: {
245
+ ...dataOutcome.dispatchEvidence,
246
+ fallback: {
247
+ used: false,
248
+ trigger: "not_triggered",
249
+ reason: "Data policy result did not trigger fallback",
250
+ fromResult: dataOutcome.result,
251
+ definitionVersion: policy.policyVersion,
252
+ codeEvaluatorPolicyId: fallback.codeEvaluatorPolicyId
253
+ }
254
+ }
255
+ };
256
+ return dataOutcome;
257
+ }
258
+ const codeOutcome = await evaluateCodePolicy({
259
+ policyId: policy.policyId,
260
+ policyVersion: policy.policyVersion,
261
+ kind: "hybrid",
262
+ codeEvaluatorPolicyId: fallback.codeEvaluatorPolicyId
263
+ }, ctx);
264
+ return normalizeOutcome(policy, codeOutcome, {
265
+ ...codeOutcome.dispatchEvidence ?? {
266
+ policyKind: "hybrid",
267
+ policyId: policy.policyId,
268
+ policyVersion: policy.policyVersion,
269
+ dispatchPath: ["code"]
270
+ },
271
+ policyKind: "hybrid",
272
+ policyId: policy.policyId,
273
+ policyVersion: policy.policyVersion,
274
+ dispatchPath: [
275
+ "data",
276
+ "fallback",
277
+ "code"
278
+ ],
279
+ data: dataOutcome.dispatchEvidence?.data,
280
+ fallback: {
281
+ used: true,
282
+ trigger: fallbackDecision.trigger,
283
+ reason: fallback.reason ?? "Data policy result triggered code fallback",
284
+ fromResult: dataOutcome.result,
285
+ definitionVersion: policy.policyVersion,
286
+ codeEvaluatorPolicyId: fallback.codeEvaluatorPolicyId
287
+ }
288
+ });
289
+ }
290
+ function resolveFallbackDecision(policy, dataOutcome, fallback) {
291
+ const allowedTriggers = fallback.triggers ?? [
292
+ "data_result",
293
+ "missing_data_definition",
294
+ "invalid_data_definition"
295
+ ];
296
+ const definitionStatus = dataOutcome.dispatchEvidence?.data?.definitionStatus;
297
+ if (definitionStatus === "missing") return {
298
+ shouldFallback: allowedTriggers.includes("missing_data_definition"),
299
+ trigger: "missing_data_definition"
300
+ };
301
+ if (definitionStatus === "invalid") return {
302
+ shouldFallback: allowedTriggers.includes("invalid_data_definition"),
303
+ trigger: "invalid_data_definition"
304
+ };
305
+ const fallbackResults = fallback.onResults ?? ["warn", "block"];
306
+ return {
307
+ shouldFallback: policy.kind === "hybrid" && allowedTriggers.includes("data_result") && fallbackResults.includes(dataOutcome.result),
308
+ trigger: "data_result"
309
+ };
310
+ }
311
+ function evaluateDataPolicy(policy, ctx) {
312
+ const definition = policy.dataDefinition;
313
+ if (!definition) return {
314
+ policyId: policy.policyId,
315
+ policyVersion: policy.policyVersion,
316
+ policyKind: policy.kind,
317
+ result: "block",
318
+ reason: "Data policy definition is missing",
319
+ dispatchEvidence: {
320
+ policyKind: policy.kind,
321
+ policyId: policy.policyId,
322
+ policyVersion: policy.policyVersion,
323
+ dispatchPath: ["data"],
324
+ data: {
325
+ definitionVersion: policy.policyVersion,
326
+ definitionStatus: "missing",
327
+ conditionResults: []
328
+ }
329
+ }
330
+ };
331
+ const validation = validateDataPolicyDefinition(definition);
332
+ if (!validation.valid) return {
333
+ policyId: policy.policyId,
334
+ policyVersion: policy.policyVersion,
335
+ policyKind: policy.kind,
336
+ result: "block",
337
+ reason: `Invalid data policy definition: ${validation.errors.join("; ")}`,
338
+ metadata: { validationErrors: validation.errors },
339
+ dispatchEvidence: {
340
+ policyKind: policy.kind,
341
+ policyId: policy.policyId,
342
+ policyVersion: policy.policyVersion,
343
+ dispatchPath: ["data"],
344
+ data: {
345
+ definitionVersion: policy.policyVersion,
346
+ definitionStatus: "invalid",
347
+ conditionResults: [],
348
+ validationErrors: validation.errors
349
+ }
350
+ }
351
+ };
352
+ const evaluations = definition.conditions.map((condition) => evaluateDataPolicyCondition(condition, ctx));
353
+ const conditionResults = evaluations.flatMap((evaluation) => evaluation.evidence);
354
+ const topLevelResults = evaluations.map((evaluation) => evaluation.result);
355
+ const aggregate = topLevelResults.find((result) => result.result === "block") ?? topLevelResults.find((result) => result.result === "warn");
356
+ const result = aggregate?.result ?? definition.defaultResult ?? "pass";
357
+ return {
358
+ policyId: policy.policyId,
359
+ policyVersion: policy.policyVersion,
360
+ policyKind: policy.kind,
361
+ result,
362
+ reason: aggregate?.reason ?? definition.reason,
363
+ metadata: {
364
+ conditionCount: definition.conditions.length,
365
+ failedConditionId: aggregate?.conditionId
366
+ },
367
+ dispatchEvidence: {
368
+ policyKind: policy.kind,
369
+ policyId: policy.policyId,
370
+ policyVersion: policy.policyVersion,
371
+ dispatchPath: ["data"],
372
+ data: {
373
+ definitionVersion: policy.policyVersion,
374
+ definitionStatus: "evaluated",
375
+ conditionResults
376
+ }
377
+ }
378
+ };
379
+ }
380
+ function validateDataPolicyDefinition(definition) {
381
+ const errors = [];
382
+ if (!Array.isArray(definition.conditions) || definition.conditions.length === 0) errors.push("conditions must contain at least one condition");
383
+ else if (definition.conditions.length > DATA_POLICY_MAX_CONDITIONS_PER_NODE) errors.push(`conditions must contain at most ${DATA_POLICY_MAX_CONDITIONS_PER_NODE} top-level conditions`);
384
+ if (definition.defaultResult && !POLICY_RESULTS.includes(definition.defaultResult)) errors.push("defaultResult must be pass, warn, or block");
385
+ let totalConditions = 0;
386
+ for (const condition of definition.conditions ?? []) validateDataPolicyCondition(condition, errors, 1, () => {
387
+ totalConditions += 1;
388
+ });
389
+ if (totalConditions > DATA_POLICY_MAX_TOTAL_CONDITIONS) errors.push(`policy must contain at most ${DATA_POLICY_MAX_TOTAL_CONDITIONS} total conditions`);
390
+ return {
391
+ valid: errors.length === 0,
392
+ errors
393
+ };
394
+ }
395
+ function validateDataPolicyCondition(condition, errors, depth, count) {
396
+ count();
397
+ if (!condition || typeof condition !== "object") {
398
+ errors.push("condition must be an object");
399
+ return;
400
+ }
401
+ if (depth > DATA_POLICY_MAX_DEPTH) {
402
+ errors.push(`condition depth must not exceed ${DATA_POLICY_MAX_DEPTH}`);
403
+ return;
404
+ }
405
+ if (!isNonEmptyBoundedString(condition.conditionId)) errors.push("conditionId must be a non-empty bounded string");
406
+ validateOptionalPolicyResult("onPass" in condition ? condition.onPass : void 0, "onPass", errors);
407
+ validateOptionalPolicyResult("onFail" in condition ? condition.onFail : void 0, "onFail", errors);
408
+ if (condition.reason !== void 0 && !isNonEmptyBoundedString(condition.reason)) errors.push(`condition ${condition.conditionId} reason must be a bounded string`);
409
+ if (condition.type === "always") {
410
+ if (!POLICY_RESULTS.includes(condition.result)) errors.push(`condition ${condition.conditionId} result must be pass, warn, or block`);
411
+ return;
412
+ }
413
+ if (condition.type === "parameter") {
414
+ validatePath(condition.path, `condition ${condition.conditionId} path`, errors);
415
+ validateComparison(condition.operator, condition.value, condition.conditionId, errors);
416
+ return;
417
+ }
418
+ if (condition.type === "comparison") {
419
+ validateSourceReference(condition.left, condition.conditionId, errors);
420
+ validateComparison(condition.operator, condition.value, condition.conditionId, errors);
421
+ return;
422
+ }
423
+ if (condition.type === "all" || condition.type === "any") {
424
+ if (!Array.isArray(condition.conditions) || condition.conditions.length === 0) {
425
+ errors.push(`condition ${condition.conditionId} must contain child conditions`);
426
+ return;
427
+ }
428
+ if (condition.conditions.length > DATA_POLICY_MAX_CONDITIONS_PER_NODE) errors.push(`condition ${condition.conditionId} must contain at most ${DATA_POLICY_MAX_CONDITIONS_PER_NODE} child conditions`);
429
+ for (const child of condition.conditions) validateDataPolicyCondition(child, errors, depth + 1, count);
430
+ return;
431
+ }
432
+ if (condition.type === "not") {
433
+ validateDataPolicyCondition(condition.condition, errors, depth + 1, count);
434
+ return;
435
+ }
436
+ errors.push(`condition ${condition.conditionId} has unsupported type`);
437
+ }
438
+ function validateOptionalPolicyResult(result, fieldName, errors) {
439
+ if (result !== void 0 && !POLICY_RESULTS.includes(result)) errors.push(`${fieldName} must be pass, warn, or block`);
440
+ }
441
+ function validateSourceReference(reference, conditionId, errors) {
442
+ if (!reference || typeof reference !== "object") {
443
+ errors.push(`condition ${conditionId} left must be a source reference`);
444
+ return;
445
+ }
446
+ if (reference.source !== "parameters" && reference.source !== "context") errors.push(`condition ${conditionId} source must be parameters or context`);
447
+ validatePath(reference.path, `condition ${conditionId} left.path`, errors);
448
+ if (reference.source === "context" && !DATA_POLICY_CONTEXT_PATHS.includes(reference.path)) errors.push(`condition ${conditionId} uses an unsupported context path`);
449
+ }
450
+ function validateComparison(operator, value, conditionId, errors) {
451
+ if (!DATA_POLICY_COMPARISON_OPERATORS.includes(operator)) {
452
+ errors.push(`condition ${conditionId} has unsupported operator`);
453
+ return;
454
+ }
455
+ if (operator === "exists") return;
456
+ if (!isDataPolicyLiteral(value)) {
457
+ errors.push(`condition ${conditionId} comparison value must be a bounded literal`);
458
+ return;
459
+ }
460
+ if ([
461
+ "gt",
462
+ "gte",
463
+ "lt",
464
+ "lte"
465
+ ].includes(operator) && typeof value !== "number") errors.push(`condition ${conditionId} numeric comparison requires a number value`);
466
+ }
467
+ function validatePath(path, fieldName, errors) {
468
+ if (!isNonEmptyBoundedString(path)) {
469
+ errors.push(`${fieldName} must be a non-empty bounded string`);
470
+ return;
471
+ }
472
+ const segments = path.split(".");
473
+ if (segments.length > DATA_POLICY_MAX_PATH_SEGMENTS) {
474
+ errors.push(`${fieldName} must contain at most ${DATA_POLICY_MAX_PATH_SEGMENTS} segments`);
475
+ return;
476
+ }
477
+ for (const segment of segments) {
478
+ if (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(segment)) {
479
+ errors.push(`${fieldName} contains an invalid path segment`);
480
+ return;
481
+ }
482
+ if ([
483
+ "__proto__",
484
+ "constructor",
485
+ "prototype"
486
+ ].includes(segment)) {
487
+ errors.push(`${fieldName} contains a forbidden path segment`);
488
+ return;
489
+ }
490
+ }
491
+ }
492
+ function isDataPolicyLiteral(value) {
493
+ if (value === null || typeof value === "number" || typeof value === "boolean") return true;
494
+ return typeof value === "string" && value.length <= DATA_POLICY_MAX_STRING_LENGTH;
495
+ }
496
+ function isNonEmptyBoundedString(value) {
497
+ return typeof value === "string" && value.length > 0 && value.length <= DATA_POLICY_MAX_STRING_LENGTH;
498
+ }
499
+ function evaluateDataPolicyCondition(condition, ctx) {
500
+ if (condition.type === "always") {
501
+ const result = {
502
+ conditionId: condition.conditionId,
503
+ passed: condition.result === "pass",
504
+ result: condition.result,
505
+ reason: condition.reason
506
+ };
507
+ return {
508
+ result,
509
+ evidence: [result]
510
+ };
511
+ }
512
+ if (condition.type === "all" || condition.type === "any") {
513
+ const childEvaluations = condition.conditions.map((child) => evaluateDataPolicyCondition(child, ctx));
514
+ const passed = condition.type === "all" ? childEvaluations.every((evaluation) => evaluation.result.passed) : childEvaluations.some((evaluation) => evaluation.result.passed);
515
+ const result = {
516
+ conditionId: condition.conditionId,
517
+ passed,
518
+ result: passed ? condition.onPass ?? "pass" : condition.onFail ?? "block",
519
+ reason: passed ? void 0 : condition.reason
520
+ };
521
+ return {
522
+ result,
523
+ evidence: [result, ...childEvaluations.flatMap((evaluation) => evaluation.evidence)]
524
+ };
525
+ }
526
+ if (condition.type === "not") {
527
+ const childEvaluation = evaluateDataPolicyCondition(condition.condition, ctx);
528
+ const passed = !childEvaluation.result.passed;
529
+ const result = {
530
+ conditionId: condition.conditionId,
531
+ passed,
532
+ result: passed ? condition.onPass ?? "pass" : condition.onFail ?? "block",
533
+ reason: passed ? void 0 : condition.reason
534
+ };
535
+ return {
536
+ result,
537
+ evidence: [result, ...childEvaluation.evidence]
538
+ };
539
+ }
540
+ if (condition.type !== "parameter" && condition.type !== "comparison") {
541
+ const result = {
542
+ conditionId: condition.conditionId,
543
+ passed: false,
544
+ result: "block",
545
+ reason: "Unsupported data policy condition type"
546
+ };
547
+ return {
548
+ result,
549
+ evidence: [result]
550
+ };
551
+ }
552
+ const value = condition.type === "parameter" ? readPath(ctx.parameters, condition.path) : readDataPolicySource(ctx, condition.left);
553
+ const operator = condition.operator;
554
+ const expected = condition.value;
555
+ const passed = evaluateOperator(value, operator, expected);
556
+ const result = {
557
+ conditionId: condition.conditionId,
558
+ passed,
559
+ result: passed ? condition.onPass ?? "pass" : condition.onFail ?? "block",
560
+ reason: passed ? void 0 : condition.reason
561
+ };
562
+ return {
563
+ result,
564
+ evidence: [result]
565
+ };
566
+ }
567
+ function evaluateOperator(actual, operator, expected) {
568
+ switch (operator) {
569
+ case "exists": return actual !== void 0 && actual !== null && actual !== "";
570
+ case "equals": return actual === expected;
571
+ case "notEquals": return actual !== expected;
572
+ case "gt": return typeof actual === "number" && typeof expected === "number" && actual > expected;
573
+ case "gte": return typeof actual === "number" && typeof expected === "number" && actual >= expected;
574
+ case "lt": return typeof actual === "number" && typeof expected === "number" && actual < expected;
575
+ case "lte": return typeof actual === "number" && typeof expected === "number" && actual <= expected;
576
+ }
577
+ }
578
+ function readDataPolicySource(ctx, reference) {
579
+ if (reference.source === "parameters") return readPath(ctx.parameters, reference.path);
580
+ return readPath({
581
+ tenantId: ctx.tenantId,
582
+ spaceId: ctx.spaceId,
583
+ actionInvocationId: ctx.actionInvocationId,
584
+ actionId: ctx.actionId,
585
+ mode: ctx.mode
586
+ }, reference.path);
587
+ }
588
+ function readPath(source, path) {
589
+ if (!source || typeof source !== "object") return;
590
+ return path.split(".").reduce((current, segment) => {
591
+ if (!current || typeof current !== "object") return;
592
+ return current[segment];
593
+ }, source);
594
+ }
595
+ function normalizeOutcome(policy, outcome, dispatchEvidence) {
596
+ if (outcome.guidance !== void 0) {
597
+ const guidanceValidation = validatePolicyGuidance(outcome.guidance);
598
+ if (!guidanceValidation.valid) throw new Error(`Invalid guidance for policy ${outcome.policyId}: ${guidanceValidation.errors.join("; ")}`);
599
+ }
600
+ const engine = outcome.dispatchEvidence?.engine;
601
+ return {
602
+ ...outcome,
603
+ policyId: policy.policyId,
604
+ policyVersion: policy.policyVersion,
605
+ policyKind: policy.kind,
606
+ metadata: {
607
+ ...outcome.metadata ?? {},
608
+ codePolicyId: dispatchEvidence.code?.policyId ?? outcome.policyId,
609
+ codePolicyVersion: dispatchEvidence.code?.version ?? outcome.policyVersion
610
+ },
611
+ dispatchEvidence: engine ? {
612
+ ...dispatchEvidence,
613
+ engine
614
+ } : dispatchEvidence
615
+ };
616
+ }
617
+ function parsePolicyVersion(policyId) {
618
+ const segments = policyId.split(".v");
619
+ return Number(segments[segments.length - 1] ?? 1);
620
+ }
621
+ function aggregatePolicyOutcomes(outcomes) {
622
+ return outcomes.find((outcome) => outcome.result === "block") ?? outcomes.find((outcome) => outcome.result === "warn");
623
+ }
624
+ //#endregion
625
+ Object.defineProperty(exports, "ReconciliationRequiredError", {
626
+ enumerable: true,
627
+ get: function() {
628
+ return ReconciliationRequiredError;
629
+ }
630
+ });
631
+ Object.defineProperty(exports, "RetryableExecutionError", {
632
+ enumerable: true,
633
+ get: function() {
634
+ return RetryableExecutionError;
635
+ }
636
+ });
637
+ Object.defineProperty(exports, "aggregatePolicyOutcomes", {
638
+ enumerable: true,
639
+ get: function() {
640
+ return aggregatePolicyOutcomes;
641
+ }
642
+ });
643
+ Object.defineProperty(exports, "assertPolicyId", {
644
+ enumerable: true,
645
+ get: function() {
646
+ return assertPolicyId;
647
+ }
648
+ });
649
+ Object.defineProperty(exports, "createPolicyRegistry", {
650
+ enumerable: true,
651
+ get: function() {
652
+ return createPolicyRegistry;
653
+ }
654
+ });
655
+ Object.defineProperty(exports, "evaluatePolicyDefinition", {
656
+ enumerable: true,
657
+ get: function() {
658
+ return evaluatePolicyDefinition;
659
+ }
660
+ });
661
+ Object.defineProperty(exports, "evaluatePolicyDefinitions", {
662
+ enumerable: true,
663
+ get: function() {
664
+ return evaluatePolicyDefinitions;
665
+ }
666
+ });
667
+ Object.defineProperty(exports, "evaluateRegisteredPolicies", {
668
+ enumerable: true,
669
+ get: function() {
670
+ return evaluateRegisteredPolicies;
671
+ }
672
+ });
673
+ Object.defineProperty(exports, "isReconciliationRequiredError", {
674
+ enumerable: true,
675
+ get: function() {
676
+ return isReconciliationRequiredError;
677
+ }
678
+ });
679
+ Object.defineProperty(exports, "isRetryableExecutionError", {
680
+ enumerable: true,
681
+ get: function() {
682
+ return isRetryableExecutionError;
683
+ }
684
+ });
685
+ Object.defineProperty(exports, "validateDataPolicyDefinition", {
686
+ enumerable: true,
687
+ get: function() {
688
+ return validateDataPolicyDefinition;
689
+ }
690
+ });
691
+ Object.defineProperty(exports, "validatePolicyGuidance", {
692
+ enumerable: true,
693
+ get: function() {
694
+ return validatePolicyGuidance;
695
+ }
696
+ });
697
+
698
+ //# sourceMappingURL=policies-Nxbp1CH8.cjs.map