Files
Dune/docs/ADMIN_PANEL.md
T
Quintine 160fdc1f30 Prototype administrative discussion mute controls
Let owners/operators mute or unmute new public/private sends from a human seat while retaining history, incoming messages, gameplay and credentials. Fence metadata and durable audit writes with live authority, membership and versions. Preserve exact admin/message retries and inherit restrictions through seat recovery.

Validation: types/lint, 5431 offline tests, build, 52 HTTP integration tests, 24 administrator HTTP groups, independent SQL/privacy/UI review and desktop/mobile refresh acceptance. All 2230 prior games and 4746 seats preserved. Additive migration 0016. Verified runtime fingerprint 588967fbb9c2e3b6abe2990c4fce96ee69e2256fb7e3ee416314b87593cebba9; documentation-only grammar/button-label review gives b5e57bdd26812debede91c588e38f247f1fa895ad23e7ae30bc8550eedcd90ec. New-revision deployed acceptance remains open; full admin/rules scope is unfinished.
2026-09-26 14:30:52 +10:00

201 lines
14 KiB
Markdown

# Administration panel requirements
Added to the goal on 22 September 2026 at the user's request. This is required
product scope. The first access and directory prototype is available at `/admin`;
the remaining room operations are unfinished. Reuse the existing room, session,
recovery and persistence systems where suitable.
## Required capabilities
| Area | Required behavior | Stage |
| --- | --- | --- |
| Administrator access | Personal access keys, server-enforced owner/operator/viewer roles, persistent eight-hour sessions, individual/all-session sign-out and operator provisioning/revocation. A room host is not a site administrator. Account-management UI and further operational permissions remain. | Prototyped |
| Room directory | Search room codes/public player names, filter status/rules/availability, sort and paginate; show host, roster, modules, game change time, pause/join flags and bounded decision ownership. Detailed setup/shared-window ownership remains. | Prototyped |
| Create and configure | [Create a lobby](ADMIN_ROOM_CREATION.md) with an explicitly owned new host seat, Basic/Advanced preview and initial AI configuration; invite humans and use ordinary lobby controls/voluntary host-seat handover. [Neutral lobby configuration](ADMIN_LOBBY_CONFIGURATION.md) adds rules/modules, AI seats and host assignment to an existing human without private access. Reserved human seats remain. | Prototyped, partial |
| Lifecycle and removal | [Pause/resume and joining locks](ADMIN_ROOM_CONTROLS.md), [administrative close/reopen](ADMIN_ROOM_CLOSURE.md) and [recoverable removal/restoration](ADMIN_ROOM_REMOVAL.md) have controls, durable audit, exact retries and player/AI enforcement. [Archive/unarchive](ADMIN_ROOM_ARCHIVE.md) has separate directory filters and exact retries. Permanent deletion and bulk actions remain missing. | Prototyped, partial |
| Participant support | [Participant AI](ADMIN_PARTICIPANT_AI.md) enables an existing difficulty on an eligible human seat in a paused game, retaining access/takeback and private custody. [Discussion controls](ADMIN_DISCUSSION.md) mute/unmute new sends while retaining history and gameplay. Participant removal, access revocation, assisted recovery and further replacement remain. Existing lobby controls can reassign the host. | Prototyped, partial |
| Saved-game operations | Create/list/download backups, validate imports, restore a selected checkpoint safely, and diagnose or resume interrupted automatic work through authoritative game actions. | Missing |
| Operations and audit | Show server/build/storage health, room/player counts and actionable errors; provide maintenance controls and a searchable record of administrator actions. | Missing |
Track each area through Missing, Prototyped, Integrated, Verified and Polished.
As implementation begins, link its controls, server actions, persistence,
documentation and evidence. A working directory alone is not a full admin panel.
## Access and directory prototype
Use **Administration** in the home-page footer or visit `/admin`. Every directory
request checks a separate administrator session; seat cookies and forwarded
identity headers cannot grant access. The standalone NAS runtime has no trusted
Sites identity dispatcher, so this panel uses separately provisioned personal
keys. Each key contains a random 256-bit secret. Only its SHA-256 hash is stored;
sign-in issues a separate random, hashed session with an eight-hour absolute
expiry. HTTPS uses Secure, HttpOnly, SameSite=Strict cookies scoped to the admin
API. Mutations require the exact configured origin and bounded JSON requests.
All three roles may read the current directory and sign out their own sessions.
Owners/operators may pause/resume rooms and lock/unlock new joins through
[Room controls](ADMIN_ROOM_CONTROLS.md). The role is checked from the live
account, never accepted from a client.
Owners/operators can also [create a configured lobby](ADMIN_ROOM_CREATION.md),
with explicit new-host ownership and saved exact retries.
[Configure lobby](ADMIN_LOBBY_CONFIGURATION.md) changes supported rules, AI seats
and the host without granting private seat access.
[Remove or restore](ADMIN_ROOM_REMOVAL.md) blocks ordinary room access while
preserving the game, seats and access revocations. Use the Directory filter to
find removed rooms; restoration retains prior pause and joining settings.
[Close or reopen](ADMIN_ROOM_CLOSURE.md) ends further play without awarding a
winner and preserves readable private tables and discussion. Reopening retains
the saved game, pause/join settings and current credentials.
[Archive or unarchive](ADMIN_ROOM_ARCHIVE.md) organizes closed rooms with separate
directory filters and exact retries. Unarchiving leaves play closed; restoring
a removed archive preserves both flags.
Disabling an account invalidates its sessions; later re-enabling it cannot restore
them. The database refuses to disable, demote or delete the final enabled owner.
No default key, public account creation or host-to-administrator promotion exists.
[Participant AI](ADMIN_PARTICIPANT_AI.md) lets owners/operators support an absent
human in a paused, started game. The player retains access and takeback controls;
the administrator receives no private seat. Resume remains a separate action.
[Discussion controls](ADMIN_DISCUSSION.md) restrict new messages from a human seat,
including after recovery/handover, without exposing private history.
The directory uses an explicit field allowlist, independent of any player view.
It never returns hands, Traitors, predictions, plans, private messages, recovery
records or raw saved state. Searches inspect only codes and public player names.
Each page is limited to 25 rooms and repeats authorization in its read transaction
so concurrent revocation cannot expose a later directory snapshot. Malformed
saves are marked unreadable without leaking their contents or breaking searches.
Last game change refers to the room's saved-state timestamp, not private messages.
Shared windows and setup currently use broad pending labels; these labels do not
assert that a human is stalled or identify hidden-card-dependent eligibility.
Implementation: [panel](../app/admin/page.tsx), [access](../db/admin-access.ts),
[directory](../db/admin-directory.ts), [HTTP boundary](../lib/admin-http.ts),
[additive migration](../drizzle/0008_admin_access.sql), and
[operator CLI](../tools/admin-access.mjs). The migration's explicit SQLite triggers
enforce final-owner protection and account revocation/provisioning audit; retain
them when generating future schema changes. Audit browsing is still pending.
### Initial owner and access recovery
From the development checkout, apply additive migrations, then create a personal
owner key in a new private directory outside the checkout:
```sh
npm run db:local
node tools/admin-access.mjs --name 'Owner' --role owner --out /private/dune-owner
npx wrangler d1 execute DB --local --config tools/wrangler.local.json --persist-to .wrangler/state --file /private/dune-owner/provision.sql
```
The parent directory must already exist. Output files are mode 0600 in a new
mode-0700 directory. `access-key.txt` contains the sign-in key; `provision.sql`
contains only its hash. Keep the key in a private password manager or protected
file, outside Git, logs and chat. The command never connects to a database or
prints the key. Apply the SQL only to the intended instance. Do not upload a
development key to production; provision separate accounts there.
For the container, run the bundled CLI inside the existing `dune` container
(using its actual container ID/name), with output such as `/data/admin-owner`.
Apply the generated SQL using `node node_modules/wrangler/bin/wrangler.js d1
execute DB --local --config tools/wrangler.local.json --persist-to /data --file
/data/admin-owner/provision.sql`. A protected volume snapshot should precede
operational changes. Retrieve the key through an authorized private channel and
retain the account ID shown by the CLI. No application restart is needed.
To revoke an account, generate a new private output directory with
`node tools/admin-access.mjs --revoke ACCOUNT_UUID --out /private/dune-revoke`
and apply its `revoke.sql` using the same instance-specific command. To replace
a lost/compromised owner key, provision a replacement owner first, verify access,
then revoke the previous account. Existing games and seats are unchanged.
**Sign out everywhere** revokes browser sessions but keeps the personal key valid.
### Focused verification
```sh
npm test -- admin-access admin-directory admin-http
npm run test:integration -- admin-boundary
node tools/verify-admin.mjs --url http://localhost:3000 --key-file /private/dune-qa/access-key.txt --qa-account ACCOUNT_UUID --out /private/dune-admin-report
```
The HTTP verifier requires a **dedicated QA administrator account** and explicitly
checks its ID before proceeding: it creates a named QA room and signs out all
sessions of that QA account. Never supply a human operator's normal key. It checks
authentication, cookie properties, ordinary-host denial, directory privacy,
session revocation and unchanged game/seat continuation. Operator/owner QA keys
also create dedicated rooms for joining locks, pause/takeback/resume,
administrator creation, invitations, voluntary host handover and neutral lobby
configuration with existing-human host assignment and a real game start. They
also close/reopen, archive/unarchive and remove/restore separate QA games, preserving their paused state, discussion,
saved seats and revoked credentials. Private reports retain
room IDs and safe outcomes, never keys/cookies. The container verifier provisions
its own disposable QA account and checks admin-session continuity across restart
and replacement, followed by the HTTP flow and HTTPS-proxy cookie behavior.
Participant checks use another new QA room for paused AI enable, private-seat
continuity, takeback and durable retries after resuming. Discussion checks use a
new QA room for mute/unmute, own-only status, incoming messages and saved retries.
Local browser checks cover sign-in, directory filters, refresh restoration and
mobile layout. Final source-bound checks and separately recorded deployed
acceptance accompany each checkpoint; a local pass is not production evidence.
## Behavior and safeguards
Every privileged endpoint must authenticate and authorize its caller. Support
least-privilege roles, secure initial provisioning, safe credential/session
management, and accessible desktop/mobile controls. Do not ship default shared
credentials or expose administrator capabilities through ordinary room cookies.
Default views must preserve hands, Traitors, predictions, sealed plans, private
discussion and recovery credentials. Any necessary private support access must
be separately authorized and audited; it must not reveal information to other
players or feed an administrator's playing seat or AI strategy. Redact secrets
and private card contents from routine logs and reports. Backup access needs
equivalent protection, since backups can contain private state.
Pausing must stop human mutations and automatic/AI continuation consistently
without losing pending decisions. Resuming restores the same turn and pacing.
Seat removal or reassignment must explain the effect on an active game and
preserve a legal continuation; do not simply delete a faction's physical pieces.
Existing consent/recovery boundaries remain applicable to seat access.
Use authoritative rules and the existing concurrency model. Reject stale or
duplicate destructive actions safely. Imports and restoration must validate
schema, custody, private-information boundaries and session ownership; capture
a recovery checkpoint before replacing current progress. Never restore old
credentials in a way that silently reauthorizes a revoked participant.
Room removal should be reversible by default. Permanent deletion and bulk
operations must identify the selected rooms and dependent records, explain
irreversibility, require deliberate confirmation and retain appropriate audit
evidence without keeping purged secrets. Protect unrelated games. The existing
saved-game preservation rules still govern development and maintenance; they
do not preclude intentional room deletion through the authorized product workflow.
Record who acted, when, the affected room/seat, operation, reason, outcome and
safe before/after metadata. Maintenance controls must warn about interruptions
to active games and preserve restoration. Do not recreate recurring restarts or
cleanup schedules. Do not add an arbitrary game-state editor that bypasses rules,
silently changes outcomes or makes unfinished modes appear complete.
## Development order and acceptance
Prototype permissions and the room directory first, then room creation and
reversible lifecycle operations, participant support, backup/restore and
operational tools. Include functional server actions and saved continuation in
each slice; continue independent game features in parallel where useful.
Administration is part of the non-AI completion gate in the
[AI development plan](AI_DEVELOPMENT_PLAN.md).
Acceptance requires working controls and documented setup/recovery procedures,
with authenticated HTTP and persistence tests for authorization, privacy,
concurrent actions, exact retries, related-record handling and safe restoration.
Verify pause/resume with both humans and AI, archive/delete/restore with saved
rooms, and denied admin actions by ordinary players. Exercise desktop/mobile
flows and server restart recovery. Use dedicated test rooms and preserve all
unrelated saved games; complete independent security/privacy/persistence review.
Verify the panel's relevant deployed flows at
**https://dune.procrastination.games**, including denied access by ordinary
players, using the [production verification workflow](VERIFICATION_WORKFLOW.md#verify-the-deployed-application).
The full goal remains unfinished until this scope and the other completion
criteria are satisfied.