@substrat-run/kernel 0.159.0 → 0.160.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 (91) hide show
  1. package/dist/billing-retention.d.ts +46 -0
  2. package/dist/billing-retention.d.ts.map +1 -0
  3. package/dist/billing-retention.js +78 -0
  4. package/dist/billing-retention.js.map +1 -0
  5. package/dist/byte-stream.d.ts +102 -0
  6. package/dist/byte-stream.d.ts.map +1 -0
  7. package/dist/byte-stream.js +153 -0
  8. package/dist/byte-stream.js.map +1 -0
  9. package/dist/connection-landings.d.ts +15 -3
  10. package/dist/connection-landings.d.ts.map +1 -1
  11. package/dist/connection-landings.js +10 -2
  12. package/dist/connection-landings.js.map +1 -1
  13. package/dist/deadline-fetch.d.ts +34 -0
  14. package/dist/deadline-fetch.d.ts.map +1 -0
  15. package/dist/deadline-fetch.js +231 -0
  16. package/dist/deadline-fetch.js.map +1 -0
  17. package/dist/deployment-wire-auth.d.ts +82 -0
  18. package/dist/deployment-wire-auth.d.ts.map +1 -0
  19. package/dist/deployment-wire-auth.js +150 -0
  20. package/dist/deployment-wire-auth.js.map +1 -0
  21. package/dist/entity-trash.d.ts +65 -8
  22. package/dist/entity-trash.d.ts.map +1 -1
  23. package/dist/entity-trash.js +80 -12
  24. package/dist/entity-trash.js.map +1 -1
  25. package/dist/export-break.d.ts +6 -0
  26. package/dist/export-break.d.ts.map +1 -1
  27. package/dist/export-break.js +11 -0
  28. package/dist/export-break.js.map +1 -1
  29. package/dist/index.d.ts +18 -9
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +16 -7
  32. package/dist/index.js.map +1 -1
  33. package/dist/meter-days.d.ts +107 -0
  34. package/dist/meter-days.d.ts.map +1 -0
  35. package/dist/meter-days.js +230 -0
  36. package/dist/meter-days.js.map +1 -0
  37. package/dist/meters.d.ts +19 -1
  38. package/dist/meters.d.ts.map +1 -1
  39. package/dist/meters.js +0 -0
  40. package/dist/meters.js.map +1 -1
  41. package/dist/ops-failure-reference.d.ts +31 -0
  42. package/dist/ops-failure-reference.d.ts.map +1 -0
  43. package/dist/ops-failure-reference.js +32 -0
  44. package/dist/ops-failure-reference.js.map +1 -0
  45. package/dist/platform-request-cap.d.ts +9 -0
  46. package/dist/platform-request-cap.d.ts.map +1 -0
  47. package/dist/platform-request-cap.js +42 -0
  48. package/dist/platform-request-cap.js.map +1 -0
  49. package/dist/platform-sweep.d.ts +170 -7
  50. package/dist/platform-sweep.d.ts.map +1 -1
  51. package/dist/platform-sweep.js +375 -45
  52. package/dist/platform-sweep.js.map +1 -1
  53. package/dist/request-rollup.d.ts +161 -0
  54. package/dist/request-rollup.d.ts.map +1 -0
  55. package/dist/request-rollup.js +273 -0
  56. package/dist/request-rollup.js.map +1 -0
  57. package/dist/reserved-roles.d.ts +157 -4
  58. package/dist/reserved-roles.d.ts.map +1 -1
  59. package/dist/reserved-roles.js +216 -2
  60. package/dist/reserved-roles.js.map +1 -1
  61. package/dist/schedule-state.d.ts +5 -0
  62. package/dist/schedule-state.d.ts.map +1 -1
  63. package/dist/scope-host.d.ts +260 -15
  64. package/dist/scope-host.d.ts.map +1 -1
  65. package/dist/scope-host.js +53 -2
  66. package/dist/scope-host.js.map +1 -1
  67. package/dist/scope-lifecycle.d.ts +7 -0
  68. package/dist/scope-lifecycle.d.ts.map +1 -1
  69. package/dist/scope-lifecycle.js +7 -0
  70. package/dist/scope-lifecycle.js.map +1 -1
  71. package/dist/scope-record.d.ts +16 -5
  72. package/dist/scope-record.d.ts.map +1 -1
  73. package/dist/scope-record.js +72 -7
  74. package/dist/scope-record.js.map +1 -1
  75. package/dist/spine-restore.d.ts +7 -3
  76. package/dist/spine-restore.d.ts.map +1 -1
  77. package/dist/spine-restore.js +14 -3
  78. package/dist/spine-restore.js.map +1 -1
  79. package/dist/storage-gauge.d.ts +47 -13
  80. package/dist/storage-gauge.d.ts.map +1 -1
  81. package/dist/storage-gauge.js +84 -27
  82. package/dist/storage-gauge.js.map +1 -1
  83. package/dist/subject-redaction.d.ts +9 -3
  84. package/dist/subject-redaction.d.ts.map +1 -1
  85. package/dist/subject-redaction.js +24 -12
  86. package/dist/subject-redaction.js.map +1 -1
  87. package/dist/vertical-owners.d.ts +69 -0
  88. package/dist/vertical-owners.d.ts.map +1 -0
  89. package/dist/vertical-owners.js +108 -0
  90. package/dist/vertical-owners.js.map +1 -0
  91. package/package.json +2 -2
