@rotorsoft/act 1.32.16 → 1.32.18

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 (36) hide show
  1. package/dist/.tsbuildinfo +1 -1
  2. package/dist/@types/act.d.ts +10 -46
  3. package/dist/@types/act.d.ts.map +1 -1
  4. package/dist/@types/builders/builder-base.d.ts +1 -1
  5. package/dist/@types/builders/builder-base.d.ts.map +1 -1
  6. package/dist/@types/internal/autoclose-reaction.d.ts +0 -8
  7. package/dist/@types/internal/autoclose-reaction.d.ts.map +1 -1
  8. package/dist/@types/internal/close-cycle.d.ts +45 -3
  9. package/dist/@types/internal/close-cycle.d.ts.map +1 -1
  10. package/dist/@types/internal/config.d.ts +0 -6
  11. package/dist/@types/internal/config.d.ts.map +1 -1
  12. package/dist/@types/internal/drain-cycle.d.ts +1 -42
  13. package/dist/@types/internal/drain-cycle.d.ts.map +1 -1
  14. package/dist/@types/internal/event-sourcing.d.ts +2 -1
  15. package/dist/@types/internal/event-sourcing.d.ts.map +1 -1
  16. package/dist/@types/internal/index.d.ts +2 -2
  17. package/dist/@types/internal/index.d.ts.map +1 -1
  18. package/dist/@types/internal/sensitive.d.ts +0 -21
  19. package/dist/@types/internal/sensitive.d.ts.map +1 -1
  20. package/dist/@types/types/action.d.ts +15 -27
  21. package/dist/@types/types/action.d.ts.map +1 -1
  22. package/dist/@types/types/ports.d.ts +8 -20
  23. package/dist/@types/types/ports.d.ts.map +1 -1
  24. package/dist/{chunk-PZP5ZEZ4.js → chunk-QOSQI3CA.js} +2 -2
  25. package/dist/{chunk-JRTZGWVS.js → chunk-XSG2NW4J.js} +1 -1
  26. package/dist/{chunk-JRTZGWVS.js.map → chunk-XSG2NW4J.js.map} +1 -1
  27. package/dist/index.cjs +68 -110
  28. package/dist/index.cjs.map +1 -1
  29. package/dist/index.js +70 -112
  30. package/dist/index.js.map +1 -1
  31. package/dist/test/index.cjs.map +1 -1
  32. package/dist/test/index.js +2 -2
  33. package/dist/types/index.cjs.map +1 -1
  34. package/dist/types/index.js +1 -1
  35. package/package.json +1 -1
  36. /package/dist/{chunk-PZP5ZEZ4.js.map → chunk-QOSQI3CA.js.map} +0 -0
