@substrat-run/control-plane-api 0.160.0 → 0.162.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 (46) hide show
  1. package/dist/api.d.ts +8 -0
  2. package/dist/api.d.ts.map +1 -1
  3. package/dist/api.js +142 -9
  4. package/dist/api.js.map +1 -1
  5. package/dist/cf-observability.d.ts.map +1 -1
  6. package/dist/cf-observability.js +31 -8
  7. package/dist/cf-observability.js.map +1 -1
  8. package/dist/index.d.ts +3 -2
  9. package/dist/index.d.ts.map +1 -1
  10. package/dist/index.js +3 -2
  11. package/dist/index.js.map +1 -1
  12. package/dist/observability.d.ts +6 -2
  13. package/dist/observability.d.ts.map +1 -1
  14. package/dist/observability.js +1 -1
  15. package/dist/observability.js.map +1 -1
  16. package/dist/platform-drain.d.ts +26 -2
  17. package/dist/platform-drain.d.ts.map +1 -1
  18. package/dist/platform-drain.js +203 -88
  19. package/dist/platform-drain.js.map +1 -1
  20. package/dist/platform-wire.d.ts +2 -1
  21. package/dist/platform-wire.d.ts.map +1 -1
  22. package/dist/platform-wire.js +23 -3
  23. package/dist/platform-wire.js.map +1 -1
  24. package/dist/scope-copy-cleanup.js +1 -1
  25. package/dist/scope-copy-cleanup.js.map +1 -1
  26. package/dist/vertical-client.d.ts +58 -2
  27. package/dist/vertical-client.d.ts.map +1 -1
  28. package/dist/vertical-client.js +224 -21
  29. package/dist/vertical-client.js.map +1 -1
  30. package/dist/wire-readiness.d.ts +149 -0
  31. package/dist/wire-readiness.d.ts.map +1 -0
  32. package/dist/wire-readiness.js +250 -0
  33. package/dist/wire-readiness.js.map +1 -0
  34. package/dist/wire-settings.d.ts +77 -0
  35. package/dist/wire-settings.d.ts.map +1 -0
  36. package/dist/wire-settings.js +155 -0
  37. package/dist/wire-settings.js.map +1 -0
  38. package/dist/wire-upload.d.ts +26 -0
  39. package/dist/wire-upload.d.ts.map +1 -1
  40. package/dist/wire-upload.js +29 -2
  41. package/dist/wire-upload.js.map +1 -1
  42. package/dist/wire-walk.d.ts +161 -0
  43. package/dist/wire-walk.d.ts.map +1 -0
  44. package/dist/wire-walk.js +345 -0
  45. package/dist/wire-walk.js.map +1 -0
  46. package/package.json +8 -8
