// SPDX-License-Identifier: GPL-2.0-or-later // Copyright (C) 2026 Bryan Joshua Pedini /** * PLAN §12 core item 13: a large token population (300 tokens, created only through the binary) * with listing, deletion, authentication and audit checks (SQLite and the `audit` command) against * that population. */ import { test, expect, assertDbInvariants, expectCliFailure, expectContainersResponse, expectErrorResponse, formatAuditOutput, mapLimit, readOperations, readTokens, rfc3339ToNanos, } from '../../harness'; import { expectedAuditStdout } from '../../harness/personas'; const N = 300; test('300 tokens: create, list, delete, authenticate and audit', async ({ cli, startServer, http, ws, rng }) => { test.setTimeout(240_000); const server = await startServer(); server.fakeDocker!.many(1); // Created through the binary, 12 CLI processes at a time, while the server is running const descriptions = Array.from({ length: N }, (_, i) => (i % 10 === 0 ? `pop ${i} ünïcødé ✓` : i % 7 === 0 ? '' : `pop ${i}`)); const tokens = await mapLimit(descriptions, 12, (d) => cli.tokenNew(d)); expect(new Set(tokens).size, 'all tokens distinct').toBe(N); // list const rows = await cli.tokenList(); expect(rows).toHaveLength(N); const byToken = new Map(rows.map((r) => [r.token, r])); tokens.forEach((t, i) => expect(byToken.get(t)?.description).toBe(descriptions[i])); for (let i = 1; i < rows.length; i++) { const a = rfc3339ToNanos(rows[i - 1].createdAt); const b = rfc3339ToNanos(rows[i].createdAt); expect(a < b || (a === b && rows[i - 1].token < rows[i].token)).toBe(true); } expect(rows.every((r) => r.active && r.deletedAt === null)).toBe(true); // delete a random third, 8 at a time const shuffled = rng.shuffle(tokens); const deleted = shuffled.slice(0, 100); const alive = shuffled.slice(100); await mapLimit(deleted, 8, (t) => cli.tokenDelete(t)); const after = await cli.tokenListAll(); expect(after.filter((r) => !r.active).map((r) => r.token).sort()).toEqual([...deleted].sort()); expect(after.filter((r) => r.active)).toHaveLength(200); expect(after.filter((r) => !r.active).every((r) => r.deletedAt !== null)).toBe(true); // plain `token list`: exactly the 200 alive tokens, in the same relative order as `token list all` const activeOnly = await cli.tokenList(); expect(activeOnly.map((r) => r.token)).toEqual(after.filter((r) => r.active).map((r) => r.token)); expect(new Set(activeOnly.map((r) => r.token))).toEqual(new Set(alive)); // authenticate: 60 alive (200), 40 deleted (401), 20 unknown (401), concurrently const probes = rng.shuffle([ ...alive.slice(0, 60).map((t) => ({ t, ok: true })), ...deleted.slice(0, 40).map((t) => ({ t, ok: false })), ...Array.from({ length: 20 }, () => ({ t: rng.string(43, 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_'), ok: false })), ]); await mapLimit(probes, 10, async (p) => { const r = await http.get(server.url(), { token: p.t }); if (p.ok) expectContainersResponse(r); else expectErrorResponse(r, 401); }); // deleting already-deleted tokens fails and changes nothing const snapshot = JSON.stringify(readTokens(ws.dbPath)); for (const t of deleted.slice(0, 10)) expectCliFailure(await cli.run(['token', 'delete', t]), { exitCode: 1, message: 'token already inactive' }); expect(JSON.stringify(readTokens(ws.dbPath))).toBe(snapshot); expect((await server.stop()).exitCode).toBe(0); // audit: exactly one row per successful probe, each for the right token const ops = readOperations(ws.dbPath); expect(ops.map((o) => o.token).sort()).toEqual(alive.slice(0, 60).sort()); expect(server.logs().requests().filter((r) => r.attrs.status === '200')).toHaveLength(60); expect(server.logs().requests().filter((r) => r.attrs.status === '401')).toHaveLength(60); // `audit` over the population: all 60 rows, the default 10, and a window holding every row expect(formatAuditOutput(await cli.audit('60'))).toBe(expectedAuditStdout(ops, { limit: 60n })); expect(formatAuditOutput(await cli.audit())).toBe(expectedAuditStdout(ops, { limit: 10n })); expect((await cli.audit('1h')).map((r) => r.token).sort()).toEqual(alive.slice(0, 60).sort()); const report = assertDbInvariants(ws.dbPath, { tokenCount: N, operationCount: 60, auditBeforeDeletion: true }); expect(report).toEqual({ tokens: N, activeTokens: 200, inactiveTokens: 100, operations: 60 }); });