Files
EpicNext-Cms/.superpowers/sdd/2026-08-26-housekeeping-completion/task-12-report.md
T

10 KiB

Task 12 — People users, community, and staff workflows

Status: DONE

Delivered scope

  • Registered exactly the nine approved real People routes: users list/edit/multi-account/detail, community online/guilds/guild detail, and staff applications/teams. The remaining support and moderation routes stay catalogued in routes.ts but unregistered for Task 13.
  • Added query-backed People pages with explicit loading, empty, partial, dependency-error, forbidden, and ready states. Links are canonical /ase/people/* links; optional mail/IP fields and mutation affordances remain absent unless their exact capability is present.
  • Added the exact fourteen user command IDs plus the six stable People-owned IDs people.guild.disband, people.application.decide, people.team.change, people.ip.action, people.vpn.configure, and people.word-filter.update.
  • Added bounded Zod command schemas, stable rate limits, dispatcher capability rechecks, confirmation metadata, a redirect-free server-only mutation service, and deterministic bootstrap registration.
  • Extracted shared mutation behavior behind the existing actions while preserving the legacy action exports, exact ACLs, /admin revalidation, VPN redirect/fail-soft behavior, word-filter ActionResult shapes, already-gone delete semantics, and failure propagation where legacy persistence errors previously propagated.
  • Added neutral EN/IT labels only for the nine runtime routes.

Security and behavior decisions

  • No ACL slug or route authorization rank threshold was added. Exact legacy capabilities remain authoritative: single ban/unban use USERS_BAN, reset-password uses USERS_RESET_PASSWORD, bulk/user/community/team/application operations use USERS_EDIT, IP/VPN use SETTINGS_EDIT, and word filter uses WORDFILTER_EDIT.
  • The existing target hierarchy safeguard remains for legacy user mutations that previously used guardRank; alert remains capability-authorized without a new target-rank rule.
  • Ordinary user edit and alert remain reason-free because their existing semantics are non-destructive. Sanctions, destructive operations, global/security changes, currency delivery, and bulk mutations require a nonblank dispatcher reason. Ban and bulk-ban operational reasons are also persisted with the mutation audit evidence.
  • Every public service call rechecks the exact capability before production work. The production adapter is module-private; server-only placement is not treated as authorization.
  • Successful mutations emit before/after audit evidence and a stable correlation ID. Audit persistence failure is fail-closed and maps to DEPENDENCY_UNAVAILABLE. User mutation audit snapshots omit mail because it is unnecessary PII; page projection continues to follow Task 11 exactly.
  • User pages consume only Task 11 guarded read models, preserving bounded pagination, deterministic sorting, fail-closed DTO validation, serialization, zero-sentinel rules, watched state, permission context, and PII projection.
  • Legacy wrappers remain on /admin behavior until Task 25. No /admin, /mod, API, redirect, database schema, deployment, or cutover behavior was changed.

Strict TDD evidence

Initial command/page/route RED

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/commands/user-commands.test.ts src/features/housekeeping/domains/people/commands/community-commands.test.ts src/features/housekeeping/domains/people/pages/people-primary-pages.test.tsx
Test Files 3 failed (3)
Tests 0
Missing modules: community-commands, ../services/mutations, ../route-handlers

Initial focused GREEN:

Command tests: 2 files passed, 22 tests passed
Primary page/route tests: 3 files passed, 12 tests passed
Bootstrap tests: 1 file passed, 2 tests passed

Foundation integration RED/GREEN

RED after enabling People:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people src/features/housekeeping/foundation
Test Files 3 failed | 31 passed
Tests 4 failed | 376 passed
Failures: stale System-only registry assertions, stale preview expectation, and an unapproved People vertical runtime edge.

GREEN after updating the explicit runtime-edge and registry contracts:

Focused foundation contracts: 3 files passed, 40 tests passed
People + foundation: 34 files passed, 380 tests passed

Audited sanction reason

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/services/mutations-reason-production.test.ts
Test Files 1 failed (1)
Tests 1 failed (1)
The ban audit after-snapshot did not contain the nonblank sanction reason.

GREEN:

Production mutation contracts: 2 files passed, 4 tests passed
The audited snapshot includes the reason and excludes mail.

Legacy wrapper failure parity

RED:

pnpm exec vitest run --coverage.enabled=false src/actions/people-wrapper-errors.test.ts
Test Files 1 failed (1)
Tests 3 failed (3)
Persistence failures were swallowed and already-gone word-filter deletion was not idempotent.

GREEN:

Test Files 1 passed (1)
Tests 3 passed (3)

Single authorization check for positive bulk adjustment

RED:

pnpm exec vitest run --coverage.enabled=false src/actions/bulk-adjust-wrapper.test.ts
Test Files 1 failed (1)
Tests 1 failed (1)
Expected one requirePermission call; received two.

GREEN:

Test Files 1 passed (1)
Tests 1 passed (1)

Static gates during implementation

pnpm typecheck
RED: one unused `describe` import in admin-ip.test.ts
GREEN: tsc --noEmit, exit 0

pnpm exec biome check --formatter-enabled=false <exact Task 12 src files>
RED: 14 import-order assists
GREEN: checked 44 files, no fixes applied

Final verification

Focused wrapper/command/page/service/route/authorization/audit matrix
Test Files 22 passed (22)
Tests 129 passed (129)

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people src/features/housekeeping/foundation
Test Files 35 passed (35)
Tests 381 passed (381)

pnpm test:housekeeping
Test Files 54 passed (54)
Tests 469 passed (469)

pnpm typecheck
tsc --noEmit
Exit 0

pnpm exec biome check --formatter-enabled=false <44 exact changed Task 12 src files>
Checked 44 files. No fixes applied.

git diff --check
Exit 0

The Node engine warning remains the approved non-blocker: the repository requests Node >=26.8.1 <27, while this host runs Node v26.7.0 with pnpm 11.24.0. All test and type gates exited successfully.

No database operation, deployment, push, or pull-request update was performed.

Official review fix round 1

The official review reported 0 Critical and 5 Important findings. This round addresses the five findings without widening the Task 12 route catalog or changing legacy redirects, safe-action response shapes, or cutover behavior.

RED evidence

Production server authority: auth resolver was called 0 times at the public service boundary (1 failing regression).
Canonical external audit: 3 failing regressions for missing durable intent/outcome behavior.
Transactional audit: expected one transaction and observed zero (1 failing regression).
Legacy/production workflows: new production matrix initially exposed bulk truncation/deduplication, trade-lock hierarchy/state, missing StaffActivities, and missing word-filter refresh behavior.
Primary workflows: page suite started at 7 passed / 2 failed (no executable command form and no bounded URL parser); preview contract started at 61 passed / 3 failed (searchParams/loading propagation).
Import boundary after real forms: test:housekeeping reached 481 passed / 1 failed, then the focused boundary exposed one exact page-state -> People models edge (22 passed / 1 failed).

GREEN implementation

  • Production People services now rehydrate getHousekeepingCapabilityContext() on every public mutation. Invocation data can carry correlation and an expected actor only; it cannot synthesize permissions. The production adapter stays private, while test factories inject an authority resolver.
  • Pure database mutations write their canonical before/after audit evidence in the same transaction. Mixed database/RCON/cache work writes sanitized intent first and a correlated success, failure, or partial outcome afterward. Audit-outcome persistence errors retain truthful completed/partial state, and legacy wrappers preserve their observable behavior.
  • Ban/unban use observed active-ban state; trade-lock uses observed sanction/settings state. Passwords, hashes, API keys, and secrets are excluded from canonical evidence.
  • Shared legacy bulk paths preserve original order, duplicates, totals, and iteration with no service-side 100-item cap. The <=100 bound remains in command schemas. Trade lock has no invented hierarchy gate and its missing-user wrapper message remains exactly User not found.
  • Original StaffActivities side effects are retained for bulk ban/unban/currency/badge, guild disband, VPN, and trade lock. Missing word-filter deletion still reloads local cache, sends RCON refresh, and returns legacy success.
  • The nine registered pages now expose capability-gated, accessible command forms backed by executeHousekeepingCommand; no inert command spans remain. Edit submits a mutation, list inputs come from bounded URL search parameters, and the dynamic preview route passes them through. Atomic Task 11 queries keep their fail-closed contracts; the impossible synthetic partial state was removed. A real Next loading route was added.
  • The foundation contract allows only the exact same-domain edges required here: each People page to the shared People command form, the form to the single housekeeping command action, and page-state to the People ListInput model. No wildcard or prefix relaxation was introduced.

Final verification after review fixes

Focused wrapper/command/page/service/route/auth/audit/staff-smoke matrix
Test Files 24 passed (24)
Tests 187 passed (187)

pnpm test:housekeeping
Test Files 58 passed (58)
Tests 482 passed (482)

pnpm test
Test Files 206 passed | 3 skipped (209)
Tests 1321 passed | 5 skipped (1326)

pnpm typecheck
tsc --noEmit
Exit 0

pnpm exec biome check --formatter-enabled=false <40 exact changed Task 12 source files>
Checked 40 files. No fixes applied.

git diff --check e1b31ff7738eb5cc59e7765c8ed7290d62130972 --
Exit 0

The approved Node engine warning remains: the repository requests Node >=26.8.1 <27, while the host runs Node v26.7.0 with pnpm 11.24.0. No database operation, deployment, push, or pull-request update was performed.