@@ -0,0 +1,149 @@
1
+ /**
2
+ * The readiness report (RFC wire-signing §7, follow-on 4): what the fleet's capability records say
3
+ * about each rollout step, and what still blocks it. Three gates, each a list of blockers:
4
+ *
5
+ * - **`signed-only`**: what blocks moving an environment's down-channel from `dual` to `signed-only`.
6
+ * - **key drop**: what blocks dropping a public key from an issuer's list.
7
+ * - **credential withdrawal**: what blocks withdrawing the shared credential (step 7).
8
+ *
9
+ * It is **advisory**: it informs the person who flips a setting or drops a key, and nothing in the
10
+ * tooling enforces it yet (follow-on 7). It is **read-only** by construction: it reads the registry,
11
+ * the capability records and the fleet walk's admin rows, and calls nothing else. It never reads a
12
+ * script, never walks, and writes nothing; the record reads it makes leave their own access-log rows.
13
+ *
14
+ * **Unknown is never read as fact.** A script with no record, a record the walk holds (`walkHold`),
15
+ * and a record the walk could not verify (`withheld: 'unverified'`) are listed as unknown, and every
16
+ * gate treats unknown as blocking. A record is trusted as current only when it was written after the
17
+ * last confirming walk began (`wireConfirmation`); when that walk cannot be found whole in the admin
18
+ * log, confirmation is unknown, and every gate that needs it is blocked.
19
+ *
20
+ * Every reason is a fixed sentence, naming at most a setting or a vertical; never a key, a key id or
21
+ * a tenant.
22
+ */
23
+ import { type AdminLogEntry, type PlatformActorId, type WireAuthRecord } from '@substrat-run/contracts';
24
+ import type { HostAdmin } from '@substrat-run/kernel';
25
+ import { type WireUploadSettings } from './wire-upload.js';
26
+ import { type WireWalkCursor } from './wire-walk.js';
27
+ /** A report page covers this many scripts when it names no limit. */
28
+ export declare const WIRE_READINESS_LIMIT_DEFAULT = 25;
29
+ /** A report page covers at most this many scripts. */
30
+ export declare const WIRE_READINESS_LIMIT_MAX = 50;
31
+ /** The most walk rows the report reads to find the last confirming walk; a walk longer than that is unknown. */
32
+ export declare const WIRE_CONFIRM_ROWS_MAX = 200;
33
+ /** What every report says first. */
34
+ export declare const WIRE_READINESS_ADVISORY = "advisory: this report informs the person who flips the down-channel, drops a key or withdraws the shared credential; no tooling enforces it yet (follow-on 7)";
35
+ /** What every report says second: when its answer holds. */
36
+ export declare const WIRE_READINESS_AS_OF = "the answer is as of each record\u2019s recorded time, not live: run the confirming pass immediately before any flip or drop, and run the report after it";
37
+ export type WireGate = 'signed-only' | 'key-drop' | 'credential-withdrawal';
38
+ /** One thing that blocks a gate. */
39
+ export interface WireBlocker {
40
+ /**
41
+ * `standing`: by design, until a later step answers it. `settings`: the control plane's own wire
42
+ * settings. `confirmation`: the last confirming walk. `script`: one script, named.
43
+ */
44
+ readonly kind: 'standing' | 'settings' | 'confirmation' | 'script';
45
+ readonly deploymentRef?: string;
46
+ readonly vertical?: string;
47
+ readonly reason: string;
48
+ }
49
+ /** What the last confirming walk proves: when it began, or why it proves nothing. */
50
+ export type WireConfirmation = {
51
+ readonly status: 'confirmed';
52
+ readonly startedAt: string;
53
+ readonly passes: number;
54
+ } | {
55
+ readonly status: 'unknown';
56
+ readonly reason: string;
57
+ };
58
+ /** One script, as the records say. */
59
+ export interface WireReadinessScript {
60
+ readonly deploymentRef: string;
61
+ readonly vertical: string;
62
+ readonly versionId: string | null;
63
+ readonly kind: 'serving' | 'version';
64
+ /**
65
+ * `unknown`: no record, held by the walk, or unverified by it. `verifies`: its record says it carries
66
+ * the platform's entry and was given lists. `not-verifying`: its record says it verifies nothing
67
+ * (no entry, or no lists).
68
+ */
69
+ readonly status: 'unknown' | 'verifies' | 'not-verifying';
70
+ /** Its record's state, when it has a record. */
71
+ readonly state?: WireAuthRecord['state'];
72
+ /** Whether its record was written after the last confirming walk began; `null` when that is unknown. */
73
+ readonly confirmed: boolean | null;
74
+ }
75
+ /** The key a person asks to drop, and when the control plane's list stopped naming it. */
76
+ export interface WireKeyDrop {
77
+ readonly issuer: 'router' | 'platform';
78
+ readonly kid: string;
79
+ readonly since: string;
80
+ }
81
+ export interface WireReadinessReport {
82
+ readonly advisory: string;
83
+ readonly asOf: string;
84
+ readonly from: string | null;
85
+ /** Where the next page starts, `null` at the end of the fleet. A gate is clear only when every page, from the start, shows it clear. */
86
+ readonly next: string | null;
87
+ readonly confirmation: WireConfirmation;
88
+ /** The key drop asked about, echoed: its issuer and `since`. */
89
+ readonly keyDrop?: {
90
+ readonly issuer: WireKeyDrop['issuer'];
91
+ readonly since: string;
92
+ };
93
+ readonly scripts: readonly WireReadinessScript[];
94
+ readonly blockers: {
95
+ readonly signedOnly: readonly WireBlocker[];
96
+ readonly keyDrop?: readonly WireBlocker[];
97
+ readonly credentialWithdrawal: readonly WireBlocker[];
98
+ };
99
+ }
100
+ /** The fixed sentences, in one place, so every copy reads the same. */
101
+ export declare const WIRE_READINESS_REASONS: {
102
+ readonly counters: 'the cutover counters (no legacy acceptance, no dual-mismatch, no fault, no refusal outside client noise) are not read by this report yet, nor is a version whose default export has no fetch, which only the counters show';
103
+ readonly notSignedOnly: 'no environment is signed-only: every upload and every walk gives dual';
104
+ readonly upChannel: 'the up-channel removals (step 6) are not recorded per version, so no version is shown to make no up-call with the shared credential';
105
+ readonly perDeployment: 'no version carries per-deployment values for its legacy checks (Q10), so a version never rebuilt still needs the shared credential';
106
+ readonly rolloutNotFleet: 'WIRE_KEYS_ROLLOUT is not fleet: not every deployment is given key lists';
107
+ readonly noRecord: 'it has no capability record, so what it carries is unknown';
108
+ readonly held: 'the fleet walk holds it, so its record states what was last known, not what it runs: look at it, then release it or push it again';
109
+ readonly unverified: 'the fleet walk found it with no record and could not verify it, so what it carries is unknown';
110
+ readonly noEntry: 'it was uploaded without the platform entry, so it verifies nothing: it is ready once pushed again';
111
+ readonly noLists: 'it was given no key lists, so it is legacy-only';
112
+ readonly stale: 'it does not carry the key lists, audience and state the control plane gives now: walk the fleet';
113
+ readonly noRouterStandby: 'its router key list holds no standby key beside the key in use';
114
+ readonly noPlatformStandby: 'its platform key list holds no standby key beside the key in use';
115
+ readonly unconfirmed: 'its record was written before the last confirming walk began, so it is not trusted as current';
116
+ readonly confirmationUnknown: 'the last confirming walk is unknown, so no record is trusted as current';
117
+ readonly confirmedBeforeSince: 'the last confirming walk began before the key left the list, so it does not show the key gone';
118
+ readonly stillListed: 'the control plane still lists the key';
119
+ readonly listWouldEmpty: 'the key is the only one its issuer lists';
120
+ readonly stillTrusted: 'it still trusts the key';
121
+ readonly lacksKeyInUse: 'it does not carry every key its issuer lists now';
122
+ };
123
+ /**
124
+ * What the last confirming walk proves, from the walk's admin rows, newest first (at most
125
+ * `WIRE_CONFIRM_ROWS_MAX`, plus one more to tell a full read from a cut one). Fails closed: confirmed
126
+ * only when the newest APPLIED pass is a confirming one that reached the end of the fleet, and the
127
+ * applied passes before it, one after another with no other applied pass between, are confirming ones
128
+ * chained back to the start of the fleet (each pass's `from` the `next` of the pass before), none of
129
+ * them refused or ended in an error, each with its start time. Anything else is `unknown`, with why:
130
+ * no such walk, a gap in the chain, a refused or failed pass in it, a row it cannot read, or a chain
131
+ * that runs past the rows read.
132
+ */
133
+ export declare function wireConfirmation(rows: readonly Pick<AdminLogEntry, 'after'>[]): WireConfirmation;
134
+ /** `since` as a person gives it: an instant, not in the future. A fixed sentence when it is not. */
135
+ export declare function wireKeyDropSince(since: unknown, now: Date): string | {
136
+ readonly refused: string;
137
+ };
138
+ /** One page of the report. Reads only; never throws for one script, only for a directory read that fails. */
139
+ export declare function wireReadinessReport(deps: {
140
+ readonly admin: HostAdmin;
141
+ readonly actor: PlatformActorId;
142
+ readonly settings: WireUploadSettings | undefined;
143
+ }, input: {
144
+ readonly cursor: WireWalkCursor | null;
145
+ readonly from: string | null;
146
+ readonly limit: number;
147
+ readonly keyDrop?: WireKeyDrop;
148
+ }): Promise<WireReadinessReport>;
149
+ //# sourceMappingURL=wire-readiness.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-readiness.d.ts","sourceRoot":"","sources":["../src/wire-readiness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,250 @@
1
+ /**
2
+ * The readiness report (RFC wire-signing §7, follow-on 4): what the fleet's capability records say
3
+ * about each rollout step, and what still blocks it. Three gates, each a list of blockers:
4
+ *
5
+ * - **`signed-only`**: what blocks moving an environment's down-channel from `dual` to `signed-only`.
6
+ * - **key drop**: what blocks dropping a public key from an issuer's list.
7
+ * - **credential withdrawal**: what blocks withdrawing the shared credential (step 7).
8
+ *
9
+ * It is **advisory**: it informs the person who flips a setting or drops a key, and nothing in the
10
+ * tooling enforces it yet (follow-on 7). It is **read-only** by construction: it reads the registry,
11
+ * the capability records and the fleet walk's admin rows, and calls nothing else. It never reads a
12
+ * script, never walks, and writes nothing; the record reads it makes leave their own access-log rows.
13
+ *
14
+ * **Unknown is never read as fact.** A script with no record, a record the walk holds (`walkHold`),
15
+ * and a record the walk could not verify (`withheld: 'unverified'`) are listed as unknown, and every
16
+ * gate treats unknown as blocking. A record is trusted as current only when it was written after the
17
+ * last confirming walk began (`wireConfirmation`); when that walk cannot be found whole in the admin
18
+ * log, confirmation is unknown, and every gate that needs it is blocked.
19
+ *
20
+ * Every reason is a fixed sentence, naming at most a setting or a vertical; never a key, a key id or
21
+ * a tenant.
22
+ */
23
+ import { instant, z } from '@substrat-run/contracts';
24
+ import { wireUploadSettings, WIRE_UNSIGNED_ROUTES } from '@substrat-run/contracts/wire-signing';
25
+ import { wireSettingsRefusal, wireKeysRolloutOf, wireUploadGiven } from './wire-upload.js';
26
+ import { carriesAlready, wireAuthRecordsOf, wireInventory, wireInventoryPass } from './wire-walk.js';
27
+ /** A report page covers this many scripts when it names no limit. */
28
+ export const WIRE_READINESS_LIMIT_DEFAULT = 25;
29
+ /** A report page covers at most this many scripts. */
30
+ export const WIRE_READINESS_LIMIT_MAX = 50;
31
+ /** The most walk rows the report reads to find the last confirming walk; a walk longer than that is unknown. */
32
+ export const WIRE_CONFIRM_ROWS_MAX = 200;
33
+ /** What every report says first. */
34
+ export const WIRE_READINESS_ADVISORY = 'advisory: this report informs the person who flips the down-channel, drops a key or withdraws the shared credential; no tooling enforces it yet (follow-on 7)';
35
+ /** What every report says second: when its answer holds. */
36
+ export const WIRE_READINESS_AS_OF = 'the answer is as of each record’s recorded time, not live: run the confirming pass immediately before any flip or drop, and run the report after it';
37
+ /** The fixed sentences, in one place, so every copy reads the same. */
38
+ export const WIRE_READINESS_REASONS = {
39
+ counters: 'the cutover counters (no legacy acceptance, no dual-mismatch, no fault, no refusal outside client noise) are not read by this report yet, nor is a version whose default export has no fetch, which only the counters show',
40
+ notSignedOnly: 'no environment is signed-only: every upload and every walk gives dual',
41
+ upChannel: 'the up-channel removals (step 6) are not recorded per version, so no version is shown to make no up-call with the shared credential',
42
+ perDeployment: 'no version carries per-deployment values for its legacy checks (Q10), so a version never rebuilt still needs the shared credential',
43
+ rolloutNotFleet: 'WIRE_KEYS_ROLLOUT is not fleet: not every deployment is given key lists',
44
+ noRecord: 'it has no capability record, so what it carries is unknown',
45
+ held: 'the fleet walk holds it, so its record states what was last known, not what it runs: look at it, then release it or push it again',
46
+ unverified: 'the fleet walk found it with no record and could not verify it, so what it carries is unknown',
47
+ noEntry: 'it was uploaded without the platform entry, so it verifies nothing: it is ready once pushed again',
48
+ noLists: 'it was given no key lists, so it is legacy-only',
49
+ stale: 'it does not carry the key lists, audience and state the control plane gives now: walk the fleet',
50
+ noRouterStandby: 'its router key list holds no standby key beside the key in use',
51
+ noPlatformStandby: 'its platform key list holds no standby key beside the key in use',
52
+ unconfirmed: 'its record was written before the last confirming walk began, so it is not trusted as current',
53
+ confirmationUnknown: 'the last confirming walk is unknown, so no record is trusted as current',
54
+ confirmedBeforeSince: 'the last confirming walk began before the key left the list, so it does not show the key gone',
55
+ stillListed: 'the control plane still lists the key',
56
+ listWouldEmpty: 'the key is the only one its issuer lists',
57
+ stillTrusted: 'it still trusts the key',
58
+ lacksKeyInUse: 'it does not carry every key its issuer lists now',
59
+ };
60
+ const R = WIRE_READINESS_REASONS;
61
+ /** The walk row's fields the report reads; any other shape is a row it cannot read. */
62
+ const walkRow = z.object({
63
+ apply: z.boolean(),
64
+ confirm: z.boolean(),
65
+ startedAt: instant.optional(),
66
+ from: z.string().nullable(),
67
+ next: z.string().nullable(),
68
+ error: z.string().optional(),
69
+ refused: z.string().optional(),
70
+ });
71
+ /**
72
+ * What the last confirming walk proves, from the walk's admin rows, newest first (at most
73
+ * `WIRE_CONFIRM_ROWS_MAX`, plus one more to tell a full read from a cut one). Fails closed: confirmed
74
+ * only when the newest APPLIED pass is a confirming one that reached the end of the fleet, and the
75
+ * applied passes before it, one after another with no other applied pass between, are confirming ones
76
+ * chained back to the start of the fleet (each pass's `from` the `next` of the pass before), none of
77
+ * them refused or ended in an error, each with its start time. Anything else is `unknown`, with why:
78
+ * no such walk, a gap in the chain, a refused or failed pass in it, a row it cannot read, or a chain
79
+ * that runs past the rows read.
80
+ */
81
+ export function wireConfirmation(rows) {
82
+ const unknown = (reason) => ({ status: 'unknown', reason });
83
+ const read = rows.slice(0, WIRE_CONFIRM_ROWS_MAX);
84
+ const parsed = [];
85
+ for (const row of read) {
86
+ const p = walkRow.safeParse(row.after);
87
+ if (!p.success)
88
+ return unknown('a fleet walk row could not be read');
89
+ parsed.push(p.data);
90
+ }
91
+ const applied = parsed.filter((p) => p.apply);
92
+ if (applied.length === 0) {
93
+ return unknown(rows.length > read.length ? 'no applied walk is among the rows read' : 'no applied confirming walk is recorded');
94
+ }
95
+ let expected = null;
96
+ for (let i = 0; i < applied.length; i++) {
97
+ const p = applied[i];
98
+ if (!p.confirm) {
99
+ return unknown(i === 0 ? 'the last applied walk was not a confirming one' : 'an applied walk that was not confirming ran inside the last confirming walk');
100
+ }
101
+ if (p.refused !== undefined || p.error !== undefined)
102
+ return unknown('a pass of the last confirming walk was refused or ended in an error');
103
+ if (p.next !== expected)
104
+ return unknown(i === 0 ? 'the last confirming walk did not reach the end of the fleet' : 'the last confirming walk has a gap between its passes');
105
+ if (p.startedAt === undefined)
106
+ return unknown('a pass of the last confirming walk does not record when it began');
107
+ if (p.from === null)
108
+ return { status: 'confirmed', startedAt: p.startedAt, passes: i + 1 };
109
+ expected = p.from;
110
+ }
111
+ return unknown(rows.length > read.length ? 'the last confirming walk runs past the rows read' : 'the last confirming walk does not reach back to the start of the fleet');
112
+ }
113
+ /** `since` as a person gives it: an instant, not in the future. A fixed sentence when it is not. */
114
+ export function wireKeyDropSince(since, now) {
115
+ if (since === undefined || since === null || since === '')
116
+ return { refused: 'a key drop names since: when the control plane’s list stopped naming the key' };
117
+ const parsed = instant.safeParse(since);
118
+ if (!parsed.success)
119
+ return { refused: 'since is an ISO 8601 instant' };
120
+ if (Date.parse(parsed.data) > now.getTime())
121
+ return { refused: 'since is not in the future' };
122
+ return parsed.data;
123
+ }
124
+ /** The key ids each issuer's list names now, or `null` when the lists do not load. */
125
+ async function listedKids(settings) {
126
+ try {
127
+ const given = await wireUploadSettings({ routerKeys: settings?.routerKeys ?? '', platformKeys: settings?.platformKeys ?? '', audience: 'wire-settings-check' });
128
+ return { router: given.routerKids, platform: given.platformKids };
129
+ }
130
+ catch {
131
+ return null;
132
+ }
133
+ }
134
+ const unknownReason = (record) => !record ? R.noRecord : record.record.walkHold !== undefined ? R.held : record.record.withheld === 'unverified' ? R.unverified : null;
135
+ /** One page of the report. Reads only; never throws for one script, only for a directory read that fails. */
136
+ export async function wireReadinessReport(deps, input) {
137
+ const { admin, actor, settings } = deps;
138
+ const rows = await admin.auditLog(actor, { action: 'walkWireAuth', order: 'desc', limit: WIRE_CONFIRM_ROWS_MAX + 1 });
139
+ const confirmation = wireConfirmation(rows);
140
+ const refused = await wireSettingsRefusal(settings);
141
+ const rollout = wireKeysRolloutOf(settings?.rollout);
142
+ const kids = await listedKids(settings);
143
+ const signedOnly = [
144
+ ...WIRE_UNSIGNED_ROUTES.map((r) => ({ kind: 'standing', reason: `${r.method} ${r.path}: ${r.reason}` })),
145
+ { kind: 'standing', reason: R.counters },
146
+ ];
147
+ const drop = input.keyDrop ? [] : undefined;
148
+ const settingsBlocker = refused ? { kind: 'settings', reason: `the control plane’s wire settings are refused (${refused.withheld}): ${refused.reason}` } : null;
149
+ if (settingsBlocker) {
150
+ signedOnly.push(settingsBlocker);
151
+ drop?.push(settingsBlocker);
152
+ }
153
+ else if ('refused' in rollout || rollout.kind !== 'fleet') {
154
+ // Only while the settings are usable: a refusal hides the rollout state, and is the fix to make first.
155
+ signedOnly.push({ kind: 'settings', reason: R.rolloutNotFleet });
156
+ }
157
+ if (confirmation.status === 'unknown') {
158
+ const blocker = { kind: 'confirmation', reason: `${R.confirmationUnknown}: ${confirmation.reason}` };
159
+ signedOnly.push(blocker);
160
+ drop?.push(blocker);
161
+ }
162
+ const keyDrop = input.keyDrop;
163
+ if (keyDrop && drop) {
164
+ const listed = kids?.[keyDrop.issuer] ?? null;
165
+ if (listed === null) {
166
+ if (!settingsBlocker)
167
+ drop.push({ kind: 'settings', reason: 'the control plane’s key lists do not load' });
168
+ }
169
+ else {
170
+ if (listed.includes(keyDrop.kid))
171
+ drop.push({ kind: 'settings', reason: R.stillListed });
172
+ if (listed.every((k) => k === keyDrop.kid))
173
+ drop.push({ kind: 'settings', reason: R.listWouldEmpty });
174
+ }
175
+ if (confirmation.status === 'confirmed' && Date.parse(confirmation.startedAt) < Date.parse(keyDrop.since)) {
176
+ drop.push({ kind: 'confirmation', reason: R.confirmedBeforeSince });
177
+ }
178
+ }
179
+ let records = null;
180
+ const recordOf = async (script) => {
181
+ if (records?.vertical !== script.vertical)
182
+ records = { vertical: script.vertical, held: await wireAuthRecordsOf(admin, actor, script.vertical) };
183
+ return records.held.get(script.deploymentRef);
184
+ };
185
+ const judge = async (script) => {
186
+ const stored = await recordOf(script);
187
+ const named = (reason) => ({ kind: 'script', deploymentRef: script.deploymentRef, vertical: script.vertical, reason });
188
+ const base = { deploymentRef: script.deploymentRef, vertical: script.vertical, versionId: script.versionId, kind: script.kind };
189
+ const unknown = unknownReason(stored);
190
+ if (unknown !== null || !stored) {
191
+ const blocker = named(unknown ?? R.noRecord);
192
+ signedOnly.push(blocker);
193
+ drop?.push(blocker);
194
+ return { ...base, status: 'unknown', ...(stored ? { state: stored.record.state } : {}), confirmed: null };
195
+ }
196
+ const record = stored.record;
197
+ const confirmed = confirmation.status === 'confirmed' ? Date.parse(stored.recordedAt) >= Date.parse(confirmation.startedAt) : null;
198
+ const verifies = record.envelope !== null && record.withheld === null;
199
+ if (record.envelope === null) {
200
+ signedOnly.push(named(R.noEntry));
201
+ }
202
+ else if (record.withheld !== null) {
203
+ signedOnly.push(named(`${R.noLists} (${record.withheld})`));
204
+ }
205
+ const given = await wireUploadGiven(settings, { vertical: script.vertical, deploymentRef: script.deploymentRef, entry: { envelope: record.envelope, entrySkipped: record.entrySkipped } });
206
+ if (verifies) {
207
+ if (!carriesAlready(record, given.record))
208
+ signedOnly.push(named(R.stale));
209
+ if (record.routerKids.length < 2)
210
+ signedOnly.push(named(R.noRouterStandby));
211
+ if (record.platformKids.length < 2)
212
+ signedOnly.push(named(R.noPlatformStandby));
213
+ }
214
+ if (confirmed === false) {
215
+ signedOnly.push(named(R.unconfirmed));
216
+ drop?.push(named(R.unconfirmed));
217
+ }
218
+ if (keyDrop && drop) {
219
+ const trusted = keyDrop.issuer === 'router' ? record.routerKids : record.platformKids;
220
+ if (trusted.includes(keyDrop.kid))
221
+ drop.push(named(R.stillTrusted));
222
+ const listed = kids?.[keyDrop.issuer];
223
+ if (trusted.length > 0 && listed && listed.some((k) => k !== keyDrop.kid && !trusted.includes(k)))
224
+ drop.push(named(R.lacksKeyInUse));
225
+ }
226
+ return { ...base, status: verifies ? 'verifies' : 'not-verifying', state: record.state, confirmed };
227
+ };
228
+ const scripts = [];
229
+ const next = await wireInventoryPass(wireInventory(admin, actor, input.cursor), input.limit, judge, scripts);
230
+ // Everything that blocks signed-only but its standing blockers blocks the withdrawal too: a script
231
+ // that does not carry and verify signed calls still needs the shared credential. Signed-only's
232
+ // standing blockers are covered by the withdrawal's own first one (no environment is signed-only).
233
+ const withdrawal = [
234
+ { kind: 'standing', reason: R.notSignedOnly },
235
+ { kind: 'standing', reason: R.upChannel },
236
+ { kind: 'standing', reason: R.perDeployment },
237
+ ...signedOnly.filter((b) => b.kind !== 'standing'),
238
+ ];
239
+ return {
240
+ advisory: WIRE_READINESS_ADVISORY,
241
+ asOf: WIRE_READINESS_AS_OF,
242
+ from: input.from,
243
+ next,
244
+ confirmation,
245
+ ...(keyDrop ? { keyDrop: { issuer: keyDrop.issuer, since: keyDrop.since } } : {}),
246
+ scripts,
247
+ blockers: { signedOnly, ...(drop ? { keyDrop: drop } : {}), credentialWithdrawal: withdrawal },
248
+ };
249
+ }
250
+ //# sourceMappingURL=wire-readiness.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-readiness.js","sourceRoot":"","sources":["../src/wire-readiness.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /** Binding types whose values the endpoint never returns: carried by `keep_bindings`, never sent. */
2
+ export declare const SECRET_BINDING_TYPES: readonly string[];
3
+ /** The version a script runs, as its upload injected it (#1242). */
4
+ export declare const VERSION_ID_VAR = "SUBSTRAT_VERSION_ID";
5
+ /** How many times a change between the two reads is retried from the newer read. */
6
+ export declare const CONCURRENT_RETRIES = 3;
7
+ /** One binding as the settings endpoint answers it. */
8
+ export interface ScriptBinding {
9
+ readonly type: string;
10
+ readonly name: string;
11
+ readonly [field: string]: unknown;
12
+ }
13
+ /** The namespace's script-settings endpoint: read a script's bindings, write them back. */
14
+ export interface WireSettingsApi {
15
+ read(script: string): Promise<readonly ScriptBinding[]>;
16
+ write(script: string, body: {
17
+ readonly bindings: readonly ScriptBinding[];
18
+ readonly keep_bindings: readonly string[];
19
+ }): Promise<void>;
20
+ }
21
+ /** What a desired state is: the four settings with their text, or none of them (withdrawn). */
22
+ export type WireSettingsWanted = readonly {
23
+ readonly name: string;
24
+ readonly text: string;
25
+ }[];
26
+ export type WireSettingsOutcome =
27
+ /** The four already match: nothing was written. */
28
+ {
29
+ readonly outcome: 'unchanged';
30
+ }
31
+ /** A dry run: what would change, by name. Nothing was written. */
32
+ | {
33
+ readonly outcome: 'would-change';
34
+ readonly changes: readonly string[];
35
+ }
36
+ /** Written and verified. */
37
+ | {
38
+ readonly outcome: 'updated';
39
+ readonly changes: readonly string[];
40
+ }
41
+ /** The bindings kept changing between the two reads: nothing was written. */
42
+ | {
43
+ readonly outcome: 'concurrent-change';
44
+ }
45
+ /** A serving script whose version is not the one served: nothing was written, or the serve moved after it was. */
46
+ | {
47
+ readonly outcome: 'serve-in-flight';
48
+ readonly written: boolean;
49
+ }
50
+ /** Written, but the read after it differs, in these binding names. */
51
+ | {
52
+ readonly outcome: 'verify';
53
+ readonly bindings: readonly string[];
54
+ };
55
+ /** The names among the four whose value (or presence, or type) differs from what is wanted. */
56
+ export declare function wireSettingsChanges(bindings: readonly ScriptBinding[], wanted: WireSettingsWanted): string[];
57
+ /**
58
+ * Bring `script`'s four settings to `wanted` (all four, or none to withdraw them). With `apply`
59
+ * false it only reads: the write is unreachable. With `servedVersion`, the script is a serving
60
+ * script and that is the version the directory says it serves; `servedVersionAfter` reads the
61
+ * directory again after the write.
62
+ */
63
+ export declare function applyWireSettings(api: WireSettingsApi, script: string, wanted: WireSettingsWanted, opts: {
64
+ readonly apply: boolean;
65
+ readonly servedVersion?: string;
66
+ readonly servedVersionAfter?: () => Promise<string | null>;
67
+ }): Promise<WireSettingsOutcome>;
68
+ /**
69
+ * The `WireSettingsApi` over the namespace's script-settings endpoint. A failure names the script and
70
+ * the status only, never a response body: the body of a settings answer holds binding values.
71
+ */
72
+ export declare function createWfpWireSettingsApi(opts: {
73
+ readonly accountId: string;
74
+ readonly namespace: string;
75
+ readonly apiToken: string;
76
+ }): WireSettingsApi;
77
+ //# sourceMappingURL=wire-settings.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"wire-settings.d.ts","sourceRoot":"","sources":["../src/wire-settings.ts"],"names":[],"mappings":"AAwBA,qGAAqG;AACrG,eAAO,MAAM,oBAAoB,EAAE,SAAS,MAAM,EAAiD,CAAC;AAGpG,oEAAoE;AACpE,eAAO,MAAM,cAAc,wBAAwB,CAAC;AAEpD,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,IAAI,CAAC;AAEpC,uDAAuD;AACvD,MAAM,WAAW,aAAa;IAC5B,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,QAAQ,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC;CACnC;AAED,2FAA2F;AAC3F,MAAM,WAAW,eAAe;IAC9B,IAAI,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,SAAS,aAAa,EAAE,CAAC,CAAC;IACxD,KAAK,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE;QAAE,QAAQ,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,CAAC;QAAC,QAAQ,CAAC,aAAa,EAAE,SAAS,MAAM,EAAE,CAAA;KAAE,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxI;AAED,+FAA+F;AAC/F,MAAM,MAAM,kBAAkB,GAAG,SAAS;IAAE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAA;CAAE,EAAE,CAAC;AAE7F,MAAM,MAAM,mBAAmB;AAC7B,mDAAmD;AACjD;IAAE,QAAQ,CAAC,OAAO,EAAE,WAAW,CAAA;CAAE;AACnC,kEAAkE;GAChE;IAAE,QAAQ,CAAC,OAAO,EAAE,cAAc,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AAC3E,4BAA4B;GAC1B;IAAE,QAAQ,CAAC,OAAO,EAAE,SAAS,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE;AACtE,6EAA6E;GAC3E;IAAE,QAAQ,CAAC,OAAO,EAAE,mBAAmB,CAAA;CAAE;AAC3C,kHAAkH;GAChH;IAAE,QAAQ,CAAC,OAAO,EAAE,iBAAiB,CAAC;IAAC,QAAQ,CAAC,OAAO,EAAE,OAAO,CAAA;CAAE;AACpE,sEAAsE;GACpE;IAAE,QAAQ,CAAC,OAAO,EAAE,QAAQ,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,SAAS,MAAM,EAAE,CAAA;CAAE,CAAC;AAWzE,+FAA+F;AAC/F,wBAAgB,mBAAmB,CAAC,QAAQ,EAAE,SAAS,aAAa,EAAE,EAAE,MAAM,EAAE,kBAAkB,GAAG,MAAM,EAAE,CAS5G;AAmCD;;;;;GAKG;AACH,wBAAsB,iBAAiB,CACrC,GAAG,EAAE,eAAe,EACpB,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,kBAAkB,EAC1B,IAAI,EAAE;IAAE,QAAQ,CAAC,KAAK,EAAE,OAAO,CAAC;IAAC,QAAQ,CAAC,aAAa,CAAC,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,kBAAkB,CAAC,EAAE,MAAM,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC,CAAA;CAAE,GAC7H,OAAO,CAAC,mBAAmB,CAAC,CA4B9B;AAED;;;GAGG;AACH,wBAAgB,wBAAwB,CAAC,IAAI,EAAE;IAAE,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;IAAC,QAAQ,CAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAAG,eAAe,CA2BrJ"}