@@ -0,0 +1,273 @@
1
+ import { requestDay, requestRollupDay, } from '@substrat-run/contracts';
2
+ import { assertRowLimit } from './scope-host.js';
3
+ import { assertUtcDay, pruneBillingDays, pushDayWindow, utcDayOf } from './billing-retention.js';
4
+ /**
5
+ * The daily request rollup (#2501), as statements both adapters run against their directory:
6
+ * the SQLite host over better-sqlite3, the hosted one inside ControlPlaneDO. Written once so the
7
+ * two cannot keep different histories of the same fleet.
8
+ *
9
+ * The router writes one Analytics Engine datapoint per request it dispatches, and Analytics
10
+ * Engine keeps them three months, sampled under load. This keeps one row per (UTC day, tenant,
11
+ * vertical, scope) holding that day's count, so the history outlives the datapoints. The count
12
+ * is `sum(_sample_interval)` over the day's datapoints, an ESTIMATE: an exact counter at the
13
+ * router comes only when pricing uses requests as a unit (#39).
14
+ *
15
+ * `_substrat_request_day_reads` keeps one row per day the rollup tried: when, whether a read
16
+ * succeeded, and why the last one failed. A day is rolled up once a read succeeds and is never
17
+ * read again. A day without a successful read has no rows to say anything with, so the read row
18
+ * is what tells "no traffic" from "not rolled up yet". A failed attempt also carries the run of
19
+ * identical failures it belongs to (`failing_since`, `failing_count`), handed on from the attempt
20
+ * before it, because a day keeps only its last attempt and the run's start would be lost.
21
+ *
22
+ * `vertical` is `''` when a request resolved to no vertical: a primary key cannot hold a NULL
23
+ * that compares equal to itself. The read maps it back to null.
24
+ *
25
+ * Beside the total, each row keeps the split by status class and the 429s, from the status the
26
+ * router writes on each datapoint. Which of them a price counts is a later decision; once the
27
+ * datapoints age out the split could not be recovered, so it is kept now.
28
+ */
29
+ export const REQUEST_ROLLUP_DDL = `
30
+ CREATE TABLE IF NOT EXISTS _substrat_request_days (
31
+ day TEXT NOT NULL,
32
+ tenant_id TEXT NOT NULL,
33
+ vertical TEXT NOT NULL,
34
+ scope_id TEXT NOT NULL,
35
+ requests INTEGER NOT NULL,
36
+ class2xx INTEGER NOT NULL,
37
+ class3xx INTEGER NOT NULL,
38
+ class4xx INTEGER NOT NULL,
39
+ class5xx INTEGER NOT NULL,
40
+ rate_limited INTEGER NOT NULL,
41
+ sampled INTEGER NOT NULL,
42
+ PRIMARY KEY (day, tenant_id, vertical, scope_id)
43
+ );
44
+ CREATE INDEX IF NOT EXISTS _substrat_request_days_tenant ON _substrat_request_days (tenant_id, day);
45
+ CREATE TABLE IF NOT EXISTS _substrat_request_day_reads (
46
+ day TEXT PRIMARY KEY,
47
+ attempted_at TEXT NOT NULL,
48
+ read_at TEXT,
49
+ row_count INTEGER,
50
+ error TEXT,
51
+ saturated INTEGER NOT NULL DEFAULT 0,
52
+ failing_since TEXT,
53
+ failing_count INTEGER
54
+ );
55
+ `;
56
+ /**
57
+ * What a reader throws when a day holds more (tenant, vertical, scope) groups than one query may
58
+ * answer: the answer would be part of the day, so it is refused. A saturated day is a standing
59
+ * state rather than a failure. It is recorded as such (`saturated` on the day's record), is not
60
+ * read again, and does not end the pass's reads, so the days after it are still rolled up.
61
+ * Recognised by its `saturated` flag rather than `instanceof`, so a copy of the kernel bundled
62
+ * elsewhere still matches.
63
+ */
64
+ export class RequestRollupSaturated extends Error {
65
+ saturated = true;
66
+ }
67
+ /** Whether `err` is a `RequestRollupSaturated`. */
68
+ export const isRequestRollupSaturated = (err) => typeof err === 'object' && err !== null && err.saturated === true;
69
+ /**
70
+ * How many days back the rollup reaches: inside Analytics Engine's three months, with a margin,
71
+ * so the oldest day read is never one the store has started to age out.
72
+ */
73
+ export const REQUEST_ROLLUP_LOOKBACK_DAYS = 85;
74
+ /**
75
+ * The furthest back a lookback may reach. Analytics Engine keeps three months, which is 89 days
76
+ * when February is among them, and the first day read starts at midnight before `now − lookback`,
77
+ * up to a day earlier still. At 88 that first day starts within 89 days. A day the store has begun
78
+ * to age out would be read in part and recorded as whole, or as a day without traffic, and then
79
+ * never read again.
80
+ */
81
+ export const REQUEST_ROLLUP_MAX_LOOKBACK_DAYS = 88;
82
+ /** How long after a day ends it may be read, so the datapoints written at its last instant have landed. */
83
+ export const REQUEST_ROLLUP_SETTLE_MS = 3_600_000;
84
+ /** How long a day whose read failed waits before it is tried again. */
85
+ export const REQUEST_ROLLUP_RETRY_MS = 3_600_000;
86
+ /**
87
+ * How long one day's read may take before it counts as failed. A fleet-wide query over a day
88
+ * answers in seconds; this is the bound that keeps a stalled one from holding the pass.
89
+ */
90
+ export const REQUEST_ROLLUP_READ_TIMEOUT_MS = 30_000;
91
+ /** The most days one pass reads, one Analytics Engine query each. A first pass backfills over several. */
92
+ export const REQUEST_ROLLUP_DAYS_PER_PASS = 7;
93
+ /** How many rows one `pruneRequestDays` call deletes, by default. */
94
+ export const REQUEST_ROLLUP_PRUNE_BATCH = 500;
95
+ /** The most rows one `listRequestDays` call returns, and its default. */
96
+ export const REQUEST_ROLLUP_LIMIT_MAX = 10_000;
97
+ export const REQUEST_ROLLUP_LIMIT_DEFAULT = 1_000;
98
+ const DAY_MS = 86_400_000;
99
+ /**
100
+ * Record one attempt. A successful read replaces the day's rows with what it counted, in the
101
+ * caller's transaction, and marks the day read. A failed one records only the attempt and its
102
+ * error: the day's rows and its last successful read stay as they were.
103
+ *
104
+ * Every count is parsed before anything is written, so a malformed one (a tenant id that is not
105
+ * an id, a negative count) refuses the whole day rather than writing part of it. Returns how many
106
+ * rows were written.
107
+ */
108
+ export function recordRequestDayRows(sql, input) {
109
+ const day = assertUtcDay('day', input.day);
110
+ const attemptedAt = new Date(input.attemptedAt).toISOString();
111
+ if ('error' in input) {
112
+ const saturated = input.saturated === true;
113
+ const since = saturated ? null : new Date(input.failingSince ?? attemptedAt).toISOString();
114
+ const count = saturated ? null : input.failingCount ?? 1;
115
+ if (count !== null && !(Number.isInteger(count) && count >= 1)) {
116
+ throw new Error(`failingCount must be a whole number, at least one, got ${String(count)}`);
117
+ }
118
+ sql(`INSERT INTO _substrat_request_day_reads
119
+ (day, attempted_at, read_at, row_count, error, saturated, failing_since, failing_count)
120
+ VALUES (?, ?, NULL, NULL, ?, ?, ?, ?)
121
+ ON CONFLICT (day) DO UPDATE SET
122
+ attempted_at = excluded.attempted_at, error = excluded.error, saturated = excluded.saturated,
123
+ failing_since = excluded.failing_since, failing_count = excluded.failing_count`, [day, attemptedAt, input.error || 'the read failed', saturated ? 1 : 0, since, count]);
124
+ return 0;
125
+ }
126
+ const rows = input.counts.map((c) => requestDay.parse({
127
+ day,
128
+ tenantId: c.tenantId,
129
+ vertical: c.vertical === '' ? null : c.vertical,
130
+ scopeId: c.scopeId,
131
+ requests: c.requests,
132
+ class2xx: c.class2xx,
133
+ class3xx: c.class3xx,
134
+ class4xx: c.class4xx,
135
+ class5xx: c.class5xx,
136
+ rateLimited: c.rateLimited,
137
+ sampled: c.sampled,
138
+ estimated: true,
139
+ }));
140
+ sql('DELETE FROM _substrat_request_days WHERE day = ?', [day]);
141
+ for (const r of rows) {
142
+ // Two counts for one key are one key's count: summed, never one dropped.
143
+ sql(`INSERT INTO _substrat_request_days
144
+ (day, tenant_id, vertical, scope_id, requests, class2xx, class3xx, class4xx, class5xx, rate_limited, sampled)
145
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
146
+ ON CONFLICT (day, tenant_id, vertical, scope_id) DO UPDATE SET
147
+ requests = _substrat_request_days.requests + excluded.requests,
148
+ class2xx = _substrat_request_days.class2xx + excluded.class2xx,
149
+ class3xx = _substrat_request_days.class3xx + excluded.class3xx,
150
+ class4xx = _substrat_request_days.class4xx + excluded.class4xx,
151
+ class5xx = _substrat_request_days.class5xx + excluded.class5xx,
152
+ rate_limited = _substrat_request_days.rate_limited + excluded.rate_limited,
153
+ sampled = MAX(_substrat_request_days.sampled, excluded.sampled)`, [
154
+ day,
155
+ r.tenantId,
156
+ r.vertical ?? '',
157
+ r.scopeId,
158
+ r.requests,
159
+ r.class2xx,
160
+ r.class3xx,
161
+ r.class4xx,
162
+ r.class5xx,
163
+ r.rateLimited,
164
+ r.sampled ? 1 : 0,
165
+ ]);
166
+ }
167
+ const written = sql('SELECT COUNT(*) AS n FROM _substrat_request_days WHERE day = ?', [day])[0]?.n ?? 0;
168
+ sql(`INSERT INTO _substrat_request_day_reads
169
+ (day, attempted_at, read_at, row_count, error, saturated, failing_since, failing_count)
170
+ VALUES (?, ?, ?, ?, NULL, 0, NULL, NULL)
171
+ ON CONFLICT (day) DO UPDATE SET
172
+ attempted_at = excluded.attempted_at, read_at = excluded.read_at, row_count = excluded.row_count,
173
+ error = NULL, saturated = 0, failing_since = NULL, failing_count = NULL`, [day, attemptedAt, attemptedAt, written]);
174
+ return written;
175
+ }
176
+ /** Read stored day counts — see `RequestDayFilter`. Every row is parsed on the way out. */
177
+ export function listRequestDayRows(sql, filter = {}) {
178
+ const where = [];
179
+ const params = [];
180
+ if (filter.tenantId !== undefined) {
181
+ where.push('tenant_id = ?');
182
+ params.push(filter.tenantId);
183
+ }
184
+ if (filter.vertical !== undefined) {
185
+ where.push('vertical = ?');
186
+ params.push(filter.vertical);
187
+ }
188
+ if (filter.scopeId !== undefined) {
189
+ where.push('scope_id = ?');
190
+ params.push(filter.scopeId);
191
+ }
192
+ pushDayWindow(filter, where, params);
193
+ const limit = Math.min(assertRowLimit('limit', filter.limit ?? REQUEST_ROLLUP_LIMIT_DEFAULT), REQUEST_ROLLUP_LIMIT_MAX);
194
+ params.push(limit);
195
+ const rows = sql(`SELECT day, tenant_id, vertical, scope_id, requests, class2xx, class3xx, class4xx, class5xx, rate_limited, sampled
196
+ FROM _substrat_request_days
197
+ ${where.length ? `WHERE ${where.join(' AND ')}` : ''}
198
+ ORDER BY day, tenant_id, vertical, scope_id LIMIT ?`, params);
199
+ return rows.map((r) => requestDay.parse({
200
+ day: r.day,
201
+ tenantId: r.tenant_id,
202
+ vertical: r.vertical === '' ? null : r.vertical,
203
+ scopeId: r.scope_id,
204
+ requests: r.requests,
205
+ class2xx: r.class2xx,
206
+ class3xx: r.class3xx,
207
+ class4xx: r.class4xx,
208
+ class5xx: r.class5xx,
209
+ rateLimited: r.rate_limited,
210
+ sampled: r.sampled === 1,
211
+ estimated: true,
212
+ }));
213
+ }
214
+ /** The rollup's record of each day it tried, in day order — see `RequestRollupDayFilter`. */
215
+ export function listRequestRollupDayRows(sql, filter = {}) {
216
+ const where = [];
217
+ const params = [];
218
+ pushDayWindow(filter, where, params);
219
+ const rows = sql(`SELECT day, attempted_at, read_at, row_count, error, saturated, failing_since, failing_count
220
+ FROM _substrat_request_day_reads
221
+ ${where.length ? `WHERE ${where.join(' AND ')}` : ''}
222
+ ORDER BY day`, params);
223
+ return rows.map((r) => requestRollupDay.parse({
224
+ day: r.day,
225
+ attemptedAt: r.attempted_at,
226
+ readAt: r.read_at,
227
+ rows: r.row_count,
228
+ error: r.error,
229
+ saturated: r.saturated === 1,
230
+ failingSince: r.failing_since,
231
+ failingCount: r.failing_count,
232
+ }));
233
+ }
234
+ /**
235
+ * Delete at most `limit` day rows older than a retention of `months`, oldest first, then the
236
+ * read rows of the days that are gone (`pruneBillingDays`). `months` null deletes nothing. A read
237
+ * row outlives a day still being pruned, so that day is not rolled up again in between. Returns
238
+ * how many day rows went.
239
+ */
240
+ export function pruneRequestDayRows(sql, nowMs, limit, months) {
241
+ return pruneBillingDays(sql, { rows: '_substrat_request_days', records: '_substrat_request_day_reads' }, nowMs, limit, months);
242
+ }
243
+ /**
244
+ * The days the rollup should read now, oldest first: every day from `lookbackDays` ago to the
245
+ * last day that ended at least `settleMs` ago, without a successful read, not saturated, and either
246
+ * never tried or last tried at least `retryMs` ago. A day before `horizon` (the retention's first kept day)
247
+ * is not read, so a prune and a rollup never take turns on the same day. Oldest first, because the
248
+ * oldest day is the next one Analytics Engine ages out.
249
+ */
250
+ export function requestRollupDueDays(input) {
251
+ const byDay = new Map(input.reads.map((r) => [r.day, r]));
252
+ const retryBefore = new Date(input.nowMs - input.retryMs).toISOString();
253
+ const last = utcDayOf(input.nowMs - input.settleMs - DAY_MS);
254
+ let first = utcDayOf(input.nowMs - input.lookbackDays * DAY_MS);
255
+ if (input.horizon !== null && input.horizon > first)
256
+ first = input.horizon;
257
+ const due = [];
258
+ for (let ms = Date.parse(`${first}T00:00:00Z`); utcDayOf(ms) <= last; ms += DAY_MS) {
259
+ const day = utcDayOf(ms);
260
+ const read = byDay.get(day);
261
+ if (read?.readAt)
262
+ continue;
263
+ // Saturated is a standing state: the day's group count will not shrink, so reading it again
264
+ // would spend a query on the same refusal.
265
+ if (read?.saturated)
266
+ continue;
267
+ if (read && read.attemptedAt > retryBefore)
268
+ continue;
269
+ due.push(day);
270
+ }
271
+ return due;
272
+ }
273
+ //# sourceMappingURL=request-rollup.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"request-rollup.js","sourceRoot":"","sources":["../src/request-rollup.ts"],"names":[],"mappings":"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"}
@@ -21,17 +21,168 @@ import { type ReservedKeySource } from '@substrat-run/contracts';
21
21
  * admitted only when its stored holder is `system`. A legacy row with no holder keeps the
