@substrat-run/control-plane-api 0.102.0 → 0.105.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/api.d.ts +23 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +52 -0
- package/dist/api.js.map +1 -1
- package/dist/cf-observability.d.ts.map +1 -1
- package/dist/cf-observability.js +103 -0
- package/dist/cf-observability.js.map +1 -1
- package/dist/connect-url.d.ts +52 -0
- package/dist/connect-url.d.ts.map +1 -0
- package/dist/connect-url.js +129 -0
- package/dist/connect-url.js.map +1 -0
- package/dist/index.d.ts +3 -1
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/observability.d.ts +33 -0
- package/dist/observability.d.ts.map +1 -1
- package/dist/vertical-client.d.ts +9 -0
- package/dist/vertical-client.d.ts.map +1 -1
- package/dist/vertical-client.js +7 -0
- package/dist/vertical-client.js.map +1 -1
- package/package.json +6 -6
package/dist/api.d.ts
CHANGED
|
@@ -260,7 +260,30 @@ export interface ControlPlaneApiOptions {
|
|
|
260
260
|
* (correct for a deployment that mints no platform hostnames).
|
|
261
261
|
*/
|
|
262
262
|
platformBaseDomains?: string[];
|
|
263
|
+
/**
|
|
264
|
+
* The CLI version advisory (#971) — what `substrat` reads off every response to nudge
|
|
265
|
+
* a builder whose CLI has fallen behind (`packages/cli/src/version.ts`). The control
|
|
266
|
+
* plane is the authority on whether a CLI is still *compatible*, which npm's `latest`
|
|
267
|
+
* tag is not, so the two values are deployment facts, not package metadata:
|
|
268
|
+
* `minVersion` the oldest CLI this platform still accepts pushes from (the floor)
|
|
269
|
+
* `latestVersion` the newest published CLI
|
|
270
|
+
* Each is emitted only when supplied, as {@link CLI_MIN_VERSION_HEADER} /
|
|
271
|
+
* {@link CLI_LATEST_VERSION_HEADER}. Absent ⇒ no header at all, and a CLI that reads
|
|
272
|
+
* nothing says nothing — a server that stays silent costs nobody anything. Advisory
|
|
273
|
+
* only: this package does not refuse a push below the floor.
|
|
274
|
+
*/
|
|
275
|
+
cliAdvisory?: {
|
|
276
|
+
minVersion?: string;
|
|
277
|
+
latestVersion?: string;
|
|
278
|
+
};
|
|
263
279
|
}
|
|
280
|
+
/**
|
|
281
|
+
* Response headers carrying the CLI version advisory (`ControlPlaneApiOptions.cliAdvisory`).
|
|
282
|
+
* The CLI reads these by the same spelling (`packages/cli/src/version.ts`); exported so a
|
|
283
|
+
* host or a test names the header rather than restating the string.
|
|
284
|
+
*/
|
|
285
|
+
export declare const CLI_MIN_VERSION_HEADER = "x-substrat-cli-min-version";
|
|
286
|
+
export declare const CLI_LATEST_VERSION_HEADER = "x-substrat-cli-latest-version";
|
|
264
287
|
type Vars = {
|
|
265
288
|
actor: PlatformActorId;
|
|
266
289
|
principal: Principal;
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/api.js
CHANGED
|
@@ -31,6 +31,13 @@ import { mintPushToken, pushActorFor } from './push-token.js';
|
|
|
31
31
|
import { namespacesForScript } from './do-namespaces.js';
|
|
32
32
|
import { backupDirectoryIfDue } from './directory-backup.js';
|
|
33
33
|
import { isCustomHostname, validateBindableHostname, } from './custom-hostnames.js';
|
|
34
|
+
/**
|
|
35
|
+
* Response headers carrying the CLI version advisory (`ControlPlaneApiOptions.cliAdvisory`).
|
|
36
|
+
* The CLI reads these by the same spelling (`packages/cli/src/version.ts`); exported so a
|
|
37
|
+
* host or a test names the header rather than restating the string.
|
|
38
|
+
*/
|
|
39
|
+
export const CLI_MIN_VERSION_HEADER = 'x-substrat-cli-min-version';
|
|
40
|
+
export const CLI_LATEST_VERSION_HEADER = 'x-substrat-cli-latest-version';
|
|
34
41
|
// -- request schemas ---------------------------------------------------------
|
|
35
42
|
// Parse, don't trust: every input crosses Zod at the boundary. The ids stay
|
|
36
43
|
// CALLER-SUPPLIED rather than minted here, exactly as the contract has them —
|
|
@@ -344,6 +351,20 @@ export function createControlPlaneApi(options) {
|
|
|
344
351
|
const { host, authenticate, authenticateBuilder } = options;
|
|
345
352
|
const admin = host.admin;
|
|
346
353
|
const app = new Hono();
|
|
354
|
+
// The CLI version advisory (#971), stamped on EVERY response — including the 401 the
|
|
355
|
+
// auth middleware below answers with, since a CLI too old to authenticate is exactly
|
|
356
|
+
// the one that needs to hear it. Registered first so nothing can return around it.
|
|
357
|
+
// Nothing configured ⇒ no header touched, byte-identical to before this existed.
|
|
358
|
+
const advisory = options.cliAdvisory;
|
|
359
|
+
if (advisory?.minVersion || advisory?.latestVersion) {
|
|
360
|
+
app.use('*', async (c, next) => {
|
|
361
|
+
await next();
|
|
362
|
+
if (advisory.minVersion)
|
|
363
|
+
c.header(CLI_MIN_VERSION_HEADER, advisory.minVersion);
|
|
364
|
+
if (advisory.latestVersion)
|
|
365
|
+
c.header(CLI_LATEST_VERSION_HEADER, advisory.latestVersion);
|
|
366
|
+
});
|
|
367
|
+
}
|
|
347
368
|
// Fail closed, before any route runs: no principal, no reach. Staff/service first
|
|
348
369
|
// (unchanged, a superset); a builder session only when staff declines.
|
|
349
370
|
app.use('*', async (c, next) => {
|
|
@@ -2259,6 +2280,22 @@ export function createControlPlaneApi(options) {
|
|
|
2259
2280
|
return c.json({ error: 'restore failed — the backup could not be loaded', detail }, 422);
|
|
2260
2281
|
}
|
|
2261
2282
|
});
|
|
2283
|
+
// #1236: when this scope's migrations actually ran — the schema-change history
|
|
2284
|
+
// whose instants `_substrat_migrations.applied_at` has held all along with no
|
|
2285
|
+
// reader. Read through the vertical that holds the scope's data when one
|
|
2286
|
+
// resolves; the co-located host otherwise. Metadata only, so no masking.
|
|
2287
|
+
app.get('/tenants/:tenantId/scopes/:scopeId/migrations', async (c) => {
|
|
2288
|
+
const tenantId = tenantIdSchema.parse(c.req.param('tenantId'));
|
|
2289
|
+
const scopeId = scopeIdSchema.parse(c.req.param('scopeId'));
|
|
2290
|
+
const actor = c.get('actor');
|
|
2291
|
+
const scope = await admin.getScopeRecord(actor, tenantId, scopeId);
|
|
2292
|
+
if (!scope)
|
|
2293
|
+
return c.json({ error: `unknown scope for tenant: (${tenantId}, ${scopeId})` }, 404);
|
|
2294
|
+
const vertical = await verticalForScope(c, scope);
|
|
2295
|
+
return c.json(vertical
|
|
2296
|
+
? await vertical.appliedMigrations(scopeId)
|
|
2297
|
+
: await admin.scopeAppliedMigrations(actor, tenantId, scopeId));
|
|
2298
|
+
});
|
|
2262
2299
|
// #286: the PITR bookmarks a scope recorded before its migration passes — the
|
|
2263
2300
|
// rewind points the deployments UI offers for a backout. Read through the
|
|
2264
2301
|
// vertical that holds the scope's data when one resolves; the co-located host
|
|
@@ -3471,6 +3508,21 @@ export function createControlPlaneApi(options) {
|
|
|
3471
3508
|
.parse({ hours: c.req.query('hours') });
|
|
3472
3509
|
return c.json(await options.observability.serviceMetrics({ hours }));
|
|
3473
3510
|
});
|
|
3511
|
+
// The bucketed twin (#1236): the series a chart plots, with the deploy markers
|
|
3512
|
+
// drawn on top by the caller (push instants are registry facts, not telemetry).
|
|
3513
|
+
// 501 when the reader cannot bucket — an empty series would render as "quiet".
|
|
3514
|
+
app.get('/observability/metrics-series', async (c) => {
|
|
3515
|
+
if (!options.observability?.serviceMetricsSeries) {
|
|
3516
|
+
return c.json({ error: 'bucketed observability is not configured on this control plane' }, 501);
|
|
3517
|
+
}
|
|
3518
|
+
const { hours } = z
|
|
3519
|
+
.object({ hours: z.coerce.number().int().min(1).max(72).default(24) })
|
|
3520
|
+
.parse({ hours: c.req.query('hours') });
|
|
3521
|
+
// Repeats like /observability/logs' `service`: a caller narrows to the handful
|
|
3522
|
+
// it will plot, which is what keeps scripts × buckets bounded.
|
|
3523
|
+
const services = c.req.queries('service') ?? undefined;
|
|
3524
|
+
return c.json(await options.observability.serviceMetricsSeries({ hours, services }));
|
|
3525
|
+
});
|
|
3474
3526
|
app.get('/observability/logs', async (c) => {
|
|
3475
3527
|
if (!options.observability) {
|
|
3476
3528
|
return c.json({ error: 'observability is not configured on this control plane' }, 501);
|