pipework 0.176.0 → 0.177.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,13 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.177.0
4
+
5
+ - **Added: alert sources for schedules, step graphs, pipelines and traces** (failure-alert class, part 3 of 4):
6
+ - `alerts.source.schedules({ graceMs? })` raises `schedule-overdue:<name>` while a schedule's next run is more than 5 min past, which means no scheduler is firing it.
7
+ - `alerts.source.steps({ notifyAfterMs?, waitingAfterMs?, runningAfterMs? })` raises `step-run-failed:<graph>` for runs that failed since the last tick, `step-run-unnotified:<graph>` while finished runs were never notified, `step-task-waiting:<graph>` while a task waits on a person too long, and `step-run-stalled:<graph>` while a run stays running with nothing waiting on a person.
8
+ - `alerts.source.pipelines({ waitingAfterMs?, runningAfterMs? })` raises `pipeline-failed:<pipeline>`, `pipeline-waiting:<pipeline>` and `pipeline-stalled:<pipeline>`.
9
+ - `alerts.source.traces({ graceMs? })` raises `trace-expired:<entryKind>` for traces the expiry sweep force-closed, and `trace-expiry-undrained:all` while open traces are more than 26 h past expiry (the expiry job is not running).
10
+
3
11
  ## 0.176.0
4
12
 
5
13
  - **Added: alert sources for mail, storage, access links and sign-in lockouts** (failure-alert class, part 2 of 3):
package/REFERENCE.md CHANGED
@@ -1754,6 +1754,10 @@ Pass in `sources`; each raises with a fixed key on a tick and, where it can tell
1754
1754
  - `alerts.source.storage({ sweepGraceMs? = 3_600_000, severity?, owner?, runbook?, database? })` — needs `storage: {}`. `storage-expiry-undrained:all` while `storage_file` rows are `sweepGraceMs` past `expires_at` and not swept.
1755
1755
  - `alerts.source.accessLinks({ graceMs? = 900_000, severity?, owner?, runbook?, database? })` — needs `accessLinks: {}`. `access-link-abandoned:<tenantId>` while uses stay `pending` `graceMs` past `reserved_until`.
1756
1756
  - `alerts.source.lockouts({ tables? = the ones that exist, severity? = 'warning', owner?, runbook?, database? })` — `auth-lockout:<table>` while rows have `locked_until` in the future (count only; no account is named). `pipework_signin_attempts` needs `passwords: {}`, `pipework_guard_attempts` needs `guards: {}`; with `tables` omitted, the tables that exist are resolved once on the first evaluate (it throws, naming both keys, if neither does); pass `tables` to override.
1757
+ - `alerts.source.schedules({ graceMs? = 300_000, severity?, owner?, runbook?, database? })` — `schedule-overdue:<name>` while a schedule's `next_run_at` is more than `graceMs` past (every scheduler pass moves it forward, firing or skipping, so overdue means no scheduler is running); resolves when it catches up. Needs a worker surface with schedules.
1758
+ - `alerts.source.steps({ notifyAfterMs? = 900_000, waitingAfterMs? = 3_600_000, runningAfterMs? = 3_600_000, settleMs?, severity?, owner?, runbook?, database? })` — `step-run-failed:<graph>` for runs that failed since the last tick (context `count`, `lastError`, `lastRunId`, `lastTenantId`; clears by the quiet period); `step-run-unnotified:<graph>` while runs finished more than `notifyAfterMs` ago still have `notified = false`; `step-task-waiting:<graph>` while a task has waited for a person's decision more than `waitingAfterMs` (measured from its run's `created_at`); `step-run-stalled:<graph>` while runs are still `running` more than `runningAfterMs` after `created_at` with no task `waiting` (`blocked` and `queued` tasks are work in flight). Needs a step graph.
1759
+ - `alerts.source.pipelines({ waitingAfterMs? = 3_600_000, runningAfterMs? = 3_600_000, settleMs?, severity?, owner?, runbook?, database? })` — `pipeline-failed:<pipeline>` for runs that failed since the last tick (context `count`, `lastError`, `lastRunId`, `lastTenantId`); `pipeline-waiting:<pipeline>` while runs have been `waiting` more than `waitingAfterMs` since they started (`started_at`; no wait time is recorded); `pipeline-stalled:<pipeline>` while runs are `running` more than `runningAfterMs` after `started_at`. Needs the app's `pipework_pipeline_runs` table.
1760
+ - `alerts.source.traces({ graceMs? = 93_600_000, settleMs?, severity?, owner?, runbook?, database? })` — `trace-expired:<entryKind>` for traces the expiry sweep force-closed since the last tick (read from `closed_at` where `status = 'expired'`); `trace-expiry-undrained:all` while open traces are more than `graceMs` (default 26 h, as the maintenance job is daily) past `expires_at`, meaning the expiry job is not running. Needs the `trace` block in the blueprint.
1757
1761
  - `queue.totals(db)` — `{ overall, byType }`, each `{ ready, running, oldestReadyWaitMs }` (ready: pending and not waiting on a retry time; running: claimed or running; wait from `queued_at`, null when none is ready); `byType` omits a type with neither.
1758
1762
  - `alerts.source.health(checks, { severity? = 'error' })` — `health:<name>` while a `HealthCheck` is unhealthy or throws; resolves when it recovers. Degraded is not a fault.
1759
1763
 
package/dist/REFERENCE.md CHANGED
@@ -1,7 +1,7 @@
1
1
  # Pipework API Reference
2
2
 
3
3
  > Auto-generated from source JSDoc. Do not edit manually.
4
- > Generated: 2026-10-20
4
+ > Generated: 2026-10-22
5
5
 
6
6
  ## Contents
7
7
 
@@ -816,6 +816,10 @@ Acquires a transaction-scoped advisory lock. Released at commit/rollback.
816
816
 
817
817
  Runs a function in a SERIALIZABLE transaction with automatic retry on serialization failures and deadlocks.
818
818
 
819
+ ### `pipe.withTimeouts`
820
+
821
+ Sets statement_timeout and/or lock_timeout for the current transaction in one statement, then runs fn; a statement cancelled for them rejects with StatementTimeoutError or LockTimeoutError.
822
+
819
823
  ### `pipe.bulkSet`
820
824
 
821
825
  Bulk UPDATE ... FROM (VALUES ...) — updates multiple rows with per-row values in a single statement.
@@ -824,6 +828,10 @@ Bulk UPDATE ... FROM (VALUES ...) — updates multiple rows with per-row values
824
828
 
825
829
  Produces a typed VALUES clause for bulk operations — the base primitive for bulkSet and bulkUpsert.
826
830
 
831
+ ### `pipe.fn`
832
+
833
+ A set-returning SQL function as a typed source for `.from()` and joins — `pipe.fn('schema.f', { args: [field.uuid()], columns: { path: field.text() } })`. Arguments are bound and cast to their declared types.
834
+
827
835
  ### `pipe.field`
828
836
 
829
837
  Field builders for domain definitions — uuid(), text(), integer(), etc.
@@ -836,6 +844,10 @@ Registers a domain definition with table, validators, and factory projections. T
836
844
 
837
845
  Returns the global registry of all domain definitions.
838
846
 