@@ -861,7 +861,7 @@ export interface Store extends Disposable, EventSource {
861
861
  *
862
862
  * **Prefer `Act.reset()` over calling this directly.** This primitive
863
863
  * only resets the store; it does not raise the orchestrator's internal
864
- * "needs drain" flag, so a settled `Act` instance will short-circuit and
864
+ * drain-armed flag, so a settled `Act` instance will short-circuit and
865
865
  * skip the replay. `Act.reset()` wraps this and arms the flag.
866
866
  *
867
867
  * Accepts either an explicit list of stream names or a
@@ -905,7 +905,7 @@ export interface Store extends Disposable, EventSource {
905
905
  *
906
906
  * **Prefer `Act.unblock()` over calling this directly.** Like
907
907
  * `reset()`, this primitive doesn't raise the orchestrator's internal
908
- * "needs drain" flag — a settled `Act` instance will short-circuit and
908
+ * drain-armed flag — a settled `Act` instance will short-circuit and
909
909
  * skip the resume. `Act.unblock()` wraps this and arms the flag.
910
910
  *
911
911
  * Only streams that were actually blocked at call time count toward
@@ -991,24 +991,12 @@ export interface Store extends Disposable, EventSource {
991
991
  * 2. Inserts a `__snapshot__` (when `snapshot` is provided) or
992
992
  * `__tombstone__` event as the sole event on the stream
993
993
  *
994
- * **Subscriptions are not touched.** This is purely event-log work, and
995
- * that is what lets a store keep its event log and its subscriptions on
996
- * different systems: every method belongs cleanly to one half, so a hybrid
997
- * routes rather than reimplements. Removing the subscription row
998
- * here was the one step that spanned both, and it forced such a store into
999
- * a distributed transaction it could not have.
1000
- *
1001
- * Nothing is lost by leaving the row. A retired stream's subscription is
1002
- * **inert**: the framework refuses commits on a tombstoned stream, so no
1003
- * scan can raise its work mark, so `at < correlated_at` never becomes true
1004
- * again and {@link claim} never returns it. What the row does keep is the
1005
- * final watermark of every consumer — a record of how far each got before
1006
- * the stream was retired, which outlives the events themselves.
1007
- *
1008
- * Operators who would rather reclaim the space can delete those rows on
1009
- * their own schedule; the production checklist carries the statement. It is
1010
- * housekeeping, not correctness, and deliberately not a framework concern.
1011
- *
994
+ * **Subscriptions are not touched**, so the event log and the
995
+ * subscriptions can live on different systems. A retired stream's
996
+ * subscription is inert (commits to a tombstoned stream are refused, so its
997
+ * work mark never rises and {@link claim} never returns it) and keeps each
998
+ * consumer's final watermark. Deleting those rows is optional housekeeping.
999
+
1012
1000
  * A **windowed** target (`before` set) is a pure prefix delete behind
1013
1001
  * a real snapshot the app wrote — no seed, no tombstone, and the
1014
1002
  * streams table is left untouched. The store finds the closest safe
@@ -1 +1 @@
1
- {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/types/ports.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"ports.d.ts","sourceRoot":"","sources":["../../../src/types/ports.ts"],"names":[],"mappings":"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"}
@@ -3,7 +3,7 @@ import {
3
3
  Environments,
4
4
  LogLevels,
5
5
  ValidationError
6
- } from "./chunk-JRTZGWVS.js";
6
+ } from "./chunk-XSG2NW4J.js";
7
7
 
8
8
  // src/adapters/console-logger.ts
9
9
  var LEVEL_VALUES = {
@@ -1380,4 +1380,4 @@ export {
1380
1380
  TOMBSTONE_EVENT,
1381
1381
  DEFAULT_LANE
1382
1382
  };
1383
- //# sourceMappingURL=chunk-PZP5ZEZ4.js.map
1383
+ //# sourceMappingURL=chunk-QOSQI3CA.js.map
@@ -280,4 +280,4 @@ export {
280
280
  Environments,
281
281
  LogLevels
282
282
  };
283
- //# sourceMappingURL=chunk-JRTZGWVS.js.map
283
+ //# sourceMappingURL=chunk-XSG2NW4J.js.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/types/errors.ts","../src/types/schemas.ts","../src/internal/sensitive.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n NonRetryableError: \"ERR_NON_RETRYABLE\",\n StoreError: \"ERR_STORE\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string;\n /** The invalid payload that failed validation */\n public readonly payload: any;\n /** Zod validation error details */\n public readonly details: any;\n\n constructor(target: string, payload: any, details: any) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n this.target = target;\n this.payload = payload;\n this.details = details;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n /** The action that was attempted */\n readonly action: TKey;\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>;\n /** The target stream and actor context */\n readonly target: Target<TActor>;\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>;\n /** Human-readable description of why the invariant failed */\n readonly description: string;\n\n constructor(\n action: TKey,\n payload: Readonly<TActions[TKey]>,\n target: Target<TActor>,\n snapshot: Snapshot<TState, TEvents>,\n description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n this.action = action;\n this.payload = payload;\n this.target = target;\n this.snapshot = snapshot;\n this.description = description;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n /** The stream that had the concurrent modification */\n public readonly stream: string;\n /** The actual current version in the store */\n public readonly lastVersion: number;\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[];\n /** The version number that was expected */\n public readonly expectedVersion: number;\n\n constructor(\n stream: string,\n lastVersion: number,\n events: Message<Schemas, keyof Schemas>[],\n expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n this.stream = stream;\n this.lastVersion = lastVersion;\n this.events = events;\n this.expectedVersion = expectedVersion;\n }\n}\n\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n /** The stream that is closed */\n public readonly stream: string;\n\n constructor(stream: string) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n this.stream = stream;\n }\n}\n\n/**\n * Thrown by a {@link Store} adapter when an infrastructure operation fails\n * for a reason that is *not* a domain condition — a dropped connection, a\n * transaction rollback, a query timeout. It is the typed boundary between\n * \"the store is unavailable/degraded\" and the domain errors above\n * ({@link ConcurrencyError}, {@link StreamClosedError}), which describe\n * legitimate outcomes the caller should branch on.\n *\n * Adapters wrap their driver errors in `StoreError` (preserving the\n * original via `cause`) so the orchestrator can distinguish a degraded\n * backend from \"no work\" and react accordingly — see the drain circuit\n * breaker, which trips on repeated `StoreError`s and surfaces an\n * `error` lifecycle event instead of silently spinning on a down\n * database.\n *\n * @example\n * ```typescript\n * app.on(\"error\", ({ error, circuit }) => {\n * if (error instanceof StoreError)\n * alert(`store ${error.operation} failing; circuit=${circuit}`);\n * });\n * ```\n */\nexport class StoreError extends Error {\n /** The store operation that failed (e.g. `\"claim\"`, `\"ack\"`, `\"commit\"`). */\n public readonly operation: string;\n\n constructor(operation: string, options?: { cause?: unknown }) {\n super(`Store operation \"${operation}\" failed`, options);\n this.name = Errors.StoreError;\n this.operation = operation;\n }\n}\n\n/**\n * Thrown by a reaction handler to signal that the failure is permanent\n * and the drain pipeline should block the stream immediately, without\n * consuming the rest of the `maxRetries` budget.\n *\n * The drain finalizer detects `instanceof NonRetryableError` and forces\n * `block = options.blockOnError` regardless of `lease.retry`. When\n * `blockOnError` is `false`, behavior is unchanged (drain keeps retrying\n * forever) — the class never overrides the operator's explicit \"never\n * block\" choice.\n *\n * Use this for failures the handler *knows* won't get better on retry:\n * a 4xx from a webhook, a `ZodError` on malformed input, a \"user\n * deleted\" 404 from a downstream API. Use regular `Error` (or a\n * subclass) for transient failures so the existing retry-with-backoff\n * loop applies.\n *\n * @example Wrapping a permanent downstream error\n * ```typescript\n * import { NonRetryableError } from \"@rotorsoft/act\";\n *\n * .on(\"OrderConfirmed\")\n * .do(async (event) => {\n * const res = await fetch(url, ...);\n * if (res.status >= 400 && res.status < 500) {\n * throw new NonRetryableError(\n * `webhook ${url} responded ${res.status}`,\n * { cause: await res.text() }\n * );\n * }\n * if (!res.ok) throw new Error(`webhook ${url} responded ${res.status}`);\n * })\n * ```\n *\n * @example Marking validation failures as non-retryable\n * ```typescript\n * .on(\"PaymentReceived\")\n * .do(async (event) => {\n * const parsed = Schema.safeParse(event.data);\n * if (!parsed.success) {\n * throw new NonRetryableError(\"payment payload failed validation\", {\n * cause: parsed.error,\n * });\n * }\n * // ... handle parsed payload\n * })\n * ```\n */\nexport class NonRetryableError extends Error {\n /** The original failure, if any. Mirrors the standard `Error.cause` shape. */\n public override readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = Errors.NonRetryableError;\n this.cause = options?.cause;\n }\n}\n","import { type ZodObject, type ZodRawShape, z } from \"zod\";\n// Deep-path import (vs `../internal/index.js`) is deliberate — `_registry` is\n// a side-effect-free leaf, and going through the internal barrel would pull\n// tracing.ts → config.ts in at type-schema load time and crash on TDZ when a\n// test imports a public schema before config is initialized.\nimport { _mark_sensitive, _registry } from \"../internal/sensitive.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Sensitive-data foundation re-exports.\n *\n * - `REDACTED` / `SHREDDED` — sentinels placed in `event.data[field]`\n * when the caller isn't authorized to see a sensitive field\n * (`.discloses(predicate)` returned `false` or none was declared —\n * recoverable) or the underlying PII was wiped (`Store.forget_pii` —\n * irrecoverable).\n * top-level field names marked via {@link sensitive}. A pure,\n * read-only helper that inspects the out-of-band sensitive registry (a\n * process-global `WeakMap`) `sensitive()` populates, otherwise\n * unreachable from outside the package. Surfaced for adapters and\n * tooling that must reflect input sensitivity on their own wire\n * surface — e.g. the `@rotorsoft/act-http/openapi` emitter marks these\n * fields `writeOnly` + `format: password` so generated clients and\n * Swagger UI don't echo PII freely. Returns `[]` for non-object\n * schemas or objects with no sensitive fields; top-level shape only.\n */\nexport { pii_fields, REDACTED, SHREDDED } from \"../internal/sensitive.js\";\n\n/**\n * Mark a Zod schema as sensitive. Returns the same schema instance — the\n * marker is registered out-of-band so the static type is preserved and the\n * call site reads as a pure annotation.\n *\n * Idempotent: re-wrapping an already-sensitive schema is a no-op.\n *\n * The marker is what the orchestrator inspects to split event payloads into\n * `data` + `pii` on commit, gate reads via `.discloses`, and strip handler\n * payloads. Part of the sensitive-data foundation.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { state, sensitive } from \"@rotorsoft/act\";\n *\n * const UserRegistered = z.object({\n * email: sensitive(z.string()),\n * name: sensitive(z.string()),\n * plan: z.enum([\"free\", \"pro\"]), // not sensitive — stays in events.data\n * });\n * ```\n *\n * @param schema - The Zod schema to mark sensitive.\n * @returns The same schema instance, unmodified at the type level.\n */\nexport function sensitive<T extends z.ZodType>(schema: T): T {\n _registry.add(schema, { sensitive: true });\n // Also stamp the def, so the marker survives the clone Zod produces for\n // any refinement chained AFTER this call — `sensitive(z.string()).min(1)`\n // used to lose it silently and write plaintext into `events.data`.\n _mark_sensitive(schema);\n return schema;\n}\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n with_pii: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @module sensitive\n * @category Internal\n *\n * Internal mechanics for the sensitive-data foundation.\n * The public surface (`sensitive(zodType)`) lives at `libs/act/src/sensitive.ts`\n * and re-exports `REDACTED` / `SHREDDED` from here; this module holds the\n * registry plus the helpers the orchestrator calls during commit, load, and\n * handler dispatch.\n *\n * - `_registry` — process-global `z.registry<{ sensitive: true }>()`. Public\n * `sensitive()` adds to it; the helpers in this module read it.\n * - `pii_fields(schema)` — walk a Zod schema's top-level shape, return the\n * keys marked via `sensitive(...)`.\n * - `pii_gate(event, fields, predicate, actor)` — produce the external\n * view: plaintext when authorized, `[REDACTED]` when not, `[SHREDDED]`\n * when the underlying pii column is null.\n * - `pii_strip(event, fields)` — remove sensitive keys entirely\n * before invoking projection / reaction handlers.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { Actor, Committed, Schemas } from \"../types/index.js\";\n\n/**\n * Sentinel placed in `event.data[field]` when the caller isn't authorized to\n * see the sensitive field — either `.discloses(predicate)` returned `false`,\n * or no predicate was declared (framework default-deny). Recoverable: a\n * properly-authorized read returns the plaintext.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const REDACTED = \"[REDACTED]\" as const;\n\n/**\n * Sentinel placed in `event.data[field]` when the underlying PII payload has\n * been wiped via `Store.forget_pii(stream)` — the row's pii column is `NULL`\n * and the original plaintext is gone forever. Irrecoverable.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const SHREDDED = \"[SHREDDED]\" as const;\n\n/**\n * Process-global registry holding every Zod schema marked sensitive. Backed\n * by a `WeakMap`, so wrapper-created instances (`.optional()`, `.nullable()`,\n * `.default()`) that chain off a marked schema produce *new* schema instances\n * the registry doesn't track; the field walker handles those via unwrap.\n *\n * Exported so the public `sensitive(zodType)` wrapper can call `_registry.add`.\n * Underscore prefix marks \"framework-private, don't touch from user code.\"\n *\n * @internal\n */\nexport const _registry = z.registry<{ sensitive: true }>();\n\n/**\n * Marker key stamped onto a schema's own `def`. Zod clones a schema on every\n * refinement (`.min()`, `.email()`, `.trim()`, `.describe()`, `.refine()`,\n * `.transform()`, …) via `{...def}`, which copies own symbol keys — so a\n * marker on the def survives the whole chain, while the `_registry` WeakMap\n * (keyed on the *instance*) does not.\n *\n * The registry is still populated and still consulted: it covers schemas\n * marked before this key existed, and it is the mechanism the public\n * `sensitive()` doc-comment describes.\n *\n * @internal\n */\nconst _SENSITIVE = Symbol.for(\"act.sensitive\");\n\n/**\n * Stamp the def-level marker. Called by the public `sensitive()` alongside\n * `_registry.add`.\n *\n * @internal\n */\nexport function _mark_sensitive(schema: z.ZodType): void {\n const def = (\n schema as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def) def[_SENSITIVE] = true;\n}\n\n/**\n * True when the given schema was marked via `sensitive(...)`.\n *\n * Walks through Zod wrapper layers (`.optional()`, `.nullable()`,\n * `.default()`, `.readonly()`) by following `_def.innerType` until it reaches\n * a non-wrapper schema, then checks the registry. Wrappers create new schema\n * instances; the marker lives on the *inner* schema the user wrapped, so we\n * test that one.\n *\n * @internal\n */\nfunction is_pii(schema: z.ZodType): boolean {\n let cur: z.ZodType = schema;\n while (true) {\n if (_registry.has(cur)) return true;\n // Def-level marker: survives the clone a refinement produces, which the\n // instance-keyed registry above cannot.\n const def = (\n cur as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def?.[_SENSITIVE] === true) return true;\n const inner = (cur as { _def?: { innerType?: z.ZodType } })._def?.innerType;\n if (!inner || inner === cur) return false;\n cur = inner;\n }\n}\n\n/**\n * Derive an event's sensitive fields, as the declared schema of each.\n *\n * Walks the top-level shape of a `z.object({...})` and keeps the keys whose\n * schema (after unwrapping optional/nullable/default wrappers) was marked via\n * `sensitive(...)`. Returns an empty object for non-object schemas or events\n * with no sensitive fields — the common-case zero-cost path.\n *\n * Only the top-level shape is walked. Sensitive fields nested inside a\n * `z.object` declared inside the event payload would require recursive\n * descent; that's deferred until a real callsite needs it.\n *\n * A union event has no top-level shape, so the options are walked and merged:\n * a key sensitive in any variant must be split, because the stored payload\n * could be that variant.\n * The first variant to declare a key wins, which only matters to a caller that\n * wants the schema rather than the name.\n *\n * Returning the schemas rather than just the names is what lets a caller do\n * something per field — the event builder asks each one whether it holds a\n * date, so the `pii` sidecar's dates can be revived like any other.\n *\n * @internal\n */\nexport function pii_schemas(schema: z.ZodType): Record<string, z.ZodType> {\n const shape = (schema as { shape?: Record<string, z.ZodType> }).shape;\n if (shape && typeof shape === \"object\") {\n const fields: Record<string, z.ZodType> = {};\n for (const key of Object.keys(shape))\n if (is_pii(shape[key])) fields[key] = shape[key];\n return fields;\n }\n const options = (schema as { options?: unknown }).options;\n if (Array.isArray(options)) {\n const fields: Record<string, z.ZodType> = {};\n for (const option of options)\n for (const [key, field] of Object.entries(\n pii_schemas(option as z.ZodType)\n ))\n fields[key] ??= field;\n return fields;\n }\n return {};\n}\n\n/**\n * The names of an event's sensitive fields — {@link pii_schemas} keyed.\n *\n * @internal — consumed by the registry's `sensitive_fields(event_name)` lookup,\n * and public through `types/schemas.ts`, where act-http's OpenAPI emitter uses\n * it to mark request-body properties `writeOnly`.\n */\nexport function pii_fields(schema: z.ZodType): readonly string[] {\n return Object.keys(pii_schemas(schema));\n}\n\n/**\n * Split an emitted event's `data` into `data` (non-sensitive) + `pii`\n * (sensitive) using the field list precomputed at build time. Used by the\n * State's `_pii_split` decorator just before `Store.commit`.\n *\n * Single forward pass over `Object.keys(validated)` — same shape as the\n * spread-and-delete-free implementation in slice 3, just hoisted out of the\n * orchestrator hot path so it's only invoked when the State actually has a\n * sensitive event.\n *\n * @internal\n */\nexport function pii_split<TName, TData extends Record<string, unknown>>(\n emitted: { name: TName; data: TData },\n fields: readonly string[]\n): { name: TName; data: TData; pii: Record<string, unknown> } {\n const data = { ...emitted.data };\n const pii: Record<string, unknown> = {};\n for (const f of fields) {\n if (f in data) {\n pii[f] = data[f];\n delete data[f];\n }\n }\n return { name: emitted.name, data, pii };\n}\n\n/**\n * Build the **external view** of a committed event — the form returned by\n * `load()`, `query()`, `query_array()`, and the snapshot in `do()`'s reply.\n *\n * Only ever reached for events that declare sensitive fields — the sole caller\n * is {@link make_gate}, which the builder invokes exclusively for sensitive\n * events; non-sensitive events short-circuit to {@link IDENTITY_GATE} before\n * they get here. `fields` is therefore guaranteed non-empty (same contract as\n * {@link pii_strip}).\n *\n * - Event whose `pii` payload is null/undefined → substitute {@link SHREDDED}\n * for each declared field. Irrecoverable, so no predicate check.\n * - Event with a `pii` payload, predicate returns `true` → merge `pii` into\n * `data` (plaintext).\n * - Event with a `pii` payload, predicate returns `false` OR no predicate\n * declared (framework default-deny) → substitute {@link REDACTED} for each\n * declared field.\n *\n * @internal\n */\nexport function pii_gate<TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null,\n actor: Actor | undefined\n): Committed<TEvents, TKey> {\n const data = event.data as Record<string, unknown>;\n // The external view NEVER carries the isolated `pii` sidecar — dropping it\n // is the whole point of the gate. Keeping it (an earlier `...event` spread)\n // leaked plaintext PII on every gated read surface (`load`, `query`,\n // `query_array`) even while `data` was correctly redacted. Strip it\n // once here; the plaintext lives in `data` only on the authorized path.\n const { pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: Record<string, unknown> | null;\n };\n if (pii == null) {\n const shredded: Record<string, unknown> = { ...data };\n for (const f of fields) shredded[f] = SHREDDED;\n return { ...rest, data: shredded as Committed<TEvents, TKey>[\"data\"] };\n }\n // Plaintext path requires both an actor AND a predicate that allows. Missing\n // either → default-deny → REDACTED.\n const allowed = !!actor && !!predicate && predicate(event, actor);\n if (allowed) {\n return {\n ...rest,\n data: { ...data, ...pii } as Committed<TEvents, TKey>[\"data\"],\n };\n }\n const redacted: Record<string, unknown> = { ...data };\n for (const f of fields) redacted[f] = REDACTED;\n return { ...rest, data: redacted as Committed<TEvents, TKey>[\"data\"] };\n}\n\n/**\n * A prebuilt per-event read gate: given a committed event and the reading\n * actor, return the caller-visible form. This is the single gating primitive\n * the builder prebuilds for **every** read surface — both the actor-less\n * `query` / `query_array` (which pass no actor → default-deny) and the\n * actor-aware `load` / `do`-return view (which pass the reader). Non-sensitive\n * events use the shared {@link IDENTITY_GATE}; sensitive events use a redactor\n * built by {@link make_gate} that closes over the field list and the state's\n * disclosure predicate, so the read path never recomputes the sensitive-field\n * lookup nor allocates per event.\n *\n * The `actor` is optional so the actor-less surfaces can call `gate(event)`.\n *\n * @internal\n */\nexport type EventGate = <TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n actor?: Actor\n) => Committed<TEvents, TKey>;\n\n/**\n * Shared zero-cost gate for every event with no `sensitive(...)` fields — a\n * single frozen reference the builder hands back for non-sensitive events, so\n * the common path is one `Map` miss and an identity call, no allocation. This\n * is the \"by default, return the event\" half of the prebuilt per-event gate.\n *\n * @internal\n */\nexport const IDENTITY_GATE: EventGate = (event) => event;\n\n/**\n * Prebuild a read gate for a sensitive event, capturing its field list and the\n * disclosure predicate once at build time. The returned closure defers to\n * {@link pii_gate} with the reading actor supplied per call:\n *\n * - `predicate = null` (the actor-less `query` surfaces, or a state that never\n * declared `.discloses`) → default-deny: declared fields come back\n * {@link REDACTED} (or {@link SHREDDED} once the pii column is forgotten).\n * - `predicate` set + an authorized actor → plaintext merged into `data`.\n *\n * Either way the isolated `pii` sidecar is dropped. The builder stores one gate\n * per sensitive event (per state for the load path; predicate-less for the\n * query path); non-sensitive events fall back to {@link IDENTITY_GATE}.\n *\n * @internal\n */\nexport function make_gate(\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null\n): EventGate {\n return (event, actor) => pii_gate(event, fields, predicate, actor);\n}\n\n/**\n * Build the **handler view** — sensitive keys removed entirely from `data`\n * and the `pii` field dropped from the event. Used before invoking projection\n * handlers and reaction handlers, which never see PII by framework rule.\n *\n * Different from {@link pii_gate} (which substitutes {@link REDACTED} or\n * {@link SHREDDED}) — projection tables and reaction sinks shouldn't even\n * structurally observe the keys, so a handler that mistakenly writes\n * `event.data.email` into a column would get `undefined`, not a sentinel\n * string that looks like real data. The strictness is deliberate.\n *\n * Reactions that genuinely need PII (e.g. a welcome-email reaction reading\n * `email`) opt back in by explicitly calling `app.load(stream, { actor:\n * system_actor })` inside the handler — pulling PII through the gate at the\n * call site makes the security-relevant path visible in code review.\n *\n * @internal\n */\nexport function pii_strip<\n TEvents extends Schemas,\n TKey extends keyof TEvents & string,\n>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[]\n): Committed<TEvents, TKey> {\n // Contract: `fields` is non-empty. `build_handle` / `build_handle_batch`\n // filter on `fields.length > 0` before invocation.\n const data = event.data as Record<string, unknown>;\n const stripped: Record<string, unknown> = {};\n for (const k of Object.keys(data)) {\n if (!fields.includes(k)) stripped[k] = data[k];\n }\n const { pii: _drop_pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: unknown;\n };\n return {\n ...rest,\n data: stripped as Committed<TEvents, TKey>[\"data\"],\n } as Committed<TEvents, TKey>;\n}\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport type * from \"./audit.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n"],"mappings":"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","names":["z","z"]}
1
+ {"version":3,"sources":["../src/types/errors.ts","../src/types/schemas.ts","../src/internal/sensitive.ts","../src/types/index.ts"],"sourcesContent":["import type {\n Actor,\n Message,\n Schema,\n Schemas,\n Snapshot,\n Target,\n} from \"./action.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Application error type constants and error classes for the Act Framework.\n *\n * - `ERR_VALIDATION`: Schema validation error\n * - `ERR_INVARIANT`: Invariant validation error\n * - `ERR_CONCURRENCY`: Optimistic concurrency validation error on commits\n */\nexport const Errors = {\n ValidationError: \"ERR_VALIDATION\",\n InvariantError: \"ERR_INVARIANT\",\n ConcurrencyError: \"ERR_CONCURRENCY\",\n StreamClosedError: \"ERR_STREAM_CLOSED\",\n NonRetryableError: \"ERR_NON_RETRYABLE\",\n StoreError: \"ERR_STORE\",\n} as const;\n\n/**\n * Thrown when an action or event payload fails Zod schema validation.\n *\n * This error indicates that data doesn't match the expected schema defined\n * for an action or event. The `details` property contains the Zod validation\n * error with specific information about what failed.\n *\n * @example Catching validation errors\n * ```typescript\n * import { ValidationError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"createUser\", target, {\n * email: \"invalid-email\", // Missing @ symbol\n * age: -5 // Negative age\n * });\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * console.error(\"Validation failed for:\", error.target);\n * console.error(\"Invalid payload:\", error.payload);\n * console.error(\"Validation details:\", error.details);\n * // details contains Zod error with field-level info\n * }\n * }\n * ```\n *\n * @example Logging validation details\n * ```typescript\n * try {\n * await app.do(\"updateProfile\", target, payload);\n * } catch (error) {\n * if (error instanceof ValidationError) {\n * error.details.errors.forEach((err) => {\n * console.error(`Field ${err.path.join(\".\")}: ${err.message}`);\n * });\n * }\n * }\n * ```\n *\n * @see {@link https://zod.dev | Zod documentation} for validation details\n */\nexport class ValidationError extends Error {\n /** The type of target being validated (e.g., \"action\", \"event\") */\n public readonly target: string;\n /** The invalid payload that failed validation */\n public readonly payload: any;\n /** Zod validation error details */\n public readonly details: any;\n\n constructor(target: string, payload: any, details: any) {\n super(`Invalid ${target} payload`);\n this.name = Errors.ValidationError;\n this.target = target;\n this.payload = payload;\n this.details = details;\n }\n}\n\n/**\n * Thrown when a business rule (invariant) is violated during action execution.\n *\n * Invariants are conditions that must hold true for an action to succeed.\n * They're checked after loading the current state but before emitting events.\n * This error provides complete context about what action was attempted and\n * why it was rejected.\n *\n * @template TState - State schema type\n * @template TEvents - Event schemas type\n * @template TActions - Action schemas type\n * @template TKey - Action name\n * @template TActor - Actor type extending base Actor\n *\n * @example Catching invariant violations\n * ```typescript\n * import { InvariantError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"withdraw\",\n * { stream: \"account-123\", actor: { id: \"user1\", name: \"Alice\" } },\n * { amount: 1000 }\n * );\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * console.error(\"Action:\", error.action);\n * console.error(\"Reason:\", error.description);\n * console.error(\"Current state:\", error.snapshot.state);\n * console.error(\"Attempted payload:\", error.payload);\n * }\n * }\n * ```\n *\n * @example User-friendly error messages\n * ```typescript\n * try {\n * await app.do(\"closeTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * // Present friendly message to user\n * if (error.description === \"Ticket must be open\") {\n * return { error: \"This ticket is already closed\" };\n * } else if (error.description === \"Not authorized\") {\n * return { error: \"You don't have permission to close this ticket\" };\n * }\n * }\n * }\n * ```\n *\n * @example Logging with context\n * ```typescript\n * try {\n * await app.do(\"transfer\", target, { to: \"account2\", amount: 500 });\n * } catch (error) {\n * if (error instanceof InvariantError) {\n * logger.error({\n * action: error.action,\n * stream: error.target.stream,\n * actor: error.target.actor,\n * reason: error.description,\n * balance: error.snapshot.state.balance,\n * attempted: error.payload.amount\n * }, \"Invariant violation\");\n * }\n * }\n * ```\n *\n * @see {@link Invariant} for defining business rules\n */\nexport class InvariantError<\n TState extends Schema,\n TEvents extends Schemas,\n TActions extends Schemas,\n TKey extends keyof TActions,\n TActor extends Actor = Actor,\n> extends Error {\n /** The action that was attempted */\n readonly action: TKey;\n /** The action payload that was provided */\n readonly payload: Readonly<TActions[TKey]>;\n /** The target stream and actor context */\n readonly target: Target<TActor>;\n /** The current state snapshot when invariant was checked */\n readonly snapshot: Snapshot<TState, TEvents>;\n /** Human-readable description of why the invariant failed */\n readonly description: string;\n\n constructor(\n action: TKey,\n payload: Readonly<TActions[TKey]>,\n target: Target<TActor>,\n snapshot: Snapshot<TState, TEvents>,\n description: string\n ) {\n super(`${action as string} failed invariant: ${description}`);\n this.name = Errors.InvariantError;\n this.action = action;\n this.payload = payload;\n this.target = target;\n this.snapshot = snapshot;\n this.description = description;\n }\n}\n\n/**\n * Thrown when optimistic concurrency control detects a conflict.\n *\n * This error occurs when trying to commit events to a stream that has been\n * modified by another process since it was last loaded. The version number\n * doesn't match expectations, indicating a concurrent modification.\n *\n * This is a normal occurrence in distributed systems and should be handled\n * by reloading the current state and retrying the action.\n *\n * @example Handling concurrency conflicts with retry\n * ```typescript\n * import { ConcurrencyError } from \"@rotorsoft/act\";\n *\n * async function transferWithRetry(from, to, amount, maxRetries = 3) {\n * for (let attempt = 0; attempt < maxRetries; attempt++) {\n * try {\n * await app.do(\"transfer\",\n * { stream: from, actor: currentUser },\n * { to, amount }\n * );\n * return { success: true };\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * if (attempt < maxRetries - 1) {\n * console.log(`Concurrent modification detected, retrying... (${attempt + 1}/${maxRetries})`);\n * await sleep(100 * Math.pow(2, attempt)); // Exponential backoff\n * continue;\n * }\n * }\n * throw error;\n * }\n * }\n * return { success: false, reason: \"Too many concurrent modifications\" };\n * }\n * ```\n *\n * @example Logging concurrency conflicts\n * ```typescript\n * try {\n * await app.do(\"updateInventory\", target, payload);\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * logger.warn({\n * stream: error.stream,\n * expectedVersion: error.expectedVersion,\n * actualVersion: error.lastVersion,\n * events: error.events.map(e => e.name)\n * }, \"Concurrent modification detected\");\n * }\n * }\n * ```\n *\n * @example User feedback for conflicts\n * ```typescript\n * try {\n * await app.do(\"editDocument\", target, { content: newContent });\n * } catch (error) {\n * if (error instanceof ConcurrencyError) {\n * return {\n * error: \"This document was modified by another user. Please refresh and try again.\",\n * code: \"CONCURRENT_MODIFICATION\"\n * };\n * }\n * }\n * ```\n *\n * @see {@link Store.commit} for version checking details\n */\nexport class ConcurrencyError extends Error {\n /** The stream that had the concurrent modification */\n public readonly stream: string;\n /** The actual current version in the store */\n public readonly lastVersion: number;\n /** The events that were being committed */\n public readonly events: Message<Schemas, keyof Schemas>[];\n /** The version number that was expected */\n public readonly expectedVersion: number;\n\n constructor(\n stream: string,\n lastVersion: number,\n events: Message<Schemas, keyof Schemas>[],\n expectedVersion: number\n ) {\n // Message lists stream + event names only. Payloads remain accessible\n // via `error.events` for callers who need them — keeping them out of\n // the message avoids MB-scale strings on contended writes and keeps\n // potentially-sensitive data out of log streams.\n super(\n `Concurrency error committing \"${events\n .map((e) => `${stream}.${e.name}`)\n .join(\n \", \"\n )}\". Expected version ${expectedVersion} but found version ${lastVersion}.`\n );\n this.name = Errors.ConcurrencyError;\n this.stream = stream;\n this.lastVersion = lastVersion;\n this.events = events;\n this.expectedVersion = expectedVersion;\n }\n}\n\n/**\n * Thrown when attempting to write to a stream that has been closed\n * with a tombstone event.\n *\n * A tombstoned stream is permanently closed — no further actions can\n * be executed against it. The only way to reopen a tombstoned stream\n * is through `Act.close()` with a `restart` callback.\n *\n * @example\n * ```typescript\n * import { StreamClosedError } from \"@rotorsoft/act\";\n *\n * try {\n * await app.do(\"updateTicket\", target, payload);\n * } catch (error) {\n * if (error instanceof StreamClosedError) {\n * console.error(`Stream ${error.stream} is closed`);\n * }\n * }\n * ```\n *\n * @see {@link Act.close} for closing streams\n */\nexport class StreamClosedError extends Error {\n /** The stream that is closed */\n public readonly stream: string;\n\n constructor(stream: string) {\n super(`Stream \"${stream}\" is closed (tombstoned)`);\n this.name = Errors.StreamClosedError;\n this.stream = stream;\n }\n}\n\n/**\n * Thrown by a {@link Store} adapter when an infrastructure operation fails\n * for a reason that is *not* a domain condition — a dropped connection, a\n * transaction rollback, a query timeout. It is the typed boundary between\n * \"the store is unavailable/degraded\" and the domain errors above\n * ({@link ConcurrencyError}, {@link StreamClosedError}), which describe\n * legitimate outcomes the caller should branch on.\n *\n * Adapters wrap their driver errors in `StoreError` (preserving the\n * original via `cause`) so the orchestrator can distinguish a degraded\n * backend from \"no work\" and react accordingly — see the drain circuit\n * breaker, which trips on repeated `StoreError`s and surfaces an\n * `error` lifecycle event instead of silently spinning on a down\n * database.\n *\n * @example\n * ```typescript\n * app.on(\"error\", ({ error, circuit }) => {\n * if (error instanceof StoreError)\n * alert(`store ${error.operation} failing; circuit=${circuit}`);\n * });\n * ```\n */\nexport class StoreError extends Error {\n /** The store operation that failed (e.g. `\"claim\"`, `\"ack\"`, `\"commit\"`). */\n public readonly operation: string;\n\n constructor(operation: string, options?: { cause?: unknown }) {\n super(`Store operation \"${operation}\" failed`, options);\n this.name = Errors.StoreError;\n this.operation = operation;\n }\n}\n\n/**\n * Thrown by a reaction handler to signal that the failure is permanent\n * and the drain pipeline should block the stream immediately, without\n * consuming the rest of the `maxRetries` budget.\n *\n * The drain finalizer detects `instanceof NonRetryableError` and forces\n * `block = options.blockOnError` regardless of `lease.retry`. When\n * `blockOnError` is `false`, behavior is unchanged (drain keeps retrying\n * forever) — the class never overrides the operator's explicit \"never\n * block\" choice.\n *\n * Use this for failures the handler *knows* won't get better on retry:\n * a 4xx from a webhook, a `ZodError` on malformed input, a \"user\n * deleted\" 404 from a downstream API. Use regular `Error` (or a\n * subclass) for transient failures so the existing retry-with-backoff\n * loop applies.\n *\n * @example Wrapping a permanent downstream error\n * ```typescript\n * import { NonRetryableError } from \"@rotorsoft/act\";\n *\n * .on(\"OrderConfirmed\")\n * .do(async (event) => {\n * const res = await fetch(url, ...);\n * if (res.status >= 400 && res.status < 500) {\n * throw new NonRetryableError(\n * `webhook ${url} responded ${res.status}`,\n * { cause: await res.text() }\n * );\n * }\n * if (!res.ok) throw new Error(`webhook ${url} responded ${res.status}`);\n * })\n * ```\n *\n * @example Marking validation failures as non-retryable\n * ```typescript\n * .on(\"PaymentReceived\")\n * .do(async (event) => {\n * const parsed = Schema.safeParse(event.data);\n * if (!parsed.success) {\n * throw new NonRetryableError(\"payment payload failed validation\", {\n * cause: parsed.error,\n * });\n * }\n * // ... handle parsed payload\n * })\n * ```\n */\nexport class NonRetryableError extends Error {\n /** The original failure, if any. Mirrors the standard `Error.cause` shape. */\n public override readonly cause?: unknown;\n\n constructor(message: string, options?: { cause?: unknown }) {\n super(message);\n this.name = Errors.NonRetryableError;\n this.cause = options?.cause;\n }\n}\n","import { type ZodObject, type ZodRawShape, z } from \"zod\";\n// Deep-path import (vs `../internal/index.js`) is deliberate — `_registry` is\n// a side-effect-free leaf, and going through the internal barrel would pull\n// tracing.ts → config.ts in at type-schema load time and crash on TDZ when a\n// test imports a public schema before config is initialized.\nimport { _mark_sensitive, _registry } from \"../internal/sensitive.js\";\n\n/**\n * @packageDocumentation\n * @module act/types\n * @category Types\n * Zod schemas and helpers for the Act Framework.\n */\n\n/**\n * An empty Zod schema (no properties).\n */\nexport const ZodEmpty = z.record(z.string(), z.never());\n\n/**\n * Sensitive-data foundation re-exports.\n *\n * - `REDACTED` / `SHREDDED` — sentinels placed in `event.data[field]`\n * when the caller isn't authorized to see a sensitive field\n * (`.discloses(predicate)` returned `false` or none was declared —\n * recoverable) or the underlying PII was wiped (`Store.forget_pii` —\n * irrecoverable).\n * top-level field names marked via {@link sensitive}. A pure,\n * read-only helper that inspects the out-of-band sensitive registry (a\n * process-global `WeakMap`) `sensitive()` populates, otherwise\n * unreachable from outside the package. Surfaced for adapters and\n * tooling that must reflect input sensitivity on their own wire\n * surface — e.g. the `@rotorsoft/act-http/openapi` emitter marks these\n * fields `writeOnly` + `format: password` so generated clients and\n * Swagger UI don't echo PII freely. Returns `[]` for non-object\n * schemas or objects with no sensitive fields; top-level shape only.\n */\nexport { pii_fields, REDACTED, SHREDDED } from \"../internal/sensitive.js\";\n\n/**\n * Mark a Zod schema as sensitive. Returns the same schema instance — the\n * marker is registered out-of-band so the static type is preserved and the\n * call site reads as a pure annotation.\n *\n * Idempotent: re-wrapping an already-sensitive schema is a no-op.\n *\n * The marker is what the orchestrator inspects to split event payloads into\n * `data` + `pii` on commit, gate reads via `.discloses`, and strip handler\n * payloads. Part of the sensitive-data foundation.\n *\n * @example\n * ```ts\n * import { z } from \"zod\";\n * import { state, sensitive } from \"@rotorsoft/act\";\n *\n * const UserRegistered = z.object({\n * email: sensitive(z.string()),\n * name: sensitive(z.string()),\n * plan: z.enum([\"free\", \"pro\"]), // not sensitive — stays in events.data\n * });\n * ```\n *\n * @param schema - The Zod schema to mark sensitive.\n * @returns The same schema instance, unmodified at the type level.\n */\nexport function sensitive<T extends z.ZodType>(schema: T): T {\n _registry.add(schema, { sensitive: true });\n // Also stamp the def, so the marker survives the clone Zod produces for\n // any refinement chained AFTER this call — `sensitive(z.string()).min(1)`\n // used to lose it silently and write plaintext into `events.data`.\n _mark_sensitive(schema);\n return schema;\n}\n\n/**\n * Zod schema for an actor (user, system, etc.).\n */\nexport const ActorSchema = z\n .object({\n id: z.string(),\n name: z.string(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for a target (stream and actor info).\n */\nexport const TargetSchema = z\n .object({\n stream: z.string(),\n actor: ActorSchema,\n expectedVersion: z.number().optional(),\n })\n .loose()\n .readonly();\n\n/**\n * Zod schema for causation event metadata.\n */\nexport const CausationEventSchema = z.object({\n id: z.number(),\n name: z.string(),\n stream: z.string(),\n});\n\n/**\n * Zod schema for event metadata (correlation and causation).\n */\nexport const EventMetaSchema = z\n .object({\n correlation: z.string(),\n causation: z.object({\n action: TargetSchema.and(z.object({ name: z.string() })).optional(),\n event: CausationEventSchema.optional(),\n }),\n })\n .readonly();\n\n/**\n * Zod schema for committed event metadata (id, stream, version, created, meta).\n */\nexport const CommittedMetaSchema = z\n .object({\n id: z.number(),\n stream: z.string(),\n version: z.number(),\n created: z.date(),\n meta: EventMetaSchema,\n })\n .readonly();\n\n/**\n * Type representing the full state schema for a domain.\n * @property events - Map of event names to Zod schemas.\n * @property actions - Map of action names to Zod schemas.\n * @property state - Zod schema for the state object.\n */\nexport type StateSchema = Readonly<{\n events: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n actions: Record<string, ZodObject<ZodRawShape> | typeof ZodEmpty>;\n state: ZodObject<ZodRawShape>;\n}>;\n\n/**\n * Query options for event store queries.\n */\nexport const QuerySchema = z\n .object({\n stream: z.string().optional(),\n names: z.string().array().optional(),\n before: z.number().optional(),\n after: z.number().optional(),\n limit: z.number().optional(),\n created_before: z.date().optional(),\n created_after: z.date().optional(),\n backward: z.boolean().optional(),\n correlation: z.string().optional(),\n with_snaps: z.boolean().optional(),\n with_pii: z.boolean().optional(),\n stream_exact: z.boolean().optional(),\n })\n .readonly();\n","/**\n * @module sensitive\n * @category Internal\n *\n * Internal mechanics for the sensitive-data foundation.\n * The public surface (`sensitive(zodType)`) lives at `libs/act/src/sensitive.ts`\n * and re-exports `REDACTED` / `SHREDDED` from here; this module holds the\n * registry plus the helpers the orchestrator calls during commit, load, and\n * handler dispatch.\n *\n * - `_registry` — process-global `z.registry<{ sensitive: true }>()`. Public\n * `sensitive()` adds to it; the helpers in this module read it.\n * - `pii_fields(schema)` — walk a Zod schema's top-level shape, return the\n * keys marked via `sensitive(...)`.\n * - `pii_gate(event, fields, predicate, actor)` — produce the external\n * view: plaintext when authorized, `[REDACTED]` when not, `[SHREDDED]`\n * when the underlying pii column is null.\n * - `pii_strip(event, fields)` — remove sensitive keys entirely\n * before invoking projection / reaction handlers.\n *\n * @internal\n */\n\nimport { z } from \"zod\";\nimport type { Actor, Committed, Schemas } from \"../types/index.js\";\n\n/**\n * Sentinel placed in `event.data[field]` when the caller isn't authorized to\n * see the sensitive field — either `.discloses(predicate)` returned `false`,\n * or no predicate was declared (framework default-deny). Recoverable: a\n * properly-authorized read returns the plaintext.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const REDACTED = \"[REDACTED]\" as const;\n\n/**\n * Sentinel placed in `event.data[field]` when the underlying PII payload has\n * been wiped via `Store.forget_pii(stream)` — the row's pii column is `NULL`\n * and the original plaintext is gone forever. Irrecoverable.\n *\n * Re-exported from `libs/act/src/sensitive.ts` as part of the public surface.\n */\nexport const SHREDDED = \"[SHREDDED]\" as const;\n\n/**\n * Process-global registry holding every Zod schema marked sensitive. Backed\n * by a `WeakMap`, so wrapper-created instances (`.optional()`, `.nullable()`,\n * `.default()`) that chain off a marked schema produce *new* schema instances\n * the registry doesn't track; the field walker handles those via unwrap.\n *\n * Exported so the public `sensitive(zodType)` wrapper can call `_registry.add`.\n * Underscore prefix marks \"framework-private, don't touch from user code.\"\n *\n * @internal\n */\nexport const _registry = z.registry<{ sensitive: true }>();\n\n/**\n * Marker key stamped onto a schema's own `def`. Zod clones a schema on every\n * refinement (`.min()`, `.email()`, `.trim()`, `.describe()`, `.refine()`,\n * `.transform()`, …) via `{...def}`, which copies own symbol keys — so a\n * marker on the def survives the whole chain, while the `_registry` WeakMap\n * (keyed on the *instance*) does not.\n *\n * The registry is still populated and still consulted: it covers schemas\n * marked before this key existed, and it is the mechanism the public\n * `sensitive()` doc-comment describes.\n *\n * @internal\n */\nconst _SENSITIVE = Symbol.for(\"act.sensitive\");\n\n/**\n * Stamp the def-level marker. Called by the public `sensitive()` alongside\n * `_registry.add`.\n *\n * @internal\n */\nexport function _mark_sensitive(schema: z.ZodType): void {\n const def = (\n schema as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def) def[_SENSITIVE] = true;\n}\n\n/**\n * True when the given schema was marked via `sensitive(...)`.\n *\n * Walks through Zod wrapper layers (`.optional()`, `.nullable()`,\n * `.default()`, `.readonly()`) by following `_def.innerType` until it reaches\n * a non-wrapper schema, then checks the registry. Wrappers create new schema\n * instances; the marker lives on the *inner* schema the user wrapped, so we\n * test that one.\n *\n * @internal\n */\nfunction is_pii(schema: z.ZodType): boolean {\n let cur: z.ZodType = schema;\n while (true) {\n if (_registry.has(cur)) return true;\n // Def-level marker: survives the clone a refinement produces, which the\n // instance-keyed registry above cannot.\n const def = (\n cur as unknown as {\n _zod?: { def?: Record<PropertyKey, unknown> };\n }\n )._zod?.def;\n if (def?.[_SENSITIVE] === true) return true;\n const inner = (cur as { _def?: { innerType?: z.ZodType } })._def?.innerType;\n if (!inner || inner === cur) return false;\n cur = inner;\n }\n}\n\n/**\n * Derive an event's sensitive fields, as the declared schema of each.\n *\n * Walks the top-level shape of a `z.object({...})` and keeps the keys whose\n * schema (after unwrapping optional/nullable/default wrappers) was marked via\n * `sensitive(...)`. Returns an empty object for non-object schemas or events\n * with no sensitive fields — the common-case zero-cost path.\n *\n * Only the top-level shape is walked. Sensitive fields nested inside a\n * `z.object` declared inside the event payload would require recursive\n * descent; that's deferred until a real callsite needs it.\n *\n * A union event has no top-level shape, so the options are walked and merged:\n * a key sensitive in any variant must be split, because the stored payload\n * could be that variant.\n * The first variant to declare a key wins, which only matters to a caller that\n * wants the schema rather than the name.\n *\n * Returning the schemas rather than just the names is what lets a caller do\n * something per field — the event builder asks each one whether it holds a\n * date, so the `pii` sidecar's dates can be revived like any other.\n *\n * @internal\n */\nexport function pii_schemas(schema: z.ZodType): Record<string, z.ZodType> {\n const shape = (schema as { shape?: Record<string, z.ZodType> }).shape;\n if (shape && typeof shape === \"object\") {\n const fields: Record<string, z.ZodType> = {};\n for (const key of Object.keys(shape))\n if (is_pii(shape[key])) fields[key] = shape[key];\n return fields;\n }\n const options = (schema as { options?: unknown }).options;\n if (Array.isArray(options)) {\n const fields: Record<string, z.ZodType> = {};\n for (const option of options)\n for (const [key, field] of Object.entries(\n pii_schemas(option as z.ZodType)\n ))\n fields[key] ??= field;\n return fields;\n }\n return {};\n}\n\n/**\n * The names of an event's sensitive fields — {@link pii_schemas} keyed.\n *\n * @internal — consumed by the registry's `sensitive_fields(event_name)` lookup,\n * and public through `types/schemas.ts`, where act-http's OpenAPI emitter uses\n * it to mark request-body properties `writeOnly`.\n */\nexport function pii_fields(schema: z.ZodType): readonly string[] {\n return Object.keys(pii_schemas(schema));\n}\n\n/**\n * Split an emitted event's `data` into `data` (non-sensitive) + `pii`\n * (sensitive) using the field list precomputed at build time. Used by the\n * State's `_pii_split` decorator just before `Store.commit`.\n *\n * Single forward pass over `Object.keys(validated)` — same shape as the\n * spread-and-delete-free implementation in slice 3, just hoisted out of the\n * orchestrator hot path so it's only invoked when the State actually has a\n * sensitive event.\n *\n * @internal\n */\nexport function pii_split<TName, TData extends Record<string, unknown>>(\n emitted: { name: TName; data: TData },\n fields: readonly string[]\n): { name: TName; data: TData; pii: Record<string, unknown> } {\n const data = { ...emitted.data };\n const pii: Record<string, unknown> = {};\n for (const f of fields) {\n if (f in data) {\n pii[f] = data[f];\n delete data[f];\n }\n }\n return { name: emitted.name, data, pii };\n}\n\n/**\n * Build the **external view** of a committed event — the form returned by\n * `load()`, `query()`, `query_array()`, and the snapshot in `do()`'s reply.\n *\n * Only ever reached for events that declare sensitive fields — the sole caller\n * is {@link make_gate}, which the builder invokes exclusively for sensitive\n * events; non-sensitive events short-circuit to {@link IDENTITY_GATE} before\n * they get here. `fields` is therefore guaranteed non-empty (same contract as\n * {@link pii_strip}).\n *\n * - Event whose `pii` payload is null/undefined → substitute {@link SHREDDED}\n * for each declared field. Irrecoverable, so no predicate check.\n * - Event with a `pii` payload, predicate returns `true` → merge `pii` into\n * `data` (plaintext).\n * - Event with a `pii` payload, predicate returns `false` OR no predicate\n * declared (framework default-deny) → substitute {@link REDACTED} for each\n * declared field.\n *\n * @internal\n */\nfunction pii_gate<TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null,\n actor: Actor | undefined\n): Committed<TEvents, TKey> {\n const data = event.data as Record<string, unknown>;\n // The external view NEVER carries the isolated `pii` sidecar — dropping it\n // is the whole point of the gate. Keeping it (an earlier `...event` spread)\n // leaked plaintext PII on every gated read surface (`load`, `query`,\n // `query_array`) even while `data` was correctly redacted. Strip it\n // once here; the plaintext lives in `data` only on the authorized path.\n const { pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: Record<string, unknown> | null;\n };\n if (pii == null) {\n const shredded: Record<string, unknown> = { ...data };\n for (const f of fields) shredded[f] = SHREDDED;\n return { ...rest, data: shredded as Committed<TEvents, TKey>[\"data\"] };\n }\n // Plaintext path requires both an actor AND a predicate that allows. Missing\n // either → default-deny → REDACTED.\n const allowed = !!actor && !!predicate && predicate(event, actor);\n if (allowed) {\n return {\n ...rest,\n data: { ...data, ...pii } as Committed<TEvents, TKey>[\"data\"],\n };\n }\n const redacted: Record<string, unknown> = { ...data };\n for (const f of fields) redacted[f] = REDACTED;\n return { ...rest, data: redacted as Committed<TEvents, TKey>[\"data\"] };\n}\n\n/**\n * A prebuilt per-event read gate: given a committed event and the reading\n * actor, return the caller-visible form. This is the single gating primitive\n * the builder prebuilds for **every** read surface — both the actor-less\n * `query` / `query_array` (which pass no actor → default-deny) and the\n * actor-aware `load` / `do`-return view (which pass the reader). Non-sensitive\n * events use the shared {@link IDENTITY_GATE}; sensitive events use a redactor\n * built by {@link make_gate} that closes over the field list and the state's\n * disclosure predicate, so the read path never recomputes the sensitive-field\n * lookup nor allocates per event.\n *\n * The `actor` is optional so the actor-less surfaces can call `gate(event)`.\n *\n * @internal\n */\nexport type EventGate = <TEvents extends Schemas, TKey extends keyof TEvents>(\n event: Committed<TEvents, TKey>,\n actor?: Actor\n) => Committed<TEvents, TKey>;\n\n/**\n * Shared zero-cost gate for every event with no `sensitive(...)` fields — a\n * single frozen reference the builder hands back for non-sensitive events, so\n * the common path is one `Map` miss and an identity call, no allocation. This\n * is the \"by default, return the event\" half of the prebuilt per-event gate.\n *\n * @internal\n */\nexport const IDENTITY_GATE: EventGate = (event) => event;\n\n/**\n * Prebuild a read gate for a sensitive event, capturing its field list and the\n * disclosure predicate once at build time. The returned closure defers to\n * {@link pii_gate} with the reading actor supplied per call:\n *\n * - `predicate = null` (the actor-less `query` surfaces, or a state that never\n * declared `.discloses`) → default-deny: declared fields come back\n * {@link REDACTED} (or {@link SHREDDED} once the pii column is forgotten).\n * - `predicate` set + an authorized actor → plaintext merged into `data`.\n *\n * Either way the isolated `pii` sidecar is dropped. The builder stores one gate\n * per sensitive event (per state for the load path; predicate-less for the\n * query path); non-sensitive events fall back to {@link IDENTITY_GATE}.\n *\n * @internal\n */\nexport function make_gate(\n fields: readonly string[],\n predicate: ((event: any, actor: Actor) => boolean) | null\n): EventGate {\n return (event, actor) => pii_gate(event, fields, predicate, actor);\n}\n\n/**\n * Build the **handler view** — sensitive keys removed entirely from `data`\n * and the `pii` field dropped from the event. Used before invoking projection\n * handlers and reaction handlers, which never see PII by framework rule.\n *\n * Different from {@link pii_gate} (which substitutes {@link REDACTED} or\n * {@link SHREDDED}) — projection tables and reaction sinks shouldn't even\n * structurally observe the keys, so a handler that mistakenly writes\n * `event.data.email` into a column would get `undefined`, not a sentinel\n * string that looks like real data. The strictness is deliberate.\n *\n * Reactions that genuinely need PII (e.g. a welcome-email reaction reading\n * `email`) opt back in by explicitly calling `app.load(stream, { actor:\n * system_actor })` inside the handler — pulling PII through the gate at the\n * call site makes the security-relevant path visible in code review.\n *\n * @internal\n */\nexport function pii_strip<\n TEvents extends Schemas,\n TKey extends keyof TEvents & string,\n>(\n event: Committed<TEvents, TKey>,\n fields: readonly string[]\n): Committed<TEvents, TKey> {\n // Contract: `fields` is non-empty. `build_handle` / `build_handle_batch`\n // filter on `fields.length > 0` before invocation.\n const data = event.data as Record<string, unknown>;\n const stripped: Record<string, unknown> = {};\n for (const k of Object.keys(data)) {\n if (!fields.includes(k)) stripped[k] = data[k];\n }\n const { pii: _drop_pii, ...rest } = event as Committed<TEvents, TKey> & {\n pii?: unknown;\n };\n return {\n ...rest,\n data: stripped as Committed<TEvents, TKey>[\"data\"],\n } as Committed<TEvents, TKey>;\n}\n","/**\n * @packageDocumentation\n * @module act/types\n * Barrel file for Act Framework core types.\n *\n * Re-exports all major type definitions for actions, errors, ports, reactions, registries, and schemas.\n * Also defines common environment and log level types/constants for configuration and logging.\n *\n * @remarks\n * Import from this module to access all core framework types in one place.\n */\nexport type * from \"./action.js\";\nexport type * from \"./audit.js\";\nexport * from \"./errors.js\";\nexport type * from \"./ports.js\";\nexport type * from \"./reaction.js\";\nexport type * from \"./registry.js\";\nexport * from \"./schemas.js\";\n\n/**\n * Supported runtime environments for the framework.\n * - `development`: Local development\n * - `test`: Automated testing\n * - `staging`: Pre-production\n * - `production`: Live/production\n */\nexport const Environments = [\n \"development\",\n \"test\",\n \"staging\",\n \"production\",\n] as const;\n\n/**\n * Type representing a valid environment string.\n */\nexport type Environment = (typeof Environments)[number];\n\n/**\n * Supported log levels for framework logging.\n * - `fatal`, `error`, `warn`, `info`, `debug`, `trace`\n */\nexport const LogLevels = [\n \"fatal\",\n \"error\",\n \"warn\",\n \"info\",\n \"debug\",\n \"trace\",\n] as const;\n\n/**\n * Type representing a valid log level string.\n */\nexport type LogLevel = (typeof LogLevels)[number];\n"],"mappings":"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","names":["z","z"]}
package/dist/index.cjs CHANGED
@@ -2834,6 +2834,31 @@ var CircuitBreaker = class {
2834
2834
  };
2835
2835
 
2836
2836
  // src/internal/close-cycle.ts
2837
+ var CLOSE_CATCH_UP_LIMIT = 1e3;
2838
+ var CLOSE_CATCH_UP_PASSES = 20;
2839
+ async function catch_up_correlation(cursor, correlate, until) {
2840
+ for (let pass = 0; pass < CLOSE_CATCH_UP_PASSES && cursor.checkpoint < until; pass++) {
2841
+ const before = cursor.checkpoint;
2842
+ cursor.arm();
2843
+ await correlate(CLOSE_CATCH_UP_LIMIT);
2844
+ if (cursor.checkpoint <= before) break;
2845
+ }
2846
+ return cursor.checkpoint;
2847
+ }
2848
+ var CloseLock = class {
2849
+ _tails = /* @__PURE__ */ new Map();
2850
+ /** Run `work` after every earlier close of `stream` has settled. */
2851
+ run(stream, work) {
2852
+ const prev = this._tails.get(stream) ?? Promise.resolve();
2853
+ const next = prev.then(work, work);
2854
+ this._tails.set(stream, next);
2855
+ const cleanup = () => {
2856
+ if (this._tails.get(stream) === next) this._tails.delete(stream);
2857
+ };
2858
+ next.then(cleanup, cleanup);
2859
+ return next;
2860
+ }
2861
+ };
2837
2862
  var SAFETY_PROBE_PAGE_SIZE = 1e3;
2838
2863
  async function run_close_cycle(targets, deps) {
2839
2864
  const target_map = new Map(targets.map((t) => [t.stream, t]));
@@ -2855,6 +2880,8 @@ async function run_close_cycle(targets, deps) {
2855
2880
  deps,
2856
2881
  () => run_full_closes(full, target_map, deps, skipped)
2857
2882
  );
2883
+ const retired = [...truncated.entries()].filter(([, r]) => r.committed.name === TOMBSTONE_EVENT).map(([stream]) => stream);
2884
+ if (retired.length) deps.forget_subscribed?.(retired);
2858
2885
  for (const [stream, entry] of windowed_result) truncated.set(stream, entry);
2859
2886
  return { truncated, skipped };
2860
2887
  }
@@ -3013,12 +3040,12 @@ async function scan_stream_heads(streams) {
3013
3040
  }
3014
3041
  return out;
3015
3042
  }
3016
- async function partition_by_safety(stream_info, reactive_events_size, skipped, page_size, catch_up_correlation) {
3043
+ async function partition_by_safety(stream_info, reactive_events_size, skipped, page_size, catch_up_correlation2) {
3017
3044
  if (reactive_events_size === 0) return [...stream_info.keys()];
3018
3045
  let needed = -1;
3019
3046
  for (const info of stream_info.values())
3020
3047
  needed = Math.max(needed, info.max_id);
3021
- const checkpoint = await catch_up_correlation(needed);
3048
+ const checkpoint = await catch_up_correlation2(needed);
3022
3049
  const uncorrelated = /* @__PURE__ */ new Set();
3023
3050
  for (const [stream, info] of stream_info) {
3024
3051
  if (checkpoint < info.max_id) uncorrelated.add(stream);
@@ -4949,8 +4976,6 @@ function build_handle_batch(logger) {
4949
4976
  }
4950
4977
 
4951
4978
  // src/act.ts
4952
- var CLOSE_CATCH_UP_LIMIT = 1e3;
4953
- var CLOSE_CATCH_UP_PASSES = 20;
4954
4979
  function validate_only_lanes(options, lanes) {
4955
4980
  if (!options.onlyLanes || options.onlyLanes.length === 0) return;
4956
4981
  const declared = /* @__PURE__ */ new Set(["default", ...lanes.map((l) => l.name)]);
@@ -5103,28 +5128,10 @@ var Act = class {
5103
5128
  _handle_batch;
5104
5129
  /** Declared drain lanes. */
5105
5130
  _lanes;
5106
- /**
5107
- * Per-stream close serialization tails, so a manual close and an
5108
- * autoclose of the same stream never prune concurrently (the manual path
5109
- * has no drain lease to exclude it). Entries are dropped once settled.
5110
- */
5111
- _close_locks = /* @__PURE__ */ new Map();
5112
- /**
5113
- * Run `work` under the per-stream close lock. Serializes close
5114
- * critical sections for the same stream (windowed prunes and full
5115
- * closes) while letting different streams proceed in parallel.
5116
- */
5117
- _with_close_lock(stream, work) {
5118
- const prev = this._close_locks.get(stream) ?? Promise.resolve();
5119
- const next = prev.then(work, work);
5120
- this._close_locks.set(stream, next);
5121
- const cleanup = () => {
5122
- if (this._close_locks.get(stream) === next)
5123
- this._close_locks.delete(stream);
5124
- };
5125
- next.then(cleanup, cleanup);
5126
- return next;
5127
- }
5131
+ /** Serializes close critical sections per stream. */
5132
+ _close_lock = new CloseLock();
5133
+ /** Every lane a controller can exist for: `"default"` plus each declared one. */
5134
+ _declared_lanes;
5128
5135
  /** Drain lanes declared via `.withLane(...)`. Implicit default not included. */
5129
5136
  get lanes() {
5130
5137
  return this._lanes;
@@ -5154,6 +5161,7 @@ var Act = class {
5154
5161
  this._states = states;
5155
5162
  this._batch_handlers = batch_handlers;
5156
5163
  this._lanes = lanes;
5164
+ this._declared_lanes = ["default", ...lanes.map((l) => l.name)];
5157
5165
  validate_only_lanes(options, lanes);
5158
5166
  this._ports = options.scoped ?? default_scope();
5159
5167
  const ports = this._ports;
@@ -5191,7 +5199,7 @@ var Act = class {
5191
5199
  this._drain = options.drain !== false;
5192
5200
  this._breaker = this._build_breaker(options);
5193
5201
  this._drain_controllers = this._build_drain_controllers(options, lanes);
5194
- this._advise_orphaned_lanes(options, lanes);
5202
+ this._advise_orphaned_lanes(options);
5195
5203
  this._audit_deps = this._build_audit_deps();
5196
5204
  this._correlate = this._build_correlate(options, classification);
5197
5205
  this._settle = this._build_settle(options);
@@ -5222,7 +5230,7 @@ var Act = class {
5222
5230
  * to `claim`.
5223
5231
  */
5224
5232
  _build_drain_controllers(options, lanes) {
5225
- const all_lanes = ["default", ...lanes.map((l) => l.name)];
5233
+ const all_lanes = this._declared_lanes;
5226
5234
  const only_set = options.onlyLanes && options.onlyLanes.length > 0 ? new Set(options.onlyLanes) : void 0;
5227
5235
  const active_lanes = only_set ? all_lanes.filter((n) => only_set.has(n)) : all_lanes;
5228
5236
  const single_default_lane = lanes.length === 0;
@@ -5240,19 +5248,7 @@ var Act = class {
5240
5248
  on_blocked: (blocked) => this.emit("blocked", blocked),
5241
5249
  // Reaction-requested close: the same machinery as `app.close`.
5242
5250
  on_close: async (targets) => {
5243
- const close_actor = { id: "$close", name: "close" };
5244
- const result = await run_close_cycle(targets, {
5245
- reactive_events_size: this._reactive_events.size,
5246
- catch_up_correlation: (until) => this._catch_up_correlation(until),
5247
- event_to_state: this._event_to_state,
5248
- load: this._es.load,
5249
- tombstone: this._es.tombstone,
5250
- logger: this._logger,
5251
- correlation: close_correlation(this._correlator, close_actor),
5252
- with_stream_lock: (stream, work) => this._with_close_lock(stream, work)
5253
- });
5254
- this._forget_closed_subscriptions(result);
5255
- this.emit("closed", result);
5251
+ await this._run_close(targets);
5256
5252
  },
5257
5253
  breaker: this._breaker,
5258
5254
  run_scoped: this._scoped,
@@ -5273,12 +5269,10 @@ var Act = class {
5273
5269
  * controller here. One process can't check that the cluster covers every
5274
5270
  * lane, so it reports its own gaps.
5275
5271
  */
5276
- _advise_orphaned_lanes(options, lanes) {
5272
+ _advise_orphaned_lanes(options) {
5277
5273
  if (!options.onlyLanes || options.onlyLanes.length === 0) return;
5278
5274
  const active = new Set(this._drain_controllers.keys());
5279
- const orphaned = ["default", ...lanes.map((l) => l.name)].filter(
5280
- (name) => !active.has(name)
5281
- );
5275
+ const orphaned = this._declared_lanes.filter((name) => !active.has(name));
5282
5276
  if (orphaned.length === 0) return;
5283
5277
  const list = orphaned.map((name) => `"${name}"`).join(", ");
5284
5278
  this._logger.info(
@@ -5294,7 +5288,7 @@ var Act = class {
5294
5288
  states: this._states,
5295
5289
  // Declared lanes, not this process's controllers: a lane another
5296
5290
  // worker drains is not `unknown-lane`.
5297
- declared_lanes: /* @__PURE__ */ new Set(["default", ...this._lanes.map((l) => l.name)]),
5291
+ declared_lanes: new Set(this._declared_lanes),
5298
5292
  routed_events: new Set(this._event_to_lanes.keys())
5299
5293
  };
5300
5294
  }
@@ -5311,10 +5305,7 @@ var Act = class {
5311
5305
  max_subscribed_streams: options.maxSubscribedStreams ?? DEFAULT_MAX_SUBSCRIBED_STREAMS,
5312
5306
  // Declared lanes (not active ones): a lane another process claims is
5313
5307
  // still a valid destination.
5314
- declared_lanes: /* @__PURE__ */ new Set([
5315
- "default",
5316
- ...this._lanes.map((l) => l.name)
5317
- ]),
5308
+ declared_lanes: new Set(this._declared_lanes),
5318
5309
  on_init: () => {
5319
5310
  if (this._drain && this._reactive_events.size > 0) this._arm_all();
5320
5311
  },
@@ -6204,6 +6195,31 @@ var Act = class {
6204
6195
  async prioritize(filter, priority) {
6205
6196
  return this._scoped(() => store2().prioritize(filter, priority));
6206
6197
  }
6198
+ /**
6199
+ * Run one close: the cycle with this Act's ports, then emit `closed`. Shared by `close()` and the drain's
6200
+ * reaction-requested closes. The close actor lets a custom correlator
6201
+ * still tag tenant context or trace ids.
6202
+ */
6203
+ async _run_close(targets) {
6204
+ const close_actor = { id: "$close", name: "close" };
6205
+ const result = await run_close_cycle(targets, {
6206
+ reactive_events_size: this._reactive_events.size,
6207
+ catch_up_correlation: (until) => catch_up_correlation(
6208
+ this._correlate,
6209
+ (limit) => this.correlate({ limit }),
6210
+ until
6211
+ ),
6212
+ event_to_state: this._event_to_state,
6213
+ load: this._es.load,
6214
+ tombstone: this._es.tombstone,
6215
+ logger: this._logger,
6216
+ correlation: close_correlation(this._correlator, close_actor),
6217
+ with_stream_lock: (stream, work) => this._close_lock.run(stream, work),
6218
+ forget_subscribed: (streams) => this._correlate.forget_subscribed(streams)
6219
+ });
6220
+ this.emit("closed", result);
6221
+ return result;
6222
+ }
6207
6223
  /**
6208
6224
  * Close the books — guard, archive, truncate, and optionally restart streams.
6209
6225
  *
@@ -6262,69 +6278,11 @@ var Act = class {
6262
6278
  * ]);
6263
6279
  * ```
6264
6280
  */
6265
- /**
6266
- * After a close, forget any target whose subscription row the truncate
6267
- * removed, so a later correlate can re-subscribe it. Restart
6268
- * targets keep their row, so only fully-retired streams are forgotten.
6269
- */
6270
- /**
6271
- * Advance correlation until the read cursor reaches `until`, and report
6272
- * where it landed. Used by the close cycle's safety probe, which
6273
- * cannot judge a subscription's pending work over events correlate has
6274
- * not resolved yet.
6275
- *
6276
- * Bounded on both ends: it stops as soon as a pass makes no progress (the
6277
- * log has no more to give), and after {@link CLOSE_CATCH_UP_PASSES}
6278
- * windows, so a close behind an enormous backlog degrades to skipping the
6279
- * stream — the documented retryable outcome — instead of scanning the
6280
- * whole log inside an operator call.
6281
- */
6282
- async _catch_up_correlation(until) {
6283
- for (let pass = 0; pass < CLOSE_CATCH_UP_PASSES && this._correlate.checkpoint < until; pass++) {
6284
- const before = this._correlate.checkpoint;
6285
- this._correlate.arm();
6286
- await this.correlate({ limit: CLOSE_CATCH_UP_LIMIT });
6287
- if (this._correlate.checkpoint <= before) break;
6288
- }
6289
- return this._correlate.checkpoint;
6290
- }
6291
- /**
6292
- * Drop retired streams from correlate's in-process "already subscribed"
6293
- * set, so a later scan re-issues `subscribe()` for them.
6294
- *
6295
- * A tombstone seed means the stream was retired; a snapshot seed means it
6296
- * was restarted and is still consuming.
6297
- *
6298
- * `truncate` no longer removes the subscription row, so this is no
6299
- * longer repairing damage the close itself did. It still matters, because
6300
- * the row can disappear later: reclaiming retired subscriptions is an
6301
- * operator job now, and that `DELETE` can land while this process is
6302
- * running. Forgetting here keeps the in-process view from outliving a row
6303
- * an operator removed, which is a silent-no-delivery failure — a reaction whose target is named after the stream would never
6304
- * be re-registered.
6305
- */
6306
- _forget_closed_subscriptions(result) {
6307
- const retired = [...result.truncated.entries()].filter(([, r]) => r.committed.name === TOMBSTONE_EVENT).map(([stream]) => stream);
6308
- if (retired.length) this._correlate.forget_subscribed(retired);
6309
- }
6310
6281
  async close(targets) {
6311
6282
  if (!targets.length) return { truncated: /* @__PURE__ */ new Map(), skipped: [] };
6312
6283
  return this._scoped(async () => {
6313
- await this.correlate({ limit: 1e3 });
6314
- const close_actor = { id: "$close", name: "close" };
6315
- const result = await run_close_cycle(targets, {
6316
- reactive_events_size: this._reactive_events.size,
6317
- catch_up_correlation: (until) => this._catch_up_correlation(until),
6318
- event_to_state: this._event_to_state,
6319
- load: this._es.load,
6320
- tombstone: this._es.tombstone,
6321
- logger: this._logger,
6322
- correlation: close_correlation(this._correlator, close_actor),
6323
- with_stream_lock: (stream, work) => this._with_close_lock(stream, work)
6324
- });
6325
- this._forget_closed_subscriptions(result);
6326
- this.emit("closed", result);
6327
- return result;
6284
+ await this.correlate({ limit: CLOSE_CATCH_UP_LIMIT });
6285
+ return this._run_close(targets);
6328
6286
  });
6329
6287
  }
6330
6288
  /**