@fabricorg/platform 1.7.0 → 1.8.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (59) hide show
  1. package/CHANGELOG.md +56 -0
  2. package/README.md +214 -3
  3. package/dist/actions/index.cjs +6 -6
  4. package/dist/actions/index.d.cts +9 -2
  5. package/dist/actions/index.d.ts +9 -2
  6. package/dist/actions/index.js +1 -1
  7. package/dist/adapters/index.cjs +33 -9
  8. package/dist/adapters/index.d.cts +388 -1
  9. package/dist/adapters/index.d.ts +388 -1
  10. package/dist/adapters/index.js +1 -1
  11. package/dist/chunk-5FOCPRTR.js +511 -0
  12. package/dist/chunk-5FOCPRTR.js.map +1 -0
  13. package/dist/{chunk-USDLP4E7.cjs → chunk-5IVFPWK6.cjs} +4 -4
  14. package/dist/{chunk-USDLP4E7.cjs.map → chunk-5IVFPWK6.cjs.map} +1 -1
  15. package/dist/chunk-6HY35TKB.cjs +491 -0
  16. package/dist/chunk-6HY35TKB.cjs.map +1 -0
  17. package/dist/chunk-6UGEIDLC.cjs +26 -0
  18. package/dist/chunk-6UGEIDLC.cjs.map +1 -0
  19. package/dist/chunk-BJGZE3GE.js +20 -0
  20. package/dist/chunk-BJGZE3GE.js.map +1 -0
  21. package/dist/{chunk-X3GHYMAJ.cjs → chunk-CRZXTZ36.cjs} +2 -22
  22. package/dist/chunk-CRZXTZ36.cjs.map +1 -0
  23. package/dist/{chunk-DCC3UIUJ.js → chunk-GFU7BGEJ.js} +3 -3
  24. package/dist/{chunk-DCC3UIUJ.js.map → chunk-GFU7BGEJ.js.map} +1 -1
  25. package/dist/chunk-HEYMMVDP.js +480 -0
  26. package/dist/chunk-HEYMMVDP.js.map +1 -0
  27. package/dist/chunk-IF6NJORI.cjs +526 -0
  28. package/dist/chunk-IF6NJORI.cjs.map +1 -0
  29. package/dist/{chunk-6QX4I45I.js → chunk-PIDZQAEL.js} +2 -2
  30. package/dist/{chunk-6QX4I45I.js.map → chunk-PIDZQAEL.js.map} +1 -1
  31. package/dist/{chunk-ATWWZTRC.js → chunk-TYNIFC7J.js} +3 -18
  32. package/dist/chunk-TYNIFC7J.js.map +1 -0
  33. package/dist/{chunk-XCAOO6KG.cjs → chunk-UGWGHTNC.cjs} +2 -2
  34. package/dist/{chunk-XCAOO6KG.cjs.map → chunk-UGWGHTNC.cjs.map} +1 -1
  35. package/dist/evidence/index.cjs +45 -1
  36. package/dist/evidence/index.d.cts +187 -1
  37. package/dist/evidence/index.d.ts +187 -1
  38. package/dist/evidence/index.js +3 -1
  39. package/dist/governance/index.d.cts +1 -0
  40. package/dist/governance/index.d.ts +1 -0
  41. package/dist/index.cjs +124 -59
  42. package/dist/index.d.cts +2 -2
  43. package/dist/index.d.ts +2 -2
  44. package/dist/index.js +7 -6
  45. package/dist/privacy/index.cjs +19 -18
  46. package/dist/privacy/index.js +2 -1
  47. package/dist/testing/index.cjs +5 -5
  48. package/dist/testing/index.js +2 -2
  49. package/package.json +1 -1
  50. package/dist/chunk-ATWWZTRC.js.map +0 -1
  51. package/dist/chunk-FAG2RTPM.js +0 -120
  52. package/dist/chunk-FAG2RTPM.js.map +0 -1
  53. package/dist/chunk-OZLZHISS.js +0 -3
  54. package/dist/chunk-OZLZHISS.js.map +0 -1
  55. package/dist/chunk-PG5LYTUX.cjs +0 -4
  56. package/dist/chunk-PG5LYTUX.cjs.map +0 -1
  57. package/dist/chunk-X3GHYMAJ.cjs.map +0 -1
  58. package/dist/chunk-XZQZQ5SW.cjs +0 -129
  59. package/dist/chunk-XZQZQ5SW.cjs.map +0 -1