847
+ ### `pipe.external`
848
+
849
+ Declares a table or view another service owns (`pipe.external(name, fields, { schema, table? })`): typed columns and every query operator, read-only, never migrated, not tenant-scoped.
850
+
839
851
  ### `pipe.update`
840
852
 
841
853
  Pipework-owned UPDATE builder — the only consumer-facing way to update pipework-managed tables (Q8).
@@ -866,12 +878,54 @@ interface WindowSpec
866
878
  interface ValueColumnDef
867
879
  ```
868
880
 
881
+ **`JsonbElements`** — A jsonb array read as its elements' text. Produced by {@link jsonbElements}.
882
+
883
+ ```typescript
884
+ interface JsonbElements
885
+ ```
886
+
887
+ **`ArraySource`** — Something whose elements `arrayAny` / `arrayAll` can test.
888
+
889
+ ```typescript
890
+ type ArraySource =
891
+ ```
892
+
893
+ **`ElementOf`** — The element type of an {@link ArraySource}.
894
+
895
+ ```typescript
896
+ type ElementOf<S> =
897
+ ```
898
+
899
+ **`FunctionSpec`** — Declares a SQL function's argument and result-column shapes. See {@link fn}.
900
+
901
+ ```typescript
902
+ interface FunctionSpec<TArgs extends readonly AnyField[], TColumns extends Record<string, AnyField>>
903
+ ```
904
+
905
+ **`FunctionSourceFields`** — The selected fields of a function source: each result column as a typed SQL expression.
906
+
907
+ ```typescript
908
+ type FunctionSourceFields<TColumns extends Record<string, AnyField>> =
909
+ ```
910
+
911
+ **`FunctionSource`** — A function call usable in `.from()` and joins; its result columns are properties of it.
912
+
913
+ ```typescript
914
+ type FunctionSource<TAlias extends string, TColumns extends Record<string, AnyField>> =
915
+ ```
916
+
869
917
  **`SerializableOptions`** — Retry policy for {@link serializable}: how many attempts on a serialization failure / deadlock, and the base backoff between them.
870
918
 
871
919
  ```typescript
872
920
  interface SerializableOptions
873
921
  ```
874
922
 
923
+ **`TimeoutOptions`** — Which timeouts {@link withTimeouts} sets; each a positive integer number of milliseconds.
924
+
925
+ ```typescript
926
+ interface TimeoutOptions
927
+ ```
928
+
875
929
  **`ManagedConnection`** — A standalone pooled connection: the raw postgres.js client, its drizzle handle, and a `close()` that ends the pool.
876
930
 
877
931
  ```typescript
@@ -892,6 +946,10 @@ JSONB query operators — typed helpers for PostgreSQL JSONB containment, key ch
892
946
 
893
947
  The @> containment operator — tests whether a JSONB column contains the given value.
894
948
 
949
+ ### `jsonb.merge`
950
+
951
+ Merges an object into a JSONB column in `.set()`: `coalesce(col, '{}') || value`. Top-level keys overwrite; others are kept.
952
+
895
953
  ### `jsonb.containedBy`
896
954
 
897
955
  The <@ contained-by operator — tests whether a JSONB column is contained by the given value.
@@ -958,6 +1016,60 @@ type Schema<T = unknown> = z.ZodType<T>
958
1016
  type Infer<T extends Schema> = z.infer<T>
959
1017
  ```
960
1018
 
1019
+ **`StringSchema`** — A string validator — what check.string() returns, nameable without importing zod.
1020
+
1021
+ ```typescript
1022
+ interface StringSchema extends z.ZodString
1023
+ ```
1024
+
1025
+ **`NumberSchema`** — A number validator — what check.number() returns.
1026
+
1027
+ ```typescript
1028
+ interface NumberSchema extends z.ZodNumber
1029
+ ```
1030
+
1031
+ **`BooleanSchema`** — A boolean validator — what check.boolean() returns.
1032
+
1033
+ ```typescript
1034
+ interface BooleanSchema extends z.ZodBoolean
1035
+ ```
1036
+
1037
+ **`EnumSchema`** — An enum validator over string literals — what check.enum([...]) returns.
1038
+
1039
+ ```typescript
1040
+ interface EnumSchema<V extends string = string> extends z.ZodEnum<
1041
+ ```
1042
+
1043
+ **`LiteralSchema`** — A literal validator — what check.literal(v) returns.
1044
+
1045
+ ```typescript
1046
+ interface LiteralSchema<V extends string | number | boolean | null = string> extends z.ZodLiteral<V>
1047
+ ```
1048
+
1049
+ **`ArraySchema`** — An array validator — what check.array(item) returns.
1050
+
1051
+ ```typescript
1052
+ interface ArraySchema<Item extends z.core.SomeType = z.core.SomeType> extends z.ZodArray<Item>
1053
+ ```
1054
+
1055
+ **`OptionalSchema`** — An optional validator — what check.optional(inner) returns.
1056
+
1057
+ ```typescript
1058
+ interface OptionalSchema<Inner extends z.core.SomeType = z.core.SomeType> extends z.ZodOptional<Inner>
1059
+ ```
1060
+
1061
+ **`NullableSchema`** — A nullable validator — what check.nullable(inner) returns.
1062
+
1063
+ ```typescript
1064
+ interface NullableSchema<Inner extends z.core.SomeType = z.core.SomeType> extends z.ZodNullable<Inner>
1065
+ ```
1066
+
1067
+ **`ObjectSchema`** — An object validator whose .extend, .pick, .omit and .partial results stay ObjectSchema — what check.object({...}) returns.
1068
+
1069
+ ```typescript
1070
+ type ObjectSchema<S extends Shape = Shape> =
1071
+ ```
1072
+
961
1073
  ## temporal — Bitemporal Data
962
1074
 
963
1075
  Temporal (bitemporal) data namespace — version history with effective date ranges.
@@ -1474,7 +1586,11 @@ interface RateLimitConfig
1474
1586
  interface RateLimitWindow
1475
1587
  ```
1476
1588
 
1477
- **`RateLimitClass`** — A named limit class: any of a per-user, per-tenant and per-address window, each counted on its own.
1589
+ **`RateLimitClass`**
1590
+
1591
+ A named limit class: any of a per-user, per-tenant, per-address and total window, each counted on its own.
1592
+ Each key takes one window or an array of windows (distinct `windowSeconds`); a request is counted against
1593
+ all of a key's windows and refused if any is over.
1478
1594
 
1479
1595
  ```typescript
1480
1596
  interface RateLimitClass
@@ -1490,8 +1606,8 @@ interface RateLimitRefusal
1490
1606
 
1491
1607
  Named limit classes, checked after auth and counted in Postgres (`pipework_rate_limit_counts`, opted in
1492
1608
  with the blueprint's `rateLimits: {}`), so every server process on the same database shares one count.
1493
- Windows are counted perUser, perTenant, perAddress in turn, up to the first one over its max, so one user's
1494
- refused requests don't spend the tenant's budget. A route is in `signedIn` (auth required, or optional with
1609
+ Keys are counted perUser, perTenant, perAddress, total in turn, up to the first key with a window over its max, so one user's
1610
+ refused requests don't spend the tenant's budget. The 429's Retry-After is the longest wait of the windows that refused. A route is in `signedIn` (auth required, or optional with
1495
1611
  a user), `public` (no auth, or optional without a user) or the class its fitting names with `.rateLimit(name)`.
1496
1612
 
1497
1613
  ```typescript
