45 lines
2.4 KiB
Markdown
45 lines
2.4 KiB
Markdown
# F-154 — Implementer Evidence
|
|
|
|
## Feature
|
|
F-154 — Admin: separate customers from internal users (fix, high/high).
|
|
|
|
## Changes (all under project/)
|
|
|
|
### Backend
|
|
1. `users/infrastructure/pg-profile-repository.ts` (`listCustomers` → `GET /users`):
|
|
Added literal `iu.role = 'customer' AND` to both the COUNT and SELECT WHERE clauses.
|
|
Parameter indices unchanged (`$1` = email search, `$2` = limit, `$3` = offset) since the
|
|
role filter is a code constant, not a bound parameter (no injection). `findCustomerById`
|
|
(`/users/:id`) is untouched (owner-or-admin, role-agnostic).
|
|
2. `security/api/security.routes.ts` (`GET /admin/users`):
|
|
Base condition `["role <> 'customer'"]` so the Users list NEVER returns storefront
|
|
customers. `?role=admin|editor` still narrows within internal staff via `role = $N`.
|
|
`?role=customer` resolves to an empty intersection (no leak). `where` is always present.
|
|
|
|
### Frontend (apps/admin)
|
|
- `(dashboard)/users/page.tsx`: removed the `customer` option from the Users role filter
|
|
dropdown. The Customers page is unchanged (already calls `/users`, now customer-only).
|
|
|
|
### Tests
|
|
- `users/infrastructure/pg-profile-repository.test.ts` (NEW, 3 tests): mock pool —
|
|
`listCustomers` emits `iu.role = 'customer'` on SELECT+COUNT; `q` stays parametrized as `$1`.
|
|
- `security/api/security.routes.test.ts` (NEW, 3 tests): mock Fastify + mock deps —
|
|
`/admin/users` default → `role <> 'customer'`; `?role=admin` → adds `role = $1` with param;
|
|
`?role=customer` → empty (intersection), never returns customers.
|
|
- `app/tests/users.itest.ts` AC2/AC3: flipped — `/users` returns the customer (ben), not the
|
|
promoted admin (ana). (DB itest, skipped without TEST_DATABASE_URL.)
|
|
|
|
## Verification
|
|
- `npx vitest run <2 new files>` → 6/6 pass (re-run fresh for this session).
|
|
- `npm test` → 206 passed / 56 skipped (itests), 0 failures, no regressions.
|
|
- `npm run typecheck` → 0 errors.
|
|
- `cd project/apps/admin && npx tsc --noEmit` → 0 errors.
|
|
- `npm run lint` → no errors/warnings in files touched.
|
|
- `npm run lint:boundaries` → no NEW violation (R1 on security.routes.ts → log-broadcaster
|
|
is pre-existing: git diff shows the import is untouched by F-154).
|
|
- `./scripts/verify.sh` → exit 0.
|
|
|
|
## Risk
|
|
Medium-high: list semantics change. Mitigated by: single-user `/users/:id` unchanged,
|
|
no migration (`identity_users.role` already exists), tsc + lint + tests green, itest updated.
|