| … | … | @@ -504,3 +504,45 @@ test('listAllIdentities', async (t) => { |
| 504 | 504 | |
| 505 | 505 | await cleanup() |
| 506 | 506 | }) |
| 507 | |
| 508 | // --- Timestamp preservation (identity-publish-reconciler prerequisite) --- |
| 509 | // The reconciler re-emits records it already holds. createUser must NOT bump |
| 510 | // the record's clock when explicit timestamps are passed, or a re-announce |
| 511 | // would out-clock a peer's newer edit and break keyed LWW convergence. |
| 512 | |
| 513 | test('createUser preserves explicit createdAt/updatedAt', async (t) => { |
| 514 | const { registry, cleanup } = await createRegistry() |
| 515 | |
| 516 | // Bootstrap a first user so the replayed one isn't the first-admin (and to |
| 517 | // mirror the real reconcile path where the registry is already populated). |
| 518 | await registry.createUser({ name: 'Admin' }) |
| 519 | |
| 520 | const createdAt = 1700000000000 |
| 521 | const updatedAt = 1700000500000 |
| 522 | const user = await registry.createUser({ |
| 523 | userId: 'replayed-uid-1', |
| 524 | name: 'Replayed', |
| 525 | createdAt, |
| 526 | updatedAt |
| 527 | }) |
| 528 | t.is(user.createdAt, createdAt, 'createdAt preserved on return') |
| 529 | t.is(user.updatedAt, updatedAt, 'updatedAt preserved on return') |
| 530 | |
| 531 | const fetched = await registry.getUser('replayed-uid-1') |
| 532 | t.is(fetched.createdAt, createdAt, 'createdAt persisted in view') |
| 533 | t.is(fetched.updatedAt, updatedAt, 'updatedAt persisted in view') |
| 534 | |
| 535 | await cleanup() |
| 536 | }) |
| 537 | |
| 538 | test('createUser defaults timestamps to now when not provided', async (t) => { |
| 539 | const { registry, cleanup } = await createRegistry() |
| 540 | |
| 541 | const before = Date.now() |
| 542 | const user = await registry.createUser({ name: 'NowUser' }) |
| 543 | t.ok(user.createdAt >= before, 'createdAt defaulted to ~now') |
| 544 | t.ok(user.updatedAt >= before, 'updatedAt defaulted to ~now') |
| 545 | t.ok(typeof user.updatedAt === 'number', 'updatedAt is set even without opts') |
| 546 | |
| 547 | await cleanup() |
| 548 | }) |