@@ -1643,15 +1759,20 @@ interface TraceTree
1643
1759
 
1644
1760
  ## data
1645
1761
 
1646
- ### `tap`
1762
+ ### `StatementTimeoutError`
1763
+
1764
+ A statement was cancelled by Postgres for running past the statement timeout a {@link withTimeouts} call set. `cause` is the driver error.
1765
+
1766
+ ```typescript
1767
+ class StatementTimeoutError extends Error constructor(readonly statementTimeoutMs: number, cause: unknown)
1768
+ ```
1769
+
1770
+ ### `LockTimeoutError`
1647
1771
 
1648
- Opens a standalone managed connection outside the manifold's pools — the
1649
- sanctioned door for contexts where `pipe()` structurally cannot resolve:
1650
- `worker_threads`, detached monitors, one-off scripts. Callers own the
1651
- lifecycle: always `await conn.close()`.
1772
+ A statement gave up waiting for a lock past the lock timeout a {@link withTimeouts} call set. `cause` is the driver error.
1652
1773
 
1653
1774
  ```typescript
1654
- function tap(url: string, options?: ConnectOptions): ManagedConnection
1775
+ class LockTimeoutError extends Error constructor(readonly lockTimeoutMs: number, cause: unknown)
1655
1776
  ```
1656
1777
 
1657
1778
  ## request
