@fabricorg/platform 1.10.0 → 1.10.1
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/CHANGELOG.md +46 -0
- package/README.md +31 -2
- package/dist/actions/index.cjs +45 -26
- package/dist/actions/index.cjs.map +1 -1
- package/dist/actions/index.d.cts +225 -226
- package/dist/actions/index.d.ts +225 -226
- package/dist/actions/index.js +41 -2
- package/dist/actions/index.js.map +1 -1
- package/dist/adapters/index.cjs +696 -66
- package/dist/adapters/index.cjs.map +1 -1
- package/dist/adapters/index.d.cts +367 -365
- package/dist/adapters/index.d.ts +367 -365
- package/dist/adapters/index.js +682 -2
- package/dist/adapters/index.js.map +1 -1
- package/dist/agent-hitl/index.cjs +21 -10
- package/dist/agent-hitl/index.cjs.map +1 -1
- package/dist/agent-hitl/index.d.cts +30 -30
- package/dist/agent-hitl/index.d.ts +30 -30
- package/dist/agent-hitl/index.js +21 -2
- package/dist/agent-hitl/index.js.map +1 -1
- package/dist/certification/index.cjs +109 -24
- package/dist/certification/index.cjs.map +1 -1
- package/dist/certification/index.d.cts +33 -39
- package/dist/certification/index.d.ts +33 -39
- package/dist/certification/index.js +107 -8
- package/dist/certification/index.js.map +1 -1
- package/dist/discovery/index.cjs +12 -10
- package/dist/discovery/index.cjs.map +1 -1
- package/dist/discovery/index.d.cts +2 -10
- package/dist/discovery/index.d.ts +2 -10
- package/dist/discovery/index.js +12 -2
- package/dist/discovery/index.js.map +1 -1
- package/dist/engine-B4csEOEc.js +223 -0
- package/dist/engine-B4csEOEc.js.map +1 -0
- package/dist/engine-BqScuhrT.cjs +246 -0
- package/dist/engine-BqScuhrT.cjs.map +1 -0
- package/dist/events/index.cjs +39 -10
- package/dist/events/index.cjs.map +1 -1
- package/dist/events/index.d.cts +43 -43
- package/dist/events/index.d.ts +43 -43
- package/dist/events/index.js +39 -2
- package/dist/events/index.js.map +1 -1
- package/dist/evidence/index.cjs +12 -50
- package/dist/evidence/index.d.cts +2 -229
- package/dist/evidence/index.d.ts +2 -229
- package/dist/evidence/index.js +1 -5
- package/dist/evidence-BuCICb0c.js +516 -0
- package/dist/evidence-BuCICb0c.js.map +1 -0
- package/dist/evidence-Cq48eDvA.cjs +575 -0
- package/dist/evidence-Cq48eDvA.cjs.map +1 -0
- package/dist/governance/index.cjs +24 -18
- package/dist/governance/index.cjs.map +1 -1
- package/dist/governance/index.d.cts +80 -83
- package/dist/governance/index.d.ts +80 -83
- package/dist/governance/index.js +22 -2
- package/dist/governance/index.js.map +1 -1
- package/dist/ids/index.cjs +52 -22
- package/dist/ids/index.cjs.map +1 -1
- package/dist/ids/index.d.cts +17 -17
- package/dist/ids/index.d.ts +17 -17
- package/dist/ids/index.js +49 -2
- package/dist/ids/index.js.map +1 -1
- package/dist/index-9jasmw76.d.cts +124 -0
- package/dist/index-BXpeFdk2.d.cts +190 -0
- package/dist/index-BXpeFdk2.d.ts +190 -0
- package/dist/index-BnbsKZsT.d.cts +231 -0
- package/dist/index-CIl1rYRv.d.cts +11 -0
- package/dist/index-CIl1rYRv.d.ts +11 -0
- package/dist/index-CVHA1ypT.d.cts +262 -0
- package/dist/index-DZ4mnNb7.d.cts +78 -0
- package/dist/index-DZ4mnNb7.d.ts +78 -0
- package/dist/index-IqcDvl69.d.ts +124 -0
- package/dist/index-fmUiRBXu.d.cts +57 -0
- package/dist/index-fmUiRBXu.d.ts +57 -0
- package/dist/index-sPUPs8pr.d.ts +262 -0
- package/dist/index-z9-CYOIo.d.ts +231 -0
- package/dist/index.cjs +111 -393
- package/dist/index.d.cts +18 -17
- package/dist/index.d.ts +18 -17
- package/dist/index.js +19 -20
- package/dist/manifest/index.cjs +224 -35
- package/dist/manifest/index.cjs.map +1 -1
- package/dist/manifest/index.d.cts +130 -131
- package/dist/manifest/index.d.ts +130 -131
- package/dist/manifest/index.js +219 -7
- package/dist/manifest/index.js.map +1 -1
- package/dist/modules/index.cjs +281 -42
- package/dist/modules/index.cjs.map +1 -1
- package/dist/modules/index.d.cts +157 -159
- package/dist/modules/index.d.ts +157 -159
- package/dist/modules/index.js +274 -6
- package/dist/modules/index.js.map +1 -1
- package/dist/objects/index.cjs +355 -22
- package/dist/objects/index.cjs.map +1 -1
- package/dist/objects/index.d.cts +2 -77
- package/dist/objects/index.d.ts +2 -77
- package/dist/objects/index.js +352 -2
- package/dist/objects/index.js.map +1 -1
- package/dist/policies/index.cjs +14 -56
- package/dist/policies/index.d.cts +2 -261
- package/dist/policies/index.d.ts +2 -261
- package/dist/policies/index.js +1 -3
- package/dist/policies-DH_GCXQ-.js +627 -0
- package/dist/policies-DH_GCXQ-.js.map +1 -0
- package/dist/policies-Nxbp1CH8.cjs +698 -0
- package/dist/policies-Nxbp1CH8.cjs.map +1 -0
- package/dist/privacy/index.cjs +26 -43
- package/dist/privacy/index.cjs.map +1 -1
- package/dist/privacy/index.d.cts +2 -189
- package/dist/privacy/index.d.ts +2 -189
- package/dist/privacy/index.js +18 -3
- package/dist/privacy/index.js.map +1 -1
- package/dist/projections/index.cjs +241 -23
- package/dist/projections/index.cjs.map +1 -1
- package/dist/projections/index.d.cts +2 -125
- package/dist/projections/index.d.ts +2 -125
- package/dist/projections/index.js +238 -3
- package/dist/projections/index.js.map +1 -1
- package/dist/state-machines/index.cjs +76 -18
- package/dist/state-machines/index.cjs.map +1 -1
- package/dist/state-machines/index.d.cts +2 -55
- package/dist/state-machines/index.d.ts +2 -55
- package/dist/state-machines/index.js +74 -2
- package/dist/state-machines/index.js.map +1 -1
- package/dist/testing/index.cjs +27 -19
- package/dist/testing/index.cjs.map +1 -1
- package/dist/testing/index.d.cts +17 -19
- package/dist/testing/index.d.ts +17 -19
- package/dist/testing/index.js +25 -3
- package/dist/testing/index.js.map +1 -1
- package/package.json +6 -5
- package/dist/chunk-2AE6TMAX.cjs +0 -44
- package/dist/chunk-2AE6TMAX.cjs.map +0 -1
- package/dist/chunk-6HY35TKB.cjs +0 -491
- package/dist/chunk-6HY35TKB.cjs.map +0 -1
- package/dist/chunk-6UGEIDLC.cjs +0 -26
- package/dist/chunk-6UGEIDLC.cjs.map +0 -1
- package/dist/chunk-7GAWSUOG.js +0 -64
- package/dist/chunk-7GAWSUOG.js.map +0 -1
- package/dist/chunk-A42JJIPL.cjs +0 -699
- package/dist/chunk-A42JJIPL.cjs.map +0 -1
- package/dist/chunk-AFXKSIVI.cjs +0 -540
- package/dist/chunk-AFXKSIVI.cjs.map +0 -1
- package/dist/chunk-B5DOGDPG.js +0 -42
- package/dist/chunk-B5DOGDPG.js.map +0 -1
- package/dist/chunk-BJGZE3GE.js +0 -20
- package/dist/chunk-BJGZE3GE.js.map +0 -1
- package/dist/chunk-CRZXTZ36.cjs +0 -258
- package/dist/chunk-CRZXTZ36.cjs.map +0 -1
- package/dist/chunk-D4SWRBUH.cjs +0 -22
- package/dist/chunk-D4SWRBUH.cjs.map +0 -1
- package/dist/chunk-DBTAUI6C.cjs +0 -395
- package/dist/chunk-DBTAUI6C.cjs.map +0 -1
- package/dist/chunk-EMSAFNPX.js +0 -98
- package/dist/chunk-EMSAFNPX.js.map +0 -1
- package/dist/chunk-F3E5SXPN.cjs +0 -28
- package/dist/chunk-F3E5SXPN.cjs.map +0 -1
- package/dist/chunk-HEYMMVDP.js +0 -480
- package/dist/chunk-HEYMMVDP.js.map +0 -1
- package/dist/chunk-IFW43ELT.cjs +0 -331
- package/dist/chunk-IFW43ELT.cjs.map +0 -1
- package/dist/chunk-LFE74IJX.js +0 -20
- package/dist/chunk-LFE74IJX.js.map +0 -1
- package/dist/chunk-LZSE6QGQ.cjs +0 -60
- package/dist/chunk-LZSE6QGQ.cjs.map +0 -1
- package/dist/chunk-MCWSUGB3.cjs +0 -102
- package/dist/chunk-MCWSUGB3.cjs.map +0 -1
- package/dist/chunk-MLBALEUR.js +0 -290
- package/dist/chunk-MLBALEUR.js.map +0 -1
- package/dist/chunk-NNXQZPB3.cjs +0 -31
- package/dist/chunk-NNXQZPB3.cjs.map +0 -1
- package/dist/chunk-OFCCZ27Z.js +0 -26
- package/dist/chunk-OFCCZ27Z.js.map +0 -1
- package/dist/chunk-PDN5DOLQ.js +0 -242
- package/dist/chunk-PDN5DOLQ.js.map +0 -1
- package/dist/chunk-PIDZQAEL.js +0 -50
- package/dist/chunk-PIDZQAEL.js.map +0 -1
- package/dist/chunk-PXD7NG6X.js +0 -686
- package/dist/chunk-PXD7NG6X.js.map +0 -1
- package/dist/chunk-Q4Q4JPR3.js +0 -524
- package/dist/chunk-Q4Q4JPR3.js.map +0 -1
- package/dist/chunk-RALMUSOX.js +0 -55
- package/dist/chunk-RALMUSOX.js.map +0 -1
- package/dist/chunk-SNTV45LH.cjs +0 -295
- package/dist/chunk-SNTV45LH.cjs.map +0 -1
- package/dist/chunk-TBS2S5AX.cjs +0 -40
- package/dist/chunk-TBS2S5AX.cjs.map +0 -1
- package/dist/chunk-TYNIFC7J.js +0 -253
- package/dist/chunk-TYNIFC7J.js.map +0 -1
- package/dist/chunk-UGWGHTNC.cjs +0 -56
- package/dist/chunk-UGWGHTNC.cjs.map +0 -1
- package/dist/chunk-WI7CWNYI.cjs +0 -68
- package/dist/chunk-WI7CWNYI.cjs.map +0 -1
- package/dist/chunk-WNZP53GI.js +0 -386
- package/dist/chunk-WNZP53GI.js.map +0 -1
- package/dist/chunk-WQ3BYI7T.cjs +0 -249
- package/dist/chunk-WQ3BYI7T.cjs.map +0 -1
- package/dist/chunk-Y2PJLRIY.js +0 -36
- package/dist/chunk-Y2PJLRIY.js.map +0 -1
- package/dist/chunk-ZAEVQSB5.js +0 -326
- package/dist/chunk-ZAEVQSB5.js.map +0 -1
- package/dist/chunk-ZMQTV5OJ.js +0 -27
- package/dist/chunk-ZMQTV5OJ.js.map +0 -1
- package/dist/evidence/index.cjs.map +0 -1
- package/dist/evidence/index.js.map +0 -1
- package/dist/index.cjs.map +0 -1
- package/dist/index.js.map +0 -1
- package/dist/policies/index.cjs.map +0 -1
- 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
|