@substrat-run/adapter-cloudflare 0.149.0 → 0.150.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/host.d.ts.map +1 -1
- package/dist/host.js +8 -0
- package/dist/host.js.map +1 -1
- package/dist/scope-do.d.ts.map +1 -1
- package/dist/scope-do.js +46 -4
- package/dist/scope-do.js.map +1 -1
- package/package.json +9 -9
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":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA8DnD,OAAO,EA2DL,KAAK,SAAS,EAsBd,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,
|
|
1
|
+
{"version":3,"file":"scope-do.d.ts","sourceRoot":"","sources":["../src/scope-do.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,aAAa,EAAE,MAAM,oBAAoB,CAAC;AA8DnD,OAAO,EA2DL,KAAK,SAAS,EAsBd,KAAK,kBAAkB,EAEvB,KAAK,gBAAgB,EAkHtB,MAAM,sBAAsB,CAAC;AAoD9B,OAAO,EAAW,KAAK,OAAO,EAAE,MAAM,eAAe,CAAC;AAGtD,OAAO,EAwBL,kBAAkB,EA4EnB,MAAM,sBAAsB,CAAC;AA0B9B;;;;;;;;;;;;;GAaG;AAEH,MAAM,WAAW,UAAU;IACzB;;;;;OAKG;IACH,aAAa,CAAC,EAAE,sBAAsB,CAAC;IACvC;;;;;;OAMG;IACH,mBAAmB,CAAC,EAAE,MAAM,CAAC;IAC7B;;;;;OAKG;IACH,0BAA0B,CAAC,EAAE,MAAM,CAAC;CACrC;AAoFD,oFAAoF;AACpF,MAAM,MAAM,aAAa,GAAG,UAAU,GAAG,UAAU,GAAG,SAAS,GAAG,SAAS,CAAC;AAwkB5E;;;GAGG;AACH,MAAM,MAAM,yBAAyB,CAAC,CAAC,IAAI,OAAO,CAAC,CAAC,CAAC,CAAC;AAmBtD;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH;;;;GAIG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,UAAU,GAAG,SAAS,CAOxD;AAED,gHAAgH;AAChH,OAAO,EAAE,kBAAkB,EAAE,CAAC;AA2B9B,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,CAAC,UAAU,CAAC,CAozO7E"}
|
package/dist/scope-do.js
CHANGED
|
@@ -2,7 +2,7 @@ import { REWIND_REFUSED } from './rewind-refusal.js';
|
|
|
2
2
|
import { SYSTEM_DOOR_MOVED } from './system-door.js';
|
|
3
3
|
import { DurableObject } from 'cloudflare:workers';
|
|
4
4
|
import { ATTACHMENT_ADDED, ATTACHMENT_REMOVED, attachmentRecord, domainEvent, domainEventInput, eventId, instant, objectRef, entityObjectRef, assertModuleEmittableType, assertKernelAuthoredType, toWireFailure, grantRefFromProof, principalId, principalBecomeCapabilityInput, 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, pageOf, countedPageOf, requestFingerprint, substratError, errorCodeOf, assertReplayableDump, REDRAIN_BATCH, } from '@substrat-run/contracts';
|
|
5
|
-
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, eraseSubjectFromModules, moduleErasurePlan, redactSubjectScopeText, assertRowLimit, assertRowOffset, JOB_RUN_PATCH_SQL, JOB_RUN_CLAIM_SQL, JOB_RUN_RENEW_SQL, JOB_RUN_BEGIN_SQL, JOB_RUN_MISS_SQL, JOB_RUN_MISS_SETTLE_SQL, admissionMissOutcome, JOB_LEASE_EXPIRED_NOTE, JOB_STEP_RECORD_SQL, DELIVERY_ERROR_REDACTION_SQL, REDACTED_DELIVERY_NOTE, seatScopeTuple, delegatedRevokeSql, writeExplicitTupleIn, grantEntityShapeIn, topUpEntityGrantShapes, applyScopeRoleChange, changeScopeRole, revokeScopeRoles, scopeRoleHolders, effectiveRoleGrantQuery, switchRecordedOff, switchSystemSchedules, peerGrantsStatus, systemGrantsStatus, systemScheduleState, systemSwitchedOff, denialListQuery, refusalListQuery, mapRefusalRow, denialSummaryQuery, denialTotalsQuery, DENIAL_WINDOW_QUERY, mapDenialRow, mapDenialSummaryBuckets, PermissionDenied, assertImpersonationWrites, assertModuleEnqueueableKind, impersonationStampOf, createAtomic, NotSearchable, isSearchIndexTable, searchIndexPlans, NotListable, listIndexPlans, moduleMigrations, MIGRATION_DIGEST_FENCE_DDL, MIGRATION_DIGEST_MARK_LEGACY, assertJournalDumpCoherent, assertMigrationSql, migrationDivergence, migrationFailedError, migrationSetDivergence, migrationSteps, planMigrations, listQuery, cursorOf, searchLimit, searchMatchExpression, searchQuery, ATTACHMENT_TEXT_DDL, ATTACHMENT_CONDEMNED_DDL,
|
|
5
|
+
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, eraseSubjectFromModules, moduleErasurePlan, redactSubjectScopeText, assertRowLimit, assertRowOffset, JOB_RUN_PATCH_SQL, JOB_RUN_CLAIM_SQL, JOB_RUN_RENEW_SQL, JOB_RUN_BEGIN_SQL, JOB_RUN_MISS_SQL, JOB_RUN_MISS_SETTLE_SQL, admissionMissOutcome, JOB_LEASE_EXPIRED_NOTE, JOB_STEP_RECORD_SQL, DELIVERY_ERROR_REDACTION_SQL, REDACTED_DELIVERY_NOTE, seatScopeTuple, delegatedRevokeSql, writeExplicitTupleIn, grantEntityShapeIn, topUpEntityGrantShapes, applyScopeRoleChange, changeScopeRole, revokeScopeRoles, scopeRoleHolders, effectiveRoleGrantQuery, switchRecordedOff, switchSystemSchedules, peerGrantsStatus, systemGrantsStatus, systemScheduleState, systemSwitchedOff, denialListQuery, refusalListQuery, mapRefusalRow, denialSummaryQuery, denialTotalsQuery, DENIAL_WINDOW_QUERY, mapDenialRow, mapDenialSummaryBuckets, PermissionDenied, assertImpersonationWrites, assertModuleEnqueueableKind, impersonationStampOf, createAtomic, NotSearchable, isSearchIndexTable, searchIndexPlans, NotListable, listIndexPlans, moduleMigrations, MIGRATION_DIGEST_FENCE_DDL, MIGRATION_DIGEST_MARK_LEGACY, assertJournalDumpCoherent, assertMigrationSql, migrationDivergence, migrationFailedError, migrationSetDivergence, migrationSteps, planMigrations, listQuery, cursorOf, searchLimit, searchMatchExpression, searchQuery, ATTACHMENT_TEXT_DDL, ATTACHMENT_CONDEMNED_DDL, ATTACHMENT_SWEEP_LICENCE_DDL, ATTACHMENT_SWEEP_LICENCE_TABLE, clearOrphanSweepLicence, condemnLicensedOrphanAttachments, consumeOrphanSweepLicence, licensedOrphanIds, recordOrphanSweepLicence, refuseUnlicensedOrphanSweep, refuseCondemnedAttachment, refuseCondemnedInDump, rowlessAttachmentIds, attachmentRecordOfRow, enqueueAttachmentText, reconcileAttachmentText, queueAttachmentTextBackfill, startAttachmentTextBackfill, recordAttachmentText, searchAttachments, IDEMPOTENCY_DDL, REFUSALS_TABLE_DDL, REFUSALS_INDEX, refusalInsert, refusalOf, markGuardRefusal, REFUSALS_REBUILD, refusalsAdmitGuards, 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, emptyImportResult, 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, JOB_RUN_DUE_AT, jobRunListLimit, SYSTEM_DOOR_WAIT, ancestorsWithin, } from '@substrat-run/kernel';
|
|
6
6
|
import { isUpgradeRequest, readSubscription, LIVE_DECIDE_ATTEMPTS, LIVE_FANOUT_LIMIT, LIVE_MODE_HEADER, LIVE_PRINCIPAL_HEADER, LIVE_SCOPE_HEADER, LIVE_SUBSCRIBE_PATH, LIVE_TENANT_HEADER, LIVE_WITHIN_HEADER, LIVE_EXPIRES_HEADER, LIVE_CLOSE, LIVE_SOCKETS_PER_PRINCIPAL, decodeLiveWithin, liveInstant, } from './live-reads.js';
|
|
7
7
|
import { replyOf } from './do-reply.js';
|
|
8
8
|
import { OperationQueue } from './serialization.js';
|
|
@@ -355,6 +355,9 @@ const KERNEL_DDL = `
|
|
|
355
355
|
-- #2314: the orphan sweep's tombstones, shared from @substrat-run/kernel. An id here
|
|
356
356
|
-- never takes an attachment row again: the insert path refuses it.
|
|
357
357
|
${ATTACHMENT_CONDEMNED_DDL}
|
|
358
|
+
-- #2350: the orphan sweep's dry-run licence, shared from @substrat-run/kernel. Store-local:
|
|
359
|
+
-- never dumped, and every load drops it.
|
|
360
|
+
${ATTACHMENT_SWEEP_LICENCE_DDL}
|
|
358
361
|
-- #901: an entity's version is the ULID of the last event about it (a state move
|
|
359
362
|
-- excepted, #2191), so the newest id per (entity_type, entity_id) is the read. The id
|
|
360
363
|
-- column sits last so SQLite walks the matched range backwards instead of aggregating.
|
|
@@ -2887,14 +2890,46 @@ export function defineScopeDO(modules, bareOps) {
|
|
|
2887
2890
|
throw misrouted;
|
|
2888
2891
|
await this.refuseOrphanJudgement(tenantId, vouched);
|
|
2889
2892
|
// The verdict alone (no ids, the host's first call) changes nothing: no migration, no repair.
|
|
2890
|
-
|
|
2893
|
+
// A destructive pass's verdict also asks for this store's own dry-run licence (#2350), so a
|
|
2894
|
+
// pass with nothing to condemn is refused all the same.
|
|
2895
|
+
if (ids.length === 0) {
|
|
2896
|
+
if (condemn)
|
|
2897
|
+
await this.queue.enqueue(async () => refuseUnlicensedOrphanSweep(doSpineSql(this.sql), now));
|
|
2891
2898
|
return [];
|
|
2899
|
+
}
|
|
2892
2900
|
await this.ensureMigrations();
|
|
2893
2901
|
return this.queue.enqueue(async () => {
|
|
2894
2902
|
await this.refuseOrphanJudgement(tenantId, vouched);
|
|
2895
2903
|
if (!condemn)
|
|
2896
2904
|
return rowlessAttachmentIds(doSpineSql(this.sql), ids);
|
|
2897
|
-
return this.revision.transaction(async () =>
|
|
2905
|
+
return this.revision.transaction(async () => condemnLicensedOrphanAttachments(doSpineSql(this.sql), ids, now));
|
|
2906
|
+
});
|
|
2907
|
+
});
|
|
2908
|
+
}
|
|
2909
|
+
/**
|
|
2910
|
+
* #2350: the licence half of a pass, behind the same refusals as the judgement. `record` keeps
|
|
2911
|
+
* what a dry run listed as this store's licence; `read` answers the ids it lists; `consume` takes
|
|
2912
|
+
* ids out of it (what a destructive pass deleted, and what is gone some other way). Each write
|
|
2913
|
+
* happens only when it changes the licence, so a dry run that keeps finding the same orphans
|
|
2914
|
+
* leaves the write revision where it was. Only `read` answers ids; the others answer none.
|
|
2915
|
+
*/
|
|
2916
|
+
orphanSweepLicenceReply(op, ids, now, tenantId, vouched = false, expectedVersionId) {
|
|
2917
|
+
return replyOf(async () => {
|
|
2918
|
+
const misrouted = orphanSweepVersionRefusal(this.env.SUBSTRAT_VERSION_ID ?? null, expectedVersionId, op !== 'record');
|
|
2919
|
+
if (misrouted)
|
|
2920
|
+
throw misrouted;
|
|
2921
|
+
await this.ensureMigrations();
|
|
2922
|
+
return this.queue.enqueue(async () => {
|
|
2923
|
+
await this.refuseOrphanJudgement(tenantId, vouched);
|
|
2924
|
+
if (op === 'read')
|
|
2925
|
+
return licensedOrphanIds(doSpineSql(this.sql));
|
|
2926
|
+
await this.revision.transaction(async () => {
|
|
2927
|
+
if (op === 'record')
|
|
2928
|
+
recordOrphanSweepLicence(doSpineSql(this.sql), ids, now);
|
|
2929
|
+
else
|
|
2930
|
+
consumeOrphanSweepLicence(doSpineSql(this.sql), ids);
|
|
2931
|
+
});
|
|
2932
|
+
return [];
|
|
2898
2933
|
});
|
|
2899
2934
|
});
|
|
2900
2935
|
}
|
|
@@ -4907,7 +4942,10 @@ export function defineScopeDO(modules, bareOps) {
|
|
|
4907
4942
|
// in a dump (`exportDumpStamped` hands the stamp over beside one); every load writes its own.
|
|
4908
4943
|
const cursor = name === '_substrat_meta'
|
|
4909
4944
|
? this.sql.exec(`SELECT * FROM "${name}" WHERE key NOT IN (${STORE_LOCAL_META_KEYS.map(() => '?').join(', ')})`, ...STORE_LOCAL_META_KEYS)
|
|
4910
|
-
: this
|
|
4945
|
+
: // #2350: the orphan sweep's licence is this store's own, so its rows never leave in a dump.
|
|
4946
|
+
name === ATTACHMENT_SWEEP_LICENCE_TABLE
|
|
4947
|
+
? this.sql.exec(`SELECT * FROM "${name}" WHERE 0`)
|
|
4948
|
+
: this.sql.exec(`SELECT * FROM "${name}"`);
|
|
4911
4949
|
const columns = cursor.columnNames;
|
|
4912
4950
|
const rows = Array.from(cursor.raw(), (row) => row);
|
|
4913
4951
|
return { name, ddl: sql, columns, rows };
|
|
@@ -5270,6 +5308,10 @@ export function defineScopeDO(modules, bareOps) {
|
|
|
5270
5308
|
// from before a suspension does not lift it; a copy keeps only its own.
|
|
5271
5309
|
settleLifecycleAfterLoad(this.switchSql(), lifecycleBefore, markCopy === true || isCopyLoad(destScopeId, sourceScopeId));
|
|
5272
5310
|
reconcileAttachmentText(doSpineSql(this.sql), ulid, now);
|
|
5311
|
+
// #2350: the orphan sweep's licence describes this store's last dry run, never the dump's.
|
|
5312
|
+
// A dump does not carry it; a hand-made one that does is dropped here all the same, so a
|
|
5313
|
+
// loaded store's next pass is a dry run.
|
|
5314
|
+
clearOrphanSweepLicence(doSpineSql(this.sql));
|
|
5273
5315
|
// Re-point the restored grants at THIS scope (after the spine exists, so a dump
|
|
5274
5316
|
// that carried no tuples table still finds one here).
|
|
5275
5317
|
if (destScopeId) {
|