Files
Dune/docs/ADMIN_ROOM_CONTROLS.md
Quintine 8c922b446b Add administrator pause and joining-lock controls
Provide authenticated owner/operator room controls with live account binding, durable audit and exact saved retries. Pause gates human, bot and automatic writes while preserving recovery, discussion and taking back control. Resume keeps decisions and restores AI pacing. Add directory availability filters and player notices.

Verified types, lint, 5223 offline tests, 52 HTTP tests and build. Independent persistence/privacy review and authenticated HTTP acceptance passed. Desktop/mobile browser QA confirmed lost-response refresh/retry makes one audit row and resume restores controls. Existing games preserved. Authenticated deployed admin acceptance remains pending explicit QA access confirmation.
2026-09-22 10:41:09 +10:00

84 lines
4.9 KiB
Markdown

# Administrator pause and joining locks
The directory now offers **Room controls** and an **Availability** filter. Owners
and operators can pause/resume a selected room and lock/unlock new joins; viewers
can inspect its flags. This is a reversible lifecycle prototype. Closing,
archiving, removal, participant support and backups remain unfinished in
[the panel checklist](ADMIN_PANEL.md).
Identify the room, provide a short operational reason, warn active players if
necessary, and explicitly confirm the displayed scope before applying settings.
Reasons belong to the private audit and must not contain credentials or private
game information. Players see only public availability flags.
## Paused behavior
| Operation | While paused |
| --- | --- |
| Game decisions, lobby changes and new joins | Rejected without changing the game |
| Automatic normalization and native/human-owned AI | Stop before work and are fenced again at the database write, including sleeping workers |
| Reading, refresh, discussion and component inspection | Remain available |
| Seat protection, recovery and voluntary handover | Remain available with existing ownership/revocation safeguards |
| Taking back control and revoking AI permission | Remain available |
| New AI permission or activation | Rejected; completed saved requests can still be confirmed |
A joining lock alone prevents new seats. Existing seats can reconnect, recover
or confirm an already completed join. Neither flag removes players, cards,
forces or pending choices. Resume preserves the game and gives existing AI seats
a fresh 1.5-second pacing deadline; it does not settle a player's decision.
## Persistence, authority and retries
The additive [migration](../drizzle/0009_admin_room_controls.sql) stores flags in
`room_controls`, separate from game JSON. A control change, room-version fence
and durable `admin_room_audit` receipt commit together. The audit records actor,
room, time, reason, expected revision and previous/new flags; it contains no
cards, credentials or raw game state. Audit browsing remains unfinished.
Untouched rooms retain their existing player-view shape; an absent control field
means running with joins open. After the first control change, player views keep
the public flags and revision, including after resume. Administrator reads always
return explicit defaults. Operational settings never enter saved game JSON.
The [HTTP endpoint](../app/api/admin/rooms/[code]/control/route.ts) requires the
configured origin, administrator authentication and owner/operator permissions
for writes. `X-Dune-Admin-Id` binds a write to the displayed account, preventing
an old tab from applying that account's saved intent after another account signs
in. SQL rechecks live session, role and generation within the transaction.
Each request has an operation ID, expected control revision, desired flags and
reason. Exact retries confirm the receipt and return current settings without
reapplying old flags. Conflicting revisions or reused IDs cannot overwrite a
later change. The [client](../components/admin-room-controls.tsx) saves the exact
request in account/room-scoped tab storage before sending. Uncertain responses
keep explicit retry controls across refresh. Authentication failures retain the
original account's pending request for confirmation after sign-in. There is no
automatic mutation retry. Deliberately discarding an unreadable local record
does not cancel a server change.
## Verification and remaining gates
Focused in-memory tests execute production SQL for roles, revoked sessions,
stale/conflicting requests, replay, rollback, joined-seat receipts, worker/action
races, pause during AI sleep, recovery/handover and resume pacing. UI tests cover
pause guidance, disabled AI-start controls, available takeback, account-scoped
retry storage and directory filters.
Authenticated local HTTP acceptance uses dedicated QA rooms. A temporary local
transport loses one successful control response: the browser reads the paused
state, refresh keeps the exact request, and explicit retry confirms one audit
row. Player controls disable on pause and return on resume. Mobile controls were
inspected at 390 pixels with 16-pixel labels and a 44-pixel apply button. Existing
games were not reset or used for these operations.
`tools/verify-admin.mjs` creates one room for access checks. A dedicated operator
or owner QA key also creates one room for account binding, joining locks,
pause/takeback/resume and saved-seat checks. Cleanup restores that QA room's flags
and stops its owning human's autopilot. Original failures and cleanup failures
are recorded separately. Never pass a human operator's key. The isolated container
verifier provisions its own QA operator and runs this flow.
Source checks, container checks and deployed acceptance are separate evidence.
Production administrator provisioning still needs explicit access confirmation;
local success does not close that deployed gate.