@substrat-run/control-plane-api 0.151.0 → 0.153.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.
@@ -35,7 +35,10 @@ export interface CustomHostnameIssuance {
35
35
  records: DnsRecord[];
36
36
  }
37
37
  export interface CustomHostnameProvisioner {
38
- /** Register a custom hostname for issuance. Idempotent on Cloudflare's side per name. */
38
+ /**
39
+ * Register a custom hostname for issuance. Idempotent per name: when the zone already
40
+ * holds one, that object is adopted and its current state returned.
41
+ */
39
42
  create(hostname: string): Promise<CustomHostnameIssuance>;
40
43
  /** Poll a registered custom hostname's validation + certificate state. */
41
44
  check(customHostnameId: string): Promise<CustomHostnameIssuance>;
@@ -1 +1 @@
1
- {"version":3,"file":"custom-hostnames.d.ts","sourceRoot":"","sources":["../src/custom-hostnames.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"custom-hostnames.d.ts","sourceRoot":"","sources":["../src/custom-hostnames.ts"],"names":[],"mappings":"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"}
@@ -112,16 +112,39 @@ export function createCustomHostnameProvisioner(opts) {
112
112
  }
113
113
  return env.result;
114
114
  };
115
+ /**
116
+ * The zone's custom hostname for exactly `name`, or null. Cloudflare's `hostname` filter
117
+ * is an exact match, but the result is compared again so a looser upstream filter can
118
+ * never hand back a neighbour's object.
119
+ */
120
+ const findByName = async (name) => {
121
+ const res = await fetchFn(`${base}?hostname=${encodeURIComponent(name)}`, { headers: auth });
122
+ if (!res.ok)
123
+ return null;
124
+ const env = (await res.json().catch(() => undefined));
125
+ return env?.result?.find((ch) => ch.hostname.toLowerCase() === name) ?? null;
126
+ };
115
127
  return {
116
128
  async create(hostname) {
129
+ const name = hostname.toLowerCase();
117
130
  const res = await fetchFn(base, {
118
131
  method: 'POST',
119
132
  headers: { ...auth, 'content-type': 'application/json' },
120
133
  body: JSON.stringify({
121
- hostname: hostname.toLowerCase(),
134
+ hostname: name,
122
135
  ssl: { method: opts.sslMethod ?? 'txt', type: 'dv', settings: { min_tls_version: '1.2' } },
123
136
  }),
124
137
  });
138
+ // 409: the zone already holds this name. The object is ours — the SaaS zone is the
139
+ // control plane's own, and a binding row is unique per hostname, so nothing else
140
+ // can be counting on it — most often left behind by an unbind whose best-effort
141
+ // delete failed. Adopt it rather than fail: refusing would strand the row `failed`
142
+ // with no id, and every "Check again" and every sweep would POST into the same 409.
143
+ if (res.status === 409) {
144
+ const existing = await findByName(name);
145
+ if (existing)
146
+ return toIssuance(existing);
147
+ }
125
148
  return toIssuance(await readEnvelope(res, 'custom-hostname create'));
126
149
  },
127
150
  async check(customHostnameId) {
@@ -166,8 +189,8 @@ const DEAD_SCOPE_STATUSES = ['archiving', 'archived', 'reaped'];
166
189
  */
167
190
  export async function reconcilePendingHostnames(deps) {
168
191
  const out = { polled: 0, activated: 0, failed: 0, created: 0, healed: 0, orphaned: 0, errors: [] };
169
- // Fork scopes stay `active` until deleted (and their delete removes their rows), so
170
- // this set is exactly the retired primaries — never a live preview's hostname.
192
+ // A live fork is `active`; a preview's reap archives it only after unrouting it (#1704),
193
+ // and its delete removes its rows, so this set never holds a live preview's hostname.
171
194
  // `archived` is restorable (unarchiveScope), and unbinding here is still deliberate:
172
195
  // delete-app already unbinds at delete time, so a bound row on an archived scope is a
173
196
  // relic; a staff rescue that unarchives re-binds hostnames as part of the restore,
@@ -1 +1 @@
1
- {"version":3,"file":"custom-hostnames.js","sourceRoot":"","sources":["../src/custom-hostnames.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"custom-hostnames.js","sourceRoot":"","sources":["../src/custom-hostnames.ts"],"names":[],"mappings":"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"}
@@ -22,6 +22,6 @@ export declare const PLATFORM_ENTRY_ALS_FALLBACK = "const AsyncLocalStorage = un
22
22
  * re-exports its class, when a vertical declares schedules and brings no sweeper of its own.
23
23
  */
24
24
  export declare const PLATFORM_SWEEPER_MODULE = "substrat-platform-sweeper.js";
25
- /** The sweeper itself — 9754 bytes of ESM. */
25
+ /** The sweeper itself — 10096 bytes of ESM. */
26
26
  export declare const PLATFORM_SWEEPER_SOURCE: string;
27
27
  //# sourceMappingURL=platform-entry.generated.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform-entry.generated.d.ts","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAElE,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,gCAAgC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB,EAAE,MAAu2sB,CAAC;AAE54sB;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,4DAA4D,CAAC;AACnG,eAAO,MAAM,2BAA2B,yCAAyC,CAAC;AAElF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE,8CAA8C;AAC9C,eAAO,MAAM,uBAAuB,EAAE,MAA60T,CAAC"}
1
+ {"version":3,"file":"platform-entry.generated.d.ts","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAGA;;;;;GAKG;AACH,eAAO,MAAM,qBAAqB,+BAA+B,CAAC;AAElE,gFAAgF;AAChF,eAAO,MAAM,0BAA0B,gCAAgC,CAAC;AAExE,6CAA6C;AAC7C,eAAO,MAAM,qBAAqB,EAAE,MAAu2sB,CAAC;AAE54sB;;;;;GAKG;AACH,eAAO,MAAM,yBAAyB,4DAA4D,CAAC;AACnG,eAAO,MAAM,2BAA2B,yCAAyC,CAAC;AAElF;;;GAGG;AACH,eAAO,MAAM,uBAAuB,iCAAiC,CAAC;AAEtE,+CAA+C;AAC/C,eAAO,MAAM,uBAAuB,EAAE,MAA0qU,CAAC"}
@@ -24,6 +24,6 @@ export const PLATFORM_ENTRY_ALS_FALLBACK = "const AsyncLocalStorage = undefined;
24
24
  * re-exports its class, when a vertical declares schedules and brings no sweeper of its own.
25
25
  */
26
26
  export const PLATFORM_SWEEPER_MODULE = 'substrat-platform-sweeper.js';
27
- /** The sweeper itself — 9754 bytes of ESM. */
28
- export const PLATFORM_SWEEPER_SOURCE = "// packages/adapter-cloudflare/src/scope-sweeper-do.ts\nimport { DurableObject } from \"cloudflare:workers\";\nvar SWEEPER_ID = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nfunction parseId(value, what) {\n if (typeof value !== \"string\" || !SWEEPER_ID.test(value)) {\n throw new TypeError(`${what} must be a ULID, got ${JSON.stringify(value)}`);\n }\n return value;\n}\nvar ROSTER_PREFIX = \"scope:\";\nvar JOB_START_PREFIX = \"job-start:\";\nfunction defineScopeSweeperDO(config) {\n return class ScopeSweeperDO extends DurableObject {\n /** The in-flight pass, when one is running — the overlap guard. */\n #pass = null;\n async noteScope(tenantId, scopeId) {\n const t = parseId(tenantId, \"tenantId\");\n const s = parseId(scopeId, \"scopeId\");\n await this.ctx.storage.put(`${ROSTER_PREFIX}${s}`, t);\n await this.ensureArmed();\n return { scopes: await this.#rosterSize() };\n }\n async forgetScope(scopeId) {\n const s = parseId(scopeId, \"scopeId\");\n await this.ctx.storage.delete([`${ROSTER_PREFIX}${s}`, `${JOB_START_PREFIX}${s}`]);\n return { scopes: await this.#rosterSize() };\n }\n /**\n * Arm the loop if it is not armed. Idempotent: an already-set alarm is left\n * exactly where it is, so this is safe to call on every request.\n */\n async ensureArmed() {\n const existing = await this.ctx.storage.getAlarm();\n if (existing !== null) return { armed: false, alarmAt: existing };\n const alarmAt = Date.now() + config.intervalMs;\n await this.ctx.storage.setAlarm(alarmAt);\n return { armed: true, alarmAt };\n }\n /**\n * Run a pass NOW (a manual kick, a just-provisioned scope's first tick, a\n * test). Joins the in-flight pass if one is running — never a second one —\n * and re-arms afterwards while scopes remain.\n */\n async sweepNow() {\n return this.#run();\n }\n /** The loop: one pass, then re-arm. Never throws (see the class doc). */\n async alarm() {\n await this.#run();\n }\n async #rosterSize() {\n return (await this.ctx.storage.list({ prefix: ROSTER_PREFIX })).size;\n }\n async #run() {\n if (this.#pass) return this.#pass;\n this.#pass = (async () => {\n try {\n const report = await this.#sweep();\n config.onPass?.(report, this.env);\n return report;\n } catch (err) {\n const outcome = { error: err instanceof Error ? err.message : String(err) };\n config.onPass?.(outcome, this.env);\n return outcome;\n }\n })();\n try {\n return await this.#pass;\n } finally {\n this.#pass = null;\n if (await this.#rosterSize() > 0) {\n await this.ctx.storage.setAlarm(Date.now() + config.intervalMs);\n }\n }\n }\n /** One pass over the roster: drain + due schedules per scope, errors contained. */\n async #sweep() {\n const host = config.host(this.env);\n const roster = await this.ctx.storage.list({ prefix: ROSTER_PREFIX });\n const report = {\n scopes: roster.size,\n drainTotals: { attempted: 0, delivered: 0, retrying: 0, deadLettered: 0 },\n schedules: { scopes: 0, fired: 0, skipped: 0, failed: 0 },\n ...config.runJobs ? { jobs: { attempted: 0, advanced: 0, completed: 0, retrying: 0, failed: 0 } } : {},\n errors: []\n };\n const registrations = host.registeredSchedules().filter((r) => r.schedules.length > 0);\n const entries = [...roster].map(([key, tenant]) => ({\n scopeId: key.slice(ROSTER_PREFIX.length),\n tenantId: tenant\n }));\n const concurrency = config.concurrency ?? 8;\n let next = 0;\n const worker = async () => {\n while (next < entries.length) {\n const { tenantId, scopeId } = entries[next++];\n if (host.lifecycleHeld) {\n try {\n if (await host.lifecycleHeld(scopeId)) {\n report.held = (report.held ?? 0) + 1;\n continue;\n }\n } catch (err) {\n report.errors.push({ kind: \"lifecycle\", id: scopeId, error: message(err) });\n continue;\n }\n }\n if (config.drainRetries !== false) {\n try {\n const r = await host.drainDue(tenantId, scopeId);\n report.drainTotals.attempted += r.attempted;\n report.drainTotals.delivered += r.delivered;\n report.drainTotals.retrying += r.retrying;\n report.drainTotals.deadLettered += r.deadLettered;\n } catch (err) {\n report.errors.push({ kind: \"drain\", id: scopeId, error: message(err) });\n }\n }\n if (config.runJobs) {\n if (config.startJobs) {\n try {\n const key = `${JOB_START_PREFIX}${scopeId}`;\n const last = await this.ctx.storage.get(key);\n const now = Date.now();\n if (last === void 0 || now - last >= (config.jobStartIntervalMs ?? config.intervalMs)) {\n await config.startJobs(host, tenantId, scopeId);\n await this.ctx.storage.put(key, now);\n }\n } catch (err) {\n report.errors.push({ kind: \"job\", id: `${scopeId}:start`, error: message(err) });\n }\n }\n try {\n const r = await host.runDueJobs(tenantId, scopeId);\n const totals = report.jobs;\n totals.attempted += r.attempted;\n totals.advanced += r.advanced;\n totals.completed += r.completed;\n totals.retrying += r.retrying;\n totals.failed += r.failed;\n for (const error of r.errors) {\n report.errors.push({ kind: \"job\", id: `${scopeId}:${error.runId}`, error: error.error });\n }\n } catch (err) {\n report.errors.push({ kind: \"job\", id: scopeId, error: message(err) });\n }\n }\n let touched = false;\n const passAt = (/* @__PURE__ */ new Date()).toISOString();\n const passRuns = [];\n for (const reg of registrations) {\n try {\n const r = await host.runDueSchedules(reg.moduleId, tenantId, scopeId);\n if (r.fired > 0 || r.failed > 0) touched = true;\n report.schedules.fired += r.fired;\n report.schedules.skipped += r.skipped;\n report.schedules.failed += r.failed;\n for (const e of r.errors) {\n report.errors.push({\n kind: \"schedule\",\n id: `${scopeId}:${e.operation}`,\n error: e.error\n });\n }\n for (const run of r.runs ?? []) {\n passRuns.push({\n kind: \"schedule\",\n operation: run.operation,\n outcome: run.outcome,\n at: passAt,\n ...run.outcome === \"failed\" ? { error: r.errors.find((e) => e.operation === run.operation)?.error ?? null } : {}\n });\n }\n } catch (err) {\n report.errors.push({\n kind: \"schedule\",\n id: `${scopeId}:${reg.moduleId}`,\n error: message(err)\n });\n }\n }\n if (touched) report.schedules.scopes += 1;\n if (host.registeredFreshness && host.checkFreshness) {\n const freshRegs = host.registeredFreshness().filter((r) => r.freshness.length > 0);\n if (freshRegs.length > 0) {\n try {\n const r = await host.checkFreshness(freshRegs[0].moduleId, tenantId, scopeId);\n for (const check of r.checks) {\n passRuns.push({\n kind: \"freshness\",\n eventType: check.eventType,\n outcome: check.outcome,\n at: passAt,\n observedAt: check.observedAt\n });\n }\n } catch (err) {\n report.errors.push({ kind: \"freshness\", id: scopeId, error: message(err) });\n }\n }\n }\n if (passRuns.length > 0 && host.enqueueSweepRuns) {\n try {\n await host.enqueueSweepRuns(scopeId, {\n version: config.versionId?.(this.env) ?? null,\n // The payload caps its batch; a pathological schedule count truncates\n // rather than refusing the whole report.\n entries: passRuns.slice(0, 64)\n });\n } catch {\n }\n }\n }\n };\n await Promise.all(\n Array.from({ length: Math.max(1, Math.min(concurrency, entries.length)) }, worker)\n );\n return report;\n }\n };\n}\nvar message = (err) => err instanceof Error ? err.message : String(err);\n\n// packages/vertical-host/src/scope-sweep-host.ts\nvar SCOPE_SWEEP_HOST_KEY = \"substrat.scope-sweep-host\";\nfunction slot() {\n return globalThis;\n}\nfunction registeredScopeSweepHost() {\n return slot()[Symbol.for(SCOPE_SWEEP_HOST_KEY)];\n}\n\n// substrat-platform-sweeper.ts\nvar SweeperDO = defineScopeSweeperDO({\n intervalMs: 12e4,\n versionId: (env) => env.SUBSTRAT_VERSION_ID ?? null,\n host(env) {\n const hostFor = registeredScopeSweepHost();\n if (!hostFor) {\n throw new Error(\"this bundle registered no scope host for the platform sweeper: mount mountPlatformSurface from a current @substrat-run/vertical-host\");\n }\n return hostFor(env);\n },\n onPass(outcome) {\n if (\"error\" in outcome || outcome.errors.length > 0) {\n console.error(JSON.stringify({ substrat: \"scope-sweep\", ...outcome }));\n }\n }\n});\nexport {\n SweeperDO\n};\n";
27
+ /** The sweeper itself — 10096 bytes of ESM. */
28
+ export const PLATFORM_SWEEPER_SOURCE = "// packages/adapter-cloudflare/src/scope-sweeper-do.ts\nimport { DurableObject } from \"cloudflare:workers\";\nvar SWEEPER_ID = /^[0-9A-HJKMNP-TV-Z]{26}$/;\nfunction parseId(value, what) {\n if (typeof value !== \"string\" || !SWEEPER_ID.test(value)) {\n throw new TypeError(`${what} must be a ULID, got ${JSON.stringify(value)}`);\n }\n return value;\n}\nvar ROSTER_PREFIX = \"scope:\";\nvar JOB_START_PREFIX = \"job-start:\";\nfunction defineScopeSweeperDO(config) {\n return class ScopeSweeperDO extends DurableObject {\n /** The in-flight pass, when one is running — the overlap guard. */\n #pass = null;\n async noteScope(tenantId, scopeId) {\n const t = parseId(tenantId, \"tenantId\");\n const s = parseId(scopeId, \"scopeId\");\n await this.ctx.storage.put(`${ROSTER_PREFIX}${s}`, t);\n await this.ensureArmed();\n return { scopes: await this.#rosterSize() };\n }\n async forgetScope(scopeId) {\n const s = parseId(scopeId, \"scopeId\");\n await this.ctx.storage.delete([`${ROSTER_PREFIX}${s}`, `${JOB_START_PREFIX}${s}`]);\n return { scopes: await this.#rosterSize() };\n }\n /**\n * Arm the loop if it is not armed. Idempotent: an already-set alarm is left\n * exactly where it is, so this is safe to call on every request.\n */\n async ensureArmed() {\n const existing = await this.ctx.storage.getAlarm();\n if (existing !== null) return { armed: false, alarmAt: existing };\n const alarmAt = Date.now() + config.intervalMs;\n await this.ctx.storage.setAlarm(alarmAt);\n return { armed: true, alarmAt };\n }\n /**\n * Run a pass NOW (a manual kick, a just-provisioned scope's first tick, a\n * test). Joins the in-flight pass if one is running — never a second one —\n * and re-arms afterwards while scopes remain.\n */\n async sweepNow() {\n return this.#run();\n }\n /** The loop: one pass, then re-arm. Never throws (see the class doc). */\n async alarm() {\n await this.#run();\n }\n async #rosterSize() {\n return (await this.ctx.storage.list({ prefix: ROSTER_PREFIX })).size;\n }\n async #run() {\n if (this.#pass) return this.#pass;\n this.#pass = (async () => {\n try {\n const report = await this.#sweep();\n config.onPass?.(report, this.env);\n return report;\n } catch (err) {\n const outcome = { error: err instanceof Error ? err.message : String(err) };\n config.onPass?.(outcome, this.env);\n return outcome;\n }\n })();\n try {\n return await this.#pass;\n } finally {\n this.#pass = null;\n if (await this.#rosterSize() > 0) {\n await this.ctx.storage.setAlarm(Date.now() + config.intervalMs);\n }\n }\n }\n /** One pass over the roster: drain + due schedules per scope, errors contained. */\n async #sweep() {\n const host = config.host(this.env);\n const roster = await this.ctx.storage.list({ prefix: ROSTER_PREFIX });\n const report = {\n scopes: roster.size,\n drainTotals: { attempted: 0, delivered: 0, retrying: 0, deadLettered: 0 },\n schedules: { scopes: 0, fired: 0, skipped: 0, failed: 0 },\n ...config.runJobs ? { jobs: { attempted: 0, advanced: 0, completed: 0, retrying: 0, failed: 0 } } : {},\n errors: []\n };\n const registrations = host.registeredSchedules().filter((r) => r.schedules.length > 0);\n const entries = [...roster].map(([key, tenant]) => ({\n scopeId: key.slice(ROSTER_PREFIX.length),\n tenantId: tenant\n }));\n const concurrency = config.concurrency ?? 8;\n let next = 0;\n const worker = async () => {\n while (next < entries.length) {\n const { tenantId, scopeId } = entries[next++];\n if (host.lifecycleHeld) {\n try {\n if (await host.lifecycleHeld(scopeId)) {\n report.held = (report.held ?? 0) + 1;\n continue;\n }\n } catch (err) {\n report.errors.push({ kind: \"lifecycle\", id: scopeId, error: message(err) });\n continue;\n }\n }\n if (config.drainRetries !== false) {\n try {\n const r = await host.drainDue(tenantId, scopeId);\n report.drainTotals.attempted += r.attempted;\n report.drainTotals.delivered += r.delivered;\n report.drainTotals.retrying += r.retrying;\n report.drainTotals.deadLettered += r.deadLettered;\n } catch (err) {\n report.errors.push({ kind: \"drain\", id: scopeId, error: message(err) });\n }\n }\n if (config.runJobs) {\n if (config.startJobs) {\n try {\n const key = `${JOB_START_PREFIX}${scopeId}`;\n const last = await this.ctx.storage.get(key);\n const now = Date.now();\n if (last === void 0 || now - last >= (config.jobStartIntervalMs ?? config.intervalMs)) {\n await config.startJobs(host, tenantId, scopeId);\n await this.ctx.storage.put(key, now);\n }\n } catch (err) {\n report.errors.push({ kind: \"job\", id: `${scopeId}:start`, error: message(err) });\n }\n }\n try {\n const r = await host.runDueJobs(tenantId, scopeId);\n const totals = report.jobs;\n totals.attempted += r.attempted;\n totals.advanced += r.advanced;\n totals.completed += r.completed;\n totals.retrying += r.retrying;\n totals.failed += r.failed;\n for (const error of r.errors) {\n report.errors.push({ kind: \"job\", id: `${scopeId}:${error.runId}`, error: error.error });\n }\n } catch (err) {\n report.errors.push({ kind: \"job\", id: scopeId, error: message(err) });\n }\n }\n let touched = false;\n const passAt = (/* @__PURE__ */ new Date()).toISOString();\n const passRuns = [];\n for (const reg of registrations) {\n try {\n const r = await host.runDueSchedules(reg.moduleId, tenantId, scopeId);\n if (r.fired > 0 || r.failed > 0) touched = true;\n report.schedules.fired += r.fired;\n report.schedules.skipped += r.skipped;\n report.schedules.failed += r.failed;\n if (r.platformRequests) {\n report.schedules.platformRequests = (report.schedules.platformRequests ?? 0) + r.platformRequests;\n }\n for (const e of r.errors) {\n report.errors.push({\n kind: \"schedule\",\n id: `${scopeId}:${e.operation}`,\n error: e.error\n });\n }\n for (const run of r.runs ?? []) {\n passRuns.push({\n kind: \"schedule\",\n operation: run.operation,\n outcome: run.outcome,\n at: passAt,\n ...run.outcome === \"failed\" ? { error: r.errors.find((e) => e.operation === run.operation)?.error ?? null } : {}\n });\n }\n } catch (err) {\n report.errors.push({\n kind: \"schedule\",\n id: `${scopeId}:${reg.moduleId}`,\n error: message(err)\n });\n }\n }\n if (touched) report.schedules.scopes += 1;\n if (host.registeredFreshness && host.checkFreshness) {\n const freshRegs = host.registeredFreshness().filter((r) => r.freshness.length > 0);\n if (freshRegs.length > 0) {\n try {\n const r = await host.checkFreshness(freshRegs[0].moduleId, tenantId, scopeId);\n for (const check of r.checks) {\n passRuns.push({\n kind: \"freshness\",\n eventType: check.eventType,\n outcome: check.outcome,\n at: passAt,\n observedAt: check.observedAt\n });\n }\n } catch (err) {\n report.errors.push({ kind: \"freshness\", id: scopeId, error: message(err) });\n }\n }\n }\n if (passRuns.length > 0 && host.enqueueSweepRuns) {\n try {\n await host.enqueueSweepRuns(scopeId, {\n version: config.versionId?.(this.env) ?? null,\n // The payload caps its batch; a pathological schedule count truncates\n // rather than refusing the whole report.\n entries: passRuns.slice(0, 64)\n });\n } catch {\n }\n }\n }\n };\n await Promise.all(\n Array.from({ length: Math.max(1, Math.min(concurrency, entries.length)) }, worker)\n );\n return report;\n }\n };\n}\nvar message = (err) => err instanceof Error ? err.message : String(err);\n\n// packages/vertical-host/src/scope-sweep-host.ts\nvar SCOPE_SWEEP_HOST_KEY = \"substrat.scope-sweep-host\";\nfunction slot() {\n return globalThis;\n}\nfunction registeredScopeSweepHost() {\n return slot()[Symbol.for(SCOPE_SWEEP_HOST_KEY)];\n}\n\n// substrat-platform-sweeper.ts\nvar SweeperDO = defineScopeSweeperDO({\n intervalMs: 12e4,\n versionId: (env) => env.SUBSTRAT_VERSION_ID ?? null,\n host(env) {\n const hostFor = registeredScopeSweepHost();\n if (!hostFor) {\n throw new Error(\"this bundle registered no scope host for the platform sweeper: mount mountPlatformSurface from a current @substrat-run/vertical-host\");\n }\n return hostFor(env);\n },\n onPass(outcome) {\n if (\"error\" in outcome || outcome.errors.length > 0) {\n console.error(JSON.stringify({ substrat: \"scope-sweep\", ...outcome }));\n } else if (outcome.schedules.platformRequests) {\n console.log(JSON.stringify({ substrat: \"scope-sweep\", scopes: outcome.scopes, schedules: outcome.schedules }));\n }\n }\n});\nexport {\n SweeperDO\n};\n";
29
29
  //# sourceMappingURL=platform-entry.generated.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"platform-entry.generated.js","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAAA,8KAA8K;AAC9K,sEAAsE;AAEtE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAElE,gFAAgF;AAChF,MAAM,CAAC,MAAM,0BAA0B,GAAG,6BAA6B,CAAC;AAExE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,qBAAqB,GAAW,81sBAA81sB,CAAC;AAE54sB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yDAAyD,CAAC;AACnG,MAAM,CAAC,MAAM,2BAA2B,GAAG,sCAAsC,CAAC;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE,8CAA8C;AAC9C,MAAM,CAAC,MAAM,uBAAuB,GAAW,o0TAAo0T,CAAC"}
1
+ {"version":3,"file":"platform-entry.generated.js","sourceRoot":"","sources":["../src/platform-entry.generated.ts"],"names":[],"mappings":"AAAA,8KAA8K;AAC9K,sEAAsE;AAEtE;;;;;GAKG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,4BAA4B,CAAC;AAElE,gFAAgF;AAChF,MAAM,CAAC,MAAM,0BAA0B,GAAG,6BAA6B,CAAC;AAExE,6CAA6C;AAC7C,MAAM,CAAC,MAAM,qBAAqB,GAAW,81sBAA81sB,CAAC;AAE54sB;;;;;GAKG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAG,yDAAyD,CAAC;AACnG,MAAM,CAAC,MAAM,2BAA2B,GAAG,sCAAsC,CAAC;AAElF;;;GAGG;AACH,MAAM,CAAC,MAAM,uBAAuB,GAAG,8BAA8B,CAAC;AAEtE,+CAA+C;AAC/C,MAAM,CAAC,MAAM,uBAAuB,GAAW,iqUAAiqU,CAAC"}
@@ -2,10 +2,12 @@ import { oidcCallbackUrl, type PlatformActorId, type PreviewAuth, type Scope, ty
2
2
  import type { HostAdmin } from '@substrat-run/kernel';
3
3
  import type { VerticalClient } from './vertical-client.js';
4
4
  export interface PreviewAuthDeps {
5
- admin: Pick<HostAdmin, 'listScopes' | 'listVerticals' | 'listHostnames' | 'getScopeRecord'>;
5
+ admin: Pick<HostAdmin, 'listScopes' | 'listVerticals' | 'listHostnames' | 'getScopeRecord' | 'archiveScope' | 'resolveHostname'>;
6
6
  actor: PlatformActorId;
7
- /** The deployment serving an ISSUER scope — where its `/internal/preview-client` lives. */
7
+ /** The deployment serving an ISSUER scope — where its `/internal/preview-client` and `/internal/configure` live. */
8
8
  issuerClient(scope: Scope): Promise<VerticalClient | undefined>;
9
+ /** Re-run an issuer call that failed transiently, as a delivery to the preview is. Default: once. */
10
+ retry?: <T>(fn: () => Promise<T>) => Promise<T>;
9
11
  }
10
12
  /** The team's own auth-servers: active, not a fork, not a preview, of a vertical that provides `oidc-issuer`. */
11
13
  export declare function tenantIssuers(deps: PreviewAuthDeps, tenantId: TenantId): Promise<Scope[]>;
@@ -36,16 +38,20 @@ export interface WirePreviewAuthInput {
36
38
  */
37
39
  export declare function wirePreviewAuth(deps: PreviewAuthDeps, input: WirePreviewAuthInput): Promise<PreviewAuth>;
38
40
  /**
39
- * Delete every client minted for a preview, at every auth-server of its tenant — the reap's
40
- * half, run BEFORE the preview's storage and row go, so a failure leaves a preview a retry can
41
- * still find. An auth-server that predates preview clients cannot have minted one and is
42
- * skipped; any other failure throws.
41
+ * Un-register a preview's MCP endpoint and delete every client minted for it, at every
42
+ * auth-server of its tenant, in that order (see "A reap racing a push") — the reap's half,
43
+ * run BEFORE the preview's storage and row go, so a failure leaves a preview a retry can still
44
+ * find. A deployment that takes no delivery holds no registration, and one that predates
45
+ * preview clients holds no client; each is skipped for that half. Any other failure throws.
43
46
  */
44
47
  export declare function retireAllPreviewClients(deps: PreviewAuthDeps, tenantId: TenantId, previewScopeId: ScopeId): Promise<string[]>;
45
48
  /**
46
49
  * The reap's half for ANY scope about to go, as the platform sweep's expiry GC sees it: a
47
- * preview fork's clients are retired, and anything else — a snapshot, a clean room — has none
48
- * and is left alone. One predicate for the interactive reap and the sweep, so they agree.
50
+ * preview fork is archived — so no push still running can wire it again — and then its MCP
51
+ * registration is cleared and its clients retired; anything else — a snapshot, a clean room —
52
+ * has neither and is left alone. One predicate for the interactive reap and the sweep, so
53
+ * they agree. A reap that fails after the archive leaves an archived preview, which the reap's
54
+ * retry (the DELETE, the sweep's next pass, a create of the same tag) finds and finishes.
49
55
  */
50
56
  export declare function retireClientsOfReapedScope(deps: PreviewAuthDeps, scope: Scope | undefined): Promise<string[]>;
51
57
  //# sourceMappingURL=preview-auth.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"preview-auth.d.ts","sourceRoot":"","sources":["../src/preview-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,eAAe,EAGf,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,KAAK,QAAQ,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAgD3D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,GAAG,eAAe,GAAG,eAAe,GAAG,gBAAgB,CAAC,CAAC;IAC5F,KAAK,EAAE,eAAe,CAAC;IACvB,2FAA2F;IAC3F,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;CACjE;AAED,iHAAiH;AACjH,wBAAsB,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAO/F;AAaD,wFAAwF;AACxF,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,8FAA8F;IAC9F,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,8DAA8D;IAC9D,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAWD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAiK9G;AAaD;;;;;GAKG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,OAAO,GACtB,OAAO,CAAC,MAAM,EAAE,CAAC,CAanB;AAED;;;;GAIG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAGnH"}
1
+ {"version":3,"file":"preview-auth.d.ts","sourceRoot":"","sources":["../src/preview-auth.ts"],"names":[],"mappings":"AAAA,OAAO,EAIL,eAAe,EAGf,KAAK,eAAe,EACpB,KAAK,WAAW,EAChB,KAAK,KAAK,EACV,KAAK,OAAO,EACZ,KAAK,QAAQ,EACd,MAAM,yBAAyB,CAAC;AACjC,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AAEtD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAgF3D,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,YAAY,GAAG,eAAe,GAAG,eAAe,GAAG,gBAAgB,GAAG,cAAc,GAAG,iBAAiB,CAAC,CAAC;IACjI,KAAK,EAAE,eAAe,CAAC;IACvB,oHAAoH;IACpH,YAAY,CAAC,KAAK,EAAE,KAAK,GAAG,OAAO,CAAC,cAAc,GAAG,SAAS,CAAC,CAAC;IAChE,qGAAqG;IACrG,KAAK,CAAC,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,OAAO,CAAC,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,CAAC,CAAC;CACjD;AAKD,iHAAiH;AACjH,wBAAsB,aAAa,CAAC,IAAI,EAAE,eAAe,EAAE,QAAQ,EAAE,QAAQ,GAAG,OAAO,CAAC,KAAK,EAAE,CAAC,CAO/F;AAkBD,wFAAwF;AACxF,OAAO,EAAE,eAAe,EAAE,CAAC;AAE3B,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,QAAQ,CAAC;IACnB,uFAAuF;IACvF,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,OAAO,CAAC;IACnB,GAAG,EAAE,MAAM,CAAC;IACZ,8FAA8F;IAC9F,MAAM,EAAE,KAAK,GAAG,IAAI,CAAC;IACrB,8DAA8D;IAC9D,eAAe,EAAE,MAAM,CAAC;IACxB,OAAO,EAAE,MAAM,CAAC;IAChB,8FAA8F;IAC9F,OAAO,CAAC,OAAO,EAAE,KAAK,CAAC;QAAE,GAAG,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CACxE;AAWD;;;;;GAKG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,oBAAoB,GAAG,OAAO,CAAC,WAAW,CAAC,CAyQ9G;AAgBD;;;;;;GAMG;AACH,wBAAsB,uBAAuB,CAC3C,IAAI,EAAE,eAAe,EACrB,QAAQ,EAAE,QAAQ,EAClB,cAAc,EAAE,OAAO,GACtB,OAAO,CAAC,MAAM,EAAE,CAAC,CAiBnB;AAED;;;;;;;GAOG;AACH,wBAAsB,0BAA0B,CAAC,IAAI,EAAE,eAAe,EAAE,KAAK,EAAE,KAAK,GAAG,SAAS,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC,CAInH"}
@@ -1,4 +1,4 @@
1
- import { SHARED_ISSUER_CONFIG_KEY, oidcCallbackUrl, } from '@substrat-run/contracts';
1
+ import { MCP_RESOURCES_CONFIG_PREFIX, SHARED_ISSUER_CONFIG_KEY, mcpResourceOf, oidcCallbackUrl, } from '@substrat-run/contracts';
2
2
  import { ControlPlaneError } from '@substrat-run/control-plane-client';
3
3
  /**
4
4
  * A preview's login (#1704) — the control plane's half. The issuer's half, and why the
@@ -36,6 +36,38 @@ import { ControlPlaneError } from '@substrat-run/control-plane-client';
36
36
  * exists) means stop: the push that minted it owns what happens next. Only `kept: false`
37
37
  * — its own client vanished while its version is still bound — is retried, three
38
38
  * attempts in all; running out is a failure, never a success.
39
+ *
40
+ * ## Its MCP endpoint
41
+ *
42
+ * The issuer that now signs the preview in is also told to mint for the preview's MCP
43
+ * endpoint, or an MCP client pointed at the preview meets `invalid_target` before any login
44
+ * page (#1619). It is the dashboard's own delivery, `substrat:resources:<scope id>` through
45
+ * the issuer's `/internal/configure`, keyed by the PREVIEW's scope: the issuer touches only
46
+ * rows marked for that key, so prod's registration is never read or written. The value is
47
+ * the whole set, so every push re-asserts it at no cost, and the reap clears it. Like the
48
+ * dashboard's registration it is best-effort: a login that works is not failed for it.
49
+ *
50
+ * ## A reap racing a push
51
+ *
52
+ * The reap keeps the preview's row until its very last step, so the row alone cannot tell a
53
+ * push that the preview is going. The reap therefore ARCHIVES it before it touches any issuer
54
+ * (`retireClientsOfReapedScope`), and a push reads anything but `active` as gone. Archived is
55
+ * one-way here: no push ever restores a scope. Every issuer write of a push is followed by
56
+ * one of its looks at the binding before it answers, so either that look came before the
57
+ * archive, and the reap's issuer step, which runs after the archive, removes what the push
58
+ * wrote; or the look sees the archive, and the push removes what it wrote itself.
59
+ *
60
+ * Both removals clear the registration BEFORE they retire the clients. The issuer refuses to
61
+ * treat a scope it minted preview clients for as a parent, while the registration's row
62
+ * carries the same platform marker an app's does; clearing first means that row never
63
+ * outlives the clients that make the issuer read the scope as a preview.
64
+ *
65
+ * One row per endpoint, and the issuer moves it to whichever key delivered it last. A fresh
66
+ * preview of the same tag holds the same `--<tag>` hostname under a new scope, so a push still
67
+ * running for the reaped one could move that preview's row onto its own key, and its removal
68
+ * would then delete it. A push therefore registers only the hostnames the directory says its
69
+ * preview holds now, and after its removal hands back any such row to the preview of the same
70
+ * app that holds the hostname (`handBack`).
39
71
  */
40
72
  /** The capability a vertical declares to be a team issuer (manifest `provides`, #427). */
41
73
  const OIDC_ISSUER = 'oidc-issuer';
@@ -44,6 +76,8 @@ const LEGACY_ISSUER_SLUG = 'auth-server';
44
76
  /** The most callbacks a parent's hostnames yield in one check (the wire bound). */
45
77
  const MAX_PARENT_CALLBACKS = 32;
46
78
  const MAX_ATTEMPTS = 3;
79
+ /** The statuses `archiveScope` leaves; anything else is gone already, or past archived. */
80
+ const ARCHIVABLE = new Set(['provisioning', 'active', 'suspended']);
47
81
  /** The team's own auth-servers: active, not a fork, not a preview, of a vertical that provides `oidc-issuer`. */
48
82
  export async function tenantIssuers(deps, tenantId) {
49
83
  const verticals = await deps.admin.listVerticals(deps.actor);
@@ -59,6 +93,10 @@ function issuerHostname(bound) {
59
93
  return (pick(active) ?? pick(live))?.hostname;
60
94
  }
61
95
  const reasonOf = (e) => (e instanceof Error ? e.message : String(e));
96
+ /** The issuer's registration of a preview's MCP endpoints (#1619's entry): `[]` clears them. */
97
+ function previewResourcesEntry(previewScopeId, resources) {
98
+ return { key: `${MCP_RESOURCES_CONFIG_PREFIX}${previewScopeId}`, value: resources.length > 0 ? JSON.stringify(resources) : '' };
99
+ }
62
100
  /** Re-exported for the preview routes, which name a preview's callback on every row. */
63
101
  export { oidcCallbackUrl };
64
102
  /** Why a push left the login alone, as `preview create` reports it. */
@@ -157,15 +195,87 @@ export async function wirePreviewAuth(deps, input) {
157
195
  const issuer = `https://${claim.hostname}`;
158
196
  const address = { tenantId: input.tenantId, scopeId: claim.scope.id, previewScopeId: input.previewId };
159
197
  const retireOwn = (minted) => claim.client.retirePreviewClients({ ...address, only: minted.clientId }).then(() => null, (e) => reasonOf(e));
198
+ /** Deliver a scope's whole set of MCP endpoints, under that scope's own key, at this issuer. */
199
+ const registerMcp = (scopeId, hosts) => (deps.retry ?? ((fn) => fn()))(() => claim.client.configureInstance({
200
+ tenantId: input.tenantId,
201
+ scopeId: claim.scope.id,
202
+ entries: [previewResourcesEntry(scopeId, hosts.map((h) => mcpResourceOf(`https://${h}`)))],
203
+ }));
204
+ /**
205
+ * The hostnames a scope's endpoints are, by the dashboard's rule (`mcpResourcesFor`): every
206
+ * one the directory says it actively answers on NOW. Never one it no longer holds: the issuer
207
+ * moves a row to whichever key delivered it last, so a push still running for a reaped
208
+ * preview must not claim the `--<tag>` hostname a newer preview of the same tag holds.
209
+ */
210
+ const activeHosts = async (scopeId) => [
211
+ ...new Set((await deps.admin.listHostnames(deps.actor, { scopeId }))
212
+ .filter((h) => h.status === 'active')
213
+ .map((h) => h.hostname)),
214
+ ].sort();
215
+ /** Anything but `active` is gone: the reap archives a preview before its issuer step. */
160
216
  const bound = async () => {
161
217
  const rec = await deps.admin.getScopeRecord(deps.actor, input.tenantId, input.previewId);
162
218
  if (!rec || rec.status !== 'active')
163
219
  return 'gone';
164
220
  return rec.verticalVersionId === input.versionId ? 'ours' : 'moved';
165
221
  };
222
+ /** Set once this push has minted: from then on it may have left something at the issuer. */
223
+ let wrote = false;
224
+ /** What this push last asked the issuer to register — the rows its delivery may have moved. */
225
+ let registeredHosts = [];
226
+ /** Is this scope an active preview of the same app — one a hand-back may write for? */
227
+ const liveSibling = async (scopeId) => {
228
+ const rec = await deps.admin.getScopeRecord(deps.actor, input.tenantId, scopeId);
229
+ return rec?.status === 'active' && rec.kind === 'preview' && rec.forkedFrom === parent.id;
230
+ };
231
+ /**
232
+ * After this push cleared its own key: hand back a row it moved off a NEWER preview of the
233
+ * same app (the same `--<tag>` hostname under a fresh scope), which the clear just deleted.
234
+ * The directory names who holds each hostname now; that preview gets its own whole set back
235
+ * under its own key, as its own push sends it. Anything else holding one is left alone.
236
+ *
237
+ * The hand-back is an issuer write like any other, so it is followed by a look: a holder
238
+ * reaped while it was in flight has its key cleared again. Its reap archives it before its
239
+ * own clear, so either this look sees the archive or that clear lands after this write.
240
+ */
241
+ const handBack = async () => {
242
+ const holders = new Set();
243
+ for (const hostname of registeredHosts) {
244
+ const route = await deps.admin.resolveHostname(hostname);
245
+ if (route && route.tenantId === input.tenantId && route.scopeId !== input.previewId)
246
+ holders.add(route.scopeId);
247
+ }
248
+ for (const holder of holders) {
249
+ if (!(await liveSibling(holder)))
250
+ continue;
251
+ await registerMcp(holder, await activeHosts(holder));
252
+ if (!(await liveSibling(holder)))
253
+ await registerMcp(holder, []);
254
+ }
255
+ };
166
256
  const reapedMeanwhile = async () => {
167
- // The preview was reaped while this push ran: nothing may outlive it at the issuer.
168
- await claim.client.retirePreviewClients(address).catch(() => undefined);
257
+ // The preview was reaped while this push ran. What this push wrote after the reap's issuer
258
+ // step is this push's to remove (see "A reap racing a push"), and a step that fails is
259
+ // said, each in its own words: after the row is gone, nothing names those writes again.
260
+ // Every step runs whatever the others did, except that the clients stay when the clear
261
+ // failed, so the registration never outlives them (clear first, as the reap does).
262
+ if (wrote) {
263
+ const failed = [];
264
+ const step = (what, run) => run().then(() => true, (e) => {
265
+ failed.push(`${what} failed (${reasonOf(e)})`);
266
+ return false;
267
+ });
268
+ const cleared = await step("clearing this preview's MCP registration", () => registerMcp(input.previewId, []));
269
+ await step('handing back the MCP registration of the newer preview that holds its hostname', handBack);
270
+ if (cleared)
271
+ await step("deleting this push's client", () => claim.client.retirePreviewClients(address));
272
+ else
273
+ failed.push("its client was kept, so it does not outlive the registration that failed to clear");
274
+ if (failed.length > 0) {
275
+ throw new ControlPlaneError(502, `preview '${input.tag}' was reaped while this push ran, and at the auth server ${claim.scope.id} ` +
276
+ `${failed.join('; ')}.`);
277
+ }
278
+ }
169
279
  return superseded(callbackUrl, 'the preview was reaped while this push ran');
170
280
  };
171
281
  const noLogin = (why) => new ControlPlaneError(502, `preview '${input.tag}' was created but has NO working login: ${why}. Re-run \`preview create\` to retry.`);
@@ -189,6 +299,7 @@ export async function wirePreviewAuth(deps, input) {
189
299
  catch (e) {
190
300
  throw noLogin(`the auth server ${claim.scope.id} did not mint its client (${reasonOf(e)})`);
191
301
  }
302
+ wrote = true;
192
303
  try {
193
304
  await input.deliver([
194
305
  {
@@ -205,29 +316,51 @@ export async function wirePreviewAuth(deps, input) {
205
316
  (cleanup ? `, and removing that client failed too (${cleanup}) — the preview's reap removes it` : ''));
206
317
  }
207
318
  const after = await bound();
208
- if (after !== 'ours') {
319
+ if (after === 'gone')
320
+ return reapedMeanwhile(); // which removes our client with the rest
321
+ if (after === 'moved') {
209
322
  // Our client sits only in our own version's store, which is no longer served.
210
323
  await retireOwn(minted);
211
- return after === 'gone' ? reapedMeanwhile() : superseded(callbackUrl, 'another push re-bound the preview');
324
+ return superseded(callbackUrl, 'another push re-bound the preview');
212
325
  }
213
- let retired;
326
+ // Delivered and bound: the issuer signs this preview in now, so it may mint for the
327
+ // preview's MCP endpoints too. A repeat (a retry below, every later push) writes nothing.
328
+ const mcp = await activeHosts(input.previewId)
329
+ .then(async (hosts) => {
330
+ registeredHosts = hosts;
331
+ await registerMcp(input.previewId, hosts);
332
+ return hosts.length > 0
333
+ ? ` MCP: ${hosts.map((h) => mcpResourceOf(`https://${h}`)).join(', ')} registered there too, and un-registered by the same reap.`
334
+ : ` MCP: the preview answers on no active hostname yet, so no endpoint of it is registered there.`;
335
+ })
336
+ .catch((e) => ` MCP: the preview's endpoint could not be registered there (${reasonOf(e)}), so an MCP client ` +
337
+ `pointed at the preview gets invalid_target until the next push registers it.`);
338
+ let older = '';
214
339
  try {
215
- retired = await claim.client.retirePreviewClients({ ...address, keep: minted.clientId });
340
+ const retired = await claim.client.retirePreviewClients({ ...address, keep: minted.clientId });
341
+ if (retired.kept === false)
342
+ continue; // our own client vanished while our version is bound
216
343
  }
217
344
  catch (e) {
218
345
  // Delivered and bound: the login works. What is left is older clients, which the next
219
346
  // push or the reap removes — said, not hidden.
220
- return wired(claim.scope.id, issuer, minted.clientId, callbackUrl, ` Older clients of this preview could not be removed yet (${reasonOf(e)}); the next push or the reap removes them.`);
347
+ older = ` Older clients of this preview could not be removed yet (${reasonOf(e)}); the next push or the reap removes them.`;
221
348
  }
222
- if (retired.kept === false)
223
- continue; // our own client vanished while our version is bound
349
+ // The look after this push's last issuer write, on every way to `wired` (see "A reap racing a push").
224
350
  if ((await bound()) === 'gone')
225
351
  return reapedMeanwhile();
226
- return wired(claim.scope.id, issuer, minted.clientId, callbackUrl);
352
+ return wired(claim.scope.id, issuer, minted.clientId, callbackUrl, `${mcp}${older}`);
227
353
  }
354
+ // The last attempt's `continue` lands here, after its writes: the same look, before giving up,
355
+ // and the same answers the loop gives.
356
+ const last = await bound();
357
+ if (last === 'gone')
358
+ return reapedMeanwhile();
359
+ if (last === 'moved')
360
+ return superseded(callbackUrl, 'another push re-bound the preview');
228
361
  throw noLogin(`its client kept disappearing at the auth server ${claim.scope.id} (${MAX_ATTEMPTS} attempts)`);
229
362
  }
230
- function wired(issuerScopeId, issuer, clientId, callbackUrl, extra = '') {
363
+ function wired(issuerScopeId, issuer, clientId, callbackUrl, extra) {
231
364
  return {
232
365
  status: 'wired',
233
366
  callbackUrl,
@@ -237,11 +370,14 @@ function wired(issuerScopeId, issuer, clientId, callbackUrl, extra = '') {
237
370
  note: `Sign-in: this preview has its own client at your auth server ${issuer} (client ${clientId}); it is deleted when the preview is reaped.${extra}`,
238
371
  };
239
372
  }
373
+ /** A refusal that says the deployment does not implement the call: it cannot hold what the call removes. */
374
+ const predates = (e) => e instanceof ControlPlaneError && e.status === 501;
240
375
  /**
241
- * Delete every client minted for a preview, at every auth-server of its tenant — the reap's
242
- * half, run BEFORE the preview's storage and row go, so a failure leaves a preview a retry can
243
- * still find. An auth-server that predates preview clients cannot have minted one and is
244
- * skipped; any other failure throws.
376
+ * Un-register a preview's MCP endpoint and delete every client minted for it, at every
377
+ * auth-server of its tenant, in that order (see "A reap racing a push") — the reap's half,
378
+ * run BEFORE the preview's storage and row go, so a failure leaves a preview a retry can still
379
+ * find. A deployment that takes no delivery holds no registration, and one that predates
380
+ * preview clients holds no client; each is skipped for that half. Any other failure throws.
245
381
  */
246
382
  export async function retireAllPreviewClients(deps, tenantId, previewScopeId) {
247
383
  const deleted = [];
@@ -249,25 +385,46 @@ export async function retireAllPreviewClients(deps, tenantId, previewScopeId) {
249
385
  const client = await deps.issuerClient(scope);
250
386
  if (!client)
251
387
  throw new ControlPlaneError(502, `the auth server ${scope.id} could not be reached to delete preview ${previewScopeId}'s clients`);
388
+ await client
389
+ .configureInstance({ tenantId, scopeId: scope.id, entries: [previewResourcesEntry(previewScopeId, [])] })
390
+ .catch((e) => {
391
+ if (!predates(e))
392
+ throw e;
393
+ });
252
394
  try {
253
395
  deleted.push(...(await client.retirePreviewClients({ tenantId, scopeId: scope.id, previewScopeId })).deleted);
254
396
  }
255
397
  catch (e) {
256
- if (e instanceof ControlPlaneError && e.status === 501)
257
- continue;
258
- throw e;
398
+ if (!predates(e))
399
+ throw e;
259
400
  }
260
401
  }
261
402
  return deleted;
262
403
  }
263
404
  /**
264
405
  * The reap's half for ANY scope about to go, as the platform sweep's expiry GC sees it: a
265
- * preview fork's clients are retired, and anything else — a snapshot, a clean room — has none
266
- * and is left alone. One predicate for the interactive reap and the sweep, so they agree.
406
+ * preview fork is archived — so no push still running can wire it again — and then its MCP
407
+ * registration is cleared and its clients retired; anything else — a snapshot, a clean room —
408
+ * has neither and is left alone. One predicate for the interactive reap and the sweep, so
409
+ * they agree. A reap that fails after the archive leaves an archived preview, which the reap's
410
+ * retry (the DELETE, the sweep's next pass, a create of the same tag) finds and finishes.
267
411
  */
268
412
  export async function retireClientsOfReapedScope(deps, scope) {
269
413
  if (!scope || scope.kind !== 'preview' || !scope.forkedFrom)
270
414
  return [];
415
+ await archiveForReap(deps, scope);
271
416
  return retireAllPreviewClients(deps, scope.tenantId, scope.id);
272
417
  }
418
+ /** Archive a preview about to be reaped, unless it is archived (or gone) already — by a reap racing this one, too. */
419
+ async function archiveForReap(deps, scope) {
420
+ const current = async () => (await deps.admin.getScopeRecord(deps.actor, scope.tenantId, scope.id))?.status;
421
+ const status = await current();
422
+ if (status === undefined || !ARCHIVABLE.has(status))
423
+ return;
424
+ await deps.admin.archiveScope(deps.actor, scope.tenantId, scope.id).catch(async (e) => {
425
+ const now = await current();
426
+ if (now !== undefined && ARCHIVABLE.has(now))
427
+ throw e;
428
+ });
429
+ }
273
430
  //# sourceMappingURL=preview-auth.js.map