Prototype owner-only administrator account management
This commit is contained in:
1 parent
ac8742c829
commit
882d006b3c
24 files changed
+3438
-15
No files matched your search
@@ -0,0 +1,50 @@
|
||||
# Administrator account management
|
||||
|
||||
Open **Administration → Accounts** as an enabled owner. Operators, viewers and room hosts cannot list or change administrator accounts. The directory shows account names, roles, enabled status and timestamps in pages of 25. It never returns access keys, their hashes or administrator sessions.
|
||||
|
||||
## Provision and protect a key
|
||||
|
||||
Choose a name, owner/operator/viewer role and operational reason, then review the exact account ID, name, role and reason before confirming. The browser generates a new UUID and 256-bit personal access key with Web Crypto. It saves the exact request in this tab before sending it. The server stores only its SHA-256 hash and returns account metadata, **not the key**. After confirmation, save the one-time displayed key privately and explicitly clear its tab record. Refresh restores an unconfirmed request or the confirmed key until it is cleared. If the response is uncertain, retry the same saved request; do not generate a replacement request or discard the only key copy. Do not place keys in reasons, screenshots, issue reports or shared logs.
|
||||
|
||||
## Change or disable access
|
||||
|
||||
Choose an enabled account other than your own. Review its exact name, ID,
|
||||
current role, requested new role or disable, and operational reason before
|
||||
sending. A role change uses the current account timestamp; a stale target
|
||||
is rejected and must be reviewed again. Disabling blocks the key and
|
||||
permanently invalidates current sessions; this page cannot re-enable the
|
||||
account. **Do not manually re-enable its database row:** without a separate
|
||||
key rotation, its old access key would become usable again. Provision a new
|
||||
account instead. Another owner must perform a self-demotion or self-disable.
|
||||
The database refuses to remove the final enabled owner. Existing game rooms,
|
||||
seats and recovery kits are not modified.
|
||||
|
||||
Each operation has an exact saved identifier and request fingerprint. Concurrent or repeated identical requests resolve to one account change and one actor-attributed audit record; a different request cannot reuse that identifier. Live owner role, session expiry/generation and target version are rechecked at the database write, not inferred from the rendered page. An uncertain role or disable response can be retried from this tab; a conflicting or revoked request remains blocked for review. Tab records are scoped to the original owner account.
|
||||
|
||||
Action history shows successful account operations with safe role changes and an operational reason for authorized readers. External CLI provisioning or revocation may still have no human actor attribution. Rejected attempts are not yet part of that history. No browser account operation grants access to a playing seat or reveals saved game data.
|
||||
|
||||
## Verification and remaining work
|
||||
|
||||
Implementation: [account query and transactions](../db/admin-accounts.ts), [request contract](../lib/admin-accounts.ts), [route](../app/api/admin/accounts/route.ts), [page](../app/admin/accounts/page.tsx) and [additive operation receipt](../drizzle/0019_admin_accounts.sql). Keep the original owner-protection and session-revocation triggers in migration `0008`.
|
||||
|
||||
```sh
|
||||
npm test -- admin-accounts admin-audit
|
||||
npm run test:integration -- admin-boundary
|
||||
```
|
||||
|
||||
The source-bound local checkpoint passes 5,780 offline tests, 55 HTTP
|
||||
integration tests, the app build and Drizzle migration check. An isolated
|
||||
Request/Response route-handler smoke exercised owner provisioning, exact
|
||||
replay, directory read and foreign-origin denial; it did not use a network
|
||||
server or persistent administrator account. Browser owner fixtures blocked
|
||||
or intercepted POSTs and verified one-time key recovery and mobile disable
|
||||
confirmation. Independent security and persistence reviews resolved
|
||||
unchanged-role audit no-ops, missing point-of-risk copy and a logout-all
|
||||
timestamp rollback.
|
||||
|
||||
Use an isolated owner and disposable target for authenticated end-to-end
|
||||
account changes; never use a person's normal owner key in a destructive QA
|
||||
flow. Client/browser fixtures alone do not prove a signed-in **network**
|
||||
HTTP mutation or production deployment. Key rotation, re-enabling a
|
||||
disabled account, failed-attempt audit, complete administration and live
|
||||
acceptance remain unfinished.
|
||||
@@ -17,9 +17,11 @@ Each record identifies the action, time, room/seat/account where recorded, actor
|
||||
operational reason when permitted, and bounded before/after settings. Expand
|
||||
**Recorded settings** for the public configuration, lifecycle flags, revisions,
|
||||
AI difficulty or changed player circle. Names come from current administrator
|
||||
accounts; deleted accounts retain their recorded identifiers. External account
|
||||
provisioning/revocation records have no human actor attribution, and the page
|
||||
explicitly says so. A **Recorded** outcome means the operation was applied; a
|
||||
accounts; deleted accounts retain their recorded identifiers. Web-managed
|
||||
provisioning, role changes and disabling identify the acting owner and record
|
||||
the supplied reason. External CLI provisioning/revocation may lack human
|
||||
actor attribution, and the page says so. A **Recorded** outcome means the
|
||||
operation was applied; a
|
||||
room-control operation may successfully save identical settings, and later
|
||||
operations may supersede it. It does not assert the room's current state.
|
||||
|
||||
@@ -51,7 +53,10 @@ and uses the existing no-store, cookie-varying administration boundary.
|
||||
Implementation: [query/projection](../db/admin-audit.ts),
|
||||
[response contract](../lib/admin-audit.ts),
|
||||
[route](../app/api/admin/audit/route.ts), [page](../app/admin/audit/page.tsx).
|
||||
No schema migration is needed.
|
||||
The original nine-source read needed no migration. Owner account management
|
||||
adds a safe `reason` field and durable retry receipts in additive
|
||||
[migration 0019](../drizzle/0019_admin_accounts.sql); it does not add a
|
||||
new raw game or message source.
|
||||
|
||||
```sh
|
||||
npm test -- admin-audit
|
||||
@@ -71,7 +76,7 @@ sources under its five-term compound-query limit, with live role demotion and
|
||||
filtered reads. Materialized groups keep the unified query within that limit.
|
||||
|
||||
Existing records cover successful operations only. Failed/rejected attempts,
|
||||
additional account-management actions, full operational health/diagnostics,
|
||||
key rotation and re-enable, full operational health/diagnostics,
|
||||
backup/import/restore and the remaining participant support are still required.
|
||||
Local/browser/source-bound evidence is separate from deployed acceptance, which
|
||||
must identify the actual running revision and use authorized QA access.
|
||||
+8
-1
@@ -9,7 +9,7 @@ recovery and persistence systems where suitable.
|
||||
|
||||
| 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 |
|
||||
| Administrator access | Personal access keys, server-enforced owner/operator/viewer roles, persistent eight-hour sessions and individual/all-session sign-out. [Owner-only account management](ADMIN_ACCOUNTS.md) adds a paginated directory, browser-created one-time keys, role changes, disabling, live authority and exact retries. A room host is not a site administrator. Key rotation/re-enable, failed-attempt history and further operational permissions remain. | Prototyped, partial |
|
||||
| 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 |
|
||||
@@ -53,6 +53,13 @@ Disabling an account invalidates its sessions; later re-enabling it cannot resto
|
||||
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.
|
||||
|
||||
[Manage accounts](ADMIN_ACCOUNTS.md) lets a current owner provision a personal
|
||||
key, change another administrator’s role or disable its access. The exact
|
||||
request and generated key remain tab-scoped through uncertain responses;
|
||||
the server never returns a key. The owner reviews the target and reason
|
||||
before submitting, and no game or seat is modified. Key rotation and
|
||||
re-enabling disabled accounts are not available in this prototype.
|
||||
|
||||
[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.
|
||||
|
||||
@@ -6,6 +6,16 @@ Expansion starts and full rules/publication acceptance remain gated.**
|
||||
|
||||
## Current checkpoint and work
|
||||
|
||||
The owner-only [administrator accounts](ADMIN_ACCOUNTS.md) prototype now
|
||||
lists accounts, provisions a browser-generated one-time personal key, changes
|
||||
another account’s role and disables access. Server actions repeat live owner
|
||||
authority and target-version checks at commit, preserve exact tab-scoped
|
||||
retries and attribute successful changes in action history without exposing
|
||||
keys or saved games. Key rotation/re-enable, rejected-attempt history,
|
||||
authenticated positive **network** HTTP on a dedicated isolated QA account, deployed
|
||||
acceptance and the rest of full administration remain unfinished. This code
|
||||
is not in the last verified live image.
|
||||
|
||||
The bounded [Advanced Moritani Assassinate Leaders preview](MORITANI_ASSASSINATE_LEADERS.md)
|
||||
now has repeatable genuine games across two through six supported seats.
|
||||
Five samples completed 2,511 accepted actions, no rejected candidates
|
||||
|
||||
@@ -1,5 +1,42 @@
|
||||
# Dune implementation status
|
||||
|
||||
## 29 September 2026 — owner account management prototype
|
||||
|
||||
The [account page](ADMIN_ACCOUNTS.md) lists only safe metadata to a live
|
||||
owner. Provisioning uses a tab-scoped, browser-generated 256-bit key and an
|
||||
exact durable operation receipt; only its SHA-256 hash enters the database.
|
||||
Owners can change another account’s role or disable it after reviewing the
|
||||
name, ID, current/desired role and reason. Database writes repeat live owner
|
||||
authority and target-version checks, retain the final-owner trigger, and
|
||||
attribute the single successful provision/role/disable audit event. Disabled
|
||||
sessions fail immediately; room and seat rows remain untouched. Rotation,
|
||||
re-enable, failed-attempt audit and complete administration remain pending.
|
||||
|
||||
An isolated direct D1 smoke provisioned a disposable account, changed its
|
||||
role, disabled it, confirmed its old key/session fail and verified safe
|
||||
owner-attributed history without a raw key. An isolated Request/Response
|
||||
route-handler smoke confirmed owner provision, exact replay, directory read
|
||||
and foreign-origin denial without contacting a persistent database. Focused
|
||||
account/access/audit regressions include an additive migration preserving
|
||||
existing room, seat, credential and audit bytes. The local browser showed
|
||||
signed-out denial at phone width; intercepted owner fixtures displayed exact
|
||||
owner-role disable confirmation, retained a one-time key after refresh and
|
||||
hid directory/key controls after a focus-triggered demotion. Browser fixture
|
||||
POSTs never reached an account database. Authenticated positive **network**
|
||||
HTTP and live NAS acceptance remain untested.
|
||||
|
||||
Independent security review found and corrected unchanged-role audit no-ops
|
||||
and incomplete final disable confirmation. A separate persistence review
|
||||
reproduced a logout-all timestamp rollback; the account version is now
|
||||
monotonic and a stale disable rejects. Both follow-up read-only reviews
|
||||
reported no remaining scoped finding. The first focused HTTP run found a
|
||||
test assuming JSON for Vite’s foreign-origin 403; the corrected boundary
|
||||
test passes 3/3, and the full local HTTP suite passes 55/55.
|
||||
|
||||
`npm run check` passes typecheck, lint and 5,780/5,780 offline cases;
|
||||
`npm run build` and `drizzle-kit check` pass. These results do not certify
|
||||
complete administration, authenticated production mutations or deployment.
|
||||
|
||||
## 29 September 2026 — Advanced Moritani assassination sample matrix
|
||||
|
||||
The reusable offline runner now supports the explicitly gated
|
||||
|
||||
Reference in new issue
Block a user