6.5 KiB
6.5 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.tsbut 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, andpeople.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,
/adminrevalidation, VPN redirect/fail-soft behavior, word-filterActionResultshapes, 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 usesUSERS_RESET_PASSWORD, bulk/user/community/team/application operations useUSERS_EDIT, IP/VPN useSETTINGS_EDIT, and word filter usesWORDFILTER_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
/adminbehavior 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.