feat(housekeeping): deliver people account workflows
This commit is contained in:
1 parent
7920d4f46c
commit
e1b31ff773
45 files changed
+4290
-1243
No files matched your search
@@ -0,0 +1,155 @@
|
||||
# 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
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
Focused foundation contracts: 3 files passed, 40 tests passed
|
||||
People + foundation: 34 files passed, 380 tests passed
|
||||
```
|
||||
|
||||
### Audited sanction reason
|
||||
|
||||
RED:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
Production mutation contracts: 2 files passed, 4 tests passed
|
||||
The audited snapshot includes the reason and excludes mail.
|
||||
```
|
||||
|
||||
### Legacy wrapper failure parity
|
||||
|
||||
RED:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
Test Files 1 passed (1)
|
||||
Tests 3 passed (3)
|
||||
```
|
||||
|
||||
### Single authorization check for positive bulk adjustment
|
||||
|
||||
RED:
|
||||
|
||||
```text
|
||||
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:
|
||||
|
||||
```text
|
||||
Test Files 1 passed (1)
|
||||
Tests 1 passed (1)
|
||||
```
|
||||
|
||||
### Static gates during implementation
|
||||
|
||||
```text
|
||||
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
|
||||
|
||||
```text
|
||||
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.
|
||||
Reference in new issue
Block a user