@substrat-run/kernel 0.158.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.
- package/dist/billing-retention.d.ts +46 -0
- package/dist/billing-retention.d.ts.map +1 -0
- package/dist/billing-retention.js +78 -0
- package/dist/billing-retention.js.map +1 -0
- package/dist/byte-stream.d.ts +102 -0
- package/dist/byte-stream.d.ts.map +1 -0
- package/dist/byte-stream.js +153 -0
- package/dist/byte-stream.js.map +1 -0
- package/dist/connection-landings.d.ts +15 -3
- package/dist/connection-landings.d.ts.map +1 -1
- package/dist/connection-landings.js +10 -2
- package/dist/connection-landings.js.map +1 -1
- package/dist/deadline-fetch.d.ts +34 -0
- package/dist/deadline-fetch.d.ts.map +1 -0
- package/dist/deadline-fetch.js +231 -0
- package/dist/deadline-fetch.js.map +1 -0
- package/dist/deployment-wire-auth.d.ts +82 -0
- package/dist/deployment-wire-auth.d.ts.map +1 -0
- package/dist/deployment-wire-auth.js +150 -0
- package/dist/deployment-wire-auth.js.map +1 -0
- package/dist/entity-trash.d.ts +65 -8
- package/dist/entity-trash.d.ts.map +1 -1
- package/dist/entity-trash.js +80 -12
- package/dist/entity-trash.js.map +1 -1
- package/dist/export-break.d.ts +6 -0
- package/dist/export-break.d.ts.map +1 -1
- package/dist/export-break.js +11 -0
- package/dist/export-break.js.map +1 -1
- package/dist/index.d.ts +18 -9
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +16 -7
- package/dist/index.js.map +1 -1
- package/dist/invocation-line.d.ts +3 -2
- package/dist/invocation-line.d.ts.map +1 -1
- package/dist/invocation-line.js +2 -0
- package/dist/invocation-line.js.map +1 -1
- package/dist/meter-days.d.ts +107 -0
- package/dist/meter-days.d.ts.map +1 -0
- package/dist/meter-days.js +230 -0
- package/dist/meter-days.js.map +1 -0
- package/dist/meters.d.ts +19 -1
- package/dist/meters.d.ts.map +1 -1
- package/dist/meters.js +0 -0
- package/dist/meters.js.map +1 -1
- package/dist/ops-failure-reference.d.ts +31 -0
- package/dist/ops-failure-reference.d.ts.map +1 -0
- package/dist/ops-failure-reference.js +32 -0
- package/dist/ops-failure-reference.js.map +1 -0
- package/dist/platform-request-cap.d.ts +9 -0
- package/dist/platform-request-cap.d.ts.map +1 -0
- package/dist/platform-request-cap.js +42 -0
- package/dist/platform-request-cap.js.map +1 -0
- package/dist/platform-sweep.d.ts +170 -7
- package/dist/platform-sweep.d.ts.map +1 -1
- package/dist/platform-sweep.js +375 -45
- package/dist/platform-sweep.js.map +1 -1
- package/dist/request-rollup.d.ts +161 -0
- package/dist/request-rollup.d.ts.map +1 -0
- package/dist/request-rollup.js +273 -0
- package/dist/request-rollup.js.map +1 -0
- package/dist/reserved-roles.d.ts +157 -4
- package/dist/reserved-roles.d.ts.map +1 -1
- package/dist/reserved-roles.js +216 -2
- package/dist/reserved-roles.js.map +1 -1
- package/dist/schedule-state.d.ts +5 -0
- package/dist/schedule-state.d.ts.map +1 -1
- package/dist/scope-host.d.ts +260 -15
- package/dist/scope-host.d.ts.map +1 -1
- package/dist/scope-host.js +53 -2
- package/dist/scope-host.js.map +1 -1
- package/dist/scope-lifecycle.d.ts +7 -0
- package/dist/scope-lifecycle.d.ts.map +1 -1
- package/dist/scope-lifecycle.js +7 -0
- package/dist/scope-lifecycle.js.map +1 -1
- package/dist/scope-record.d.ts +16 -5
- package/dist/scope-record.d.ts.map +1 -1
- package/dist/scope-record.js +72 -7
- package/dist/scope-record.js.map +1 -1
- package/dist/spine-restore.d.ts +7 -3
- package/dist/spine-restore.d.ts.map +1 -1
- package/dist/spine-restore.js +14 -3
- package/dist/spine-restore.js.map +1 -1
- package/dist/storage-gauge.d.ts +47 -13
- package/dist/storage-gauge.d.ts.map +1 -1
- package/dist/storage-gauge.js +84 -27
- package/dist/storage-gauge.js.map +1 -1
- package/dist/subject-redaction.d.ts +9 -3
- package/dist/subject-redaction.d.ts.map +1 -1
- package/dist/subject-redaction.js +24 -12
- package/dist/subject-redaction.js.map +1 -1
- package/dist/vertical-owners.d.ts +69 -0
- package/dist/vertical-owners.d.ts.map +1 -0
- package/dist/vertical-owners.js +108 -0
- package/dist/vertical-owners.js.map +1 -0
- 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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"}
|
package/dist/reserved-roles.d.ts
CHANGED
|
@@ -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
|
-
*
|
|
25
|
-
* a
|
|
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
|
-
}
|
|
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
|
|
1
|
+
{"version":3,"file":"reserved-roles.d.ts","sourceRoot":"","sources":["../src/reserved-roles.ts"],"names":[],"mappings":"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"}
|