@@ -0,0 +1,54 @@
1
+ import { type AlertSource } from './sources.js';
2
+ import { type Basics } from './source-options.js';
3
+ /**
4
+ * Raises `schedule-overdue:<schedule name>` while a cron schedule's `next_run_at` is more than `graceMs` (default 5 min)
5
+ * in the past. Every scheduler pass moves `next_run_at` into the future, whether it fires the job or skips it because
6
+ * the previous run is still pending, so an overdue row means no scheduler is running (or it cannot reach the row).
7
+ * Resolves when the scheduler catches up. Needs a worker surface that declares schedules (the `pipework_schedules` table; no blueprint key).
8
+ */
9
+ export declare function schedulesSource(options?: Basics & {
10
+ graceMs?: number;
11
+ }): AlertSource;
12
+ /**
13
+ * Raises `step-run-failed:<graph>` for step runs that failed since the last tick (message with the count and the last
14
+ * error; context `count`, `lastError`, `lastRunId`, `lastTenantId`), `step-run-unnotified:<graph>` while runs finished
15
+ * more than `notifyAfterMs` (default 15 min) ago still have `notified = false` (the graph's `onDone` has not run), and
16
+ * `step-task-waiting:<graph>` while a task has waited for a person's decision more than `waitingAfterMs` (default 1 h);
17
+ * the wait is measured from its run's `created_at`, as tasks carry no timestamp, and `step-run-stalled:<graph>` while runs
18
+ * are still `running` more than `runningAfterMs` (default 1 h) after `created_at` with no task `waiting` (a `waiting` task is a
19
+ * person's decision and is covered above; `blocked` and `queued` tasks are work in flight, so a run stuck on them is stalled). A failed task always fails its run in the
20
+ * same transaction, so failed runs cover failed tasks. The failed condition clears by the handle's quiet period; the other two
21
+ * resolve when the rows drain. Needs a step graph defined in the app (the `pipework_step_run` and `pipework_step_task` tables; no blueprint key).
22
+ */
23
+ export declare function stepsSource(options?: Basics & {
24
+ notifyAfterMs?: number;
25
+ waitingAfterMs?: number;
26
+ runningAfterMs?: number;
27
+ settleMs?: number;
28
+ }): AlertSource;
29
+ /**
30
+ * Raises `pipeline-failed:<pipeline name>` for pipeline runs that failed since the last tick (context `count`,
31
+ * `lastError`, `lastRunId`, `lastTenantId`), and `pipeline-waiting:<pipeline name>` while runs sit in `waiting` more than
32
+ * `waitingAfterMs` (default 1 h) after they started (the table keeps no time for when a run began to wait, so the age is
33
+ * `started_at`), and `pipeline-stalled:<pipeline name>` while runs are `running` more than `runningAfterMs` (default 1 h)
34
+ * after `started_at` (the process died mid-run). The failed condition clears by the handle's quiet period; the others
35
+ * resolve when the runs resume or finish. Needs the app's own `pipework_pipeline_runs` table (pipelines have no blueprint key; the app creates it).
36
+ */
37
+ export declare function pipelinesSource(options?: Basics & {
38
+ waitingAfterMs?: number;
39
+ runningAfterMs?: number;
40
+ settleMs?: number;
41
+ }): AlertSource;
42
+ /**
43
+ * Raises `trace-expired:<entry kind>` (http, job, cron, test) for traces the expiry sweep force-closed since the last
44
+ * tick: the sweep stamps `status = 'expired'` and `closed_at`, so `closed_at` is the cursor. Also raises
45
+ * `trace-expiry-undrained:all` while traces still `open` have an `expires_at` more than `graceMs` (default 26 h: the maintenance job that
46
+ * runs the sweep is daily, so a trace legitimately stays open up to a day past its deadline) in the past, which means
47
+ * nothing is running the expiry job. The expired condition clears by the handle's quiet period; the
48
+ * undrained one resolves once the sweep runs. Needs the blueprint's `trace` block (the `trace` table).
49
+ */
50
+ export declare function tracesSource(options?: Basics & {
51
+ graceMs?: number;
52
+ settleMs?: number;
53
+ }): AlertSource;
54
+ //# sourceMappingURL=async-sources.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-sources.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/async-sources.ts"],"names":[],"mappings":"AAIA,OAAO,EAA8C,KAAK,WAAW,EAAE,MAAM,cAAc,CAAA;AAC3F,OAAO,EAA6C,KAAK,MAAM,EAAE,MAAM,qBAAqB,CAAA;AAuB5F;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,WAAW,CAoBxF;AAED;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,OAAO,GAAE,MAAM,GAAG;IAAE,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,WAAW,CAiE/J;AAED;;;;;;;GAOG;AACH,wBAAgB,eAAe,CAAC,OAAO,GAAE,MAAM,GAAG;IAAE,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,cAAc,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,WAAW,CA+C3I;AAED;;;;;;;GAOG;AACH,wBAAgB,YAAY,CAAC,OAAO,GAAE,MAAM,GAAG;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,WAAW,CA+BxG"}
@@ -0,0 +1,233 @@
1
+ // Sources over the failures the async subsystems already record: cron schedules, step graphs, pipelines and
2
+ // trace expiry. Each is a composition of `querySource` and `newRowsSource`.
3
+ import { sql } from '../../data/db/sql.js';
4
+ import { composeSources, newRowsSource, querySource } from './sources.js';
5
+ import { common, positive, text, FIFTEEN_MIN, HOUR } from './source-options.js';
6
+ const FIVE_MIN = 5 * 60_000;
7
+ const TRACE_SWEEP_GRACE = 26 * HOUR;
8
+ /** The `error` jsonb of a recorded failure as one line: its `message`, `error` or `step`/`error` pair, else the JSON. */
9
+ function errorText(v) {
10
+ if (v === null || v === undefined)
11
+ return null;
12
+ const parsed = typeof v === 'string' ? safeParse(v) : v;
13
+ if (typeof parsed === 'string')
14
+ return parsed;
15
+ if (typeof parsed === 'object' && parsed !== null) {
16
+ const o = parsed;
17
+ const inner = o['message'] ?? o['error'];
18
+ if (typeof inner === 'string')
19
+ return typeof o['step'] === 'string' ? `${o['step']}: ${inner}` : inner;
20
+ if (typeof inner === 'object' && inner !== null)
21
+ return errorText(inner);
22
+ }
23
+ return JSON.stringify(parsed);
24
+ }
25
+ function safeParse(s) {
26
+ try {
27
+ return JSON.parse(s);
28
+ }
29
+ catch {
30
+ return s;
31
+ }
32
+ }
33
+ /**
34
+ * Raises `schedule-overdue:<schedule name>` while a cron schedule's `next_run_at` is more than `graceMs` (default 5 min)
35
+ * in the past. Every scheduler pass moves `next_run_at` into the future, whether it fires the job or skips it because
36
+ * the previous run is still pending, so an overdue row means no scheduler is running (or it cannot reach the row).
37
+ * Resolves when the scheduler catches up. Needs a worker surface that declares schedules (the `pipework_schedules` table; no blueprint key).
38
+ */
39
+ export function schedulesSource(options = {}) {
40
+ const grace = positive(options.graceMs ?? FIVE_MIN, 'graceMs', 'alerts.source.schedules');
41
+ return querySource({
42
+ ...common(options),
43
+ name: 'schedule-overdue',
44
+ query: sql `
45
+ SELECT name, next_run_at, last_run_at, (extract(epoch FROM clock_timestamp() - next_run_at) * 1000)::bigint AS overdue_ms
46
+ FROM pipework_schedules
47
+ WHERE next_run_at < clock_timestamp() - ${grace} * interval '1 millisecond'
48
+ ORDER BY name`,
49
+ id: r => String(r['name']),
50
+ message: r => `schedule ${String(r['name'])} is ${String(r['overdue_ms'])} ms past its next run; is the scheduler running?`,
51
+ subject: r => ({ entity: 'schedule', entityId: String(r['name']) }),
52
+ context: r => ({
53
+ schedule: String(r['name']),
54
+ overdueMs: Number(r['overdue_ms']),
55
+ nextRunAt: new Date(String(r['next_run_at'])).toISOString(),
56
+ lastRunAt: r['last_run_at'] === null ? null : new Date(String(r['last_run_at'])).toISOString(),
57
+ }),
58
+ });
59
+ }
60
+ /**
61
+ * Raises `step-run-failed:<graph>` for step runs that failed since the last tick (message with the count and the last
62
+ * error; context `count`, `lastError`, `lastRunId`, `lastTenantId`), `step-run-unnotified:<graph>` while runs finished
63
+ * more than `notifyAfterMs` (default 15 min) ago still have `notified = false` (the graph's `onDone` has not run), and
64
+ * `step-task-waiting:<graph>` while a task has waited for a person's decision more than `waitingAfterMs` (default 1 h);
65
+ * the wait is measured from its run's `created_at`, as tasks carry no timestamp, and `step-run-stalled:<graph>` while runs
66
+ * are still `running` more than `runningAfterMs` (default 1 h) after `created_at` with no task `waiting` (a `waiting` task is a
67
+ * person's decision and is covered above; `blocked` and `queued` tasks are work in flight, so a run stuck on them is stalled). A failed task always fails its run in the
68
+ * same transaction, so failed runs cover failed tasks. The failed condition clears by the handle's quiet period; the other two
69
+ * resolve when the rows drain. Needs a step graph defined in the app (the `pipework_step_run` and `pipework_step_task` tables; no blueprint key).
70
+ */
71
+ export function stepsSource(options = {}) {
72
+ const notifyAfter = positive(options.notifyAfterMs ?? FIFTEEN_MIN, 'notifyAfterMs', 'alerts.source.steps');
73
+ const waitingAfter = positive(options.waitingAfterMs ?? HOUR, 'waitingAfterMs', 'alerts.source.steps');
74
+ const runningAfter = positive(options.runningAfterMs ?? HOUR, 'runningAfterMs', 'alerts.source.steps');
75
+ const failed = newRowsSource({
76
+ ...common(options),
77
+ name: 'step-run-failed',
78
+ table: 'pipework_step_run',
79
+ at: 'finished_at',
80
+ where: sql `t.status = 'failed'`,
81
+ groupBy: 'graph',
82
+ ...(options.settleMs !== undefined ? { settleMs: options.settleMs } : {}),
83
+ message: g => `${String(g.count)} run(s) of step graph ${g.id} failed; last error: ${text(errorText(g.last['error']))}`,
84
+ context: g => ({
85
+ graph: g.id,
86
+ count: g.count,
87
+ lastError: errorText(g.last['error']),
88
+ lastRunId: String(g.last['id']),
89
+ lastTenantId: String(g.last['tenant_id']),
90
+ }),
91
+ });
92
+ const unnotified = querySource({
93
+ ...common(options),
94
+ name: 'step-run-unnotified',
95
+ query: sql `
96
+ SELECT graph, count(*)::int AS n, (extract(epoch FROM clock_timestamp() - min(finished_at)) * 1000)::bigint AS oldest_ms
97
+ FROM pipework_step_run
98
+ WHERE status = 'done' AND notified = false
99
+ AND finished_at < clock_timestamp() - ${notifyAfter} * interval '1 millisecond'
100
+ GROUP BY graph ORDER BY graph`,
101
+ id: r => String(r['graph']),
102
+ message: r => `${String(r['n'])} finished run(s) of step graph ${String(r['graph'])} not notified for more than ${String(notifyAfter)} ms (oldest ${String(r['oldest_ms'])} ms)`,
103
+ subject: r => ({ entity: 'step-graph', entityId: String(r['graph']) }),
104
+ context: r => ({ graph: String(r['graph']), count: Number(r['n']), oldestMs: Number(r['oldest_ms']) }),
105
+ });
106
+ const waiting = querySource({
107
+ ...common(options),
108
+ name: 'step-task-waiting',
109
+ query: sql `
110
+ SELECT r.graph, count(*)::int AS n, (extract(epoch FROM clock_timestamp() - min(r.created_at)) * 1000)::bigint AS oldest_ms
111
+ FROM pipework_step_task k JOIN pipework_step_run r ON r.id = k.run_id
112
+ WHERE k.status = 'waiting' AND r.status = 'running'
113
+ AND r.created_at < clock_timestamp() - ${waitingAfter} * interval '1 millisecond'
114
+ GROUP BY r.graph ORDER BY r.graph`,
115
+ id: r => String(r['graph']),
116
+ message: r => `${String(r['n'])} task(s) of step graph ${String(r['graph'])} waiting more than ${String(waitingAfter)} ms (oldest run ${String(r['oldest_ms'])} ms old)`,
117
+ subject: r => ({ entity: 'step-graph', entityId: String(r['graph']) }),
118
+ context: r => ({ graph: String(r['graph']), count: Number(r['n']), oldestMs: Number(r['oldest_ms']) }),
119
+ });
120
+ const stalled = querySource({
121
+ ...common(options),
122
+ name: 'step-run-stalled',
123
+ query: sql `
124
+ SELECT r.graph, count(*)::int AS n, (extract(epoch FROM clock_timestamp() - min(r.created_at)) * 1000)::bigint AS oldest_ms
125
+ FROM pipework_step_run r
126
+ WHERE r.status = 'running'
127
+ AND r.created_at < clock_timestamp() - ${runningAfter} * interval '1 millisecond'
128
+ AND NOT EXISTS (SELECT 1 FROM pipework_step_task k WHERE k.run_id = r.id AND k.status = 'waiting')
129
+ GROUP BY r.graph ORDER BY r.graph`,
130
+ id: r => String(r['graph']),
131
+ message: r => `${String(r['n'])} run(s) of step graph ${String(r['graph'])} still running after more than ${String(runningAfter)} ms with no person step waiting (oldest ${String(r['oldest_ms'])} ms)`,
132
+ subject: r => ({ entity: 'step-graph', entityId: String(r['graph']) }),
133
+ context: r => ({ graph: String(r['graph']), count: Number(r['n']), oldestMs: Number(r['oldest_ms']) }),
134
+ });
135
+ return composeSources('steps', [failed, unnotified, waiting, stalled]);
136
+ }
137
+ /**
138
+ * Raises `pipeline-failed:<pipeline name>` for pipeline runs that failed since the last tick (context `count`,
139
+ * `lastError`, `lastRunId`, `lastTenantId`), and `pipeline-waiting:<pipeline name>` while runs sit in `waiting` more than
140
+ * `waitingAfterMs` (default 1 h) after they started (the table keeps no time for when a run began to wait, so the age is
141
+ * `started_at`), and `pipeline-stalled:<pipeline name>` while runs are `running` more than `runningAfterMs` (default 1 h)
142
+ * after `started_at` (the process died mid-run). The failed condition clears by the handle's quiet period; the others
143
+ * resolve when the runs resume or finish. Needs the app's own `pipework_pipeline_runs` table (pipelines have no blueprint key; the app creates it).
144
+ */
145
+ export function pipelinesSource(options = {}) {
146
+ const waitingAfter = positive(options.waitingAfterMs ?? HOUR, 'waitingAfterMs', 'alerts.source.pipelines');
147
+ const runningAfter = positive(options.runningAfterMs ?? HOUR, 'runningAfterMs', 'alerts.source.pipelines');
148
+ const failed = newRowsSource({
149
+ ...common(options),
150
+ name: 'pipeline-failed',
151
+ table: 'pipework_pipeline_runs',
152
+ at: 'completed_at',
153
+ where: sql `t.status = 'failed'`,
154
+ groupBy: 'pipeline_name',
155
+ ...(options.settleMs !== undefined ? { settleMs: options.settleMs } : {}),
156
+ message: g => `${String(g.count)} run(s) of pipeline ${g.id} failed; last error: ${text(errorText(g.last['error']))}`,
157
+ context: g => ({
158
+ pipeline: g.id,
159
+ count: g.count,
160
+ lastError: errorText(g.last['error']),
161
+ lastRunId: String(g.last['id']),
162
+ lastTenantId: String(g.last['tenant_id']),
163
+ }),
164
+ });
165
+ const waiting = querySource({
166
+ ...common(options),
167
+ name: 'pipeline-waiting',
168
+ query: sql `
169
+ SELECT pipeline_name, count(*)::int AS n, (extract(epoch FROM clock_timestamp() - min(started_at)) * 1000)::bigint AS oldest_ms
170
+ FROM pipework_pipeline_runs
171
+ WHERE status = 'waiting' AND started_at < clock_timestamp() - ${waitingAfter} * interval '1 millisecond'
172
+ GROUP BY pipeline_name ORDER BY pipeline_name`,
173
+ id: r => String(r['pipeline_name']),
174
+ message: r => `${String(r['n'])} run(s) of pipeline ${String(r['pipeline_name'])} waiting more than ${String(waitingAfter)} ms (oldest ${String(r['oldest_ms'])} ms)`,
175
+ subject: r => ({ entity: 'pipeline', entityId: String(r['pipeline_name']) }),
176
+ context: r => ({ pipeline: String(r['pipeline_name']), count: Number(r['n']), oldestMs: Number(r['oldest_ms']) }),
177
+ });
178
+ const stalled = querySource({
179
+ ...common(options),
180
+ name: 'pipeline-stalled',
181
+ query: sql `
182
+ SELECT pipeline_name, count(*)::int AS n, (extract(epoch FROM clock_timestamp() - min(started_at)) * 1000)::bigint AS oldest_ms
183
+ FROM pipework_pipeline_runs
184
+ WHERE status = 'running' AND started_at < clock_timestamp() - ${runningAfter} * interval '1 millisecond'
185
+ GROUP BY pipeline_name ORDER BY pipeline_name`,
186
+ id: r => String(r['pipeline_name']),
187
+ message: r => `${String(r['n'])} run(s) of pipeline ${String(r['pipeline_name'])} still running after more than ${String(runningAfter)} ms (oldest ${String(r['oldest_ms'])} ms)`,
188
+ subject: r => ({ entity: 'pipeline', entityId: String(r['pipeline_name']) }),
189
+ context: r => ({ pipeline: String(r['pipeline_name']), count: Number(r['n']), oldestMs: Number(r['oldest_ms']) }),
190
+ });
191
+ return composeSources('pipelines', [failed, waiting, stalled]);
192
+ }
193
+ /**
194
+ * Raises `trace-expired:<entry kind>` (http, job, cron, test) for traces the expiry sweep force-closed since the last
195
+ * tick: the sweep stamps `status = 'expired'` and `closed_at`, so `closed_at` is the cursor. Also raises
196
+ * `trace-expiry-undrained:all` while traces still `open` have an `expires_at` more than `graceMs` (default 26 h: the maintenance job that
197
+ * runs the sweep is daily, so a trace legitimately stays open up to a day past its deadline) in the past, which means
198
+ * nothing is running the expiry job. The expired condition clears by the handle's quiet period; the
199
+ * undrained one resolves once the sweep runs. Needs the blueprint's `trace` block (the `trace` table).
200
+ */
201
+ export function tracesSource(options = {}) {
202
+ const grace = positive(options.graceMs ?? TRACE_SWEEP_GRACE, 'graceMs', 'alerts.source.traces');
203
+ const expired = newRowsSource({
204
+ ...common(options),
205
+ name: 'trace-expired',
206
+ table: 'trace',
207
+ at: 'closed_at',
208
+ where: sql `t.status = 'expired'`,
209
+ groupBy: 'entry_kind',
210
+ ...(options.settleMs !== undefined ? { settleMs: options.settleMs } : {}),
211
+ message: g => `${String(g.count)} ${g.id} trace(s) force-closed after expiring; last trace ${String(g.last['id'])}`,
212
+ context: g => ({
213
+ entryKind: g.id,
214
+ count: g.count,
215
+ lastTraceId: String(g.last['id']),
216
+ lastTenantId: g.last['tenant_id'] === null || g.last['tenant_id'] === undefined ? null : String(g.last['tenant_id']),
217
+ }),
218
+ });
219
+ const undrained = querySource({
220
+ ...common(options),
221
+ name: 'trace-expiry-undrained',
222
+ query: sql `
223
+ SELECT count(*)::int AS n, (extract(epoch FROM clock_timestamp() - min(expires_at)) * 1000)::bigint AS oldest_ms
224
+ FROM "trace"
225
+ WHERE status = 'open' AND expires_at <= clock_timestamp() - ${grace} * interval '1 millisecond'
226
+ HAVING count(*) > 0`,
227
+ id: () => 'all',
228
+ message: r => `${String(r['n'])} open trace(s) expired more than ${String(grace)} ms ago and not closed; is the trace expiry job scheduled?`,
229
+ context: r => ({ count: Number(r['n']), oldestMs: Number(r['oldest_ms']) }),
230
+ });
231
+ return composeSources('traces', [expired, undrained]);
232
+ }
233
+ //# sourceMappingURL=async-sources.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"async-sources.js","sourceRoot":"","sources":["../../../src/infra/alerts/async-sources.ts"],"names":[],"mappings":"AAAA,4GAA4G;AAC5G,4EAA4E;AAE5E,OAAO,EAAE,GAAG,EAAE,MAAM,sBAAsB,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,WAAW,EAAoB,MAAM,cAAc,CAAA;AAC3F,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,IAAI,EAAE,WAAW,EAAE,IAAI,EAAe,MAAM,qBAAqB,CAAA;AAE5F,MAAM,QAAQ,GAAG,CAAC,GAAG,MAAM,CAAA;AAC3B,MAAM,iBAAiB,GAAG,EAAE,GAAG,IAAI,CAAA;AAEnC,yHAAyH;AACzH,SAAS,SAAS,CAAC,CAAU;IAC3B,IAAI,CAAC,KAAK,IAAI,IAAI,CAAC,KAAK,SAAS;QAAE,OAAO,IAAI,CAAA;IAC9C,MAAM,MAAM,GAAG,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAA;IACvD,IAAI,OAAO,MAAM,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAA;IAC7C,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,KAAK,IAAI,EAAE,CAAC;QAClD,MAAM,CAAC,GAAG,MAAiC,CAAA;QAC3C,MAAM,KAAK,GAAG,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,CAAA;QACxC,IAAI,OAAO,KAAK,KAAK,QAAQ;YAAE,OAAO,OAAO,CAAC,CAAC,MAAM,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,KAAK,CAAA;QACtG,IAAI,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,SAAS,CAAC,KAAK,CAAC,CAAA;IAC1E,CAAC;IACD,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAA;AAC/B,CAAC;AAED,SAAS,SAAS,CAAC,CAAS;IAC1B,IAAI,CAAC;QAAC,OAAO,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAA;IAAC,CAAC;IAAC,MAAM,CAAC;QAAC,OAAO,CAAC,CAAA;IAAC,CAAC;AACjD,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,eAAe,CAAC,UAAyC,EAAE;IACzE,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,QAAQ,EAAE,SAAS,EAAE,yBAAyB,CAAC,CAAA;IACzF,OAAO,WAAW,CAAC;QACjB,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,GAAG,CAAA;;;gDAGkC,KAAK;oBACjC;QAChB,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;QAC1B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,YAAY,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,OAAO,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,kDAAkD;QAC3H,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,EAAE,CAAC;QACnE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACb,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC3B,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;YAClC,SAAS,EAAE,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;YAC3D,SAAS,EAAE,CAAC,CAAC,aAAa,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,MAAM,CAAC,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE;SAC/F,CAAC;KACH,CAAC,CAAA;AACJ,CAAC;AAED;;;;;;;;;;GAUG;AACH,MAAM,UAAU,WAAW,CAAC,UAAoH,EAAE;IAChJ,MAAM,WAAW,GAAG,QAAQ,CAAC,OAAO,CAAC,aAAa,IAAI,WAAW,EAAE,eAAe,EAAE,qBAAqB,CAAC,CAAA;IAC1G,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,CAAA;IACtG,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,EAAE,gBAAgB,EAAE,qBAAqB,CAAC,CAAA;IACtG,MAAM,MAAM,GAAG,aAAa,CAAC;QAC3B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,mBAAmB;QAC1B,EAAE,EAAE,aAAa;QACjB,KAAK,EAAE,GAAG,CAAA,qBAAqB;QAC/B,OAAO,EAAE,OAAO;QAChB,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,yBAAyB,CAAC,CAAC,EAAE,wBAAwB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QACvH,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACb,KAAK,EAAE,CAAC,CAAC,EAAE;YACX,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SAC1C,CAAC;KACH,CAAC,CAAA;IACF,MAAM,UAAU,GAAG,WAAW,CAAC;QAC7B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,qBAAqB;QAC3B,KAAK,EAAE,GAAG,CAAA;;;;gDAIkC,WAAW;oCACvB;QAChC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,kCAAkC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,+BAA+B,MAAM,CAAC,WAAW,CAAC,eAAe,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM;QAChL,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;KACvG,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,WAAW,CAAC;QAC1B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,mBAAmB;QACzB,KAAK,EAAE,GAAG,CAAA;;;;iDAImC,YAAY;wCACrB;QACpC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,0BAA0B,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,sBAAsB,MAAM,CAAC,YAAY,CAAC,mBAAmB,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,UAAU;QACxK,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;KACvG,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,WAAW,CAAC;QAC1B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,GAAG,CAAA;;;;iDAImC,YAAY;;wCAErB;QACpC,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;QAC3B,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,yBAAyB,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,kCAAkC,MAAM,CAAC,YAAY,CAAC,2CAA2C,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM;QACvM,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,YAAY,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACtE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;KACvG,CAAC,CAAA;IACF,OAAO,cAAc,CAAC,OAAO,EAAE,CAAC,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AACxE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,eAAe,CAAC,UAA4F,EAAE;IAC5H,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,EAAE,gBAAgB,EAAE,yBAAyB,CAAC,CAAA;IAC1G,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,cAAc,IAAI,IAAI,EAAE,gBAAgB,EAAE,yBAAyB,CAAC,CAAA;IAC1G,MAAM,MAAM,GAAG,aAAa,CAAC;QAC3B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,iBAAiB;QACvB,KAAK,EAAE,wBAAwB;QAC/B,EAAE,EAAE,cAAc;QAClB,KAAK,EAAE,GAAG,CAAA,qBAAqB;QAC/B,OAAO,EAAE,eAAe;QACxB,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC,EAAE,wBAAwB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE;QACrH,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACb,QAAQ,EAAE,CAAC,CAAC,EAAE;YACd,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,SAAS,EAAE,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACrC,SAAS,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YAC/B,YAAY,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SAC1C,CAAC;KACH,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,WAAW,CAAC;QAC1B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,GAAG,CAAA;;;sEAGwD,YAAY;oDAC9B;QAChD,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;QACnC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,uBAAuB,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,sBAAsB,MAAM,CAAC,YAAY,CAAC,eAAe,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM;QACrK,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;KAClH,CAAC,CAAA;IACF,MAAM,OAAO,GAAG,WAAW,CAAC;QAC1B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,kBAAkB;QACxB,KAAK,EAAE,GAAG,CAAA;;;sEAGwD,YAAY;oDAC9B;QAChD,EAAE,EAAE,CAAC,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;QACnC,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,uBAAuB,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,kCAAkC,MAAM,CAAC,YAAY,CAAC,eAAe,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,MAAM;QACjL,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,MAAM,EAAE,UAAU,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,CAAC;QAC5E,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;KAClH,CAAC,CAAA;IACF,OAAO,cAAc,CAAC,WAAW,EAAE,CAAC,MAAM,EAAE,OAAO,EAAE,OAAO,CAAC,CAAC,CAAA;AAChE,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,UAAU,YAAY,CAAC,UAA4D,EAAE;IACzF,MAAM,KAAK,GAAG,QAAQ,CAAC,OAAO,CAAC,OAAO,IAAI,iBAAiB,EAAE,SAAS,EAAE,sBAAsB,CAAC,CAAA;IAC/F,MAAM,OAAO,GAAG,aAAa,CAAC;QAC5B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,eAAe;QACrB,KAAK,EAAE,OAAO;QACd,EAAE,EAAE,WAAW;QACf,KAAK,EAAE,GAAG,CAAA,sBAAsB;QAChC,OAAO,EAAE,YAAY;QACrB,GAAG,CAAC,OAAO,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,OAAO,CAAC,QAAQ,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;QACzE,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,EAAE,qDAAqD,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE;QACnH,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC;YACb,SAAS,EAAE,CAAC,CAAC,EAAE;YACf,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,WAAW,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;YACjC,YAAY,EAAE,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,IAAI,IAAI,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SACrH,CAAC;KACH,CAAC,CAAA;IACF,MAAM,SAAS,GAAG,WAAW,CAAC;QAC5B,GAAG,MAAM,CAAC,OAAO,CAAC;QAClB,IAAI,EAAE,wBAAwB;QAC9B,KAAK,EAAE,GAAG,CAAA;;;oEAGsD,KAAK;0BAC/C;QACtB,EAAE,EAAE,GAAG,EAAE,CAAC,KAAK;QACf,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,GAAG,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,oCAAoC,MAAM,CAAC,KAAK,CAAC,4DAA4D;QAC5I,OAAO,EAAE,CAAC,CAAC,EAAE,CAAC,CAAC,EAAE,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;KAC5E,CAAC,CAAA;IACF,OAAO,cAAc,CAAC,QAAQ,EAAE,CAAC,OAAO,EAAE,SAAS,CAAC,CAAC,CAAA;AACvD,CAAC"}
@@ -6,6 +6,7 @@ import { requestFaultsHook } from './request-faults.js';
6
6
  import { deadLetterSource, longRunningSource, backlogSource, healthSource, quotaExhaustedSource, unitFaultSource, loopStalledSource, loopCheck, querySource, newRowsSource } from './sources.js';
