@fabricorg/platform 1.6.0 → 1.8.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/CHANGELOG.md +79 -0
- package/README.md +216 -3
- package/dist/actions/index.cjs +6 -6
- package/dist/actions/index.d.cts +85 -3
- package/dist/actions/index.d.ts +85 -3
- package/dist/actions/index.js +1 -1
- package/dist/adapters/index.cjs +33 -9
- package/dist/adapters/index.d.cts +388 -1
- package/dist/adapters/index.d.ts +388 -1
- package/dist/adapters/index.js +1 -1
- package/dist/certification/index.cjs +6 -6
- package/dist/certification/index.js +3 -3
- package/dist/{chunk-VZ6C4LXC.cjs → chunk-45OKKLNY.cjs} +17 -9
- package/dist/chunk-45OKKLNY.cjs.map +1 -0
- package/dist/chunk-5FOCPRTR.js +511 -0
- package/dist/chunk-5FOCPRTR.js.map +1 -0
- package/dist/{chunk-USDLP4E7.cjs → chunk-5IVFPWK6.cjs} +4 -4
- package/dist/{chunk-USDLP4E7.cjs.map → chunk-5IVFPWK6.cjs.map} +1 -1
- package/dist/chunk-6HY35TKB.cjs +491 -0
- package/dist/chunk-6HY35TKB.cjs.map +1 -0
- package/dist/chunk-6UGEIDLC.cjs +26 -0
- package/dist/chunk-6UGEIDLC.cjs.map +1 -0
- package/dist/chunk-BJGZE3GE.js +20 -0
- package/dist/chunk-BJGZE3GE.js.map +1 -0
- package/dist/{chunk-X3GHYMAJ.cjs → chunk-CRZXTZ36.cjs} +2 -22
- package/dist/chunk-CRZXTZ36.cjs.map +1 -0
- package/dist/{chunk-TMMP4U2D.cjs → chunk-DBTAUI6C.cjs} +5 -2
- package/dist/chunk-DBTAUI6C.cjs.map +1 -0
- package/dist/{chunk-UYCQV65U.js → chunk-EMSAFNPX.js} +3 -3
- package/dist/{chunk-UYCQV65U.js.map → chunk-EMSAFNPX.js.map} +1 -1
- package/dist/{chunk-DCC3UIUJ.js → chunk-GFU7BGEJ.js} +3 -3
- package/dist/{chunk-DCC3UIUJ.js.map → chunk-GFU7BGEJ.js.map} +1 -1
- package/dist/{chunk-JFVEPAED.js → chunk-GU3LZWJD.js} +17 -9
- package/dist/chunk-GU3LZWJD.js.map +1 -0
- package/dist/chunk-HEYMMVDP.js +480 -0
- package/dist/chunk-HEYMMVDP.js.map +1 -0
- package/dist/chunk-IF6NJORI.cjs +526 -0
- package/dist/chunk-IF6NJORI.cjs.map +1 -0
- package/dist/{chunk-XS7EUS4T.cjs → chunk-MCWSUGB3.cjs} +4 -4
- package/dist/{chunk-XS7EUS4T.cjs.map → chunk-MCWSUGB3.cjs.map} +1 -1
- package/dist/{chunk-QHV6LOS6.js → chunk-PDN5DOLQ.js} +3 -3
- package/dist/{chunk-QHV6LOS6.js.map → chunk-PDN5DOLQ.js.map} +1 -1
- package/dist/{chunk-OZWUNGJE.js → chunk-PIDZQAEL.js} +5 -2
- package/dist/chunk-PIDZQAEL.js.map +1 -0
- package/dist/{chunk-ATWWZTRC.js → chunk-TYNIFC7J.js} +3 -18
- package/dist/chunk-TYNIFC7J.js.map +1 -0
- package/dist/{chunk-DDX5FKOM.cjs → chunk-UGWGHTNC.cjs} +5 -2
- package/dist/chunk-UGWGHTNC.cjs.map +1 -0
- package/dist/{chunk-ZF5HDNSU.js → chunk-WNZP53GI.js} +5 -2
- package/dist/chunk-WNZP53GI.js.map +1 -0
- package/dist/{chunk-2URHPZXL.cjs → chunk-WQ3BYI7T.cjs} +6 -6
- package/dist/{chunk-2URHPZXL.cjs.map → chunk-WQ3BYI7T.cjs.map} +1 -1
- package/dist/evidence/index.cjs +45 -1
- package/dist/evidence/index.d.cts +187 -1
- package/dist/evidence/index.d.ts +187 -1
- package/dist/evidence/index.js +3 -1
- package/dist/governance/index.d.cts +1 -0
- package/dist/governance/index.d.ts +1 -0
- package/dist/index.cjs +153 -88
- package/dist/index.d.cts +4 -4
- package/dist/index.d.ts +4 -4
- package/dist/index.js +11 -10
- package/dist/manifest/index.cjs +8 -8
- package/dist/manifest/index.js +2 -2
- package/dist/modules/index.cjs +9 -9
- package/dist/modules/index.js +1 -1
- package/dist/policies/index.cjs +9 -9
- package/dist/policies/index.d.cts +14 -1
- package/dist/policies/index.d.ts +14 -1
- package/dist/policies/index.js +1 -1
- package/dist/privacy/index.cjs +19 -18
- package/dist/privacy/index.js +2 -1
- package/dist/testing/index.cjs +5 -5
- package/dist/testing/index.js +2 -2
- package/package.json +1 -1
- package/dist/chunk-ATWWZTRC.js.map +0 -1
- package/dist/chunk-DDX5FKOM.cjs.map +0 -1
- package/dist/chunk-FAG2RTPM.js +0 -120
- package/dist/chunk-FAG2RTPM.js.map +0 -1
- package/dist/chunk-JFVEPAED.js.map +0 -1
- package/dist/chunk-OZLZHISS.js +0 -3
- package/dist/chunk-OZLZHISS.js.map +0 -1
- package/dist/chunk-OZWUNGJE.js.map +0 -1
- package/dist/chunk-PG5LYTUX.cjs +0 -4
- package/dist/chunk-PG5LYTUX.cjs.map +0 -1
- package/dist/chunk-TMMP4U2D.cjs.map +0 -1
- package/dist/chunk-VZ6C4LXC.cjs.map +0 -1
- package/dist/chunk-X3GHYMAJ.cjs.map +0 -1
- package/dist/chunk-XZQZQ5SW.cjs +0 -129
- package/dist/chunk-XZQZQ5SW.cjs.map +0 -1
- package/dist/chunk-ZF5HDNSU.js.map +0 -1
package/dist/adapters/index.d.ts
CHANGED
|
@@ -1,3 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* State of an adapter circuit breaker.
|
|
3
|
+
*
|
|
4
|
+
* - `closed`: calls flow and outcomes are counted.
|
|
5
|
+
* - `open`: the dependency is presumed unhealthy. In `enforce` mode calls are
|
|
6
|
+
* rejected without being attempted until `cooldownMs` has elapsed.
|
|
7
|
+
* - `half_open`: the cooldown elapsed. One probe call is admitted; its outcome
|
|
8
|
+
* closes the breaker (success) or reopens it (failure).
|
|
9
|
+
*/
|
|
10
|
+
type AdapterCircuitState = "closed" | "open" | "half_open";
|
|
11
|
+
/**
|
|
12
|
+
* How a single adapter outcome counts toward the breaker.
|
|
13
|
+
*
|
|
14
|
+
* - `success`: the dependency answered and the call succeeded.
|
|
15
|
+
* - `failure`: evidence the dependency is unhealthy.
|
|
16
|
+
* - `ignored`: the dependency answered but rejected the request on its merits
|
|
17
|
+
* (a validation or business rejection). It is neither a success nor a
|
|
18
|
+
* dependency failure and does not enter the rolling window.
|
|
19
|
+
*/
|
|
20
|
+
type AdapterCircuitOutcome = "success" | "failure" | "ignored";
|
|
21
|
+
/**
|
|
22
|
+
* Map an {@link AdapterOutcomeKind} to how it counts toward a circuit breaker.
|
|
23
|
+
*
|
|
24
|
+
* | Outcome kind | Counts as |
|
|
25
|
+
* |---------------------|-----------|
|
|
26
|
+
* | `success` | `success` |
|
|
27
|
+
* | `transient_failure` | `failure` |
|
|
28
|
+
* | `timeout` | `failure` |
|
|
29
|
+
* | `ambiguous` | `failure` |
|
|
30
|
+
* | `permanent_failure` | `ignored` |
|
|
31
|
+
*
|
|
32
|
+
* `ambiguous` counts as a failure: the dependency did not give a definite
|
|
33
|
+
* answer, which is a health signal even though the Host routes the invocation
|
|
34
|
+
* to reconciliation. `permanent_failure` (validation or rejection) is the
|
|
35
|
+
* dependency working correctly and saying no, so it does not trip the breaker.
|
|
36
|
+
* `executeWithAdapterRetry` classifies a thrown error with the caller's
|
|
37
|
+
* `classifyThrownError` (default `transient_failure`) and maps that kind here,
|
|
38
|
+
* so an unclassified thrown error counts as a failure.
|
|
39
|
+
*/
|
|
40
|
+
declare function classifyCircuitBreakerOutcome(kind: AdapterOutcomeKind): AdapterCircuitOutcome;
|
|
41
|
+
/** The answer a breaker gives before a call. */
|
|
42
|
+
interface AdapterCircuitAdmission {
|
|
43
|
+
/**
|
|
44
|
+
* Whether the call may proceed. Always `true` in `monitor` mode; `false`
|
|
45
|
+
* only in `enforce` mode while the breaker is open, forced open, or
|
|
46
|
+
* half-open with its probe already in flight.
|
|
47
|
+
*/
|
|
48
|
+
allowed: boolean;
|
|
49
|
+
/** State at the time of the decision. */
|
|
50
|
+
state: AdapterCircuitState;
|
|
51
|
+
/** True when this admission is the half-open probe. Pass it back to `record`. */
|
|
52
|
+
probe: boolean;
|
|
53
|
+
/** Monitor mode only: true when `enforce` mode would have rejected this call. */
|
|
54
|
+
wouldReject?: boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Milliseconds until the breaker will admit a probe, when known. Absent while
|
|
57
|
+
* a manual `force_open` override is set or a half-open probe is in flight.
|
|
58
|
+
*/
|
|
59
|
+
retryAfterMs?: number;
|
|
60
|
+
/** Set when a manual override decided the admission. */
|
|
61
|
+
manualOverride?: AdapterCircuitBreakerManualOverride;
|
|
62
|
+
/**
|
|
63
|
+
* The breaker epoch the admission was granted in; opaque to callers.
|
|
64
|
+
* {@link InMemoryAdapterCircuitBreaker} lets an outcome change state only
|
|
65
|
+
* when this still matches its current epoch. An admission without it is
|
|
66
|
+
* treated as current.
|
|
67
|
+
*/
|
|
68
|
+
generation?: number;
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Contract between a circuit breaker and `executeWithAdapterRetry`.
|
|
72
|
+
* Implement it to plug in a shared or distributed breaker.
|
|
73
|
+
*/
|
|
74
|
+
interface AdapterCircuitBreaker {
|
|
75
|
+
/** `adapterType:operation` this breaker guards. */
|
|
76
|
+
readonly key: string;
|
|
77
|
+
readonly mode: "monitor" | "enforce";
|
|
78
|
+
/** Current state, applying any elapsed cooldown or manual override. */
|
|
79
|
+
getState(): AdapterCircuitState;
|
|
80
|
+
/**
|
|
81
|
+
* Preview whether a call would be admitted now. Side-effect free: it does
|
|
82
|
+
* not commit an elapsed cooldown, take the half-open probe or emit
|
|
83
|
+
* telemetry.
|
|
84
|
+
*/
|
|
85
|
+
check(): AdapterCircuitAdmission;
|
|
86
|
+
/**
|
|
87
|
+
* Decide whether a call may start now. Call it immediately before the
|
|
88
|
+
* external effect and pass the returned admission to {@link record}.
|
|
89
|
+
*/
|
|
90
|
+
acquire(): AdapterCircuitAdmission;
|
|
91
|
+
/**
|
|
92
|
+
* Record the outcome of a call that was admitted by {@link acquire}. Pass
|
|
93
|
+
* that admission, not a {@link check} preview, so the breaker can tell a
|
|
94
|
+
* stale outcome from a current one.
|
|
95
|
+
*/
|
|
96
|
+
record(outcome: AdapterCircuitOutcome, admission?: AdapterCircuitAdmission): void;
|
|
97
|
+
}
|
|
98
|
+
type AdapterCircuitBreakerEventReason = "failure_threshold" | "cooldown_elapsed" | "probe_succeeded" | "probe_failed" | "manual_override" | "manual_override_cleared";
|
|
99
|
+
interface AdapterCircuitBreakerEventBase {
|
|
100
|
+
key: string;
|
|
101
|
+
mode: "monitor" | "enforce";
|
|
102
|
+
/** Epoch milliseconds from the breaker's clock. */
|
|
103
|
+
at: number;
|
|
104
|
+
}
|
|
105
|
+
/** Telemetry reported by {@link InMemoryAdapterCircuitBreaker}. */
|
|
106
|
+
type AdapterCircuitBreakerEvent = (AdapterCircuitBreakerEventBase & {
|
|
107
|
+
type: "state_change";
|
|
108
|
+
from: AdapterCircuitState;
|
|
109
|
+
to: AdapterCircuitState;
|
|
110
|
+
reason: AdapterCircuitBreakerEventReason;
|
|
111
|
+
manualOverride?: AdapterCircuitBreakerManualOverride;
|
|
112
|
+
}) | (AdapterCircuitBreakerEventBase & {
|
|
113
|
+
/** Enforce mode refused a call; it was not attempted. */
|
|
114
|
+
type: "rejected";
|
|
115
|
+
state: AdapterCircuitState;
|
|
116
|
+
retryAfterMs?: number;
|
|
117
|
+
manualOverride?: AdapterCircuitBreakerManualOverride;
|
|
118
|
+
}) | (AdapterCircuitBreakerEventBase & {
|
|
119
|
+
/** Monitor mode let a call through that enforce mode would have refused. */
|
|
120
|
+
type: "would_reject";
|
|
121
|
+
state: AdapterCircuitState;
|
|
122
|
+
retryAfterMs?: number;
|
|
123
|
+
manualOverride?: AdapterCircuitBreakerManualOverride;
|
|
124
|
+
});
|
|
125
|
+
/**
|
|
126
|
+
* Telemetry callback. Errors it throws and promises it rejects are caught
|
|
127
|
+
* and discarded so telemetry cannot change an adapter call's outcome.
|
|
128
|
+
*
|
|
129
|
+
* {@link InMemoryAdapterCircuitBreaker} calls it only after the operation that
|
|
130
|
+
* produced the event has committed, never part-way through a decision or a
|
|
131
|
+
* record. A callback may call back into the breaker; it sees committed state,
|
|
132
|
+
* and events its own calls produce are delivered after it returns, in order.
|
|
133
|
+
*/
|
|
134
|
+
type AdapterCircuitBreakerEventListener = (event: AdapterCircuitBreakerEvent) => void | Promise<void>;
|
|
135
|
+
interface InMemoryAdapterCircuitBreakerOptions {
|
|
136
|
+
/** Usually `adapterType:operation`. */
|
|
137
|
+
key: string;
|
|
138
|
+
config: AdapterCircuitBreakerConfig;
|
|
139
|
+
/** Epoch-millisecond clock. Defaults to `Date.now`. */
|
|
140
|
+
now?: () => number;
|
|
141
|
+
onEvent?: AdapterCircuitBreakerEventListener;
|
|
142
|
+
}
|
|
143
|
+
/**
|
|
144
|
+
* Validate a circuit-breaker config. Throws a `RangeError` naming the first
|
|
145
|
+
* invalid field: `mode` must be `monitor` or `enforce`; `failureThreshold` and
|
|
146
|
+
* `minimumSamples` positive integers; `windowMs` and `probeLeaseMs` positive
|
|
147
|
+
* finite numbers; `cooldownMs` a non-negative finite number; `manualOverride`
|
|
148
|
+
* `force_open` or `force_closed` when present.
|
|
149
|
+
*/
|
|
150
|
+
declare function assertAdapterCircuitBreakerConfig(config: AdapterCircuitBreakerConfig): void;
|
|
151
|
+
/**
|
|
152
|
+
* Dependency-free, in-process circuit breaker for one adapter operation.
|
|
153
|
+
*
|
|
154
|
+
* State lives in this instance only: it is not shared between processes,
|
|
155
|
+
* hosts, or replicas, and it is lost on restart. Each replica trips on the
|
|
156
|
+
* failures it observes itself.
|
|
157
|
+
*
|
|
158
|
+
* Tripping rule (parity with the .NET `InMemoryAdapterCircuitBreaker`): after
|
|
159
|
+
* a failure is recorded while `closed`, let `N` be the outcomes recorded within
|
|
160
|
+
* the last `windowMs` and `M = minimumSamples ?? failureThreshold`. The breaker
|
|
161
|
+
* opens when `N >= M` and either
|
|
162
|
+
* 1. the most recent `failureThreshold` outcomes in the window are all
|
|
163
|
+
* failures, or
|
|
164
|
+
* 2. the failure ratio in the window is at least `failureThreshold / M`.
|
|
165
|
+
*
|
|
166
|
+
* With `minimumSamples` omitted this reads "`failureThreshold` consecutive
|
|
167
|
+
* failures". With `minimumSamples: 20, failureThreshold: 10` it also opens at
|
|
168
|
+
* a 50% failure rate over at least 20 calls.
|
|
169
|
+
*
|
|
170
|
+
* After `cooldownMs` the breaker turns `half_open` and admits one probe. A
|
|
171
|
+
* probe success closes it and clears the window; a probe failure reopens it
|
|
172
|
+
* and restarts the cooldown. At most one probe is outstanding at a time: it
|
|
173
|
+
* holds a lease of `probeLeaseMs` (default `max(cooldownMs, windowMs)`, never
|
|
174
|
+
* derived from the cooldown alone, so `cooldownMs: 0` still admits one probe).
|
|
175
|
+
* A probe that has not recorded when its lease expires is considered lost and
|
|
176
|
+
* the next call becomes the probe.
|
|
177
|
+
*
|
|
178
|
+
* Epochs: the breaker keeps a generation counter that advances on every state
|
|
179
|
+
* change (including one committed by an elapsed cooldown), every manual
|
|
180
|
+
* override change, and every probe grant. Each admission carries the
|
|
181
|
+
* generation it was granted in. `record` first commits any elapsed cooldown,
|
|
182
|
+
* then compares generations. An outcome from an earlier epoch is stale: it is
|
|
183
|
+
* dropped entirely. It changes no state, does not resolve or free the probe
|
|
184
|
+
* slot, and is not added to the rolling window, so it cannot contribute to a
|
|
185
|
+
* later trip either. Because a probe grant starts a new epoch, the outstanding
|
|
186
|
+
* probe is the only `probe: true` admission of the current epoch, which is how
|
|
187
|
+
* a replaced probe's late outcome is told apart. An outcome recorded without an
|
|
188
|
+
* admission, or with one that has no `generation`, is treated as current: it is
|
|
189
|
+
* sampled, can trip a closed breaker and resolves an outstanding probe.
|
|
190
|
+
*
|
|
191
|
+
* Telemetry is buffered and delivered after each operation commits. An
|
|
192
|
+
* elapsed cooldown is committed, and its `cooldown_elapsed` event delivered,
|
|
193
|
+
* as a step of its own before `acquire`, `record`, `getState` or
|
|
194
|
+
* `setManualOverride` continues, so a callback reacting to it (for example by
|
|
195
|
+
* forcing the breaker open) governs the call that observed it. Every other
|
|
196
|
+
* event is delivered once the method's decision or record is final, and a
|
|
197
|
+
* callback never revokes an admission that is already committed. Two cases
|
|
198
|
+
* follow from that: a breaker call made from inside a callback queues its own
|
|
199
|
+
* `cooldown_elapsed` behind the current delivery and decides first; and with
|
|
200
|
+
* `cooldownMs: 0`, a cooldown that falls due again during the decision (because
|
|
201
|
+
* a callback reopened the breaker) is committed and admitted before its event
|
|
202
|
+
* is delivered.
|
|
203
|
+
*
|
|
204
|
+
* `monitor` mode runs the same state machine and reports the same telemetry
|
|
205
|
+
* but admits every call; calls enforce mode would have refused are reported
|
|
206
|
+
* as `would_reject`.
|
|
207
|
+
*
|
|
208
|
+
* A manual override pins the reported state (`force_open` → `open`,
|
|
209
|
+
* `force_closed` → `closed`) and suspends automatic transitions while set;
|
|
210
|
+
* outcomes of calls admitted under the override are still recorded. Like an
|
|
211
|
+
* automatic open, `force_open` blocks only in `enforce` mode. Clearing the
|
|
212
|
+
* override returns the breaker to `closed` with its window intact.
|
|
213
|
+
*/
|
|
214
|
+
declare class InMemoryAdapterCircuitBreaker implements AdapterCircuitBreaker {
|
|
215
|
+
readonly key: string;
|
|
216
|
+
readonly mode: "monitor" | "enforce";
|
|
217
|
+
private readonly config;
|
|
218
|
+
private readonly now;
|
|
219
|
+
private readonly onEvent;
|
|
220
|
+
private readonly probeLeaseMs;
|
|
221
|
+
private samples;
|
|
222
|
+
private state;
|
|
223
|
+
private openedAt;
|
|
224
|
+
private probeIssuedAt;
|
|
225
|
+
/** Advances on every state change, manual override change and probe grant. */
|
|
226
|
+
private generation;
|
|
227
|
+
private manualOverride;
|
|
228
|
+
/** Telemetry waiting for the current operation to commit. */
|
|
229
|
+
private readonly outbox;
|
|
230
|
+
private operationDepth;
|
|
231
|
+
private flushing;
|
|
232
|
+
constructor(options: InMemoryAdapterCircuitBreakerOptions);
|
|
233
|
+
getState(): AdapterCircuitState;
|
|
234
|
+
getManualOverride(): AdapterCircuitBreakerManualOverride | undefined;
|
|
235
|
+
/**
|
|
236
|
+
* Set (`force_open` / `force_closed`) or clear (`undefined`) the manual
|
|
237
|
+
* override. Clearing returns the breaker to `closed` with its window intact.
|
|
238
|
+
*/
|
|
239
|
+
setManualOverride(override: AdapterCircuitBreakerManualOverride | undefined): void;
|
|
240
|
+
check(): AdapterCircuitAdmission;
|
|
241
|
+
acquire(): AdapterCircuitAdmission;
|
|
242
|
+
record(outcome: AdapterCircuitOutcome, admission?: AdapterCircuitAdmission): void;
|
|
243
|
+
private applyOutcome;
|
|
244
|
+
/**
|
|
245
|
+
* `take` is false for {@link check}: a pure preview that sees an elapsed
|
|
246
|
+
* cooldown without committing it, takes no probe and emits nothing.
|
|
247
|
+
*/
|
|
248
|
+
private decide;
|
|
249
|
+
private refuse;
|
|
250
|
+
private releaseProbe;
|
|
251
|
+
/** Apply the time-based open → half_open transition. */
|
|
252
|
+
private advance;
|
|
253
|
+
private shouldTrip;
|
|
254
|
+
private prune;
|
|
255
|
+
private transition;
|
|
256
|
+
private reportedState;
|
|
257
|
+
/**
|
|
258
|
+
* Commit an elapsed cooldown as an operation of its own, delivering its
|
|
259
|
+
* event before the caller's operation reads state.
|
|
260
|
+
*/
|
|
261
|
+
private settle;
|
|
262
|
+
/**
|
|
263
|
+
* Run `step` to completion, then deliver the telemetry it produced. The
|
|
264
|
+
* return value is fixed before any listener runs.
|
|
265
|
+
*/
|
|
266
|
+
private operation;
|
|
267
|
+
private emit;
|
|
268
|
+
/**
|
|
269
|
+
* Deliver buffered events in order. A listener that calls back into the
|
|
270
|
+
* breaker queues its own events; this loop delivers them after it returns
|
|
271
|
+
* instead of recursing.
|
|
272
|
+
*/
|
|
273
|
+
private flush;
|
|
274
|
+
private deliver;
|
|
275
|
+
}
|
|
276
|
+
/** Supplies the breaker, if any, that guards an adapter. */
|
|
277
|
+
interface AdapterCircuitBreakerProvider {
|
|
278
|
+
forAdapter(adapter: AdapterImplementation): AdapterCircuitBreaker | undefined;
|
|
279
|
+
}
|
|
280
|
+
interface AdapterCircuitBreakerRegistryOptions {
|
|
281
|
+
/** Epoch-millisecond clock handed to every breaker. Defaults to `Date.now`. */
|
|
282
|
+
now?: () => number;
|
|
283
|
+
onEvent?: AdapterCircuitBreakerEventListener;
|
|
284
|
+
}
|
|
285
|
+
/**
|
|
286
|
+
* Lazily creates one {@link InMemoryAdapterCircuitBreaker} per
|
|
287
|
+
* `adapterType:operation`, from that adapter's own `circuitBreaker` config.
|
|
288
|
+
* Adapters without a config get no breaker. The first config seen for a key
|
|
289
|
+
* wins; share a registry only between hosts that register the same adapters.
|
|
290
|
+
*/
|
|
291
|
+
declare class AdapterCircuitBreakerRegistry implements AdapterCircuitBreakerProvider {
|
|
292
|
+
private readonly options;
|
|
293
|
+
private readonly breakers;
|
|
294
|
+
constructor(options?: AdapterCircuitBreakerRegistryOptions);
|
|
295
|
+
forAdapter(adapter: AdapterImplementation): InMemoryAdapterCircuitBreaker | undefined;
|
|
296
|
+
/** The breaker already created for `adapterType:operation`, if any. */
|
|
297
|
+
get(adapterType: string, operation: string): InMemoryAdapterCircuitBreaker | undefined;
|
|
298
|
+
}
|
|
299
|
+
/**
|
|
300
|
+
* Thrown by `executeWithAdapterRetry` when an `enforce`-mode breaker refuses
|
|
301
|
+
* an attempt. The refused attempt never reached `execute`, so no external
|
|
302
|
+
* effect happened for it.
|
|
303
|
+
*/
|
|
304
|
+
declare class AdapterCircuitOpenError extends Error {
|
|
305
|
+
readonly name = "AdapterCircuitOpenError";
|
|
306
|
+
readonly code: "ADAPTER_CIRCUIT_OPEN";
|
|
307
|
+
readonly reason: "circuit_open";
|
|
308
|
+
readonly adapterKey: string;
|
|
309
|
+
readonly state: AdapterCircuitState;
|
|
310
|
+
/** The attempt number that was refused (1 = refused before any call). */
|
|
311
|
+
readonly attempt: number;
|
|
312
|
+
readonly retryAfterMs?: number;
|
|
313
|
+
readonly manualOverride?: AdapterCircuitBreakerManualOverride;
|
|
314
|
+
/** Error of the previous attempt, when the breaker opened mid-retry. */
|
|
315
|
+
readonly lastError?: string;
|
|
316
|
+
constructor(input: {
|
|
317
|
+
adapterKey: string;
|
|
318
|
+
state: AdapterCircuitState;
|
|
319
|
+
attempt: number;
|
|
320
|
+
retryAfterMs?: number;
|
|
321
|
+
manualOverride?: AdapterCircuitBreakerManualOverride;
|
|
322
|
+
lastError?: string;
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Recognise an {@link AdapterCircuitOpenError}, including one constructed by a
|
|
327
|
+
* second copy of this package (for example an ESM and a CommonJS build loaded
|
|
328
|
+
* side by side), where `instanceof` fails.
|
|
329
|
+
*/
|
|
330
|
+
declare function isAdapterCircuitOpenError(error: unknown): error is AdapterCircuitOpenError;
|
|
331
|
+
|
|
1
332
|
interface AdapterExecutionContext {
|
|
2
333
|
tenantId: string;
|
|
3
334
|
spaceId: string;
|
|
@@ -89,12 +420,49 @@ interface ResolvedAdapterRetryPolicy {
|
|
|
89
420
|
backoffMultiplier: number;
|
|
90
421
|
maxDelayMs: number;
|
|
91
422
|
}
|
|
423
|
+
/** Manual circuit-breaker override: pin the breaker open or closed. */
|
|
424
|
+
type AdapterCircuitBreakerManualOverride = "force_open" | "force_closed";
|
|
425
|
+
/**
|
|
426
|
+
* Per-adapter circuit-breaker configuration, read by
|
|
427
|
+
* {@link AdapterCircuitBreakerRegistry} (and so by Platform Host) to create one
|
|
428
|
+
* in-process {@link InMemoryAdapterCircuitBreaker} per `adapterType:operation`.
|
|
429
|
+
* Validated by {@link assertAdapterCircuitBreakerConfig}.
|
|
430
|
+
*/
|
|
92
431
|
interface AdapterCircuitBreakerConfig {
|
|
432
|
+
/**
|
|
433
|
+
* `monitor` records outcomes, runs the state machine and reports what it
|
|
434
|
+
* would have refused, but never blocks a call. `enforce` refuses calls
|
|
435
|
+
* while the breaker is open, without attempting them.
|
|
436
|
+
*/
|
|
93
437
|
mode: "monitor" | "enforce";
|
|
438
|
+
/**
|
|
439
|
+
* A failure count. Let `M = minimumSamples ?? failureThreshold`. Once at
|
|
440
|
+
* least `M` outcomes fall within `windowMs`, the breaker opens when the most
|
|
441
|
+
* recent `failureThreshold` of them are all failures, or when the failure
|
|
442
|
+
* ratio in the window reaches `failureThreshold / M`. Without
|
|
443
|
+
* `minimumSamples` this is "`failureThreshold` consecutive failures".
|
|
444
|
+
* Matches the .NET port's `InMemoryAdapterCircuitBreaker`. Positive integer.
|
|
445
|
+
*/
|
|
94
446
|
failureThreshold: number;
|
|
447
|
+
/** Rolling window, in milliseconds, of outcomes the thresholds consider. */
|
|
95
448
|
windowMs: number;
|
|
449
|
+
/** Milliseconds an open breaker waits before admitting one half-open probe. */
|
|
96
450
|
cooldownMs: number;
|
|
451
|
+
/** Outcomes required in the window before the breaker can open. Defaults to `failureThreshold`. */
|
|
97
452
|
minimumSamples?: number;
|
|
453
|
+
/**
|
|
454
|
+
* How long, in milliseconds, the single half-open probe holds its slot
|
|
455
|
+
* before it is presumed lost and another call may probe. Defaults to
|
|
456
|
+
* `max(cooldownMs, windowMs)`; it is independent of `cooldownMs`, so a zero
|
|
457
|
+
* or short cooldown never admits concurrent probes. Positive.
|
|
458
|
+
*/
|
|
459
|
+
probeLeaseMs?: number;
|
|
460
|
+
/**
|
|
461
|
+
* Optional initial manual override. `force_open` reports `open` (and blocks
|
|
462
|
+
* only in `enforce` mode); `force_closed` reports `closed` and never blocks.
|
|
463
|
+
* Change it at runtime with `InMemoryAdapterCircuitBreaker.setManualOverride`.
|
|
464
|
+
*/
|
|
465
|
+
manualOverride?: AdapterCircuitBreakerManualOverride;
|
|
98
466
|
}
|
|
99
467
|
interface AdapterImplementation {
|
|
100
468
|
adapterType: string;
|
|
@@ -136,6 +504,25 @@ interface ExecuteWithRetryOptions<T> {
|
|
|
136
504
|
classifyThrownError?: (error: unknown) => AdapterOutcomeKind;
|
|
137
505
|
sleep?: (delayMs: number) => Promise<void>;
|
|
138
506
|
onAttempt?: (attempt: AdapterAttempt<T>) => Promise<void> | void;
|
|
507
|
+
/**
|
|
508
|
+
* Optional per-attempt preparation, awaited before the circuit breaker is
|
|
509
|
+
* consulted and before `execute` (for example, persisting the attempt
|
|
510
|
+
* number). Put every await a caller needs before the call here, so that
|
|
511
|
+
* nothing awaits between breaker admission and the external call. If it
|
|
512
|
+
* throws, no admission is taken and no breaker outcome is recorded; the
|
|
513
|
+
* error is classified with `classifyThrownError` and retried or rethrown
|
|
514
|
+
* exactly like an error thrown by `execute`.
|
|
515
|
+
*/
|
|
516
|
+
prepareAttempt?: (attempt: number, maxAttempts: number) => Promise<void> | void;
|
|
517
|
+
/**
|
|
518
|
+
* Optional circuit breaker. When present, `acquire()` is called
|
|
519
|
+
* immediately before every `execute` call, with no await in between, and every attempt's outcome is
|
|
520
|
+
* recorded through {@link classifyCircuitBreakerOutcome}. In `enforce` mode
|
|
521
|
+
* a refused attempt is not executed and {@link AdapterCircuitOpenError} is
|
|
522
|
+
* thrown; if the breaker opens between attempts, retrying stops and the
|
|
523
|
+
* same error is thrown. When omitted, behaviour is unchanged.
|
|
524
|
+
*/
|
|
525
|
+
circuitBreaker?: AdapterCircuitBreaker;
|
|
139
526
|
}
|
|
140
527
|
declare class MissingAdapterRegistrationError extends Error {
|
|
141
528
|
constructor(adapterType: string, operation: string);
|
|
@@ -171,4 +558,4 @@ declare function shouldRetryAdapterOutcome(kind: AdapterOutcomeKind, idempotent:
|
|
|
171
558
|
declare function assertAdapterOutcomeConsistency(result: AdapterExecutionResult): void;
|
|
172
559
|
declare function executeWithAdapterRetry<T>(options: ExecuteWithRetryOptions<T>): Promise<T>;
|
|
173
560
|
|
|
174
|
-
export { type AcceptedExternalOperation, type AdapterAttempt, type AdapterCircuitBreakerConfig, type AdapterExecutionContext, type AdapterExecutionResult, type AdapterExecutor, type AdapterImplementation, type AdapterOutcomeEvidence, type AdapterOutcomeKind, AdapterRegistry, type AdapterRetryPolicy, type ExecuteWithRetryOptions, MissingAdapterRegistrationError, type ResolvedAdapterRetryPolicy, assertAdapterOutcomeConsistency, classifyAdapterOutcome, executeWithAdapterRetry, getRetryDelayMs, resolveAdapterRetryPolicy, shouldRetryAdapterOutcome };
|
|
561
|
+
export { type AcceptedExternalOperation, type AdapterAttempt, type AdapterCircuitAdmission, type AdapterCircuitBreaker, type AdapterCircuitBreakerConfig, type AdapterCircuitBreakerEvent, type AdapterCircuitBreakerEventListener, type AdapterCircuitBreakerEventReason, type AdapterCircuitBreakerManualOverride, type AdapterCircuitBreakerProvider, AdapterCircuitBreakerRegistry, type AdapterCircuitBreakerRegistryOptions, AdapterCircuitOpenError, type AdapterCircuitOutcome, type AdapterCircuitState, type AdapterExecutionContext, type AdapterExecutionResult, type AdapterExecutor, type AdapterImplementation, type AdapterOutcomeEvidence, type AdapterOutcomeKind, AdapterRegistry, type AdapterRetryPolicy, type ExecuteWithRetryOptions, InMemoryAdapterCircuitBreaker, type InMemoryAdapterCircuitBreakerOptions, MissingAdapterRegistrationError, type ResolvedAdapterRetryPolicy, assertAdapterCircuitBreakerConfig, assertAdapterOutcomeConsistency, classifyAdapterOutcome, classifyCircuitBreakerOutcome, executeWithAdapterRetry, getRetryDelayMs, isAdapterCircuitOpenError, resolveAdapterRetryPolicy, shouldRetryAdapterOutcome };
|
package/dist/adapters/index.js
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
|
-
export { AdapterRegistry, MissingAdapterRegistrationError, assertAdapterOutcomeConsistency, classifyAdapterOutcome, executeWithAdapterRetry, getRetryDelayMs, resolveAdapterRetryPolicy, shouldRetryAdapterOutcome } from '../chunk-
|
|
1
|
+
export { AdapterCircuitBreakerRegistry, AdapterCircuitOpenError, AdapterRegistry, InMemoryAdapterCircuitBreaker, MissingAdapterRegistrationError, assertAdapterCircuitBreakerConfig, assertAdapterOutcomeConsistency, classifyAdapterOutcome, classifyCircuitBreakerOutcome, executeWithAdapterRetry, getRetryDelayMs, isAdapterCircuitOpenError, resolveAdapterRetryPolicy, shouldRetryAdapterOutcome } from '../chunk-5FOCPRTR.js';
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
|
3
3
|
//# sourceMappingURL=index.js.map
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
-
var
|
|
4
|
-
require('../chunk-
|
|
5
|
-
require('../chunk-
|
|
3
|
+
var chunkMCWSUGB3_cjs = require('../chunk-MCWSUGB3.cjs');
|
|
4
|
+
require('../chunk-WQ3BYI7T.cjs');
|
|
5
|
+
require('../chunk-DBTAUI6C.cjs');
|
|
6
6
|
require('../chunk-IFW43ELT.cjs');
|
|
7
7
|
require('../chunk-SNTV45LH.cjs');
|
|
8
8
|
require('../chunk-D4SWRBUH.cjs');
|
|
@@ -12,15 +12,15 @@ require('../chunk-2AE6TMAX.cjs');
|
|
|
12
12
|
|
|
13
13
|
Object.defineProperty(exports, "STRICT_EXECUTION_CONTRACT_PROFILE", {
|
|
14
14
|
enumerable: true,
|
|
15
|
-
get: function () { return
|
|
15
|
+
get: function () { return chunkMCWSUGB3_cjs.STRICT_EXECUTION_CONTRACT_PROFILE; }
|
|
16
16
|
});
|
|
17
17
|
Object.defineProperty(exports, "STRICT_EXECUTION_CONTRACT_PROFILE_ID", {
|
|
18
18
|
enumerable: true,
|
|
19
|
-
get: function () { return
|
|
19
|
+
get: function () { return chunkMCWSUGB3_cjs.STRICT_EXECUTION_CONTRACT_PROFILE_ID; }
|
|
20
20
|
});
|
|
21
21
|
Object.defineProperty(exports, "executionContractProfile", {
|
|
22
22
|
enumerable: true,
|
|
23
|
-
get: function () { return
|
|
23
|
+
get: function () { return chunkMCWSUGB3_cjs.executionContractProfile; }
|
|
24
24
|
});
|
|
25
25
|
//# sourceMappingURL=index.cjs.map
|
|
26
26
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
export { STRICT_EXECUTION_CONTRACT_PROFILE, STRICT_EXECUTION_CONTRACT_PROFILE_ID, executionContractProfile } from '../chunk-
|
|
2
|
-
import '../chunk-
|
|
3
|
-
import '../chunk-
|
|
1
|
+
export { STRICT_EXECUTION_CONTRACT_PROFILE, STRICT_EXECUTION_CONTRACT_PROFILE_ID, executionContractProfile } from '../chunk-EMSAFNPX.js';
|
|
2
|
+
import '../chunk-PDN5DOLQ.js';
|
|
3
|
+
import '../chunk-WNZP53GI.js';
|
|
4
4
|
import '../chunk-ZAEVQSB5.js';
|
|
5
5
|
import '../chunk-MLBALEUR.js';
|
|
6
6
|
import '../chunk-LFE74IJX.js';
|
|
@@ -147,13 +147,21 @@ async function evaluatePolicyDefinitions(policies, ctx) {
|
|
|
147
147
|
return outcomes;
|
|
148
148
|
}
|
|
149
149
|
async function evaluatePolicyDefinition(policy, ctx) {
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
150
|
+
const authority = policy.authority ? { ...policy.authority } : void 0;
|
|
151
|
+
const outcome = policy.kind === "data" ? await evaluateDataPolicy(policy, ctx) : policy.kind === "code" ? await evaluateCodePolicy(policy, ctx) : await evaluateHybridPolicy(policy, ctx);
|
|
152
|
+
if (!authority) return outcome;
|
|
153
|
+
return {
|
|
154
|
+
...outcome,
|
|
155
|
+
dispatchEvidence: {
|
|
156
|
+
...outcome.dispatchEvidence ?? {
|
|
157
|
+
policyKind: policy.kind,
|
|
158
|
+
policyId: policy.policyId,
|
|
159
|
+
policyVersion: policy.policyVersion,
|
|
160
|
+
dispatchPath: []
|
|
161
|
+
},
|
|
162
|
+
authority
|
|
163
|
+
}
|
|
164
|
+
};
|
|
157
165
|
}
|
|
158
166
|
async function evaluateCodePolicy(policy, ctx) {
|
|
159
167
|
const codeEvaluatorPolicyId = policy.codeEvaluatorPolicyId ?? policy.policyId;
|
|
@@ -657,5 +665,5 @@ exports.evaluatePolicyDefinitions = evaluatePolicyDefinitions;
|
|
|
657
665
|
exports.evaluateRegisteredPolicies = evaluateRegisteredPolicies;
|
|
658
666
|
exports.validateDataPolicyDefinition = validateDataPolicyDefinition;
|
|
659
667
|
exports.validatePolicyGuidance = validatePolicyGuidance;
|
|
660
|
-
//# sourceMappingURL=chunk-
|
|
661
|
-
//# sourceMappingURL=chunk-
|
|
668
|
+
//# sourceMappingURL=chunk-45OKKLNY.cjs.map
|
|
669
|
+
//# sourceMappingURL=chunk-45OKKLNY.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../policies/index.ts"],"names":["result","passed"],"mappings":"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","file":"chunk-45OKKLNY.cjs","sourcesContent":["import type { ActionId, ActorType, FabricRuntimeServices } from \"../actions\";\n\nexport type PolicyEvaluationResult = \"pass\" | \"warn\" | \"block\";\n\nexport type PolicyKind = \"code\" | \"data\" | \"hybrid\";\n\nexport type PolicyId = `${string}.v${number}`;\n\nexport type PolicyEvaluationMode = \"preview\" | \"execute\";\n\nexport function assertPolicyId(policyId: string): asserts policyId is PolicyId {\n\tif (!/^[a-z][a-z0-9_-]*(\\.[a-z][a-z0-9_-]*)*\\.v[0-9]+$/.test(policyId)) {\n\t\tthrow new Error(`Invalid policy ID: ${policyId}`);\n\t}\n}\n\nexport interface PolicyContext<TDb = unknown> {\n\ttenantId: string;\n\tspaceId: string;\n\tactionInvocationId: string;\n\tactionId: string;\n\t/** Authenticated actor identity supplied by the host. Omitted only by legacy hosts and previews. */\n\tactorId?: string;\n\tactorType?: ActorType;\n\tparameters: unknown;\n\tdb: TDb;\n\tnow?: Date;\n\tmode?: PolicyEvaluationMode;\n\t/**\n\t * Optional runtime services bag, mirroring {@link FabricRuntimeServices} on\n\t * `ActionContext`. Lets the host inject dependencies (HTTP clients, secret\n\t * managers, external policy engines such as OPA, feature flags, etc.) that\n\t * a code policy evaluator may need without resorting to module-level\n\t * globals. The shape is opaque to the platform — adapters narrow it.\n\t */\n\tservices?: FabricRuntimeServices;\n\t/** Explicit code-policy catalog for this runtime; absence fails closed. */\n\tresolveCodePolicy?: (policyId: PolicyId) => PolicyEvaluator | undefined;\n}\n\nexport interface PolicyFact {\n\tname: string;\n\tvalue: unknown;\n\tlabel?: string;\n}\n\nexport type PolicyCorrectiveActionKind = \"invoke_action\" | \"navigate\" | \"manual\";\n\nexport interface PolicyCorrectiveActionBase {\n\tkind: PolicyCorrectiveActionKind;\n\tlabel: string;\n\tdescription?: string;\n\trequiresRole?: string[];\n\trequiresConfirmation?: boolean;\n}\n\nexport interface PolicyInvokeActionCorrectiveAction extends PolicyCorrectiveActionBase {\n\tkind: \"invoke_action\";\n\tactionId: ActionId;\n\tparameters?: Record<string, unknown>;\n}\n\nexport interface PolicyNavigateCorrectiveAction extends PolicyCorrectiveActionBase {\n\tkind: \"navigate\";\n\troute?: string;\n\ttarget?: {\n\t\tsurface?: string;\n\t\ttab?: string;\n\t\tfield?: string;\n\t};\n}\n\nexport interface PolicyManualCorrectiveAction extends PolicyCorrectiveActionBase {\n\tkind: \"manual\";\n}\n\nexport type PolicyCorrectiveAction =\n\t| PolicyInvokeActionCorrectiveAction\n\t| PolicyNavigateCorrectiveAction\n\t| PolicyManualCorrectiveAction;\n\nexport interface PolicyGuidance {\n\tsummary?: string;\n\tfactsUsed: PolicyFact[];\n\tcorrectiveActions: PolicyCorrectiveAction[];\n}\n\nexport interface PolicyGuidanceValidationResult {\n\tvalid: boolean;\n\terrors: string[];\n}\n\nexport function validatePolicyGuidance(guidance: unknown): PolicyGuidanceValidationResult {\n\tconst errors: string[] = [];\n\n\tif (!isPlainRecord(guidance)) {\n\t\treturn { valid: false, errors: [\"guidance must be an object\"] };\n\t}\n\n\tif (guidance.summary !== undefined && typeof guidance.summary !== \"string\") {\n\t\terrors.push(\"guidance.summary must be a string when present\");\n\t}\n\n\tif (!Array.isArray(guidance.factsUsed)) {\n\t\terrors.push(\"guidance.factsUsed must be an array\");\n\t} else {\n\t\tguidance.factsUsed.forEach((fact, index) => {\n\t\t\tif (!isPlainRecord(fact)) {\n\t\t\t\terrors.push(`guidance.factsUsed[${index}] must be an object`);\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tif (typeof fact.name !== \"string\" || fact.name.length === 0) {\n\t\t\t\terrors.push(`guidance.factsUsed[${index}].name must be a non-empty string`);\n\t\t\t}\n\t\t\tif (fact.label !== undefined && typeof fact.label !== \"string\") {\n\t\t\t\terrors.push(`guidance.factsUsed[${index}].label must be a string when present`);\n\t\t\t}\n\t\t});\n\t}\n\n\tif (!Array.isArray(guidance.correctiveActions)) {\n\t\terrors.push(\"guidance.correctiveActions must be an array\");\n\t} else {\n\t\tguidance.correctiveActions.forEach((action, index) => {\n\t\t\terrors.push(...validatePolicyCorrectiveAction(action, index));\n\t\t});\n\t}\n\n\treturn { valid: errors.length === 0, errors };\n}\n\nfunction validatePolicyCorrectiveAction(action: unknown, index: number): string[] {\n\tconst errors: string[] = [];\n\tconst prefix = `guidance.correctiveActions[${index}]`;\n\n\tif (!isPlainRecord(action)) {\n\t\treturn [`${prefix} must be an object`];\n\t}\n\n\tif (\n\t\taction.kind !== \"invoke_action\" &&\n\t\taction.kind !== \"navigate\" &&\n\t\taction.kind !== \"manual\"\n\t) {\n\t\terrors.push(`${prefix}.kind must be \"invoke_action\" | \"navigate\" | \"manual\"`);\n\t}\n\tif (typeof action.label !== \"string\" || action.label.length === 0) {\n\t\terrors.push(`${prefix}.label must be a non-empty string`);\n\t}\n\tif (action.description !== undefined && typeof action.description !== \"string\") {\n\t\terrors.push(`${prefix}.description must be a string when present`);\n\t}\n\tif (action.requiresConfirmation !== undefined && typeof action.requiresConfirmation !== \"boolean\") {\n\t\terrors.push(`${prefix}.requiresConfirmation must be a boolean when present`);\n\t}\n\tif (action.requiresRole !== undefined) {\n\t\tif (!Array.isArray(action.requiresRole)) {\n\t\t\terrors.push(`${prefix}.requiresRole must be an array when present`);\n\t\t} else if (action.requiresRole.some((role) => typeof role !== \"string\" || role.length === 0)) {\n\t\t\terrors.push(`${prefix}.requiresRole must contain only non-empty strings`);\n\t\t}\n\t}\n\n\tif (action.kind === \"invoke_action\") {\n\t\tif (typeof action.actionId !== \"string\" || action.actionId.length === 0) {\n\t\t\terrors.push(`${prefix}.actionId must be a non-empty string for invoke_action`);\n\t\t}\n\t\tif (action.parameters !== undefined && !isPlainRecord(action.parameters)) {\n\t\t\terrors.push(`${prefix}.parameters must be an object when present`);\n\t\t}\n\t}\n\n\tif (action.kind === \"navigate\") {\n\t\tif (action.route !== undefined && typeof action.route !== \"string\") {\n\t\t\terrors.push(`${prefix}.route must be a string when present`);\n\t\t}\n\t\tif (action.target !== undefined && !isPlainRecord(action.target)) {\n\t\t\terrors.push(`${prefix}.target must be an object when present`);\n\t\t}\n\t}\n\n\treturn errors;\n}\n\nfunction isPlainRecord(value: unknown): value is Record<string, unknown> {\n\treturn value !== null && typeof value === \"object\" && !Array.isArray(value);\n}\n\nexport interface PolicyOutcome {\n\tpolicyId: PolicyId;\n\tpolicyVersion: number;\n\tpolicyKind?: PolicyKind;\n\tresult: PolicyEvaluationResult;\n\treason?: string;\n\tguidance?: PolicyGuidance;\n\tmetadata?: Record<string, unknown>;\n\tdispatchEvidence?: PolicyDispatchEvidence;\n}\n\nexport interface PolicyEvaluator<TDb = unknown> {\n\tpolicyId: PolicyId;\n\tversion: number;\n\tkind?: Extract<PolicyKind, \"code\">;\n\tpreviewSafe?: boolean;\n\tevaluate: (ctx: PolicyContext<TDb>) => Promise<PolicyOutcome>;\n}\n\nexport type DataPolicySource = \"parameters\" | \"context\";\n\nexport type DataPolicyLiteral = string | number | boolean | null;\n\nexport type DataPolicyComparisonOperator =\n\t| \"exists\"\n\t| \"equals\"\n\t| \"notEquals\"\n\t| \"gt\"\n\t| \"gte\"\n\t| \"lt\"\n\t| \"lte\";\n\nexport interface DataPolicySourceReference {\n\tsource: DataPolicySource;\n\tpath: string;\n}\n\nexport type DataPolicyCondition =\n\t| {\n\t\t\tconditionId: string;\n\t\t\ttype: \"always\";\n\t\t\tresult: PolicyEvaluationResult;\n\t\t\treason?: string;\n\t\t}\n\t| {\n\t\t\tconditionId: string;\n\t\t\ttype: \"parameter\";\n\t\t\tpath: string;\n\t\t\toperator: DataPolicyComparisonOperator;\n\t\t\tvalue?: DataPolicyLiteral;\n\t\t\tonPass?: PolicyEvaluationResult;\n\t\t\tonFail?: PolicyEvaluationResult;\n\t\t\treason?: string;\n\t\t}\n\t| {\n\t\t\tconditionId: string;\n\t\t\ttype: \"comparison\";\n\t\t\tleft: DataPolicySourceReference;\n\t\t\toperator: DataPolicyComparisonOperator;\n\t\t\tvalue?: DataPolicyLiteral;\n\t\t\tonPass?: PolicyEvaluationResult;\n\t\t\tonFail?: PolicyEvaluationResult;\n\t\t\treason?: string;\n\t\t}\n\t| {\n\t\t\tconditionId: string;\n\t\t\ttype: \"all\" | \"any\";\n\t\t\tconditions: DataPolicyCondition[];\n\t\t\tonPass?: PolicyEvaluationResult;\n\t\t\tonFail?: PolicyEvaluationResult;\n\t\t\treason?: string;\n\t\t}\n\t| {\n\t\t\tconditionId: string;\n\t\t\ttype: \"not\";\n\t\t\tcondition: DataPolicyCondition;\n\t\t\tonPass?: PolicyEvaluationResult;\n\t\t\tonFail?: PolicyEvaluationResult;\n\t\t\treason?: string;\n\t\t};\n\nexport interface DataPolicyDefinition {\n\tconditions: DataPolicyCondition[];\n\tdefaultResult?: PolicyEvaluationResult;\n\treason?: string;\n}\n\nexport interface DataPolicyValidationResult {\n\tvalid: boolean;\n\terrors: string[];\n}\n\nconst DATA_POLICY_MAX_DEPTH = 5;\nconst DATA_POLICY_MAX_CONDITIONS_PER_NODE = 20;\nconst DATA_POLICY_MAX_TOTAL_CONDITIONS = 100;\nconst DATA_POLICY_MAX_PATH_SEGMENTS = 12;\nconst DATA_POLICY_MAX_STRING_LENGTH = 500;\n\nconst DATA_POLICY_CONTEXT_PATHS = Object.freeze([\n\t\"tenantId\",\n\t\"spaceId\",\n\t\"actionInvocationId\",\n\t\"actionId\",\n\t\"mode\",\n]);\n\nconst DATA_POLICY_COMPARISON_OPERATORS: readonly DataPolicyComparisonOperator[] = Object.freeze([\n\t\"exists\",\n\t\"equals\",\n\t\"notEquals\",\n\t\"gt\",\n\t\"gte\",\n\t\"lt\",\n\t\"lte\",\n]);\n\nconst POLICY_RESULTS: readonly PolicyEvaluationResult[] = Object.freeze([\"pass\", \"warn\", \"block\"]);\n\nexport interface PolicyFallbackDefinition {\n\tcodeEvaluatorPolicyId: PolicyId;\n\tonResults?: PolicyEvaluationResult[];\n\ttriggers?: PolicyFallbackTrigger[];\n\treason?: string;\n}\n\nexport type PolicyFallbackTrigger =\n\t| \"data_result\"\n\t| \"missing_data_definition\"\n\t| \"invalid_data_definition\";\n\nexport interface DataPolicyConditionResult {\n\tconditionId: string;\n\tpassed: boolean;\n\tresult: PolicyEvaluationResult;\n\treason?: string;\n}\n\n/**\n * Opaque, consumer-defined reference to the immutable policy authority or\n * snapshot a runtime policy definition was resolved from. Platform records it\n * in dispatch evidence and does not interpret it.\n */\nexport interface PolicyAuthorityReference {\n\tsnapshotId: string;\n\tcontentHash?: string;\n}\n\nexport interface RuntimePolicyDefinition {\n\tpolicyId: PolicyId;\n\tpolicyVersion: number;\n\tkind: PolicyKind;\n\t/** Snapshot/authority this definition came from; copied into dispatch evidence. */\n\tauthority?: PolicyAuthorityReference;\n\tdataDefinition?: DataPolicyDefinition;\n\tcodeEvaluatorPolicyId?: PolicyId;\n\tfallback?: PolicyFallbackDefinition;\n}\n\nexport interface PolicyDispatchEvidence {\n\tpolicyKind: PolicyKind;\n\tpolicyId?: PolicyId;\n\tpolicyVersion?: number;\n\t/** Snapshot/authority the evaluated definition was resolved from, when supplied. */\n\tauthority?: PolicyAuthorityReference;\n\tdispatchPath: Array<\"data\" | \"code\" | \"fallback\">;\n\tdata?: {\n\t\tdefinitionVersion: number;\n\t\tdefinitionStatus: \"evaluated\" | \"missing\" | \"invalid\";\n\t\tconditionResults: DataPolicyConditionResult[];\n\t\tvalidationErrors?: string[];\n\t};\n\tcode?: {\n\t\trequestedPolicyId?: PolicyId;\n\t\tpolicyId: PolicyId;\n\t\tversion?: number;\n\t\tregistered: boolean;\n\t\tskipped?: boolean;\n\t\tskipReason?: string;\n\t};\n\tfallback?: {\n\t\tused: boolean;\n\t\ttrigger: PolicyFallbackTrigger | \"not_triggered\";\n\t\treason: string;\n\t\tfromResult?: PolicyEvaluationResult;\n\t\tdefinitionVersion: number;\n\t\tcodeEvaluatorPolicyId: PolicyId;\n\t};\n\t/**\n\t * Provenance for the engine that produced this decision when a code\n\t * evaluator delegates to an external policy engine (OPA, Cedar, Cerbos,\n\t * Topaz, etc.). Fabric's `policyId` / `policyVersion` remain canonical for\n\t * audit; this block carries deployment provenance (decision path, bundle\n\t * revision, decision ID, input hash). Adapters populate it; the platform\n\t * keeps `metadata` open-ended so engine-specific typing can live in the\n\t * adapter package.\n\t */\n\tengine?: {\n\t\tname: string;\n\t\tversion?: string;\n\t\tmetadata?: Record<string, unknown>;\n\t};\n}\n\nexport interface PolicyRegistry {\n\tregister(evaluator: PolicyEvaluator): void;\n\tregisterIfMissing(evaluator: PolicyEvaluator): void;\n\tresolve(policyId: PolicyId): PolicyEvaluator | undefined;\n\tids(): PolicyId[];\n}\n\nexport function createPolicyRegistry(evaluators: readonly PolicyEvaluator[] = []): PolicyRegistry {\n\tconst policies = new Map<PolicyId, PolicyEvaluator>();\n\tconst register = (evaluator: PolicyEvaluator): void => {\n\t\tassertPolicyId(evaluator.policyId);\n\t\tconst existing = policies.get(evaluator.policyId);\n\t\tif (existing && existing !== evaluator) throw new Error(`Conflicting policy registration for \"${evaluator.policyId}\". A different evaluator is already registered.`);\n\t\tpolicies.set(evaluator.policyId, evaluator);\n\t};\n\tfor (const evaluator of evaluators) register(evaluator);\n\treturn {\n\t\tregister,\n\t\tregisterIfMissing(evaluator) {\n\t\t\tconst existing = policies.get(evaluator.policyId);\n\t\t\tif (!existing) register(evaluator);\n\t\t\telse if (existing !== evaluator) throw new Error(`Conflicting policy registration for \"${evaluator.policyId}\". A different evaluator is already registered.`);\n\t\t},\n\t\tresolve: (policyId) => policies.get(policyId),\n\t\tids: () => Array.from(policies.keys()),\n\t};\n}\n\nexport async function evaluateRegisteredPolicies(\n\tpolicyIds: PolicyId[],\n\tctx: PolicyContext,\n): Promise<PolicyOutcome[]> {\n\treturn evaluatePolicyDefinitions(\n\t\tpolicyIds.map((policyId) => ({\n\t\t\tpolicyId,\n\t\t\tpolicyVersion: parsePolicyVersion(policyId),\n\t\t\tkind: \"code\",\n\t\t\tcodeEvaluatorPolicyId: policyId,\n\t\t})),\n\t\tctx,\n\t);\n}\n\nexport async function evaluatePolicyDefinitions(\n\tpolicies: RuntimePolicyDefinition[],\n\tctx: PolicyContext,\n): Promise<PolicyOutcome[]> {\n\tconst outcomes: PolicyOutcome[] = [];\n\n\tfor (const policy of policies) {\n\t\tassertPolicyId(policy.policyId);\n\t\toutcomes.push(await evaluatePolicyDefinition(policy, ctx));\n\t}\n\n\treturn outcomes;\n}\n\nexport async function evaluatePolicyDefinition(\n\tpolicy: RuntimePolicyDefinition,\n\tctx: PolicyContext,\n): Promise<PolicyOutcome> {\n\t// Copy before awaiting so a resolver that mutates or replaces a cached\n\t// definition mid-evaluation cannot change the authority this outcome records.\n\tconst authority = policy.authority ? { ...policy.authority } : undefined;\n\tconst outcome =\n\t\tpolicy.kind === \"data\"\n\t\t\t? await evaluateDataPolicy(policy, ctx)\n\t\t\t: policy.kind === \"code\"\n\t\t\t\t? await evaluateCodePolicy(policy, ctx)\n\t\t\t\t: await evaluateHybridPolicy(policy, ctx);\n\tif (!authority) return outcome;\n\treturn {\n\t\t...outcome,\n\t\tdispatchEvidence: {\n\t\t\t...(outcome.dispatchEvidence ?? {\n\t\t\t\tpolicyKind: policy.kind,\n\t\t\t\tpolicyId: policy.policyId,\n\t\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\t\tdispatchPath: [],\n\t\t\t}),\n\t\t\tauthority,\n\t\t},\n\t};\n}\n\nasync function evaluateCodePolicy(\n\tpolicy: RuntimePolicyDefinition,\n\tctx: PolicyContext,\n): Promise<PolicyOutcome> {\n\tconst codeEvaluatorPolicyId = policy.codeEvaluatorPolicyId ?? policy.policyId;\n\tconst evaluator = ctx.resolveCodePolicy?.(codeEvaluatorPolicyId);\n\n\tif (!evaluator) {\n\t\treturn {\n\t\t\tpolicyId: policy.policyId,\n\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\tpolicyKind: policy.kind,\n\t\t\tresult: \"block\",\n\t\t\treason: `No evaluator registered for policy ${codeEvaluatorPolicyId}`,\n\t\t\tmetadata: {\n\t\t\t\tmissingCodeEvaluatorPolicyId: codeEvaluatorPolicyId,\n\t\t\t},\n\t\t\tdispatchEvidence: {\n\t\t\t\tpolicyKind: policy.kind,\n\t\t\t\tpolicyId: policy.policyId,\n\t\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\t\tdispatchPath: [\"code\"],\n\t\t\t\tcode: {\n\t\t\t\t\trequestedPolicyId: codeEvaluatorPolicyId,\n\t\t\t\t\tpolicyId: codeEvaluatorPolicyId,\n\t\t\t\t\tregistered: false,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tif (ctx.mode === \"preview\" && evaluator.previewSafe !== true) {\n\t\tconst skipReason =\n\t\t\t`Policy ${evaluator.policyId} skipped in preview mode ` +\n\t\t\t`(evaluator is not declared previewSafe)`;\n\t\treturn {\n\t\t\tpolicyId: policy.policyId,\n\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\tpolicyKind: policy.kind,\n\t\t\tresult: \"warn\",\n\t\t\treason: skipReason,\n\t\t\tmetadata: {\n\t\t\t\tcodePolicyId: evaluator.policyId,\n\t\t\t\tcodePolicyVersion: evaluator.version,\n\t\t\t\tpreviewSkipped: true,\n\t\t\t},\n\t\t\tdispatchEvidence: {\n\t\t\t\tpolicyKind: policy.kind,\n\t\t\t\tpolicyId: policy.policyId,\n\t\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\t\tdispatchPath: [\"code\"],\n\t\t\t\tcode: {\n\t\t\t\t\trequestedPolicyId: codeEvaluatorPolicyId,\n\t\t\t\t\tpolicyId: evaluator.policyId,\n\t\t\t\t\tversion: evaluator.version,\n\t\t\t\t\tregistered: true,\n\t\t\t\t\tskipped: true,\n\t\t\t\t\tskipReason,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tconst outcome = await evaluator.evaluate(ctx);\n\treturn normalizeOutcome(policy, outcome, {\n\t\tpolicyKind: policy.kind,\n\t\tpolicyId: policy.policyId,\n\t\tpolicyVersion: policy.policyVersion,\n\t\tdispatchPath: [\"code\"],\n\t\tcode: {\n\t\t\trequestedPolicyId: codeEvaluatorPolicyId,\n\t\t\tpolicyId: evaluator.policyId,\n\t\t\tversion: evaluator.version,\n\t\t\tregistered: true,\n\t\t},\n\t});\n}\n\nasync function evaluateHybridPolicy(\n\tpolicy: RuntimePolicyDefinition,\n\tctx: PolicyContext,\n): Promise<PolicyOutcome> {\n\tconst dataOutcome = evaluateDataPolicy(policy, ctx);\n\tconst fallback = policy.fallback;\n\tconst fallbackDecision = fallback\n\t\t? resolveFallbackDecision(policy, dataOutcome, fallback)\n\t\t: { shouldFallback: false, trigger: \"not_triggered\" as const };\n\n\tif (!fallback || !fallbackDecision.shouldFallback) {\n\t\tif (fallback && dataOutcome.dispatchEvidence) {\n\t\t\treturn {\n\t\t\t\t...dataOutcome,\n\t\t\t\tdispatchEvidence: {\n\t\t\t\t\t...dataOutcome.dispatchEvidence,\n\t\t\t\t\tfallback: {\n\t\t\t\t\t\tused: false,\n\t\t\t\t\t\ttrigger: \"not_triggered\",\n\t\t\t\t\t\treason: \"Data policy result did not trigger fallback\",\n\t\t\t\t\t\tfromResult: dataOutcome.result,\n\t\t\t\t\t\tdefinitionVersion: policy.policyVersion,\n\t\t\t\t\t\tcodeEvaluatorPolicyId: fallback.codeEvaluatorPolicyId,\n\t\t\t\t\t},\n\t\t\t\t},\n\t\t\t};\n\t\t}\n\n\t\treturn dataOutcome;\n\t}\n\n\tconst codePolicy: RuntimePolicyDefinition = {\n\t\tpolicyId: policy.policyId,\n\t\tpolicyVersion: policy.policyVersion,\n\t\tkind: \"hybrid\",\n\t\tcodeEvaluatorPolicyId: fallback.codeEvaluatorPolicyId,\n\t};\n\tconst codeOutcome = await evaluateCodePolicy(codePolicy, ctx);\n\n\treturn normalizeOutcome(policy, codeOutcome, {\n\t\t...(codeOutcome.dispatchEvidence ?? {\n\t\t\tpolicyKind: \"hybrid\",\n\t\t\tpolicyId: policy.policyId,\n\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\tdispatchPath: [\"code\"],\n\t\t}),\n\t\tpolicyKind: \"hybrid\",\n\t\tpolicyId: policy.policyId,\n\t\tpolicyVersion: policy.policyVersion,\n\t\tdispatchPath: [\"data\", \"fallback\", \"code\"],\n\t\tdata: dataOutcome.dispatchEvidence?.data,\n\t\tfallback: {\n\t\t\tused: true,\n\t\t\ttrigger: fallbackDecision.trigger,\n\t\t\treason: fallback.reason ?? \"Data policy result triggered code fallback\",\n\t\t\tfromResult: dataOutcome.result,\n\t\t\tdefinitionVersion: policy.policyVersion,\n\t\t\tcodeEvaluatorPolicyId: fallback.codeEvaluatorPolicyId,\n\t\t},\n\t});\n}\n\nfunction resolveFallbackDecision(\n\tpolicy: RuntimePolicyDefinition,\n\tdataOutcome: PolicyOutcome,\n\tfallback: PolicyFallbackDefinition,\n): { shouldFallback: boolean; trigger: PolicyFallbackTrigger | \"not_triggered\" } {\n\tconst allowedTriggers = fallback.triggers ?? [\n\t\t\"data_result\",\n\t\t\"missing_data_definition\",\n\t\t\"invalid_data_definition\",\n\t];\n\tconst definitionStatus = dataOutcome.dispatchEvidence?.data?.definitionStatus;\n\n\tif (definitionStatus === \"missing\") {\n\t\treturn {\n\t\t\tshouldFallback: allowedTriggers.includes(\"missing_data_definition\"),\n\t\t\ttrigger: \"missing_data_definition\",\n\t\t};\n\t}\n\n\tif (definitionStatus === \"invalid\") {\n\t\treturn {\n\t\t\tshouldFallback: allowedTriggers.includes(\"invalid_data_definition\"),\n\t\t\ttrigger: \"invalid_data_definition\",\n\t\t};\n\t}\n\n\tconst fallbackResults = fallback.onResults ?? [\"warn\", \"block\"];\n\treturn {\n\t\tshouldFallback:\n\t\t\tpolicy.kind === \"hybrid\" &&\n\t\t\tallowedTriggers.includes(\"data_result\") &&\n\t\t\tfallbackResults.includes(dataOutcome.result),\n\t\ttrigger: \"data_result\",\n\t};\n}\n\nfunction evaluateDataPolicy(policy: RuntimePolicyDefinition, ctx: PolicyContext): PolicyOutcome {\n\tconst definition = policy.dataDefinition;\n\n\tif (!definition) {\n\t\treturn {\n\t\t\tpolicyId: policy.policyId,\n\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\tpolicyKind: policy.kind,\n\t\t\tresult: \"block\",\n\t\t\treason: \"Data policy definition is missing\",\n\t\t\tdispatchEvidence: {\n\t\t\t\tpolicyKind: policy.kind,\n\t\t\t\tpolicyId: policy.policyId,\n\t\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\t\tdispatchPath: [\"data\"],\n\t\t\t\tdata: {\n\t\t\t\t\tdefinitionVersion: policy.policyVersion,\n\t\t\t\t\tdefinitionStatus: \"missing\",\n\t\t\t\t\tconditionResults: [],\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tconst validation = validateDataPolicyDefinition(definition);\n\tif (!validation.valid) {\n\t\treturn {\n\t\t\tpolicyId: policy.policyId,\n\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\tpolicyKind: policy.kind,\n\t\t\tresult: \"block\",\n\t\t\treason: `Invalid data policy definition: ${validation.errors.join(\"; \")}`,\n\t\t\tmetadata: {\n\t\t\t\tvalidationErrors: validation.errors,\n\t\t\t},\n\t\t\tdispatchEvidence: {\n\t\t\t\tpolicyKind: policy.kind,\n\t\t\t\tpolicyId: policy.policyId,\n\t\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\t\tdispatchPath: [\"data\"],\n\t\t\t\tdata: {\n\t\t\t\t\tdefinitionVersion: policy.policyVersion,\n\t\t\t\t\tdefinitionStatus: \"invalid\",\n\t\t\t\t\tconditionResults: [],\n\t\t\t\t\tvalidationErrors: validation.errors,\n\t\t\t\t},\n\t\t\t},\n\t\t};\n\t}\n\n\tconst evaluations = definition.conditions.map((condition) => evaluateDataPolicyCondition(condition, ctx));\n\tconst conditionResults = evaluations.flatMap((evaluation) => evaluation.evidence);\n\tconst topLevelResults = evaluations.map((evaluation) => evaluation.result);\n\tconst aggregate =\n\t\ttopLevelResults.find((result) => result.result === \"block\") ??\n\t\ttopLevelResults.find((result) => result.result === \"warn\");\n\tconst result = aggregate?.result ?? definition.defaultResult ?? \"pass\";\n\n\treturn {\n\t\tpolicyId: policy.policyId,\n\t\tpolicyVersion: policy.policyVersion,\n\t\tpolicyKind: policy.kind,\n\t\tresult,\n\t\treason: aggregate?.reason ?? definition.reason,\n\t\tmetadata: {\n\t\t\tconditionCount: definition.conditions.length,\n\t\t\tfailedConditionId: aggregate?.conditionId,\n\t\t},\n\t\tdispatchEvidence: {\n\t\t\tpolicyKind: policy.kind,\n\t\t\tpolicyId: policy.policyId,\n\t\t\tpolicyVersion: policy.policyVersion,\n\t\t\tdispatchPath: [\"data\"],\n\t\t\tdata: {\n\t\t\t\tdefinitionVersion: policy.policyVersion,\n\t\t\t\tdefinitionStatus: \"evaluated\",\n\t\t\t\tconditionResults,\n\t\t\t},\n\t\t},\n\t};\n}\n\nexport function validateDataPolicyDefinition(\n\tdefinition: DataPolicyDefinition,\n): DataPolicyValidationResult {\n\tconst errors: string[] = [];\n\n\tif (!Array.isArray(definition.conditions) || definition.conditions.length === 0) {\n\t\terrors.push(\"conditions must contain at least one condition\");\n\t} else if (definition.conditions.length > DATA_POLICY_MAX_CONDITIONS_PER_NODE) {\n\t\terrors.push(\n\t\t\t`conditions must contain at most ${DATA_POLICY_MAX_CONDITIONS_PER_NODE} top-level conditions`,\n\t\t);\n\t}\n\n\tif (definition.defaultResult && !POLICY_RESULTS.includes(definition.defaultResult)) {\n\t\terrors.push(\"defaultResult must be pass, warn, or block\");\n\t}\n\n\tlet totalConditions = 0;\n\tfor (const condition of definition.conditions ?? []) {\n\t\tvalidateDataPolicyCondition(condition, errors, 1, () => {\n\t\t\ttotalConditions += 1;\n\t\t});\n\t}\n\n\tif (totalConditions > DATA_POLICY_MAX_TOTAL_CONDITIONS) {\n\t\terrors.push(`policy must contain at most ${DATA_POLICY_MAX_TOTAL_CONDITIONS} total conditions`);\n\t}\n\n\treturn { valid: errors.length === 0, errors };\n}\n\nfunction validateDataPolicyCondition(\n\tcondition: DataPolicyCondition,\n\terrors: string[],\n\tdepth: number,\n\tcount: () => void,\n): void {\n\tcount();\n\n\tif (!condition || typeof condition !== \"object\") {\n\t\terrors.push(\"condition must be an object\");\n\t\treturn;\n\t}\n\n\tif (depth > DATA_POLICY_MAX_DEPTH) {\n\t\terrors.push(`condition depth must not exceed ${DATA_POLICY_MAX_DEPTH}`);\n\t\treturn;\n\t}\n\n\tif (!isNonEmptyBoundedString(condition.conditionId)) {\n\t\terrors.push(\"conditionId must be a non-empty bounded string\");\n\t}\n\n\tvalidateOptionalPolicyResult(\"onPass\" in condition ? condition.onPass : undefined, \"onPass\", errors);\n\tvalidateOptionalPolicyResult(\"onFail\" in condition ? condition.onFail : undefined, \"onFail\", errors);\n\n\tif (condition.reason !== undefined && !isNonEmptyBoundedString(condition.reason)) {\n\t\terrors.push(`condition ${condition.conditionId} reason must be a bounded string`);\n\t}\n\n\tif (condition.type === \"always\") {\n\t\tif (!POLICY_RESULTS.includes(condition.result)) {\n\t\t\terrors.push(`condition ${condition.conditionId} result must be pass, warn, or block`);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (condition.type === \"parameter\") {\n\t\tvalidatePath(condition.path, `condition ${condition.conditionId} path`, errors);\n\t\tvalidateComparison(condition.operator, condition.value, condition.conditionId, errors);\n\t\treturn;\n\t}\n\n\tif (condition.type === \"comparison\") {\n\t\tvalidateSourceReference(condition.left, condition.conditionId, errors);\n\t\tvalidateComparison(condition.operator, condition.value, condition.conditionId, errors);\n\t\treturn;\n\t}\n\n\tif (condition.type === \"all\" || condition.type === \"any\") {\n\t\tif (!Array.isArray(condition.conditions) || condition.conditions.length === 0) {\n\t\t\terrors.push(`condition ${condition.conditionId} must contain child conditions`);\n\t\t\treturn;\n\t\t}\n\n\t\tif (condition.conditions.length > DATA_POLICY_MAX_CONDITIONS_PER_NODE) {\n\t\t\terrors.push(\n\t\t\t\t`condition ${condition.conditionId} must contain at most ${DATA_POLICY_MAX_CONDITIONS_PER_NODE} child conditions`,\n\t\t\t);\n\t\t}\n\n\t\tfor (const child of condition.conditions) {\n\t\t\tvalidateDataPolicyCondition(child, errors, depth + 1, count);\n\t\t}\n\t\treturn;\n\t}\n\n\tif (condition.type === \"not\") {\n\t\tvalidateDataPolicyCondition(condition.condition, errors, depth + 1, count);\n\t\treturn;\n\t}\n\n\terrors.push(`condition ${condition.conditionId} has unsupported type`);\n}\n\nfunction validateOptionalPolicyResult(\n\tresult: PolicyEvaluationResult | undefined,\n\tfieldName: string,\n\terrors: string[],\n): void {\n\tif (result !== undefined && !POLICY_RESULTS.includes(result)) {\n\t\terrors.push(`${fieldName} must be pass, warn, or block`);\n\t}\n}\n\nfunction validateSourceReference(\n\treference: DataPolicySourceReference,\n\tconditionId: string,\n\terrors: string[],\n): void {\n\tif (!reference || typeof reference !== \"object\") {\n\t\terrors.push(`condition ${conditionId} left must be a source reference`);\n\t\treturn;\n\t}\n\n\tif (reference.source !== \"parameters\" && reference.source !== \"context\") {\n\t\terrors.push(`condition ${conditionId} source must be parameters or context`);\n\t}\n\n\tvalidatePath(reference.path, `condition ${conditionId} left.path`, errors);\n\n\tif (reference.source === \"context\" && !DATA_POLICY_CONTEXT_PATHS.includes(reference.path)) {\n\t\terrors.push(`condition ${conditionId} uses an unsupported context path`);\n\t}\n}\n\nfunction validateComparison(\n\toperator: DataPolicyComparisonOperator,\n\tvalue: DataPolicyLiteral | undefined,\n\tconditionId: string,\n\terrors: string[],\n): void {\n\tif (!DATA_POLICY_COMPARISON_OPERATORS.includes(operator)) {\n\t\terrors.push(`condition ${conditionId} has unsupported operator`);\n\t\treturn;\n\t}\n\n\tif (operator === \"exists\") {\n\t\treturn;\n\t}\n\n\tif (!isDataPolicyLiteral(value)) {\n\t\terrors.push(`condition ${conditionId} comparison value must be a bounded literal`);\n\t\treturn;\n\t}\n\n\tif ([\"gt\", \"gte\", \"lt\", \"lte\"].includes(operator) && typeof value !== \"number\") {\n\t\terrors.push(`condition ${conditionId} numeric comparison requires a number value`);\n\t}\n}\n\nfunction validatePath(path: string, fieldName: string, errors: string[]): void {\n\tif (!isNonEmptyBoundedString(path)) {\n\t\terrors.push(`${fieldName} must be a non-empty bounded string`);\n\t\treturn;\n\t}\n\n\tconst segments = path.split(\".\");\n\tif (segments.length > DATA_POLICY_MAX_PATH_SEGMENTS) {\n\t\terrors.push(`${fieldName} must contain at most ${DATA_POLICY_MAX_PATH_SEGMENTS} segments`);\n\t\treturn;\n\t}\n\n\tfor (const segment of segments) {\n\t\tif (!/^[A-Za-z][A-Za-z0-9_-]*$/.test(segment)) {\n\t\t\terrors.push(`${fieldName} contains an invalid path segment`);\n\t\t\treturn;\n\t\t}\n\n\t\tif ([\"__proto__\", \"constructor\", \"prototype\"].includes(segment)) {\n\t\t\terrors.push(`${fieldName} contains a forbidden path segment`);\n\t\t\treturn;\n\t\t}\n\t}\n}\n\nfunction isDataPolicyLiteral(value: unknown): value is DataPolicyLiteral {\n\tif (value === null || typeof value === \"number\" || typeof value === \"boolean\") {\n\t\treturn true;\n\t}\n\n\treturn typeof value === \"string\" && value.length <= DATA_POLICY_MAX_STRING_LENGTH;\n}\n\nfunction isNonEmptyBoundedString(value: unknown): value is string {\n\treturn typeof value === \"string\" && value.length > 0 && value.length <= DATA_POLICY_MAX_STRING_LENGTH;\n}\n\nfunction evaluateDataPolicyCondition(\n\tcondition: DataPolicyCondition,\n\tctx: PolicyContext,\n): { result: DataPolicyConditionResult; evidence: DataPolicyConditionResult[] } {\n\tif (condition.type === \"always\") {\n\t\tconst result = {\n\t\t\tconditionId: condition.conditionId,\n\t\t\tpassed: condition.result === \"pass\",\n\t\t\tresult: condition.result,\n\t\t\treason: condition.reason,\n\t\t};\n\t\treturn { result, evidence: [result] };\n\t}\n\n\tif (condition.type === \"all\" || condition.type === \"any\") {\n\t\tconst childEvaluations = condition.conditions.map((child) => evaluateDataPolicyCondition(child, ctx));\n\t\tconst passed =\n\t\t\tcondition.type === \"all\"\n\t\t\t\t? childEvaluations.every((evaluation) => evaluation.result.passed)\n\t\t\t\t: childEvaluations.some((evaluation) => evaluation.result.passed);\n\t\tconst result = {\n\t\t\tconditionId: condition.conditionId,\n\t\t\tpassed,\n\t\t\tresult: passed ? (condition.onPass ?? \"pass\") : (condition.onFail ?? \"block\"),\n\t\t\treason: passed ? undefined : condition.reason,\n\t\t};\n\n\t\treturn {\n\t\t\tresult,\n\t\t\tevidence: [result, ...childEvaluations.flatMap((evaluation) => evaluation.evidence)],\n\t\t};\n\t}\n\n\tif (condition.type === \"not\") {\n\t\tconst childEvaluation = evaluateDataPolicyCondition(condition.condition, ctx);\n\t\tconst passed = !childEvaluation.result.passed;\n\t\tconst result = {\n\t\t\tconditionId: condition.conditionId,\n\t\t\tpassed,\n\t\t\tresult: passed ? (condition.onPass ?? \"pass\") : (condition.onFail ?? \"block\"),\n\t\t\treason: passed ? undefined : condition.reason,\n\t\t};\n\n\t\treturn { result, evidence: [result, ...childEvaluation.evidence] };\n\t}\n\n\tif (condition.type !== \"parameter\" && condition.type !== \"comparison\") {\n\t\tconst result: DataPolicyConditionResult = {\n\t\t\tconditionId: condition.conditionId,\n\t\t\tpassed: false,\n\t\t\tresult: \"block\",\n\t\t\treason: \"Unsupported data policy condition type\",\n\t\t};\n\t\treturn { result, evidence: [result] };\n\t}\n\n\tconst value =\n\t\tcondition.type === \"parameter\"\n\t\t\t? readPath(ctx.parameters, condition.path)\n\t\t\t: readDataPolicySource(ctx, condition.left);\n\tconst operator = condition.operator;\n\tconst expected = condition.value;\n\tconst passed = evaluateOperator(value, operator, expected);\n\tconst result = {\n\t\tconditionId: condition.conditionId,\n\t\tpassed,\n\t\tresult: passed ? (condition.onPass ?? \"pass\") : (condition.onFail ?? \"block\"),\n\t\treason: passed ? undefined : condition.reason,\n\t};\n\treturn { result, evidence: [result] };\n}\n\nfunction evaluateOperator(\n\tactual: unknown,\n\toperator: DataPolicyComparisonOperator,\n\texpected: unknown,\n): boolean {\n\tswitch (operator) {\n\t\tcase \"exists\":\n\t\t\treturn actual !== undefined && actual !== null && actual !== \"\";\n\t\tcase \"equals\":\n\t\t\treturn actual === expected;\n\t\tcase \"notEquals\":\n\t\t\treturn actual !== expected;\n\t\tcase \"gt\":\n\t\t\treturn typeof actual === \"number\" && typeof expected === \"number\" && actual > expected;\n\t\tcase \"gte\":\n\t\t\treturn typeof actual === \"number\" && typeof expected === \"number\" && actual >= expected;\n\t\tcase \"lt\":\n\t\t\treturn typeof actual === \"number\" && typeof expected === \"number\" && actual < expected;\n\t\tcase \"lte\":\n\t\t\treturn typeof actual === \"number\" && typeof expected === \"number\" && actual <= expected;\n\t}\n}\n\nfunction readDataPolicySource(ctx: PolicyContext, reference: DataPolicySourceReference): unknown {\n\tif (reference.source === \"parameters\") {\n\t\treturn readPath(ctx.parameters, reference.path);\n\t}\n\n\treturn readPath(\n\t\t{\n\t\t\ttenantId: ctx.tenantId,\n\t\t\tspaceId: ctx.spaceId,\n\t\t\tactionInvocationId: ctx.actionInvocationId,\n\t\t\tactionId: ctx.actionId,\n\t\t\tmode: ctx.mode,\n\t\t},\n\t\treference.path,\n\t);\n}\n\nfunction readPath(source: unknown, path: string): unknown {\n\tif (!source || typeof source !== \"object\") {\n\t\treturn undefined;\n\t}\n\n\treturn path.split(\".\").reduce<unknown>((current, segment) => {\n\t\tif (!current || typeof current !== \"object\") {\n\t\t\treturn undefined;\n\t\t}\n\n\t\treturn (current as Record<string, unknown>)[segment];\n\t}, source);\n}\n\nfunction normalizeOutcome(\n\tpolicy: RuntimePolicyDefinition,\n\toutcome: PolicyOutcome,\n\tdispatchEvidence: PolicyDispatchEvidence,\n): PolicyOutcome {\n\tif (outcome.guidance !== undefined) {\n\t\tconst guidanceValidation = validatePolicyGuidance(outcome.guidance);\n\t\tif (!guidanceValidation.valid) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid guidance for policy ${outcome.policyId}: ${guidanceValidation.errors.join(\"; \")}`,\n\t\t\t);\n\t\t}\n\t}\n\n\t// The platform owns the dispatch envelope (kind, id, version, path,\n\t// data/code/fallback blocks). Engine provenance is evaluator-controlled —\n\t// preserve it so BYO-engine adapters (OPA, Cedar, ...) can attach decision\n\t// path, bundle revision, decision ID, input hash, etc.\n\tconst engine = outcome.dispatchEvidence?.engine;\n\treturn {\n\t\t...outcome,\n\t\tpolicyId: policy.policyId,\n\t\tpolicyVersion: policy.policyVersion,\n\t\tpolicyKind: policy.kind,\n\t\tmetadata: {\n\t\t\t...(outcome.metadata ?? {}),\n\t\t\tcodePolicyId: dispatchEvidence.code?.policyId ?? outcome.policyId,\n\t\t\tcodePolicyVersion: dispatchEvidence.code?.version ?? outcome.policyVersion,\n\t\t},\n\t\tdispatchEvidence: engine ? { ...dispatchEvidence, engine } : dispatchEvidence,\n\t};\n}\n\nfunction parsePolicyVersion(policyId: PolicyId): number {\n\tconst segments = policyId.split(\".v\");\n\treturn Number(segments[segments.length - 1] ?? 1);\n}\n\nexport function aggregatePolicyOutcomes(outcomes: PolicyOutcome[]): PolicyOutcome | undefined {\n\treturn (\n\t\toutcomes.find((outcome) => outcome.result === \"block\") ??\n\t\toutcomes.find((outcome) => outcome.result === \"warn\")\n\t);\n}\n"]}
|