@substrat-run/adapter-cloudflare 0.52.0 → 0.54.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 +68 -1
- package/dist/control-plane-do.d.ts.map +1 -1
- package/dist/control-plane-do.js +167 -0
- package/dist/control-plane-do.js.map +1 -1
- package/dist/host.d.ts +12 -0
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +118 -4
- package/dist/host.js.map +1 -1
- package/dist/scope-do.d.ts.map +1 -1
- package/dist/scope-do.js +25 -0
- package/dist/scope-do.js.map +1 -1
- package/package.json +4 -4
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,
|
|
1
|
+
{"version":3,"file":"host.d.ts","sourceRoot":"","sources":["../src/host.ts"],"names":[],"mappings":"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"}
|
package/dist/host.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { accessLogEntry, adminLogEntry, attachmentRecord, createTenantInput, identityLink, identityPool, createOrgInput, promotionAcknowledgement, bindHostnameInput, channelHistoryEntry, hostnameBinding, publishVersionInput, AUTO_ADMISSION_NOTE, registerVerticalInput, vertical as verticalSchema, verticalServingState, verticalChannel, verticalVersion, connection, connectionGrant, connectionSecret, systemGrant, entitlementGrant, entitlementGrantInput, instant, meterReading, subjectRef, createConnectionInput, moduleManifest, org as orgSchema, orgMembership, resolvedIdentity, roleDefinition, scope as scopeSchema, tenant as tenantSchema, tenantRole, platformRequest, } from '@substrat-run/contracts';
|
|
1
|
+
import { accessLogEntry, adminLogEntry, opsFailureEntry, attachmentRecord, createTenantInput, identityLink, identityPool, createOrgInput, promotionAcknowledgement, bindHostnameInput, channelHistoryEntry, hostnameBinding, publishVersionInput, AUTO_ADMISSION_NOTE, registerVerticalInput, vertical as verticalSchema, verticalServingState, verticalChannel, verticalVersion, connection, connectionGrant, connectionSecret, systemGrant, entitlementGrant, entitlementGrantInput, instant, meterReading, subjectRef, createConnectionInput, moduleManifest, org as orgSchema, orgMembership, resolvedIdentity, roleDefinition, scope as scopeSchema, tenant as tenantSchema, tenantRole, subjectShredReceipt, platformRequest, } from '@substrat-run/contracts';
|
|
2
2
|
import { normalizeHostname, toRouteTarget } from './route-resolver.js';
|
|
3
|
-
import { attachmentBlobKey, foldMeterReading, resolveScopeRecord, ulid, backoffAt, resolveRetryPolicy, unconfiguredSecretBox, } from '@substrat-run/kernel';
|
|
3
|
+
import { attachmentBlobKey, foldMeterReading, parseValidationRecords, resolveScopeRecord, ulid, backoffAt, resolveRetryPolicy, unconfiguredSecretBox, createSubjectKeys, } from '@substrat-run/kernel';
|
|
4
4
|
import { tenantStoreDatabaseName } from './d1.js';
|
|
5
5
|
import { blobStoreBucketName, r2TenantBlobStore } from './r2.js';
|
|
6
6
|
/** DO row → contract shape. Never reads the secrets table — that is the split. */
|
|
@@ -1005,7 +1005,7 @@ export class CloudflareScopeHost {
|
|
|
1005
1005
|
canonical: r.canonical === 1,
|
|
1006
1006
|
createdAt: r.created_at,
|
|
1007
1007
|
customHostnameId: r.custom_hostname_id,
|
|
1008
|
-
validationRecords:
|
|
1008
|
+
validationRecords: parseValidationRecords(r.validation_records),
|
|
1009
1009
|
});
|
|
1010
1010
|
const mapVertical = (r) => verticalSchema.parse({
|
|
1011
1011
|
slug: r.slug,
|
|
@@ -1296,6 +1296,7 @@ export class CloudflareScopeHost {
|
|
|
1296
1296
|
tenantId: filter?.tenantId,
|
|
1297
1297
|
scopeId: filter?.scopeId,
|
|
1298
1298
|
status: filter?.status,
|
|
1299
|
+
verticalSlug: filter?.verticalSlug,
|
|
1299
1300
|
limit: filter?.limit,
|
|
1300
1301
|
cursor: filter?.cursor,
|
|
1301
1302
|
order: filter?.order,
|
|
@@ -1389,6 +1390,13 @@ export class CloudflareScopeHost {
|
|
|
1389
1390
|
await this.recordAccess(actor, 'listVersions', {}, { verticalSlug }, rows.length);
|
|
1390
1391
|
return rows.map(mapVersion);
|
|
1391
1392
|
},
|
|
1393
|
+
getVersion: async (actor, versionId, verticalSlug) => {
|
|
1394
|
+
const row = await this.cp.readVersion(versionId);
|
|
1395
|
+
// A version of another vertical reads as absent when the caller named one.
|
|
1396
|
+
const hit = row && (verticalSlug === undefined || row.vertical_slug === verticalSlug) ? row : undefined;
|
|
1397
|
+
await this.recordAccess(actor, 'getVersion', {}, { versionId, verticalSlug }, hit ? 1 : 0);
|
|
1398
|
+
return hit ? mapVersion(hit) : undefined;
|
|
1399
|
+
},
|
|
1392
1400
|
setVerticalListed: async (actor, slug, listed) => {
|
|
1393
1401
|
const existing = await this.cp.readVertical(slug);
|
|
1394
1402
|
if (!existing)
|
|
@@ -1941,6 +1949,42 @@ export class CloudflareScopeHost {
|
|
|
1941
1949
|
backupRef: opts?.backupRef ?? null,
|
|
1942
1950
|
});
|
|
1943
1951
|
},
|
|
1952
|
+
// -- subject erasure (#37) ----------------------------------------------
|
|
1953
|
+
sealSubjectPayloads: async (actor, tenantId, scopeId, items) => {
|
|
1954
|
+
await this.assertScope(tenantId, scopeId);
|
|
1955
|
+
const sealed = await this.subjectKeysFor(tenantId, scopeId).sealMany(items);
|
|
1956
|
+
await this.recordAccess(actor, 'sealSubjectPayloads', { tenantId, scopeId }, { subjects: new Set(items.map((i) => i.subjectId)).size }, sealed.filter((s) => s !== null).length);
|
|
1957
|
+
return sealed;
|
|
1958
|
+
},
|
|
1959
|
+
openSubjectPayloads: async (actor, tenantId, scopeId, items) => {
|
|
1960
|
+
await this.assertScope(tenantId, scopeId);
|
|
1961
|
+
const opened = await this.subjectKeysFor(tenantId, scopeId).openMany(items);
|
|
1962
|
+
await this.recordAccess(actor, 'openSubjectPayloads', { tenantId, scopeId }, { subjects: new Set(items.map((i) => i.subjectId)).size }, opened.filter((o) => o !== null).length);
|
|
1963
|
+
return opened;
|
|
1964
|
+
},
|
|
1965
|
+
shredSubject: async (actor, tenantId, scopeId, subjectId) => {
|
|
1966
|
+
await this.assertScope(tenantId, scopeId);
|
|
1967
|
+
// Redact the live spine FIRST, destroy the key LAST. Both halves are idempotent and
|
|
1968
|
+
// a crash between them converges on retry, so the order is decided by which
|
|
1969
|
+
// half-done state harms the person: dying after the redaction leaves ciphertext in
|
|
1970
|
+
// a backup that no key opens; destroying the key first would leave their PII in the
|
|
1971
|
+
// live database while the audit log already claims they were erased.
|
|
1972
|
+
const eventsRedacted = await this.scopeStub(scopeId).redactSubject(subjectId);
|
|
1973
|
+
const at = new Date().toISOString();
|
|
1974
|
+
const { existed } = await this.subjectKeysFor(tenantId, scopeId).destroy(subjectId, at);
|
|
1975
|
+
const receipt = subjectShredReceipt.parse({
|
|
1976
|
+
subjectId,
|
|
1977
|
+
eventsRedacted,
|
|
1978
|
+
keyDestroyed: existed,
|
|
1979
|
+
tombstoned: true,
|
|
1980
|
+
});
|
|
1981
|
+
// BOTH logs, deliberately: the admin log because this is a mutation, the access log
|
|
1982
|
+
// because it destroys evidence. An erasure is the one action where "who asked for
|
|
1983
|
+
// this to disappear" is itself part of the record.
|
|
1984
|
+
await this.recordAdmin(actor, 'shredSubject', { tenantId, scopeId }, null, receipt);
|
|
1985
|
+
await this.recordAccess(actor, 'shredSubject', { tenantId, scopeId }, { subjectId }, eventsRedacted);
|
|
1986
|
+
return receipt;
|
|
1987
|
+
},
|
|
1944
1988
|
grantEntitlement: async (actor, tenantId, entitlementKey, plan) => {
|
|
1945
1989
|
const input = entitlementGrantInput.parse(plan ?? {});
|
|
1946
1990
|
const result = await this.cp.grantEntitlement(tenantId, entitlementKey, input, actor);
|
|
@@ -2187,6 +2231,7 @@ export class CloudflareScopeHost {
|
|
|
2187
2231
|
actor: filter?.actor,
|
|
2188
2232
|
tenantId: filter?.tenantId,
|
|
2189
2233
|
method: filter?.method,
|
|
2234
|
+
drained: filter?.drained,
|
|
2190
2235
|
limit: filter?.limit,
|
|
2191
2236
|
cursor: filter?.cursor,
|
|
2192
2237
|
order: filter?.order,
|
|
@@ -2206,10 +2251,22 @@ export class CloudflareScopeHost {
|
|
|
2206
2251
|
at: r.at,
|
|
2207
2252
|
}));
|
|
2208
2253
|
},
|
|
2254
|
+
markAccessLogDrained: async (actor, upToId, drainedAt) => {
|
|
2255
|
+
const drained = await this.cp.markAccessLogDrained(upToId, drainedAt);
|
|
2256
|
+
if (drained > 0) {
|
|
2257
|
+
// The payload is the APPLIED state, so it belongs in `after` (contracts'
|
|
2258
|
+
// adminLogEntry: before = prior state, after = the applied payload).
|
|
2259
|
+
await this.recordAdmin(actor, 'drainAccessLog', { tenantId: null }, null, { drained, upToId, drainedAt });
|
|
2260
|
+
}
|
|
2261
|
+
return drained;
|
|
2262
|
+
},
|
|
2209
2263
|
pruneAccessLog: async (actor, limit) => {
|
|
2210
2264
|
const pruned = await this.cp.pruneAccessLog(limit);
|
|
2211
2265
|
if (pruned > 0) {
|
|
2212
|
-
|
|
2266
|
+
// The payload is the APPLIED state, so it belongs in `after` (contracts'
|
|
2267
|
+
// adminLogEntry: before = prior state, after = the applied payload) — the
|
|
2268
|
+
// same shape as drainAccessLog's row above (#557).
|
|
2269
|
+
await this.recordAdmin(actor, 'pruneAccessLog', { tenantId: null }, null, { pruned });
|
|
2213
2270
|
}
|
|
2214
2271
|
return pruned;
|
|
2215
2272
|
},
|
|
@@ -2234,6 +2291,41 @@ export class CloudflareScopeHost {
|
|
|
2234
2291
|
await this.recordAccess(actor, 'auditLog', { tenantId: filter?.tenantId ?? null, scopeId: filter?.scopeId ?? null }, filter, rows.length);
|
|
2235
2292
|
return rows.map((r) => adminLogEntry.parse(r));
|
|
2236
2293
|
},
|
|
2294
|
+
recordOpsFailure: async (entry) => {
|
|
2295
|
+
await this.cp.recordOpsFailure({
|
|
2296
|
+
id: ulid(),
|
|
2297
|
+
actor: entry.actor,
|
|
2298
|
+
operation: entry.operation,
|
|
2299
|
+
stage: entry.stage ?? null,
|
|
2300
|
+
tenant_id: entry.tenantId ?? null,
|
|
2301
|
+
scope_id: entry.scopeId ?? null,
|
|
2302
|
+
vertical: entry.vertical ?? null,
|
|
2303
|
+
status: entry.status ?? null,
|
|
2304
|
+
// Bounded here, not trusted from the catch site: one runaway upstream body
|
|
2305
|
+
// must not become a runaway directory row (#559).
|
|
2306
|
+
message: entry.message.slice(0, 2000),
|
|
2307
|
+
reference: entry.reference ?? null,
|
|
2308
|
+
at: new Date().toISOString(),
|
|
2309
|
+
});
|
|
2310
|
+
},
|
|
2311
|
+
listOpsFailures: async (actor, filter) => {
|
|
2312
|
+
const rows = await this.cp.listOpsFailures({
|
|
2313
|
+
tenantId: filter?.tenantId,
|
|
2314
|
+
scopeId: filter?.scopeId,
|
|
2315
|
+
vertical: filter?.vertical,
|
|
2316
|
+
operation: filter?.operation,
|
|
2317
|
+
reference: filter?.reference,
|
|
2318
|
+
since: filter?.since,
|
|
2319
|
+
until: filter?.until,
|
|
2320
|
+
limit: filter?.limit,
|
|
2321
|
+
cursor: filter?.cursor,
|
|
2322
|
+
order: filter?.order,
|
|
2323
|
+
});
|
|
2324
|
+
// Rows can name tenants and scopes, so reading them is recorded like the
|
|
2325
|
+
// audit trail's own reads (K-24).
|
|
2326
|
+
await this.recordAccess(actor, 'listOpsFailures', { tenantId: filter?.tenantId ?? null, scopeId: filter?.scopeId ?? null }, filter, rows.length);
|
|
2327
|
+
return rows.map((r) => opsFailureEntry.parse(r));
|
|
2328
|
+
},
|
|
2237
2329
|
};
|
|
2238
2330
|
}
|
|
2239
2331
|
// -- helpers --------------------------------------------------------------
|
|
@@ -2241,6 +2333,28 @@ export class CloudflareScopeHost {
|
|
|
2241
2333
|
* Record a staff read (K-24). `params` is a bounded summary, capped so one query
|
|
2242
2334
|
* cannot write an unbounded row.
|
|
2243
2335
|
*/
|
|
2336
|
+
/**
|
|
2337
|
+
* K-3's cross-check on its own: the (tenant, scope) pair must exist and agree before a
|
|
2338
|
+
* subject-key operation touches anything. Without it a caller could reach another
|
|
2339
|
+
* tenant's keys by naming their scope id.
|
|
2340
|
+
*/
|
|
2341
|
+
async assertScope(tenantId, scopeId) {
|
|
2342
|
+
const rec = await this.cp.getScopeRecord(tenantId, scopeId);
|
|
2343
|
+
if (!rec)
|
|
2344
|
+
throw new Error(`unknown scope for tenant: (${tenantId}, ${scopeId})`);
|
|
2345
|
+
}
|
|
2346
|
+
/**
|
|
2347
|
+
* This scope's per-subject keys (#37). The crypto lives in the kernel
|
|
2348
|
+
* (`createSubjectKeys`); the adapter supplies only the three row operations, which here
|
|
2349
|
+
* are RPCs into the control-plane DO that holds the directory.
|
|
2350
|
+
*/
|
|
2351
|
+
subjectKeysFor(tenantId, scopeId) {
|
|
2352
|
+
return createSubjectKeys(this.secretBox, {
|
|
2353
|
+
read: (subjectId) => this.cp.readSubjectKey(scopeId, subjectId),
|
|
2354
|
+
insert: (subjectId, row) => this.cp.insertSubjectKey({ scopeId, subjectId, tenantId, ...row }),
|
|
2355
|
+
tombstone: (subjectId, at) => this.cp.tombstoneSubjectKey({ scopeId, subjectId, tenantId, at }),
|
|
2356
|
+
});
|
|
2357
|
+
}
|
|
2244
2358
|
async recordAccess(actor, method, target, params, resultCount) {
|
|
2245
2359
|
await this.cp.recordAccess({
|
|
2246
2360
|
id: ulid(),
|