Prototype paused admin participant AI support

Enable an existing AI difficulty for a human seat through admin controls without granting private access or advancing paused play. Preserve custody, credentials, takeback and separate paced resume. Bind atomic writes and outgoing-grant revocation to live authority, room/pause versions and active seat access with durable exact receipts.

Validation: types/lint, 5408 offline tests, build and 52 HTTP tests passed on source fingerprint 2157de0f4bb0b74d9760d52102601c52344cf674dee8ccd1d559f0a246a1d4ff; 22 authenticated admin HTTP groups, independent SQL/privacy/UI review, desktop/mobile and refresh checks. All 2098 baseline rooms and 4455 seats preserved. Migration 0015 is additive. Positive production admin QA awaits authorized access; full admin/rules scope remains unfinished.
This commit is contained in:
Quintine committed 2026-09-26 14:04:17 +10:00
1 parent 137f9223f1
commit 2cddf03932
23 files changed
+3187 -10

No files matched your search

+19
View File
@@ -181,6 +181,25 @@ export const adminRoomArchives = sqliteTable(
],
);
// Participant AI never gives administrators a private seat. Receipts survive room removal.
export const adminSeatAiOperations = sqliteTable(
'admin_seat_ai_operations',
{
operationId: text('operation_id').primaryKey(),
actorAdminId: text('actor_admin_id').notNull(),
roomCode: text('room_code').notNull(),
requestHash: text('request_hash').notNull(),
expectedVersion: integer('expected_version').notNull(),
expectedControlRevision: integer('expected_control_revision').notNull(),
appliedVersion: integer('applied_version').notNull(),
target: text('target').notNull(),
difficulty: text('difficulty').notNull(),
reason: text('reason').notNull(),
createdAt: integer('created_at').notNull(),
},
table => [index('admin_seat_ai_room').on(table.roomCode, table.createdAt)],
);
// Durable receipts are also the room operations audit. They intentionally survive
// account/room removal, and contain no credentials, game state or private cards.
export const adminRoomAudit = sqliteTable(