@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
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"names":[],"mappings":"","file":"index.js"}
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../adapters/circuit-breaker.ts","../../adapters/index.ts"],"sourcesContent":["import type {\n\tAdapterCircuitBreakerConfig,\n\tAdapterCircuitBreakerManualOverride,\n\tAdapterImplementation,\n\tAdapterOutcomeKind,\n} from \"./index\";\n\n/**\n * State of an adapter circuit breaker.\n *\n * - `closed`: calls flow and outcomes are counted.\n * - `open`: the dependency is presumed unhealthy. In `enforce` mode calls are\n * rejected without being attempted until `cooldownMs` has elapsed.\n * - `half_open`: the cooldown elapsed. One probe call is admitted; its outcome\n * closes the breaker (success) or reopens it (failure).\n */\nexport type AdapterCircuitState = \"closed\" | \"open\" | \"half_open\";\n\n/**\n * How a single adapter outcome counts toward the breaker.\n *\n * - `success`: the dependency answered and the call succeeded.\n * - `failure`: evidence the dependency is unhealthy.\n * - `ignored`: the dependency answered but rejected the request on its merits\n * (a validation or business rejection). It is neither a success nor a\n * dependency failure and does not enter the rolling window.\n */\nexport type AdapterCircuitOutcome = \"success\" | \"failure\" | \"ignored\";\n\n/**\n * Map an {@link AdapterOutcomeKind} to how it counts toward a circuit breaker.\n *\n * | Outcome kind | Counts as |\n * |---------------------|-----------|\n * | `success` | `success` |\n * | `transient_failure` | `failure` |\n * | `timeout` | `failure` |\n * | `ambiguous` | `failure` |\n * | `permanent_failure` | `ignored` |\n *\n * `ambiguous` counts as a failure: the dependency did not give a definite\n * answer, which is a health signal even though the Host routes the invocation\n * to reconciliation. `permanent_failure` (validation or rejection) is the\n * dependency working correctly and saying no, so it does not trip the breaker.\n * `executeWithAdapterRetry` classifies a thrown error with the caller's\n * `classifyThrownError` (default `transient_failure`) and maps that kind here,\n * so an unclassified thrown error counts as a failure.\n */\nexport function classifyCircuitBreakerOutcome(kind: AdapterOutcomeKind): AdapterCircuitOutcome {\n\tswitch (kind) {\n\t\tcase \"success\":\n\t\t\treturn \"success\";\n\t\tcase \"permanent_failure\":\n\t\t\treturn \"ignored\";\n\t\tcase \"transient_failure\":\n\t\tcase \"timeout\":\n\t\tcase \"ambiguous\":\n\t\t\treturn \"failure\";\n\t\tdefault:\n\t\t\t// An unknown kind is treated as a dependency failure (fail closed).\n\t\t\treturn \"failure\";\n\t}\n}\n\n/** The answer a breaker gives before a call. */\nexport interface AdapterCircuitAdmission {\n\t/**\n\t * Whether the call may proceed. Always `true` in `monitor` mode; `false`\n\t * only in `enforce` mode while the breaker is open, forced open, or\n\t * half-open with its probe already in flight.\n\t */\n\tallowed: boolean;\n\t/** State at the time of the decision. */\n\tstate: AdapterCircuitState;\n\t/** True when this admission is the half-open probe. Pass it back to `record`. */\n\tprobe: boolean;\n\t/** Monitor mode only: true when `enforce` mode would have rejected this call. */\n\twouldReject?: boolean;\n\t/**\n\t * Milliseconds until the breaker will admit a probe, when known. Absent while\n\t * a manual `force_open` override is set or a half-open probe is in flight.\n\t */\n\tretryAfterMs?: number;\n\t/** Set when a manual override decided the admission. */\n\tmanualOverride?: AdapterCircuitBreakerManualOverride;\n\t/**\n\t * The breaker epoch the admission was granted in; opaque to callers.\n\t * {@link InMemoryAdapterCircuitBreaker} lets an outcome change state only\n\t * when this still matches its current epoch. An admission without it is\n\t * treated as current.\n\t */\n\tgeneration?: number;\n}\n\n/**\n * Contract between a circuit breaker and `executeWithAdapterRetry`.\n * Implement it to plug in a shared or distributed breaker.\n */\nexport interface AdapterCircuitBreaker {\n\t/** Registry key this breaker guards; defaults to `adapterType:operation`. */\n\treadonly key: string;\n\treadonly mode: \"monitor\" | \"enforce\";\n\t/** Current state, applying any elapsed cooldown or manual override. */\n\tgetState(): AdapterCircuitState;\n\t/**\n\t * Preview whether a call would be admitted now. Side-effect free: it does\n\t * not commit an elapsed cooldown, take the half-open probe or emit\n\t * telemetry.\n\t */\n\tcheck(): AdapterCircuitAdmission;\n\t/**\n\t * Decide whether a call may start now. Call it immediately before the\n\t * external effect and pass the returned admission to {@link record}.\n\t */\n\tacquire(): AdapterCircuitAdmission;\n\t/**\n\t * Record the outcome of a call that was admitted by {@link acquire}. Pass\n\t * that admission, not a {@link check} preview, so the breaker can tell a\n\t * stale outcome from a current one.\n\t */\n\trecord(outcome: AdapterCircuitOutcome, admission?: AdapterCircuitAdmission): void;\n}\n\nexport type AdapterCircuitBreakerEventReason =\n\t| \"failure_threshold\"\n\t| \"cooldown_elapsed\"\n\t| \"probe_succeeded\"\n\t| \"probe_failed\"\n\t| \"manual_override\"\n\t| \"manual_override_cleared\";\n\ninterface AdapterCircuitBreakerEventBase {\n\tkey: string;\n\tmode: \"monitor\" | \"enforce\";\n\t/** Epoch milliseconds from the breaker's clock. */\n\tat: number;\n}\n\n/** Telemetry reported by {@link InMemoryAdapterCircuitBreaker}. */\nexport type AdapterCircuitBreakerEvent =\n\t| (AdapterCircuitBreakerEventBase & {\n\t\t\ttype: \"state_change\";\n\t\t\tfrom: AdapterCircuitState;\n\t\t\tto: AdapterCircuitState;\n\t\t\treason: AdapterCircuitBreakerEventReason;\n\t\t\tmanualOverride?: AdapterCircuitBreakerManualOverride;\n\t })\n\t| (AdapterCircuitBreakerEventBase & {\n\t\t\t/** Enforce mode refused a call; it was not attempted. */\n\t\t\ttype: \"rejected\";\n\t\t\tstate: AdapterCircuitState;\n\t\t\tretryAfterMs?: number;\n\t\t\tmanualOverride?: AdapterCircuitBreakerManualOverride;\n\t })\n\t| (AdapterCircuitBreakerEventBase & {\n\t\t\t/** Monitor mode let a call through that enforce mode would have refused. */\n\t\t\ttype: \"would_reject\";\n\t\t\tstate: AdapterCircuitState;\n\t\t\tretryAfterMs?: number;\n\t\t\tmanualOverride?: AdapterCircuitBreakerManualOverride;\n\t });\n\n/**\n * Telemetry callback. Errors it throws and promises it rejects are caught\n * and discarded so telemetry cannot change an adapter call's outcome.\n *\n * {@link InMemoryAdapterCircuitBreaker} calls it only after the operation that\n * produced the event has committed, never part-way through a decision or a\n * record. A callback may call back into the breaker; it sees committed state,\n * and events its own calls produce are delivered after it returns, in order.\n */\nexport type AdapterCircuitBreakerEventListener = (\n\tevent: AdapterCircuitBreakerEvent,\n) => void | Promise<void>;\n\nexport interface InMemoryAdapterCircuitBreakerOptions {\n\t/** Usually `adapterType:operation`. */\n\tkey: string;\n\tconfig: AdapterCircuitBreakerConfig;\n\t/** Epoch-millisecond clock. Defaults to `Date.now`. */\n\tnow?: () => number;\n\tonEvent?: AdapterCircuitBreakerEventListener;\n}\n\nconst MANUAL_OVERRIDES: readonly AdapterCircuitBreakerManualOverride[] = [\"force_open\", \"force_closed\"];\n\n/**\n * Validate a circuit-breaker config. Throws a `RangeError` naming the first\n * invalid field: `mode` must be `monitor` or `enforce`; `failureThreshold` and\n * `minimumSamples` positive integers; `windowMs` and `probeLeaseMs` positive\n * finite numbers; `cooldownMs` a non-negative finite number; `manualOverride`\n * `force_open` or `force_closed` when present.\n */\nexport function assertAdapterCircuitBreakerConfig(config: AdapterCircuitBreakerConfig): void {\n\tif (!config || typeof config !== \"object\") {\n\t\tthrow new RangeError(\"Adapter circuit breaker config must be an object.\");\n\t}\n\tif (config.mode !== \"monitor\" && config.mode !== \"enforce\") {\n\t\tthrow new RangeError(`Adapter circuit breaker mode must be \"monitor\" or \"enforce\"; got ${JSON.stringify(config.mode)}.`);\n\t}\n\tif (!Number.isInteger(config.failureThreshold) || config.failureThreshold < 1) {\n\t\tthrow new RangeError(`Adapter circuit breaker failureThreshold must be a positive integer; got ${String(config.failureThreshold)}.`);\n\t}\n\tif (typeof config.windowMs !== \"number\" || !Number.isFinite(config.windowMs) || config.windowMs <= 0) {\n\t\tthrow new RangeError(`Adapter circuit breaker windowMs must be a positive number of milliseconds; got ${String(config.windowMs)}.`);\n\t}\n\tif (typeof config.cooldownMs !== \"number\" || !Number.isFinite(config.cooldownMs) || config.cooldownMs < 0) {\n\t\tthrow new RangeError(`Adapter circuit breaker cooldownMs must be a non-negative number of milliseconds; got ${String(config.cooldownMs)}.`);\n\t}\n\tif (\n\t\tconfig.minimumSamples !== undefined &&\n\t\t(!Number.isInteger(config.minimumSamples) || config.minimumSamples < 1)\n\t) {\n\t\tthrow new RangeError(`Adapter circuit breaker minimumSamples must be a positive integer; got ${String(config.minimumSamples)}.`);\n\t}\n\tif (\n\t\tconfig.probeLeaseMs !== undefined &&\n\t\t(typeof config.probeLeaseMs !== \"number\" || !Number.isFinite(config.probeLeaseMs) || config.probeLeaseMs <= 0)\n\t) {\n\t\tthrow new RangeError(`Adapter circuit breaker probeLeaseMs must be a positive number of milliseconds; got ${String(config.probeLeaseMs)}.`);\n\t}\n\tif (config.manualOverride !== undefined && !MANUAL_OVERRIDES.includes(config.manualOverride)) {\n\t\tthrow new RangeError(`Adapter circuit breaker manualOverride must be \"force_open\" or \"force_closed\"; got ${JSON.stringify(config.manualOverride)}.`);\n\t}\n}\n\ninterface Sample {\n\tat: number;\n\tfailure: boolean;\n}\n\n/**\n * Dependency-free, in-process circuit breaker for one adapter operation.\n *\n * State lives in this instance only: it is not shared between processes,\n * hosts, or replicas, and it is lost on restart. Each replica trips on the\n * failures it observes itself.\n *\n * Tripping rule (parity with the .NET `InMemoryAdapterCircuitBreaker`): after\n * a failure is recorded while `closed`, let `N` be the outcomes recorded within\n * the last `windowMs` and `M = minimumSamples ?? failureThreshold`. The breaker\n * opens when `N >= M` and either\n * 1. the most recent `failureThreshold` outcomes in the window are all\n * failures, or\n * 2. the failure ratio in the window is at least `failureThreshold / M`.\n *\n * With `minimumSamples` omitted this reads \"`failureThreshold` consecutive\n * failures\". With `minimumSamples: 20, failureThreshold: 10` it also opens at\n * a 50% failure rate over at least 20 calls.\n *\n * After `cooldownMs` the breaker turns `half_open` and admits one probe. A\n * probe success closes it and clears the window; a probe failure reopens it\n * and restarts the cooldown. At most one probe is outstanding at a time: it\n * holds a lease of `probeLeaseMs` (default `max(cooldownMs, windowMs)`, never\n * derived from the cooldown alone, so `cooldownMs: 0` still admits one probe).\n * A probe that has not recorded when its lease expires is considered lost and\n * the next call becomes the probe.\n *\n * Epochs: the breaker keeps a generation counter that advances on every state\n * change (including one committed by an elapsed cooldown), every manual\n * override change, and every probe grant. Each admission carries the\n * generation it was granted in. `record` first commits any elapsed cooldown,\n * then compares generations. An outcome from an earlier epoch is stale: it is\n * dropped entirely. It changes no state, does not resolve or free the probe\n * slot, and is not added to the rolling window, so it cannot contribute to a\n * later trip either. Because a probe grant starts a new epoch, the outstanding\n * probe is the only `probe: true` admission of the current epoch, which is how\n * a replaced probe's late outcome is told apart. An outcome recorded without an\n * admission, or with one that has no `generation`, is treated as current: it is\n * sampled, can trip a closed breaker and resolves an outstanding probe.\n *\n * Telemetry is buffered and delivered after each operation commits. An\n * elapsed cooldown is committed, and its `cooldown_elapsed` event delivered,\n * as a step of its own before `acquire`, `record`, `getState` or\n * `setManualOverride` continues, so a callback reacting to it (for example by\n * forcing the breaker open) governs the call that observed it. Every other\n * event is delivered once the method's decision or record is final, and a\n * callback never revokes an admission that is already committed. Two cases\n * follow from that: a breaker call made from inside a callback queues its own\n * `cooldown_elapsed` behind the current delivery and decides first; and with\n * `cooldownMs: 0`, a cooldown that falls due again during the decision (because\n * a callback reopened the breaker) is committed and admitted before its event\n * is delivered.\n *\n * `monitor` mode runs the same state machine and reports the same telemetry\n * but admits every call; calls enforce mode would have refused are reported\n * as `would_reject`.\n *\n * A manual override pins the reported state (`force_open` → `open`,\n * `force_closed` → `closed`) and suspends automatic transitions while set;\n * outcomes of calls admitted under the override are still recorded. Like an\n * automatic open, `force_open` blocks only in `enforce` mode. Clearing the\n * override returns the breaker to `closed` with its window intact.\n */\nexport class InMemoryAdapterCircuitBreaker implements AdapterCircuitBreaker {\n\treadonly key: string;\n\treadonly mode: \"monitor\" | \"enforce\";\n\tprivate readonly config: AdapterCircuitBreakerConfig;\n\tprivate readonly now: () => number;\n\tprivate readonly onEvent: AdapterCircuitBreakerEventListener | undefined;\n\tprivate readonly probeLeaseMs: number;\n\tprivate samples: Sample[] = [];\n\tprivate state: AdapterCircuitState = \"closed\";\n\tprivate openedAt = 0;\n\tprivate probeIssuedAt: number | undefined;\n\t/** Advances on every state change, manual override change and probe grant. */\n\tprivate generation = 0;\n\tprivate manualOverride: AdapterCircuitBreakerManualOverride | undefined;\n\t/** Telemetry waiting for the current operation to commit. */\n\tprivate readonly outbox: AdapterCircuitBreakerEvent[] = [];\n\tprivate operationDepth = 0;\n\tprivate flushing = false;\n\n\tconstructor(options: InMemoryAdapterCircuitBreakerOptions) {\n\t\tassertAdapterCircuitBreakerConfig(options.config);\n\t\tthis.key = options.key;\n\t\tthis.config = { ...options.config };\n\t\tthis.mode = options.config.mode;\n\t\tthis.now = options.now ?? Date.now;\n\t\tthis.onEvent = options.onEvent;\n\t\tthis.manualOverride = options.config.manualOverride;\n\t\tthis.probeLeaseMs = options.config.probeLeaseMs ?? Math.max(options.config.cooldownMs, options.config.windowMs);\n\t}\n\n\tgetState(): AdapterCircuitState {\n\t\tthis.settle(this.now());\n\t\treturn this.reportedState();\n\t}\n\n\tgetManualOverride(): AdapterCircuitBreakerManualOverride | undefined {\n\t\treturn this.manualOverride;\n\t}\n\n\t/**\n\t * Set (`force_open` / `force_closed`) or clear (`undefined`) the manual\n\t * override. Clearing returns the breaker to `closed` with its window intact.\n\t */\n\tsetManualOverride(override: AdapterCircuitBreakerManualOverride | undefined): void {\n\t\tif (override !== undefined && !MANUAL_OVERRIDES.includes(override)) {\n\t\t\tthrow new RangeError(`Adapter circuit breaker manualOverride must be \"force_open\" or \"force_closed\"; got ${JSON.stringify(override)}.`);\n\t\t}\n\t\tconst now = this.now();\n\t\tthis.settle(now);\n\t\t// Compared after settle: a telemetry callback may have set this override.\n\t\tif (override === this.manualOverride) return;\n\t\tthis.operation(() => {\n\t\t\tconst from = this.reportedState();\n\t\t\tthis.manualOverride = override;\n\t\t\tthis.generation++;\n\t\t\tif (override === undefined) {\n\t\t\t\tthis.state = \"closed\";\n\t\t\t\tthis.releaseProbe();\n\t\t\t}\n\t\t\tthis.emit({\n\t\t\t\ttype: \"state_change\",\n\t\t\t\tkey: this.key,\n\t\t\t\tmode: this.mode,\n\t\t\t\tat: now,\n\t\t\t\tfrom,\n\t\t\t\tto: this.reportedState(),\n\t\t\t\treason: override === undefined ? \"manual_override_cleared\" : \"manual_override\",\n\t\t\t\t...(override ? { manualOverride: override } : {}),\n\t\t\t});\n\t\t});\n\t}\n\n\tcheck(): AdapterCircuitAdmission {\n\t\treturn this.decide(false, this.now());\n\t}\n\n\tacquire(): AdapterCircuitAdmission {\n\t\tconst now = this.now();\n\t\tthis.settle(now);\n\t\treturn this.operation(() => this.decide(true, now));\n\t}\n\n\trecord(outcome: AdapterCircuitOutcome, admission?: AdapterCircuitAdmission): void {\n\t\tconst now = this.now();\n\t\t// Commit an elapsed cooldown first, so an outcome admitted while open\n\t\t// is judged against the half_open epoch it would otherwise influence.\n\t\tthis.settle(now);\n\t\tthis.operation(() => this.applyOutcome(outcome, admission, now));\n\t}\n\n\tprivate applyOutcome(outcome: AdapterCircuitOutcome, admission: AdapterCircuitAdmission | undefined, now: number): void {\n\t\tconst generation = admission?.generation;\n\t\t// Stale: admitted in an earlier epoch. No transition, no probe release, no sample.\n\t\tif (generation !== undefined && generation !== this.generation) return;\n\t\t// In the current epoch the only probe admission is the outstanding probe.\n\t\tconst resolvesProbe =\n\t\t\tthis.state === \"half_open\" &&\n\t\t\tthis.probeIssuedAt !== undefined &&\n\t\t\t(generation === undefined || admission?.probe === true);\n\t\tif (outcome === \"ignored\") {\n\t\t\t// The dependency answered; the probe proved nothing either way.\n\t\t\tif (resolvesProbe) this.releaseProbe();\n\t\t\treturn;\n\t\t}\n\t\tthis.prune(now);\n\t\tthis.samples.push({ at: now, failure: outcome === \"failure\" });\n\t\tif (this.manualOverride) return;\n\t\tif (resolvesProbe) {\n\t\t\tthis.releaseProbe();\n\t\t\tif (outcome === \"success\") {\n\t\t\t\tthis.samples = [];\n\t\t\t\tthis.transition(\"closed\", \"probe_succeeded\", now);\n\t\t\t} else {\n\t\t\t\tthis.openedAt = now;\n\t\t\t\tthis.transition(\"open\", \"probe_failed\", now);\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\t\tif (this.state === \"closed\" && outcome === \"failure\" && this.shouldTrip()) {\n\t\t\tthis.openedAt = now;\n\t\t\tthis.transition(\"open\", \"failure_threshold\", now);\n\t\t}\n\t}\n\n\t/**\n\t * `take` is false for {@link check}: a pure preview that sees an elapsed\n\t * cooldown without committing it, takes no probe and emits nothing.\n\t */\n\tprivate decide(take: boolean, now: number): AdapterCircuitAdmission {\n\t\tif (this.manualOverride === \"force_closed\") {\n\t\t\treturn { allowed: true, state: \"closed\", probe: false, manualOverride: \"force_closed\", generation: this.generation };\n\t\t}\n\t\tif (this.manualOverride === \"force_open\") {\n\t\t\treturn this.refuse(take, { state: \"open\", manualOverride: \"force_open\" });\n\t\t}\n\t\t// An elapsed cooldown releases any probe, so a pending open → half_open\n\t\t// transition always has its probe free.\n\t\tconst cooldownElapsed = this.state === \"open\" && now - this.openedAt >= this.config.cooldownMs;\n\t\t// Normally a no-op: acquire() settled first. A listener run by that\n\t\t// settle can reopen the breaker (with cooldownMs 0 it is due at once);\n\t\t// that cooldown is committed here and reported after the decision.\n\t\tif (take) this.advance(now);\n\t\tconst state: AdapterCircuitState = !take && cooldownElapsed ? \"half_open\" : this.state;\n\t\tif (state === \"closed\") return { allowed: true, state: \"closed\", probe: false, generation: this.generation };\n\t\tif (state === \"open\") {\n\t\t\treturn this.refuse(take, {\n\t\t\t\tstate: \"open\",\n\t\t\t\tretryAfterMs: Math.max(0, this.openedAt + this.config.cooldownMs - now),\n\t\t\t});\n\t\t}\n\t\t// half_open: one probe at a time, until it records or its lease expires.\n\t\tconst probeFree =\n\t\t\t(!take && cooldownElapsed) ||\n\t\t\tthis.probeIssuedAt === undefined ||\n\t\t\tnow - this.probeIssuedAt >= this.probeLeaseMs;\n\t\tif (!probeFree) return this.refuse(take, { state: \"half_open\" });\n\t\tif (!take) return { allowed: true, state: \"half_open\", probe: true, generation: this.generation };\n\t\t// Granting the probe starts a new epoch, so a replaced probe's token goes stale.\n\t\tthis.probeIssuedAt = now;\n\t\tthis.generation++;\n\t\treturn { allowed: true, state: \"half_open\", probe: true, generation: this.generation };\n\t}\n\n\tprivate refuse(\n\t\ttake: boolean,\n\t\tdetail: { state: AdapterCircuitState; retryAfterMs?: number; manualOverride?: AdapterCircuitBreakerManualOverride },\n\t): AdapterCircuitAdmission {\n\t\tconst enforce = this.mode === \"enforce\";\n\t\tif (take) {\n\t\t\tthis.emit({\n\t\t\t\ttype: enforce ? \"rejected\" : \"would_reject\",\n\t\t\t\tkey: this.key,\n\t\t\t\tmode: this.mode,\n\t\t\t\tat: this.now(),\n\t\t\t\t...detail,\n\t\t\t});\n\t\t}\n\t\tconst generation = this.generation;\n\t\treturn enforce\n\t\t\t? { allowed: false, probe: false, ...detail, generation }\n\t\t\t: { allowed: true, probe: false, wouldReject: true, ...detail, generation };\n\t}\n\n\tprivate releaseProbe(): void {\n\t\tthis.probeIssuedAt = undefined;\n\t}\n\n\t/** Apply the time-based open → half_open transition. */\n\tprivate advance(now: number): void {\n\t\tif (this.state === \"open\" && now - this.openedAt >= this.config.cooldownMs) {\n\t\t\tthis.releaseProbe();\n\t\t\tthis.transition(\"half_open\", \"cooldown_elapsed\", now);\n\t\t}\n\t}\n\n\tprivate shouldTrip(): boolean {\n\t\tconst minimumSamples = this.config.minimumSamples ?? this.config.failureThreshold;\n\t\tconst total = this.samples.length;\n\t\tif (total < minimumSamples) return false;\n\t\tlet consecutive = 0;\n\t\tfor (let index = total - 1; index >= 0 && this.samples[index]!.failure; index--) consecutive++;\n\t\tif (consecutive >= this.config.failureThreshold) return true;\n\t\tconst failures = this.samples.reduce((count, sample) => count + (sample.failure ? 1 : 0), 0);\n\t\treturn failures / total >= this.config.failureThreshold / minimumSamples;\n\t}\n\n\tprivate prune(now: number): void {\n\t\tconst cutoff = now - this.config.windowMs;\n\t\tlet drop = 0;\n\t\twhile (drop < this.samples.length && this.samples[drop]!.at < cutoff) drop++;\n\t\tif (drop > 0) this.samples.splice(0, drop);\n\t}\n\n\tprivate transition(to: AdapterCircuitState, reason: AdapterCircuitBreakerEventReason, at: number): void {\n\t\tconst from = this.state;\n\t\tif (from === to) return;\n\t\tthis.state = to;\n\t\tthis.generation++;\n\t\tthis.emit({ type: \"state_change\", key: this.key, mode: this.mode, at, from, to, reason });\n\t}\n\n\tprivate reportedState(): AdapterCircuitState {\n\t\tif (this.manualOverride) return this.manualOverride === \"force_open\" ? \"open\" : \"closed\";\n\t\treturn this.state;\n\t}\n\n\t/**\n\t * Commit an elapsed cooldown as an operation of its own, delivering its\n\t * event before the caller's operation reads state.\n\t */\n\tprivate settle(now: number): void {\n\t\tif (this.manualOverride) return;\n\t\tthis.operation(() => this.advance(now));\n\t}\n\n\t/**\n\t * Run `step` to completion, then deliver the telemetry it produced. The\n\t * return value is fixed before any listener runs.\n\t */\n\tprivate operation<T>(step: () => T): T {\n\t\tthis.operationDepth++;\n\t\ttry {\n\t\t\treturn step();\n\t\t} finally {\n\t\t\tthis.operationDepth--;\n\t\t\tif (this.operationDepth === 0) this.flush();\n\t\t}\n\t}\n\n\tprivate emit(event: AdapterCircuitBreakerEvent): void {\n\t\tif (this.onEvent) this.outbox.push(event);\n\t}\n\n\t/**\n\t * Deliver buffered events in order. A listener that calls back into the\n\t * breaker queues its own events; this loop delivers them after it returns\n\t * instead of recursing.\n\t */\n\tprivate flush(): void {\n\t\tif (this.flushing) return;\n\t\tthis.flushing = true;\n\t\ttry {\n\t\t\tfor (let event = this.outbox.shift(); event; event = this.outbox.shift()) this.deliver(event);\n\t\t} finally {\n\t\t\tthis.flushing = false;\n\t\t}\n\t}\n\n\tprivate deliver(event: AdapterCircuitBreakerEvent): void {\n\t\tconst listener = this.onEvent;\n\t\tif (!listener) return;\n\t\ttry {\n\t\t\tconst result = listener(event);\n\t\t\tif (result && typeof (result as PromiseLike<void>).then === \"function\") {\n\t\t\t\t(result as PromiseLike<void>).then(undefined, () => undefined);\n\t\t\t}\n\t\t} catch {\n\t\t\t// Telemetry must never change an adapter call's outcome.\n\t\t}\n\t}\n}\n\n/** Trusted invocation context available when selecting an adapter breaker. */\nexport interface AdapterCircuitBreakerScope {\n\ttenantId: string;\n\tspaceId?: string;\n}\n\n/**\n * Key by tenant, optional space, vendor, and adapter operation. Components are\n * URI-encoded to distinguish embedded delimiters; ordinary adapter identifiers\n * remain readable as the trailing `adapterType:operation`.\n *\n * Missing scope uses a separate `unscoped` namespace (still split by vendor)\n * rather than rejecting the call. Calls without scope share that\n * namespace; callers must supply scope for tenant isolation. Missing space or\n * vendor is distinct from an empty string. `vendor` is required by the public\n * adapter type, but its absence is tolerated for JavaScript callers.\n * Keys appear in errors and telemetry: use non-secret identifiers.\n */\nexport function scopedAdapterCircuitBreakerKey(\n\tadapter: AdapterImplementation,\n\tscope: AdapterCircuitBreakerScope | undefined,\n): string {\n\treturn [\n\t\tscope === undefined ? \"unscoped\" : `tenant=${encodeURIComponent(scope.tenantId)}`,\n\t\tscope?.spaceId === undefined ? \"space\" : `space=${encodeURIComponent(scope.spaceId)}`,\n\t\tadapter.vendor === undefined ? \"vendor\" : `vendor=${encodeURIComponent(adapter.vendor)}`,\n\t\tencodeURIComponent(adapter.adapterType),\n\t\tencodeURIComponent(adapter.operation),\n\t].join(\":\");\n}\n\n/** Supplies the breaker, if any, that guards an adapter in invocation scope. */\nexport interface AdapterCircuitBreakerProvider {\n\tforAdapter(adapter: AdapterImplementation, scope?: AdapterCircuitBreakerScope): AdapterCircuitBreaker | undefined;\n}\n\nexport interface AdapterCircuitBreakerRegistryOptions {\n\t/**\n\t * Defaults to `adapterType:operation`, shared across tenants and vendors in\n\t * this registry. Use {@link scopedAdapterCircuitBreakerKey} for tenant,\n\t * space, and vendor isolation. The first config seen for a key wins;\n\t * later conflicting configs reuse that breaker without throwing. Breakers\n\t * are never evicted, and scoped keys are high-cardinality: avoid them as\n\t * metric labels.\n\t */\n\tkey?: (adapter: AdapterImplementation, scope: AdapterCircuitBreakerScope | undefined) => string;\n\t/** Epoch-millisecond clock handed to every breaker. Defaults to `Date.now`. */\n\tnow?: () => number;\n\tonEvent?: AdapterCircuitBreakerEventListener;\n}\n\n/**\n * Lazily creates one {@link InMemoryAdapterCircuitBreaker} per\n * key, from that adapter's own `circuitBreaker` config. The default key is\n * `adapterType:operation`, shared across tenants and vendors; override it with\n * {@link AdapterCircuitBreakerRegistryOptions.key} to isolate invocation scopes.\n * Adapters without a config get no breaker. The first config seen for a key\n * wins; later conflicting configs reuse the existing breaker without throwing.\n * Share a key only between adapters intended to use the same configuration.\n */\nexport class AdapterCircuitBreakerRegistry implements AdapterCircuitBreakerProvider {\n\tprivate readonly breakers = new Map<string, InMemoryAdapterCircuitBreaker>();\n\n\tconstructor(private readonly options: AdapterCircuitBreakerRegistryOptions = {}) {}\n\n\tforAdapter(adapter: AdapterImplementation, scope?: AdapterCircuitBreakerScope): InMemoryAdapterCircuitBreaker | undefined {\n\t\tif (!adapter.circuitBreaker) return undefined;\n\t\tconst key = this.options.key?.(adapter, scope) ?? `${adapter.adapterType}:${adapter.operation}`;\n\t\tlet breaker = this.breakers.get(key);\n\t\tif (!breaker) {\n\t\t\tbreaker = new InMemoryAdapterCircuitBreaker({\n\t\t\t\tkey,\n\t\t\t\tconfig: adapter.circuitBreaker,\n\t\t\t\t...(this.options.now ? { now: this.options.now } : {}),\n\t\t\t\t...(this.options.onEvent ? { onEvent: this.options.onEvent } : {}),\n\t\t\t});\n\t\t\tthis.breakers.set(key, breaker);\n\t\t}\n\t\treturn breaker;\n\t}\n\n\t/** Looks up the default `adapterType:operation` key without creating a breaker. */\n\tget(adapterType: string, operation: string): InMemoryAdapterCircuitBreaker | undefined {\n\t\treturn this.getByKey(`${adapterType}:${operation}`);\n\t}\n\n\t/** Looks up an exact key, including a custom key, without creating a breaker. */\n\tgetByKey(key: string): InMemoryAdapterCircuitBreaker | undefined {\n\t\treturn this.breakers.get(key);\n\t}\n}\n\n/**\n * Thrown by `executeWithAdapterRetry` when an `enforce`-mode breaker refuses\n * an attempt. The refused attempt never reached `execute`, so no external\n * effect happened for it.\n */\nexport class AdapterCircuitOpenError extends Error {\n\toverride readonly name = \"AdapterCircuitOpenError\";\n\treadonly code = \"ADAPTER_CIRCUIT_OPEN\" as const;\n\treadonly reason = \"circuit_open\" as const;\n\treadonly adapterKey: string;\n\treadonly state: AdapterCircuitState;\n\t/** The attempt number that was refused (1 = refused before any call). */\n\treadonly attempt: number;\n\treadonly retryAfterMs?: number;\n\treadonly manualOverride?: AdapterCircuitBreakerManualOverride;\n\t/** Error of the previous attempt, when the breaker opened mid-retry. */\n\treadonly lastError?: string;\n\n\tconstructor(input: {\n\t\tadapterKey: string;\n\t\tstate: AdapterCircuitState;\n\t\tattempt: number;\n\t\tretryAfterMs?: number;\n\t\tmanualOverride?: AdapterCircuitBreakerManualOverride;\n\t\tlastError?: string;\n\t}) {\n\t\tconst after = input.retryAfterMs !== undefined ? `; retry after ${input.retryAfterMs} ms` : \"\";\n\t\tsuper(`Adapter circuit is ${input.state === \"half_open\" ? \"half-open with its probe in flight\" : \"open\"} for ${input.adapterKey}; the call was not attempted${after}.`);\n\t\tthis.adapterKey = input.adapterKey;\n\t\tthis.state = input.state;\n\t\tthis.attempt = input.attempt;\n\t\tif (input.retryAfterMs !== undefined) this.retryAfterMs = input.retryAfterMs;\n\t\tif (input.manualOverride !== undefined) this.manualOverride = input.manualOverride;\n\t\tif (input.lastError !== undefined) this.lastError = input.lastError;\n\t}\n}\n\n/**\n * Recognise an {@link AdapterCircuitOpenError}, including one constructed by a\n * second copy of this package (for example an ESM and a CommonJS build loaded\n * side by side), where `instanceof` fails.\n */\nexport function isAdapterCircuitOpenError(error: unknown): error is AdapterCircuitOpenError {\n\tif (error instanceof AdapterCircuitOpenError) return true;\n\treturn (\n\t\ttypeof error === \"object\" &&\n\t\terror !== null &&\n\t\t(error as { name?: unknown }).name === \"AdapterCircuitOpenError\" &&\n\t\t(error as { code?: unknown }).code === \"ADAPTER_CIRCUIT_OPEN\"\n\t);\n}\n","import {\n\tAdapterCircuitOpenError,\n\tclassifyCircuitBreakerOutcome,\n\ttype AdapterCircuitAdmission,\n\ttype AdapterCircuitBreaker,\n\ttype AdapterCircuitOutcome,\n} from \"./circuit-breaker\";\n\nexport * from \"./circuit-breaker\";\n\nexport interface AdapterExecutionContext {\n\ttenantId: string;\n\tspaceId: string;\n\tactionInvocationId: string;\n\tadapterInvocationId: string;\n\tcorrelationId: string;\n\tcausationId?: string;\n\tattempt: number;\n\tmaxAttempts: number;\n\t/** Epoch-millis deadline after which the adapter should abandon the call. */\n\tdeadlineMs?: number;\n\t/** Set by the host when the invocation has been cancelled; adapters should stop work. */\n\tcancelled?: boolean;\n\t/** Non-secret reason the invocation was cancelled. */\n\tcancellationReason?: string;\n\t/**\n\t * AbortSignal the host aborts when the deadline expires or the invocation is\n\t * cancelled. Adapters should propagate this to underlying HTTP/database\n\t * clients so in-flight work is abandoned rather than left dangling.\n\t */\n\tsignal?: AbortSignal;\n}\n\n/**\n * Additive classification of an adapter outcome so the retry layer can\n * distinguish retryable transient failures from permanent rejections,\n * timeouts, and ambiguous results that require manual reconciliation.\n *\n * When `outcome` is absent on an {@link AdapterExecutionResult}, the retry\n * layer treats a non-success result as `transient_failure` for backward\n * compatibility.\n */\nexport type AdapterOutcomeKind =\n\t| \"success\"\n\t| \"transient_failure\"\n\t| \"permanent_failure\"\n\t| \"timeout\"\n\t| \"ambiguous\";\n\n/**\n * Durable, non-secret evidence attached to a classified adapter outcome.\n * Used by the host to record reconciliation evidence when an adapter returns\n * an ambiguous result whose external effect may or may not have been applied.\n */\nexport interface AdapterOutcomeEvidence {\n\tkind: AdapterOutcomeKind;\n\treason?: string;\n\t/** Opaque, non-secret reference to external operation state for reconciliation. */\n\texternalReference?: string;\n\t/** Whether the external effect may have been applied (true for ambiguous/timeout). */\n\teffectMayHaveApplied?: boolean;\n\tobservedAt: Date | string;\n}\n\n/**\n * An adapter handed the work to an external system that will finish it later.\n *\n * Explicit rather than inferred from evidence: a successful adapter call that\n * merely records a reference is not the same as one that has left the outcome\n * in someone else's hands. The host keeps the invocation running and expects a\n * completion carrying this reference through its completion ingress.\n */\nexport interface AcceptedExternalOperation {\n\t/** Opaque, non-secret reference the external system will complete by. */\n\texternalReference: string;\n\t/** When the external system said it expects to finish, if it said. */\n\texpectedBy?: Date | string;\n}\n\nexport interface AdapterExecutionResult {\n\tsuccess: boolean;\n\tcorrelationId?: string;\n\terror?: string;\n\t/** Additive outcome classification. Omitted = infer from `success`. */\n\toutcome?: AdapterOutcomeKind;\n\t/** Durable evidence for ambiguous or timeout outcomes requiring reconciliation. */\n\toutcomeEvidence?: AdapterOutcomeEvidence;\n\t/** Present when a successful call handed the work off to finish elsewhere. */\n\tacceptedExternalOperation?: AcceptedExternalOperation;\n}\n\nexport type AdapterExecutor = (\n\tinput: Record<string, unknown>,\n\tcontext: AdapterExecutionContext,\n) => Promise<AdapterExecutionResult>;\n\nexport interface AdapterRetryPolicy {\n\t/** External calls must explicitly opt into retry by being idempotent. */\n\tidempotent: boolean;\n\t/** Total attempts including the first call. Non-idempotent policies are forced to 1. */\n\tmaxAttempts?: number;\n\t/** First backoff delay in milliseconds. */\n\tinitialDelayMs?: number;\n\t/** Exponential multiplier applied after each failed attempt. */\n\tbackoffMultiplier?: number;\n\t/** Upper bound for any single retry delay in milliseconds. */\n\tmaxDelayMs?: number;\n}\n\nexport interface ResolvedAdapterRetryPolicy {\n\tidempotent: boolean;\n\tmaxAttempts: number;\n\tinitialDelayMs: number;\n\tbackoffMultiplier: number;\n\tmaxDelayMs: number;\n}\n\n/** Manual circuit-breaker override: pin the breaker open or closed. */\nexport type AdapterCircuitBreakerManualOverride = \"force_open\" | \"force_closed\";\n\n/**\n * Per-adapter circuit-breaker configuration, read by\n * {@link AdapterCircuitBreakerRegistry} (and so by Platform Host) to create one\n * in-process {@link InMemoryAdapterCircuitBreaker} per registry key (default\n * `adapterType:operation`; configurable through the registry `key` option).\n * Validated by {@link assertAdapterCircuitBreakerConfig}.\n */\nexport interface AdapterCircuitBreakerConfig {\n\t/**\n\t * `monitor` records outcomes, runs the state machine and reports what it\n\t * would have refused, but never blocks a call. `enforce` refuses calls\n\t * while the breaker is open, without attempting them.\n\t */\n\tmode: \"monitor\" | \"enforce\";\n\t/**\n\t * A failure count. Let `M = minimumSamples ?? failureThreshold`. Once at\n\t * least `M` outcomes fall within `windowMs`, the breaker opens when the most\n\t * recent `failureThreshold` of them are all failures, or when the failure\n\t * ratio in the window reaches `failureThreshold / M`. Without\n\t * `minimumSamples` this is \"`failureThreshold` consecutive failures\".\n\t * Matches the .NET port's `InMemoryAdapterCircuitBreaker`. Positive integer.\n\t */\n\tfailureThreshold: number;\n\t/** Rolling window, in milliseconds, of outcomes the thresholds consider. */\n\twindowMs: number;\n\t/** Milliseconds an open breaker waits before admitting one half-open probe. */\n\tcooldownMs: number;\n\t/** Outcomes required in the window before the breaker can open. Defaults to `failureThreshold`. */\n\tminimumSamples?: number;\n\t/**\n\t * How long, in milliseconds, the single half-open probe holds its slot\n\t * before it is presumed lost and another call may probe. Defaults to\n\t * `max(cooldownMs, windowMs)`; it is independent of `cooldownMs`, so a zero\n\t * or short cooldown never admits concurrent probes. Positive.\n\t */\n\tprobeLeaseMs?: number;\n\t/**\n\t * Optional initial manual override. `force_open` reports `open` (and blocks\n\t * only in `enforce` mode); `force_closed` reports `closed` and never blocks.\n\t * Change it at runtime with `InMemoryAdapterCircuitBreaker.setManualOverride`.\n\t */\n\tmanualOverride?: AdapterCircuitBreakerManualOverride;\n}\n\nexport interface AdapterImplementation {\n\tadapterType: string;\n\toperation: string;\n\tvendor: string;\n\t/** Whether this adapter operation can be safely retried by default. */\n\tidempotent: boolean;\n\tretryPolicy?: AdapterRetryPolicy;\n\t/** Defaults to monitor-only; enforce mode must be explicitly configured. */\n\tcircuitBreaker?: AdapterCircuitBreakerConfig;\n\texecute: AdapterExecutor;\n}\n\nexport interface AdapterAttempt<T> {\n\tattempt: number;\n\tresult?: T;\n\terror?: string;\n\twillRetry: boolean;\n\tnextDelayMs?: number;\n}\n\nexport interface ExecuteWithRetryOptions<T> {\n\tpolicy?: AdapterRetryPolicy;\n\tdefaultIdempotent: boolean;\n\texecute: (attempt: number, maxAttempts: number) => Promise<T>;\n\tisSuccessful: (result: T) => boolean;\n\tgetError: (result: T) => string | undefined;\n\t/**\n\t * Optional outcome classifier. When provided, the retry layer retries only\n\t * `transient_failure` outcomes (and only when the policy is idempotent).\n\t * `permanent_failure`, `timeout`, and `ambiguous` outcomes are never retried.\n\t * When omitted, all non-success results are treated as transient (backward compatible).\n\t */\n\tclassifyOutcome?: (result: T) => AdapterOutcomeKind;\n\t/**\n\t * Optional classifier for errors thrown by the execute callback (not returned\n\t * as results). When provided, the retry layer retries only `transient_failure`\n\t * classifications. When omitted, thrown errors are never retried — the caller\n\t * must explicitly opt into retrying a thrown failure by classifying it.\n\t */\n\tclassifyThrownError?: (error: unknown) => AdapterOutcomeKind;\n\tsleep?: (delayMs: number) => Promise<void>;\n\tonAttempt?: (attempt: AdapterAttempt<T>) => Promise<void> | void;\n\t/**\n\t * Optional per-attempt preparation, awaited before the circuit breaker is\n\t * consulted and before `execute` (for example, persisting the attempt\n\t * number). Put every await a caller needs before the call here, so that\n\t * nothing awaits between breaker admission and the external call. If it\n\t * throws, no admission is taken and no breaker outcome is recorded; the\n\t * error is classified with `classifyThrownError` and retried or rethrown\n\t * exactly like an error thrown by `execute`.\n\t */\n\tprepareAttempt?: (attempt: number, maxAttempts: number) => Promise<void> | void;\n\t/**\n\t * Optional circuit breaker. When present, `acquire()` is called\n\t * immediately before every `execute` call, with no await in between, and every attempt's outcome is\n\t * recorded through {@link classifyCircuitBreakerOutcome}. In `enforce` mode\n\t * a refused attempt is not executed and {@link AdapterCircuitOpenError} is\n\t * thrown; if the breaker opens between attempts, retrying stops and the\n\t * same error is thrown. When omitted, behaviour is unchanged.\n\t */\n\tcircuitBreaker?: AdapterCircuitBreaker;\n}\n\nfunction adapterKey(adapterType: string, operation: string): string {\n\treturn `${adapterType}:${operation}`;\n}\n\nexport class MissingAdapterRegistrationError extends Error {\n\tconstructor(adapterType: string, operation: string) {\n\t\tsuper(`No adapter registered for adapterType \"${adapterType}\" and operation \"${operation}\"`);\n\t\tthis.name = \"MissingAdapterRegistrationError\";\n\t}\n}\n\nexport class AdapterRegistry {\n\tprivate readonly adapters = new Map<string, AdapterImplementation>();\n\n\tregister(adapter: AdapterImplementation): void {\n\t\tconst key = adapterKey(adapter.adapterType, adapter.operation);\n\t\tif (this.adapters.has(key)) {\n\t\t\tthrow new Error(\n\t\t\t\t`Adapter already registered for adapterType \"${adapter.adapterType}\" and operation \"${adapter.operation}\"`,\n\t\t\t);\n\t\t}\n\n\t\tthis.adapters.set(key, adapter);\n\t}\n\n\tresolve(adapterType: string, operation: string): AdapterImplementation | undefined {\n\t\treturn this.adapters.get(adapterKey(adapterType, operation));\n\t}\n\n\trequire(adapterType: string, operation: string): AdapterImplementation {\n\t\tconst adapter = this.resolve(adapterType, operation);\n\t\tif (!adapter) {\n\t\t\tthrow new MissingAdapterRegistrationError(adapterType, operation);\n\t\t}\n\n\t\treturn adapter;\n\t}\n}\n\nconst DEFAULT_RETRY_POLICY: ResolvedAdapterRetryPolicy = {\n\tidempotent: true,\n\tmaxAttempts: 3,\n\tinitialDelayMs: 100,\n\tbackoffMultiplier: 2,\n\tmaxDelayMs: 1_000,\n};\n\nconst NO_RETRY_POLICY: ResolvedAdapterRetryPolicy = {\n\tidempotent: false,\n\tmaxAttempts: 1,\n\tinitialDelayMs: 0,\n\tbackoffMultiplier: 1,\n\tmaxDelayMs: 0,\n};\n\nexport function resolveAdapterRetryPolicy(\n\tpolicy: AdapterRetryPolicy | undefined,\n\tdefaultIdempotent: boolean,\n): ResolvedAdapterRetryPolicy {\n\tconst idempotent = policy?.idempotent ?? defaultIdempotent;\n\n\tif (!idempotent) {\n\t\treturn NO_RETRY_POLICY;\n\t}\n\n\treturn {\n\t\tidempotent: true,\n\t\tmaxAttempts: Math.max(1, Math.min(policy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts, 5)),\n\t\tinitialDelayMs: Math.max(0, policy?.initialDelayMs ?? DEFAULT_RETRY_POLICY.initialDelayMs),\n\t\tbackoffMultiplier: Math.max(\n\t\t\t1,\n\t\t\tpolicy?.backoffMultiplier ?? DEFAULT_RETRY_POLICY.backoffMultiplier,\n\t\t),\n\t\tmaxDelayMs: Math.max(0, policy?.maxDelayMs ?? DEFAULT_RETRY_POLICY.maxDelayMs),\n\t};\n}\n\nexport function getRetryDelayMs(attempt: number, policy: ResolvedAdapterRetryPolicy): number {\n\tconst exponentialDelay =\n\t\tpolicy.initialDelayMs * policy.backoffMultiplier ** Math.max(0, attempt - 1);\n\n\treturn Math.min(exponentialDelay, policy.maxDelayMs);\n}\n\n/**\n * Classify an {@link AdapterExecutionResult} into an {@link AdapterOutcomeKind}.\n * When `outcome` is explicitly set, it is returned directly, after rejecting a\n * contradictory result where `success` is true but the outcome is non-success.\n * Otherwise a successful result maps to `success` and a failed result maps to\n * `transient_failure` (the historical default).\n */\nexport function classifyAdapterOutcome(result: AdapterExecutionResult): AdapterOutcomeKind {\n\tif (result.outcome) {\n\t\tassertAdapterOutcomeConsistency(result);\n\t\treturn result.outcome;\n\t}\n\treturn result.success ? \"success\" : \"transient_failure\";\n}\n\n/**\n * Determine whether an outcome kind is retryable. Only `transient_failure`\n * is retryable, and only when the adapter policy is idempotent. Permanent\n * failures, timeouts, and ambiguous outcomes are never retried.\n */\nexport function shouldRetryAdapterOutcome(\n\tkind: AdapterOutcomeKind,\n\tidempotent: boolean,\n): boolean {\n\treturn kind === \"transient_failure\" && idempotent;\n}\n\n/**\n * Reject a contradictory adapter result where `success` is true but the\n * explicit `outcome` is a non-success kind. A successful result claiming an\n * ambiguous, permanent, timeout, or transient outcome is a programming\n * error — the adapter cannot have both succeeded and require reconciliation.\n */\nexport function assertAdapterOutcomeConsistency(result: AdapterExecutionResult): void {\n\tif (result.success && result.outcome && result.outcome !== \"success\") {\n\t\tthrow new Error(\n\t\t\t`Adapter returned success=true with contradictory outcome \"${result.outcome}\"; a successful result must not declare a non-success outcome.`,\n\t\t);\n\t}\n}\n\n/**\n * Record an outcome on the breaker. A breaker that throws must not turn a\n * call that already ran (and may have had its external effect) into a failure.\n */\nfunction recordCircuitOutcome(\n\tbreaker: AdapterCircuitBreaker | undefined,\n\toutcome: AdapterCircuitOutcome,\n\tadmission: AdapterCircuitAdmission | undefined,\n): void {\n\tif (!breaker) return;\n\ttry {\n\t\tbreaker.record(outcome, admission);\n\t} catch {\n\t\t// Breaker bookkeeping is best effort once the call has happened.\n\t}\n}\n\nfunction circuitOpenError(\n\tbreaker: AdapterCircuitBreaker,\n\tadmission: AdapterCircuitAdmission,\n\tattempt: number,\n\tlastError: string | undefined,\n): AdapterCircuitOpenError {\n\treturn new AdapterCircuitOpenError({\n\t\tadapterKey: breaker.key,\n\t\tstate: admission.state,\n\t\tattempt,\n\t\t...(admission.retryAfterMs !== undefined ? { retryAfterMs: admission.retryAfterMs } : {}),\n\t\t...(admission.manualOverride !== undefined ? { manualOverride: admission.manualOverride } : {}),\n\t\t...(lastError !== undefined ? { lastError } : {}),\n\t});\n}\n\nexport async function executeWithAdapterRetry<T>(options: ExecuteWithRetryOptions<T>): Promise<T> {\n\tconst policy = resolveAdapterRetryPolicy(options.policy, options.defaultIdempotent);\n\tconst sleep =\n\t\toptions.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));\n\tconst breaker = options.circuitBreaker;\n\tlet lastError: string | undefined;\n\n\tfor (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {\n\t\tlet admission: AdapterCircuitAdmission | undefined;\n\t\t// One outcome per attempt reaches the breaker, and only for an attempt\n\t\t// that reached `execute`; a later step of this iteration (onAttempt,\n\t\t// sleep) that throws into the catch below does not record a second one.\n\t\tlet executed = false;\n\t\tlet recorded = false;\n\t\tconst record = (outcome: AdapterCircuitOutcome) => {\n\t\t\tif (!executed || recorded) return;\n\t\t\trecorded = true;\n\t\t\trecordCircuitOutcome(breaker, outcome, admission);\n\t\t};\n\t\tlet refusal: AdapterCircuitAdmission | undefined;\n\t\t/**\n\t\t * Classify an error thrown by `prepareAttempt`, `execute` or a later\n\t\t * step of this attempt. Returns \"retry\" after sleeping, \"rethrow\", or the\n\t\t * breaker admission that refuses the retry.\n\t\t */\n\t\tasync function handleThrown(error: unknown): Promise<\"retry\" | \"rethrow\" | AdapterCircuitAdmission> {\n\t\t\tlastError = error instanceof Error ? error.message : String(error);\n\t\t\t// Preserve the pre-classification contract for direct callers. The\n\t\t\t// governed Host supplies a classifier and therefore remains fail-closed\n\t\t\t// for ambiguous, timeout, and permanent failures.\n\t\t\tconst thrownOutcome = options.classifyThrownError\n\t\t\t\t? options.classifyThrownError(error)\n\t\t\t\t: \"transient_failure\" as const;\n\t\t\trecord(classifyCircuitBreakerOutcome(thrownOutcome));\n\t\t\tlet willRetry =\n\t\t\t\tshouldRetryAdapterOutcome(thrownOutcome, policy.idempotent) && attempt < policy.maxAttempts;\n\t\t\tconst blocked = willRetry ? refusedRetry(breaker) : undefined;\n\t\t\tif (blocked) willRetry = false;\n\t\t\tconst nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : undefined;\n\t\t\tawait options.onAttempt?.({ attempt, error: lastError, willRetry, nextDelayMs });\n\n\t\t\tif (blocked) return blocked;\n\t\t\tif (!willRetry) return \"rethrow\";\n\t\t\tawait sleep(nextDelayMs ?? 0);\n\t\t\treturn \"retry\";\n\t\t}\n\n\t\ttry {\n\t\t\tif (options.prepareAttempt) await options.prepareAttempt(attempt, policy.maxAttempts);\n\t\t} catch (error) {\n\t\t\tconst decision = await handleThrown(error);\n\t\t\tif (decision === \"rethrow\") throw error;\n\t\t\tif (decision === \"retry\") continue;\n\t\t\trefusal = decision;\n\t\t}\n\t\tif (!refusal) {\n\t\t\t// Admission sits immediately before the external call: no await between.\n\t\t\tif (breaker) {\n\t\t\t\tadmission = breaker.acquire();\n\t\t\t\tif (!admission.allowed) throw circuitOpenError(breaker, admission, attempt, lastError);\n\t\t\t}\n\t\t\ttry {\n\t\t\t\texecuted = true;\n\t\t\t\tconst result = await options.execute(attempt, policy.maxAttempts);\n\t\t\t\tif (options.isSuccessful(result)) {\n\t\t\t\t\trecord(\"success\");\n\t\t\t\t\tawait options.onAttempt?.({ attempt, result, willRetry: false });\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tlastError = options.getError(result) ?? \"Adapter returned unsuccessful result\";\n\t\t\t\tconst outcome = options.classifyOutcome\n\t\t\t\t\t? options.classifyOutcome(result)\n\t\t\t\t\t: \"transient_failure\" as const;\n\t\t\t\trecord(classifyCircuitBreakerOutcome(outcome));\n\t\t\t\tlet willRetry =\n\t\t\t\t\tshouldRetryAdapterOutcome(outcome, policy.idempotent) && attempt < policy.maxAttempts;\n\t\t\t\trefusal = willRetry ? refusedRetry(breaker) : undefined;\n\t\t\t\tif (refusal) willRetry = false;\n\t\t\t\tconst nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : undefined;\n\t\t\t\tawait options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });\n\n\t\t\t\tif (!willRetry && !refusal) {\n\t\t\t\t\treturn result;\n\t\t\t\t}\n\n\t\t\t\tif (!refusal) await sleep(nextDelayMs ?? 0);\n\t\t\t} catch (error) {\n\t\t\t\tconst decision = await handleThrown(error);\n\t\t\t\tif (decision === \"rethrow\") throw error;\n\t\t\t\trefusal = decision === \"retry\" ? undefined : decision;\n\t\t\t}\n\t\t}\n\t\t// The breaker opened on this attempt's outcome: stop instead of retrying.\n\t\tif (refusal && breaker) throw circuitOpenError(breaker, refusal, attempt + 1, lastError);\n\t}\n\n\tthrow new Error(lastError ?? \"Adapter retry exhausted\");\n}\n\n/**\n * Preview whether an `enforce`-mode breaker would refuse the next attempt.\n * Returns the refusing admission, or undefined when the retry may proceed.\n */\nfunction refusedRetry(breaker: AdapterCircuitBreaker | undefined): AdapterCircuitAdmission | undefined {\n\tif (!breaker) return undefined;\n\tconst preview = breaker.check();\n\treturn preview.allowed ? undefined : preview;\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAgDA,SAAgB,8BAA8B,MAAiD;CAC9F,QAAQ,MAAR;EACC,KAAK,WACJ,OAAO;EACR,KAAK,qBACJ,OAAO;EACR,KAAK;EACL,KAAK;EACL,KAAK,aACJ,OAAO;EACR,SAEC,OAAO;CACT;AACD;AA0HA,MAAM,mBAAmE,CAAC,cAAc,cAAc;;;;;;;;AAStG,SAAgB,kCAAkC,QAA2C;CAC5F,IAAI,CAAC,UAAU,OAAO,WAAW,UAChC,MAAM,IAAI,WAAW,mDAAmD;CAEzE,IAAI,OAAO,SAAS,aAAa,OAAO,SAAS,WAChD,MAAM,IAAI,WAAW,oEAAoE,KAAK,UAAU,OAAO,IAAI,EAAE,EAAE;CAExH,IAAI,CAAC,OAAO,UAAU,OAAO,gBAAgB,KAAK,OAAO,mBAAmB,GAC3E,MAAM,IAAI,WAAW,4EAA4E,OAAO,OAAO,gBAAgB,EAAE,EAAE;CAEpI,IAAI,OAAO,OAAO,aAAa,YAAY,CAAC,OAAO,SAAS,OAAO,QAAQ,KAAK,OAAO,YAAY,GAClG,MAAM,IAAI,WAAW,mFAAmF,OAAO,OAAO,QAAQ,EAAE,EAAE;CAEnI,IAAI,OAAO,OAAO,eAAe,YAAY,CAAC,OAAO,SAAS,OAAO,UAAU,KAAK,OAAO,aAAa,GACvG,MAAM,IAAI,WAAW,yFAAyF,OAAO,OAAO,UAAU,EAAE,EAAE;CAE3I,IACC,OAAO,mBAAmB,KAAA,MACzB,CAAC,OAAO,UAAU,OAAO,cAAc,KAAK,OAAO,iBAAiB,IAErE,MAAM,IAAI,WAAW,0EAA0E,OAAO,OAAO,cAAc,EAAE,EAAE;CAEhI,IACC,OAAO,iBAAiB,KAAA,MACvB,OAAO,OAAO,iBAAiB,YAAY,CAAC,OAAO,SAAS,OAAO,YAAY,KAAK,OAAO,gBAAgB,IAE5G,MAAM,IAAI,WAAW,uFAAuF,OAAO,OAAO,YAAY,EAAE,EAAE;CAE3I,IAAI,OAAO,mBAAmB,KAAA,KAAa,CAAC,iBAAiB,SAAS,OAAO,cAAc,GAC1F,MAAM,IAAI,WAAW,sFAAsF,KAAK,UAAU,OAAO,cAAc,EAAE,EAAE;AAErJ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAsEA,IAAa,gCAAb,MAA4E;CAC3E;CACA;CACA;CACA;CACA;CACA;CACA,UAA4B,CAAC;CAC7B,QAAqC;CACrC,WAAmB;CACnB;;CAEA,aAAqB;CACrB;;CAEA,SAAwD,CAAC;CACzD,iBAAyB;CACzB,WAAmB;CAEnB,YAAY,SAA+C;EAC1D,kCAAkC,QAAQ,MAAM;EAChD,KAAK,MAAM,QAAQ;EACnB,KAAK,SAAS,EAAE,GAAG,QAAQ,OAAO;EAClC,KAAK,OAAO,QAAQ,OAAO;EAC3B,KAAK,MAAM,QAAQ,OAAO,KAAK;EAC/B,KAAK,UAAU,QAAQ;EACvB,KAAK,iBAAiB,QAAQ,OAAO;EACrC,KAAK,eAAe,QAAQ,OAAO,gBAAgB,KAAK,IAAI,QAAQ,OAAO,YAAY,QAAQ,OAAO,QAAQ;CAC/G;CAEA,WAAgC;EAC/B,KAAK,OAAO,KAAK,IAAI,CAAC;EACtB,OAAO,KAAK,cAAc;CAC3B;CAEA,oBAAqE;EACpE,OAAO,KAAK;CACb;;;;;CAMA,kBAAkB,UAAiE;EAClF,IAAI,aAAa,KAAA,KAAa,CAAC,iBAAiB,SAAS,QAAQ,GAChE,MAAM,IAAI,WAAW,sFAAsF,KAAK,UAAU,QAAQ,EAAE,EAAE;EAEvI,MAAM,MAAM,KAAK,IAAI;EACrB,KAAK,OAAO,GAAG;EAEf,IAAI,aAAa,KAAK,gBAAgB;EACtC,KAAK,gBAAgB;GACpB,MAAM,OAAO,KAAK,cAAc;GAChC,KAAK,iBAAiB;GACtB,KAAK;GACL,IAAI,aAAa,KAAA,GAAW;IAC3B,KAAK,QAAQ;IACb,KAAK,aAAa;GACnB;GACA,KAAK,KAAK;IACT,MAAM;IACN,KAAK,KAAK;IACV,MAAM,KAAK;IACX,IAAI;IACJ;IACA,IAAI,KAAK,cAAc;IACvB,QAAQ,aAAa,KAAA,IAAY,4BAA4B;IAC7D,GAAI,WAAW,EAAE,gBAAgB,SAAS,IAAI,CAAC;GAChD,CAAC;EACF,CAAC;CACF;CAEA,QAAiC;EAChC,OAAO,KAAK,OAAO,OAAO,KAAK,IAAI,CAAC;CACrC;CAEA,UAAmC;EAClC,MAAM,MAAM,KAAK,IAAI;EACrB,KAAK,OAAO,GAAG;EACf,OAAO,KAAK,gBAAgB,KAAK,OAAO,MAAM,GAAG,CAAC;CACnD;CAEA,OAAO,SAAgC,WAA2C;EACjF,MAAM,MAAM,KAAK,IAAI;EAGrB,KAAK,OAAO,GAAG;EACf,KAAK,gBAAgB,KAAK,aAAa,SAAS,WAAW,GAAG,CAAC;CAChE;CAEA,aAAqB,SAAgC,WAAgD,KAAmB;EACvH,MAAM,aAAa,WAAW;EAE9B,IAAI,eAAe,KAAA,KAAa,eAAe,KAAK,YAAY;EAEhE,MAAM,gBACL,KAAK,UAAU,eACf,KAAK,kBAAkB,KAAA,MACtB,eAAe,KAAA,KAAa,WAAW,UAAU;EACnD,IAAI,YAAY,WAAW;GAE1B,IAAI,eAAe,KAAK,aAAa;GACrC;EACD;EACA,KAAK,MAAM,GAAG;EACd,KAAK,QAAQ,KAAK;GAAE,IAAI;GAAK,SAAS,YAAY;EAAU,CAAC;EAC7D,IAAI,KAAK,gBAAgB;EACzB,IAAI,eAAe;GAClB,KAAK,aAAa;GAClB,IAAI,YAAY,WAAW;IAC1B,KAAK,UAAU,CAAC;IAChB,KAAK,WAAW,UAAU,mBAAmB,GAAG;GACjD,OAAO;IACN,KAAK,WAAW;IAChB,KAAK,WAAW,QAAQ,gBAAgB,GAAG;GAC5C;GACA;EACD;EACA,IAAI,KAAK,UAAU,YAAY,YAAY,aAAa,KAAK,WAAW,GAAG;GAC1E,KAAK,WAAW;GAChB,KAAK,WAAW,QAAQ,qBAAqB,GAAG;EACjD;CACD;;;;;CAMA,OAAe,MAAe,KAAsC;EACnE,IAAI,KAAK,mBAAmB,gBAC3B,OAAO;GAAE,SAAS;GAAM,OAAO;GAAU,OAAO;GAAO,gBAAgB;GAAgB,YAAY,KAAK;EAAW;EAEpH,IAAI,KAAK,mBAAmB,cAC3B,OAAO,KAAK,OAAO,MAAM;GAAE,OAAO;GAAQ,gBAAgB;EAAa,CAAC;EAIzE,MAAM,kBAAkB,KAAK,UAAU,UAAU,MAAM,KAAK,YAAY,KAAK,OAAO;EAIpF,IAAI,MAAM,KAAK,QAAQ,GAAG;EAC1B,MAAM,QAA6B,CAAC,QAAQ,kBAAkB,cAAc,KAAK;EACjF,IAAI,UAAU,UAAU,OAAO;GAAE,SAAS;GAAM,OAAO;GAAU,OAAO;GAAO,YAAY,KAAK;EAAW;EAC3G,IAAI,UAAU,QACb,OAAO,KAAK,OAAO,MAAM;GACxB,OAAO;GACP,cAAc,KAAK,IAAI,GAAG,KAAK,WAAW,KAAK,OAAO,aAAa,GAAG;EACvE,CAAC;EAOF,IAAI,EAHF,CAAC,QAAQ,mBACV,KAAK,kBAAkB,KAAA,KACvB,MAAM,KAAK,iBAAiB,KAAK,eAClB,OAAO,KAAK,OAAO,MAAM,EAAE,OAAO,YAAY,CAAC;EAC/D,IAAI,CAAC,MAAM,OAAO;GAAE,SAAS;GAAM,OAAO;GAAa,OAAO;GAAM,YAAY,KAAK;EAAW;EAEhG,KAAK,gBAAgB;EACrB,KAAK;EACL,OAAO;GAAE,SAAS;GAAM,OAAO;GAAa,OAAO;GAAM,YAAY,KAAK;EAAW;CACtF;CAEA,OACC,MACA,QAC0B;EAC1B,MAAM,UAAU,KAAK,SAAS;EAC9B,IAAI,MACH,KAAK,KAAK;GACT,MAAM,UAAU,aAAa;GAC7B,KAAK,KAAK;GACV,MAAM,KAAK;GACX,IAAI,KAAK,IAAI;GACb,GAAG;EACJ,CAAC;EAEF,MAAM,aAAa,KAAK;EACxB,OAAO,UACJ;GAAE,SAAS;GAAO,OAAO;GAAO,GAAG;GAAQ;EAAW,IACtD;GAAE,SAAS;GAAM,OAAO;GAAO,aAAa;GAAM,GAAG;GAAQ;EAAW;CAC5E;CAEA,eAA6B;EAC5B,KAAK,gBAAgB,KAAA;CACtB;;CAGA,QAAgB,KAAmB;EAClC,IAAI,KAAK,UAAU,UAAU,MAAM,KAAK,YAAY,KAAK,OAAO,YAAY;GAC3E,KAAK,aAAa;GAClB,KAAK,WAAW,aAAa,oBAAoB,GAAG;EACrD;CACD;CAEA,aAA8B;EAC7B,MAAM,iBAAiB,KAAK,OAAO,kBAAkB,KAAK,OAAO;EACjE,MAAM,QAAQ,KAAK,QAAQ;EAC3B,IAAI,QAAQ,gBAAgB,OAAO;EACnC,IAAI,cAAc;EAClB,KAAK,IAAI,QAAQ,QAAQ,GAAG,SAAS,KAAK,KAAK,QAAQ,MAAM,CAAE,SAAS,SAAS;EACjF,IAAI,eAAe,KAAK,OAAO,kBAAkB,OAAO;EAExD,OADiB,KAAK,QAAQ,QAAQ,OAAO,WAAW,SAAS,OAAO,UAAU,IAAI,IAAI,CAC5E,IAAI,SAAS,KAAK,OAAO,mBAAmB;CAC3D;CAEA,MAAc,KAAmB;EAChC,MAAM,SAAS,MAAM,KAAK,OAAO;EACjC,IAAI,OAAO;EACX,OAAO,OAAO,KAAK,QAAQ,UAAU,KAAK,QAAQ,KAAK,CAAE,KAAK,QAAQ;EACtE,IAAI,OAAO,GAAG,KAAK,QAAQ,OAAO,GAAG,IAAI;CAC1C;CAEA,WAAmB,IAAyB,QAA0C,IAAkB;EACvG,MAAM,OAAO,KAAK;EAClB,IAAI,SAAS,IAAI;EACjB,KAAK,QAAQ;EACb,KAAK;EACL,KAAK,KAAK;GAAE,MAAM;GAAgB,KAAK,KAAK;GAAK,MAAM,KAAK;GAAM;GAAI;GAAM;GAAI;EAAO,CAAC;CACzF;CAEA,gBAA6C;EAC5C,IAAI,KAAK,gBAAgB,OAAO,KAAK,mBAAmB,eAAe,SAAS;EAChF,OAAO,KAAK;CACb;;;;;CAMA,OAAe,KAAmB;EACjC,IAAI,KAAK,gBAAgB;EACzB,KAAK,gBAAgB,KAAK,QAAQ,GAAG,CAAC;CACvC;;;;;CAMA,UAAqB,MAAkB;EACtC,KAAK;EACL,IAAI;GACH,OAAO,KAAK;EACb,UAAU;GACT,KAAK;GACL,IAAI,KAAK,mBAAmB,GAAG,KAAK,MAAM;EAC3C;CACD;CAEA,KAAa,OAAyC;EACrD,IAAI,KAAK,SAAS,KAAK,OAAO,KAAK,KAAK;CACzC;;;;;;CAOA,QAAsB;EACrB,IAAI,KAAK,UAAU;EACnB,KAAK,WAAW;EAChB,IAAI;GACH,KAAK,IAAI,QAAQ,KAAK,OAAO,MAAM,GAAG,OAAO,QAAQ,KAAK,OAAO,MAAM,GAAG,KAAK,QAAQ,KAAK;EAC7F,UAAU;GACT,KAAK,WAAW;EACjB;CACD;CAEA,QAAgB,OAAyC;EACxD,MAAM,WAAW,KAAK;EACtB,IAAI,CAAC,UAAU;EACf,IAAI;GACH,MAAM,SAAS,SAAS,KAAK;GAC7B,IAAI,UAAU,OAAQ,OAA6B,SAAS,YAC3D,OAA8B,KAAK,KAAA,SAAiB,KAAA,CAAS;EAE/D,QAAQ,CAER;CACD;AACD;;;;;;;;;;;;;AAoBA,SAAgB,+BACf,SACA,OACS;CACT,OAAO;EACN,UAAU,KAAA,IAAY,aAAa,UAAU,mBAAmB,MAAM,QAAQ;EAC9E,OAAO,YAAY,KAAA,IAAY,UAAU,SAAS,mBAAmB,MAAM,OAAO;EAClF,QAAQ,WAAW,KAAA,IAAY,WAAW,UAAU,mBAAmB,QAAQ,MAAM;EACrF,mBAAmB,QAAQ,WAAW;EACtC,mBAAmB,QAAQ,SAAS;CACrC,CAAC,CAAC,KAAK,GAAG;AACX;;;;;;;;;;AA+BA,IAAa,gCAAb,MAAoF;CAGtD;CAF7B,2BAA4B,IAAI,IAA2C;CAE3E,YAAY,UAAiE,CAAC,GAAG;EAApD,KAAA,UAAA;CAAqD;CAElF,WAAW,SAAgC,OAA+E;EACzH,IAAI,CAAC,QAAQ,gBAAgB,OAAO,KAAA;EACpC,MAAM,MAAM,KAAK,QAAQ,MAAM,SAAS,KAAK,KAAK,GAAG,QAAQ,YAAY,GAAG,QAAQ;EACpF,IAAI,UAAU,KAAK,SAAS,IAAI,GAAG;EACnC,IAAI,CAAC,SAAS;GACb,UAAU,IAAI,8BAA8B;IAC3C;IACA,QAAQ,QAAQ;IAChB,GAAI,KAAK,QAAQ,MAAM,EAAE,KAAK,KAAK,QAAQ,IAAI,IAAI,CAAC;IACpD,GAAI,KAAK,QAAQ,UAAU,EAAE,SAAS,KAAK,QAAQ,QAAQ,IAAI,CAAC;GACjE,CAAC;GACD,KAAK,SAAS,IAAI,KAAK,OAAO;EAC/B;EACA,OAAO;CACR;;CAGA,IAAI,aAAqB,WAA8D;EACtF,OAAO,KAAK,SAAS,GAAG,YAAY,GAAG,WAAW;CACnD;;CAGA,SAAS,KAAwD;EAChE,OAAO,KAAK,SAAS,IAAI,GAAG;CAC7B;AACD;;;;;;AAOA,IAAa,0BAAb,cAA6C,MAAM;CAClD,OAAyB;CACzB,OAAgB;CAChB,SAAkB;CAClB;CACA;;CAEA;CACA;CACA;;CAEA;CAEA,YAAY,OAOT;EACF,MAAM,QAAQ,MAAM,iBAAiB,KAAA,IAAY,iBAAiB,MAAM,aAAa,OAAO;EAC5F,MAAM,sBAAsB,MAAM,UAAU,cAAc,uCAAuC,OAAO,OAAO,MAAM,WAAW,8BAA8B,MAAM,EAAE;EACtK,KAAK,aAAa,MAAM;EACxB,KAAK,QAAQ,MAAM;EACnB,KAAK,UAAU,MAAM;EACrB,IAAI,MAAM,iBAAiB,KAAA,GAAW,KAAK,eAAe,MAAM;EAChE,IAAI,MAAM,mBAAmB,KAAA,GAAW,KAAK,iBAAiB,MAAM;EACpE,IAAI,MAAM,cAAc,KAAA,GAAW,KAAK,YAAY,MAAM;CAC3D;AACD;;;;;;AAOA,SAAgB,0BAA0B,OAAkD;CAC3F,IAAI,iBAAiB,yBAAyB,OAAO;CACrD,OACC,OAAO,UAAU,YACjB,UAAU,QACT,MAA6B,SAAS,6BACtC,MAA6B,SAAS;AAEzC;;;AC3eA,SAAS,WAAW,aAAqB,WAA2B;CACnE,OAAO,GAAG,YAAY,GAAG;AAC1B;AAEA,IAAa,kCAAb,cAAqD,MAAM;CAC1D,YAAY,aAAqB,WAAmB;EACnD,MAAM,0CAA0C,YAAY,mBAAmB,UAAU,EAAE;EAC3F,KAAK,OAAO;CACb;AACD;AAEA,IAAa,kBAAb,MAA6B;CAC5B,2BAA4B,IAAI,IAAmC;CAEnE,SAAS,SAAsC;EAC9C,MAAM,MAAM,WAAW,QAAQ,aAAa,QAAQ,SAAS;EAC7D,IAAI,KAAK,SAAS,IAAI,GAAG,GACxB,MAAM,IAAI,MACT,+CAA+C,QAAQ,YAAY,mBAAmB,QAAQ,UAAU,EACzG;EAGD,KAAK,SAAS,IAAI,KAAK,OAAO;CAC/B;CAEA,QAAQ,aAAqB,WAAsD;EAClF,OAAO,KAAK,SAAS,IAAI,WAAW,aAAa,SAAS,CAAC;CAC5D;CAEA,QAAQ,aAAqB,WAA0C;EACtE,MAAM,UAAU,KAAK,QAAQ,aAAa,SAAS;EACnD,IAAI,CAAC,SACJ,MAAM,IAAI,gCAAgC,aAAa,SAAS;EAGjE,OAAO;CACR;AACD;AAEA,MAAM,uBAAmD;CACxD,YAAY;CACZ,aAAa;CACb,gBAAgB;CAChB,mBAAmB;CACnB,YAAY;AACb;AAEA,MAAM,kBAA8C;CACnD,YAAY;CACZ,aAAa;CACb,gBAAgB;CAChB,mBAAmB;CACnB,YAAY;AACb;AAEA,SAAgB,0BACf,QACA,mBAC6B;CAG7B,IAAI,EAFe,QAAQ,cAAc,oBAGxC,OAAO;CAGR,OAAO;EACN,YAAY;EACZ,aAAa,KAAK,IAAI,GAAG,KAAK,IAAI,QAAQ,eAAe,qBAAqB,aAAa,CAAC,CAAC;EAC7F,gBAAgB,KAAK,IAAI,GAAG,QAAQ,kBAAkB,qBAAqB,cAAc;EACzF,mBAAmB,KAAK,IACvB,GACA,QAAQ,qBAAqB,qBAAqB,iBACnD;EACA,YAAY,KAAK,IAAI,GAAG,QAAQ,cAAc,qBAAqB,UAAU;CAC9E;AACD;AAEA,SAAgB,gBAAgB,SAAiB,QAA4C;CAC5F,MAAM,mBACL,OAAO,iBAAiB,OAAO,qBAAqB,KAAK,IAAI,GAAG,UAAU,CAAC;CAE5E,OAAO,KAAK,IAAI,kBAAkB,OAAO,UAAU;AACpD;;;;;;;;AASA,SAAgB,uBAAuB,QAAoD;CAC1F,IAAI,OAAO,SAAS;EACnB,gCAAgC,MAAM;EACtC,OAAO,OAAO;CACf;CACA,OAAO,OAAO,UAAU,YAAY;AACrC;;;;;;AAOA,SAAgB,0BACf,MACA,YACU;CACV,OAAO,SAAS,uBAAuB;AACxC;;;;;;;AAQA,SAAgB,gCAAgC,QAAsC;CACrF,IAAI,OAAO,WAAW,OAAO,WAAW,OAAO,YAAY,WAC1D,MAAM,IAAI,MACT,6DAA6D,OAAO,QAAQ,+DAC7E;AAEF;;;;;AAMA,SAAS,qBACR,SACA,SACA,WACO;CACP,IAAI,CAAC,SAAS;CACd,IAAI;EACH,QAAQ,OAAO,SAAS,SAAS;CAClC,QAAQ,CAER;AACD;AAEA,SAAS,iBACR,SACA,WACA,SACA,WAC0B;CAC1B,OAAO,IAAI,wBAAwB;EAClC,YAAY,QAAQ;EACpB,OAAO,UAAU;EACjB;EACA,GAAI,UAAU,iBAAiB,KAAA,IAAY,EAAE,cAAc,UAAU,aAAa,IAAI,CAAC;EACvF,GAAI,UAAU,mBAAmB,KAAA,IAAY,EAAE,gBAAgB,UAAU,eAAe,IAAI,CAAC;EAC7F,GAAI,cAAc,KAAA,IAAY,EAAE,UAAU,IAAI,CAAC;CAChD,CAAC;AACF;AAEA,eAAsB,wBAA2B,SAAiD;CACjG,MAAM,SAAS,0BAA0B,QAAQ,QAAQ,QAAQ,iBAAiB;CAClF,MAAM,QACL,QAAQ,WAAW,YAAY,IAAI,SAAS,YAAY,WAAW,SAAS,OAAO,CAAC;CACrF,MAAM,UAAU,QAAQ;CACxB,IAAI;CAEJ,KAAK,IAAI,UAAU,GAAG,WAAW,OAAO,aAAa,WAAW;EAC/D,IAAI;EAIJ,IAAI,WAAW;EACf,IAAI,WAAW;EACf,MAAM,UAAU,YAAmC;GAClD,IAAI,CAAC,YAAY,UAAU;GAC3B,WAAW;GACX,qBAAqB,SAAS,SAAS,SAAS;EACjD;EACA,IAAI;;;;;;EAMJ,eAAe,aAAa,OAAwE;GACnG,YAAY,iBAAiB,QAAQ,MAAM,UAAU,OAAO,KAAK;GAIjE,MAAM,gBAAgB,QAAQ,sBAC3B,QAAQ,oBAAoB,KAAK,IACjC;GACH,OAAO,8BAA8B,aAAa,CAAC;GACnD,IAAI,YACH,0BAA0B,eAAe,OAAO,UAAU,KAAK,UAAU,OAAO;GACjF,MAAM,UAAU,YAAY,aAAa,OAAO,IAAI,KAAA;GACpD,IAAI,SAAS,YAAY;GACzB,MAAM,cAAc,YAAY,gBAAgB,SAAS,MAAM,IAAI,KAAA;GACnE,MAAM,QAAQ,YAAY;IAAE;IAAS,OAAO;IAAW;IAAW;GAAY,CAAC;GAE/E,IAAI,SAAS,OAAO;GACpB,IAAI,CAAC,WAAW,OAAO;GACvB,MAAM,MAAM,eAAe,CAAC;GAC5B,OAAO;EACR;EAEA,IAAI;GACH,IAAI,QAAQ,gBAAgB,MAAM,QAAQ,eAAe,SAAS,OAAO,WAAW;EACrF,SAAS,OAAO;GACf,MAAM,WAAW,MAAM,aAAa,KAAK;GACzC,IAAI,aAAa,WAAW,MAAM;GAClC,IAAI,aAAa,SAAS;GAC1B,UAAU;EACX;EACA,IAAI,CAAC,SAAS;GAEb,IAAI,SAAS;IACZ,YAAY,QAAQ,QAAQ;IAC5B,IAAI,CAAC,UAAU,SAAS,MAAM,iBAAiB,SAAS,WAAW,SAAS,SAAS;GACtF;GACA,IAAI;IACH,WAAW;IACX,MAAM,SAAS,MAAM,QAAQ,QAAQ,SAAS,OAAO,WAAW;IAChE,IAAI,QAAQ,aAAa,MAAM,GAAG;KACjC,OAAO,SAAS;KAChB,MAAM,QAAQ,YAAY;MAAE;MAAS;MAAQ,WAAW;KAAM,CAAC;KAC/D,OAAO;IACR;IAEA,YAAY,QAAQ,SAAS,MAAM,KAAK;IACxC,MAAM,UAAU,QAAQ,kBACrB,QAAQ,gBAAgB,MAAM,IAC9B;IACH,OAAO,8BAA8B,OAAO,CAAC;IAC7C,IAAI,YACH,0BAA0B,SAAS,OAAO,UAAU,KAAK,UAAU,OAAO;IAC3E,UAAU,YAAY,aAAa,OAAO,IAAI,KAAA;IAC9C,IAAI,SAAS,YAAY;IACzB,MAAM,cAAc,YAAY,gBAAgB,SAAS,MAAM,IAAI,KAAA;IACnE,MAAM,QAAQ,YAAY;KAAE;KAAS;KAAQ,OAAO;KAAW;KAAW;IAAY,CAAC;IAEvF,IAAI,CAAC,aAAa,CAAC,SAClB,OAAO;IAGR,IAAI,CAAC,SAAS,MAAM,MAAM,eAAe,CAAC;GAC3C,SAAS,OAAO;IACf,MAAM,WAAW,MAAM,aAAa,KAAK;IACzC,IAAI,aAAa,WAAW,MAAM;IAClC,UAAU,aAAa,UAAU,KAAA,IAAY;GAC9C;EACD;EAEA,IAAI,WAAW,SAAS,MAAM,iBAAiB,SAAS,SAAS,UAAU,GAAG,SAAS;CACxF;CAEA,MAAM,IAAI,MAAM,aAAa,yBAAyB;AACvD;;;;;AAMA,SAAS,aAAa,SAAiF;CACtG,IAAI,CAAC,SAAS,OAAO,KAAA;CACrB,MAAM,UAAU,QAAQ,MAAM;CAC9B,OAAO,QAAQ,UAAU,KAAA,IAAY;AACtC"}
|
|
@@ -1,12 +1,23 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
//#region agent-hitl/index.ts
|
|
3
|
+
var AgentActionPolicyRegistry = class {
|
|
4
|
+
_policies = /* @__PURE__ */ new Map();
|
|
5
|
+
register(definition) {
|
|
6
|
+
const existing = this._policies.get(definition.actionId);
|
|
7
|
+
if (existing && existing.evaluator !== definition.evaluator) throw new Error(`Conflicting agent action policy registration for "${definition.actionId}". A different evaluator is already registered.`);
|
|
8
|
+
this._policies.set(definition.actionId, definition);
|
|
9
|
+
}
|
|
10
|
+
resolve(actionId) {
|
|
11
|
+
return this._policies.get(actionId);
|
|
12
|
+
}
|
|
13
|
+
listAll() {
|
|
14
|
+
return Array.from(this._policies.values());
|
|
15
|
+
}
|
|
16
|
+
clear() {
|
|
17
|
+
this._policies.clear();
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
//#endregion
|
|
21
|
+
exports.AgentActionPolicyRegistry = AgentActionPolicyRegistry;
|
|
2
22
|
|
|
3
|
-
var chunkF3E5SXPN_cjs = require('../chunk-F3E5SXPN.cjs');
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
Object.defineProperty(exports, "AgentActionPolicyRegistry", {
|
|
8
|
-
enumerable: true,
|
|
9
|
-
get: function () { return chunkF3E5SXPN_cjs.AgentActionPolicyRegistry; }
|
|
10
|
-
});
|
|
11
|
-
//# sourceMappingURL=index.cjs.map
|
|
12
23
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"index.cjs","names":[],"sources":["../../agent-hitl/index.ts"],"sourcesContent":["export type AgentActionRoute = \"auto-execute\" | \"needs-approval\" | \"escalate\" | \"rejected\";\n\nexport type AgentActionRiskTier = \"low\" | \"medium\" | \"high\";\n\nexport interface AgentActionPolicyContext {\n\tactionId: string;\n\tactorId: string;\n\tactorType: string;\n\ttenantId: string;\n\tspaceId: string;\n\tparameters: Record<string, unknown>;\n\tconfidence?: number;\n\triskTier?: AgentActionRiskTier;\n\tagentSessionId?: string;\n\tagentRunId?: string;\n}\n\nexport interface AgentActionPolicyDecision {\n\troute: AgentActionRoute;\n\triskTier: AgentActionRiskTier;\n\treason: string;\n}\n\nexport type AgentActionPolicyEvaluator = (\n\tcontext: AgentActionPolicyContext,\n) => AgentActionPolicyDecision | Promise<AgentActionPolicyDecision>;\n\nexport interface AgentActionPolicyDefinition {\n\tactionId: string;\n\tevaluator: AgentActionPolicyEvaluator;\n\tdescription?: string;\n}\n\nexport class AgentActionPolicyRegistry {\n\tprivate _policies = new Map<string, AgentActionPolicyDefinition>();\n\n\tregister(definition: AgentActionPolicyDefinition): void {\n\t\tconst existing = this._policies.get(definition.actionId);\n\t\tif (existing && existing.evaluator !== definition.evaluator) {\n\t\t\tthrow new Error(\n\t\t\t\t`Conflicting agent action policy registration for \"${definition.actionId}\". ` +\n\t\t\t\t\t`A different evaluator is already registered.`,\n\t\t\t);\n\t\t}\n\t\tthis._policies.set(definition.actionId, definition);\n\t}\n\n\tresolve(actionId: string): AgentActionPolicyDefinition | undefined {\n\t\treturn this._policies.get(actionId);\n\t}\n\n\tlistAll(): AgentActionPolicyDefinition[] {\n\t\treturn Array.from(this._policies.values());\n\t}\n\n\tclear(): void {\n\t\tthis._policies.clear();\n\t}\n}\n"],"mappings":";;AAiCA,IAAa,4BAAb,MAAuC;CACtC,4BAAoB,IAAI,IAAyC;CAEjE,SAAS,YAA+C;EACvD,MAAM,WAAW,KAAK,UAAU,IAAI,WAAW,QAAQ;EACvD,IAAI,YAAY,SAAS,cAAc,WAAW,WACjD,MAAM,IAAI,MACT,qDAAqD,WAAW,SAAS,gDAE1E;EAED,KAAK,UAAU,IAAI,WAAW,UAAU,UAAU;CACnD;CAEA,QAAQ,UAA2D;EAClE,OAAO,KAAK,UAAU,IAAI,QAAQ;CACnC;CAEA,UAAyC;EACxC,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC;CAC1C;CAEA,QAAc;EACb,KAAK,UAAU,MAAM;CACtB;AACD"}
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
//#region agent-hitl/index.d.ts
|
|
2
|
+
export type AgentActionRoute = "auto-execute" | "needs-approval" | "escalate" | "rejected";
|
|
3
|
+
export type AgentActionRiskTier = "low" | "medium" | "high";
|
|
4
|
+
export interface AgentActionPolicyContext {
|
|
5
|
+
actionId: string;
|
|
6
|
+
actorId: string;
|
|
7
|
+
actorType: string;
|
|
8
|
+
tenantId: string;
|
|
9
|
+
spaceId: string;
|
|
10
|
+
parameters: Record<string, unknown>;
|
|
11
|
+
confidence?: number;
|
|
12
|
+
riskTier?: AgentActionRiskTier;
|
|
13
|
+
agentSessionId?: string;
|
|
14
|
+
agentRunId?: string;
|
|
14
15
|
}
|
|
15
|
-
interface AgentActionPolicyDecision {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
export interface AgentActionPolicyDecision {
|
|
17
|
+
route: AgentActionRoute;
|
|
18
|
+
riskTier: AgentActionRiskTier;
|
|
19
|
+
reason: string;
|
|
19
20
|
}
|
|
20
|
-
type AgentActionPolicyEvaluator = (context: AgentActionPolicyContext) => AgentActionPolicyDecision | Promise<AgentActionPolicyDecision>;
|
|
21
|
-
interface AgentActionPolicyDefinition {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
export type AgentActionPolicyEvaluator = (context: AgentActionPolicyContext) => AgentActionPolicyDecision | Promise<AgentActionPolicyDecision>;
|
|
22
|
+
export interface AgentActionPolicyDefinition {
|
|
23
|
+
actionId: string;
|
|
24
|
+
evaluator: AgentActionPolicyEvaluator;
|
|
25
|
+
description?: string;
|
|
25
26
|
}
|
|
26
|
-
declare class AgentActionPolicyRegistry {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
export declare class AgentActionPolicyRegistry {
|
|
28
|
+
private _policies;
|
|
29
|
+
register(definition: AgentActionPolicyDefinition): void;
|
|
30
|
+
resolve(actionId: string): AgentActionPolicyDefinition | undefined;
|
|
31
|
+
listAll(): AgentActionPolicyDefinition[];
|
|
32
|
+
clear(): void;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
export { type AgentActionPolicyContext, type AgentActionPolicyDecision, type AgentActionPolicyDefinition, type AgentActionPolicyEvaluator, AgentActionPolicyRegistry, type AgentActionRiskTier, type AgentActionRoute };
|
|
34
|
+
//#endregion
|
|
@@ -1,34 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
type
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
1
|
+
//#region agent-hitl/index.d.ts
|
|
2
|
+
export type AgentActionRoute = "auto-execute" | "needs-approval" | "escalate" | "rejected";
|
|
3
|
+
export type AgentActionRiskTier = "low" | "medium" | "high";
|
|
4
|
+
export interface AgentActionPolicyContext {
|
|
5
|
+
actionId: string;
|
|
6
|
+
actorId: string;
|
|
7
|
+
actorType: string;
|
|
8
|
+
tenantId: string;
|
|
9
|
+
spaceId: string;
|
|
10
|
+
parameters: Record<string, unknown>;
|
|
11
|
+
confidence?: number;
|
|
12
|
+
riskTier?: AgentActionRiskTier;
|
|
13
|
+
agentSessionId?: string;
|
|
14
|
+
agentRunId?: string;
|
|
14
15
|
}
|
|
15
|
-
interface AgentActionPolicyDecision {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
16
|
+
export interface AgentActionPolicyDecision {
|
|
17
|
+
route: AgentActionRoute;
|
|
18
|
+
riskTier: AgentActionRiskTier;
|
|
19
|
+
reason: string;
|
|
19
20
|
}
|
|
20
|
-
type AgentActionPolicyEvaluator = (context: AgentActionPolicyContext) => AgentActionPolicyDecision | Promise<AgentActionPolicyDecision>;
|
|
21
|
-
interface AgentActionPolicyDefinition {
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
21
|
+
export type AgentActionPolicyEvaluator = (context: AgentActionPolicyContext) => AgentActionPolicyDecision | Promise<AgentActionPolicyDecision>;
|
|
22
|
+
export interface AgentActionPolicyDefinition {
|
|
23
|
+
actionId: string;
|
|
24
|
+
evaluator: AgentActionPolicyEvaluator;
|
|
25
|
+
description?: string;
|
|
25
26
|
}
|
|
26
|
-
declare class AgentActionPolicyRegistry {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
27
|
+
export declare class AgentActionPolicyRegistry {
|
|
28
|
+
private _policies;
|
|
29
|
+
register(definition: AgentActionPolicyDefinition): void;
|
|
30
|
+
resolve(actionId: string): AgentActionPolicyDefinition | undefined;
|
|
31
|
+
listAll(): AgentActionPolicyDefinition[];
|
|
32
|
+
clear(): void;
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
-
export { type AgentActionPolicyContext, type AgentActionPolicyDecision, type AgentActionPolicyDefinition, type AgentActionPolicyEvaluator, AgentActionPolicyRegistry, type AgentActionRiskTier, type AgentActionRoute };
|
|
34
|
+
//#endregion
|
package/dist/agent-hitl/index.js
CHANGED
|
@@ -1,3 +1,22 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
//#region agent-hitl/index.ts
|
|
2
|
+
var AgentActionPolicyRegistry = class {
|
|
3
|
+
_policies = /* @__PURE__ */ new Map();
|
|
4
|
+
register(definition) {
|
|
5
|
+
const existing = this._policies.get(definition.actionId);
|
|
6
|
+
if (existing && existing.evaluator !== definition.evaluator) throw new Error(`Conflicting agent action policy registration for "${definition.actionId}". A different evaluator is already registered.`);
|
|
7
|
+
this._policies.set(definition.actionId, definition);
|
|
8
|
+
}
|
|
9
|
+
resolve(actionId) {
|
|
10
|
+
return this._policies.get(actionId);
|
|
11
|
+
}
|
|
12
|
+
listAll() {
|
|
13
|
+
return Array.from(this._policies.values());
|
|
14
|
+
}
|
|
15
|
+
clear() {
|
|
16
|
+
this._policies.clear();
|
|
17
|
+
}
|
|
18
|
+
};
|
|
19
|
+
//#endregion
|
|
20
|
+
export { AgentActionPolicyRegistry };
|
|
21
|
+
|
|
3
22
|
//# sourceMappingURL=index.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../../agent-hitl/index.ts"],"sourcesContent":["export type AgentActionRoute = \"auto-execute\" | \"needs-approval\" | \"escalate\" | \"rejected\";\n\nexport type AgentActionRiskTier = \"low\" | \"medium\" | \"high\";\n\nexport interface AgentActionPolicyContext {\n\tactionId: string;\n\tactorId: string;\n\tactorType: string;\n\ttenantId: string;\n\tspaceId: string;\n\tparameters: Record<string, unknown>;\n\tconfidence?: number;\n\triskTier?: AgentActionRiskTier;\n\tagentSessionId?: string;\n\tagentRunId?: string;\n}\n\nexport interface AgentActionPolicyDecision {\n\troute: AgentActionRoute;\n\triskTier: AgentActionRiskTier;\n\treason: string;\n}\n\nexport type AgentActionPolicyEvaluator = (\n\tcontext: AgentActionPolicyContext,\n) => AgentActionPolicyDecision | Promise<AgentActionPolicyDecision>;\n\nexport interface AgentActionPolicyDefinition {\n\tactionId: string;\n\tevaluator: AgentActionPolicyEvaluator;\n\tdescription?: string;\n}\n\nexport class AgentActionPolicyRegistry {\n\tprivate _policies = new Map<string, AgentActionPolicyDefinition>();\n\n\tregister(definition: AgentActionPolicyDefinition): void {\n\t\tconst existing = this._policies.get(definition.actionId);\n\t\tif (existing && existing.evaluator !== definition.evaluator) {\n\t\t\tthrow new Error(\n\t\t\t\t`Conflicting agent action policy registration for \"${definition.actionId}\". ` +\n\t\t\t\t\t`A different evaluator is already registered.`,\n\t\t\t);\n\t\t}\n\t\tthis._policies.set(definition.actionId, definition);\n\t}\n\n\tresolve(actionId: string): AgentActionPolicyDefinition | undefined {\n\t\treturn this._policies.get(actionId);\n\t}\n\n\tlistAll(): AgentActionPolicyDefinition[] {\n\t\treturn Array.from(this._policies.values());\n\t}\n\n\tclear(): void {\n\t\tthis._policies.clear();\n\t}\n}\n"],"mappings":";AAiCA,IAAa,4BAAb,MAAuC;CACtC,4BAAoB,IAAI,IAAyC;CAEjE,SAAS,YAA+C;EACvD,MAAM,WAAW,KAAK,UAAU,IAAI,WAAW,QAAQ;EACvD,IAAI,YAAY,SAAS,cAAc,WAAW,WACjD,MAAM,IAAI,MACT,qDAAqD,WAAW,SAAS,gDAE1E;EAED,KAAK,UAAU,IAAI,WAAW,UAAU,UAAU;CACnD;CAEA,QAAQ,UAA2D;EAClE,OAAO,KAAK,UAAU,IAAI,QAAQ;CACnC;CAEA,UAAyC;EACxC,OAAO,MAAM,KAAK,KAAK,UAAU,OAAO,CAAC;CAC1C;CAEA,QAAc;EACb,KAAK,UAAU,MAAM;CACtB;AACD"}
|
|
@@ -1,26 +1,111 @@
|
|
|
1
|
-
|
|
1
|
+
Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
|
|
2
|
+
const require_manifest_index = require("../manifest/index.cjs");
|
|
3
|
+
//#region certification/index.ts
|
|
4
|
+
const STRICT_EXECUTION_CONTRACT_PROFILE_ID = "fabric.execution-contract.strict";
|
|
5
|
+
/** The permitted values of each required dimension, mirrored from the action types. */
|
|
6
|
+
function permittedDimensions() {
|
|
7
|
+
return [
|
|
8
|
+
["connectivity", /* @__PURE__ */ new Set(["online-required", "offline-capturable"])],
|
|
9
|
+
["authorityMoment", /* @__PURE__ */ new Set([
|
|
10
|
+
"capture",
|
|
11
|
+
"execution",
|
|
12
|
+
"both"
|
|
13
|
+
])],
|
|
14
|
+
["idempotency", /* @__PURE__ */ new Set([
|
|
15
|
+
"required",
|
|
16
|
+
"supported",
|
|
17
|
+
"prohibited"
|
|
18
|
+
])],
|
|
19
|
+
["completion", /* @__PURE__ */ new Set([
|
|
20
|
+
"immediate",
|
|
21
|
+
"accepted",
|
|
22
|
+
"long-running"
|
|
23
|
+
])],
|
|
24
|
+
["consistency", /* @__PURE__ */ new Set(["authoritative-now", "provisional-until-reconciled"])]
|
|
25
|
+
];
|
|
26
|
+
}
|
|
27
|
+
const permittedSensitivities = () => /* @__PURE__ */ new Set([
|
|
28
|
+
"public",
|
|
29
|
+
"internal",
|
|
30
|
+
"confidential",
|
|
31
|
+
"restricted"
|
|
32
|
+
]);
|
|
33
|
+
function executionContractProfile(options = {}) {
|
|
34
|
+
const id = options.id ?? "fabric.execution-contract.strict";
|
|
35
|
+
const requireSensitivity = options.requireSensitivity ?? true;
|
|
36
|
+
const requireDeadlineFor = new Set(options.requireDeadlineFor ?? ["accepted", "long-running"]);
|
|
37
|
+
const dimensions = permittedDimensions();
|
|
38
|
+
const sensitivities = permittedSensitivities();
|
|
39
|
+
const validate = (manifest) => {
|
|
40
|
+
const findings = [];
|
|
41
|
+
for (const action of manifest.actions) {
|
|
42
|
+
const contract = action.execution;
|
|
43
|
+
if (!contract) {
|
|
44
|
+
findings.push({
|
|
45
|
+
code: "missing_execution_contract",
|
|
46
|
+
actionId: action.actionId,
|
|
47
|
+
message: `Action "${action.actionId}" declares no execution contract; connectivity, authorityMoment, idempotency, completion, and consistency are required.`
|
|
48
|
+
});
|
|
49
|
+
continue;
|
|
50
|
+
}
|
|
51
|
+
let complete = true;
|
|
52
|
+
for (const [dimension, permitted] of dimensions) {
|
|
53
|
+
const value = contract[dimension];
|
|
54
|
+
if (!permitted.has(value)) {
|
|
55
|
+
complete = false;
|
|
56
|
+
findings.push({
|
|
57
|
+
code: "invalid_execution_dimension",
|
|
58
|
+
actionId: action.actionId,
|
|
59
|
+
message: `Action "${action.actionId}" ${value === void 0 ? "declares no" : `declares an unknown`} ${dimension}${value === void 0 ? "" : ` "${String(value)}"`}; permitted values are ${[...permitted].map((item) => `"${String(item)}"`).join(", ")}.`
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
if (contract.sensitivity !== void 0 && !sensitivities.has(contract.sensitivity)) findings.push({
|
|
64
|
+
code: "invalid_execution_dimension",
|
|
65
|
+
actionId: action.actionId,
|
|
66
|
+
message: `Action "${action.actionId}" declares an unknown sensitivity "${String(contract.sensitivity)}"; permitted values are ${[...sensitivities].map((item) => `"${item}"`).join(", ")}.`
|
|
67
|
+
});
|
|
68
|
+
if (!complete) continue;
|
|
69
|
+
if (contract.completion === "immediate" && contract.completionDeadlineMs !== void 0) findings.push({
|
|
70
|
+
code: "unexpected_completion_deadline",
|
|
71
|
+
actionId: action.actionId,
|
|
72
|
+
message: `Action "${action.actionId}" declares immediate completion and a completionDeadlineMs; nothing external completes it.`
|
|
73
|
+
});
|
|
74
|
+
if (requireSensitivity && contract.sensitivity === void 0) findings.push({
|
|
75
|
+
code: "missing_sensitivity",
|
|
76
|
+
actionId: action.actionId,
|
|
77
|
+
message: `Action "${action.actionId}" declares no sensitivity; say whether its durable data is public, internal, confidential, or restricted.`
|
|
78
|
+
});
|
|
79
|
+
if (requireDeadlineFor.has(contract.completion) && !(typeof contract.completionDeadlineMs === "number" && contract.completionDeadlineMs > 0)) findings.push({
|
|
80
|
+
code: "missing_completion_deadline",
|
|
81
|
+
actionId: action.actionId,
|
|
82
|
+
message: `Action "${action.actionId}" declares ${contract.completion} completion and no completionDeadlineMs; a callback that never comes would never be noticed.`
|
|
83
|
+
});
|
|
84
|
+
}
|
|
85
|
+
return findings;
|
|
86
|
+
};
|
|
87
|
+
return {
|
|
88
|
+
id,
|
|
89
|
+
validate,
|
|
90
|
+
assert(subject) {
|
|
91
|
+
const manifest = isManifest(subject) ? subject : require_manifest_index.exportModuleManifest(subject);
|
|
92
|
+
const findings = validate(manifest);
|
|
93
|
+
if (findings.length > 0) throw new Error(`Execution-contract profile "${id}" failed for "${manifest.namespace}":\n${findings.map((finding) => `- ${finding.message}`).join("\n")}`);
|
|
94
|
+
},
|
|
95
|
+
adapter: {
|
|
96
|
+
id,
|
|
97
|
+
evaluate: validate
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
}
|
|
101
|
+
/** All six dimensions on every action, and a deadline wherever work is handed off. */
|
|
102
|
+
const STRICT_EXECUTION_CONTRACT_PROFILE = executionContractProfile();
|
|
103
|
+
function isManifest(subject) {
|
|
104
|
+
return typeof subject.manifestVersion === "number" && Array.isArray(subject.actions);
|
|
105
|
+
}
|
|
106
|
+
//#endregion
|
|
107
|
+
exports.STRICT_EXECUTION_CONTRACT_PROFILE = STRICT_EXECUTION_CONTRACT_PROFILE;
|
|
108
|
+
exports.STRICT_EXECUTION_CONTRACT_PROFILE_ID = STRICT_EXECUTION_CONTRACT_PROFILE_ID;
|
|
109
|
+
exports.executionContractProfile = executionContractProfile;
|
|
2
110
|
|
|
3
|
-
var chunkMCWSUGB3_cjs = require('../chunk-MCWSUGB3.cjs');
|
|
4
|
-
require('../chunk-WQ3BYI7T.cjs');
|
|
5
|
-
require('../chunk-DBTAUI6C.cjs');
|
|
6
|
-
require('../chunk-IFW43ELT.cjs');
|
|
7
|
-
require('../chunk-SNTV45LH.cjs');
|
|
8
|
-
require('../chunk-D4SWRBUH.cjs');
|
|
9
|
-
require('../chunk-2AE6TMAX.cjs');
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
Object.defineProperty(exports, "STRICT_EXECUTION_CONTRACT_PROFILE", {
|
|
14
|
-
enumerable: true,
|
|
15
|
-
get: function () { return chunkMCWSUGB3_cjs.STRICT_EXECUTION_CONTRACT_PROFILE; }
|
|
16
|
-
});
|
|
17
|
-
Object.defineProperty(exports, "STRICT_EXECUTION_CONTRACT_PROFILE_ID", {
|
|
18
|
-
enumerable: true,
|
|
19
|
-
get: function () { return chunkMCWSUGB3_cjs.STRICT_EXECUTION_CONTRACT_PROFILE_ID; }
|
|
20
|
-
});
|
|
21
|
-
Object.defineProperty(exports, "executionContractProfile", {
|
|
22
|
-
enumerable: true,
|
|
23
|
-
get: function () { return chunkMCWSUGB3_cjs.executionContractProfile; }
|
|
24
|
-
});
|
|
25
|
-
//# sourceMappingURL=index.cjs.map
|
|
26
111
|
//# sourceMappingURL=index.cjs.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":[],"
|
|
1
|
+
{"version":3,"file":"index.cjs","names":["exportModuleManifest"],"sources":["../../certification/index.ts"],"sourcesContent":["import type { ActionCompletionMode } from \"../actions\";\nimport { exportModuleManifest, type ModuleManifest } from \"../manifest\";\nimport type { FabricModule } from \"../modules\";\n\n// ── Execution-contract certification ────────────────────────────────────────\n//\n// The base types keep the execution contract optional, because making it\n// mandatory is a break for every existing manifest. A deployment that wants\n// the guarantee applies a profile at certification instead: every governed\n// action declares all six dimensions, and any action that hands work to an\n// external system says how long it may wait. The profile is a seam a\n// vertical applies, not content the platform assumes.\n\nexport type ExecutionContractFindingCode =\n\t| \"missing_execution_contract\"\n\t| \"invalid_execution_dimension\"\n\t| \"missing_sensitivity\"\n\t| \"missing_completion_deadline\"\n\t| \"unexpected_completion_deadline\";\n\nexport interface ExecutionContractFinding {\n\tcode: ExecutionContractFindingCode;\n\tactionId: string;\n\tmessage: string;\n}\n\nexport interface ExecutionContractProfileOptions {\n\t/** Adapter and profile id. Defaults to the strict profile's id. */\n\tid?: string;\n\t/** Require `sensitivity`, which the base contract leaves optional. Defaults to true. */\n\trequireSensitivity?: boolean;\n\t/**\n\t * Completion modes that must declare `completionDeadlineMs`. Defaults to\n\t * both modes that hand work off, since without a deadline nothing sweeps a\n\t * callback that never comes.\n\t */\n\trequireDeadlineFor?: readonly ActionCompletionMode[];\n}\n\nexport interface ExecutionContractProfile {\n\treadonly id: string;\n\tvalidate(manifest: ModuleManifest): ExecutionContractFinding[];\n\tassert(subject: FabricModule<unknown> | ModuleManifest): void;\n\t/** For certification tooling: the compiler's conformance adapter shape. */\n\treadonly adapter: { id: string; evaluate(manifest: ModuleManifest): ExecutionContractFinding[] };\n}\n\nexport const STRICT_EXECUTION_CONTRACT_PROFILE_ID = \"fabric.execution-contract.strict\";\n\n/** The permitted values of each required dimension, mirrored from the action types. */\nfunction permittedDimensions(): ReadonlyArray<[string, ReadonlySet<unknown>]> {\n\treturn [\n\t\t[\"connectivity\", new Set([\"online-required\", \"offline-capturable\"])],\n\t\t[\"authorityMoment\", new Set([\"capture\", \"execution\", \"both\"])],\n\t\t[\"idempotency\", new Set([\"required\", \"supported\", \"prohibited\"])],\n\t\t[\"completion\", new Set([\"immediate\", \"accepted\", \"long-running\"])],\n\t\t[\"consistency\", new Set([\"authoritative-now\", \"provisional-until-reconciled\"])],\n\t];\n}\nconst permittedSensitivities = (): ReadonlySet<string> => new Set([\"public\", \"internal\", \"confidential\", \"restricted\"]);\n\nexport function executionContractProfile(options: ExecutionContractProfileOptions = {}): ExecutionContractProfile {\n\tconst id = options.id ?? STRICT_EXECUTION_CONTRACT_PROFILE_ID;\n\tconst requireSensitivity = options.requireSensitivity ?? true;\n\tconst requireDeadlineFor = new Set<ActionCompletionMode>(options.requireDeadlineFor ?? [\"accepted\", \"long-running\"]);\n\tconst dimensions = permittedDimensions();\n\tconst sensitivities = permittedSensitivities();\n\tconst validate = (manifest: ModuleManifest): ExecutionContractFinding[] => {\n\t\tconst findings: ExecutionContractFinding[] = [];\n\t\tfor (const action of manifest.actions) {\n\t\t\tconst contract = action.execution;\n\t\t\tif (!contract) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"missing_execution_contract\",\n\t\t\t\t\tactionId: action.actionId,\n\t\t\t\t\tmessage: `Action \"${action.actionId}\" declares no execution contract; connectivity, authorityMoment, idempotency, completion, and consistency are required.`,\n\t\t\t\t});\n\t\t\t\tcontinue;\n\t\t\t}\n\t\t\t// The contract's presence proves nothing about its content: a manifest\n\t\t\t// reaches certification without passing through the registry, so each\n\t\t\t// dimension is checked against its permitted values here.\n\t\t\tlet complete = true;\n\t\t\tfor (const [dimension, permitted] of dimensions) {\n\t\t\t\tconst value = (contract as unknown as Record<string, unknown>)[dimension];\n\t\t\t\tif (!permitted.has(value)) {\n\t\t\t\t\tcomplete = false;\n\t\t\t\t\tfindings.push({\n\t\t\t\t\t\tcode: \"invalid_execution_dimension\",\n\t\t\t\t\t\tactionId: action.actionId,\n\t\t\t\t\t\tmessage: `Action \"${action.actionId}\" ${value === undefined ? \"declares no\" : `declares an unknown`} ${dimension}${value === undefined ? \"\" : ` \"${String(value)}\"`}; permitted values are ${[...permitted].map((item) => `\"${String(item)}\"`).join(\", \")}.`,\n\t\t\t\t\t});\n\t\t\t\t}\n\t\t\t}\n\t\t\tif (contract.sensitivity !== undefined && !sensitivities.has(contract.sensitivity)) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"invalid_execution_dimension\",\n\t\t\t\t\tactionId: action.actionId,\n\t\t\t\t\tmessage: `Action \"${action.actionId}\" declares an unknown sensitivity \"${String(contract.sensitivity)}\"; permitted values are ${[...sensitivities].map((item) => `\"${item}\"`).join(\", \")}.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (!complete) continue;\n\t\t\tif (contract.completion === \"immediate\" && contract.completionDeadlineMs !== undefined) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"unexpected_completion_deadline\",\n\t\t\t\t\tactionId: action.actionId,\n\t\t\t\t\tmessage: `Action \"${action.actionId}\" declares immediate completion and a completionDeadlineMs; nothing external completes it.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (requireSensitivity && contract.sensitivity === undefined) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"missing_sensitivity\",\n\t\t\t\t\tactionId: action.actionId,\n\t\t\t\t\tmessage: `Action \"${action.actionId}\" declares no sensitivity; say whether its durable data is public, internal, confidential, or restricted.`,\n\t\t\t\t});\n\t\t\t}\n\t\t\tif (requireDeadlineFor.has(contract.completion) && !(typeof contract.completionDeadlineMs === \"number\" && contract.completionDeadlineMs > 0)) {\n\t\t\t\tfindings.push({\n\t\t\t\t\tcode: \"missing_completion_deadline\",\n\t\t\t\t\tactionId: action.actionId,\n\t\t\t\t\tmessage: `Action \"${action.actionId}\" declares ${contract.completion} completion and no completionDeadlineMs; a callback that never comes would never be noticed.`,\n\t\t\t\t});\n\t\t\t}\n\t\t}\n\t\treturn findings;\n\t};\n\treturn {\n\t\tid,\n\t\tvalidate,\n\t\tassert(subject) {\n\t\t\tconst manifest = isManifest(subject) ? subject : exportModuleManifest(subject);\n\t\t\tconst findings = validate(manifest);\n\t\t\tif (findings.length > 0) {\n\t\t\t\tthrow new Error(`Execution-contract profile \"${id}\" failed for \"${manifest.namespace}\":\\n${findings.map((finding) => `- ${finding.message}`).join(\"\\n\")}`);\n\t\t\t}\n\t\t},\n\t\tadapter: { id, evaluate: validate },\n\t};\n}\n\n/** All six dimensions on every action, and a deadline wherever work is handed off. */\nexport const STRICT_EXECUTION_CONTRACT_PROFILE: ExecutionContractProfile = executionContractProfile();\n\nfunction isManifest(subject: FabricModule<unknown> | ModuleManifest): subject is ModuleManifest {\n\treturn typeof (subject as ModuleManifest).manifestVersion === \"number\" && Array.isArray((subject as ModuleManifest).actions);\n}\n"],"mappings":"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"}
|
|
@@ -1,43 +1,37 @@
|
|
|
1
|
-
import { ActionCompletionMode } from
|
|
2
|
-
import {
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
type ExecutionContractFindingCode = "missing_execution_contract" | "invalid_execution_dimension" | "missing_sensitivity" | "missing_completion_deadline" | "unexpected_completion_deadline";
|
|
11
|
-
interface ExecutionContractFinding {
|
|
12
|
-
code: ExecutionContractFindingCode;
|
|
13
|
-
actionId: string;
|
|
14
|
-
message: string;
|
|
1
|
+
import { ActionCompletionMode } from "../actions/index.cjs";
|
|
2
|
+
import { FabricModule } from "../modules/index.cjs";
|
|
3
|
+
import { ModuleManifest } from "../manifest/index.cjs";
|
|
4
|
+
//#region certification/index.d.ts
|
|
5
|
+
export type ExecutionContractFindingCode = "missing_execution_contract" | "invalid_execution_dimension" | "missing_sensitivity" | "missing_completion_deadline" | "unexpected_completion_deadline";
|
|
6
|
+
export interface ExecutionContractFinding {
|
|
7
|
+
code: ExecutionContractFindingCode;
|
|
8
|
+
actionId: string;
|
|
9
|
+
message: string;
|
|
15
10
|
}
|
|
16
|
-
interface ExecutionContractProfileOptions {
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
11
|
+
export interface ExecutionContractProfileOptions {
|
|
12
|
+
/** Adapter and profile id. Defaults to the strict profile's id. */
|
|
13
|
+
id?: string;
|
|
14
|
+
/** Require `sensitivity`, which the base contract leaves optional. Defaults to true. */
|
|
15
|
+
requireSensitivity?: boolean;
|
|
16
|
+
/**
|
|
17
|
+
* Completion modes that must declare `completionDeadlineMs`. Defaults to
|
|
18
|
+
* both modes that hand work off, since without a deadline nothing sweeps a
|
|
19
|
+
* callback that never comes.
|
|
20
|
+
*/
|
|
21
|
+
requireDeadlineFor?: readonly ActionCompletionMode[];
|
|
27
22
|
}
|
|
28
|
-
interface ExecutionContractProfile {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
23
|
+
export interface ExecutionContractProfile {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
validate(manifest: ModuleManifest): ExecutionContractFinding[];
|
|
26
|
+
assert(subject: FabricModule<unknown> | ModuleManifest): void;
|
|
27
|
+
/** For certification tooling: the compiler's conformance adapter shape. */
|
|
28
|
+
readonly adapter: {
|
|
29
|
+
id: string;
|
|
30
|
+
evaluate(manifest: ModuleManifest): ExecutionContractFinding[];
|
|
31
|
+
};
|
|
37
32
|
}
|
|
38
|
-
declare const STRICT_EXECUTION_CONTRACT_PROFILE_ID = "fabric.execution-contract.strict";
|
|
39
|
-
declare function executionContractProfile(options?: ExecutionContractProfileOptions): ExecutionContractProfile;
|
|
33
|
+
export declare const STRICT_EXECUTION_CONTRACT_PROFILE_ID = "fabric.execution-contract.strict";
|
|
34
|
+
export declare function executionContractProfile(options?: ExecutionContractProfileOptions): ExecutionContractProfile;
|
|
40
35
|
/** All six dimensions on every action, and a deadline wherever work is handed off. */
|
|
41
|
-
declare const STRICT_EXECUTION_CONTRACT_PROFILE: ExecutionContractProfile;
|
|
42
|
-
|
|
43
|
-
export { type ExecutionContractFinding, type ExecutionContractFindingCode, type ExecutionContractProfile, type ExecutionContractProfileOptions, STRICT_EXECUTION_CONTRACT_PROFILE, STRICT_EXECUTION_CONTRACT_PROFILE_ID, executionContractProfile };
|
|
36
|
+
export declare const STRICT_EXECUTION_CONTRACT_PROFILE: ExecutionContractProfile;
|
|
37
|
+
//#endregion
|