@substrat-run/contract-tests 0.139.0 → 0.141.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.
Files changed (106) hide show
  1. package/dist/attachment-text-suite.d.ts.map +1 -1
  2. package/dist/attachment-text-suite.js +12 -4
  3. package/dist/attachment-text-suite.js.map +1 -1
  4. package/dist/capability-attachment-suite.d.ts.map +1 -1
  5. package/dist/capability-attachment-suite.js +84 -4
  6. package/dist/capability-attachment-suite.js.map +1 -1
  7. package/dist/capability-expiry-suite.d.ts.map +1 -1
  8. package/dist/capability-expiry-suite.js +6 -2
  9. package/dist/capability-expiry-suite.js.map +1 -1
  10. package/dist/capability-suite.d.ts.map +1 -1
  11. package/dist/capability-suite.js +9 -0
  12. package/dist/capability-suite.js.map +1 -1
  13. package/dist/caused-by-suite.d.ts.map +1 -1
  14. package/dist/caused-by-suite.js +54 -10
  15. package/dist/caused-by-suite.js.map +1 -1
  16. package/dist/connect-link-suite.d.ts +19 -0
  17. package/dist/connect-link-suite.d.ts.map +1 -0
  18. package/dist/connect-link-suite.js +215 -0
  19. package/dist/connect-link-suite.js.map +1 -0
  20. package/dist/entity-state-migration-suite.d.ts +16 -0
  21. package/dist/entity-state-migration-suite.d.ts.map +1 -0
  22. package/dist/entity-state-migration-suite.js +305 -0
  23. package/dist/entity-state-migration-suite.js.map +1 -0
  24. package/dist/entity-state-module.d.ts +183 -0
  25. package/dist/entity-state-module.d.ts.map +1 -1
  26. package/dist/entity-state-module.js +139 -1
  27. package/dist/entity-state-module.js.map +1 -1
  28. package/dist/entity-state-suite.d.ts.map +1 -1
  29. package/dist/entity-state-suite.js +35 -12
  30. package/dist/entity-state-suite.js.map +1 -1
  31. package/dist/entity-trash-module.d.ts +439 -0
  32. package/dist/entity-trash-module.d.ts.map +1 -0
  33. package/dist/entity-trash-module.js +287 -0
  34. package/dist/entity-trash-module.js.map +1 -0
  35. package/dist/entity-trash-suite.d.ts +59 -0
  36. package/dist/entity-trash-suite.d.ts.map +1 -0
  37. package/dist/entity-trash-suite.js +568 -0
  38. package/dist/entity-trash-suite.js.map +1 -0
  39. package/dist/erasure-module.d.ts +259 -0
  40. package/dist/erasure-module.d.ts.map +1 -0
  41. package/dist/erasure-module.js +251 -0
  42. package/dist/erasure-module.js.map +1 -0
  43. package/dist/index.d.ts +13 -1
  44. package/dist/index.d.ts.map +1 -1
  45. package/dist/index.js +13 -1
  46. package/dist/index.js.map +1 -1
  47. package/dist/job-run-suite.d.ts.map +1 -1
  48. package/dist/job-run-suite.js +29 -15
  49. package/dist/job-run-suite.js.map +1 -1
  50. package/dist/list-suite.d.ts.map +1 -1
  51. package/dist/list-suite.js +101 -1
  52. package/dist/list-suite.js.map +1 -1
  53. package/dist/membership-executor-suite.d.ts.map +1 -1
  54. package/dist/membership-executor-suite.js +60 -9
  55. package/dist/membership-executor-suite.js.map +1 -1
  56. package/dist/migration-comments-suite.d.ts +3 -0
  57. package/dist/migration-comments-suite.d.ts.map +1 -0
  58. package/dist/migration-comments-suite.js +92 -0
  59. package/dist/migration-comments-suite.js.map +1 -0
  60. package/dist/migration-comments.d.ts +3 -0
  61. package/dist/migration-comments.d.ts.map +1 -0
  62. package/dist/migration-comments.js +50 -0
  63. package/dist/migration-comments.js.map +1 -0
  64. package/dist/migration-digest-suite.d.ts +3 -0
  65. package/dist/migration-digest-suite.d.ts.map +1 -0
  66. package/dist/migration-digest-suite.js +175 -0
  67. package/dist/migration-digest-suite.js.map +1 -0
  68. package/dist/modules.d.ts +542 -0
  69. package/dist/modules.d.ts.map +1 -1
  70. package/dist/modules.js +167 -7
  71. package/dist/modules.js.map +1 -1
  72. package/dist/peer-suite.d.ts +2 -1
  73. package/dist/peer-suite.d.ts.map +1 -1
  74. package/dist/peer-suite.js +103 -1
  75. package/dist/peer-suite.js.map +1 -1
  76. package/dist/permission-suite.d.ts.map +1 -1
  77. package/dist/permission-suite.js +515 -2
  78. package/dist/permission-suite.js.map +1 -1
  79. package/dist/schedule-suite.d.ts +4 -1
  80. package/dist/schedule-suite.d.ts.map +1 -1
  81. package/dist/schedule-suite.js +150 -2
  82. package/dist/schedule-suite.js.map +1 -1
  83. package/dist/scope-host-suite.d.ts.map +1 -1
  84. package/dist/scope-host-suite.js +215 -2
  85. package/dist/scope-host-suite.js.map +1 -1
  86. package/dist/split-cases.d.ts +12 -0
  87. package/dist/split-cases.d.ts.map +1 -0
  88. package/dist/split-cases.js +59 -0
  89. package/dist/split-cases.js.map +1 -0
  90. package/dist/subject-erasure-suite.d.ts +6 -0
  91. package/dist/subject-erasure-suite.d.ts.map +1 -0
  92. package/dist/subject-erasure-suite.js +287 -0
  93. package/dist/subject-erasure-suite.js.map +1 -0
  94. package/dist/switch-audit-fault.d.ts +48 -0
  95. package/dist/switch-audit-fault.d.ts.map +1 -0
  96. package/dist/switch-audit-fault.js +80 -0
  97. package/dist/switch-audit-fault.js.map +1 -0
  98. package/dist/system-switch-suite.d.ts +2 -1
  99. package/dist/system-switch-suite.d.ts.map +1 -1
  100. package/dist/system-switch-suite.js +90 -0
  101. package/dist/system-switch-suite.js.map +1 -1
  102. package/dist/vertical-events-suite.d.ts +41 -0
  103. package/dist/vertical-events-suite.d.ts.map +1 -1
  104. package/dist/vertical-events-suite.js +55 -0
  105. package/dist/vertical-events-suite.js.map +1 -1
  106. package/package.json +5 -5
@@ -1,4 +1,4 @@
1
- import { describe, it, expect, beforeAll, afterAll } from 'vitest';
1
+ import { describe, it, expect, beforeAll, afterAll, vi } from 'vitest';
2
2
  import { moduleId, platformActorId, principalId, scopeId, tenantId } from '@substrat-run/contracts';
