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

12 KiB

Task 11 — People workflow read models

Status: DONE — fix round 1

Delivered scope

  • Added the exact 24-route People catalog covering the 39 migration-matrix entries across users, multi-account review, online/community, guilds, staff applications/teams, support tickets/help tickets, CFH, moderation overview, bans, IP rules, VPN settings, and word filter workflows.
  • Added canonical, JSON-serializable People DTOs, /ase/people link builders, bounded list normalization, and stable sorting with numeric-ID tie breaking.
  • Added injected query factories and narrow server-only production adapters for user/detail, community/guild, staff/applications/teams, support queues/tickets/help/CFH, and moderation/bans/sanctions sources.
  • Reused foundation HousekeepingResult, error codes, capability context, authorization, and canonical href contracts. People-local ListInput and Page were added because no shared foundation equivalents exist in this checkout.
  • Kept the People manifest, global handlers, pages, mutations, providers, widgets, search, and inbox unchanged for Task 12.

Security and behavior decisions

  • User mail and current IP remain independently nullable fields. Each is projected only when the capability context contains the existing PERMS.USERS_VIEW; PERMS.MOD_USERS_VIEW alone receives the safe base projection with both values set to null, and a context with neither permission is forbidden.
  • No new ACL slug or rank threshold was introduced. Staff filtering reuses the existing getMinStaffRank() source.
  • The production user selection is explicit and excludes passwords, authentication tickets, secrets, and two-factor material. VPN settings intentionally exclude vpn_api_key.
  • Adapters fail closed. Malformed driver envelopes, invalid or non-positive identifiers, corrupt links, non-serializable DTO values, and count failures map to DEPENDENCY_UNAVAILABLE. Missing valid detail entities map to NOT_FOUND; invalid request identifiers map to VALIDATION. No partial-result shape is returned because no People DTO explicitly names failed sources.
  • Pagination clamps page size to 100 and offset to 10,000. Deterministic primary sorting, numeric-ID tie breaking, and LIMIT/OFFSET now execute in the database; no list query fetches a prefix for locale re-sorting or second slicing.
  • Raw production adapters and buildPeopleUserSelection are module-private. Runtime exports expose only context-authorized query factories and singleton query surfaces.
  • Multi-account clusters use one bounded CTE/window query, cap accounts per cluster at 100, and never issue one query per IP cluster.
  • User detail/edit now includes the operator's watched state and canonical permission-rank data. Support ticket reads use the existing unified inbox through a strict, fail-closed, database-paged mode that includes CMS and help-center rows while leaving the legacy tolerant mode unchanged.
  • Support desk/detail DTOs explicitly include queue counts, bounded staff, and the relevant active ban. Ticket messages/replies and staff rows are bounded.
  • Active bans are filtered before sorting. Expiry 0 remains the permanent-active sentinel; expired rows cannot hide permanent or future-active bans in lists or details.

Official fix round 1 findings

  1. Authorization boundary: fixed by making all raw production adapters and the user selection builder module-private and testing only guarded public query surfaces plus source/runtime export contracts.
  2. Pagination and sorting: fixed by moving declared sort fields, deterministic tie ordering, and bounded LIMIT/OFFSET to production adapters. The exact user10/user2 and support status/updatedAt page regressions are covered.
  3. Resource bounds: fixed by replacing multi-account prefix loading plus per-row Promise.all with one bounded batched CTE/window query. No million-row prefix and no N+1 cluster query remain.
  4. Fail-closed database validation: fixed across People models and community/support/moderation query boundaries. Invalid driver shapes and invalid identifiers cannot become empty lists, NOT_FOUND, ID 0, or corrupt canonical links.
  5. Canonical dependencies: fixed watched and permission-rank data for user detail/edit; /support/tickets now calls strict fetchUnifiedTicketInbox; support queue/staff/active-ban data is explicit in canonical query DTOs.
  6. Moderation capability equality: fixed after direct user authorization. moderationQuery.capability now exactly equals the existing eleven-slug overview union already used by the route and run; no route, mutation, rank threshold, or new slug changed.
  7. Active bans: fixed list/detail selection so permanent ban_expire = 0 and future-active bans are deterministic and expired rows cannot hide them.

The two official Minor findings remain parked and unchanged as instructed.

Strict TDD evidence

Cycle 1 — exact route catalog

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/routes.test.ts
Test Files 1 failed
Error: Cannot find module './routes'

GREEN:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/routes.test.ts
Test Files 1 passed (1)
Tests 3 passed (3)

Cycle 2 — canonical models and normalizers

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/models.test.ts
Test Files 1 failed
Error: Cannot find module './models'