22
22
  * old key-only behavior until its definition is written again.
23
23
  *
24
- * Never asked on a provisioning seat or the owner hand-over, and nothing already held is revoked:
25
- * a seat that exists keeps working whatever a later engine declares.
24
+ * A person's door also refuses a role whose stored holder is `system` (#2447), whatever this host
25
+ * knows: the holder a role definition carries is the reservation delivered with the role, so a
26
+ * host that registers no module (and so reserves nothing) still keeps a system-held role from a
27
+ * person. The provisioning owner seat and the owner hand-over are person doors too (#2447).
28
+ *
29
+ * Nothing already held is revoked: a seat that exists keeps working whatever a later engine
30
+ * declares. A refusal is of the write it was asked for, and writes nothing.
26
31
  *
27
32
  * The person's refusal is also `canAssign`'s, which is the bound on taking a role away as well as
28
33
  * on giving it, so it is worded for both: no person's bound covers such a role.
29
34
  */
30
- export declare function reservedRoleRefusal(role: {
35
+ export declare function reservedRoleRefusal(role: RoleShape, reserved: ReadonlySet<string>, door: 'person' | 'platform'): string | null;
36
+ /** A role as the reserved-key rule reads it: a definition, a stored row, or a projected one. */
37
+ export interface RoleShape {
31
38
  key: string;
32
39
  permissions: readonly string[];
33
40
  holder?: 'person' | 'system';
34
- }, reserved: ReadonlySet<string>, door: 'person' | 'platform'): string | null;
41
+ }
42
+ /**
43
+ * What a host knows about keys (#2447): `reserved`, every key a module it registers or lists (and,
44
+ * at a Cloudflare scope node, the scope class's) marks `holder: 'system'`; `declared`, every key
45
+ * those modules declare at all. A declared key that is not reserved is a person's key.
46
+ */
47
+ export interface HostReservations {
48
+ reserved: ReadonlySet<string>;
49
+ declared: ReadonlySet<string>;
50
+ }
51
+ /**
52
+ * Why `role` may not be DEFINED for a tenant whose roles are stored as `tenantRoles`, or null (#2447):
53
+ * the write a role definition makes, judged before it is made, so a role that passed a door when
54
+ * it was assigned cannot be widened afterwards with a key no person may hold. `tenantRoles` is
55
+ * what the host stores for the tenant now, the definition this one replaces included; `seated`
56
+ * says whether anyone but a system principal holds a live seat in the role's key, whether or not a
57
+ * definition of it is stored
58
+ * (`SCOPE_SEATED_ROLES_SQL`, `TENANT_SEATED_ROLES_SQL`).
59
+ *
60
+ * The keys judged reserved are the host's, plus every key one of the tenant's system-held roles
61
+ * holds: K-55 lets a system-held role hold reserved keys only, so its keys are reserved, and the
62
+ * stored holder (#2444) is how a host that registers no modules learns the reservation at all. A
63
+ * key the host's own modules declare unmarked is a person's, whatever a stored role says.
64
+ *
65
+ * - **A first definition** of a key: a person's role (holder omitted or `person`) carrying a
66
+ * reserved key is refused, and so is a system-held role carrying a key a person may hold (one
67
+ * the host's modules declare unmarked, or one a person's role of the tenant holds).
68
+ * - **A redefinition** is judged as that new definition, against the stored roles, so a key added
69
+ * to a role whose seats were made through a person's door meets the person's rule.
70
+ * - **A stored system-held role redefined as a person's** is judged as a person's role with the
71
+ * stored role's keys counted as reserved: the stored holder is the evidence, and a redefinition
72
+ * does not erase it.
73
+ * - **A system-held definition of a key anyone but a system principal holds a seat in** is refused
74
+ * unless a system-held definition is stored for it. What kind of principal holds a seat is not
75
+ * recorded, so a seat made before any definition, under a person's definition, or under one a
76
+ * projection since dropped may be a person's, and relabelling the role would make it a system
77
+ * principal's. A K-55 host principal's seat in a system-held role a release dropped and a later
78
+ * one adds back cannot be told apart from that, so it is refused too. Taking the seats back first, or defining a new key, is the
79
+ * way. The seats decide for a role stored before the holder was recorded (#2480: no holder) too:
80
+ * it may be declared `holder: 'system'` only while nobody but a system principal holds a seat in
81
+ * it, since an upgrade admitted beside such a seat would let a later system-held definition add
82
+ * keys to it.
83
+ *
84
+ * **A key the host knows nothing about is admitted, deliberately (fail-open).** A host judges only
85
+ * the reservations of modules it knows and of the tenant's system-held roles. Refusing every key it
86
+ * cannot place would refuse every role a module-less host is given; the push (`substrat push`, the
87
+ * registry boundary) is where the vertical's whole surface is judged. So a key reserved only
88
+ * through a schedule's `permissions`, which no system-held role of the tenant holds, is not caught
89
+ * on a host that does not register its module (the control plane verifying a pushed registry's
90
+ * marks is #2446).
91
+ *
92
+ * A refusal writes nothing, and so revokes nothing: a seat of the role as it was stored keeps
93
+ * working. A definition is never refused for a key it takes out, only for what it still holds.
94
+ */
95
+ export declare function reservedRoleDefinitionRefusal(role: RoleShape, host: HostReservations, tenantRoles: readonly RoleShape[], seated?: boolean): string | null;
96
+ /** What a host stores for a tenant's roles where a role set is defined, and which of them are seated. */
97
+ export interface StoredRoles {
98
+ roles: readonly RoleShape[];
99
+ /** Role keys anyone but a system principal holds a live seat in, defined or not. */
100
+ seated: ReadonlySet<string>;
101
+ }
102
+ /**
103
+ * `reservedRoleDefinitionRefusal` over a whole role set defined at once (a provision's or a
104
+ * restore's projection, which replaces the tenant's roles in a scope): each role judged against the
105
+ * rest of the set and the definition of its own key stored there now (`stored`), with its seats.
106
+ * The first refusal, or null.
107
+ */
108
+ export declare function reservedRoleSetRefusal(roles: readonly RoleShape[], host: HostReservations, stored?: StoredRoles): string | null;
109
+ /**
110
+ * #2446: a scope's stored roles and seated role keys as they cross the wire (`roleStateLocal`, the
111
+ * vertical's `/internal/role-state`): what `StoredRoles` holds, with the set as a list. Role keys,
112
+ * permissions and holders only; no principal is named.
113
+ */
114
+ export interface RoleState {
115
+ roles: RoleShape[];
116
+ seated: string[];
117
+ }
118
+ /**
119
+ * #2446: the reservations a pushed registry's rows mark — `reserved`, every key marked
120
+ * `holder: 'system'`; `declared`, every key it lists. The push boundary holds those marks to the
121
+ * module declarations shipped beside them (`pushedModuleRegistryProblems`), so they are what the
122
+ * incoming version's modules reserve and declare, the reservation its reconcile judges with.
123
+ */
124
+ export declare function registryReservations(registry: {
125
+ permissions: readonly {
126
+ key: string;
127
+ holder?: 'system';
128
+ }[];
129
+ }): HostReservations;
130
+ /**
131
+ * #2446: why a release's role set would be refused where a scope stores `state`, or null: the
132
+ * question that scope's reconcile asks (`reservedRoleSetRefusal`, with the incoming version's
133
+ * reservations), asked before a promote moves it. A promote that would hold a seated scope's
134
+ * reconcile is refused instead.
135
+ */
136
+ export declare function releaseRoleSetRefusal(registry: {
137
+ permissions: readonly {
138
+ key: string;
139
+ holder?: 'system';
140
+ }[];
141
+ roles: readonly RoleShape[];
142
+ }, state: RoleState): string | null;
143
+ /**
144
+ * #2446: whether a release's role set can be refused by any scope's stored state, so its promote
145
+ * must ask the scopes it moves. A system-held role meets the seat rule and the stored definitions
146
+ * (`reservedRoleDefinitionRefusal`). A person's role is judged against stored state only for a key
147
+ * its registry does not declare: every declared key is a reserved one, refused at push, or a
148
+ * person's, which no stored row overrides. A release with neither asks no scope.
149
+ */
150
+ export declare function releaseRolesAskScopes(registry: {
151
+ permissions: readonly {
152
+ key: string;
153
+ }[];
154
+ roles: readonly RoleShape[];
155
+ }): boolean;
156
+ /**
157
+ * #2447: the role keys a scope's own tuples seat anyone but a system principal in, live now — what
158
+ * a role set defined on the scope is judged against. One parameter: now (ISO text).
159
+ */
160
+ export declare const SCOPE_SEATED_ROLES_SQL = "SELECT DISTINCT substr(relation, 6) AS role_key FROM _substrat_tuples WHERE relation LIKE 'role:%' AND subject NOT LIKE 'system:%' AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at > ?)";
161
+ /** A scope dump's table, as a restore carries it: its name, its columns, and its rows in that order. */
162
+ export interface DumpTable {
163
+ name: string;
164
+ columns: readonly string[];
165
+ rows: readonly (readonly unknown[])[];
166
+ }
167
+ /**
168
+ * #2447: what a scope dump stores for a tenant's roles, and the role keys anyone but a system
169
+ * principal holds a live scope-level seat in there — `SCOPE_SEATED_ROLES_SQL`'s reading, over a dump's
170
+ * rows instead of a table. A dump's projected tenant-level tuples are not seats here: the repair a
171
+ * restore runs projects none, so they do not survive it, and the tenant's own seats are the
172
+ * directory's. A restore judges the role set its repair defines against it before it imports the dump.
173
+ */
174
+ export declare function dumpRoleState(tables: readonly DumpTable[], tenantId: string, now: string): StoredRoles;
175
+ /**
176
+ * #2447: the scope statuses whose seats count as held when a role definition is judged: every one
177
+ * but `reaped` (whose storage is gone), a scope archived straight from `provisioning` included: it
178
+ * can hold a seat (the platform's door seats into a provisioning scope), and unarchive brings it back.
179
+ * Each adapter reads such a scope without creating storage it never had, and where it cannot, fails
180
+ * closed. An archived scope comes back on unarchive with its seats, so
181
+ * a definition judged without them would relabel those seats; both adapters read this one list.
182
+ */
183
+ export declare const SEAT_HOLDING_SCOPE_STATUSES: readonly ['provisioning', 'active', 'suspended', 'archiving', 'archived'];
184
+ /** #2447: `SCOPE_SEATED_ROLES_SQL` for a tenant's tenant-level tuples. Parameters: tenantId, now. */
185
+ export declare const TENANT_SEATED_ROLES_SQL = "SELECT DISTINCT substr(relation, 6) AS role_key FROM _substrat_tenant_tuples WHERE tenant_id = ? AND relation LIKE 'role:%' AND subject NOT LIKE 'system:%' AND revoked_at IS NULL AND (expires_at IS NULL OR expires_at > ?)";
35
186
  /**
36
187
  * Why `permissions` may not be granted directly to a principal, an org or a connection, or null
37
188
  * (#2430): a raw grant (`HostAdmin.grant`, `grantToOrg`, `grantEntityShape`, `ctx.grant`) names a
@@ -57,6 +208,8 @@ export declare function reservedShapeRefusal(shapes: readonly {
57
208
  * module its declared `permissions` lists (a manifest there with no permission list adds nothing).
58
209
  */
59
210
  export declare function noteReservedKeys(reserved: Set<string>, manifest: DeclaredManifest): void;
211
+ /** #2447: add every key `manifest` declares, marked or not, to a host's `declared` set (`HostReservations`). */
212
+ export declare function noteDeclaredKeys(declared: Set<string>, manifest: DeclaredManifest): void;
60
213
  /** A manifest as far as a reservation and the declared-module check read it. */
61
214
  export type DeclaredManifest = Omit<ReservedKeySource['manifest'], 'permissions'> & {
62
215
  permissions?: ReservedKeySource['manifest']['permissions'];
@@ -1 +1 @@
1
- {"version":3,"file":"reserved-roles.d.ts","sourceRoot":"","sources":["../src/reserved-roles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAkB,KAAK,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAEjF;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,mBAAmB,CACjC,IAAI,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAC;IAAC,MAAM,CAAC,EAAE,QAAQ,GAAG,QAAQ,CAAA;CAAE,EACnF,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,EAC7B,IAAI,EAAE,QAAQ,GAAG,UAAU,GAC1B,MAAM,GAAG,IAAI,CAuBf;AAED;;;;;;;GAOG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,SAAS,MAAM,EAAE,EAAE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,IAAI,CAIjH;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAClC,MAAM,EAAE,SAAS;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,EAAE,EACzE,QAAQ,EAAE,WAAW,CAAC,MAAM,CAAC,GAC5B,MAAM,GAAG,IAAI,CAMf;AASD;;;GAGG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,GAAG,CAAC,MAAM,CAAC,EAAE,QAAQ,EAAE,gBAAgB,GAAG,IAAI,CAExF;AAED,gFAAgF;AAChF,MAAM,MAAM,gBAAgB,GAAG,IAAI,CAAC,iBAAiB,CAAC,UAAU,CAAC,EAAE,aAAa,CAAC,GAAG;IAAE,WAAW,CAAC,EAAE,iBAAiB,CAAC,UAAU,CAAC,CAAC,aAAa,CAAC,CAAA;CAAE,CAAC;AAEnJ;;;;;GAKG;AACH,MAAM,WAAW,mBAAmB;IAClC,OAAO,EAAE,SAAS;QAAE,QAAQ,EAAE,gBAAgB,CAAA;KAAE,EAAE,CAAC;CACpD;AAED;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,mBAAmB,GAAG,SAAS,EAAE,QAAQ,EAAE,MAAM,GAAG,IAAI,CAQzG"}
1
+ {"version":3,"file":"reserved-roles.d.ts","sourceRoot":"","sources":["../src/reserved-roles.ts"],"names":[],"mappings":"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"}