task(ids): replace remaining Date.now() auto-ids with randomUUID - fixes BUG-1 collision class across 9 entities

This commit is contained in:
Agent Zero
2026-08-28 13:42:46 +02:00
parent 7c94de1590
commit c78d8d8334
2 changed files with 78 additions and 9 deletions
+69
View File
@@ -381,3 +381,72 @@ describe('SqliteAdapter', () => {
});
});
});
// ─── ID-Kollisionsklasse: Date.now() → randomUUID (BUG-1-Familie) ──
// Deterministischer Beweis: Date.now() wird via Fake-Timers EINGEFROREN,
// damit zwei Creates garantiert im selben Tick landen. Mit Date.now()-IDs
// kollidiert der zweite INSERT am PRIMARY KEY (UNIQUE-Exception); mit
// randomUUID sind die IDs stets eindeutig.
import { vi } from 'vitest';
const FROZEN_NOW = 1756000000000;
describe('SqliteAdapter auto-ID uniqueness within same tick', () => {
let db: SqliteAdapter;
beforeAll(async () => {
vi.useFakeTimers();
vi.setSystemTime(FROZEN_NOW);
db = new SqliteAdapter(':memory:');
await db.init();
});
afterAll(() => {
db.close();
vi.useRealTimers();
});
it('createUser liefert unterschiedliche IDs bei zwei Creates im selben Tick', () => {
const a = db.createUser({ email: `tick-a-${Date.now()}@x.de`, password_hash: 'h', name: 'A' });
const b = db.createUser({ email: `tick-b-${Date.now()}@x.de`, password_hash: 'h', name: 'B' });
expect(b.id).not.toBe(a.id);
});
it('createProject/createProjectFolder liefern unterschiedliche IDs im selben Tick', () => {
const p1 = db.createProject({ name: 'P1' });
const p2 = db.createProject({ name: 'P2' });
expect(p2.id).not.toBe(p1.id);
const f1 = db.createProjectFolder({ name: 'F1' });
const f2 = db.createProjectFolder({ name: 'F2' });
expect(f2.id).not.toBe(f1.id);
});
it('createDrawing/createLayer/createElement/createBlock liefern unterschiedliche IDs im selben Tick', () => {
const proj = db.createProject({ name: 'DrawHost' });
const d1 = db.createDrawing({ project_id: proj.id, name: 'D1' });
const d2 = db.createDrawing({ project_id: proj.id, name: 'D2' });
expect(d2.id).not.toBe(d1.id);
const l1 = db.createLayer({ drawing_id: d1.id, name: 'L1' });
const l2 = db.createLayer({ drawing_id: d1.id, name: 'L2' });
expect(l2.id).not.toBe(l1.id);
const e1 = db.createElement({ drawing_id: d1.id, layer_id: l1.id, type: 'line' });
const e2 = db.createElement({ drawing_id: d1.id, layer_id: l1.id, type: 'line' });
expect(e2.id).not.toBe(e1.id);
const b1 = db.createBlock({ drawing_id: d1.id, name: 'B1' });
const b2 = db.createBlock({ drawing_id: d1.id, name: 'B2' });
expect(b2.id).not.toBe(b1.id);
});
it('createNotification/createProjectShare liefern unterschiedliche IDs im selben Tick', () => {
const proj = db.createProject({ name: 'ShareHost' });
const n1 = db.createNotification({ user_id: 'user-default', title: 'T1', message: 'M1' });
const n2 = db.createNotification({ user_id: 'user-default', title: 'T2', message: 'M2' });
expect(n2.id).not.toBe(n1.id);
const s1 = db.createProjectShare({ project_id: proj.id, shared_with_email: 'a@x.de', shared_by: 'user-default' });
const s2 = db.createProjectShare({ project_id: proj.id, shared_with_email: 'b@x.de', shared_by: 'user-default' });
expect(s2.id).not.toBe(s1.id);
});
});