3
3
  import { runPlatformSweep, ulid } from '@substrat-run/kernel';
4
4
  import { deniedScheduleMod, scheduleMod } from './modules.js';
@@ -30,7 +30,9 @@ export function errorsOfScope(errors, scope) {
30
30
  * must: fire a due schedule under a system actor, gate re-runs by cadence, and let
31
31
  * `ctx.check` (not a bypass) decide what the schedule may do.
32
32
  */
33
- export function scheduleContractSuite(adapterName, makeFixture) {
33
+ export function scheduleContractSuite(adapterName, makeFixture, suspendAtSystemDoor,
34
+ /** Interpose after the pass's first fire has run and before its next schedule is read. */
35
+ suspendAfterFirstFire) {
34
36
  describe(`schedule contract (#383): ${adapterName}`, () => {
35
37
  let fixture;
36
38
  let host;
@@ -234,6 +236,152 @@ export function scheduleContractSuite(adapterName, makeFixture) {
234
236
  const denial = denials.find((d) => d.operation === 'sched-denied/tick');
235
237
  expect(denial?.invocation_id).toBe(failedRow.invocation_id);
236
238
  });
239
+ it('a tenant suspension holds every scope schedule, while another tenant still runs', async () => {
240
+ const sibling = scopeId.parse(ulid());
241
+ const otherTenant = tenantId.parse(ulid());
242
+ const otherScope = scopeId.parse(ulid());
243
+ await host.provisionScope(staff, { tenantId: t, scopeId: sibling, vertical: 'sched-vertical' });
244
+ await host.admin.activateScope(staff, t, sibling);
245
+ await host.admin.createTenant(staff, { id: otherTenant, slug: `sched-${otherTenant.toLowerCase()}`, name: 'Sched' });
246
+ await host.admin.grantEntitlement(staff, otherTenant, 'sched');
247
+ await host.provisionScope(staff, { tenantId: otherTenant, scopeId: otherScope, vertical: 'sched-vertical' });
248
+ await host.admin.activateScope(staff, otherTenant, otherScope);
249
+ await host.admin.setTenantStatus(staff, t, 'suspended');
250
+ expect((await host.runDueSchedules(SCHED_MODULE, t, sibling)).fired).toBe(0);
251
+ expect((await host.runDueSchedules(SCHED_MODULE, t, s)).fired).toBe(0);
252
+ expect((await host.runDueSchedules(SCHED_MODULE, otherTenant, otherScope)).fired).toBe(2);
253
+ await host.admin.setTenantStatus(staff, t, 'active');
254
+ expect((await host.runDueSchedules(SCHED_MODULE, t, sibling)).fired).toBe(2);
255
+ expect((await (await host.getScope(reader, t, sibling)).invoke('sched/count'))).toBe(1);
256
+ expect((await host.runDueSchedules(SCHED_MODULE, t, sibling)).fired).toBe(0);
257
+ });
258
+ it('a previously fired schedule stays due through several held cadences and fires once on reactivation', async () => {
259
+ const held = scopeId.parse(ulid());
260
+ await host.provisionScope(staff, { tenantId: t, scopeId: held, vertical: 'sched-vertical' });
261
+ await host.admin.activateScope(staff, t, held);
262
+ expect((await host.runDueSchedules(SCHED_MODULE, t, held)).fired).toBe(2);
263
+ const first = Date.now();
264
+ await host.admin.suspendScope(staff, t, held);
265
+ vi.useFakeTimers({ toFake: ['Date'] });
266
+ try {
267
+ for (const hours of [2, 4, 6]) {
268
+ vi.setSystemTime(first + hours * 3_600_000);
269
+ expect((await host.runDueSchedules(SCHED_MODULE, t, held)).fired).toBe(0);
270
+ }
271
+ await host.admin.unsuspendScope(staff, t, held);
272
+ expect((await host.runDueSchedules(SCHED_MODULE, t, held)).fired).toBe(2);
273
+ expect((await (await host.getScope(reader, t, held)).invoke('sched/count'))).toBe(2);
274
+ expect((await host.runDueSchedules(SCHED_MODULE, t, held)).fired).toBe(0);
275
+ }
276
+ finally {
277
+ vi.useRealTimers();
278
+ }
279
+ });
280
+ it('a suspension at the system door does not consume an already due cadence', async () => {
281
+ const racing = scopeId.parse(ulid());
282
+ await host.provisionScope(staff, { tenantId: t, scopeId: racing, vertical: 'sched-vertical' });
283
+ await host.admin.activateScope(staff, t, racing);
284
+ expect((await host.runDueSchedules(SCHED_MODULE, t, racing)).fired).toBe(2);
285
+ vi.useFakeTimers({ toFake: ['Date'] });
286
+ const restore = suspendAtSystemDoor(host, () => host.admin.suspendScope(staff, t, racing).then(() => { }));
287
+ try {
288
+ vi.setSystemTime(Date.now() + 2 * 3_600_000);
289
+ expect(await host.runDueSchedules(SCHED_MODULE, t, racing)).toMatchObject({ fired: 0, failed: 0, skipped: 2, lifecycleHeld: true });
290
+ restore();
291
+ await host.admin.unsuspendScope(staff, t, racing);
292
+ expect((await host.runDueSchedules(SCHED_MODULE, t, racing)).fired).toBe(2);
293
+ expect((await (await host.getScope(reader, t, racing)).invoke('sched/count'))).toBe(2);
294
+ }
295
+ finally {
296
+ restore();
297
+ vi.useRealTimers();
298
+ }
299
+ });
300
+ it('a brief suspension whose refusal arrives after reactivation still leaves that schedule due', async () => {
301
+ const racing = scopeId.parse(ulid());
302
+ await host.provisionScope(staff, { tenantId: t, scopeId: racing, vertical: 'sched-vertical' });
303
+ await host.admin.activateScope(staff, t, racing);
304
+ expect((await host.runDueSchedules(SCHED_MODULE, t, racing)).fired).toBe(2);
305
+ vi.useFakeTimers({ toFake: ['Date'] });
306
+ const restore = suspendAtSystemDoor(host, () => host.admin.suspendScope(staff, t, racing).then(() => { }), () => host.admin.unsuspendScope(staff, t, racing).then(() => { }));
307
+ try {
308
+ vi.setSystemTime(Date.now() + 2 * 3_600_000);
309
+ expect(await host.runDueSchedules(SCHED_MODULE, t, racing)).toMatchObject({ fired: 1, failed: 0, skipped: 1, lifecycleHeld: true });
310
+ restore();
311
+ expect((await host.runDueSchedules(SCHED_MODULE, t, racing)).fired).toBe(1);
312
+ expect((await (await host.getScope(reader, t, racing)).invoke('sched/count'))).toBe(2);
313
+ expect((await host.runDueSchedules(SCHED_MODULE, t, racing)).fired).toBe(0);
314
+ }
315
+ finally {
316
+ restore();
317
+ vi.useRealTimers();
318
+ }
319
+ });
320
+ it('a suspension between two fires of one pass holds the later schedule', async () => {
321
+ const between = scopeId.parse(ulid());
322
+ await host.provisionScope(staff, { tenantId: t, scopeId: between, vertical: 'sched-vertical' });
323
+ await host.admin.activateScope(staff, t, between);
324
+ expect((await host.runDueSchedules(SCHED_MODULE, t, between)).fired).toBe(2);
325
+ vi.useFakeTimers({ toFake: ['Date'] });
326
+ const restore = suspendAfterFirstFire(host, () => host.admin.suspendScope(staff, t, between).then(() => { }));
327
+ try {
328
+ vi.setSystemTime(Date.now() + 2 * 3_600_000);
329
+ // The first fire ran while the scope was live; the second meets the suspension and is
330
+ // held, never run on the lifecycle read the first fire made.
331
+ expect(await host.runDueSchedules(SCHED_MODULE, t, between)).toMatchObject({ fired: 1, failed: 0, skipped: 1, lifecycleHeld: true });
332
+ restore();
333
+ expect((await host.runDueSchedules(SCHED_MODULE, t, between)).fired).toBe(0);
334
+ await host.admin.unsuspendScope(staff, t, between);
335
+ expect((await host.runDueSchedules(SCHED_MODULE, t, between)).fired).toBe(1);
336
+ expect((await host.runDueSchedules(SCHED_MODULE, t, between)).fired).toBe(0);
337
+ }
338
+ finally {
339
+ restore();
340
+ vi.useRealTimers();
341
+ }
342
+ });
343
+ it('a retry queued before suspension waits without an attempt, then drains once', async () => {
344
+ const retryScope = scopeId.parse(ulid());
345
+ await host.provisionScope(staff, { tenantId: t, scopeId: retryScope, vertical: 'sched-vertical' });
346
+ await host.admin.activateScope(staff, t, retryScope);
347
+ expect((await host.runDueSchedules(SCHED_MODULE, t, retryScope)).fired).toBe(2);
348
+ const ran = [];
349
+ host.registerExecutor(`suspend-${retryScope}`, 'sched.ticked', async (_admin, event) => {
350
+ ran.push(event.id);
351
+ });
352
+ await host.admin.suspendScope(staff, t, retryScope);
353
+ const held = await host.drainDue(t, retryScope).catch((error) => {
354
+ expect(String(error)).toMatch(/scope not active/);
355
+ return null;
356
+ });
357
+ expect(held === null || held.attempted === 0).toBe(true);
358
+ expect(ran).toEqual([]);
359
+ await host.admin.unsuspendScope(staff, t, retryScope);
360
+ expect((await host.drainDue(t, retryScope)).delivered).toBe(1);
361
+ expect(ran).toHaveLength(1);
362
+ expect((await host.drainDue(t, retryScope)).attempted).toBe(0);
363
+ });
364
+ it('a suspension inside the first delivery leaves later outbox work due', async () => {
365
+ const draining = scopeId.parse(ulid());
366
+ await host.provisionScope(staff, { tenantId: t, scopeId: draining, vertical: 'sched-vertical' });
367
+ await host.admin.activateScope(staff, t, draining);
368
+ const stub = await host.getSystemScope(SCHED_MODULE, t, draining);
369
+ await stub.invoke('sched/tick');
370
+ await stub.invoke('sched/tick');
371
+ const ran = [];
372
+ host.registerExecutor(`mid-suspend-${draining}`, 'sched.ticked', async (_admin, event) => {
373
+ ran.push(event.id);
374
+ if (ran.length === 1)
375
+ await host.admin.suspendScope(staff, t, draining);
376
+ });
377
+ const first = await host.drainDue(t, draining);
378
+ expect(first).toMatchObject({ attempted: 1, delivered: 1, lifecycleHeld: true });
379
+ expect(ran).toHaveLength(1);
380
+ await host.admin.unsuspendScope(staff, t, draining);
381
+ expect(await host.drainDue(t, draining)).toMatchObject({ attempted: 1, delivered: 1 });
382
+ expect(ran).toHaveLength(2);
383
+ expect((await host.drainDue(t, draining)).attempted).toBe(0);
384
+ });
237
385
  /**
238
386
  * #1288's backfill, on a dump captured before the column: a restore builds the table
239
387
  * from the kernel's DDL (#1883) and derives each row's `kind` from its key, by the
@@ -1 +1 @@
1
- {"version":3,"file":"schedule-suite.js","sourceRoot":"","sources":["../src/schedule-suite.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,QAAQ,CAAC;AACnE,OAAO,EAAE,QAAQ,EAAE,eAAe,EAAE,WAAW,EAAE,OAAO,EAAE,QAAQ,EAAoB,MAAM,yBAAyB,CAAC;AACtH,OAAO,EAAE,gBAAgB,EAAE,IAAI,EAAkC,MAAM,sBAAsB,CAAC;AAE9F,OAAO,EAAE,iBAAiB,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAE9D,MAAM,YAAY,GAAG,QAAQ,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;AACnD,MAAM,aAAa,GAAG,QAAQ,CAAC,KAAK,CAAC,oBAAoB,CAAC,CAAC;AAC3D,+EAA+E;AAC/E,MAAM,UAAU,GAAG,0BAA0B,CAAC;AAC9C,sFAAsF;AACtF,MAAM,OAAO,GAAG,CAAC,GAAG,EAAE;IACpB,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC,CAAC;AACtE,CAAC,CAAyB,CAAC;AAE3B;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,aAAa,CAA2B,MAAoB,EAAE,KAAa;IACzF,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,KAAK,IAAI,CAAC,CAAC,EAAE,CAAC,UAAU,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,CAAC;AAC9E,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CACnC,WAAmB,EACnB,WAA4C;IAE5C,QAAQ,CAAC,6BAA6B,WAAW,EAAE,EAAE,GAAG,EAAE;QACxD,IAAI,OAAyB,CAAC;QAC9B,IAAI,IAAe,CAAC;QACpB,MAAM,CAAC,GAAG,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACjC,MAAM,CAAC,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAChC,MAAM,MAAM,GAAgB,WAAW,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QACtD,MAAM,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;QAC5C,mFAAmF;QACnF,iFAAiF;QACjF,4CAA4C;QAC5C,IAAI,QAA6C,CAAC;QAElD,MAAM,KAAK,GAAG,GAAG,EAAE,CACjB,gBAAgB,CAAC,IAAI,EAAE;YACrB,KAAK,EAAE,KAAK;YACZ,KAAK,EAAE,OAAO;YACd,QAAQ,EAAE,EAAE;YACZ,sDAAsD;YACtD,YAAY,EAAE,KAAK;YACnB,WAAW,EAAE,KAAK;YAClB,mBAAmB,EAAE,KAAK;SAC3B,CAAC,CAAC;QAEL,SAAS,CAAC,KAAK,IAAI,EAAE;YACnB,OAAO,GAAG,MAAM,WAAW,EAAE,CAAC;YAC9B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC;YACpB,IAAI,CAAC,cAAc,CAAC,WAAW,CAAC,CAAC;YACjC,MAAM,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,EAAE,EAAE,CAAC,EAAE,IAAI,EAAE,OAAO,EAAE,IAAI,EAAE,OAAO,EAAE,CAAC,CAAC;YAC9E,MAAM,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,KAAK,EAAE,CAAC,EAAE,OAAO,CAAC,CAAC;YACrD,2EAA2E;YAC3E,0EAA0E;YAC1E,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAC1F,MAAM,IAAI,CAAC,KAAK,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9C,CAAC,CAAC,CAAC;QAEH,QAAQ,CAAC,KAAK,IAAI,EAAE;YAClB,MAAM,OAAO,CAAC,OAAO,EAAE,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,KAAK,IAAI,EAAE;YAC1E,MAAM,MAAM,GAAG,MAAM,KAAK,EAAE,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,QAAQ,EAAE,CAAC;YACxC,6EAA6E;YAC7E,MAAM,CAAC,MAAM,CAAC,SAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxC,gFAAgF;YAChF,yEAAyE;YACzE,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,aAAa,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC;YAC3E,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;gBACvB,OAAO,CAAC,IAAI,CAAC,+BAA+B,OAAO,CAAC,MAAM,8BAA8B,EAAE,OAAO,CAAC,CAAC;YACrG,CAAC;YACD,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAEpD,6EAA6E;YAC7E,6DAA6D;YAC7D,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,MAAM,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAInD,CAAC;YACJ,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,cAAc,CAAC,CAAC;YAC3D,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC3B,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,IAAK,CAAC,KAAK,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,MAAM,EAAE,aAAa,EAAE,CAAC,CAAC;YACnE,0EAA0E;YAC1E,8DAA8D;YAC9D,MAAM,CAAE,IAAsC,CAAC,SAAS,CAAC,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YAE7E,8EAA8E;YAC9E,+EAA+E;YAC/E,8EAA8E;YAC9E,MAAM,CAAC,IAAK,CAAC,aAAa,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAChD,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAIrD,CAAC;YACJ,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC;YAC5F,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,IAAK,CAAC,aAAa,CAAC,CAAC;YAC1D,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YAC/D,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;YAE/C,+EAA+E;YAC/E,kFAAkF;YAClF,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,KAAK,wBAAwB,CAC3E,CAAC;YACF,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,GAAG,CAAC,IAAI,CAAC,QAAS,CAAC,aAAa,CAAC,CAAC;YACtE,QAAQ,GAAG,EAAE,IAAI,EAAE,QAAS,CAAC,aAAc,EAAE,SAAS,EAAE,YAAa,CAAC,aAAc,EAAE,CAAC;QACzF,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,kDAAkD,EAAE,KAAK,IAAI,EAAE;YAChE,MAAM,MAAM,GAAG,MAAM,KAAK,EAAE,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,SAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,CAAC,MAAM,CAAC,SAAU,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC1C,sDAAsD;YACtD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACjD,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAKrD,CAAC;YACJ,+EAA+E;YAC/E,8EAA8E;YAC9E,gFAAgF;YAChF,uEAAuE;YACvE,2EAA2E;YAC3E,wCAAwC;YACxC,EAAE;YACF,6EAA6E;YAC7E,gFAAgF;YAChF,8EAA8E;YAC9E,8EAA8E;YAC9E,kEAAkE;YAClE,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;gBACpB,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;gBACpG;oBACE,IAAI,EAAE,UAAU;oBAChB,WAAW,EAAE,wBAAwB;oBACrC,WAAW,EAAE,IAAI;oBACjB,aAAa,EAAE,QAAQ,CAAC,SAAS;iBAClC;gBACD;oBACE,IAAI,EAAE,UAAU;oBAChB,WAAW,EAAE,YAAY;oBACzB,WAAW,EAAE,IAAI;oBACjB,aAAa,EAAE,QAAQ,CAAC,IAAI;iBAC7B;aACF,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,0EAA0E,EAAE,KAAK,IAAI,EAAE;YACxF,4EAA4E;YAC5E,2EAA2E;YAC3E,8EAA8E;YAC9E,kCAAkC;YAClC,MAAM,GAAG,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,YAAY,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC1D,MAAM,MAAM,CAAC,GAAG,CAAC,MAAM,CAAC,mBAAmB,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;QAClE,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,mDAAmD,EAAE,KAAK,IAAI,EAAE;YACjE,MAAM,MAAM,CACV,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,KAAK,CAAC,sBAAsB,CAAC,EAAE,CAAC,EAAE,CAAC,CAAC,CAClE,CAAC,OAAO,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC;QACtC,CAAC,CAAC,CAAC;QAEH;;;;;;;;;;;;;;;;;;WAkBG;QACH,EAAE,CAAC,iGAAiG,EAAE,KAAK,IAAI,EAAE;YAC/G,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YACvD,MAAM,UAAU,GAAG;gBACjB,GAAG,IAAI;gBACP,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAChC,KAAK,CAAC,IAAI,KAAK,0BAA0B;oBACvC,CAAC,CAAC;wBACE,IAAI,EAAE,KAAK,CAAC,IAAI;wBAChB,uEAAuE;wBACvE,gDAAgD;wBAChD,GAAG,EACD,wFAAwF;4BACxF,sEAAsE;wBACxE,OAAO,EAAE,CAAC,MAAM,EAAE,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC;wBAC9D,4DAA4D;wBAC5D,IAAI,EAAE,CAAC,CAAC,UAAU,EAAE,YAAY,EAAE,0BAA0B,EAAE,IAAI,CAAC,CAAC;qBACrE;oBACH,CAAC,CAAC,KAAK,CACV;aACF,CAAC;YACF,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE,UAAU,CAAC,CAAC;YAEjD,MAAM,MAAM,GAAG,MAAM,KAAK,EAAE,CAAC;YAC7B,gFAAgF;YAChF,gFAAgF;YAChF,2DAA2D;YAC3D,MAAM,CAAC,MAAM,CAAC,SAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACxC,MAAM,CAAC,aAAa,CAAC,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC;YAEpD,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAIrD,CAAC;YACJ,MAAM,QAAQ,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,KAAK,YAAY,CAAC,CAAC;YAC5F,MAAM,CAAC,QAAQ,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YACpD,+EAA+E;YAC/E,0DAA0D;YAC1D,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,WAAW,CAAC,CAAC;YAC/D,MAAM,CAAC,YAAY,EAAE,aAAa,CAAC,CAAC,QAAQ,EAAE,CAAC;QACjD,CAAC,CAAC,CAAC;QAEH;;;;;;;;;;;;;WAaG;QACH,EAAE,CAAC,gFAAgF,EAAE,KAAK,IAAI,EAAE;YAC9F,IAAI,CAAC,cAAc,CAAC,iBAAiB,CAAC,CAAC;YACvC,MAAM,IAAI,CAAC,cAAc,CAAC,KAAK,EAAE,EAAE,QAAQ,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,QAAQ,EAAE,gBAAgB,EAAE,CAAC,CAAC;YAE1F,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,eAAe,CAAC,aAAa,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/D,MAAM,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YAE9B,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAKrD,CAAC;YACJ,MAAM,SAAS,GAAG,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,CAAC,WAAW,KAAK,mBAAmB,CAAC,CAAC;YACpG,MAAM,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YAC9C,MAAM,CAAC,SAAS,EAAE,aAAa,CAAC,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;YAErD,2EAA2E;YAC3E,8EAA8E;YAC9E,0BAA0B;YAC1B,MAAM,OAAO,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAGrD,CAAC;YACJ,MAAM,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,mBAAmB,CAAC,CAAC;YACxE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC,IAAI,CAAC,SAAU,CAAC,aAAa,CAAC,CAAC;QAC/D,CAAC,CAAC,CAAC;QAEH;;;;;;;;;WASG;QACH,EAAE,CAAC,8EAA8E,EAAE,KAAK,IAAI,EAAE;YAC5F,MAAM,IAAI,CAAC,YAAY,CAAC,KAAK,EAAE,CAAC,EAAE,CAAC,EAAE;gBACnC,QAAQ,EAAE,CAAC;gBACX,OAAO,EAAE,CAAC;gBACV,UAAU,EAAE,0BAA0B;gBACtC,MAAM,EAAE;oBACN;wBACE,IAAI,EAAE,0BAA0B;wBAChC,wEAAwE;wBACxE,uEAAuE;wBACvE,kCAAkC;wBAClC,GAAG,EACD,uEAAuE;4BACvE,qCAAqC;wBACvC,OAAO,EAAE,CAAC,aAAa,EAAE,aAAa,EAAE,aAAa,CAAC;wBACtD,IAAI,EAAE;4BACJ,CAAC,wBAAwB,EAAE,0BAA0B,EAAE,QAAQ,CAAC;4BAChE,CAAC,YAAY,EAAE,0BAA0B,EAAE,IAAI,CAAC;yBACjD;qBACF;iBACF;aACF,CAAC,CAAC;YAEH,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,CAAC,CAAC;YAC/C,MAAM,KAAK,GAAG,CAAC,MAAM,IAAI,CAAC,MAAM,CAAC,sBAAsB,CAAC,CAKrD,CAAC;YACJ,iFAAiF;YACjF,6EAA6E;YAC7E,4EAA4E;YAC5E,2EAA2E;YAC3E,mDAAmD;YACnD,EAAE;YACF,gFAAgF;YAChF,iFAAiF;YACjF,+EAA+E;YAC/E,MAAM,CAAC,KAAK,CAAC,CAAC,OAAO,CAAC;gBACpB,EAAE,IAAI,EAAE,WAAW,EAAE,WAAW,EAAE,wBAAwB,EAAE,WAAW,EAAE,QAAQ,EAAE,aAAa,EAAE,IAAI,EAAE;gBACxG,EAAE,IAAI,EAAE,UAAU,EAAE,WAAW,EAAE,YAAY,EAAE,WAAW,EAAE,IAAI,EAAE,aAAa,EAAE,IAAI,EAAE;aACxF,CAAC,CAAC;QACL,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC"}
1
+ {"version":3,"file":"schedule-suite.js","sourceRoot":"","sources":["../src/schedule-suite.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"scope-host-suite.d.ts","sourceRoot":"","sources":["../src/scope-host-suite.ts"],"names":[],"mappings":"AAEA,OAAO,EAqBL,KAAK,SAAS,EAcf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAaL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAY9B,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AA2BD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,MACrB,OAAO,CAAC,OAAO,CAAC,QACb,SAAS,YACL,MAAM,KACf,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,EAC5C,IAAI,GAAE,qBAA0B,GAC/B,IAAI,CAm4RN"}
1
+ {"version":3,"file":"scope-host-suite.d.ts","sourceRoot":"","sources":["../src/scope-host-suite.ts"],"names":[],"mappings":"AAEA,OAAO,EAqBL,KAAK,SAAS,EAkBf,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAcL,KAAK,SAAS,EACf,MAAM,sBAAsB,CAAC;AAY9B,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,SAAS,CAAC;IAChB;;;;;OAKG;IACH,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,OAAO,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;CAC1B;AA2BD;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,eAAO,MAAM,aAAa,MACrB,OAAO,CAAC,OAAO,CAAC,QACb,SAAS,YACL,MAAM,KACf,OAAO,CAAC,IAAI,CAOd,CAAC;AAEF,iFAAiF;AACjF,MAAM,WAAW,qBAAqB;IACpC;;;;;;OAMG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;CACvC;AAED;;;;;GAKG;AACH,wBAAgB,sBAAsB,CACpC,WAAW,EAAE,MAAM,EACnB,WAAW,EAAE,MAAM,OAAO,CAAC,gBAAgB,CAAC,EAC5C,IAAI,GAAE,qBAA0B,GAC/B,IAAI,CAonSN"}
@@ -1,7 +1,7 @@
1
1
  import { describe, it, expect, beforeAll, afterAll } from 'vitest';
2
2
  import { connectorCalls, connectorTestFetch, resetConnectorCalls } from './connector-fixture.js';
3
- import { connectionId, dataSubjectId, domainEvent, errorCodeOf, moduleId, SCOPE_GATE_REASONS, eventId, instant, moduleManifest, orgId, AUTO_ADMISSION_NOTE, permissionKey, platformActorId, platformRequestId, principalId, scopeId, tenantId, SCOPE_QUERY_ROW_MAX, KERNEL_AUTHORED_EVENT_TYPES, SWEEP_RUNS_KIND, SCOPE_TABLE_PAGE_MAX, } from '@substrat-run/contracts';
4
- import { INERT_SCOPE_REASON, isSearchIndexTable, platformIntentFailureMessage, REDACTED_DELIVERY_NOTE, REDACTED_FAILURE_NOTE, REDACTED_INTENT_MARKER, runPlatformSweep, startPlatformSweeper, createUlid, ulid, } from '@substrat-run/kernel';
3
+ import { connectionId, dataSubjectId, domainEvent, errorCodeOf, moduleId, SCOPE_GATE_REASONS, eventId, instant, moduleManifest, orgId, AUTO_ADMISSION_NOTE, permissionKey, platformActorId, platformRequestId, principalId, scopeId, tenantId, SCOPE_QUERY_ROW_MAX, KERNEL_AUTHORED_EVENT_TYPES, EMAIL_SENT, PLATFORM_REQUEST_ENTITY_TYPE, SEND_EMAIL_KIND, SWEEP_RUNS_KIND, SCOPE_TABLE_PAGE_MAX, } from '@substrat-run/contracts';
4
+ import { INERT_SCOPE_REASON, SCOPE_COPY_LEASE_MS, isSearchIndexTable, platformIntentFailureMessage, REDACTED_DELIVERY_NOTE, REDACTED_FAILURE_NOTE, REDACTED_INTENT_MARKER, runPlatformSweep, startPlatformSweeper, createUlid, ulid, } from '@substrat-run/kernel';
5
5
  import { billedMod, contractTestBareOps, contractTestInitialModules, gateModManifest, lateMod, TEST_LIFECYCLE, testModManifest, victimModManifest, } from './modules.js';
6
6
  /**
7
7
  * Assert a refusal by the CODE it declared, not by the sentence it happens to carry
@@ -273,6 +273,45 @@ export function scopeHostContractSuite(adapterName, makeFixture, opts = {}) {
273
273
  expect(settled.status).toBe('done');
274
274
  expect(JSON.parse(settled.result)).toEqual({ scopeId: 'NEWSITE' });
275
275
  });
276
+ it('a settle carrying an outcome event writes it once, as the kernel, with the settle (#2102)', async () => {
277
+ const stub = await host.getScope(alice, t1, s1);
278
+ const mail = { to: 'ada@example.com', subject: 'Hej', html: '<p>Hej</p>', text: 'Hej' };
279
+ const id = await stub.invoke('platform/request', { kind: SEND_EMAIL_KIND, payload: mail });
280
+ const mine = () => stub
281
+ .invoke('platform/outcome-events')
282
+ .then((rows) => rows.filter((r) => JSON.parse(r.payload).request === id));
283
+ const event = (request) => ({
284
+ type: EMAIL_SENT,
285
+ entity: { entityType: PLATFORM_REQUEST_ENTITY_TYPE, entityId: id },
286
+ payload: {
287
+ request: platformRequestId.parse(request),
288
+ about: null,
289
+ sender: 'platform',
290
+ messageId: 'msg-1',
291
+ attempts: 1,
292
+ code: null,
293
+ status: null,
294
+ },
295
+ });
296
+ // Refused before anything is written: an event on a `pending` settle, or one naming
297
+ // another request. The row stays exactly as it was.
298
+ await expect(host.settlePlatformRequest(t1, s1, platformRequestId.parse(id), { status: 'pending', event: event(id) })).rejects.toThrow();
299
+ await expect(host.settlePlatformRequest(t1, s1, platformRequestId.parse(id), { status: 'done', event: event(ulid()) })).rejects.toThrow();
300
+ expect((await host.listPlatformRequests(t1, s1)).find((r) => r.id === id)?.attempts).toBe(0);
301
+ expect(await mine()).toEqual([]);
302
+ await host.settlePlatformRequest(t1, s1, platformRequestId.parse(id), { status: 'done', event: event(id) });
303
+ const written = await mine();
304
+ expect(written).toHaveLength(1);
305
+ expect(written[0].type).toBe(EMAIL_SENT);
306
+ expect(JSON.parse(written[0].actor)).toEqual({ system: '@substrat-run/kernel' });
307
+ expect([written[0].entity_type, written[0].entity_id]).toEqual([PLATFORM_REQUEST_ENTITY_TYPE, id]);
308
+ expect(JSON.parse(written[0].payload)).toMatchObject({ request: id, messageId: 'msg-1', sender: 'platform' });
309
+ // A repeated settle finds the row terminal: it moves nothing, so it writes nothing.
310
+ await host.settlePlatformRequest(t1, s1, platformRequestId.parse(id), { status: 'failed', event: event(id) });
311
+ expect(await mine()).toHaveLength(1);
312
+ const row = (await stub.invoke('platform/read-requests')).find((r) => r.id === id);
313
+ expect(row.status).toBe('done');
314
+ });
276
315
  it('a transient failure keeps the intent pending and preserves a two-phase result (retry)', async () => {
277
316
  const stub = await host.getScope(alice, t1, s1);
278
317
  const id = await stub.invoke('platform/request', { kind: 'provision-sibling', payload: {} });
@@ -4400,6 +4439,20 @@ export function scopeHostContractSuite(adapterName, makeFixture, opts = {}) {
4400
4439
  expect(rotated?.after).toMatchObject({ id: row.id, rotatedBy: officeAdmin });
4401
4440
  expect(JSON.stringify(log)).not.toContain('tok-relay-rotated');
4402
4441
  });
4442
+ it('a rotation sets the expiry, keeps it when omitted, and clears it with null (#2100)', async () => {
4443
+ const [row] = await host.admin.listConnections(staff, { tenantId: t1, vertical: 'callout' });
4444
+ const expiry = async () => (await host.admin.listConnections(staff, { tenantId: t1, vertical: 'callout' })).find((c) => c.id === row.id)
4445
+ .expiresAt;
4446
+ const at = '2027-10-07T12:00:00.000Z';
4447
+ await host.admin.updateConnectionSecret(staff, row.id, { accessToken: 'tok-dated' }, at);
4448
+ expect(await expiry()).toBe(at);
4449
+ await host.admin.updateConnectionSecret(staff, row.id, { accessToken: 'tok-kept' });
4450
+ expect(await expiry()).toBe(at);
4451
+ // The credential that had an end was replaced by one that has none (a certificate → a
4452
+ // client secret): the old end must not stay on the connection, reading as this one's.
4453
+ await host.admin.updateConnectionSecret(staff, row.id, { accessToken: 'tok-undated' }, null);
4454
+ expect(await expiry()).toBeNull();
4455
+ });
4403
4456
  it('records health, and a success clears a prior error', async () => {
4404
4457
  const [row] = await host.admin.listConnections(staff, {
4405
4458
  tenantId: t1,
@@ -4829,6 +4882,166 @@ export function scopeHostContractSuite(adapterName, makeFixture, opts = {}) {
4829
4882
  await host.admin.bindScopeVersion(staff, t1, s, v1); // legacy unconditional caller
4830
4883
  expect((await host.admin.getScopeRecord(staff, t1, s)).verticalVersionId).toBe(v1);
4831
4884
  });
4885
+ it('copy ledger is additive, scoped by tenant and scope, and fences old move receipts (#1722)', async () => {
4886
+ const s = scopeId.parse(ulid());
4887
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s });
4888
+ const ref = `version-${ulid().toLowerCase()}`;
4889
+ const first = ulid();
4890
+ const next = ulid();
4891
+ await host.admin.recordScopeScriptCopy(staff, t1, s, ref, first);
4892
+ await host.admin.recordScopeScriptCopy(staff, t1, s, ref, first); // retry keeps its state
4893
+ await expect(host.admin.recordScopeScriptCopy(staff, t2, s, ref, next)).rejects.toThrow();
4894
+ expect(await host.admin.listScopeScriptCopies(staff, { tenantId: t2, scopeId: s })).toEqual([]);
4895
+ expect(await host.admin.settleScopeScriptCopy(staff, t2, s, ref, first, 'done')).toBe(false);
4896
+ const other = scopeId.parse(ulid());
4897
+ await host.provisionScope(staff, { tenantId: t1, scopeId: other });
4898
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, other, ref, first, 'done')).toBe(false);
4899
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, s, ref, first, 'eligible', { loadStamp: 'stamp', revision: '2' })).toBe(true);
4900
+ await host.admin.recordScopeScriptCopy(staff, t1, s, ref, next);
4901
+ await host.admin.recordScopeScriptCopy(staff, t1, s, ref, first);
4902
+ expect(await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s, state: 'eligible' })).toHaveLength(1);
4903
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, s, ref, first, 'done')).toBe(true);
4904
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, s, ref, first, 'eligible')).toBe(false);
4905
+ expect((await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s }))
4906
+ .map(({ moveId, state }) => ({ moveId, state })).sort((a, b) => a.moveId.localeCompare(b.moveId)))
4907
+ .toEqual([{ moveId: first, state: 'done' }, { moveId: next, state: 'pending' }]
4908
+ .sort((a, b) => a.moveId.localeCompare(b.moveId)));
4909
+ const [pageOne] = await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s, limit: 1 });
4910
+ const pageTwo = await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s, limit: 1,
4911
+ after: { scriptRef: pageOne.scriptRef, moveId: pageOne.moveId } });
4912
+ expect(pageTwo).toHaveLength(1);
4913
+ expect(pageTwo[0].moveId).not.toBe(pageOne.moveId);
4914
+ expect((await host.admin.getScopeRecord(staff, t1, s))?.tenantId).toBe(t1);
4915
+ await expectRefusal(host.admin.beginScopeScriptReap(staff, t1, s), 'precondition_failed');
4916
+ await host.admin.settleScopeScriptCopy(staff, t1, s, ref, next, 'retained');
4917
+ const beforeClaim = await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s });
4918
+ await host.admin.beginScopeScriptReap(staff, t1, s);
4919
+ await host.admin.beginScopeScriptReap(staff, t1, s); // retry the same claim
4920
+ await expectRefusal(host.admin.recordScopeScriptCopy(staff, t1, s, ref, ulid()), 'precondition_failed');
4921
+ await host.admin.recordScopeScriptCopy(staff, t1, other, ref, ulid());
4922
+ // The reap claim lives on the directory row, never in the ledger: every listing, scoped or
4923
+ // fleet-wide and in every state, holds only the copies recorded above, so counts and pages
4924
+ // are unchanged by the claim.
4925
+ expect(await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s })).toEqual(beforeClaim);
4926
+ for (const state of [undefined, 'pending', 'eligible', 'retained', 'kept', 'done']) {
4927
+ const listed = await host.admin.listScopeScriptCopies(staff, { ...(state ? { state } : {}), limit: 1000 });
4928
+ expect(listed.filter((copy) => copy.tenantId === t1 && copy.scopeId === s)
4929
+ .every((copy) => copy.scriptRef === ref && [first, next].includes(copy.moveId))).toBe(true);
4930
+ }
4931
+ expect(beforeClaim.map((copy) => copy.moveId).sort()).toEqual([first, next].sort());
4932
+ });
4933
+ it('a pending copy entry is claimed only once its lease ran out, and only once (#1722)', async () => {
4934
+ const s = scopeId.parse(ulid());
4935
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s });
4936
+ const move = ulid();
4937
+ const [from, to] = [`version-${ulid().toLowerCase()}`, `version-${ulid().toLowerCase()}`];
4938
+ await host.admin.recordScopeScriptCopy(staff, t1, s, from, move, { role: 'source' });
4939
+ await host.admin.recordScopeScriptCopy(staff, t1, s, to, move, { role: 'destination', loadStamp: 'restore-stamp' });
4940
+ const mine = (copies) => copies.filter((copy) => copy.scopeId === s);
4941
+ const listed = await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s });
4942
+ expect(listed.map(({ scriptRef, role, loadStamp, state }) => ({ scriptRef, role, loadStamp, state }))
4943
+ .sort((a, b) => a.scriptRef.localeCompare(b.scriptRef))).toEqual([
4944
+ { scriptRef: from, role: 'source', loadStamp: null, state: 'pending' },
4945
+ { scriptRef: to, role: 'destination', loadStamp: 'restore-stamp', state: 'pending' },
4946
+ ].sort((a, b) => a.scriptRef.localeCompare(b.scriptRef)));
4947
+ expect(listed.every((copy) => copy.leaseUntil !== null && copy.leaseUntil > new Date().toISOString())).toBe(true);
4948
+ // A live lease: the move is still in flight, and no sweep may settle it.
4949
+ const now = new Date();
4950
+ expect(mine(await host.admin.claimExpiredScopeScriptCopies(staff, { now: now.toISOString(), leaseUntil: new Date(now.getTime() + 1000).toISOString(), owner: 'sweep:a', limit: 1000 }))).toEqual([]);
4951
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, s, to, move, 'done', undefined, { claimedBy: 'sweep:a' })).toBe(false);
4952
+ // Past the lease: one sweep claims both, and a second sweep inside the first one's lease does not.
4953
+ const later = new Date(Date.now() + SCOPE_COPY_LEASE_MS + 60_000);
4954
+ const leaseUntil = new Date(later.getTime() + SCOPE_COPY_LEASE_MS).toISOString();
4955
+ const claimed = mine(await host.admin.claimExpiredScopeScriptCopies(staff, { now: later.toISOString(), leaseUntil, owner: 'sweep:a', limit: 1000 }));
4956
+ expect(claimed.map((copy) => copy.scriptRef).sort()).toEqual([from, to].sort());
4957
+ expect(claimed.every((copy) => copy.leaseUntil === leaseUntil)).toBe(true);
4958
+ expect(mine(await host.admin.claimExpiredScopeScriptCopies(staff, { now: later.toISOString(), leaseUntil, owner: 'sweep:b', limit: 1000 }))).toEqual([]);
4959
+ // Settled only by its claimant.
4960
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, s, to, move, 'done', undefined, { claimedBy: 'sweep:b' })).toBe(false);
4961
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, s, to, move, 'done', undefined, { claimedBy: 'sweep:a' })).toBe(true);
4962
+ expect(await host.admin.settleScopeScriptCopy(staff, t1, s, from, move, 'retained', undefined, { claimedBy: 'sweep:a' })).toBe(true);
4963
+ // A claimed move can no longer confirm a bind: the sweep and the move never both act.
4964
+ const route = `version-${ulid().toLowerCase()}`;
4965
+ await expectRefusal(host.admin.setScopeServingRef(staff, t1, s, route, { expectedErasureEpoch: 0, confirmMove: { moveId: move, source: 'eligible' } }), 'precondition_failed');
4966
+ expect((await host.admin.getScopeRecord(staff, t1, s))?.servingRef ?? null).toBeNull();
4967
+ });
4968
+ it('a copy move confirms with the bind that routes onto it, in the same write (#1722)', async () => {
4969
+ const s = scopeId.parse(ulid());
4970
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s });
4971
+ const [from, to] = [`version-${ulid().toLowerCase()}`, `version-${ulid().toLowerCase()}`];
4972
+ const move = ulid();
4973
+ await host.admin.recordScopeScriptCopy(staff, t1, s, from, move, { role: 'source' });
4974
+ await host.admin.recordScopeScriptCopy(staff, t1, s, to, move, { role: 'destination', loadStamp: 'restore-stamp' });
4975
+ // A confirmation naming another move refuses, and writes nothing.
4976
+ await expectRefusal(host.admin.setScopeServingRef(staff, t1, s, to, { expectedErasureEpoch: 0, confirmMove: { moveId: ulid(), source: 'eligible' } }), 'precondition_failed');
4977
+ await host.admin.setScopeServingRef(staff, t1, s, to, {
4978
+ expectedErasureEpoch: 0,
4979
+ confirmMove: { moveId: move, source: 'eligible', sourceMarker: { loadStamp: 'export-stamp', revision: '7' } },
4980
+ });
4981
+ expect((await host.admin.getScopeRecord(staff, t1, s))?.servingRef).toBe(to);
4982
+ const settled = await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s });
4983
+ expect(settled.map(({ scriptRef, state, loadStamp, revision }) => ({ scriptRef, state, loadStamp, revision }))
4984
+ .sort((a, b) => a.scriptRef.localeCompare(b.scriptRef))).toEqual([
4985
+ { scriptRef: from, state: 'eligible', loadStamp: 'export-stamp', revision: '7' },
4986
+ { scriptRef: to, state: 'done', loadStamp: 'restore-stamp', revision: null },
4987
+ ].sort((a, b) => a.scriptRef.localeCompare(b.scriptRef)));
4988
+ // Nothing of a confirmed move is left for a crash-recovery sweep.
4989
+ const later = new Date(Date.now() + SCOPE_COPY_LEASE_MS + 60_000);
4990
+ expect((await host.admin.claimExpiredScopeScriptCopies(staff, { now: later.toISOString(),
4991
+ leaseUntil: later.toISOString(), owner: 'sweep:c', limit: 1000 })).filter((copy) => copy.scopeId === s)).toEqual([]);
4992
+ // And it confirms once: the same confirmation again refuses.
4993
+ await expectRefusal(host.admin.setScopeServingRef(staff, t1, s, from, { expectedErasureEpoch: 0, confirmMove: { moveId: move, source: 'eligible' } }), 'precondition_failed');
4994
+ });
4995
+ it('a reap claim refuses a conditional bind until the scope row is deleted (#1722)', async () => {
4996
+ const s = scopeId.parse(ulid());
4997
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s });
4998
+ await host.admin.beginScopeScriptReap(staff, t1, s);
4999
+ await expectRefusal(host.admin.setScopeServingRef(staff, t1, s, `version-${ulid().toLowerCase()}`, { expectedErasureEpoch: 0 }), 'precondition_failed');
5000
+ expect((await host.admin.getScopeRecord(staff, t1, s))?.servingRef ?? null).toBeNull();
5001
+ await expectRefusal(host.admin.recordScopeScriptCopy(staff, t1, s, `version-${ulid().toLowerCase()}`, ulid()), 'precondition_failed');
5002
+ // The claim survives a reaper that crashed: a second reaper resumes it, and it still refuses.
5003
+ await host.admin.beginScopeScriptReap(staff, t1, s);
5004
+ await expectRefusal(host.admin.recordScopeScriptCopy(staff, t1, s, `version-${ulid().toLowerCase()}`, ulid()), 'precondition_failed');
5005
+ });
5006
+ it('an erasure during a reap counts only real copies, so the claim cannot stall it (#1722)', async () => {
5007
+ const s = scopeId.parse(ulid());
5008
+ const subject = ulid();
5009
+ const move = ulid();
5010
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s });
5011
+ const [sealed] = await host.admin.sealSubjectPayloads(staff, t1, s, [{ subjectId: subject, plaintext: 'private' }]);
5012
+ const ref = `version-${ulid().toLowerCase()}`;
5013
+ await host.admin.recordScopeScriptCopy(staff, t1, s, ref, move);
5014
+ await host.admin.settleScopeScriptCopy(staff, t1, s, ref, move, 'retained');
5015
+ await host.admin.beginScopeScriptReap(staff, t1, s);
5016
+ const copies = await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s });
5017
+ expect(copies.map((copy) => copy.moveId)).toEqual([move]);
5018
+ const redacted = [{ events: 0, intents: 0, jobRuns: 0, idempotencyResults: 0, intentIds: [],
5019
+ vertical: { verticalRows: [], hookRows: [], unreachedEntities: [] } }];
5020
+ expect((await host.admin.finalizeSubjectShred(staff, t1, s, subject, redacted, { versionId: null, servingRef: null, epoch: 0, copyCount: copies.length })).keyDestroyed).toBe(true);
5021
+ expect(await host.admin.openSubjectPayloads(staff, t1, s, [{ subjectId: subject, sealed: sealed }])).toEqual([null]);
5022
+ });
5023
+ it('subject keys survive a pending copy move until every copy can be reached (#1722)', async () => {
5024
+ const s = scopeId.parse(ulid());
5025
+ const subject = ulid();
5026
+ const move = ulid();
5027
+ await host.provisionScope(staff, { tenantId: t1, scopeId: s });
5028
+ const [sealed] = await host.admin.sealSubjectPayloads(staff, t1, s, [{ subjectId: subject, plaintext: 'private' }]);
5029
+ await host.admin.recordScopeScriptCopy(staff, t1, s, `version-${ulid().toLowerCase()}`, move);
5030
+ const [copy] = await host.admin.listScopeScriptCopies(staff, { tenantId: t1, scopeId: s });
5031
+ const redacted = [{ events: 0, intents: 0, jobRuns: 0, idempotencyResults: 0, intentIds: [],
5032
+ vertical: { verticalRows: [], hookRows: [], unreachedEntities: [] } }];
5033
+ const expected = { versionId: null, servingRef: null, epoch: 0, copyCount: 1 };
5034
+ await expectRefusal(host.admin.finalizeSubjectShred(staff, t1, s, subject, redacted, expected), 'precondition_failed');
5035
+ expect(await host.admin.openSubjectPayloads(staff, t1, s, [{ subjectId: subject, sealed: sealed }]))
5036
+ .toEqual(['private']);
5037
+ await host.admin.settleScopeScriptCopy(staff, t1, s, copy.scriptRef, move, 'retained');
5038
+ await expectRefusal(host.admin.finalizeSubjectShred(staff, t1, s, subject, redacted, { ...expected, copyCount: 0 }), 'precondition_failed');
5039
+ expect(await host.admin.openSubjectPayloads(staff, t1, s, [{ subjectId: subject, sealed: sealed }]))
5040
+ .toEqual(['private']);
5041
+ expect((await host.admin.finalizeSubjectShred(staff, t1, s, subject, redacted, expected)).keyDestroyed).toBe(true);
5042
+ expect(await host.admin.openSubjectPayloads(staff, t1, s, [{ subjectId: subject, sealed: sealed }]))
5043
+ .toEqual([null]);
5044
+ });
4832
5045
  // #1722 (Codex #2008 r7): the admin-log record of a staff resolution of a kept copy. The
4833
5046
  // resolution itself runs in the vertical's store; the directory only records it, in full.
4834
5047
  it('records a kept-copy resolution in the admin log, before and after, and refuses an unknown scope', async () => {