@substrat-run/kernel 0.162.0 → 0.164.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (84) hide show
  1. package/dist/attachment-bytes.d.ts +121 -0
  2. package/dist/attachment-bytes.d.ts.map +1 -0
  3. package/dist/attachment-bytes.js +94 -0
  4. package/dist/attachment-bytes.js.map +1 -0
  5. package/dist/attachment-sweep.d.ts +2 -1
  6. package/dist/attachment-sweep.d.ts.map +1 -1
  7. package/dist/attachment-sweep.js +1 -1
  8. package/dist/attachment-sweep.js.map +1 -1
  9. package/dist/attachment-text.d.ts +1 -1
  10. package/dist/attachment-text.d.ts.map +1 -1
  11. package/dist/attachment-text.js +1 -1
  12. package/dist/attachment-text.js.map +1 -1
  13. package/dist/billing-retention.js +1 -1
  14. package/dist/billing-retention.js.map +1 -1
  15. package/dist/connection-context.d.ts +69 -0
  16. package/dist/connection-context.d.ts.map +1 -0
  17. package/dist/connection-context.js +19 -0
  18. package/dist/connection-context.js.map +1 -0
  19. package/dist/connection-landings.d.ts +8 -0
  20. package/dist/connection-landings.d.ts.map +1 -1
  21. package/dist/connection-landings.js +5 -1
  22. package/dist/connection-landings.js.map +1 -1
  23. package/dist/connector-transport.d.ts +313 -0
  24. package/dist/connector-transport.d.ts.map +1 -0
  25. package/dist/connector-transport.js +66 -0
  26. package/dist/connector-transport.js.map +1 -0
  27. package/dist/deadline-fetch.d.ts +1 -1
  28. package/dist/deadline-fetch.d.ts.map +1 -1
  29. package/dist/findings.js +1 -1
  30. package/dist/findings.js.map +1 -1
  31. package/dist/index.d.ts +11 -4
  32. package/dist/index.d.ts.map +1 -1
  33. package/dist/index.js +10 -3
  34. package/dist/index.js.map +1 -1
  35. package/dist/job-run.d.ts +2 -1
  36. package/dist/job-run.d.ts.map +1 -1
  37. package/dist/job-run.js +2 -1
  38. package/dist/job-run.js.map +1 -1
  39. package/dist/live-read.d.ts +258 -0
  40. package/dist/live-read.d.ts.map +1 -0
  41. package/dist/live-read.js +101 -0
  42. package/dist/live-read.js.map +1 -0
  43. package/dist/membership-executor.d.ts +2 -1
  44. package/dist/membership-executor.d.ts.map +1 -1
  45. package/dist/membership-executor.js.map +1 -1
  46. package/dist/meter-days.js +1 -1
  47. package/dist/meter-days.js.map +1 -1
  48. package/dist/migration-digest.d.ts +1 -1
  49. package/dist/migration-digest.d.ts.map +1 -1
  50. package/dist/migration-digest.js +1 -1
  51. package/dist/migration-digest.js.map +1 -1
  52. package/dist/platform-sweep.d.ts +22 -4
  53. package/dist/platform-sweep.d.ts.map +1 -1
  54. package/dist/platform-sweep.js +69 -26
  55. package/dist/platform-sweep.js.map +1 -1
  56. package/dist/promote-review.d.ts +42 -4
  57. package/dist/promote-review.d.ts.map +1 -1
  58. package/dist/promote-review.js +43 -15
  59. package/dist/promote-review.js.map +1 -1
  60. package/dist/request-rollup.js +1 -1
  61. package/dist/request-rollup.js.map +1 -1
  62. package/dist/reserved-roles.d.ts +12 -0
  63. package/dist/reserved-roles.d.ts.map +1 -1
  64. package/dist/reserved-roles.js +22 -3
  65. package/dist/reserved-roles.js.map +1 -1
  66. package/dist/retention.d.ts +106 -0
  67. package/dist/retention.d.ts.map +1 -0
  68. package/dist/retention.js +131 -0
  69. package/dist/retention.js.map +1 -0
  70. package/dist/scope-host.d.ts +23 -791
  71. package/dist/scope-host.d.ts.map +1 -1
  72. package/dist/scope-host.js +1 -385
  73. package/dist/scope-host.js.map +1 -1
  74. package/dist/storage-gauge.js +1 -1
  75. package/dist/storage-gauge.js.map +1 -1
  76. package/dist/upload-link.d.ts +1 -1
  77. package/dist/upload-link.d.ts.map +1 -1
  78. package/dist/upload-link.js +1 -1
  79. package/dist/upload-link.js.map +1 -1
  80. package/dist/wire-nonce.d.ts +80 -0
  81. package/dist/wire-nonce.d.ts.map +1 -0
  82. package/dist/wire-nonce.js +126 -0
  83. package/dist/wire-nonce.js.map +1 -0
  84. package/package.json +2 -2