GREEN:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/models.test.ts
Test Files 1 passed (1)
Tests 5 passed (5)

Cycle 3 — injected-adapter read queries

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-queries.test.ts
Test Files 1 failed
Error: Cannot find module './community'

GREEN:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-queries.test.ts
Test Files 1 passed (1)
Tests 10 passed (10)

Production-source contract RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 1 failed (1)
Tests 2 failed (2)
Reason: raw production adapters and buildPeopleUserSelection were exported as bypassable runtime internals.

Pagination regression RED after adding the production contract fixture:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 1 failed (1)
Tests 1 failed | 2 passed (3)
Expected ["203.0.113.1", "203.0.113.2"], received ["203.0.113.2"].

GREEN for the original baseline implementation:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 1 passed (1)
Tests 3 passed (3)

The query tests cover adversarial page size/offset/search, stable tie sorting, empty/missing entities, adapter and count failures, PII capability combinations, serializable DTOs, explicit source projection, and production pagination.

Fix round 1 strict behavioral TDD evidence

Authorization boundary

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 1 failed (1)
Tests 2 failed (2)
Observed runtime exports: buildPeopleUserSelection and peopleUsersAdapters.

GREEN:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 1 passed (1)
Tests 3 passed (3)

Database pagination and declared sorting

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/models.test.ts src/features/housekeeping/domains/people/queries/people-queries.test.ts
Test Files 2 failed (2)
Tests 4 failed | 14 passed (18)
Failures: offset 999999 was not capped; DB pages were sliced a second time for user10/user2 and support status/updatedAt.

GREEN:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/models.test.ts src/features/housekeeping/domains/people/queries/people-queries.test.ts
Test Files 2 passed (2)
Tests 18 passed (18)

Multi-account resource bounds

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 1 failed (1)
Tests 1 failed | 2 passed (3)
Observed prefix result plus one query per IP cluster.

GREEN:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 1 passed (1)
Tests 3 passed (3)

Fail-closed validation

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/models.test.ts src/features/housekeeping/domains/people/queries/people-queries.test.ts src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 3 failed (3)
Tests 5 failed | 21 passed (26)
Failures covered ID 0, corrupt links/dates, corrupt detail shapes, and malformed driver envelopes.

GREEN:

same command
Test Files 3 passed (3)
Tests 26 passed (26)

Canonical dependencies and unified support inbox

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-queries.test.ts src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts -t "watched state|hydrates desk|strict unified"
Test Files 2 failed (2)
Tests 3 failed | 22 skipped (25)

GREEN:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/models.test.ts src/features/housekeeping/domains/people/queries/people-queries.test.ts src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts -t "watched state|hydrates desk|strict unified|normalizes BigInt"
Test Files 3 passed (3)
Tests 4 passed | 27 skipped (31)

Moderation capability equality

RED captured before direct authorization:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-queries.test.ts -t "eleven-permission"
Test Files 1 failed (1)
Tests 1 failed | 18 skipped (19)
Expected the route/run eleven-slug union; query metadata still contains six slugs.

GREEN after the user directly authorized only this isolated metadata hunk:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-queries.test.ts -t "eleven-permission"
Test Files 1 passed (1)
Tests 1 passed | 18 skipped (19)

Active-ban semantics

RED:

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts -t "permanent"
Test Files 1 failed (1)
Tests 1 failed | 4 skipped (5)
Expected permanent expiresAt 0; received null.

GREEN:

same command
Test Files 1 passed (1)
Tests 1 passed | 4 skipped (5)

Verification

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people/routes.test.ts src/features/housekeeping/domains/people/models.test.ts src/features/housekeeping/domains/people/queries/people-queries.test.ts src/features/housekeeping/domains/people/queries/people-adapters-production.test.ts
Test Files 4 passed (4)
Tests 35 passed (35)

pnpm exec vitest run --coverage.enabled=false src/features/housekeeping/domains/people src/features/housekeeping/foundation/foundation-source-contract.test.ts src/features/housekeeping/foundation/authorization.test.ts src/features/housekeeping/foundation/capability-context.test.ts src/features/housekeeping/foundation/server-capability-context.test.ts src/features/housekeeping/foundation/contracts/contracts.test.ts
Test Files 9 passed (9)
Tests 81 passed (81)

pnpm test:housekeeping
Test Files 49 passed (49)
Tests 430 passed (430)

pnpm typecheck
tsc --noEmit
Exit 0

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

git diff --check
Exit 0

Both pnpm test:housekeeping and pnpm typecheck emitted the environment warning: the repository requires Node >=26.8.1 <27, while this host runs Node v26.7.0 with pnpm 11.24.0. Tests and typecheck still exited successfully.

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