@substrat-run/kernel 0.159.0 → 0.161.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 (95) 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 +142 -0
  6. package/dist/byte-stream.d.ts.map +1 -0
  7. package/dist/byte-stream.js +274 -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 +125 -0
  18. package/dist/deployment-wire-auth.d.ts.map +1 -0
  19. package/dist/deployment-wire-auth.js +161 -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 +19 -10
  30. package/dist/index.d.ts.map +1 -1
  31. package/dist/index.js +17 -8
  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 +43 -0
  42. package/dist/ops-failure-reference.d.ts.map +1 -0
  43. package/dist/ops-failure-reference.js +42 -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 +187 -7
  50. package/dist/platform-sweep.d.ts.map +1 -1
  51. package/dist/platform-sweep.js +388 -45
  52. package/dist/platform-sweep.js.map +1 -1
  53. package/dist/promote-review.d.ts +6 -0
  54. package/dist/promote-review.d.ts.map +1 -1
  55. package/dist/promote-review.js +9 -0
  56. package/dist/promote-review.js.map +1 -1
  57. package/dist/request-rollup.d.ts +161 -0
  58. package/dist/request-rollup.d.ts.map +1 -0
  59. package/dist/request-rollup.js +273 -0
  60. package/dist/request-rollup.js.map +1 -0
  61. package/dist/reserved-roles.d.ts +192 -4
  62. package/dist/reserved-roles.d.ts.map +1 -1
  63. package/dist/reserved-roles.js +314 -2
  64. package/dist/reserved-roles.js.map +1 -1
  65. package/dist/schedule-state.d.ts +5 -0
  66. package/dist/schedule-state.d.ts.map +1 -1
  67. package/dist/scope-host.d.ts +317 -15
  68. package/dist/scope-host.d.ts.map +1 -1
  69. package/dist/scope-host.js +93 -2
  70. package/dist/scope-host.js.map +1 -1
  71. package/dist/scope-lifecycle.d.ts +7 -0
  72. package/dist/scope-lifecycle.d.ts.map +1 -1
  73. package/dist/scope-lifecycle.js +7 -0
  74. package/dist/scope-lifecycle.js.map +1 -1
  75. package/dist/scope-record.d.ts +16 -5
  76. package/dist/scope-record.d.ts.map +1 -1
  77. package/dist/scope-record.js +72 -7
  78. package/dist/scope-record.js.map +1 -1
  79. package/dist/spine-restore.d.ts +7 -3
  80. package/dist/spine-restore.d.ts.map +1 -1
  81. package/dist/spine-restore.js +14 -3
  82. package/dist/spine-restore.js.map +1 -1
  83. package/dist/storage-gauge.d.ts +47 -13
  84. package/dist/storage-gauge.d.ts.map +1 -1
  85. package/dist/storage-gauge.js +84 -27
  86. package/dist/storage-gauge.js.map +1 -1
  87. package/dist/subject-redaction.d.ts +9 -3
  88. package/dist/subject-redaction.d.ts.map +1 -1
  89. package/dist/subject-redaction.js +23 -12
  90. package/dist/subject-redaction.js.map +1 -1
  91. package/dist/vertical-owners.d.ts +69 -0
  92. package/dist/vertical-owners.d.ts.map +1 -0
  93. package/dist/vertical-owners.js +108 -0
  94. package/dist/vertical-owners.js.map +1 -0
  95. package/package.json +2 -2