7
7
  import { deliveryFailedSource, webhookFailedSource, creditsSource } from './subsystem-sources.js';
8
8
  import { emailSource, storageSource, accessLinksSource, lockoutsSource } from './infra-sources.js';
9
+ import { schedulesSource, stepsSource, pipelinesSource, tracesSource } from './async-sources.js';
9
10
  /** Alerts namespace — raise and resolve keyed conditions, grouped, delivered to sinks through an outbox, traced. */
10
11
  export declare const alerts: {
11
12
  /** Creates an alerts handle. */
@@ -53,6 +54,14 @@ export declare const alerts: {
53
54
  readonly accessLinks: typeof accessLinksSource;
54
55
  /** Raises `auth-lockout:<table>` (warning) while sign-in or guard lockouts are active; counts only, no accounts. */
55
56
  readonly lockouts: typeof lockoutsSource;
57
+ /** Raises `schedule-overdue:<name>` while a cron schedule's `next_run_at` is long past, which means no scheduler is firing it. */
58
+ readonly schedules: typeof schedulesSource;
59
+ /** Raises `step-run-failed:<graph>`, `step-run-unnotified:<graph>` and `step-task-waiting:<graph>` and `step-run-stalled:<graph>` over the step graph tables. */
60
+ readonly steps: typeof stepsSource;
61
+ /** Raises `pipeline-failed:<pipeline>` for failed runs `pipeline-waiting:<pipeline>` for runs waiting too long and `pipeline-stalled:<pipeline>` for runs still running too long. */
62
+ readonly pipelines: typeof pipelinesSource;
63
+ /** Raises `trace-expired:<entryKind>` for traces force-closed by the expiry sweep and `trace-expiry-undrained:all` while expired open traces are not being swept. */
64
+ readonly traces: typeof tracesSource;
56
65
  /** Raises `loop-stalled:<name>` while a background loop (scheduler, reaper, claim loop, support drain) has not run or succeeded within its allowance; the tick itself is covered by `pipework alerts stale`. */
57
66
  readonly loopStalled: typeof loopStalledSource;
58
67
  };
@@ -1 +1 @@
1
- {"version":3,"file":"namespace.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAChM,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAElG,oHAAoH;AACpH,eAAO,MAAM,MAAM;IACjB,gCAAgC;;IAEhC,0HAA0H;;IAE1H,wLAAwL;;IAExL,oHAAoH;;IAEpH,2DAA2D;;IAE3D,+DAA+D;;IAE/D,kJAAkJ;;;QAGhJ,4EAA4E;;QAE5E,iFAAiF;;QAEjF,mGAAmG;;QAEnG,yGAAyG;;QAEzG,yDAAyD;;QAEzD,6IAA6I;;QAE7I,2HAA2H;;QAE3H,iIAAiI;;QAEjI,0IAA0I;;QAE1I,yJAAyJ;;QAEzJ,gIAAgI;;QAEhI,4JAA4J;;QAE5J,+EAA+E;;QAE/E,gGAAgG;;QAEhG,oHAAoH;;QAEpH,gNAAgN;;;CAG1M,CAAA"}
1
+ {"version":3,"file":"namespace.d.ts","sourceRoot":"","sources":["../../../src/infra/alerts/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAChM,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEhG,oHAAoH;AACpH,eAAO,MAAM,MAAM;IACjB,gCAAgC;;IAEhC,0HAA0H;;IAE1H,wLAAwL;;IAExL,oHAAoH;;IAEpH,2DAA2D;;IAE3D,+DAA+D;;IAE/D,kJAAkJ;;;QAGhJ,4EAA4E;;QAE5E,iFAAiF;;QAEjF,mGAAmG;;QAEnG,yGAAyG;;QAEzG,yDAAyD;;QAEzD,6IAA6I;;QAE7I,2HAA2H;;QAE3H,iIAAiI;;QAEjI,0IAA0I;;QAE1I,yJAAyJ;;QAEzJ,gIAAgI;;QAEhI,4JAA4J;;QAE5J,+EAA+E;;QAE/E,gGAAgG;;QAEhG,oHAAoH;;QAEpH,kIAAkI;;QAElI,iKAAiK;;QAEjK,qLAAqL;;QAErL,qKAAqK;;QAErK,gNAAgN;;;CAG1M,CAAA"}
@@ -6,6 +6,7 @@ import { requestFaultsHook } from './request-faults.js';
6
6
  import { deadLetterSource, longRunningSource, backlogSource, healthSource, quotaExhaustedSource, unitFaultSource, loopStalledSource, loopCheck, querySource, newRowsSource } from './sources.js';
7
7
  import { deliveryFailedSource, webhookFailedSource, creditsSource } from './subsystem-sources.js';
8
8
  import { emailSource, storageSource, accessLinksSource, lockoutsSource } from './infra-sources.js';
9
+ import { schedulesSource, stepsSource, pipelinesSource, tracesSource } from './async-sources.js';
9
10
  /** Alerts namespace — raise and resolve keyed conditions, grouped, delivered to sinks through an outbox, traced. */
10
11
  export const alerts = {
11
12
  /** Creates an alerts handle. */
@@ -53,6 +54,14 @@ export const alerts = {
53
54
  accessLinks: accessLinksSource,
54
55
  /** Raises `auth-lockout:<table>` (warning) while sign-in or guard lockouts are active; counts only, no accounts. */
55
56
  lockouts: lockoutsSource,
57
+ /** Raises `schedule-overdue:<name>` while a cron schedule's `next_run_at` is long past, which means no scheduler is firing it. */
58
+ schedules: schedulesSource,
59
+ /** Raises `step-run-failed:<graph>`, `step-run-unnotified:<graph>` and `step-task-waiting:<graph>` and `step-run-stalled:<graph>` over the step graph tables. */
60
+ steps: stepsSource,
61
+ /** Raises `pipeline-failed:<pipeline>` for failed runs `pipeline-waiting:<pipeline>` for runs waiting too long and `pipeline-stalled:<pipeline>` for runs still running too long. */
62
+ pipelines: pipelinesSource,
63
+ /** Raises `trace-expired:<entryKind>` for traces force-closed by the expiry sweep and `trace-expiry-undrained:all` while expired open traces are not being swept. */
64
+ traces: tracesSource,
56
65
  /** Raises `loop-stalled:<name>` while a background loop (scheduler, reaper, claim loop, support drain) has not run or succeeded within its allowance; the tick itself is covered by `pipework alerts stale`. */
57
66
  loopStalled: loopStalledSource,
58
67
  },
@@ -1 +1 @@
1
- {"version":3,"file":"namespace.js","sourceRoot":"","sources":["../../../src/infra/alerts/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAChM,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAElG,oHAAoH;AACpH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,gCAAgC;IAChC,MAAM,EAAE,YAAY;IACpB,0HAA0H;IAC1H,IAAI,EAAE,UAAU;IAChB,wLAAwL;IACxL,YAAY;IACZ,oHAAoH;IACpH,aAAa,EAAE,iBAAiB;IAChC,2DAA2D;IAC3D,OAAO,EAAE,WAAW;IACpB,+DAA+D;IAC/D,MAAM,EAAE,UAAU;IAClB,kJAAkJ;IAClJ,SAAS;IACT,MAAM,EAAE;QACN,4EAA4E;QAC5E,UAAU,EAAE,gBAAgB;QAC5B,iFAAiF;QACjF,WAAW,EAAE,iBAAiB;QAC9B,mGAAmG;QACnG,OAAO,EAAE,aAAa;QACtB,yGAAyG;QACzG,cAAc,EAAE,oBAAoB;QACpC,yDAAyD;QACzD,MAAM,EAAE,YAAY;QACpB,6IAA6I;QAC7I,SAAS,EAAE,eAAe;QAC1B,2HAA2H;QAC3H,KAAK,EAAE,WAAW;QAClB,iIAAiI;QACjI,OAAO,EAAE,aAAa;QACtB,0IAA0I;QAC1I,cAAc,EAAE,oBAAoB;QACpC,yJAAyJ;QACzJ,aAAa,EAAE,mBAAmB;QAClC,gIAAgI;QAChI,OAAO,EAAE,aAAa;QACtB,4JAA4J;QAC5J,KAAK,EAAE,WAAW;QAClB,+EAA+E;QAC/E,OAAO,EAAE,aAAa;QACtB,gGAAgG;QAChG,WAAW,EAAE,iBAAiB;QAC9B,oHAAoH;QACpH,QAAQ,EAAE,cAAc;QACxB,gNAAgN;QAChN,WAAW,EAAE,iBAAiB;KAC/B;CACO,CAAA"}
1
+ {"version":3,"file":"namespace.js","sourceRoot":"","sources":["../../../src/infra/alerts/namespace.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAA;AAC1C,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAA;AACtC,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AACjD,OAAO,EAAE,WAAW,EAAE,UAAU,EAAE,MAAM,YAAY,CAAA;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,qBAAqB,CAAA;AACvD,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,aAAa,EAAE,YAAY,EAAE,oBAAoB,EAAE,eAAe,EAAE,iBAAiB,EAAE,SAAS,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,cAAc,CAAA;AAChM,OAAO,EAAE,oBAAoB,EAAE,mBAAmB,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAA;AACjG,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,iBAAiB,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAA;AAClG,OAAO,EAAE,eAAe,EAAE,WAAW,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,oBAAoB,CAAA;AAEhG,oHAAoH;AACpH,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,gCAAgC;IAChC,MAAM,EAAE,YAAY;IACpB,0HAA0H;IAC1H,IAAI,EAAE,UAAU;IAChB,wLAAwL;IACxL,YAAY;IACZ,oHAAoH;IACpH,aAAa,EAAE,iBAAiB;IAChC,2DAA2D;IAC3D,OAAO,EAAE,WAAW;IACpB,+DAA+D;IAC/D,MAAM,EAAE,UAAU;IAClB,kJAAkJ;IAClJ,SAAS;IACT,MAAM,EAAE;QACN,4EAA4E;QAC5E,UAAU,EAAE,gBAAgB;QAC5B,iFAAiF;QACjF,WAAW,EAAE,iBAAiB;QAC9B,mGAAmG;QACnG,OAAO,EAAE,aAAa;QACtB,yGAAyG;QACzG,cAAc,EAAE,oBAAoB;QACpC,yDAAyD;QACzD,MAAM,EAAE,YAAY;QACpB,6IAA6I;QAC7I,SAAS,EAAE,eAAe;QAC1B,2HAA2H;QAC3H,KAAK,EAAE,WAAW;QAClB,iIAAiI;QACjI,OAAO,EAAE,aAAa;QACtB,0IAA0I;QAC1I,cAAc,EAAE,oBAAoB;QACpC,yJAAyJ;QACzJ,aAAa,EAAE,mBAAmB;QAClC,gIAAgI;QAChI,OAAO,EAAE,aAAa;QACtB,4JAA4J;QAC5J,KAAK,EAAE,WAAW;QAClB,+EAA+E;QAC/E,OAAO,EAAE,aAAa;QACtB,gGAAgG;QAChG,WAAW,EAAE,iBAAiB;QAC9B,oHAAoH;QACpH,QAAQ,EAAE,cAAc;QACxB,kIAAkI;QAClI,SAAS,EAAE,eAAe;QAC1B,iKAAiK;QACjK,KAAK,EAAE,WAAW;QAClB,qLAAqL;QACrL,SAAS,EAAE,eAAe;QAC1B,qKAAqK;QACrK,MAAM,EAAE,YAAY;QACpB,gNAAgN;QAChN,WAAW,EAAE,iBAAiB;KAC/B;CACO,CAAA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pipework",
3
- "version": "0.176.0",
3
+ "version": "0.177.0",
4
4
  "description": "TypeScript framework for multi-tenant SaaS applications. PostgreSQL-only.",
5
5
  "type": "module",
6
6
  "license": "MIT",