@substrat-run/control-plane-api 0.152.0 → 0.154.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 +8 -0
- package/dist/api.d.ts.map +1 -1
- package/dist/api.js +125 -12
- package/dist/api.js.map +1 -1
- package/dist/custom-hostnames.d.ts +15 -1
- package/dist/custom-hostnames.d.ts.map +1 -1
- package/dist/custom-hostnames.js +33 -2
- package/dist/custom-hostnames.js.map +1 -1
- package/dist/deploy.d.ts +1 -1
- package/dist/deploy.d.ts.map +1 -1
- package/dist/deploy.js +1 -1
- package/dist/deploy.js.map +1 -1
- package/dist/index.d.ts +2 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -0
- package/dist/index.js.map +1 -1
- package/dist/platform-entry.generated.d.ts +1 -1
- package/dist/platform-entry.generated.d.ts.map +1 -1
- package/dist/platform-entry.generated.js +2 -2
- package/dist/platform-entry.generated.js.map +1 -1
- package/dist/social-relay.d.ts +115 -0
- package/dist/social-relay.d.ts.map +1 -0
- package/dist/social-relay.js +118 -0
- package/dist/social-relay.js.map +1 -0
- package/dist/vertical-client.d.ts +65 -2
- package/dist/vertical-client.d.ts.map +1 -1
- package/dist/vertical-client.js +147 -5
- package/dist/vertical-client.js.map +1 -1
- package/package.json +6 -6
package/dist/api.d.ts
CHANGED
|
@@ -17,6 +17,7 @@ import { type DoNamespaceReader } from './do-namespaces.js';
|
|
|
17
17
|
import type { DirectoryBackupStore, ScopeBackupStore } from './backups.js';
|
|
18
18
|
import { type LakeQueryEngine } from './lake-gateway.js';
|
|
19
19
|
import { type CustomHostnameProvisioner } from './custom-hostnames.js';
|
|
20
|
+
import { type SocialRelayOptions } from './social-relay.js';
|
|
20
21
|
/**
|
|
21
22
|
* What one provider can answer about a live connection (#605) — the seam behind
|
|
22
23
|
* `POST /tenants/:t/connections/:id/verify` and `GET …/activity`.
|
|
@@ -372,6 +373,13 @@ export interface ControlPlaneApiOptions {
|
|
|
372
373
|
* self-host / dev shape, where there is no CF-for-SaaS zone).
|
|
373
374
|
*/
|
|
374
375
|
provisionHostname?: CustomHostnameProvisioner;
|
|
376
|
+
/**
|
|
377
|
+
* The platform's social relay (#1544, `social-relay.ts`): how an Auth Server install is given
|
|
378
|
+
* its own client there. When present, a hostname of such an install becoming active
|
|
379
|
+
* reconciles that install, and the two staff routes under `social-relay` can reconcile one
|
|
380
|
+
* install or all of them. Absent ⇒ nothing here ever calls the relay.
|
|
381
|
+
*/
|
|
382
|
+
socialRelay?: SocialRelayOptions;
|
|
375
383
|
/**
|
|
376
384
|
* The platform's base domains — the wildcard-covered zones a PLATFORM hostname is
|
|
377
385
|
* minted under (`substrat.run`, `global.substrat.run`, …). A bind AT or UNDER one of
|
package/dist/api.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,sBAAsB,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AAE9G,OAAO,EAAE,IAAI,EAAE,MAAM,MAAM,CAAC;AAE5B,OAAO,EAsBL,KAAK,qBAAqB,EAgF1B,CAAC,EAeD,KAAK,cAAc,EAEnB,KAAK,uBAAuB,
|
|
1
|
+
{"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../src/api.ts"],"names":[],"mappings":"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"}
|
package/dist/api.js
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
import { PREVIEW_CONNECTIONS_REFUSAL } from './connection-relay.js';
|
|
2
2
|
import { resolveObservabilityWindow } from './observability-window.js';
|
|
3
3
|
import { Hono } from 'hono';
|
|
4
|
-
import { permissionKey, parseHostname, withLabel, RESERVED_LABEL_SEPARATOR, adminAction, lakeEventsInput, ownerTransferInput, memberInviteInput, memberRoleInput, ASSET_PART_PREFIX, assetHash, STORE_DRIVERS, STORE_RELEASE_MAX_BYTES, channelName, connectLinkId, connectionActivity, connectionActivitySource, connectionCredential, connectionCertificate, connectionFilter, connectionHealthState, connectionProvider, connectorDispatchKind, PROVISION_SIBLING_KIND, ARCHIVE_SCOPE_KIND, PROVISION_TENANT_KIND, SET_ENTITLEMENTS_KIND, MODEL_USAGE_KIND, SWEEP_RUNS_KIND, toConnectionHealthEntry, CONNECTION_EXPIRY_WARNING_DAYS, CONNECTION_STALE_DAYS, connectionProbe, createTenantInput, entitlementGrantInput, hostname as hostnameSchema, hostnameRegion, hostnameStatus, identityLink, errorCode, issueStatus, issueStatusInput, FINDINGS_LIMIT_DEFAULT, FINDINGS_LIMIT_MAX, findingCursorOf, findingKind, findingRuleInput, findingStatus, findingStatusInput, listPageQuery, matchesOutboundHost, pageOf, platformRequestFilter, principalId as principalIdSchema, impersonationStamp, promotionAcknowledgement, bindAcknowledgement, rebindAcknowledgement, provisionableJurisdiction, publishVersionInput, queryScopeInput, readScopeTableInput, entityHistoryInput, eventFacetInput, eventCauseInput, eventEffectsInput, invocationEventsInput, deadLettersInput, lifecycleFlowInput, operationSeriesCount, operationSeriesInput, delegatedReadParams, createOrgInput, roleKey as roleKeySchema, peerSwitch, verticalSlug, systemSwitch, DEFAULT_DENIAL_LIMIT, DENIAL_LIMIT_MAX, denialGroupBy, registerVerticalInput, platformScriptCollision, platformScriptRefusal, PLATFORM_SCRIPT_NAMES, serviceDimensions, sweepRunKind, sweepRunOutcome, scopeDump, dataSubjectId as dataSubjectIdSchema, scopeId as scopeIdSchema, scopeStatus, storageShape, surfaceName, tenantId as tenantIdSchema, tenantStatus, versionOrigin, z, PROBLEM_CONTENT_TYPE, toProblem, validationIssuesFrom, redrainEventsInput, importCursorMove, importCursorAcknowledgementMissing, REDRAIN_BATCH, migrationsOnTop, substratError, errorCodeOf, capabilityFilterQuery, capabilityId as capabilityIdSchema, PLATFORM_FEATURES_HEADER, PLATFORM_FEATURE_SCOPE_SWEEPER, } from '@substrat-run/contracts';
|
|
4
|
+
import { permissionKey, parseHostname, withLabel, RESERVED_LABEL_SEPARATOR, adminAction, lakeEventsInput, ownerTransferInput, memberInviteInput, memberRoleInput, ASSET_PART_PREFIX, assetHash, STORE_DRIVERS, STORE_RELEASE_MAX_BYTES, channelName, connectLinkId, connectionActivity, connectionActivitySource, connectionCredential, connectionCertificate, connectionFilter, connectionHealthState, connectionProvider, connectorDispatchKind, PROVISION_SIBLING_KIND, ARCHIVE_SCOPE_KIND, PROVISION_TENANT_KIND, SET_ENTITLEMENTS_KIND, MODEL_USAGE_KIND, SWEEP_RUNS_KIND, toConnectionHealthEntry, CONNECTION_EXPIRY_WARNING_DAYS, CONNECTION_STALE_DAYS, connectionProbe, createTenantInput, entitlementGrantInput, hostname as hostnameSchema, hostnameRegion, hostnameStatus, identityLink, errorCode, issueStatus, issueStatusInput, FINDINGS_LIMIT_DEFAULT, FINDINGS_LIMIT_MAX, findingCursorOf, findingKind, findingRuleInput, findingStatus, findingStatusInput, listPageQuery, matchesOutboundHost, pageOf, platformRequestFilter, principalId as principalIdSchema, impersonationStamp, promotionAcknowledgement, bindAcknowledgement, rebindAcknowledgement, provisionableJurisdiction, publishVersionInput, queryScopeInput, readScopeTableInput, entityHistoryInput, eventFacetInput, eventCauseInput, eventEffectsInput, invocationEventsInput, deadLettersInput, lifecycleFlowInput, operationSeriesCount, operationSeriesInput, delegatedReadParams, createOrgInput, roleKey as roleKeySchema, peerSwitch, verticalSlug, systemSwitch, DEFAULT_DENIAL_LIMIT, DENIAL_LIMIT_MAX, denialGroupBy, registerVerticalInput, platformScriptCollision, platformScriptRefusal, PLATFORM_SCRIPT_NAMES, serviceDimensions, sweepRunKind, sweepRunOutcome, scopeDump, dataSubjectId as dataSubjectIdSchema, scopeId as scopeIdSchema, scopeStatus, storageShape, surfaceName, tenantId as tenantIdSchema, tenantStatus, versionOrigin, z, PROBLEM_CONTENT_TYPE, toProblem, validationIssuesFrom, redrainEventsInput, importCursorMove, importCursorAcknowledgementMissing, REDRAIN_BATCH, migrationsOnTop, substratError, errorCodeOf, capabilityFilterQuery, capabilityId as capabilityIdSchema, PLATFORM_FEATURES_HEADER, PLATFORM_FEATURE_SCOPE_SWEEPER, SOCIAL_RELAY_VERTICALS, } from '@substrat-run/contracts';
|
|
5
5
|
import { SCOPE_COPY_LEASE_MS, copyRestoreFence, publishedMigrationDigest, replayStoreErasures } from '@substrat-run/kernel';
|
|
6
6
|
import { attributeFailure } from './failure-attribution.js';
|
|
7
7
|
import { auditedChange, withAuditedOutcomes } from './audited-change.js';
|
|
8
8
|
import { BIND_EXPORT_BREAK_REFUSAL, CARRIED_AWAY_KEY, bindExportBreakRefusal, carriedAwayDump, dumpMetaValue, metaValueIn, crossVerticalHealth, exportBreakRefusal, isBindExportBreakRefusal, isExportBreakRefusal, isPrimaryScope, promoteReviewDigest, rebindReviewDigest, assertRebindReviewCurrent, migrationProgress, ulid, auditWarningOf, } from '@substrat-run/kernel';
|
|
9
9
|
import { TENANT_HEADER, confinedTenant } from './auth.js';
|
|
10
10
|
import { mintTenantToken } from './tenant-token.js';
|
|
11
|
-
import { connectionGrantsForScope } from './vertical-client.js';
|
|
11
|
+
import { connectionGrantsForScope, transferScope } from './vertical-client.js';
|
|
12
12
|
import { runningVersionOf, runningVersionStoresOf, scopeStoreReachOf, scopeStoresOf, unrouteScope } from './platform-scope-stores.js';
|
|
13
13
|
import { STORE_REBUILD_REQUEST_SUBREQUESTS, runStoreFleetRebuild, storeRebuildBudget, storeRebuildStatus } from './store-rebuild.js';
|
|
14
14
|
import { PUSH_HOLD_TTL_MS, runStoreDriverRollout, storeDriverRelease, storedReleaseLoader } from './store-releases.js';
|
|
@@ -25,7 +25,7 @@ import { NON_PROBLEM_REFUSAL, coded, mapError, relayed } from './errors.js';
|
|
|
25
25
|
import { maskDump, maskRecords } from './mask.js';
|
|
26
26
|
import { createPseudonymizer } from './pseudonymize.js';
|
|
27
27
|
import { openDump, sealDump } from './seal.js';
|
|
28
|
-
import { assertSandboxContract, verticalUploadBindings, migrationsDigestBindings, deployManifest, storedDeployManifest, pushedPermissionRegistry, deploymentRefFor, stableDeploymentRefFor, nextMigrationTag, upstreamStatusOf, } from './deploy.js';
|
|
28
|
+
import { assertSandboxContract, verticalUploadBindings, migrationsDigestBindings, deployManifest, storedDeployManifest, pushedOwnerGrantProblems, pushedPermissionRegistry, deploymentRefFor, stableDeploymentRefFor, nextMigrationTag, upstreamStatusOf, } from './deploy.js';
|
|
29
29
|
/**
|
|
30
30
|
* Answer with a problem document (#113 phase 4).
|
|
31
31
|
*
|
|
@@ -68,6 +68,7 @@ import { STORAGE_PAGE_DEFAULT, STORAGE_PAGE_MAX, readStoragePage } from './stora
|
|
|
68
68
|
import { queryLakeEvents } from './lake-gateway.js';
|
|
69
69
|
import { LakeQueryError } from './r2-sql-engine.js';
|
|
70
70
|
import { isCustomHostname, validateBindableHostname, } from './custom-hostnames.js';
|
|
71
|
+
import { isSocialRelayVertical, reconcileScopeSocialRelay, relayHostnames, } from './social-relay.js';
|
|
71
72
|
/**
|
|
72
73
|
* Response headers carrying the CLI version advisory (`ControlPlaneApiOptions.cliAdvisory`).
|
|
73
74
|
* The CLI reads these by the same spelling (`packages/cli/src/version.ts`); exported so a
|
|
@@ -2276,6 +2277,48 @@ export function createControlPlaneApi(options) {
|
|
|
2276
2277
|
open: (items) => c.var.admin.openSubjectPayloads(c.get('actor'), tenantId, scopeId, items),
|
|
2277
2278
|
});
|
|
2278
2279
|
const verticalForScope = async (c, scope) => (await deploymentForScope(c, scope))?.client;
|
|
2280
|
+
/**
|
|
2281
|
+
* Reconcile one install's client at the social relay (#1544). Skips — never throws for — an
|
|
2282
|
+
* install the relay is not for: not configured here, not an Auth Server, or no deployment to
|
|
2283
|
+
* deliver to. A relay or delivery failure DOES throw, so a staff route can report it.
|
|
2284
|
+
*/
|
|
2285
|
+
const reconcileRelayFor = async (c, tenantId, scopeId) => {
|
|
2286
|
+
if (!options.socialRelay)
|
|
2287
|
+
return { status: 'skipped', reason: 'no social relay is configured on this control plane' };
|
|
2288
|
+
const actor = c.get('actor');
|
|
2289
|
+
return reconcileScopeSocialRelay({
|
|
2290
|
+
relay: options.socialRelay,
|
|
2291
|
+
getScope: (t, s) => c.var.admin.getScopeRecord(actor, tenantIdSchema.parse(t), scopeIdSchema.parse(s)),
|
|
2292
|
+
activeHostnames: async (s) => relayHostnames(await c.var.admin.listHostnames(actor, { scopeId: scopeIdSchema.parse(s), status: 'active' }), {
|
|
2293
|
+
isCustom: custom,
|
|
2294
|
+
provisioner: options.provisionHostname,
|
|
2295
|
+
}),
|
|
2296
|
+
deploymentOf: (scope) => verticalForScope(c, scope),
|
|
2297
|
+
}, tenantId, scopeId);
|
|
2298
|
+
};
|
|
2299
|
+
/**
|
|
2300
|
+
* After a hostname of an Auth Server install became active: register it at the relay. Best
|
|
2301
|
+
* effort, and awaited rather than deferred — the route that activated the hostname has done its
|
|
2302
|
+
* job either way, and a failure here is logged and repaired by the next trigger or a staff run.
|
|
2303
|
+
* Awaited so two activations of one install never reconcile concurrently.
|
|
2304
|
+
*/
|
|
2305
|
+
const relayAfterActivation = async (c, before, after) => {
|
|
2306
|
+
if (!options.socialRelay || !after || after.status !== 'active' || before?.status === 'active')
|
|
2307
|
+
return;
|
|
2308
|
+
if (!isSocialRelayVertical(after.verticalSlug))
|
|
2309
|
+
return;
|
|
2310
|
+
try {
|
|
2311
|
+
const outcome = await reconcileRelayFor(c, after.tenantId, after.scopeId);
|
|
2312
|
+
console.log('social-relay.reconciled', { scopeId: after.scopeId, trigger: 'hostname-active', ...outcome });
|
|
2313
|
+
}
|
|
2314
|
+
catch (e) {
|
|
2315
|
+
console.error('social-relay.reconcile.failed', {
|
|
2316
|
+
scopeId: after.scopeId,
|
|
2317
|
+
trigger: 'hostname-active',
|
|
2318
|
+
detail: e instanceof Error ? e.message : String(e),
|
|
2319
|
+
});
|
|
2320
|
+
}
|
|
2321
|
+
};
|
|
2279
2322
|
/**
|
|
2280
2323
|
* `verticalForScope`, saying WHICH rung of the ladder chose the client (#1653).
|
|
2281
2324
|
*
|
|
@@ -2664,7 +2707,8 @@ export function createControlPlaneApi(options) {
|
|
|
2664
2707
|
await c.var.admin.recordScopeScriptCopy(actor, tenantId, scopeId, servingRef, moveId, { role: 'destination', loadStamp: restoredStamp, leaseMs: copyLeaseMs });
|
|
2665
2708
|
}
|
|
2666
2709
|
const erasureEpoch = await c.var.admin.scopeErasureEpoch(actor, tenantId, scopeId);
|
|
2667
|
-
|
|
2710
|
+
// #2450: a page at a time into the destination's stage, so a scope of any size moves.
|
|
2711
|
+
const { dump, loadStamp: sourceStamp, revision: sourceRevision } = await transferScope(source, dest, { from: scopeId }, { retry: retryTransient });
|
|
2668
2712
|
const restored = await restoreCarryingSwitches(actor, dest, tenantId, scopeId, dump, {
|
|
2669
2713
|
scopeId, exact: true, loadStamp: restoredStamp,
|
|
2670
2714
|
...(moveId ? { fence: copyRestoreFence(moveId, recordedAt, copyLeaseMs, erasureEpoch) } : {}),
|
|
@@ -2801,7 +2845,10 @@ export function createControlPlaneApi(options) {
|
|
|
2801
2845
|
// cleanup. Name it before any bytes are restored so reap and erasure can find it.
|
|
2802
2846
|
await c.var.admin.recordScopeScriptCopy(actor, scope.tenantId, scope.id, to, moveId, { role: 'destination', loadStamp: restoredStamp, leaseMs: copyLeaseMs });
|
|
2803
2847
|
const erasureEpoch = await c.var.admin.scopeErasureEpoch(actor, scope.tenantId, scope.id);
|
|
2804
|
-
|
|
2848
|
+
// #2450: a page at a time into the destination's stage, so a scope of any size moves. The
|
|
2849
|
+
// stage moves neither the destination's load stamp nor its write revision, so the marker read
|
|
2850
|
+
// next still describes the store the restore below commits into.
|
|
2851
|
+
const { dump, loadStamp: sourceStamp, revision: sourceRevision, meta } = await transferScope(source, dest, { from: scope.id }, { retry: retryTransient });
|
|
2805
2852
|
// What the destination holds now, read before the binding is checked again. The restore
|
|
2806
2853
|
// sends it back and is refused if the store moved since: another carry into the same script
|
|
2807
2854
|
// loaded it, or it went live under another carry's bind and took a write. That is a CI retry
|
|
@@ -2814,7 +2861,7 @@ export function createControlPlaneApi(options) {
|
|
|
2814
2861
|
throw new ControlPlaneError(412, `scope ${scope.id} was re-pointed while its data was being copied out of '${from}', so nothing was ` +
|
|
2815
2862
|
`moved or bound (#1722). Reload the scope and retry.`);
|
|
2816
2863
|
}
|
|
2817
|
-
if (dumpMetaValue(
|
|
2864
|
+
if (dumpMetaValue(meta, CARRIED_AWAY_KEY) !== null) {
|
|
2818
2865
|
throw new ControlPlaneError(412, `the copy of scope ${scope.id} in '${from}' was already carried to another script and wiped, so nothing ` +
|
|
2819
2866
|
`was moved or bound (#1722). Reload the scope and retry.`);
|
|
2820
2867
|
}
|
|
@@ -3186,8 +3233,8 @@ export function createControlPlaneApi(options) {
|
|
|
3186
3233
|
await releaseIfLive(c, scope, versionId, carried, carried.dest, carried.to);
|
|
3187
3234
|
let sourceMarker = { loadStamp: carried.sourceStamp, revision: carried.sourceRevision };
|
|
3188
3235
|
if (await isCarriedAway(carried.dest, scope)) {
|
|
3189
|
-
const {
|
|
3190
|
-
if (dumpMetaValue(
|
|
3236
|
+
const { dump, loadStamp: stamp, revision, meta } = await transferScope(carried.source, carried.dest, { from: scope.id }, { retry: retryTransient });
|
|
3237
|
+
if (dumpMetaValue(meta, CARRIED_AWAY_KEY) !== null) {
|
|
3191
3238
|
throw new ControlPlaneError(500, `both copies of scope ${scope.id} hold the carried_away tombstone; nothing was wiped`);
|
|
3192
3239
|
}
|
|
3193
3240
|
// The re-carry is a copy move of its own (#1722): in the ledger and leased before it
|
|
@@ -6364,6 +6411,10 @@ export function createControlPlaneApi(options) {
|
|
|
6364
6411
|
if (!registry.success)
|
|
6365
6412
|
return refuseManifest(registry.error.issues[0], ['registry']);
|
|
6366
6413
|
}
|
|
6414
|
+
// #2430: an owner grant is a person's, so it holds no key the registry reserves.
|
|
6415
|
+
const ownerGrants = pushedOwnerGrantProblems(checked.data);
|
|
6416
|
+
if (ownerGrants.length > 0)
|
|
6417
|
+
return refuseManifest({ path: ['ownerGrants'], message: ownerGrants.join('; ') });
|
|
6367
6418
|
}
|
|
6368
6419
|
await c.var.admin.publishVersion(c.get('actor'), input);
|
|
6369
6420
|
const version = await c.var.admin.getVersion(c.get('actor'), input.id, slug);
|
|
@@ -7066,6 +7117,10 @@ export function createControlPlaneApi(options) {
|
|
|
7066
7117
|
if (typeof raw !== 'string')
|
|
7067
7118
|
return refuse(c, 'validation_failed', 'missing manifest part');
|
|
7068
7119
|
const manifest = deployManifest.parse(JSON.parse(raw));
|
|
7120
|
+
// #2430: an owner grant is a person's, so it holds no key the registry reserves.
|
|
7121
|
+
const ownerGrants = pushedOwnerGrantProblems(manifest);
|
|
7122
|
+
if (ownerGrants.length > 0)
|
|
7123
|
+
return refuse(c, 'validation_failed', `manifest ownerGrants: ${ownerGrants.join('; ')}`);
|
|
7069
7124
|
// §4 sandbox contract, before anything reaches the namespace.
|
|
7070
7125
|
assertSandboxContract(manifest, options.storeDrivers);
|
|
7071
7126
|
// #2339: a push whose migration digest is not the one its migrations give is refused here,
|
|
@@ -8042,8 +8097,52 @@ export function createControlPlaneApi(options) {
|
|
|
8042
8097
|
// Re-read so the response carries the post-issuance status + DNS records the caller
|
|
8043
8098
|
// (dashboard / CLI) renders — a custom bind comes back `verifying` with records.
|
|
8044
8099
|
const out = (await c.var.admin.listHostnames(c.get('actor'), { scopeId: input.scopeId })).find((h) => h.hostname === input.hostname);
|
|
8100
|
+
// An install's platform hostname binds active here, which is what makes this the
|
|
8101
|
+
// install-time trigger for an Auth Server's relay client (#1544).
|
|
8102
|
+
await relayAfterActivation(c, undefined, out);
|
|
8045
8103
|
return c.json(out ?? bound, 201);
|
|
8046
8104
|
});
|
|
8105
|
+
// -- platform-provided social sign-in (#1544) --------------------------------
|
|
8106
|
+
// Staff only: on neither BUILDER_ROUTES nor TENANT_ROUTES, so both default-deny them. The
|
|
8107
|
+
// automatic trigger is a hostname becoming active (`relayAfterActivation`); these are the
|
|
8108
|
+
// levers for everything else — one install, or every Auth Server install after the relay
|
|
8109
|
+
// gained or lost a provider.
|
|
8110
|
+
app.post('/tenants/:tenantId/scopes/:scopeId/social-relay', async (c) => {
|
|
8111
|
+
if (!options.socialRelay)
|
|
8112
|
+
return refuseStatus(c, 501, 'no social relay is configured on this control plane');
|
|
8113
|
+
const tenantId = tenantIdSchema.parse(c.req.param('tenantId'));
|
|
8114
|
+
const scopeId = scopeIdSchema.parse(c.req.param('scopeId'));
|
|
8115
|
+
return c.json(await reconcileRelayFor(c, tenantId, scopeId));
|
|
8116
|
+
});
|
|
8117
|
+
app.post('/social-relay/reconcile', async (c) => {
|
|
8118
|
+
if (!options.socialRelay)
|
|
8119
|
+
return refuseStatus(c, 501, 'no social relay is configured on this control plane');
|
|
8120
|
+
const results = [];
|
|
8121
|
+
for (const vertical of SOCIAL_RELAY_VERTICALS) {
|
|
8122
|
+
const scopes = await c.var.admin.listScopes(c.get('actor'), { vertical, status: ['active'] });
|
|
8123
|
+
// One install at a time: each is a relay call and a delivery, and a fleet in parallel
|
|
8124
|
+
// would be a burst at the relay's single Durable Object for no gain.
|
|
8125
|
+
for (const scope of scopes) {
|
|
8126
|
+
try {
|
|
8127
|
+
results.push({ tenantId: scope.tenantId, scopeId: scope.id, ...(await reconcileRelayFor(c, scope.tenantId, scope.id)) });
|
|
8128
|
+
}
|
|
8129
|
+
catch (e) {
|
|
8130
|
+
results.push({
|
|
8131
|
+
tenantId: scope.tenantId,
|
|
8132
|
+
scopeId: scope.id,
|
|
8133
|
+
status: 'failed',
|
|
8134
|
+
reason: e instanceof Error ? e.message : String(e),
|
|
8135
|
+
});
|
|
8136
|
+
}
|
|
8137
|
+
}
|
|
8138
|
+
}
|
|
8139
|
+
return c.json({
|
|
8140
|
+
delivered: results.filter((r) => r.status === 'delivered').length,
|
|
8141
|
+
skipped: results.filter((r) => r.status === 'skipped').length,
|
|
8142
|
+
failed: results.filter((r) => r.status === 'failed').length,
|
|
8143
|
+
results,
|
|
8144
|
+
});
|
|
8145
|
+
});
|
|
8047
8146
|
// Re-poll a custom hostname's issuance ("check again" in the dashboard). Tenant-narrowed
|
|
8048
8147
|
// like the other hostname routes; a platform mint or an already-active row is a no-op
|
|
8049
8148
|
// re-affirm. Idempotent and safe to hammer — it just reflects Cloudflare's current state.
|
|
@@ -8056,7 +8155,9 @@ export function createControlPlaneApi(options) {
|
|
|
8056
8155
|
if (!row)
|
|
8057
8156
|
return refuse(c, 'not_found', `unknown hostname: ${name.toLowerCase()}`);
|
|
8058
8157
|
await runIssuance(c.var.admin, c.get('actor'), row);
|
|
8059
|
-
|
|
8158
|
+
const after = await hostnameRow(c, name);
|
|
8159
|
+
await relayAfterActivation(c, row, after);
|
|
8160
|
+
return c.json(after);
|
|
8060
8161
|
});
|
|
8061
8162
|
app.patch('/hostnames/:hostname/status', async (c) => {
|
|
8062
8163
|
const { status, note } = setHostnameStatusBody.parse(await c.req.json());
|
|
@@ -8066,8 +8167,10 @@ export function createControlPlaneApi(options) {
|
|
|
8066
8167
|
if (confinedTenant(c.get('principal')) !== null && !(await tenantHostname(c, name))) {
|
|
8067
8168
|
return refuse(c, 'not_found', `unknown hostname: ${name.toLowerCase()}`);
|
|
8068
8169
|
}
|
|
8170
|
+
const before = await hostnameRow(c, name);
|
|
8069
8171
|
await c.var.admin.setHostnameStatus(c.get('actor'), name, status, note);
|
|
8070
8172
|
const row = (await c.var.admin.listHostnames(c.get('actor'), {})).find((h) => h.hostname === name.toLowerCase());
|
|
8173
|
+
await relayAfterActivation(c, before, row);
|
|
8071
8174
|
return c.json(row);
|
|
8072
8175
|
});
|
|
8073
8176
|
// Unbind (hard-delete) a hostname row — what the orphan cleanup uses on rows
|
|
@@ -8458,6 +8561,8 @@ export function createControlPlaneApi(options) {
|
|
|
8458
8561
|
let row;
|
|
8459
8562
|
/** `fenced`: the ledger stamp and lease of this fork's restore (#1722), when it has one. */
|
|
8460
8563
|
let restore;
|
|
8564
|
+
/** #2450: the fork's data, moved into the preview's copy once the ledger names it. */
|
|
8565
|
+
let forkData = null;
|
|
8461
8566
|
/** #2009: the directory's classification of the row below, which every restore of it carries. */
|
|
8462
8567
|
const markCopyOfRow = () => {
|
|
8463
8568
|
const lineage = copyLineageOf({ kind: row.kind ?? '', forkedFrom: row.forkedFrom ?? null });
|
|
@@ -8472,7 +8577,14 @@ export function createControlPlaneApi(options) {
|
|
|
8472
8577
|
throw new ControlPlaneError(501, 'preview needs dispatch resolution for the PR version');
|
|
8473
8578
|
}
|
|
8474
8579
|
const canonical = await c.var.admin.exportScope(actor, tenantId, source.id);
|
|
8475
|
-
|
|
8580
|
+
// #2450: from a vertical, the fork's data moves a page at a time into the preview's own stage
|
|
8581
|
+
// there, so a scope of any size forks. Unstamped, as the whole export was: a fork writes
|
|
8582
|
+
// nothing into its source. Moved once, after the row and the ledger name the preview's copy
|
|
8583
|
+
// (K-31: no copied data without a record) and ahead of the restore's own retries, so a
|
|
8584
|
+
// restore blip reloads the same stage and an export fault is not recorded as a restore's.
|
|
8585
|
+
forkData = sourceClient
|
|
8586
|
+
? async () => (await transferScope(sourceClient, target, { from: source.id, to: previewId }, { retry: retryTransient, stamp: false })).dump
|
|
8587
|
+
: async () => canonical.tables;
|
|
8476
8588
|
// Directory row FIRST as `provisioning` (K-31 two-phase): a crash before the data
|
|
8477
8589
|
// copy leaves an inert row that — carrying `forkedFrom` + `expiresAt` — the GC sweep
|
|
8478
8590
|
// reaps, never copied data with no record.
|
|
@@ -8495,7 +8607,7 @@ export function createControlPlaneApi(options) {
|
|
|
8495
8607
|
// pushes a fresh version per try) — #559 (2).
|
|
8496
8608
|
// #2009: a load classifies nothing by itself, so the restore carries the directory's
|
|
8497
8609
|
// classification of the row below, as every restore onto a non-primary scope does.
|
|
8498
|
-
restore = (fenced) => target.restoreScope(tenantId, previewId,
|
|
8610
|
+
restore = (fenced, dump) => target.restoreScope(tenantId, previewId, dump ?? [], { sourceScopeId: source.id, exact: true, ...markCopyOfRow(), ...fenced });
|
|
8499
8611
|
}
|
|
8500
8612
|
else {
|
|
8501
8613
|
// A clean-room preview (#509 (b)): an EMPTY scope, no source to export. No `forkedFrom`
|
|
@@ -8541,7 +8653,8 @@ export function createControlPlaneApi(options) {
|
|
|
8541
8653
|
fenced = { loadStamp: restoredStamp, fence: copyRestoreFence(moveId, recordedAt, copyLeaseMs, erasureEpoch) };
|
|
8542
8654
|
}
|
|
8543
8655
|
const load = restore;
|
|
8544
|
-
await
|
|
8656
|
+
const dump = forkData ? await forkData() : undefined;
|
|
8657
|
+
await restoreOrRecord(() => load(fenced, dump));
|
|
8545
8658
|
}
|
|
8546
8659
|
await c.var.admin.activateScope(actor, tenantId, previewId);
|
|
8547
8660
|
// Bind the PR version. A private vertical's push self-admitted, so this is accepted; a
|