17 KiB
Housekeeping Completion and Atomic Cutover Design
Status: Approved in conversation on 2026-08-26
Delivery branch: codex/housekeeping-complete
Delivery shape: one final pull request
Cutover: atomic, with no compatibility redirects
Relationship to the existing design
This specification completes the program described by
2026-08-24-housekeeping-modernization-design.md after the merged Inventory &
Foundation subproject. The existing foundation is not the finished product: it
provides the 137-route migration matrix, capability-aware contracts, validated
domain manifests, shell primitives, and a non-production preview.
This document defines the remaining implementation and the final cutover. Where delivery details differ, this document is authoritative for phases 02 onward. The master architecture remains authoritative for domain ownership and product behavior.
This completion specification supersedes the earlier documents only for the
route namespace: the new surface uses /ase, never /admin, as its canonical
production root.
Approved decisions
- Build complete verticals behind the existing non-production gate.
- Keep all remaining work on one branch and deliver it through one final pull request.
- Implement in vertical slices rather than UI-first placeholders.
- Keep current
/adminand/modbehavior unchanged until the final cutover commit. - At cutover, make the new Command Deck live at
/ase, remove the legacy/admin,/admin-next, and/modtrees, and remove obsolete legacy routes without redirects. - Use hybrid personalization: mandatory content is capability-derived; operators may pin and reorder allowed shortcuts and optional widgets.
- Add only backward-compatible database migrations before cutover.
Outcomes
The completed program must:
- Give every one of the 137 legacy routes a verified canonical destination or an explicit removal decision.
- Replace the fragmented admin and moderator surfaces with one capability-aware Command Deck.
- Deliver real workflows for all retained administration responsibilities, not wrappers around legacy pages.
- Provide global search, safe commands, derived operational inboxes, recent work, favorites, and optional widgets.
- Enforce the existing ACL model on navigation, reads, mutations, commands, search results, inbox items, and widgets.
- Produce durable and sanitized audit evidence for sensitive operations.
- Preserve a release-level rollback path without destructive database rollback.
Delivery model
All work is committed to codex/housekeeping-complete, based on the latest
origin/main. No pull request is opened until every vertical and the cutover are
implemented, reviewed, and verified.
The foundation currently exposes /admin-next. The first completion change
renames that preview tree and its links to /ase-next; the preview remains
unavailable when NODE_ENV=production. Development and test environments use
/ase-next to exercise the new shell before cutover. The final cutover publishes
the canonical /ase tree and removes the preview entry; it does not weaken the
production preview gate before that point.
The branch is built in this order:
- access, audit, error, and preference core;
- People, moderation, and support;
- Content and engagement;
- Economy and catalog;
- Hotel, world, and operational systems;
- Command Deck operations and cross-domain composition;
- atomic route cutover and legacy removal.
Canonical route structure
After cutover the public administration route tree is:
/ase Operations workspace
/ase/people/* users, tickets, CFH, bans, moderation, teams
/ase/content/* articles, events, polls, media, engagement
/ase/economy/* catalog, shop, transactions, vouchers, values
/ase/hotel/* rooms, furni, badges, radio, emulator, Studio
/ase/system/* settings, ACL, logs, DevOps, maintenance
/ase is the operational home, not a duplicate menu page. /admin,
/admin-next, and /mod have no route after cutover. A workflow has one
canonical owner and one canonical destination; the new tree must not retain
duplicate hubs or aliases.
Module ownership
src/features/housekeeping/foundation owns only cross-cutting composition:
- request-scoped actor and capability context;
- registry and navigation projection;
- Command Deck chrome and page-state primitives;
- command dispatch contracts;
- search and inbox orchestration;
- preference reconciliation;
- shared error and audit envelopes.
Each domain owns its routes, pages, query services, commands, search providers, inbox sources, widgets, and domain-specific validation. Domains communicate with the foundation through the published contracts. They do not import another domain's internal modules.
The foundation must not import database clients, server actions, or domain page modules. Server-only domain adapters may import data and action services.
Domain manifests
Every manifest registers real, non-placeholder definitions for:
- canonical routes and contextual navigation;
- safe and sensitive commands;
- entity-search providers;
- derived-inbox sources;
- mandatory and optional widgets;
- localization keys and capability requirements.
Registry validation rejects duplicate IDs across all provider categories, duplicate routes, invalid ownership, missing localization, unknown capability slugs, invalid widget kinds, and commands without an owning domain.
The migration matrix and manifests are linked by contract tests. Every retained matrix row must resolve to one registered route or workflow. Every manifest capability set must cover the capabilities attributed to its matrix rows.
Authorization flow
Each request creates one capability context from getAdminContext(). The context
contains the authenticated actor and immutable effective permission slugs.
Rank is informational and may influence presentation defaults only; it is never
used as a new authorization threshold.
Authorization is applied at every layer:
- registry projection removes inaccessible domains and routes;
- provider orchestration calls only permitted providers;
- providers filter inaccessible results and items;
- page loaders revalidate their required capability;
- command execution revalidates capability and input on the server;
- the underlying mutation service retains its own permission guard.
Client state, hidden navigation, preferences, or a previously loaded page never authorize an operation.
Commands and audit
Commands use typed input schemas and typed success/error results. Safe commands may execute directly from the palette. Sensitive commands open a dedicated contextual confirmation flow and require a reason when the command contract says so.
The existing admin_audit_log remains the canonical audit store. An additive
migration adds nullable correlation_id varchar(64), outcome varchar(32),
reason text, and domain varchar(32) columns plus an index on
correlation_id. Existing action, target, target_id, before, after,
diff, ip_address, and actor fields remain in use.
- Database mutations write mutation and audit evidence in the same transaction whenever the affected service uses the same database connection.
- Sensitive external or file operations persist an audit intent before execution and a final outcome afterward. Failure to persist the intent blocks execution.
- Audit payloads pass through the existing recursive secret redaction.
- Every command result and audit record carries the same correlation ID.
- Failed, denied, and partially completed sensitive operations are audited.
Preferences
No suitable user-scoped HK preference store currently exists. Add
housekeeping_user_preferences with:
user_id intas the primary key and unique owner;schema_version int not null default 1;payload longtext not null, containing validated JSON presentation state;created_at datetimeandupdated_at datetimetimestamps.
The payload stores pinned route/command IDs, shortcut order, widget order, and enabled optional widget IDs. It never stores permissions, authorization decisions, workflow state, or inbox status.
Every read reconciles stored IDs against the current registry and effective capabilities. Unknown, removed, or unauthorized entries are dropped before the payload reaches the UI. Mandatory widgets cannot be disabled.
Command Deck experience
The shell has four stable regions:
- a compact six-domain rail;
- domain-owned contextual navigation;
- a global search and command field with keyboard access;
- an operational workspace for pages, inboxes, recent work, and widgets.
Desktop and mobile share the same semantic hierarchy. Mobile collapses the rail and contextual navigation without changing route ownership or available actions. Focus order, landmarks, headings, active-state uniqueness, keyboard navigation, reduced motion, and semantic theme tokens are tested contracts.
Loading, empty, partial, error, forbidden, and ready states use the shared page state primitives. Partial provider failure is visible without replacing valid results from other providers.
Search
Search supports navigation, entity results, and commands. It is not a raw database search endpoint.
- A term shorter than two trimmed characters performs navigation/command matching only.
- Entity providers have a two-second timeout and a maximum of 25 results each.
- The combined entity response is capped at 50 results before client rendering.
- Providers run only when their declared capability is satisfied.
- Results include stable ID, owner, type, title, optional description, canonical href, and capability metadata.
- Provider errors produce a typed partial result and do not fail unrelated providers.
- Search terms and result payloads are not written to audit logs by default.
Derived operational inbox
The inbox is a read model over domain-owned work: tickets, CFH reports, alerts, emulator errors, operational anomalies, and other existing live states. It does not introduce a second assignment or task-status system.
Each inbox item exposes stable source/item IDs, domain, type, title, priority,
age, state, canonical href, available actions, and required capability. Source
items are deduplicated by the pair (sourceId, itemId).
Sources run independently with a two-second timeout. The composed response contains successful items plus per-source errors. The server caps the result at 200 items after capability filtering and deterministic priority/age ordering.
Recent work, favorites, and widgets
Recent work is derived from the operator's existing audit events and canonical route visits; it does not create workflow state. Favorites and ordering come from the reconciled preference payload.
Mandatory widgets are supplied by the system according to capability and cannot be removed. Optional widgets can be enabled and reordered. Widget loaders are server-side, capability-checked, independently timed out, and represented as partial failures rather than shell failures.
Vertical scope
Access, audit, and system core
- command dispatcher and confirmation model;
- audit extension and correlation IDs;
- typed error taxonomy and boundary mapping;
- preference repository and reconciliation;
- shared provider orchestration and timeout behavior;
- System routes for ACL, settings, logs, DevOps, and maintenance.
People, moderation, and support
- user discovery, details, editing, password/reset controls, account relations, bans, and permitted staff actions;
- help tickets and moderator tickets;
- CFH queues and details;
- moderation actions, team views, and ban workflows;
- People search providers, inbox sources, commands, and widgets.
This vertical proves that all retained /mod responsibilities work inside the
new capability model before /mod is removed.
Content and engagement
- articles, events, polls, media, navigation content, tags, banners, and related editorial tools;
- Content search, commands, inbox sources, and widgets;
- consolidation of duplicate editorial hubs into canonical workflows.
Economy and catalog
- catalog and item management, Builder Club catalog, maintenance, shop, transactions, vouchers, subscriptions, marketplace, and value tools;
- Economy search, commands, anomaly sources, and widgets;
- existing specialized editors remain components of canonical workflows rather than parallel navigation roots.
Hotel, world, and operational systems
- rooms and room furni, badges, sounds, radio, emulator controls, imports, and Studio tools;
- Hotel search, commands, operational sources, and widgets;
- long-running operations retain progress/error behavior and gain consistent capability and audit envelopes.
Operations composition
- global search and command palette;
- derived inbox and partial-source reporting;
- recent work and favorites;
- mandatory operational summaries and optional widgets;
- no duplicate mutation logic: actions route to the owning domain command.
Error model
All HK services return typed errors from this stable set:
UNAUTHENTICATED;FORBIDDEN;VALIDATION;NOT_FOUND;CONFLICT;RATE_LIMITED;DEPENDENCY_UNAVAILABLE;TIMEOUT;INTERNAL.
User messages are localized and do not expose internal details. Server logs and audit evidence include correlation IDs. Expected domain errors do not rely on framework exception text. Unknown errors are sanitized at the boundary and logged once.
Database changes
Allowed pre-cutover migrations are additive only:
- nullable HK audit metadata columns on
admin_audit_log; - the
housekeeping_user_preferencestable and its unique user index.
No legacy table or column is dropped or repurposed in this program. Removal of legacy UI routes is an application cutover, not a destructive data migration.
Atomic cutover
The final cutover commit is created only after all vertical gates pass. It:
- moves the completed shell and Operations workspace from
/ase-nextto/ase; - changes domain preview hrefs to canonical
/ase/<domain>hrefs; - updates internal links, navigation configuration, and authorization fallback destinations;
- removes the legacy
/admin,/admin-next, and/modroute trees plus every legacy route markedREMOVE; - removes legacy pages whose behavior moved or merged into canonical routes;
- removes the temporary preview entry and flag if no longer used by tests;
- adds no compatibility redirects.
The cutover must leave no links, imports, route discovery entries, or tests that depend on removed UI modules.
Verification strategy
Each vertical uses TDD and has four gates:
- contract and authorization tests;
- domain query/command behavior tests, including denied and failure paths;
- page and accessibility behavior tests;
- cumulative Housekeeping and repository verification.
The final branch requires:
- the migration matrix reporting 137/137 valid with every retained row linked to a canonical implementation;
- mutation-sensitive authorization, provider, command, audit, and preference tests;
- full project tests, Housekeeping tests, typecheck, semantic Biome, targeted
formatting checks, and
git diff --check; - production build with temporary environment restoration;
- visual verification at desktop and mobile widths for every domain and shared state;
- route-level smoke checks for canonical
/asepages, denied access, and removal of/admin,/admin-next,/mod, and obsolete routes; - a broad whole-branch code review followed by one reviewed fix wave if needed.
Repository-wide pre-existing formatter debt is reported separately and must not be hidden by mass-formatting unrelated files.
Merge, deployment, and rollback
The single pull request targets main only after all final gates pass. Merging
is the atomic release boundary; no partial vertical is intentionally exposed to
production operators.
After merge, the deployment pipeline must complete and /api/health must be
verified live. A push or successful build alone is not deployment evidence.
Rollback deploys the prior application release. Because database changes are additive and ignored by the prior release, rollback does not require manual data reversal. If audit or preference migrations themselves fail, deployment stops before serving the cutover release.
Explicit non-goals
- A new task-assignment system for inbox items.
- A replacement authentication or ACL model.
- Rank-based authorization thresholds.
- Compatibility redirects for removed
/admin,/admin-next, or/modroutes. - Destructive cleanup of legacy database data.
- Rewriting specialized domain engines that already work; they are integrated behind consistent domain contracts instead.
- Unrelated CMS redesign or repository-wide formatting cleanup.
Completion criteria
The program is complete only when:
- all retained legacy capabilities are available through canonical new routes;
- all six manifests contain real routes/providers/widgets rather than empty placeholders;
- the Command Deck search, commands, inbox, preferences, recent work, and widgets operate against real domain services;
- capability enforcement and audit evidence cover every exposed read and mutation path;
/aseserves the new HK;/admin,/admin-next,/mod, and removed legacy routes are unreachable; and no compatibility redirects exist;- final local, CI, deployment, health, and visual evidence are all recorded.