@substrat-run/adapter-cloudflare 0.131.0 → 0.133.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.
@@ -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,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"}
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;AA0bD;;;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,CAslKjE"}
package/dist/scope-do.js CHANGED
@@ -160,6 +160,8 @@ const KERNEL_DDL = `
160
160
  module_id TEXT NOT NULL,
161
161
  version TEXT NOT NULL,
162
162
  applied_at TEXT NOT NULL,
163
+ duration_ms INTEGER,
164
+ rows_changed INTEGER,
163
165
  PRIMARY KEY (module_id, version)
164
166
  );
165
167
  -- #286: the PITR bookmark taken immediately BEFORE a migration pass runs on a
@@ -833,13 +835,15 @@ export function defineScopeDO(modules, bareOps) {
833
835
  */
834
836
  appliedMigrations(limit = 100) {
835
837
  return this.sql
836
- .exec(`SELECT module_id, version, applied_at FROM _substrat_migrations
838
+ .exec(`SELECT module_id, version, applied_at, duration_ms, rows_changed FROM _substrat_migrations
837
839
  ORDER BY applied_at DESC, module_id, version LIMIT ?`, limit)
838
840
  .toArray()
839
841
  .map((r) => ({
840
842
  moduleId: r.module_id,
841
843
  version: r.version,
842
844
  appliedAt: r.applied_at ?? null,
845
+ durationMs: r.duration_ms ?? null,
846
+ rowsChanged: r.rows_changed ?? null,
843
847
  }));
844
848
  }
845
849
  /**
@@ -2818,8 +2822,8 @@ export function defineScopeDO(modules, bareOps) {
2818
2822
  this.ctx.storage.transactionSync(() => {
2819
2823
  this.sql.exec(`INSERT INTO _substrat_job_runs
2820
2824
  (id, module_id, job, instance, payload, status, cursor, counters, attempts,
2821
- last_error, started_at, updated_at, next_attempt_at, ended_at)
2822
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, row.id, row.module_id, row.job, row.instance, row.payload, row.status, row.cursor, row.counters, row.attempts, row.last_error, row.started_at, row.updated_at, row.next_attempt_at, row.ended_at);
2825
+ last_error, started_at, updated_at, next_attempt_at, ended_at, subject_id)
2826
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, row.id, row.module_id, row.job, row.instance, row.payload, row.status, row.cursor, row.counters, row.attempts, row.last_error, row.started_at, row.updated_at, row.next_attempt_at, row.ended_at, row.subject_id ?? null);
2823
2827
  });
2824
2828
  return row;
2825
2829
  }
@@ -2831,8 +2835,8 @@ export function defineScopeDO(modules, bareOps) {
2831
2835
  async jobRunInsert(row) {
2832
2836
  this.sql.exec(`INSERT INTO _substrat_job_runs
2833
2837
  (id, module_id, job, instance, payload, status, cursor, counters, attempts,
2834
- last_error, started_at, updated_at, next_attempt_at, ended_at)
2835
- VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, row.id, row.module_id, row.job, row.instance, row.payload, row.status, row.cursor, row.counters, row.attempts, row.last_error, row.started_at, row.updated_at, row.next_attempt_at, row.ended_at);
2838
+ last_error, started_at, updated_at, next_attempt_at, ended_at, subject_id)
2839
+ VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`, row.id, row.module_id, row.job, row.instance, row.payload, row.status, row.cursor, row.counters, row.attempts, row.last_error, row.started_at, row.updated_at, row.next_attempt_at, row.ended_at, row.subject_id ?? null);
2836
2840
  }
2837
2841
  /**
2838
2842
  * `running` runs whose backoff has elapsed, oldest first, after `afterId`.
@@ -2989,13 +2993,16 @@ export function defineScopeDO(modules, bareOps) {
2989
2993
  .exec('SELECT 1 FROM _substrat_migrations WHERE module_id = ? AND version = ?', moduleId, migration.version)
2990
2994
  .toArray()[0];
2991
2995
  if (!already) {
2996
+ const started = performance.now();
2997
+ const before = this.sql.exec('SELECT total_changes() AS n').toArray()[0].n;
2992
2998
  // #1898: a migration runs on this DO's own handle, not `ctx.sql`, so the
2993
2999
  // spine guard's REFERENCES rule is applied here.
2994
3000
  assertNoSpineReference(migration.sql, `migration ${key}`);
2995
3001
  for (const stmt of splitSqlStatements(migration.sql)) {
2996
3002
  this.sql.exec(stmt);
2997
3003
  }
2998
- this.sql.exec('INSERT INTO _substrat_migrations (module_id, version, applied_at) VALUES (?, ?, ?)', moduleId, migration.version, new Date().toISOString());
3004
+ const after = this.sql.exec('SELECT total_changes() AS n').toArray()[0].n;
3005
+ this.sql.exec('INSERT INTO _substrat_migrations (module_id, version, applied_at, duration_ms, rows_changed) VALUES (?, ?, ?, ?, ?)', moduleId, migration.version, new Date().toISOString(), Math.max(0, Math.round(performance.now() - started)), after - before);
2999
3006
  }
3000
3007
  });
3001
3008
  }
@@ -3405,7 +3412,12 @@ export function defineScopeDO(modules, bareOps) {
3405
3412
  // have added it bare already, and then this ALTER is skipped as a duplicate (#1883).
3406
3413
  // `lint:spine-ddl` refuses one that is not.
3407
3414
  for (const alter of [
3415
+ // #1763: rows written before these fields keep NULL, meaning unrecorded.
3416
+ 'ALTER TABLE _substrat_migrations ADD COLUMN duration_ms INTEGER',
3417
+ 'ALTER TABLE _substrat_migrations ADD COLUMN rows_changed INTEGER',
3408
3418
  'ALTER TABLE _substrat_tuples ADD COLUMN revoked_at TEXT',
3419
+ // #1632: legacy runs retain an unknown subject; no content-based backfill.
3420
+ 'ALTER TABLE _substrat_job_runs ADD COLUMN subject_id TEXT',
3409
3421
  // Executor retry state (#100). The defaults read as "terminal", which is
3410
3422
  // right for every row already there: each is a completed delivery or a
3411
3423
  // consumer dead-letter.
@@ -4415,7 +4427,9 @@ export function defineScopeDO(modules, bareOps) {
4415
4427
  /** The directory's recorded-off modules (#1742), switched off in THIS unit right after the
4416
4428
  * seat, so no sweep can run the grants the seat just re-created. `scopeId` is the scope
4417
4429
  * this projection provisions (the object of `scopeTuples`), never another. */