@@ -1,120 +0,0 @@
1
- // adapters/index.ts
2
- function adapterKey(adapterType, operation) {
3
- return `${adapterType}:${operation}`;
4
- }
5
- var MissingAdapterRegistrationError = class extends Error {
6
- constructor(adapterType, operation) {
7
- super(`No adapter registered for adapterType "${adapterType}" and operation "${operation}"`);
8
- this.name = "MissingAdapterRegistrationError";
9
- }
10
- };
11
- var AdapterRegistry = class {
12
- adapters = /* @__PURE__ */ new Map();
13
- register(adapter) {
14
- const key = adapterKey(adapter.adapterType, adapter.operation);
15
- if (this.adapters.has(key)) {
16
- throw new Error(
17
- `Adapter already registered for adapterType "${adapter.adapterType}" and operation "${adapter.operation}"`
18
- );
19
- }
20
- this.adapters.set(key, adapter);
21
- }
22
- resolve(adapterType, operation) {
23
- return this.adapters.get(adapterKey(adapterType, operation));
24
- }
25
- require(adapterType, operation) {
26
- const adapter = this.resolve(adapterType, operation);
27
- if (!adapter) {
28
- throw new MissingAdapterRegistrationError(adapterType, operation);
29
- }
30
- return adapter;
31
- }
32
- };
33
- var DEFAULT_RETRY_POLICY = {
34
- maxAttempts: 3,
35
- initialDelayMs: 100,
36
- backoffMultiplier: 2,
37
- maxDelayMs: 1e3
38
- };
39
- var NO_RETRY_POLICY = {
40
- idempotent: false,
41
- maxAttempts: 1,
42
- initialDelayMs: 0,
43
- backoffMultiplier: 1,
44
- maxDelayMs: 0
45
- };
46
- function resolveAdapterRetryPolicy(policy, defaultIdempotent) {
47
- const idempotent = policy?.idempotent ?? defaultIdempotent;
48
- if (!idempotent) {
49
- return NO_RETRY_POLICY;
50
- }
51
- return {
52
- idempotent: true,
53
- maxAttempts: Math.max(1, Math.min(policy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts, 5)),
54
- initialDelayMs: Math.max(0, policy?.initialDelayMs ?? DEFAULT_RETRY_POLICY.initialDelayMs),
55
- backoffMultiplier: Math.max(
56
- 1,
57
- policy?.backoffMultiplier ?? DEFAULT_RETRY_POLICY.backoffMultiplier
58
- ),
59
- maxDelayMs: Math.max(0, policy?.maxDelayMs ?? DEFAULT_RETRY_POLICY.maxDelayMs)
60
- };
61
- }
62
- function getRetryDelayMs(attempt, policy) {
63
- const exponentialDelay = policy.initialDelayMs * policy.backoffMultiplier ** Math.max(0, attempt - 1);
64
- return Math.min(exponentialDelay, policy.maxDelayMs);
65
- }
66
- function classifyAdapterOutcome(result) {
67
- if (result.outcome) {
68
- assertAdapterOutcomeConsistency(result);
69
- return result.outcome;
70
- }
71
- return result.success ? "success" : "transient_failure";
72
- }
73
- function shouldRetryAdapterOutcome(kind, idempotent) {
74
- return kind === "transient_failure" && idempotent;
75
- }
76
- function assertAdapterOutcomeConsistency(result) {
77
- if (result.success && result.outcome && result.outcome !== "success") {
78
- throw new Error(
79
- `Adapter returned success=true with contradictory outcome "${result.outcome}"; a successful result must not declare a non-success outcome.`
80
- );
81
- }
82
- }
83
- async function executeWithAdapterRetry(options) {
84
- const policy = resolveAdapterRetryPolicy(options.policy, options.defaultIdempotent);
85
- const sleep = options.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
86
- let lastError;
87
- for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {
88
- try {
89
- const result = await options.execute(attempt, policy.maxAttempts);
90
- if (options.isSuccessful(result)) {
91
- await options.onAttempt?.({ attempt, result, willRetry: false });
92
- return result;
93
- }
94
- lastError = options.getError(result) ?? "Adapter returned unsuccessful result";
95
- const outcome = options.classifyOutcome ? options.classifyOutcome(result) : "transient_failure";
96
- const willRetry = shouldRetryAdapterOutcome(outcome, policy.idempotent) && attempt < policy.maxAttempts;
97
- const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
98
- await options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });
99
- if (!willRetry) {
100
- return result;
101
- }
102
- await sleep(nextDelayMs ?? 0);
103
- } catch (error) {
104
- lastError = error instanceof Error ? error.message : String(error);
105
- const thrownOutcome = options.classifyThrownError ? options.classifyThrownError(error) : "transient_failure";
106
- const willRetry = shouldRetryAdapterOutcome(thrownOutcome, policy.idempotent) && attempt < policy.maxAttempts;
107
- const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
108
- await options.onAttempt?.({ attempt, error: lastError, willRetry, nextDelayMs });
109
- if (!willRetry) {
110
- throw error;
111
- }
112
- await sleep(nextDelayMs ?? 0);
113
- }
114
- }
115
- throw new Error(lastError ?? "Adapter retry exhausted");
116
- }
117
-
118
- export { AdapterRegistry, MissingAdapterRegistrationError, assertAdapterOutcomeConsistency, classifyAdapterOutcome, executeWithAdapterRetry, getRetryDelayMs, resolveAdapterRetryPolicy, shouldRetryAdapterOutcome };
119
- //# sourceMappingURL=chunk-FAG2RTPM.js.map
120
- //# sourceMappingURL=chunk-FAG2RTPM.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../adapters/index.ts"],"names":[],"mappings":"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","file":"chunk-FAG2RTPM.js","sourcesContent":["export 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\nexport interface AdapterCircuitBreakerConfig {\n\tmode: \"monitor\" | \"enforce\";\n\tfailureThreshold: number;\n\twindowMs: number;\n\tcooldownMs: number;\n\tminimumSamples?: number;\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}\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\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\tlet lastError: string | undefined;\n\n\tfor (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {\n\t\ttry {\n\t\t\tconst result = await options.execute(attempt, policy.maxAttempts);\n\t\t\tif (options.isSuccessful(result)) {\n\t\t\t\tawait options.onAttempt?.({ attempt, result, willRetry: false });\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tlastError = options.getError(result) ?? \"Adapter returned unsuccessful result\";\n\t\t\tconst outcome = options.classifyOutcome\n\t\t\t\t? options.classifyOutcome(result)\n\t\t\t\t: \"transient_failure\" as const;\n\t\t\tconst willRetry =\n\t\t\t\tshouldRetryAdapterOutcome(outcome, policy.idempotent) && attempt < policy.maxAttempts;\n\t\t\tconst nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : undefined;\n\t\t\tawait options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });\n\n\t\t\tif (!willRetry) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tawait sleep(nextDelayMs ?? 0);\n\t\t} catch (error) {\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\tconst willRetry =\n\t\t\t\tshouldRetryAdapterOutcome(thrownOutcome, policy.idempotent) && attempt < policy.maxAttempts;\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 (!willRetry) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tawait sleep(nextDelayMs ?? 0);\n\t\t}\n\t}\n\n\tthrow new Error(lastError ?? \"Adapter retry exhausted\");\n}\n"]}
@@ -1,3 +0,0 @@
1
-
2
- //# sourceMappingURL=chunk-OZLZHISS.js.map
3
- //# sourceMappingURL=chunk-OZLZHISS.js.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-OZLZHISS.js"}
@@ -1,4 +0,0 @@
1
- 'use strict';
2
-
3
- //# sourceMappingURL=chunk-PG5LYTUX.cjs.map
4
- //# sourceMappingURL=chunk-PG5LYTUX.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":[],"names":[],"mappings":"","file":"chunk-PG5LYTUX.cjs"}
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../privacy/engine.ts","../privacy/index.ts"],"names":["createHash"],"mappings":";;;;;AAWO,IAAM,4BAAA,GAA+B;AAgE5C,SAAS,aAAa,GAAA,EAAqB;AAC1C,EAAA,OAAO,GAAA,CAAI,OAAA,CAAQ,eAAA,EAAiB,EAAE,EAAE,WAAA,EAAY;AACrD;AAEO,SAAS,eAAe,KAAA,EAAwB;AACtD,EAAA,OAAOA,iBAAA,CAAW,QAAQ,CAAA,CAAE,MAAA,CAAO,IAAA,CAAK,UAAU,KAAK,CAAC,CAAA,CAAE,MAAA,CAAO,KAAK,CAAA;AACvE;AAEA,SAAS,iBAAA,CACR,KAAA,EACA,OAAA,EACA,SAAA,EACS;AACT,EAAA,MAAM,KAAA,GAAQ,GAAG,OAAA,CAAQ,QAAQ,IAAI,OAAA,CAAQ,OAAA,IAAW,QAAQ,CAAA,CAAA,EAAI,SAAS,CAAA,CAAA;AAC7E,EAAA,OAAO,CAAA,IAAA,EAAOA,kBAAW,QAAQ,CAAA,CAC/B,OAAO,CAAA,EAAG,OAAA,CAAQ,aAAA,IAAiB,4BAA4B,CAAA,CAAA,EAAI,KAAK,IAAI,MAAA,CAAO,KAAK,CAAC,CAAA,CAAE,CAAA,CAC3F,MAAA,CAAO,KAAK,CAAA,CACZ,KAAA,CAAM,CAAA,EAAG,EAAE,CAAC,CAAA,CAAA;AACf;AAEA,SAAS,UAAU,KAAA,EAA+B;AACjD,EAAA,IAAI,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AAC1C,IAAA,OAAO,IAAA;AAAA,EACR;AAEA,EAAA,MAAM,WAAA,GAAc,OAAO,KAAK,CAAA;AAChC,EAAA,IAAI,WAAA,CAAY,UAAU,CAAA,EAAG;AAC5B,IAAA,OAAO,MAAA;AAAA,EACR;AAEA,EAAA,OAAO,CAAA,EAAG,GAAA,CAAI,MAAA,CAAO,IAAA,CAAK,IAAI,WAAA,CAAY,MAAA,GAAS,CAAA,EAAG,CAAC,CAAC,CAAC,CAAA,EAAG,WAAA,CAAY,KAAA,CAAM,EAAE,CAAC,CAAA,CAAA;AAClF;AAEA,SAAS,gBAAgB,KAAA,EAAyB;AACjD,EAAA,IAAI,OAAO,UAAU,QAAA,EAAU;AAC9B,IAAA,OAAO,IAAA,CAAK,KAAA,CAAM,KAAA,GAAQ,GAAI,CAAA,GAAI,GAAA;AAAA,EACnC;AAEA,EAAA,IAAI,OAAO,KAAA,KAAU,QAAA,IAAY,oBAAA,CAAqB,IAAA,CAAK,KAAK,CAAA,EAAG;AAClE,IAAA,OAAO,CAAA,EAAG,KAAA,CAAM,KAAA,CAAM,CAAA,EAAG,CAAC,CAAC,CAAA,EAAA,CAAA;AAAA,EAC5B;AAEA,EAAA,OAAO,IAAA;AACR;AAEA,SAAS,WAAA,CACR,KAAA,EACA,MAAA,EACA,OAAA,EACA,IAAA,EACU;AACV,EAAA,QAAQ,MAAA;AAAQ,IACf,KAAK,MAAA;AACJ,MAAA,OAAO,MAAA;AAAA,IACR,KAAK,SAAA;AACJ,MAAA,OAAO,IAAA;AAAA,IACR,KAAK,MAAA;AACJ,MAAA,OAAO,UAAU,KAAK,CAAA;AAAA,IACvB,KAAK,MAAA;AACJ,MAAA,OAAO,CAAA,OAAA,EAAU,cAAA,CAAe,KAAK,CAAC,CAAA,CAAA;AAAA,IACvC,KAAK,UAAA;AACJ,MAAA,OAAO,iBAAA,CAAkB,KAAA,EAAO,OAAA,EAAS,IAAI,CAAA;AAAA,IAC9C,KAAK,YAAA;AACJ,MAAA,OAAO,gBAAgB,KAAK,CAAA;AAAA;AAE/B;AAEA,SAAS,aAAA,CAAc,QAAA,EAA+C,IAAA,EAAc,GAAA,EAAoD;AACvI,EAAA,MAAM,cAAA,GAAiB,aAAa,IAAI,CAAA;AACxC,EAAA,MAAM,aAAA,GAAgB,GAAA,GAAM,YAAA,CAAa,GAAG,CAAA,GAAI,MAAA;AAEhD,EAAA,OAAO,QAAA,CAAS,IAAA,CAAK,CAAC,MAAA,KAAW;AAChC,IAAA,MAAM,eAAA,GAAkB,YAAA,CAAa,MAAA,CAAO,KAAK,CAAA;AACjD,IAAA,IAAI,MAAA,CAAO,UAAU,KAAA,EAAO;AAC3B,MAAA,OAAO,eAAA,KAAoB,aAAA;AAAA,IAC5B;AAEA,IAAA,OAAO,eAAA,KAAoB,cAAA;AAAA,EAC5B,CAAC,CAAA;AACF;AAEA,SAAS,cAAc,KAAA,EAAqC;AAC3D,EAAA,OACC,OAAA,CAAQ,KAAK,CAAA,IAAK,OAAO,KAAA,KAAU,QAAA,IAAY,CAAC,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,IAAK,EAAE,KAAA,YAAiB,IAAA,CAAA;AAE7F;AAEA,SAAS,mBACR,KAAA,EACA,OAAA,EACA,WACA,IAAA,EACA,cAAA,EACA,UACA,GAAA,EACU;AACV,EAAA,MAAM,WAAA,GAAc,aAAA,CAAc,QAAA,EAAU,IAAA,EAAM,GAAG,CAAA;AACrD,EAAA,IAAI,WAAA,IAAe,KAAA,KAAU,IAAA,IAAQ,KAAA,KAAU,MAAA,EAAW;AACzD,IAAA,cAAA,CAAe,IAAA,CAAK;AAAA,MACnB,SAAA,EAAW,IAAA;AAAA,MACX,QAAQ,WAAA,CAAY,MAAA;AAAA,MACpB,aAAA,EAAe,QAAQ,aAAA,IAAiB,4BAAA;AAAA,MACxC,OAAO,OAAA,CAAQ,KAAA;AAAA,MACf,aAAa,OAAA,CAAQ,UAAA,oBAAc,IAAI,IAAA,IAAQ,WAAA,EAAY;AAAA,MAC3D,QAAQ,OAAA,CAAQ,MAAA;AAAA,MAChB,SAAA;AAAA,MACA,cAAA,EAAgB,eAAe,KAAK;AAAA,KACpC,CAAA;AAED,IAAA,OAAO,WAAA,CAAY,KAAA,EAAO,WAAA,CAAY,MAAA,EAAQ,SAAS,IAAI,CAAA;AAAA,EAC5D;AAEA,EAAA,IAAI,KAAA,CAAM,OAAA,CAAQ,KAAK,CAAA,EAAG;AACzB,IAAA,OAAO,KAAA,CAAM,GAAA;AAAA,MAAI,CAAC,IAAA,EAAM,KAAA,KACvB,kBAAA,CAAmB,IAAA,EAAM,OAAA,EAAS,SAAA,EAAW,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,KAAK,CAAA,CAAA,CAAA,EAAK,gBAAgB,QAAQ;AAAA,KAC3F;AAAA,EACD;AAEA,EAAA,IAAI,CAAC,aAAA,CAAc,KAAK,CAAA,EAAG;AAC1B,IAAA,OAAO,KAAA;AAAA,EACR;AAEA,EAAA,MAAM,SAAqB,EAAC;AAC5B,EAAA,KAAA,MAAW,CAAC,QAAA,EAAU,UAAU,KAAK,MAAA,CAAO,OAAA,CAAQ,KAAK,CAAA,EAAG;AAC3D,IAAA,IAAI,aAAa,UAAA,EAAY;AAC5B,MAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,UAAA;AACnB,MAAA;AAAA,IACD;AAEA,IAAA,MAAM,UAAA,GAAa,kBAAA;AAAA,MAClB,UAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA;AAAA,MACA,CAAA,EAAG,IAAI,CAAA,CAAA,EAAI,QAAQ,CAAA,CAAA;AAAA,MACnB,cAAA;AAAA,MACA,QAAA;AAAA,MACA;AAAA,KACD;AAEA,IAAA,IAAI,eAAe,MAAA,EAAW;AAC7B,MAAA,MAAA,CAAO,QAAQ,CAAA,GAAI,UAAA;AAAA,IACpB;AAAA,EACD;AAEA,EAAA,OAAO,MAAA;AACR;AAEA,SAAS,aAAA,CACR,OAAA,EACA,SAAA,EACA,cAAA,EACA,kBAAA,EACwB;AACxB,EAAA,OAAO;AAAA,IACN,cAAA,EAAgB,YAAA;AAAA,IAChB,aAAA,EAAe,QAAQ,aAAA,IAAiB,4BAAA;AAAA,IACxC,OAAO,OAAA,CAAQ,KAAA;AAAA,IACf,aAAa,OAAA,CAAQ,UAAA,oBAAc,IAAI,IAAA,IAAQ,WAAA,EAAY;AAAA,IAC3D,QAAQ,OAAA,CAAQ,MAAA;AAAA,IAChB,SAAA;AAAA,IACA,cAAA;AAAA,IACA,kBAAA,EAAoB,CAAC,GAAG,kBAAkB;AAAA,GAC3C;AACD;AAEO,IAAM,gBAAN,MAAoB;AAAA,EAC1B,WAAA,CAAY,KAAA,EAAgB,MAAA,EAAyB,OAAA,EAA+B,IAAA,EAAuB;AAC1G,IAAA,OAAO,WAAA,CAAY,KAAA,EAAO,MAAA,EAAQ,OAAA,EAAS,IAAI,CAAA;AAAA,EAChD;AAAA,EAEA,KAAK,KAAA,EAA+B;AACnC,IAAA,OAAO,UAAU,KAAK,CAAA;AAAA,EACvB;AAAA,EAEA,KAAK,KAAA,EAAwB;AAC5B,IAAA,OAAO,CAAA,OAAA,EAAU,cAAA,CAAe,KAAK,CAAC,CAAA,CAAA;AAAA,EACvC;AAAA,EAEA,QAAA,CAAS,KAAA,EAAgB,OAAA,EAA+B,IAAA,EAAsB;AAC7E,IAAA,OAAO,iBAAA,CAAkB,KAAA,EAAO,OAAA,EAAS,IAAI,CAAA;AAAA,EAC9C;AAAA,EAEA,WAAW,KAAA,EAAyB;AACnC,IAAA,OAAO,gBAAgB,KAAK,CAAA;AAAA,EAC7B;AACD;AAEO,IAAM,sBAAN,MAA0B;AAAA,EACvB,OAAA;AAAA,EAET,YAAY,MAAA,EAA6B;AACxC,IAAA,IAAA,CAAK,OAAA,GAAU;AAAA,MACd,MAAA,EAAQ,OAAO,MAAA,CAAO,GAAA,CAAI,CAAC,KAAA,MAAW,EAAE,GAAG,KAAA,EAAM,CAAE,CAAA;AAAA,MACnD,oBAAoB,CAAC,GAAI,MAAA,CAAO,kBAAA,IAAsB,EAAG;AAAA,KAC1D;AAAA,EACD;AAAA,EAEA,kBAAA,CACC,KAAA,EACA,OAAA,EACA,SAAA,EAC8B;AAC9B,IAAA,OAAO,IAAA,CAAK,wBAAA,CAAyB,KAAA,EAAO,OAAA,EAAS,WAAW,GAAG,CAAA;AAAA,EACpE;AAAA,EAEA,wBAAA,CACC,KAAA,EACA,OAAA,EACA,SAAA,EACA,QAAA,EAC8B;AAC9B,IAAA,MAAM,iBAA+C,EAAC;AACtD,IAAA,MAAM,eAAA,GAAkB,kBAAA;AAAA,MACvB,KAAA;AAAA,MACA,OAAA;AAAA,MACA,SAAA;AAAA,MACA,QAAA;AAAA,MACA,cAAA;AAAA,MACA,KAAK,OAAA,CAAQ;AAAA,KACd;AAEA,IAAA,OAAO;AAAA,MACN,KAAA,EAAO,eAAA;AAAA,MACP,QAAA,EAAU,cAAc,OAAA,EAAS,SAAA,EAAW,gBAAgB,IAAA,CAAK,OAAA,CAAQ,kBAAA,IAAsB,EAAE;AAAA,KAClG;AAAA,EACD;AAAA,EAEA,0BAAA,CACC,OACA,OAAA,EAC+B;AAC/B,IAAA,MAAM,SAAS,IAAA,CAAK,kBAAA,CAAmB,KAAA,CAAM,OAAA,EAAS,SAAS,aAAa,CAAA;AAC5E,IAAA,MAAM,UAAU,aAAA,CAAc,MAAA,CAAO,KAAK,CAAA,GACvC,EAAE,GAAG,MAAA,CAAO,KAAA,EAAO,UAAU,MAAA,CAAO,QAAA,KACpC,EAAE,KAAA,EAAO,OAAO,KAAA,EAAO,QAAA,EAAU,OAAO,QAAA,EAAS;AAEpD,IAAA,OAAO,EAAE,KAAA,EAAO,OAAA,EAAS,QAAA,EAAU,OAAO,QAAA,EAAS;AAAA,EACpD;AAAA,EAEA,uBAAA,CACC,QACA,OAAA,EAC6F;AAC7F,IAAA,MAAM,SAAS,IAAA,CAAK,kBAAA,CAAmB,MAAA,CAAO,MAAA,EAAQ,SAAS,iBAAiB,CAAA;AAChF,IAAA,MAAM,iBAAA,GAAoB;AAAA,MACzB,GAAI,aAAA,CAAc,MAAA,CAAO,iBAAiB,CAAA,GAAI,MAAA,CAAO,oBAAoB,EAAC;AAAA,MAC1E,wBAAwB,MAAA,CAAO;AAAA,KAChC;AACA,IAAA,MAAM,mBAAmB,aAAA,CAAc,MAAA,CAAO,KAAK,CAAA,GAChD,EAAE,GAAG,MAAA,CAAO,KAAA,EAAO,UAAU,MAAA,CAAO,QAAA,KACpC,EAAE,KAAA,EAAO,OAAO,KAAA,EAAO,QAAA,EAAU,OAAO,QAAA,EAAS;AAEpD,IAAA,OAAO;AAAA,MACN,KAAA,EAAO;AAAA,QACN,MAAA,EAAQ,gBAAA;AAAA,QACR,iBAAA;AAAA,QACA,UAAU,cAAA,CAAe,EAAE,MAAA,EAAQ,gBAAA,EAAkB,mBAAmB;AAAA,OACzE;AAAA,MACA,UAAU,MAAA,CAAO;AAAA,KAClB;AAAA,EACD;AAAA,EAEA,oCAAoC,KAAA,EASD;AAClC,IAAA,MAAM,WAAA,GAAc,KAAA,CAAM,WAAA,IAAe,EAAC;AAC1C,IAAA,MAAM,UAAA,GAAa,KAAA,CAAM,UAAA,IAAc,EAAC;AACxC,IAAA,MAAM,eAAA,GAAkB,KAAA,CAAM,eAAA,IAAmB,EAAC;AAClD,IAAA,MAAM,cAAA,GAAiB;AAAA,MACtB,GAAG,WAAA,CAAY,OAAA,CAAQ,CAAC,IAAA,KAAS,IAAA,CAAK,SAAS,cAAc,CAAA;AAAA,MAC7D,GAAG,UAAA,CAAW,OAAA,CAAQ,CAAC,IAAA,KAAS,IAAA,CAAK,SAAS,cAAc,CAAA;AAAA,MAC5D,GAAG,eAAA,CAAgB,OAAA,CAAQ,CAAC,IAAA,KAAS,IAAA,CAAK,SAAS,cAAc;AAAA,KAClE;AAEA,IAAA,OAAO;AAAA,MACN,SAAA,EAAW,sBAAA;AAAA,MACX,aAAA,EAAe,KAAA,CAAM,OAAA,CAAQ,aAAA,IAAiB,4BAAA;AAAA,MAC9C,KAAA,EAAO,MAAM,OAAA,CAAQ,KAAA;AAAA,MACrB,MAAA,EAAQ,MAAM,OAAA,CAAQ,MAAA;AAAA,MACtB,YAAY,KAAA,CAAM,OAAA,CAAQ,8BAAc,IAAI,IAAA,IAAQ,WAAA,EAAY;AAAA,MAChE,QAAA,EAAU,MAAM,OAAA,CAAQ,QAAA;AAAA,MACxB,OAAA,EAAS,KAAA,CAAM,OAAA,CAAQ,OAAA,IAAW,IAAA;AAAA,MAClC,MAAA,EAAQ;AAAA,QACP,aAAa,WAAA,CAAY,MAAA;AAAA,QACzB,YAAY,UAAA,CAAW,MAAA;AAAA,QACvB,iBAAiB,eAAA,CAAgB,MAAA;AAAA,QACjC,gBAAgB,cAAA,CAAe;AAAA,OAChC;AAAA,MACA,OAAA,EAAS;AAAA,QACR,GAAG,WAAA,CAAY,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,UAC7B,WAAA,EAAa,aAAA;AAAA,UACb,QAAA,EAAU,KAAK,KAAA,CAAM,EAAA;AAAA,UACrB,WAAA,EAAa,KAAK,KAAA,CAAM,WAAA;AAAA,UACxB,SAAA,EAAW,KAAK,KAAA,CAAM,SAAA;AAAA,UACtB,aAAA,EAAe,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,GAAA;AAAA,YAC3C,CAAC,EAAE,SAAA,EAAW,MAAA,EAAQ,gBAAe,MAAO;AAAA,cAC3C,SAAA;AAAA,cACA,MAAA;AAAA,cACA;AAAA,aACD;AAAA;AACD,SACD,CAAE,CAAA;AAAA,QACF,GAAG,UAAA,CAAW,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,UAC5B,WAAA,EAAa,YAAA;AAAA,UACb,QAAA,EAAU,KAAK,MAAA,CAAO,EAAA;AAAA,UACtB,aAAa,IAAA,CAAK,SAAA;AAAA,UAClB,SAAA,EAAW,KAAK,MAAA,CAAO,EAAA;AAAA,UACvB,aAAA,EAAe,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,GAAA;AAAA,YAC3C,CAAC,EAAE,SAAA,EAAW,MAAA,EAAQ,gBAAe,MAAO;AAAA,cAC3C,SAAA;AAAA,cACA,MAAA;AAAA,cACA;AAAA,aACD;AAAA;AACD,SACD,CAAE,CAAA;AAAA,QACF,GAAG,eAAA,CAAgB,GAAA,CAAI,CAAC,IAAA,MAAU;AAAA,UACjC,WAAA,EAAa,iBAAA;AAAA,UACb,QAAA,EAAU,KAAK,MAAA,CAAO,EAAA;AAAA,UACtB,aAAA,EAAe,IAAA,CAAK,QAAA,CAAS,cAAA,CAAe,GAAA;AAAA,YAC3C,CAAC,EAAE,SAAA,EAAW,MAAA,EAAQ,gBAAe,MAAO;AAAA,cAC3C,SAAA;AAAA,cACA,MAAA;AAAA,cACA;AAAA,aACD;AAAA;AACD,SACD,CAAE;AAAA,OACH;AAAA,MACA,oBAAoB,CAAC,GAAI,KAAK,OAAA,CAAQ,kBAAA,IAAsB,EAAG;AAAA,KAChE;AAAA,EACD;AACD;;;AC5ZO,IAAM,+BAAA,GAAkC;AAuBxC,SAAS,kBAAA,CACf,KAAA,EACA,OAAA,EACA,SAAA,EACA,MAAA,EACgD;AAChD,EAAA,OAAO,IAAI,mBAAA,CAAoB,MAAM,EAAE,kBAAA,CAAmB,KAAA,EAAO,SAAS,SAAS,CAAA;AACpF;AAEO,SAAS,0BAAA,CACf,KAAA,EACA,OAAA,EACA,MAAA,EACiD;AACjD,EAAA,OAAO,IAAI,mBAAA,CAAoB,MAAM,CAAA,CAAE,0BAAA,CAA2B,OAAO,OAAO,CAAA;AACjF;AAEO,SAAS,uBAAA,CACf,MAAA,EACA,OAAA,EACA,MAAA,EAC+G;AAC/G,EAAA,OAAO,IAAI,mBAAA,CAAoB,MAAM,CAAA,CAAE,uBAAA,CAAwB,QAAQ,OAAO,CAAA;AAC/E;AAEO,SAAS,mCAAA,CAAoC,OASjD,MAAA,EAAgF;AAClF,EAAA,OAAO,IAAI,mBAAA,CAAoB,MAAM,CAAA,CAAE,oCAAoC,KAAK,CAAA;AACjF","file":"chunk-X3GHYMAJ.cjs","sourcesContent":["import { createHash } from \"node:crypto\";\n\nimport type {\n\tAnonymizationContext,\n\tAnonymizationFieldMetadata,\n\tAnonymizationMetadata,\n\tAnonymizationResult,\n\tPlatformDataClass,\n\tRedactionMethod,\n} from \"./index\";\n\nexport const ANONYMIZATION_POLICY_VERSION = \"adr-026-platform-anonymization-v1\";\n\ntype JsonObject = Record<string, unknown>;\n\nexport interface AnonymizationFieldPolicy {\n\tmethod: RedactionMethod;\n\tmatch: \"key\" | \"path\";\n\tvalue: string;\n}\n\nexport interface AnonymizationPolicy {\n\tfields: readonly AnonymizationFieldPolicy[];\n\tpreservedSemantics?: readonly string[];\n}\n\nexport interface AssetEventLike {\n\tid: string;\n\ttenantId: string;\n\tspaceId: string;\n\teventType: string;\n\tsubjectType: string;\n\tsubjectId: string;\n\tactionInvocationId: string;\n\tpayload: unknown;\n\tsequence: number;\n\toccurredAt: Date;\n\trecordedAt: Date;\n\tcorrelationId: string;\n\tcausationId?: string | null;\n}\n\nexport interface EvidencePacketLike {\n\tid: string;\n\tpacket: unknown;\n\tredactionMetadata: unknown;\n\tchecksum: string;\n}\n\nexport interface AnonymizationLifecycleEvidence {\n\teventType: \"AnonymizationApplied\";\n\tpolicyVersion: string;\n\tjobId: string;\n\treason: string;\n\tappliedAt: string;\n\ttenantId: string;\n\tspaceId: string | null;\n\tcounts: {\n\t\tassetEvents: number;\n\t\treadModels: number;\n\t\tevidencePackets: number;\n\t\tredactedFields: number;\n\t};\n\trecords: Array<{\n\t\trecordClass: PlatformDataClass;\n\t\trecordId: string;\n\t\tsubjectType?: string;\n\t\tsubjectId?: string;\n\t\tfieldManifest: Array<\n\t\t\tPick<AnonymizationFieldMetadata, \"fieldPath\" | \"method\" | \"beforeChecksum\">\n\t\t>;\n\t}>;\n\tpreservedSemantics: string[];\n}\n\nfunction normalizeKey(key: string): string {\n\treturn key.replace(/[^a-zA-Z0-9]/g, \"\").toLowerCase();\n}\n\nexport function stableChecksum(value: unknown): string {\n\treturn createHash(\"sha256\").update(JSON.stringify(value)).digest(\"hex\");\n}\n\nfunction stableScopedToken(\n\tvalue: unknown,\n\tcontext: AnonymizationContext,\n\tfieldPath: string,\n): string {\n\tconst scope = `${context.tenantId}:${context.spaceId ?? \"global\"}:${fieldPath}`;\n\treturn `tok_${createHash(\"sha256\")\n\t\t.update(`${context.policyVersion ?? ANONYMIZATION_POLICY_VERSION}:${scope}:${String(value)}`)\n\t\t.digest(\"hex\")\n\t\t.slice(0, 24)}`;\n}\n\nfunction maskValue(value: unknown): string | null {\n\tif (value === null || value === undefined) {\n\t\treturn null;\n\t}\n\n\tconst stringValue = String(value);\n\tif (stringValue.length <= 4) {\n\t\treturn \"****\";\n\t}\n\n\treturn `${\"*\".repeat(Math.max(stringValue.length - 4, 4))}${stringValue.slice(-4)}`;\n}\n\nfunction generalizeValue(value: unknown): unknown {\n\tif (typeof value === \"number\") {\n\t\treturn Math.round(value / 1000) * 1000;\n\t}\n\n\tif (typeof value === \"string\" && /^\\d{5}(?:-\\d{4})?$/.test(value)) {\n\t\treturn `${value.slice(0, 3)}**`;\n\t}\n\n\treturn null;\n}\n\nfunction applyMethod(\n\tvalue: unknown,\n\tmethod: RedactionMethod,\n\tcontext: AnonymizationContext,\n\tpath: string,\n): unknown {\n\tswitch (method) {\n\t\tcase \"drop\":\n\t\t\treturn undefined;\n\t\tcase \"nullify\":\n\t\t\treturn null;\n\t\tcase \"mask\":\n\t\t\treturn maskValue(value);\n\t\tcase \"hash\":\n\t\t\treturn `sha256_${stableChecksum(value)}`;\n\t\tcase \"tokenize\":\n\t\t\treturn stableScopedToken(value, context, path);\n\t\tcase \"generalize\":\n\t\t\treturn generalizeValue(value);\n\t}\n}\n\nfunction policyForPath(policies: readonly AnonymizationFieldPolicy[], path: string, key?: string): AnonymizationFieldPolicy | undefined {\n\tconst normalizedPath = normalizeKey(path);\n\tconst normalizedKey = key ? normalizeKey(key) : undefined;\n\n\treturn policies.find((policy) => {\n\t\tconst normalizedValue = normalizeKey(policy.value);\n\t\tif (policy.match === \"key\") {\n\t\t\treturn normalizedValue === normalizedKey;\n\t\t}\n\n\t\treturn normalizedValue === normalizedPath;\n\t});\n}\n\nfunction isPlainObject(value: unknown): value is JsonObject {\n\treturn (\n\t\tBoolean(value) && typeof value === \"object\" && !Array.isArray(value) && !(value instanceof Date)\n\t);\n}\n\nfunction anonymizeRecursive(\n\tvalue: unknown,\n\tcontext: AnonymizationContext,\n\tdataClass: PlatformDataClass,\n\tpath: string,\n\tredactedFields: AnonymizationFieldMetadata[],\n\tpolicies: readonly AnonymizationFieldPolicy[],\n\tkey?: string,\n): unknown {\n\tconst fieldPolicy = policyForPath(policies, path, key);\n\tif (fieldPolicy && value !== null && value !== undefined) {\n\t\tredactedFields.push({\n\t\t\tfieldPath: path,\n\t\t\tmethod: fieldPolicy.method,\n\t\t\tpolicyVersion: context.policyVersion ?? ANONYMIZATION_POLICY_VERSION,\n\t\t\tjobId: context.jobId,\n\t\t\tredactedAt: (context.redactedAt ?? new Date()).toISOString(),\n\t\t\treason: context.reason,\n\t\t\tdataClass,\n\t\t\tbeforeChecksum: stableChecksum(value),\n\t\t});\n\n\t\treturn applyMethod(value, fieldPolicy.method, context, path);\n\t}\n\n\tif (Array.isArray(value)) {\n\t\treturn value.map((item, index) =>\n\t\t\tanonymizeRecursive(item, context, dataClass, `${path}[${index}]`, redactedFields, policies),\n\t\t);\n\t}\n\n\tif (!isPlainObject(value)) {\n\t\treturn value;\n\t}\n\n\tconst result: JsonObject = {};\n\tfor (const [childKey, childValue] of Object.entries(value)) {\n\t\tif (childKey === \"_privacy\") {\n\t\t\tresult[childKey] = childValue;\n\t\t\tcontinue;\n\t\t}\n\n\t\tconst anonymized = anonymizeRecursive(\n\t\t\tchildValue,\n\t\t\tcontext,\n\t\t\tdataClass,\n\t\t\t`${path}.${childKey}`,\n\t\t\tredactedFields,\n\t\t\tpolicies,\n\t\t\tchildKey,\n\t\t);\n\n\t\tif (anonymized !== undefined) {\n\t\t\tresult[childKey] = anonymized;\n\t\t}\n\t}\n\n\treturn result;\n}\n\nfunction buildMetadata(\n\tcontext: AnonymizationContext,\n\tdataClass: PlatformDataClass,\n\tredactedFields: AnonymizationFieldMetadata[],\n\tpreservedSemantics: readonly string[],\n): AnonymizationMetadata {\n\treturn {\n\t\tredactionState: \"anonymized\",\n\t\tpolicyVersion: context.policyVersion ?? ANONYMIZATION_POLICY_VERSION,\n\t\tjobId: context.jobId,\n\t\tredactedAt: (context.redactedAt ?? new Date()).toISOString(),\n\t\treason: context.reason,\n\t\tdataClass,\n\t\tredactedFields,\n\t\tpreservedSemantics: [...preservedSemantics],\n\t};\n}\n\nexport class FieldRedactor {\n\tredactField(value: unknown, method: RedactionMethod, context: AnonymizationContext, path: string): unknown {\n\t\treturn applyMethod(value, method, context, path);\n\t}\n\n\tmask(value: unknown): string | null {\n\t\treturn maskValue(value);\n\t}\n\n\thash(value: unknown): string {\n\t\treturn `sha256_${stableChecksum(value)}`;\n\t}\n\n\ttokenize(value: unknown, context: AnonymizationContext, path: string): string {\n\t\treturn stableScopedToken(value, context, path);\n\t}\n\n\tgeneralize(value: unknown): unknown {\n\t\treturn generalizeValue(value);\n\t}\n}\n\nexport class AnonymizationEngine {\n\treadonly #policy: AnonymizationPolicy;\n\n\tconstructor(policy: AnonymizationPolicy) {\n\t\tthis.#policy = {\n\t\t\tfields: policy.fields.map((field) => ({ ...field })),\n\t\t\tpreservedSemantics: [...(policy.preservedSemantics ?? [])],\n\t\t};\n\t}\n\n\tanonymizeJsonValue<TValue>(\n\t\tvalue: TValue,\n\t\tcontext: AnonymizationContext,\n\t\tdataClass: PlatformDataClass,\n\t): AnonymizationResult<TValue> {\n\t\treturn this.anonymizeJsonValueAtPath(value, context, dataClass, \"$\");\n\t}\n\n\tanonymizeJsonValueAtPath<TValue>(\n\t\tvalue: TValue,\n\t\tcontext: AnonymizationContext,\n\t\tdataClass: PlatformDataClass,\n\t\tbasePath: string,\n\t): AnonymizationResult<TValue> {\n\t\tconst redactedFields: AnonymizationFieldMetadata[] = [];\n\t\tconst anonymizedValue = anonymizeRecursive(\n\t\t\tvalue,\n\t\t\tcontext,\n\t\t\tdataClass,\n\t\t\tbasePath,\n\t\t\tredactedFields,\n\t\t\tthis.#policy.fields,\n\t\t) as TValue;\n\n\t\treturn {\n\t\t\tvalue: anonymizedValue,\n\t\t\tmetadata: buildMetadata(context, dataClass, redactedFields, this.#policy.preservedSemantics ?? []),\n\t\t};\n\t}\n\n\tanonymizeAssetEventPayload(\n\t\tevent: AssetEventLike,\n\t\tcontext: AnonymizationContext,\n\t): AnonymizationResult<unknown> {\n\t\tconst result = this.anonymizeJsonValue(event.payload, context, \"asset_event\");\n\t\tconst payload = isPlainObject(result.value)\n\t\t\t? { ...result.value, _privacy: result.metadata }\n\t\t\t: { value: result.value, _privacy: result.metadata };\n\n\t\treturn { value: payload, metadata: result.metadata };\n\t}\n\n\tanonymizeEvidencePacket(\n\t\tpacket: EvidencePacketLike,\n\t\tcontext: AnonymizationContext,\n\t): AnonymizationResult<Pick<EvidencePacketLike, \"packet\" | \"redactionMetadata\" | \"checksum\">> {\n\t\tconst result = this.anonymizeJsonValue(packet.packet, context, \"evidence_packet\");\n\t\tconst redactionMetadata = {\n\t\t\t...(isPlainObject(packet.redactionMetadata) ? packet.redactionMetadata : {}),\n\t\t\tlifecycleAnonymization: result.metadata,\n\t\t};\n\t\tconst anonymizedPacket = isPlainObject(result.value)\n\t\t\t? { ...result.value, _privacy: result.metadata }\n\t\t\t: { value: result.value, _privacy: result.metadata };\n\n\t\treturn {\n\t\t\tvalue: {\n\t\t\t\tpacket: anonymizedPacket,\n\t\t\t\tredactionMetadata,\n\t\t\t\tchecksum: stableChecksum({ packet: anonymizedPacket, redactionMetadata }),\n\t\t\t},\n\t\t\tmetadata: result.metadata,\n\t\t};\n\t}\n\n\tbuildAnonymizationLifecycleEvidence(input: {\n\t\tcontext: AnonymizationContext;\n\t\tassetEvents?: Array<{ event: AssetEventLike; metadata: AnonymizationMetadata }>;\n\t\treadModels?: Array<{\n\t\t\tmodelKind: string;\n\t\t\trecord: JsonObject & { id: string };\n\t\t\tmetadata: AnonymizationMetadata;\n\t\t}>;\n\t\tevidencePackets?: Array<{ packet: EvidencePacketLike; metadata: AnonymizationMetadata }>;\n\t}): AnonymizationLifecycleEvidence {\n\t\tconst assetEvents = input.assetEvents ?? [];\n\t\tconst readModels = input.readModels ?? [];\n\t\tconst evidencePackets = input.evidencePackets ?? [];\n\t\tconst redactedFields = [\n\t\t\t...assetEvents.flatMap((item) => item.metadata.redactedFields),\n\t\t\t...readModels.flatMap((item) => item.metadata.redactedFields),\n\t\t\t...evidencePackets.flatMap((item) => item.metadata.redactedFields),\n\t\t];\n\n\t\treturn {\n\t\t\teventType: \"AnonymizationApplied\",\n\t\t\tpolicyVersion: input.context.policyVersion ?? ANONYMIZATION_POLICY_VERSION,\n\t\t\tjobId: input.context.jobId,\n\t\t\treason: input.context.reason,\n\t\t\tappliedAt: (input.context.redactedAt ?? new Date()).toISOString(),\n\t\t\ttenantId: input.context.tenantId,\n\t\t\tspaceId: input.context.spaceId ?? null,\n\t\t\tcounts: {\n\t\t\t\tassetEvents: assetEvents.length,\n\t\t\t\treadModels: readModels.length,\n\t\t\t\tevidencePackets: evidencePackets.length,\n\t\t\t\tredactedFields: redactedFields.length,\n\t\t\t},\n\t\t\trecords: [\n\t\t\t\t...assetEvents.map((item) => ({\n\t\t\t\t\trecordClass: \"asset_event\" as PlatformDataClass,\n\t\t\t\t\trecordId: item.event.id,\n\t\t\t\t\tsubjectType: item.event.subjectType,\n\t\t\t\t\tsubjectId: item.event.subjectId,\n\t\t\t\t\tfieldManifest: item.metadata.redactedFields.map(\n\t\t\t\t\t\t({ fieldPath, method, beforeChecksum }) => ({\n\t\t\t\t\t\t\tfieldPath,\n\t\t\t\t\t\t\tmethod,\n\t\t\t\t\t\t\tbeforeChecksum,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t})),\n\t\t\t\t...readModels.map((item) => ({\n\t\t\t\t\trecordClass: \"read_model\" as PlatformDataClass,\n\t\t\t\t\trecordId: item.record.id,\n\t\t\t\t\tsubjectType: item.modelKind,\n\t\t\t\t\tsubjectId: item.record.id,\n\t\t\t\t\tfieldManifest: item.metadata.redactedFields.map(\n\t\t\t\t\t\t({ fieldPath, method, beforeChecksum }) => ({\n\t\t\t\t\t\t\tfieldPath,\n\t\t\t\t\t\t\tmethod,\n\t\t\t\t\t\t\tbeforeChecksum,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t})),\n\t\t\t\t...evidencePackets.map((item) => ({\n\t\t\t\t\trecordClass: \"evidence_packet\" as PlatformDataClass,\n\t\t\t\t\trecordId: item.packet.id,\n\t\t\t\t\tfieldManifest: item.metadata.redactedFields.map(\n\t\t\t\t\t\t({ fieldPath, method, beforeChecksum }) => ({\n\t\t\t\t\t\t\tfieldPath,\n\t\t\t\t\t\t\tmethod,\n\t\t\t\t\t\t\tbeforeChecksum,\n\t\t\t\t\t\t}),\n\t\t\t\t\t),\n\t\t\t\t})),\n\t\t\t],\n\t\t\tpreservedSemantics: [...(this.#policy.preservedSemantics ?? [])],\n\t\t};\n\t}\n}\n","export const PLATFORM_PRIVACY_POLICY_VERSION = \"fabric-platform-privacy-v1\";\n\nexport type RedactionMethod = \"nullify\" | \"mask\" | \"hash\" | \"tokenize\" | \"generalize\" | \"drop\";\n\nexport { ANONYMIZATION_POLICY_VERSION } from \"./engine\";\nexport {\n\tAnonymizationEngine,\n\tFieldRedactor,\n\tstableChecksum,\n\ttype AssetEventLike,\n\ttype EvidencePacketLike,\n\ttype AnonymizationLifecycleEvidence,\n\ttype AnonymizationFieldPolicy,\n\ttype AnonymizationPolicy,\n} from \"./engine\";\n\nimport {\n\tAnonymizationEngine,\n\ttype AssetEventLike,\n\ttype EvidencePacketLike,\n\ttype AnonymizationLifecycleEvidence,\n} from \"./engine\";\n\nexport function anonymizeJsonValue<TValue>(\n\tvalue: TValue,\n\tcontext: import(\"./index\").AnonymizationContext,\n\tdataClass: import(\"./index\").PlatformDataClass,\n\tpolicy: import(\"./engine\").AnonymizationPolicy,\n): import(\"./index\").AnonymizationResult<TValue> {\n\treturn new AnonymizationEngine(policy).anonymizeJsonValue(value, context, dataClass);\n}\n\nexport function anonymizeAssetEventPayload(\n\tevent: AssetEventLike,\n\tcontext: import(\"./index\").AnonymizationContext,\n\tpolicy: import(\"./engine\").AnonymizationPolicy,\n): import(\"./index\").AnonymizationResult<unknown> {\n\treturn new AnonymizationEngine(policy).anonymizeAssetEventPayload(event, context);\n}\n\nexport function anonymizeEvidencePacket(\n\tpacket: EvidencePacketLike,\n\tcontext: import(\"./index\").AnonymizationContext,\n\tpolicy: import(\"./engine\").AnonymizationPolicy,\n): import(\"./index\").AnonymizationResult<Pick<EvidencePacketLike, \"packet\" | \"redactionMetadata\" | \"checksum\">> {\n\treturn new AnonymizationEngine(policy).anonymizeEvidencePacket(packet, context);\n}\n\nexport function buildAnonymizationLifecycleEvidence(input: {\n\tcontext: import(\"./index\").AnonymizationContext;\n\tassetEvents?: Array<{ event: AssetEventLike; metadata: import(\"./index\").AnonymizationMetadata }>;\n\treadModels?: Array<{\n\t\tmodelKind: string;\n\t\trecord: Record<string, unknown> & { id: string };\n\t\tmetadata: import(\"./index\").AnonymizationMetadata;\n\t}>;\n\tevidencePackets?: Array<{ packet: EvidencePacketLike; metadata: import(\"./index\").AnonymizationMetadata }>;\n}, policy: import(\"./engine\").AnonymizationPolicy): AnonymizationLifecycleEvidence {\n\treturn new AnonymizationEngine(policy).buildAnonymizationLifecycleEvidence(input);\n}\n\nexport type PlatformDataClass =\n\t| \"asset_event\"\n\t| \"read_model\"\n\t| \"raw_payload\"\n\t| \"evidence_packet\"\n\t| \"action_evidence\"\n\t| \"access_event\";\n\nexport interface RedactionRule {\n\tfieldPath: string;\n\tmethod: RedactionMethod;\n\treason: string;\n\tdataClass?: PlatformDataClass;\n}\n\nexport interface DataClassificationRule {\n\tfieldPath: string;\n\tclassification: string;\n\tcontainsDirectIdentifier?: boolean;\n\tcontainsSensitiveData?: boolean;\n}\n\nexport interface AnonymizationContext {\n\ttenantId: string;\n\tspaceId?: string | null;\n\tjobId: string;\n\treason: string;\n\tredactedAt?: Date;\n\tpolicyVersion?: string;\n}\n\nexport interface AnonymizationFieldMetadata {\n\tfieldPath: string;\n\tmethod: RedactionMethod;\n\tpolicyVersion: string;\n\tjobId: string;\n\tredactedAt: string;\n\treason: string;\n\tdataClass: PlatformDataClass;\n\tbeforeChecksum: string;\n}\n\nexport interface AnonymizationMetadata {\n\tredactionState: \"anonymized\";\n\tpolicyVersion: string;\n\tjobId: string;\n\tredactedAt: string;\n\treason: string;\n\tdataClass: PlatformDataClass;\n\tredactedFields: AnonymizationFieldMetadata[];\n\tpreservedSemantics: string[];\n}\n\nexport interface AnonymizationResult<TValue> {\n\tvalue: TValue;\n\tmetadata: AnonymizationMetadata;\n}\n\nexport interface AnalyticsDataContractSource {\n\tname: string;\n\tprivacyClass:\n\t\t| \"raw\"\n\t\t| \"operational_pii\"\n\t\t| \"tenant_scoped_tokenized\"\n\t\t| \"anonymized\"\n\t\t| \"aggregated\"\n\t\t| \"differentially_minimized\";\n\tcontainsDirectIdentifiers?: boolean;\n\tcontainsGloballyStablePersonTokens?: boolean;\n\tanonymizationPolicyVersion?: string;\n\tminimumGroupSize?: number;\n}\n\nexport interface AnalyticsDataContract {\n\tcontractId: string;\n\tstatus: \"draft\" | \"accepted\" | \"deprecated\";\n\tcrossTenant: boolean;\n\tacceptedBy?: string;\n\tacceptedAt?: string;\n\tadrReference?: string;\n\tsources: AnalyticsDataContractSource[];\n}\n\nexport interface AnalyticsEligibilityDecision {\n\teligible: boolean;\n\tpolicyVersion: string;\n\treasons: string[];\n}\n\nexport interface RetentionRule {\n\tdataClass: PlatformDataClass;\n\tretainForDays: number;\n\tafterRetention: \"delete\" | \"anonymize\" | \"archive\";\n\tlegalHoldExempt?: boolean;\n}\n"]}
@@ -1,129 +0,0 @@
1
- 'use strict';
2
-
3
- // adapters/index.ts
4
- function adapterKey(adapterType, operation) {
5
- return `${adapterType}:${operation}`;
6
- }
7
- var MissingAdapterRegistrationError = class extends Error {
8
- constructor(adapterType, operation) {
9
- super(`No adapter registered for adapterType "${adapterType}" and operation "${operation}"`);
10
- this.name = "MissingAdapterRegistrationError";
11
- }
12
- };
13
- var AdapterRegistry = class {
14
- adapters = /* @__PURE__ */ new Map();
15
- register(adapter) {
16
- const key = adapterKey(adapter.adapterType, adapter.operation);
17
- if (this.adapters.has(key)) {
18
- throw new Error(
19
- `Adapter already registered for adapterType "${adapter.adapterType}" and operation "${adapter.operation}"`
20
- );
21
- }
22
- this.adapters.set(key, adapter);
23
- }
24
- resolve(adapterType, operation) {
25
- return this.adapters.get(adapterKey(adapterType, operation));
26
- }
27
- require(adapterType, operation) {
28
- const adapter = this.resolve(adapterType, operation);
29
- if (!adapter) {
30
- throw new MissingAdapterRegistrationError(adapterType, operation);
31
- }
32
- return adapter;
33
- }
34
- };
35
- var DEFAULT_RETRY_POLICY = {
36
- maxAttempts: 3,
37
- initialDelayMs: 100,
38
- backoffMultiplier: 2,
39
- maxDelayMs: 1e3
40
- };
41
- var NO_RETRY_POLICY = {
42
- idempotent: false,
43
- maxAttempts: 1,
44
- initialDelayMs: 0,
45
- backoffMultiplier: 1,
46
- maxDelayMs: 0
47
- };
48
- function resolveAdapterRetryPolicy(policy, defaultIdempotent) {
49
- const idempotent = policy?.idempotent ?? defaultIdempotent;
50
- if (!idempotent) {
51
- return NO_RETRY_POLICY;
52
- }
53
- return {
54
- idempotent: true,
55
- maxAttempts: Math.max(1, Math.min(policy?.maxAttempts ?? DEFAULT_RETRY_POLICY.maxAttempts, 5)),
56
- initialDelayMs: Math.max(0, policy?.initialDelayMs ?? DEFAULT_RETRY_POLICY.initialDelayMs),
57
- backoffMultiplier: Math.max(
58
- 1,
59
- policy?.backoffMultiplier ?? DEFAULT_RETRY_POLICY.backoffMultiplier
60
- ),
61
- maxDelayMs: Math.max(0, policy?.maxDelayMs ?? DEFAULT_RETRY_POLICY.maxDelayMs)
62
- };
63
- }
64
- function getRetryDelayMs(attempt, policy) {
65
- const exponentialDelay = policy.initialDelayMs * policy.backoffMultiplier ** Math.max(0, attempt - 1);
66
- return Math.min(exponentialDelay, policy.maxDelayMs);
67
- }
68
- function classifyAdapterOutcome(result) {
69
- if (result.outcome) {
70
- assertAdapterOutcomeConsistency(result);
71
- return result.outcome;
72
- }
73
- return result.success ? "success" : "transient_failure";
74
- }
75
- function shouldRetryAdapterOutcome(kind, idempotent) {
76
- return kind === "transient_failure" && idempotent;
77
- }
78
- function assertAdapterOutcomeConsistency(result) {
79
- if (result.success && result.outcome && result.outcome !== "success") {
80
- throw new Error(
81
- `Adapter returned success=true with contradictory outcome "${result.outcome}"; a successful result must not declare a non-success outcome.`
82
- );
83
- }
84
- }
85
- async function executeWithAdapterRetry(options) {
86
- const policy = resolveAdapterRetryPolicy(options.policy, options.defaultIdempotent);
87
- const sleep = options.sleep ?? ((delayMs) => new Promise((resolve) => setTimeout(resolve, delayMs)));
88
- let lastError;
89
- for (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {
90
- try {
91
- const result = await options.execute(attempt, policy.maxAttempts);
92
- if (options.isSuccessful(result)) {
93
- await options.onAttempt?.({ attempt, result, willRetry: false });
94
- return result;
95
- }
96
- lastError = options.getError(result) ?? "Adapter returned unsuccessful result";
97
- const outcome = options.classifyOutcome ? options.classifyOutcome(result) : "transient_failure";
98
- const willRetry = shouldRetryAdapterOutcome(outcome, policy.idempotent) && attempt < policy.maxAttempts;
99
- const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
100
- await options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });
101
- if (!willRetry) {
102
- return result;
103
- }
104
- await sleep(nextDelayMs ?? 0);
105
- } catch (error) {
106
- lastError = error instanceof Error ? error.message : String(error);
107
- const thrownOutcome = options.classifyThrownError ? options.classifyThrownError(error) : "transient_failure";
108
- const willRetry = shouldRetryAdapterOutcome(thrownOutcome, policy.idempotent) && attempt < policy.maxAttempts;
109
- const nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : void 0;
110
- await options.onAttempt?.({ attempt, error: lastError, willRetry, nextDelayMs });
111
- if (!willRetry) {
112
- throw error;
113
- }
114
- await sleep(nextDelayMs ?? 0);
115
- }
116
- }
117
- throw new Error(lastError ?? "Adapter retry exhausted");
118
- }
119
-
120
- exports.AdapterRegistry = AdapterRegistry;
121
- exports.MissingAdapterRegistrationError = MissingAdapterRegistrationError;
122
- exports.assertAdapterOutcomeConsistency = assertAdapterOutcomeConsistency;
123
- exports.classifyAdapterOutcome = classifyAdapterOutcome;
124
- exports.executeWithAdapterRetry = executeWithAdapterRetry;
125
- exports.getRetryDelayMs = getRetryDelayMs;
126
- exports.resolveAdapterRetryPolicy = resolveAdapterRetryPolicy;
127
- exports.shouldRetryAdapterOutcome = shouldRetryAdapterOutcome;
128
- //# sourceMappingURL=chunk-XZQZQ5SW.cjs.map
129
- //# sourceMappingURL=chunk-XZQZQ5SW.cjs.map
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../adapters/index.ts"],"names":[],"mappings":"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","file":"chunk-XZQZQ5SW.cjs","sourcesContent":["export 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\nexport interface AdapterCircuitBreakerConfig {\n\tmode: \"monitor\" | \"enforce\";\n\tfailureThreshold: number;\n\twindowMs: number;\n\tcooldownMs: number;\n\tminimumSamples?: number;\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}\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\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\tlet lastError: string | undefined;\n\n\tfor (let attempt = 1; attempt <= policy.maxAttempts; attempt++) {\n\t\ttry {\n\t\t\tconst result = await options.execute(attempt, policy.maxAttempts);\n\t\t\tif (options.isSuccessful(result)) {\n\t\t\t\tawait options.onAttempt?.({ attempt, result, willRetry: false });\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tlastError = options.getError(result) ?? \"Adapter returned unsuccessful result\";\n\t\t\tconst outcome = options.classifyOutcome\n\t\t\t\t? options.classifyOutcome(result)\n\t\t\t\t: \"transient_failure\" as const;\n\t\t\tconst willRetry =\n\t\t\t\tshouldRetryAdapterOutcome(outcome, policy.idempotent) && attempt < policy.maxAttempts;\n\t\t\tconst nextDelayMs = willRetry ? getRetryDelayMs(attempt, policy) : undefined;\n\t\t\tawait options.onAttempt?.({ attempt, result, error: lastError, willRetry, nextDelayMs });\n\n\t\t\tif (!willRetry) {\n\t\t\t\treturn result;\n\t\t\t}\n\n\t\t\tawait sleep(nextDelayMs ?? 0);\n\t\t} catch (error) {\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\tconst willRetry =\n\t\t\t\tshouldRetryAdapterOutcome(thrownOutcome, policy.idempotent) && attempt < policy.maxAttempts;\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 (!willRetry) {\n\t\t\t\tthrow error;\n\t\t\t}\n\n\t\t\tawait sleep(nextDelayMs ?? 0);\n\t\t}\n\t}\n\n\tthrow new Error(lastError ?? \"Adapter retry exhausted\");\n}\n"]}