@@ -0,0 +1,131 @@
1
+ import { substratError } from '@substrat-run/contracts';
2
+ /**
3
+ * How long a recorded operational failure is kept (#559). Telemetry, not evidence:
4
+ * unlike the never-swept admin log, the ops-failures table self-prunes on write in
5
+ * every adapter, so it can never grow without bound and needs no cron wiring or
6
+ * operator decision. 90 days comfortably outlives any incident follow-up (a
7
+ * Cloudflare ticket round-trip) while keeping directory storage flat.
8
+ */
9
+ export const OPS_FAILURE_RETENTION_DAYS = 90;
10
+ /**
11
+ * How long a sweep-run row is kept (#1232). Much shorter than ops failures: this
12
+ * is high-frequency telemetry (a pass every few minutes times every connection
13
+ * and schedule), and its job is the recent-runs strip plus an incident window —
14
+ * 14 days covers both. Pruned on write in every adapter, like ops failures and
15
+ * for the same reason: the table stays bounded even where no scheduled pass runs.
16
+ */
17
+ export const SWEEP_RUN_RETENTION_DAYS = 14;
18
+ /**
19
+ * The drained batch's dedupe key on the directory's `_substrat_sweep_runs` (#1232), as
20
+ * both adapters build it: `recordSweepRun` is an `INSERT OR IGNORE` against this index,
21
+ * which is what makes a replayed drain write nothing twice.
22
+ *
23
+ * `kind` is in it since #1572, and that is the fix rather than a tidy-up. Every entry of
24
+ * one drained batch shares its `request_id`, and `unit` is built from two namespaces that
25
+ * nothing keeps apart — `<scopeId>:<operation>` for a schedule, `<scopeId>:<eventType>`
26
+ * for a freshness verdict — while `scheduleSpec.operation` is `z.string().min(1)`. A
27
+ * schedule named exactly like an event type its scope expects freshness on collided on
28
+ * `(request_id, unit)`, and the ignore-on-conflict write discarded the second row with no
29
+ * error anywhere. Both rows are signals by their absence (a stopped evaluator, a missed
30
+ * run), so losing one read as the very thing it was meant to rule out. It is #1288's
31
+ * collision, in the record table beside the state table.
32
+ *
33
+ * Shared rather than spelled in each adapter because a directory that predates it
34
+ * re-creates it (`ensureSweepRunsIntentKind`, in both), and `lint:spine-ddl` sees only
35
+ * the created copy. One definition keeps the re-created shape and the created shape the
36
+ * same shape; the gate then holds each adapter's DDL to including it.
37
+ */
38
+ export const SWEEP_RUNS_INTENT_INDEX = 'CREATE UNIQUE INDEX IF NOT EXISTS _substrat_sweep_runs_intent ON _substrat_sweep_runs (request_id, kind, unit);';
39
+ /**
40
+ * Whether a directory's `_substrat_sweep_runs_intent` already has `kind` among its
41
+ * columns, read off the index's `sql` in `sqlite_master` — which DO SQLite serves and
42
+ * `PRAGMA` does not, so both adapters detect by one strategy. `false` means the index
43
+ * must be DROPPED and created again: `CREATE … IF NOT EXISTS` matches on the name alone,
44
+ * so on every existing directory the old `(request_id, unit)` index would otherwise
45
+ * stand for good, while a fresh one — and any test that starts from one — gets the new.
46
+ */
47
+ export function sweepRunsIntentHasKind(indexSql) {
48
+ const columns = /\(([^()]*)\)\s*;?\s*$/.exec(indexSql)?.[1];
49
+ return columns !== undefined && columns.split(',').some((c) => c.trim() === 'kind');
50
+ }
51
+ /**
52
+ * How long an issue row outlives its last occurrence (#1233). Deliberately longer
53
+ * than the 90-day evidence beneath it: an issue is the compressed memory of a
54
+ * failure class, and "we saw this five months ago" is exactly what a regression
55
+ * needs to be recognizable. Pruned on write like everything else here, and on the
56
+ * scheduled pass (`pruneTelemetry`, #1632), so a quiet directory sheds it on time too.
57
+ */
58
+ export const ISSUE_RETENTION_DAYS = 180;
59
+ /**
60
+ * A caller-supplied row bound, checked before it reaches a SQL `LIMIT` (#1632). SQLite reads a
61
+ * negative `LIMIT` as no limit at all, so `-1` turns a bounded batch into an unbounded one; a
62
+ * fractional or non-finite value is refused by SQLite itself, as a failure every later call
63
+ * repeats. Neither is a value anyone means, so it is a configuration error, refused here with the
64
+ * option's name, and never silently normalized into something the caller did not ask for.
65
+ * Returns the value, so a call site can bind it in place.
66
+ */
67
+ export function assertRowLimit(name, value) {
68
+ if (Number.isInteger(value) && value > 0)
69
+ return value;
70
+ throw substratError('validation_failed', `${name} must be a positive integer, got ${String(value)}`);
71
+ }
72
+ /**
73
+ * A caller-supplied row offset, checked before it reaches a SQL `OFFSET` — `assertRowLimit`'s
74
+ * sibling. Zero is a valid offset; a negative, fractional or non-finite one is refused rather
75
+ * than passed to SQLite, which fails the statement on it.
76
+ */
77
+ export function assertRowOffset(name, value) {
78
+ if (Number.isInteger(value) && value >= 0)
79
+ return value;
80
+ throw substratError('validation_failed', `${name} must be a non-negative integer, got ${String(value)}`);
81
+ }
82
+ /** How many rows of EACH telemetry table one `pruneTelemetry` call deletes, by default. */
83
+ export const TELEMETRY_PRUNE_BATCH = 500;
84
+ /**
85
+ * The three telemetry retentions as statements, for `pruneTelemetry` on both adapters (#1632).
86
+ *
87
+ * Each table already prunes on write, and that bound holds only while something is written:
88
+ * a quiet directory keeps a row past its retention for as long as nothing new arrives in
89
+ * that table. An issue is the case that matters. Erasure skips an issue whose exemplar owner
90
+ * is unknown, on the promise that it ages out within `ISSUE_RETENTION_DAYS`, and on a
91
+ * directory with no new failures nothing ever deleted it. The scheduled pass runs these
92
+ * statements, which makes the stated retention a bound in time rather than in traffic.
93
+ *
94
+ * **Bounded per call, oldest first.** After a long pause or a restore the backlog can be a
95
+ * year of sweep runs, and one unbounded DELETE over it is a pass that fails on the Durable
96
+ * Object every tick. Each statement deletes at most `limit` rows, chosen through the table's
97
+ * own retention index (`… WHERE rowid IN (SELECT rowid … ORDER BY <ts> LIMIT ?)`), so the
98
+ * backlog drains over passes. `RETURNING` makes the count what was actually deleted on both
99
+ * adapters, rather than a rows-written figure that would also count index writes.
100
+ */
101
+ export function telemetryRetentionStatements(nowMs, limit) {
102
+ const horizon = (days) => new Date(nowMs - days * 86_400_000).toISOString();
103
+ const bounded = boundedRetentionDelete;
104
+ return [
105
+ {
106
+ table: 'opsFailures',
107
+ sql: bounded('_substrat_ops_failures', 'at'),
108
+ params: [horizon(OPS_FAILURE_RETENTION_DAYS), limit],
109
+ },
110
+ {
111
+ table: 'issues',
112
+ sql: bounded('_substrat_issues', 'last_seen'),
113
+ params: [horizon(ISSUE_RETENTION_DAYS), limit],
114
+ },
115
+ {
116
+ table: 'sweepRuns',
117
+ sql: bounded('_substrat_sweep_runs', 'at'),
118
+ params: [horizon(SWEEP_RUN_RETENTION_DAYS), limit],
119
+ },
120
+ ];
121
+ }
122
+ /**
123
+ * One bounded retention DELETE: at most `LIMIT ?` rows whose `column` is before `?`, oldest
124
+ * first through the column's own index, `RETURNING 1` so the count is what was deleted. Takes
125
+ * `(horizon, limit)`. The statement `telemetryRetentionStatements` and `pruneFindings` share.
126
+ */
127
+ export function boundedRetentionDelete(table, column) {
128
+ return (`DELETE FROM ${table} WHERE rowid IN ` +
129
+ `(SELECT rowid FROM ${table} WHERE ${column} < ? ORDER BY ${column} LIMIT ?) RETURNING 1`);
130
+ }
131
+ //# sourceMappingURL=retention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"retention.js","sourceRoot":"","sources":["../src/retention.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,yBAAyB,CAAC;AAExD;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,0BAA0B,GAAG,EAAE,CAAC;AAE7C;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,EAAE,CAAC;AAE3C;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAClC,iHAAiH,CAAC;AAEpH;;;;;;;GAOG;AACH,MAAM,UAAU,sBAAsB,CAAC,QAAgB;IACrD,MAAM,OAAO,GAAG,uBAAuB,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;IAC5D,OAAO,OAAO,KAAK,SAAS,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,MAAM,CAAC,CAAC;AACtF,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,oBAAoB,GAAG,GAAG,CAAC;AASxC;;;;;;;GAOG;AACH,MAAM,UAAU,cAAc,CAAC,IAAY,EAAE,KAAa;IACxD,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,GAAG,CAAC;QAAE,OAAO,KAAK,CAAC;IACvD,MAAM,aAAa,CAAC,mBAAmB,EAAE,GAAG,IAAI,oCAAoC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AACvG,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAa;IACzD,IAAI,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,CAAC;QAAE,OAAO,KAAK,CAAC;IACxD,MAAM,aAAa,CAAC,mBAAmB,EAAE,GAAG,IAAI,wCAAwC,MAAM,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;AAC3G,CAAC;AAED,2FAA2F;AAC3F,MAAM,CAAC,MAAM,qBAAqB,GAAG,GAAG,CAAC;AAEzC;;;;;;;;;;;;;;;;GAgBG;AACH,MAAM,UAAU,4BAA4B,CAC1C,KAAa,EACb,KAAa;IAEb,MAAM,OAAO,GAAG,CAAC,IAAY,EAAE,EAAE,CAAC,IAAI,IAAI,CAAC,KAAK,GAAG,IAAI,GAAG,UAAU,CAAC,CAAC,WAAW,EAAE,CAAC;IACpF,MAAM,OAAO,GAAG,sBAAsB,CAAC;IACvC,OAAO;QACL;YACE,KAAK,EAAE,aAAa;YACpB,GAAG,EAAE,OAAO,CAAC,wBAAwB,EAAE,IAAI,CAAC;YAC5C,MAAM,EAAE,CAAC,OAAO,CAAC,0BAA0B,CAAC,EAAE,KAAK,CAAC;SACrD;QACD;YACE,KAAK,EAAE,QAAQ;YACf,GAAG,EAAE,OAAO,CAAC,kBAAkB,EAAE,WAAW,CAAC;YAC7C,MAAM,EAAE,CAAC,OAAO,CAAC,oBAAoB,CAAC,EAAE,KAAK,CAAC;SAC/C;QACD;YACE,KAAK,EAAE,WAAW;YAClB,GAAG,EAAE,OAAO,CAAC,sBAAsB,EAAE,IAAI,CAAC;YAC1C,MAAM,EAAE,CAAC,OAAO,CAAC,wBAAwB,CAAC,EAAE,KAAK,CAAC;SACnD;KACF,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,sBAAsB,CAAC,KAAa,EAAE,MAAc;IAClE,OAAO,CACL,eAAe,KAAK,kBAAkB;QACtC,sBAAsB,KAAK,UAAU,MAAM,iBAAiB,MAAM,uBAAuB,CAC1F,CAAC;AACJ,CAAC"}