@@ -0,0 +1,46 @@
1
+ import type { RedactionSql } from './subject-redaction.js';
2
+ /**
3
+ * How long the platform keeps its billing rollups (#2501): the compact per-(tenant, vertical)
4
+ * daily counts a later invoice, or a dispute about one, is answered from. Today that is the daily
5
+ * request rollup (`request-rollup.ts`) and the daily meter snapshot (`meter-days.ts`). The raw
6
+ * captures behind a rollup keep their own, shorter windows, and no existing retention follows
7
+ * this constant: the storage gauge's day rows stay `STORAGE_GAUGE_RETENTION_MONTHS` and model
8
+ * usage stays `MODEL_USAGE_RETENTION_DAYS`.
9
+ *
10
+ * `null` means the rollups are never pruned. That is a placeholder, not a decision: the horizon
11
+ * waits on the maintainer's bookkeeping, and no legal period is written here. Keeping
12
+ * everything is the reversible default, since a pruned row cannot be brought back while a
13
+ * horizon can be set later. The rollups hold counts and bytes only, never personal content.
14
+ */
15
+ export declare const BILLING_ROLLUP_RETENTION_MONTHS: number | null;
16
+ /**
17
+ * The first day a billing retention of `months` keeps, or null when `months` is null (kept for
18
+ * good). A horizon is a whole number of months, at least one. Every billing rollup prunes by it.
19
+ */
20
+ export declare function billingRollupHorizon(nowMs: number, months: number | null): string | null;
21
+ /**
22
+ * The UTC day `months` calendar months before `nowMs`. The day of the month is clamped to the
23
+ * target month's last day, so the 31st counts back to the 28th, 29th or 30th rather than rolling
24
+ * forward into the month after.
25
+ */
26
+ export declare function utcDayMonthsBefore(nowMs: number, months: number): string;
27
+ /** The UTC day an instant falls on. */
28
+ export declare function utcDayOf(ms: number): string;
29
+ /** `day`, refused unless it is a UTC day that exists (`YYYY-MM-DD`). */
30
+ export declare function assertUtcDay(name: string, day: string): string;
31
+ /** Push an inclusive window of UTC days onto a `WHERE` list and its parameters, each day checked first. */
32
+ export declare function pushDayWindow(filter: {
33
+ since?: string;
34
+ until?: string;
35
+ }, where: string[], params: (string | number)[]): void;
36
+ /**
37
+ * Delete at most `limit` rows of a billing rollup's `rows` table older than a retention of
38
+ * `months`, oldest first, then the `records` of the days that are gone. `months` null deletes
39
+ * nothing. A record goes only once its day holds no row, so a day still being pruned stays marked
40
+ * done and is not rolled up again in between. Returns how many rows went.
41
+ */
42
+ export declare function pruneBillingDays(sql: RedactionSql, tables: {
43
+ rows: string;
44
+ records: string;
45
+ }, nowMs: number, limit: number, months: number | null): number;
46
+ //# sourceMappingURL=billing-retention.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-retention.d.ts","sourceRoot":"","sources":["../src/billing-retention.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,wBAAwB,CAAC;AAG3D;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,+BAA+B,EAAE,MAAM,GAAG,IAAW,CAAC;AAEnE;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAMxF;AAED;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM,GAAG,MAAM,CAMxE;AAED,uCAAuC;AACvC,wBAAgB,QAAQ,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAE3C;AAED,wEAAwE;AACxE,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,MAAM,CAG9D;AAED,2GAA2G;AAC3G,wBAAgB,aAAa,CAAC,MAAM,EAAE;IAAE,KAAK,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,MAAM,CAAA;CAAE,EAAE,KAAK,EAAE,MAAM,EAAE,EAAE,MAAM,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG,IAAI,CAS5H;AAED;;;;;GAKG;AACH,wBAAgB,gBAAgB,CAC9B,GAAG,EAAE,YAAY,EACjB,MAAM,EAAE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,EACzC,KAAK,EAAE,MAAM,EACb,KAAK,EAAE,MAAM,EACb,MAAM,EAAE,MAAM,GAAG,IAAI,GACpB,MAAM,CAWR"}
@@ -0,0 +1,78 @@
1
+ import { utcDay } from '@substrat-run/contracts';
2
+ import { assertRowLimit, boundedRetentionDelete } from './scope-host.js';
3
+ /**
4
+ * How long the platform keeps its billing rollups (#2501): the compact per-(tenant, vertical)
5
+ * daily counts a later invoice, or a dispute about one, is answered from. Today that is the daily
6
+ * request rollup (`request-rollup.ts`) and the daily meter snapshot (`meter-days.ts`). The raw
7
+ * captures behind a rollup keep their own, shorter windows, and no existing retention follows
8
+ * this constant: the storage gauge's day rows stay `STORAGE_GAUGE_RETENTION_MONTHS` and model
9
+ * usage stays `MODEL_USAGE_RETENTION_DAYS`.
10
+ *
11
+ * `null` means the rollups are never pruned. That is a placeholder, not a decision: the horizon
12
+ * waits on the maintainer's bookkeeping, and no legal period is written here. Keeping
13
+ * everything is the reversible default, since a pruned row cannot be brought back while a
14
+ * horizon can be set later. The rollups hold counts and bytes only, never personal content.
15
+ */
16
+ export const BILLING_ROLLUP_RETENTION_MONTHS = null;
17
+ /**
18
+ * The first day a billing retention of `months` keeps, or null when `months` is null (kept for
19
+ * good). A horizon is a whole number of months, at least one. Every billing rollup prunes by it.
20
+ */
21
+ export function billingRollupHorizon(nowMs, months) {
22
+ if (months === null)
23
+ return null;
24
+ if (!Number.isInteger(months) || months < 1) {
25
+ throw new Error(`a billing retention must be a whole number of months, at least one, or null, got ${String(months)}`);
26
+ }
27
+ return utcDayMonthsBefore(nowMs, months);
28
+ }
29
+ /**
30
+ * The UTC day `months` calendar months before `nowMs`. The day of the month is clamped to the
31
+ * target month's last day, so the 31st counts back to the 28th, 29th or 30th rather than rolling
32
+ * forward into the month after.
33
+ */
34
+ export function utcDayMonthsBefore(nowMs, months) {
35
+ const now = new Date(nowMs);
36
+ const month = now.getUTCMonth() - months;
37
+ // Day 0 of the following month is the last day of the target month.
38
+ const lastDay = new Date(Date.UTC(now.getUTCFullYear(), month + 1, 0)).getUTCDate();
39
+ return new Date(Date.UTC(now.getUTCFullYear(), month, Math.min(now.getUTCDate(), lastDay))).toISOString().slice(0, 10);
40
+ }
41
+ /** The UTC day an instant falls on. */
42
+ export function utcDayOf(ms) {
43
+ return new Date(ms).toISOString().slice(0, 10);
44
+ }
45
+ /** `day`, refused unless it is a UTC day that exists (`YYYY-MM-DD`). */
46
+ export function assertUtcDay(name, day) {
47
+ if (!utcDay.safeParse(day).success)
48
+ throw new Error(`${name} must be a UTC day (YYYY-MM-DD), got ${JSON.stringify(day)}`);
49
+ return day;
50
+ }
51
+ /** Push an inclusive window of UTC days onto a `WHERE` list and its parameters, each day checked first. */
52
+ export function pushDayWindow(filter, where, params) {
53
+ if (filter.since !== undefined) {
54
+ where.push('day >= ?');
55
+ params.push(assertUtcDay('since', filter.since));
56
+ }
57
+ if (filter.until !== undefined) {
58
+ where.push('day <= ?');
59
+ params.push(assertUtcDay('until', filter.until));
60
+ }
61
+ }
62
+ /**
63
+ * Delete at most `limit` rows of a billing rollup's `rows` table older than a retention of
64
+ * `months`, oldest first, then the `records` of the days that are gone. `months` null deletes
65
+ * nothing. A record goes only once its day holds no row, so a day still being pruned stays marked
66
+ * done and is not rolled up again in between. Returns how many rows went.
67
+ */
68
+ export function pruneBillingDays(sql, tables, nowMs, limit, months) {
69
+ const capped = assertRowLimit('limit', limit);
70
+ const horizon = billingRollupHorizon(nowMs, months);
71
+ if (horizon === null)
72
+ return 0;
73
+ const pruned = sql(boundedRetentionDelete(tables.rows, 'day'), [horizon, capped]).length;
74
+ sql(`DELETE FROM ${tables.records}
75
+ WHERE day < ? AND NOT EXISTS (SELECT 1 FROM ${tables.rows} d WHERE d.day = ${tables.records}.day)`, [horizon]);
76
+ return pruned;
77
+ }
78
+ //# sourceMappingURL=billing-retention.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"billing-retention.js","sourceRoot":"","sources":["../src/billing-retention.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,142 @@
1
+ /**
2
+ * Bytes as a stream (#2498, `docs/rfc/file-bearing-sources.md` §6).
3
+ *
4
+ * The byte seams between a provider, a connector and the attachment store each took the whole
5
+ * body as one buffer, so the largest file a connector could land was whatever the worker had
6
+ * memory for. Each seam now also takes a {@link SizedByteStream}: a stream, plus the length its
7
+ * producer declares. The length is declared rather than counted because the stores need it
8
+ * before the first byte (R2 refuses a stream of unknown length), and it is enforced on the way
9
+ * through: a stream that carries more or fewer bytes than it declared errors instead of landing.
10
+ *
11
+ * Structural, for the reason `FetchLike` is: the kernel depends on no platform typings, and a
12
+ * web `ReadableStream<Uint8Array>` from Node, workerd or a browser satisfies {@link ByteStream}
13
+ * without either being required.
14
+ */
15
+ /** One read from a {@link ByteStreamReader}: a chunk, or the end. */
16
+ export interface ByteStreamRead {
17
+ readonly done: boolean;
18
+ readonly value?: Uint8Array;
19
+ }
20
+ /** The reader a {@link ByteStream} hands out — the slice of `ReadableStreamDefaultReader` used here. */
21
+ export interface ByteStreamReader {
22
+ read(): Promise<ByteStreamRead>;
23
+ cancel(reason?: unknown): Promise<void>;
24
+ releaseLock(): void;
25
+ }
26
+ /** A web `ReadableStream<Uint8Array>`, structurally. */
27
+ export interface ByteStream {
28
+ getReader(): ByteStreamReader;
29
+ }
30
+ /** A byte stream with the length its producer declares. */
31
+ export interface SizedByteStream {
32
+ readonly stream: ByteStream;
33
+ readonly length: number;
34
+ }
35
+ /** A body a byte seam takes: the whole buffer, as before, or a sized stream. */
36
+ export type ByteBody = Uint8Array | SizedByteStream;
37
+ /**
38
+ * Bytes a connector already holds, in the shape a connector upload takes (#2538): the buffer itself
39
+ * up to {@link CONNECTOR_ATTACHMENT_BUFFERED_MAX_BYTES}, and above it a {@link SizedByteStream} of the
40
+ * same bytes, which the platform sends by the streamed route instead of refusing. It does not shrink
41
+ * what the connector holds; it keeps a file the connector could fetch landing end to end. The stream
42
+ * is one-shot: read it once, and call this again for another upload of the same bytes.
43
+ */
44
+ export declare function connectorUploadBody(bytes: Uint8Array): ByteBody;
45
+ /**
46
+ * Bytes already held, as a one-shot {@link SizedByteStream} handed out 1 MiB at a time. It saves no
47
+ * memory, since the buffer is held; it lets a buffer go where a seam takes a stream. Each chunk is a
48
+ * copy, not a view of `bytes`, so a consumer that takes a chunk's buffer cannot detach the rest.
49
+ */
50
+ export declare function bytesStream(bytes: Uint8Array): SizedByteStream;
51
+ /** Is `body` a sized stream rather than a buffer? */
52
+ export declare function isSizedByteStream(body: unknown): body is SizedByteStream;
53
+ /**
54
+ * A running SHA-256, fed one chunk at a time. The kernel holds no implementation: Web Crypto has
55
+ * no incremental digest and a hand-rolled one is not an option, so each adapter passes its
56
+ * runtime's own (workerd's `crypto.DigestStream`, Node's `createHash`).
57
+ */
58
+ export interface IncrementalSha256 {
59
+ update(chunk: Uint8Array): void | Promise<void>;
60
+ /** The lowercase hex digest of everything fed so far. Called once, after the last chunk. */
61
+ hex(): Promise<string>;
62
+ }
63
+ /**
64
+ * What makes the runtime's own running SHA-256, where it has one (workerd's `crypto.DigestStream`), or
65
+ * `undefined` where it has none (Node, a browser): the kernel finds the runtime's, it never holds one.
66
+ * A maker rather than a digest, so a caller can learn whether it can check bytes before it asks for
67
+ * any, and opens a digest only for bytes it has.
68
+ */
69
+ export declare function runtimeSha256(): (() => IncrementalSha256) | undefined;
70
+ /** What a witnessed stream's bytes were, once they have all passed. */
71
+ export interface StreamWitness {
72
+ readonly sha256: string;
73
+ readonly size: number;
74
+ }
75
+ /** A sized stream that hashes and counts its bytes as its reader takes them. */
76
+ export interface WitnessedStream {
77
+ readonly body: SizedByteStream;
78
+ /**
79
+ * The bytes' sha256 and size. Throws until the stream has been read to its end, so a store
80
+ * that answered without consuming the body cannot have a record written for bytes it never saw.
81
+ */
82
+ witness(): StreamWitness;
83
+ }
84
+ /**
85
+ * Hash and count `body` while it flows to wherever it is going. The digest is fed each chunk
86
+ * before the chunk moves on, and the final digest is taken before the stream reports its end, so
87
+ * once the consumer has read to the end — a store's `put` has resolved — {@link
88
+ * WitnessedStream.witness} answers.
89
+ */
90
+ export declare function witnessedStream(body: SizedByteStream, digest: IncrementalSha256): WitnessedStream;
91
+ /**
92
+ * The largest chunk a {@link verifiedStream} hands on, and so the most it holds back at its end. A
93
+ * source chunk larger than this is handed on in pieces of this size.
94
+ */
95
+ export declare const VERIFIED_STREAM_CHUNK_MAX_BYTES: number;
96
+ /**
97
+ * Stored bytes on their way out, held to the record that witnesses them (#2514): its `size` and its
98
+ * `sha256`, both checked as the bytes pass rather than before the first one, so nothing is held whole.
99
+ *
100
+ * **What a consumer sees when the bytes are wrong.** The digest is known only after the last byte, so
101
+ * the chunk that completes the declared size is held back until the source has ended and the digest
102
+ * matches. A mismatch, a source that ends short, or one that carries more errors the stream instead,
103
+ * and that last chunk is never handed on. So a consumer can never have received all `size` bytes of a
104
+ * file that did not verify. One that counts to `size` and stops reading is as safe as one that reads to
105
+ * the end. What it may have received before the error is a prefix, and it is told so by the error.
106
+ *
107
+ * The held-back chunk is at most {@link VERIFIED_STREAM_CHUNK_MAX_BYTES}: a source chunk larger than
108
+ * that is handed on in copies of that size, so the wait never holds more than one such piece beside the
109
+ * source chunk it came from. A source chunk within the cap is handed on as the source gave it.
110
+ *
111
+ * Throws before reading anything when the stream's length is not the record's `size`, or the record
112
+ * carries no sha256 to verify against, so a file is never handed on as verified when it could not be.
113
+ */
114
+ export declare function verifiedStream(body: SizedByteStream, expected: {
115
+ readonly size: number;
116
+ readonly sha256: string;
117
+ }, digest: IncrementalSha256): SizedByteStream;
118
+ /**
119
+ * `body` as a stream of known length that the runtime takes, held to its declared length: a
120
+ * stream that carries more or fewer bytes errors whatever reads it. On workerd that is a
121
+ * `FixedLengthStream`, which a `fetch` sends with a `Content-Length` rather than chunked and
122
+ * which R2's `put` accepts (it refuses a stream of unknown length); the runtime enforces the
123
+ * length there, so a web stream is piped straight in. Elsewhere it is the stream passed through
124
+ * a relay that enforces the length.
125
+ */
126
+ export declare function knownLengthStream(body: SizedByteStream): ByteStream;
127
+ /**
128
+ * A request init whose body is a sized stream, as the runtime's `fetch` takes it: the body
129
+ * as {@link knownLengthStream}, and off workerd the `Content-Length` header and `duplex: 'half'`
130
+ * a streamed request body needs there. `fetchLikeOf` sends through it, so a `FetchLike` does not
131
+ * call this itself: a runtime `fetch` becomes one by `fetchLikeOf`. A caller that holds a
132
+ * runtime `fetch` it does not make a `FetchLike` (the platform's vertical client) does.
133
+ */
134
+ export declare function knownLengthInit<Init extends {
135
+ headers?: Record<string, string>;
136
+ body: SizedByteStream;
137
+ }>(init: Init): Omit<Init, 'body'> & {
138
+ body: ByteStream;
139
+ headers: Record<string, string>;
140
+ duplex?: 'half';
141
+ };
142
+ //# sourceMappingURL=byte-stream.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byte-stream.d.ts","sourceRoot":"","sources":["../src/byte-stream.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAIH,qEAAqE;AACrE,MAAM,WAAW,cAAc;IAC7B,QAAQ,CAAC,IAAI,EAAE,OAAO,CAAC;IACvB,QAAQ,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC;CAC7B;AAED,wGAAwG;AACxG,MAAM,WAAW,gBAAgB;IAC/B,IAAI,IAAI,OAAO,CAAC,cAAc,CAAC,CAAC;IAChC,MAAM,CAAC,MAAM,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,WAAW,IAAI,IAAI,CAAC;CACrB;AAED,wDAAwD;AACxD,MAAM,WAAW,UAAU;IACzB,SAAS,IAAI,gBAAgB,CAAC;CAC/B;AAED,2DAA2D;AAC3D,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,MAAM,EAAE,UAAU,CAAC;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;CACzB;AAED,gFAAgF;AAChF,MAAM,MAAM,QAAQ,GAAG,UAAU,GAAG,eAAe,CAAC;AAEpD;;;;;;GAMG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,UAAU,GAAG,QAAQ,CAG/D;AAED;;;;GAIG;AACH,wBAAgB,WAAW,CAAC,KAAK,EAAE,UAAU,GAAG,eAAe,CAkB9D;AAED,qDAAqD;AACrD,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,OAAO,GAAG,IAAI,IAAI,eAAe,CAQxE;AAED;;;;GAIG;AACH,MAAM,WAAW,iBAAiB;IAChC,MAAM,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAChD,4FAA4F;IAC5F,GAAG,IAAI,OAAO,CAAC,MAAM,CAAC,CAAC;CACxB;AAQD;;;;;GAKG;AACH,wBAAgB,aAAa,IAAI,CAAC,MAAM,iBAAiB,CAAC,GAAG,SAAS,CAcrE;AAED,uEAAuE;AACvE,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;IACxB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;CACvB;AAED,gFAAgF;AAChF,MAAM,WAAW,eAAe;IAC9B,QAAQ,CAAC,IAAI,EAAE,eAAe,CAAC;IAC/B;;;OAGG;IACH,OAAO,IAAI,aAAa,CAAC;CAC1B;AAmED;;;;;GAKG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,MAAM,EAAE,iBAAiB,GAAG,eAAe,CAiBjG;AAED;;;GAGG;AACH,eAAO,MAAM,+BAA+B,QAAc,CAAC;AAI3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,cAAc,CAC5B,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAA;CAAE,EAC5D,MAAM,EAAE,iBAAiB,GACxB,eAAe,CAgEjB;AAUD;;;;;;;GAOG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE,eAAe,GAAG,UAAU,CAOnE;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,SAAS;IAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,IAAI,EAAE,eAAe,CAAA;CAAE,EACtG,IAAI,EAAE,IAAI,GACT,IAAI,CAAC,IAAI,EAAE,MAAM,CAAC,GAAG;IAAE,IAAI,EAAE,UAAU,CAAC;IAAC,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,CAS7F"}
@@ -0,0 +1,274 @@
1
+ /**
2
+ * Bytes as a stream (#2498, `docs/rfc/file-bearing-sources.md` §6).
3
+ *
4
+ * The byte seams between a provider, a connector and the attachment store each took the whole
5
+ * body as one buffer, so the largest file a connector could land was whatever the worker had
6
+ * memory for. Each seam now also takes a {@link SizedByteStream}: a stream, plus the length its
7
+ * producer declares. The length is declared rather than counted because the stores need it
8
+ * before the first byte (R2 refuses a stream of unknown length), and it is enforced on the way
9
+ * through: a stream that carries more or fewer bytes than it declared errors instead of landing.
10
+ *
11
+ * Structural, for the reason `FetchLike` is: the kernel depends on no platform typings, and a
12
+ * web `ReadableStream<Uint8Array>` from Node, workerd or a browser satisfies {@link ByteStream}
13
+ * without either being required.
14
+ */
15
+ import { CONNECTOR_ATTACHMENT_BUFFERED_MAX_BYTES } from '@substrat-run/contracts';
16
+ /**
17
+ * Bytes a connector already holds, in the shape a connector upload takes (#2538): the buffer itself
18
+ * up to {@link CONNECTOR_ATTACHMENT_BUFFERED_MAX_BYTES}, and above it a {@link SizedByteStream} of the
19
+ * same bytes, which the platform sends by the streamed route instead of refusing. It does not shrink
20
+ * what the connector holds; it keeps a file the connector could fetch landing end to end. The stream
21
+ * is one-shot: read it once, and call this again for another upload of the same bytes.
22
+ */
23
+ export function connectorUploadBody(bytes) {
24
+ if (bytes.byteLength <= CONNECTOR_ATTACHMENT_BUFFERED_MAX_BYTES)
25
+ return bytes;
26
+ return bytesStream(bytes);
27
+ }
28
+ /**
29
+ * Bytes already held, as a one-shot {@link SizedByteStream} handed out 1 MiB at a time. It saves no
30
+ * memory, since the buffer is held; it lets a buffer go where a seam takes a stream. Each chunk is a
31
+ * copy, not a view of `bytes`, so a consumer that takes a chunk's buffer cannot detach the rest.
32
+ */
33
+ export function bytesStream(bytes) {
34
+ const CHUNK = 1024 * 1024;
35
+ let at = 0;
36
+ const stream = new ReadableStream({
37
+ async pull(controller) {
38
+ if (at >= bytes.byteLength) {
39
+ controller.close();
40
+ return;
41
+ }
42
+ controller.enqueue(bytes.slice(at, Math.min(at + CHUNK, bytes.byteLength)));
43
+ at += CHUNK;
44
+ },
45
+ async cancel() { },
46
+ }, { highWaterMark: 0 });
47
+ return { stream, length: bytes.byteLength };
48
+ }
49
+ /** Is `body` a sized stream rather than a buffer? */
50
+ export function isSizedByteStream(body) {
51
+ return (typeof body === 'object' &&
52
+ body !== null &&
53
+ !ArrayBuffer.isView(body) &&
54
+ typeof body.stream?.getReader === 'function' &&
55
+ typeof body.length === 'number');
56
+ }
57
+ /**
58
+ * What makes the runtime's own running SHA-256, where it has one (workerd's `crypto.DigestStream`), or
59
+ * `undefined` where it has none (Node, a browser): the kernel finds the runtime's, it never holds one.
60
+ * A maker rather than a digest, so a caller can learn whether it can check bytes before it asks for
61
+ * any, and opens a digest only for bytes it has.
62
+ */
63
+ export function runtimeSha256() {
64
+ const DigestStream = globalThis.crypto?.DigestStream;
65
+ if (!DigestStream)
66
+ return undefined;
67
+ return () => {
68
+ const digest = new DigestStream('SHA-256');
69
+ const writer = digest.getWriter();
70
+ return {
71
+ update: (chunk) => writer.write(chunk),
72
+ hex: async () => {
73
+ await writer.close();
74
+ return [...new Uint8Array(await digest.digest)].map((b) => b.toString(16).padStart(2, '0')).join('');
75
+ },
76
+ };
77
+ };
78
+ }
79
+ /** Refuse a declared length no stream can have. */
80
+ function assertDeclaredLength(length) {
81
+ if (!Number.isSafeInteger(length) || length < 0) {
82
+ throw new Error(`a byte stream's declared length must be a non-negative integer, not ${length}`);
83
+ }
84
+ }
85
+ /**
86
+ * A new stream that passes `source` through chunk by chunk, holding it to `length`. Pull-driven
87
+ * with no queue of its own (`highWaterMark: 0`), so a chunk is read from the source only when the
88
+ * consumer asks for one: at most one chunk is in flight, whatever the body's size.
89
+ */
90
+ function relay(source, length, onChunk, onEnd) {
91
+ assertDeclaredLength(length);
92
+ const reader = source.getReader();
93
+ let size = 0;
94
+ return new ReadableStream({
95
+ async pull(controller) {
96
+ try {
97
+ const { done, value } = await reader.read();
98
+ if (done) {
99
+ if (size !== length) {
100
+ throw new Error(`the byte stream ended after ${size} bytes; it declared ${length}`);
101
+ }
102
+ await onEnd?.();
103
+ controller.close();
104
+ return;
105
+ }
106
+ // A read that neither ends nor carries a chunk is a broken source: answering it by
107
+ // returning would leave the consumer's read waiting for a pull that never comes.
108
+ if (!value)
109
+ throw new Error('the byte stream yielded a read with neither a chunk nor its end');
110
+ size += value.byteLength;
111
+ if (size > length) {
112
+ throw new Error(`the byte stream carried more than the ${length} bytes it declared`);
113
+ }
114
+ await onChunk?.(value);
115
+ controller.enqueue(value);
116
+ }
117
+ catch (err) {
118
+ controller.error(err);
119
+ await reader.cancel(err).catch(() => { });
120
+ }
121
+ },
122
+ cancel: (reason) => reader.cancel(reason),
123
+ }, { highWaterMark: 0 });
124
+ }
125
+ /**
126
+ * Hash and count `body` while it flows to wherever it is going. The digest is fed each chunk
127
+ * before the chunk moves on, and the final digest is taken before the stream reports its end, so
128
+ * once the consumer has read to the end — a store's `put` has resolved — {@link
129
+ * WitnessedStream.witness} answers.
130
+ */
131
+ export function witnessedStream(body, digest) {
132
+ let witnessed;
133
+ const stream = relay(body.stream, body.length, (chunk) => digest.update(chunk), async () => {
134
+ witnessed = { sha256: await digest.hex(), size: body.length };
135
+ });
136
+ return {
137
+ body: { stream, length: body.length },
138
+ witness: () => {
139
+ if (!witnessed)
140
+ throw new Error('the byte stream was not read to its end, so its bytes are unwitnessed');
141
+ return witnessed;
142
+ },
143
+ };
144
+ }
145
+ /**
146
+ * The largest chunk a {@link verifiedStream} hands on, and so the most it holds back at its end. A
147
+ * source chunk larger than this is handed on in pieces of this size.
148
+ */
149
+ export const VERIFIED_STREAM_CHUNK_MAX_BYTES = 1024 * 1024;
150
+ const SHA256_HEX = /^[0-9a-f]{64}$/;
151
+ /**
152
+ * Stored bytes on their way out, held to the record that witnesses them (#2514): its `size` and its
153
+ * `sha256`, both checked as the bytes pass rather than before the first one, so nothing is held whole.
154
+ *
155
+ * **What a consumer sees when the bytes are wrong.** The digest is known only after the last byte, so
156
+ * the chunk that completes the declared size is held back until the source has ended and the digest
157
+ * matches. A mismatch, a source that ends short, or one that carries more errors the stream instead,
158
+ * and that last chunk is never handed on. So a consumer can never have received all `size` bytes of a
159
+ * file that did not verify. One that counts to `size` and stops reading is as safe as one that reads to
160
+ * the end. What it may have received before the error is a prefix, and it is told so by the error.
161
+ *
162
+ * The held-back chunk is at most {@link VERIFIED_STREAM_CHUNK_MAX_BYTES}: a source chunk larger than
163
+ * that is handed on in copies of that size, so the wait never holds more than one such piece beside the
164
+ * source chunk it came from. A source chunk within the cap is handed on as the source gave it.
165
+ *
166
+ * Throws before reading anything when the stream's length is not the record's `size`, or the record
167
+ * carries no sha256 to verify against, so a file is never handed on as verified when it could not be.
168
+ */
169
+ export function verifiedStream(body, expected, digest) {
170
+ assertDeclaredLength(body.length);
171
+ if (body.length !== expected.size) {
172
+ throw new Error(`the stored object is ${body.length} bytes; its record says ${expected.size}`);
173
+ }
174
+ if (!SHA256_HEX.test(expected.sha256)) {
175
+ throw new Error('the record carries no sha256 to verify the bytes against');
176
+ }
177
+ const length = body.length;
178
+ const reader = body.stream.getReader();
179
+ let rest;
180
+ let delivered = 0;
181
+ /** The next non-empty piece of the source, at most the cap, or `null` at its end. */
182
+ const nextPiece = async () => {
183
+ while (!rest || rest.byteLength === 0) {
184
+ const { done, value } = await reader.read();
185
+ if (done)
186
+ return null;
187
+ if (!value)
188
+ throw new Error('the byte stream yielded a read with neither a chunk nor its end');
189
+ rest = value;
190
+ }
191
+ if (rest.byteLength <= VERIFIED_STREAM_CHUNK_MAX_BYTES) {
192
+ const piece = rest;
193
+ rest = undefined;
194
+ return piece;
195
+ }
196
+ // A copy, not a view: a consumer may take the piece's buffer, which would take the rest with it.
197
+ const piece = rest.slice(0, VERIFIED_STREAM_CHUNK_MAX_BYTES);
198
+ rest = rest.subarray(VERIFIED_STREAM_CHUNK_MAX_BYTES);
199
+ return piece;
200
+ };
201
+ const stream = new ReadableStream({
202
+ async pull(controller) {
203
+ try {
204
+ const piece = delivered < length ? await nextPiece() : null;
205
+ if (delivered < length) {
206
+ if (!piece)
207
+ throw new Error(`the stored object ended after ${delivered} bytes; its record says ${length}`);
208
+ if (delivered + piece.byteLength > length) {
209
+ throw new Error(`the stored object carried more than the ${length} bytes its record says`);
210
+ }
211
+ await digest.update(piece);
212
+ delivered += piece.byteLength;
213
+ if (delivered < length) {
214
+ controller.enqueue(piece);
215
+ return;
216
+ }
217
+ }
218
+ // The last bytes: handed on only once the source has ended and the digest matches.
219
+ if (await nextPiece())
220
+ throw new Error(`the stored object carried more than the ${length} bytes its record says`);
221
+ if ((await digest.hex()) !== expected.sha256)
222
+ throw new Error('the bytes do not match the recorded sha256');
223
+ if (piece)
224
+ controller.enqueue(piece);
225
+ controller.close();
226
+ }
227
+ catch (err) {
228
+ controller.error(err);
229
+ await reader.cancel(err).catch(() => { });
230
+ }
231
+ },
232
+ cancel: (reason) => reader.cancel(reason),
233
+ }, { highWaterMark: 0 });
234
+ return { stream, length };
235
+ }
236
+ /** The runtime's own `FixedLengthStream`, where it has one (workerd). */
237
+ function fixedLengthStream() {
238
+ return globalThis.FixedLengthStream;
239
+ }
240
+ /**
241
+ * `body` as a stream of known length that the runtime takes, held to its declared length: a
242
+ * stream that carries more or fewer bytes errors whatever reads it. On workerd that is a
243
+ * `FixedLengthStream`, which a `fetch` sends with a `Content-Length` rather than chunked and
244
+ * which R2's `put` accepts (it refuses a stream of unknown length); the runtime enforces the
245
+ * length there, so a web stream is piped straight in. Elsewhere it is the stream passed through
246
+ * a relay that enforces the length.
247
+ */
248
+ export function knownLengthStream(body) {
249
+ const Fixed = fixedLengthStream();
250
+ if (!Fixed)
251
+ return relay(body.stream, body.length);
252
+ assertDeclaredLength(body.length);
253
+ const piped = body.stream;
254
+ const source = typeof piped.pipeThrough === 'function' ? piped : relay(body.stream, body.length);
255
+ return source.pipeThrough(new Fixed(body.length));
256
+ }
257
+ /**
258
+ * A request init whose body is a sized stream, as the runtime's `fetch` takes it: the body
259
+ * as {@link knownLengthStream}, and off workerd the `Content-Length` header and `duplex: 'half'`
260
+ * a streamed request body needs there. `fetchLikeOf` sends through it, so a `FetchLike` does not
261
+ * call this itself: a runtime `fetch` becomes one by `fetchLikeOf`. A caller that holds a
262
+ * runtime `fetch` it does not make a `FetchLike` (the platform's vertical client) does.
263
+ */
264
+ export function knownLengthInit(init) {
265
+ const length = init.body.length;
266
+ const onWorkerd = fixedLengthStream() !== undefined;
267
+ return {
268
+ ...init,
269
+ body: knownLengthStream(init.body),
270
+ headers: { ...init.headers, ...(onWorkerd ? {} : { 'content-length': String(length) }) },
271
+ ...(onWorkerd ? {} : { duplex: 'half' }),
272
+ };
273
+ }
274
+ //# sourceMappingURL=byte-stream.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"byte-stream.js","sourceRoot":"","sources":["../src/byte-stream.ts"],"names":[],"mappings":"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"}
@@ -1,5 +1,5 @@
1
- import type { Connection, ConnectionLandingOptions, ManifestConnectionLandings, PlatformActorId, ScopeId, TenantId } from '@substrat-run/contracts';
2
- import type { ScopeHost } from './scope-host.js';
1
+ import type { Connection, ConnectionLandingOptions, ManifestConnectionLandings, PlatformActorId, Scope, ScopeId, TenantId } from '@substrat-run/contracts';
2
+ import type { ScopeFilter, ScopeHost } from './scope-host.js';
3
3
  /**
4
4
  * Connection landings, applied (#2316): the connector pass's step that turns a vertical's declared
5
5
  * `connections` into a held key and a binding for every live connection of that provider.
@@ -94,9 +94,21 @@ export declare class LandingPass {
94
94
  private readonly actor;
95
95
  private readonly input;
96
96
  private readonly concurrency;
97
+ /**
98
+ * How the pass reads a tenant's scopes: the sweep's own reader, so a directory row that does
99
+ * not read as a scope is stepped over here too and named once with the pass's others, rather
100
+ * than failing every landing in its tenant.
101
+ */
102
+ private readonly listScopes;
97
103
  private readonly targets;
