@substrat-run/adapter-cloudflare 0.130.0 → 0.131.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 +3 -1
- package/dist/control-plane-do.d.ts.map +1 -1
- package/dist/control-plane-do.js +8 -2
- package/dist/control-plane-do.js.map +1 -1
- package/dist/host.d.ts +16 -1
- package/dist/host.d.ts.map +1 -1
- package/dist/host.js +57 -2
- package/dist/host.js.map +1 -1
- package/dist/scope-do.d.ts.map +1 -1
- package/dist/scope-do.js +61 -10
- package/dist/scope-do.js.map +1 -1
- package/dist/scope-sweeper-do.d.ts +11 -2
- package/dist/scope-sweeper-do.d.ts.map +1 -1
- package/dist/scope-sweeper-do.js +35 -1
- package/dist/scope-sweeper-do.js.map +1 -1
- package/package.json +7 -6
package/dist/scope-do.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"scope-do.d.ts","sourceRoot":"","sources":["../src/scope-do.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAcL,KAAK,WAAW,
|
|
1
|
+
{"version":3,"file":"scope-do.d.ts","sourceRoot":"","sources":["../src/scope-do.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AACnD,OAAO,EAcL,KAAK,WAAW,EAsCjB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAoCL,KAAK,SAAS,EAmBd,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,EAuEtB,MAAM,sBAAsB,CAAC;AAsF9B;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;CAC9B;AAwbD;;;GAGG;AACH,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI;IAAE,KAAK,EAAE,CAAC,CAAC;IAAC,OAAO,CAAC,EAAE,SAAS,CAAA;CAAE,GAAG;IAAE,OAAO,EAAE,WAAW,CAAA;CAAE,CAAC;AAgDxG;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAOxD;AAED,wBAAgB,kBAAkB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,EAAE,CAwDxD;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,kBAAkB,EAAE,EAC7B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,gBAAgB,CAAC,KAAK,EAAE,OAAO,CAAC,CAAC,GACxD,KAAK,GAAG,EAAE,kBAAkB,EAAE,GAAG,EAAE,UAAU,KAAK,aAAa,CAkkKjE"}
|
package/dist/scope-do.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { REWIND_REFUSED } from './rewind-refusal.js';
|
|
2
2
|
import { DurableObject } from 'cloudflare:workers';
|
|
3
3
|
import { ATTACHMENT_ADDED, ATTACHMENT_REMOVED, attachmentRecord, domainEvent, domainEventInput, eventId, instant, objectRef, entityObjectRef, assertModuleEmittableType, assertKernelAuthoredType, toWireFailure, grantRefFromProof, principalId, scopeId as scopeIdOf, tenantId as tenantIdOf, platformRequestInput, platformRequestId, MAX_PENDING_PLATFORM_REQUESTS, MAX_PENDING_SWEEP_RUNS, SWEEP_RUNS_KIND, SCOPE_TABLE_PAGE_MAX, SCOPE_QUERY_ROW_MAX, listLimitOf, requestFingerprint, substratError, assertReplayableDump, REDRAIN_BATCH, } from '@substrat-run/contracts';
|
|
4
|
-
import { ulid, DO_SQL_LIMITS, createUlid, assertAllowed, ConnectionSealingKeyUnavailableError, noSealingKeyMessage, sealTo, assertReadOnlyQuery, entitlementDenial, platformRequestHistoryQuery, platformRequestOf, PLATFORM_REQUEST_COLUMNS, PLATFORM_REQUEST_REDACTION_SQL, platformRequestRedactionParams, platformRequestRedactionQuery, intentPayloadCarriesSubject, redactSubjectJobRuns, JOB_RUN_PATCH_SQL, JOB_STEP_RECORD_SQL, DELIVERY_ERROR_REDACTION_SQL, REDACTED_DELIVERY_NOTE, seatScopeTuple, effectiveRoleGrantQuery, switchRecordedOff, switchSystemSchedules, peerGrantsStatus, systemGrantsStatus, systemScheduleState, systemSwitchedOff, denialListQuery, denialSummaryQuery, denialTotalsQuery, DENIAL_WINDOW_QUERY, mapDenialRow, mapDenialSummaryBuckets, PermissionDenied, assertImpersonationWrites, assertModuleEnqueueableKind, impersonationStampOf, createAtomic, NotSearchable, isSearchIndexTable, searchIndexDdl, searchIndexPlans, NotListable, listIndexPlans, moduleMigrations, listQuery, cursorOf, searchLimit, searchMatchExpression, searchQuery, IDEMPOTENCY_DDL, REFUSALS_DDL, refusalInsert, refusedTransitionOf, assertIdempotencyKey, assertPermissionKey, idempotencyLookupQuery, idempotencyPruneStatement, idempotencyRecordStatement, idempotencyOptedOutMessage, replayFor, entityVersionQuery, entityVersionOf, assertIfMatch, OUTBOX_ENTITY_INDEX, SCHEDULE_STATE_DDL, SCHEDULE_STATE_REBUILD, scheduleStateHasKind, VERTICAL_EVENTS_DDL, EXPORT_HOPS_SQL, IMPORT_CURSORS_SQL, IMPORT_CURSOR_OF_SQL, OUTBOX_MARK_SQL, exportedSinceQuery, emittedSinceQuery, emittedReportOf, EMITTED_REPORT_CAP, IMPORT_CURSOR_ADVANCE_SQL, IMPORT_RECORD_SQL, moveImportCursor, CrossVerticalRegistry, exportReadPlan, exportReadQuery, planExportBatch, withheldNote, JOB_RUN_DDL, jobRunListLimit, } from '@substrat-run/kernel';
|
|
4
|
+
import { ulid, DO_SQL_LIMITS, unknownRoleError, createUlid, assertAllowed, ConnectionSealingKeyUnavailableError, noSealingKeyMessage, sealTo, assertReadOnlyQuery, entitlementDenial, platformRequestHistoryQuery, platformRequestOf, PLATFORM_REQUEST_COLUMNS, PLATFORM_REQUEST_REDACTION_SQL, platformRequestRedactionParams, platformRequestRedactionQuery, intentPayloadCarriesSubject, redactSubjectJobRuns, JOB_RUN_PATCH_SQL, JOB_STEP_RECORD_SQL, DELIVERY_ERROR_REDACTION_SQL, REDACTED_DELIVERY_NOTE, seatScopeTuple, effectiveRoleGrantQuery, switchRecordedOff, switchSystemSchedules, peerGrantsStatus, systemGrantsStatus, systemScheduleState, systemSwitchedOff, denialListQuery, denialSummaryQuery, denialTotalsQuery, DENIAL_WINDOW_QUERY, mapDenialRow, mapDenialSummaryBuckets, PermissionDenied, assertImpersonationWrites, assertModuleEnqueueableKind, impersonationStampOf, createAtomic, NotSearchable, isSearchIndexTable, searchIndexDdl, searchIndexPlans, NotListable, listIndexPlans, moduleMigrations, listQuery, cursorOf, searchLimit, searchMatchExpression, searchQuery, IDEMPOTENCY_DDL, REFUSALS_DDL, refusalInsert, refusedTransitionOf, assertIdempotencyKey, assertPermissionKey, idempotencyLookupQuery, idempotencyPruneStatement, idempotencyRecordStatement, idempotencyOptedOutMessage, replayFor, entityVersionQuery, entityVersionOf, assertIfMatch, OUTBOX_ENTITY_INDEX, SCHEDULE_STATE_DDL, SCHEDULE_STATE_REBUILD, scheduleStateHasKind, VERTICAL_EVENTS_DDL, EXPORT_HOPS_SQL, IMPORT_CURSORS_SQL, IMPORT_CURSOR_OF_SQL, OUTBOX_MARK_SQL, exportedSinceQuery, emittedSinceQuery, emittedReportOf, EMITTED_REPORT_CAP, IMPORT_CURSOR_ADVANCE_SQL, IMPORT_RECORD_SQL, moveImportCursor, CrossVerticalRegistry, exportReadPlan, exportReadQuery, planExportBatch, withheldNote, JOB_RUN_DDL, jobRunListLimit, } from '@substrat-run/kernel';
|
|
5
5
|
import { isUpgradeRequest, readSubscription, LIVE_FANOUT_LIMIT, LIVE_MODE_HEADER, LIVE_PRINCIPAL_HEADER, LIVE_SCOPE_HEADER, LIVE_SUBSCRIBE_PATH, LIVE_TENANT_HEADER, } from './live-reads.js';
|
|
6
6
|
import { OperationQueue } from './serialization.js';
|
|
7
7
|
import { doScopedSql, doBuiltColumnsOf, doSpineSql } from './sql.js';
|
|
@@ -2201,6 +2201,28 @@ export function defineScopeDO(modules, bareOps) {
|
|
|
2201
2201
|
}
|
|
2202
2202
|
return record;
|
|
2203
2203
|
}
|
|
2204
|
+
/** Authorize a job's read as its registered module, never as a person. */
|
|
2205
|
+
async systemAttachmentAuthorize(attachmentId, moduleId, tenantId, scopeId) {
|
|
2206
|
+
await this.ensureMigrations();
|
|
2207
|
+
if (!this.modules.has(moduleId)) {
|
|
2208
|
+
throw toRpcError(substratError('not_found', `module not registered in this scope: ${moduleId}`));
|
|
2209
|
+
}
|
|
2210
|
+
const record = this.attachmentRow(attachmentId);
|
|
2211
|
+
if (!record)
|
|
2212
|
+
return null;
|
|
2213
|
+
const gate = this.attachmentGate(record.entity.entityType);
|
|
2214
|
+
try {
|
|
2215
|
+
const ctx = this.operationContext(this.systemPrincipal, tenantId, scopeId, undefined, undefined, moduleId, undefined, undefined, 'attachments.open');
|
|
2216
|
+
assertAllowed(await ctx.check(gate.read, record.entity));
|
|
2217
|
+
}
|
|
2218
|
+
catch (err) {
|
|
2219
|
+
if (err instanceof PermissionDenied) {
|
|
2220
|
+
this.recordDenial({ kind: 'system', id: moduleId }, tenantId, 'attachments.open', err, null);
|
|
2221
|
+
}
|
|
2222
|
+
throw toRpcError(err);
|
|
2223
|
+
}
|
|
2224
|
+
return record;
|
|
2225
|
+
}
|
|
2204
2226
|
/** Remove an attachment's metadata fact: write gate + delete + `attachment.removed`. */
|
|
2205
2227
|
async attachmentRemove(attachmentId, principal, tenantId, scopeId, connectionId) {
|
|
2206
2228
|
await this.ensureMigrations();
|
|
@@ -2402,6 +2424,40 @@ export function defineScopeDO(modules, bareOps) {
|
|
|
2402
2424
|
return permissions.map((permission) => ({ permission, held: !missing.has(permission) }));
|
|
2403
2425
|
});
|
|
2404
2426
|
}
|
|
2427
|
+
/**
|
|
2428
|
+
* `ctx.canAssign`'s bound for a principal the host names (#1931), queued like `peerCovers`
|
|
2429
|
+
* so no invoke's open transaction is read half-done. `null` when the tenant defines no such
|
|
2430
|
+
* role: a typed error thrown here would reach the host flattened, so the host types it.
|
|
2431
|
+
*/
|
|
2432
|
+
async canAssignFor(tenantId, scopeId, principal, roleKey) {
|
|
2433
|
+
await this.ensureMigrations();
|
|
2434
|
+
return this.queue.enqueue(() => this.assignmentBound({ kind: 'principal', id: principal }, tenantId, scopeId, roleKey));
|
|
2435
|
+
}
|
|
2436
|
+
/** Check and grant in one serialized scope task; a refusal never writes a tuple. */
|
|
2437
|
+
async assignScopeRoleBoundedFor(tenantId, scopeId, caller, assignee, roleKey) {
|
|
2438
|
+
await this.ensureMigrations();
|
|
2439
|
+
return this.queue.enqueue(async () => {
|
|
2440
|
+
const bound = await this.assignmentBound({ kind: 'principal', id: caller }, tenantId, scopeId, roleKey);
|
|
2441
|
+
if (bound?.covered) {
|
|
2442
|
+
this.sql.exec(`INSERT OR REPLACE INTO _substrat_tuples (subject, relation, object, expires_at)
|
|
2443
|
+
VALUES (?, ?, ?, NULL)`, `principal:${assignee}`, `role:${roleKey}`, `scope:${scopeId}`);
|
|
2444
|
+
}
|
|
2445
|
+
return bound;
|
|
2446
|
+
});
|
|
2447
|
+
}
|
|
2448
|
+
/**
|
|
2449
|
+
* §5.1's assignment bound, resolved against the SAME role table the checker
|
|
2450
|
+
* expands — the tenant's projected role, not a vertical's compile-time `ROLES`
|
|
2451
|
+
* array, because the projected role is what assignment would actually confer.
|
|
2452
|
+
* The one resolution both `ctx.canAssign` and `canAssignFor` answer from; `null`
|
|
2453
|
+
* when the tenant defines no such role.
|
|
2454
|
+
*/
|
|
2455
|
+
async assignmentBound(subject, tenantId, scopeId, roleKey) {
|
|
2456
|
+
const role = await this.controlPlaneReader().getRole(tenantId, roleKey);
|
|
2457
|
+
if (!role)
|
|
2458
|
+
return null;
|
|
2459
|
+
return this.checker.covers(subject, role.permissions, { tenantId, scopeId });
|
|
2460
|
+
}
|
|
2405
2461
|
/**
|
|
2406
2462
|
* Every module this scope holds or has held system authority for, and where each
|
|
2407
2463
|
* stands (#1674) — the kernel's `systemGrantsStatus`, over this DO's own storage. A
|
|
@@ -3991,17 +4047,12 @@ export function defineScopeDO(modules, bareOps) {
|
|
|
3991
4047
|
}
|
|
3992
4048
|
return decision;
|
|
3993
4049
|
};
|
|
3994
|
-
/**
|
|
3995
|
-
* §5.1's assignment bound, resolved against the SAME role table the checker
|
|
3996
|
-
* expands — the tenant's projected role, not a vertical's compile-time `ROLES`
|
|
3997
|
-
* array, because the projected role is what assignment would actually confer.
|
|
3998
|
-
*/
|
|
3999
4050
|
const runCanAssign = async (roleKey) => {
|
|
4000
|
-
const
|
|
4001
|
-
if (!
|
|
4002
|
-
throw
|
|
4051
|
+
const bound = await this.assignmentBound(subject, tenantId, scopeId, roleKey);
|
|
4052
|
+
if (!bound) {
|
|
4053
|
+
throw unknownRoleError(roleKey);
|
|
4003
4054
|
}
|
|
4004
|
-
return
|
|
4055
|
+
return bound;
|
|
4005
4056
|
};
|
|
4006
4057
|
// ctx.emit's writer, and the kernel's own events' (#1864): one path to the outbox, with the
|
|
4007
4058
|
// reserved-type refusal applied to module code only. Never handed to module code as-is.
|