4418
- switchOff) {
4430
+ switchOff,
4431
+ /** Declared service subjects excluded only from human lockout repair (#1896). */
4432
+ serviceSubjects) {
4419
4433
  if (await this.isReaped())
4420
4434
  return [];
4421
4435
  // A projection that arrives after this scope was reaped is dropped, not
@@ -4500,14 +4514,14 @@ export function defineScopeDO(modules, bareOps) {
4500
4514
  this.sql.exec(seat.sql, ...seat.params);
4501
4515
  }
4502
4516
  // #1659's one exception: the owner-of-record's seat comes back over a revoke when
4503
- // NOTHING else would let anyone act here — roles projected, no effective role grant.
4504
- // That is the #332 lockout this path exists to repair, and it is decided by the same
4505
- // predicate as the flip guard below, so "locked out" means one thing in this unit.
4517
+ // No HUMAN holder remains — declared service subjects cannot prevent lockout repair.
4518
+ // That is the #332 lockout this path exists to repair. The flip guard below still
4519
+ // counts service authority; only the repair excludes the declared service subjects.
4506
4520
  // With any other effective holder, the revoke stands: a hand-over that seats a
4507
4521
  // successor before unseating the owner is not undone by the next promote. A holder of
4508
4522
  // a role the vertical no longer defines is NOT one — it passes no check, so it must
4509
4523
  // not stand in for the holder this repair exists to restore.
4510
- if (roles.length > 0 && !this.hasEffectiveRoleGrant(tenantId)) {
4524
+ if (roles.length > 0 && !this.hasEffectiveRoleGrant(tenantId, serviceSubjects)) {
4511
4525
  for (const st of scopeTuples ?? []) {
4512
4526
  if (!st.lockout_reseat)
4513
4527
  continue;
@@ -4556,8 +4570,8 @@ export function defineScopeDO(modules, bareOps) {
4556
4570
  * kernel's `effectiveRoleGrantQuery`, where it is tested against a real SQLite. A tuple
4557
4571
  * for a role the vertical no longer defines counts for nothing, exactly as in the local
4558
4572
  * checker, which expands a role only through its definition. */
4559
- hasEffectiveRoleGrant(tenantId) {
4560
- const q = effectiveRoleGrantQuery(tenantId, new Date().toISOString());
4573
+ hasEffectiveRoleGrant(tenantId, excludedSubjects) {
4574
+ const q = effectiveRoleGrantQuery(tenantId, new Date().toISOString(), undefined, excludedSubjects);
4561
4575
  const row = this.sql.exec(q.sql, ...q.params).toArray()[0];
4562
4576
  return row?.effective === 1;
4563
4577
  }