98
104
  private readonly held;
99
- constructor(host: ScopeHost, actor: PlatformActorId, input: ConnectionLandingOptionsInput, concurrency: number);
105
+ constructor(host: ScopeHost, actor: PlatformActorId, input: ConnectionLandingOptionsInput, concurrency: number,
106
+ /**
107
+ * How the pass reads a tenant's scopes: the sweep's own reader, so a directory row that does
108
+ * not read as a scope is stepped over here too and named once with the pass's others, rather
109
+ * than failing every landing in its tenant.
110
+ */
111
+ listScopes: (filter: ScopeFilter) => Promise<Scope[]>);
100
112
  /** Grant and bind what `connection`'s installs declare for its provider, and say what happened. */
101
113
  apply(connection: Connection): Promise<LandingOutcome>;
102
114
  /** Every primary, active install of `vertical` in `tenantId`, with what its running version declares. */
@@ -1 +1 @@
1
- {"version":3,"file":"connection-landings.d.ts","sourceRoot":"","sources":["../src/connection-landings.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,UAAU,EACV,wBAAwB,EACxB,0BAA0B,EAC1B,eAAe,EAGf,OAAO,EACP,QAAQ,EACT,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,iBAAiB,CAAC;AAMjD;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AAEH;;;GAGG;AACH,MAAM,WAAW,gBAAgB;IAC/B,iGAAiG;IACjG,IAAI,CAAC,IAAI,EAAE,SAAS,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,SAAS;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC,CAAC;IAC9H,kGAAkG;IAClG,IAAI,CACF,IAAI,EAAE,SAAS,EACf,UAAU,EAAE,UAAU,EACtB,MAAM,EAAE;QAAE,QAAQ,EAAE,QAAQ,CAAC;QAAC,OAAO,EAAE,OAAO,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAClI,OAAO,CAAC,OAAO,CAAC,CAAC;IACpB;;;;;OAKG;IACH,OAAO,CAAC,CACN,GAAG,EAAE,wBAAwB,GAAG,SAAS,EACzC,OAAO,CAAC,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,GACnE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAC3B;;;;OAIG;IACH,KAAK,CAAC,CAAC,OAAO,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,SAAS,EAAE,MAAM,CAAC;QAAC,UAAU,EAAE,MAAM,CAAA;KAAE,EAAE,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC;CAC9G;AAED,MAAM,WAAW,6BAA6B;IAC5C,0GAA0G;IAC1G,IAAI,CAAC,YAAY,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,0BAA0B,CAAC,CAAC;IACnF,wFAAwF;IACxF,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;CAC3C;AAED,6FAA6F;AAC7F,MAAM,WAAW,cAAc;IAC7B,0CAA0C;IAC1C,OAAO,EAAE,OAAO,EAAE,CAAC;IACnB,oEAAoE;IACpE,KAAK,EAAE,OAAO,EAAE,CAAC;IACjB,2FAA2F;IAC3F,MAAM,EAAE;QAAE,OAAO,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC9C;AASD;;;;GAIG;AACH,qBAAa,WAAW;IAKpB,OAAO,CAAC,QAAQ,CAAC,IAAI;IACrB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,KAAK;IACtB,OAAO,CAAC,QAAQ,CAAC,WAAW;IAP9B,OAAO,CAAC,QAAQ,CAAC,OAAO,CAAwC;IAChE,OAAO,CAAC,QAAQ,CAAC,IAAI,CAA0D;IAE/E,YACmB,IAAI,EAAE,SAAS,EACf,KAAK,EAAE,eAAe,EACtB,KAAK,EAAE,6BAA6B,EACpC,WAAW,EAAE,MAAM,EAClC;IAEJ,mGAAmG;IAC7F,KAAK,CAAC,UAAU,EAAE,UAAU,GAAG,OAAO,CAAC,cAAc,CAAC,CA2D3D;IAED,yGAAyG;IACzG,OAAO,CAAC,SAAS;IAwBjB,0EAA0E;IAC1E,OAAO,CAAC,QAAQ;CASjB"}
1
+ {"version":3,"file":"connection-landings.d.ts","sourceRoot":"","sources":["../src/connection-landings.ts"],"names":[],"mappings":"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"}
@@ -12,13 +12,21 @@ export class LandingPass {
12
12
  actor;
13
13
  input;
14
14
  concurrency;
15
+ listScopes;
15
16
  targets = new Map();
16
17
  held = new Map();
17
- constructor(host, actor, input, concurrency) {
18
+ constructor(host, actor, input, concurrency,
19
+ /**
20
+ * How the pass reads a tenant's scopes: the sweep's own reader, so a directory row that does
21
+ * not read as a scope is stepped over here too and named once with the pass's others, rather
22
+ * than failing every landing in its tenant.
23
+ */
24
+ listScopes) {
18
25
  this.host = host;
19
26
  this.actor = actor;
20
27
  this.input = input;
21
28
  this.concurrency = concurrency;
29
+ this.listScopes = listScopes;
22
30
  }
23
31
  /** Grant and bind what `connection`'s installs declare for its provider, and say what happened. */
24
32
  async apply(connection) {
@@ -92,7 +100,7 @@ export class LandingPass {
92
100
  let found = this.targets.get(key);
93
101
  if (!found) {
94
102
  found = (async () => {
95
- const scopes = (await this.host.admin.listScopes(this.actor, { tenantId })).filter((s) => s.vertical === vertical && s.status === 'active' && isPrimaryScope(s));
103
+ const scopes = (await this.listScopes({ tenantId })).filter((s) => s.vertical === vertical && s.status === 'active' && isPrimaryScope(s));
96
104
  if (scopes.length === 0)
97
105
  return [];
98
106
  const running = await runningFactsOf(this.host.admin, this.actor, scopes, (slug, versionId) => this.input.read(slug, versionId), (reason) => ({ kind: 'unreadable', reason }), this.concurrency);