@substrat-run/adapter-cloudflare 0.39.0 → 0.40.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/control-plane-do.d.ts +13 -13
- package/dist/control-plane-do.d.ts.map +1 -1
- package/dist/control-plane-do.js +114 -32
- package/dist/control-plane-do.js.map +1 -1
- package/dist/host.d.ts +4 -2
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +66 -24
- package/dist/host.js.map +1 -1
- package/dist/index.d.ts +4 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -1
- package/dist/scope-do.d.ts.map +1 -1
- package/dist/scope-do.js +12 -3
- package/dist/scope-do.js.map +1 -1
- package/dist/scope-sweeper-do.d.ts +139 -0
- package/dist/scope-sweeper-do.d.ts.map +1 -0
- package/dist/scope-sweeper-do.js +193 -0
- package/dist/scope-sweeper-do.js.map +1 -0
- package/package.json +4 -4
package/dist/host.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ConnectionId, type ModuleId, type EntitlementGrant, type ProjectedIdentityLink, type PlatformActorId, type PrincipalId, type ResolvedIdentity, type QueryScopeInput, type ReadScopeTableInput, type RoleDefinition, type ScopeDump, type ScopeDumpTable, type ScopeId, type PlatformRequest, type PlatformRequestId, type PlatformRequestStatus, type ScopeTable, type ScopeQueryResult, type ScopeTablePage, type TenantId, type TenantStoreHandle } from '@substrat-run/contracts';
|
|
2
|
-
import { type ExecutorDeadLetter, type ExecutorDrainReport, type ExecutorHandler, type ExecutorRetryPolicy, type MigrateScopeOutcome, type MigrationFrontier, type ConnectorHandler, type ConnectorOptions, type FetchLike, type SecretBox, type HostAdmin, type ModuleRegistration, type OperationHandler, type PermissionChecker, type ProvisionScopeInput, type ScheduleRegistration, type ScheduleRunReport, type ScopeHost, type ScopeStub, type TenantRelationalStore, type TenantStoreProvisionInput } from '@substrat-run/kernel';
|
|
2
|
+
import { type ExecutorDeadLetter, type ExecutorDrainReport, type ExecutorHandler, type ExecutorRetryPolicy, type MigrateScopeOutcome, type MigrationFrontier, type ConnectorHandler, type ConnectorOptions, type FetchLike, type SecretBox, type HostAdmin, type ModuleRegistration, type OperationHandler, type PermissionChecker, type ProvisionScopeInput, type ScheduleRegistration, type ScheduleRunReport, type ScopeHost, type ScopeStub, type ScopeStubOptions, type TenantRelationalStore, type TenantStoreProvisionInput } from '@substrat-run/kernel';
|
|
3
3
|
import { type D1TenantStores } from './d1.js';
|
|
4
4
|
export interface CloudflareScopeHostOptions {
|
|
5
5
|
scope: DurableObjectNamespace;
|
|
@@ -54,6 +54,8 @@ export declare class CloudflareScopeHost implements ScopeHost {
|
|
|
54
54
|
readonly admin: HostAdmin;
|
|
55
55
|
private readonly scopeNs;
|
|
56
56
|
private readonly cp;
|
|
57
|
+
/** No control plane bound — `this.cp` is the throwing null object (Phase 3, CP-less). */
|
|
58
|
+
private readonly cpLess;
|
|
57
59
|
/** Project + evaluate permissions scope-locally (scope-local-permissions.md). */
|
|
58
60
|
private readonly scopeLocalPermissions;
|
|
59
61
|
private readonly moduleIds;
|
|
@@ -246,7 +248,7 @@ export declare class CloudflareScopeHost implements ScopeHost {
|
|
|
246
248
|
* has taken, instead of keeping a stale `schema_version` that renders as healthy.
|
|
247
249
|
*/
|
|
248
250
|
private migrateAndRecord;
|
|
249
|
-
getScope(principal: PrincipalId, tenantId: TenantId, scopeId: ScopeId): Promise<ScopeStub>;
|
|
251
|
+
getScope(principal: PrincipalId, tenantId: TenantId, scopeId: ScopeId, options?: ScopeStubOptions): Promise<ScopeStub>;
|
|
250
252
|
/**
|
|
251
253
|
* A scope stub whose authority is a CONNECTION (#97).
|
|
252
254
|
*
|
package/dist/host.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"AAAA,OAAO,EAsCL,KAAK,YAAY,EAEjB,KAAK,QAAQ,EAUb,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
|
package/dist/host.js
CHANGED
|
@@ -69,6 +69,8 @@ export class CloudflareScopeHost {
|
|
|
69
69
|
admin;
|
|
70
70
|
scopeNs;
|
|
71
71
|
cp;
|
|
72
|
+
/** No control plane bound — `this.cp` is the throwing null object (Phase 3, CP-less). */
|
|
73
|
+
cpLess;
|
|
72
74
|
/** Project + evaluate permissions scope-locally (scope-local-permissions.md). */
|
|
73
75
|
scopeLocalPermissions;
|
|
74
76
|
// Registration-mechanics bookkeeping (validation only — the DO executes).
|
|
@@ -112,6 +114,7 @@ export class CloudflareScopeHost {
|
|
|
112
114
|
this.fetchImpl = options.fetch ?? ((input, init) => globalThis.fetch(input, init));
|
|
113
115
|
this.scopeLocalPermissions = options.scopeLocalPermissions ?? false;
|
|
114
116
|
this.scopeNs = options.scope;
|
|
117
|
+
this.cpLess = !options.controlPlane;
|
|
115
118
|
this.cp = options.controlPlane
|
|
116
119
|
? options.controlPlane.get(options.controlPlane.idFromName('control-plane'))
|
|
117
120
|
: nullControlPlane();
|
|
@@ -678,12 +681,12 @@ export class CloudflareScopeHost {
|
|
|
678
681
|
throw err;
|
|
679
682
|
}
|
|
680
683
|
}
|
|
681
|
-
async getScope(principal, tenantId, scopeId) {
|
|
684
|
+
async getScope(principal, tenantId, scopeId, options) {
|
|
682
685
|
// Lifecycle gates (control-plane.md §4.1/§4.2), the K-3 fail-closed path,
|
|
683
686
|
// evaluated durably in the ControlPlaneDO. A throw propagates here.
|
|
684
687
|
await this.cp.validateScopeAccess(tenantId, scopeId);
|
|
685
688
|
await this.migrateAndRecord(scopeId);
|
|
686
|
-
return this.buildStub(tenantId, scopeId, principal);
|
|
689
|
+
return this.buildStub(tenantId, scopeId, principal, undefined, undefined, options);
|
|
687
690
|
}
|
|
688
691
|
/**
|
|
689
692
|
* A scope stub whose authority is a CONNECTION (#97).
|
|
@@ -741,10 +744,15 @@ export class CloudflareScopeHost {
|
|
|
741
744
|
if (!schedules || schedules.length === 0)
|
|
742
745
|
return report;
|
|
743
746
|
// Only run on a live scope of this tenant; a scope archived between the sweep's
|
|
744
|
-
// enumeration and here simply has nothing due.
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
|
|
747
|
+
// enumeration and here simply has nothing due. A CP-less host has no directory
|
|
748
|
+
// to ask (#461) — it already trusts the router-asserted (tenant, scope) for the
|
|
749
|
+
// whole request path, and lifecycle for its scopes lives wherever provisioning
|
|
750
|
+
// does, so the grant check below is the only gate it can and does enforce.
|
|
751
|
+
if (!this.cpLess) {
|
|
752
|
+
const rec = await this.cp.getScopeRecord(tenantId, scopeId);
|
|
753
|
+
if (!rec || rec.status !== 'active')
|
|
754
|
+
return report;
|
|
755
|
+
}
|
|
748
756
|
const stub = this.scopeStub(scopeId);
|
|
749
757
|
// The grant IS the switch (#383): run only where the scope holds a live
|
|
750
758
|
// `system:<moduleId>` grant. Skips a foreign-vertical scope and a per-tenant
|
|
@@ -779,7 +787,7 @@ export class CloudflareScopeHost {
|
|
|
779
787
|
return report;
|
|
780
788
|
}
|
|
781
789
|
/** The stub body, shared by the principal, connection, and system doors. */
|
|
782
|
-
buildStub(tenantId, scopeId, principal, connectionId, systemModuleId) {
|
|
790
|
+
buildStub(tenantId, scopeId, principal, connectionId, systemModuleId, options) {
|
|
783
791
|
const stub = this.scopeStub(scopeId);
|
|
784
792
|
const cp = this.cp;
|
|
785
793
|
const operationEntitlement = this.operationEntitlement;
|
|
@@ -802,9 +810,13 @@ export class CloudflareScopeHost {
|
|
|
802
810
|
if (requiredKey && !(await cp.tenantHoldsEntitlement(tenantId, requiredKey))) {
|
|
803
811
|
return Promise.reject(new Error(`operation not entitled: ${operation} — tenant does not hold '${requiredKey}'`));
|
|
804
812
|
}
|
|
805
|
-
const
|
|
813
|
+
const envelope = await stub.invoke(operation, input, asPrincipalId, tenantId, scopeId, connectionId, requiredKey, systemModuleId);
|
|
806
814
|
await this.drainExecutors(tenantId, scopeId);
|
|
807
|
-
|
|
815
|
+
// #458: the operation committed having enqueued platform intents — tell the
|
|
816
|
+
// caller's harness so it can flag the response for the router kick (#381).
|
|
817
|
+
if (envelope.platformRequests > 0)
|
|
818
|
+
options?.onPlatformRequests?.(envelope.platformRequests);
|
|
819
|
+
return envelope.result;
|
|
808
820
|
},
|
|
809
821
|
};
|
|
810
822
|
}
|
|
@@ -933,7 +945,13 @@ export class CloudflareScopeHost {
|
|
|
933
945
|
await this.fanOut(tenantId); // role definitions are projected into the tenant's scopes
|
|
934
946
|
},
|
|
935
947
|
listRoles: async (actor, filter) => {
|
|
936
|
-
const rows = await this.cp.listRoles({
|
|
948
|
+
const rows = await this.cp.listRoles({
|
|
949
|
+
tenantId: filter?.tenantId,
|
|
950
|
+
source: filter?.source,
|
|
951
|
+
limit: filter?.limit,
|
|
952
|
+
cursor: filter?.cursor,
|
|
953
|
+
order: filter?.order,
|
|
954
|
+
});
|
|
937
955
|
await this.recordAccess(actor, 'listRoles', { tenantId: filter?.tenantId ?? null }, filter, rows.length);
|
|
938
956
|
// Parsed, not cast — the same parse the pure adapter does, which is what
|
|
939
957
|
// makes the shared contract suite mean anything.
|
|
@@ -1110,6 +1128,9 @@ export class CloudflareScopeHost {
|
|
|
1110
1128
|
tenantId: filter?.tenantId,
|
|
1111
1129
|
scopeId: filter?.scopeId,
|
|
1112
1130
|
status: filter?.status,
|
|
1131
|
+
limit: filter?.limit,
|
|
1132
|
+
cursor: filter?.cursor,
|
|
1133
|
+
order: filter?.order,
|
|
1113
1134
|
});
|
|
1114
1135
|
await this.recordAccess(actor, 'listHostnames', { tenantId: filter?.tenantId ?? null, scopeId: filter?.scopeId ?? null }, filter, rows.length);
|
|
1115
1136
|
return rows.map(mapHostname);
|
|
@@ -1161,9 +1182,9 @@ export class CloudflareScopeHost {
|
|
|
1161
1182
|
await this.cp.insertVertical(parsed.slug, parsed.name, parsed.source, parsed.ownerTenant, envSpecJson, installSpecJson, parsed.listed ? 1 : 0, new Date().toISOString());
|
|
1162
1183
|
await this.recordAdmin(actor, 'registerVertical', { tenantId: null }, null, parsed);
|
|
1163
1184
|
},
|
|
1164
|
-
listVerticals: async (actor) => {
|
|
1165
|
-
const rows = await this.cp.listVerticals();
|
|
1166
|
-
await this.recordAccess(actor, 'listVerticals', {}, null, rows.length);
|
|
1185
|
+
listVerticals: async (actor, page) => {
|
|
1186
|
+
const rows = await this.cp.listVerticals(page);
|
|
1187
|
+
await this.recordAccess(actor, 'listVerticals', {}, page ?? null, rows.length);
|
|
1167
1188
|
return rows.map(mapVertical);
|
|
1168
1189
|
},
|
|
1169
1190
|
publishVersion: async (actor, input) => {
|
|
@@ -1192,8 +1213,8 @@ export class CloudflareScopeHost {
|
|
|
1192
1213
|
admission: selfAdmits ? 'admitted' : 'pending',
|
|
1193
1214
|
});
|
|
1194
1215
|
},
|
|
1195
|
-
listVersions: async (actor, verticalSlug) => {
|
|
1196
|
-
const rows = await this.cp.listVersions(verticalSlug);
|
|
1216
|
+
listVersions: async (actor, verticalSlug, page) => {
|
|
1217
|
+
const rows = await this.cp.listVersions(verticalSlug, page);
|
|
1197
1218
|
await this.recordAccess(actor, 'listVersions', {}, { verticalSlug }, rows.length);
|
|
1198
1219
|
return rows.map(mapVersion);
|
|
1199
1220
|
},
|
|
@@ -1355,8 +1376,8 @@ export class CloudflareScopeHost {
|
|
|
1355
1376
|
}
|
|
1356
1377
|
await this.recordAdmin(actor, 'promoteVersion', { tenantId: null, vertical: verticalSlug }, outgoing ? { versionId: outgoing.id, version: outgoing.version } : null, { channel, versionId, version: incoming.version, acknowledged: ack });
|
|
1357
1378
|
},
|
|
1358
|
-
listChannels: async (actor, verticalSlug) => {
|
|
1359
|
-
const rows = await this.cp.listChannels(verticalSlug);
|
|
1379
|
+
listChannels: async (actor, verticalSlug, page) => {
|
|
1380
|
+
const rows = await this.cp.listChannels(verticalSlug, page);
|
|
1360
1381
|
// The serving script runs ONE version (#286); surface it on the prod row so a
|
|
1361
1382
|
// failed in-place serve (channel moved, serve did not) reads honestly instead of
|
|
1362
1383
|
// claiming the new version is live (#321).
|
|
@@ -1370,8 +1391,8 @@ export class CloudflareScopeHost {
|
|
|
1370
1391
|
servingVersionId: r.channel === 'prod' ? serving : null,
|
|
1371
1392
|
}));
|
|
1372
1393
|
},
|
|
1373
|
-
listChannelHistory: async (actor, verticalSlug, channel) => {
|
|
1374
|
-
const rows = await this.cp.listChannelHistory(verticalSlug, channel);
|
|
1394
|
+
listChannelHistory: async (actor, verticalSlug, channel, page) => {
|
|
1395
|
+
const rows = await this.cp.listChannelHistory(verticalSlug, channel, page);
|
|
1375
1396
|
await this.recordAccess(actor, 'listChannelHistory', {}, { verticalSlug, channel }, rows.length);
|
|
1376
1397
|
return rows.map((r) => channelHistoryEntry.parse({
|
|
1377
1398
|
id: r.id,
|
|
@@ -1547,10 +1568,10 @@ export class CloudflareScopeHost {
|
|
|
1547
1568
|
const before = await this.cp.reapTenant(tenantId);
|
|
1548
1569
|
await this.recordAdmin(actor, 'reapTenant', { tenantId }, { status: before }, { status: 'reaped' });
|
|
1549
1570
|
},
|
|
1550
|
-
listTenants: async (actor) => {
|
|
1551
|
-
const tenants = (await this.cp.listTenants()).map((t) => tenantSchema.parse(t));
|
|
1571
|
+
listTenants: async (actor, page) => {
|
|
1572
|
+
const tenants = (await this.cp.listTenants(page)).map((t) => tenantSchema.parse(t));
|
|
1552
1573
|
// Enumerating every tenant on the platform is the read this log exists for.
|
|
1553
|
-
await this.recordAccess(actor, 'listTenants', {}, null, tenants.length);
|
|
1574
|
+
await this.recordAccess(actor, 'listTenants', {}, page ?? null, tenants.length);
|
|
1554
1575
|
return tenants;
|
|
1555
1576
|
},
|
|
1556
1577
|
getTenant: async (actor, tenantId) => {
|
|
@@ -1567,6 +1588,9 @@ export class CloudflareScopeHost {
|
|
|
1567
1588
|
: [filter.status]
|
|
1568
1589
|
: undefined,
|
|
1569
1590
|
vertical: filter?.vertical,
|
|
1591
|
+
limit: filter?.limit,
|
|
1592
|
+
cursor: filter?.cursor,
|
|
1593
|
+
order: filter?.order,
|
|
1570
1594
|
});
|
|
1571
1595
|
await this.recordAccess(actor, 'listScopes', { tenantId: filter?.tenantId ?? null }, filter, rows.length);
|
|
1572
1596
|
return rows.map(mapScope);
|
|
@@ -1812,8 +1836,8 @@ export class CloudflareScopeHost {
|
|
|
1812
1836
|
return; // idempotent, and a no-op is not audited
|
|
1813
1837
|
await this.recordAdmin(actor, 'revokeConnection', { tenantId: row.tenant_id, vertical: row.vertical }, { status: row.status }, { id, provider: row.provider, status: 'revoked', revokedAt: now });
|
|
1814
1838
|
},
|
|
1815
|
-
openConnection: async (tenantId, vertical, provider) => {
|
|
1816
|
-
const row = await this.cp.readLiveConnection(tenantId, vertical, provider);
|
|
1839
|
+
openConnection: async (tenantId, vertical, provider, externalAccountRef) => {
|
|
1840
|
+
const row = await this.cp.readLiveConnection(tenantId, vertical, provider, externalAccountRef);
|
|
1817
1841
|
if (!row)
|
|
1818
1842
|
return undefined;
|
|
1819
1843
|
const secret = connectionSecret.parse(JSON.parse(await this.secretBox.open({ keyId: row.key_id, ciphertext: row.ciphertext })));
|
|
@@ -1889,6 +1913,8 @@ export class CloudflareScopeHost {
|
|
|
1889
1913
|
tenantId: filter?.tenantId,
|
|
1890
1914
|
method: filter?.method,
|
|
1891
1915
|
limit: filter?.limit,
|
|
1916
|
+
cursor: filter?.cursor,
|
|
1917
|
+
order: filter?.order,
|
|
1892
1918
|
});
|
|
1893
1919
|
// Reading the access log is itself a read. Recorded before returning, so
|
|
1894
1920
|
// the row describing this call is not in its own result.
|
|
@@ -2069,6 +2095,22 @@ export class CloudflareScopeHost {
|
|
|
2069
2095
|
object: `scope:${input.scopeId}`,
|
|
2070
2096
|
expires_at: null,
|
|
2071
2097
|
},
|
|
2098
|
+
// #461: each registered module's SCHEDULE grants (#383) ride the same unit —
|
|
2099
|
+
// the CP-less mirror of `provisionScope`'s writeTuple loop. Without them the
|
|
2100
|
+
// grant-is-the-switch check makes every schedule a silent no-op (`fired: 0`,
|
|
2101
|
+
// no error — the #49 unfalsifiable zero).
|
|
2102
|
+
...[...this.moduleSchedules].flatMap(([modId, schedules]) => {
|
|
2103
|
+
const perms = new Set();
|
|
2104
|
+
for (const s of schedules)
|
|
2105
|
+
for (const p of s.permissions)
|
|
2106
|
+
perms.add(p);
|
|
2107
|
+
return [...perms].map((perm) => ({
|
|
2108
|
+
subject: `system:${modId}`,
|
|
2109
|
+
relation: `granted:${perm}`,
|
|
2110
|
+
object: `scope:${input.scopeId}`,
|
|
2111
|
+
expires_at: null,
|
|
2112
|
+
}));
|
|
2113
|
+
}),
|
|
2072
2114
|
],
|
|
2073
2115
|
// #406: identity links, delivered by the platform with provisioning exactly as
|
|
2074
2116
|
// entitlements are (#310). Preserve-on-undefined, so an absent field never wipes
|