DESCRIPTION
GET /users (UsersService.listUsers, apps/api/src/users/users.service.ts) fetches the entire profiles table with no pagination, no search, and no filters, and the frontend has no dedicated admin console to manage users — role changes happen with no audit trail beyond the raw update. This epic turns user administration into a real, scalable feature end-to-end.
GOAL
Admins/TSE can browse, search, and filter the full user directory without loading the whole table at once, change roles in bulk, deactivate/reactivate accounts, and see an audit trail of every change — through a dedicated UI.
REQUIREMENTS
Backend
- Paginate
GET /users using the existing parsePagination/paginatedResponse helpers in apps/api/src/common/pagination.ts and the PaginatedResponse<T> type from @velar/types (same pattern already used elsewhere — do not reinvent it).
- Add
?role=, ?search= (name/email) query params.
- Add a bulk role-assignment endpoint (array of user ids + target role), admin-only, reusing
UsersService.setRole's authorization rule.
- Every role change and (de)activation (see the auth-lifecycle epic if it has landed) is recorded via
AuditService.emit().
Frontend
- A user-management view (e.g. under
apps/web/app/configuracion/ or a new /admin/usuarios route, gated the same way /tse and /partido already are in middleware.ts) listing users with pagination, search, role filter, bulk role assignment, and an audit-trail view per user.
- Use the shared
Table primitive if the design-system Table epic has already landed; otherwise build the minimal table needed and note the follow-up.
ACCEPTANCE CRITERIA
GET /users?page=2&limit=20&role=comprador&search=ana returns the correct paginated/filtered slice with an accurate total.
- Bulk role assignment updates multiple users in one call and is audit-logged per user.
- The admin UI lists, searches, filters, paginates, and shows an audit trail, gated to
admin/tse roles only.
npm run build, npm run lint, npm run test pass in both apps/api and apps/web with NO VELAR credentials.
NOTES
Relevant files: apps/api/src/users/users.service.ts, apps/api/src/users/users.controller.ts, apps/api/src/common/pagination.ts (reuse), apps/api/src/audit/, apps/web/middleware.ts (route gating pattern), apps/web/app/configuracion/, packages/types/src/. Backend and frontend work must respect the existing split: only the backend agent edits apps/api/** logic (docs/AGENTS.md).
No VELAR credentials required: verifiable locally with a mocked SupabaseService and local dev — no real database or credentials.
Difficulty: Advanced (full-stack)
Priority: High
PR REQUIREMENTS
- Ship this as a single pull request — do not split into stacked/sequential PRs.
- Your PR description must include
Closes #<this-issue-number> (this issue's GitHub number) so merging auto-closes it.
CAMPAIGN REQUIREMENTS (FWC26)
To be eligible for the reward on this issue, the contributor must:
DESCRIPTION
GET /users(UsersService.listUsers,apps/api/src/users/users.service.ts) fetches the entireprofilestable with no pagination, no search, and no filters, and the frontend has no dedicated admin console to manage users — role changes happen with no audit trail beyond the raw update. This epic turns user administration into a real, scalable feature end-to-end.GOAL
Admins/TSE can browse, search, and filter the full user directory without loading the whole table at once, change roles in bulk, deactivate/reactivate accounts, and see an audit trail of every change — through a dedicated UI.
REQUIREMENTS
Backend
GET /usersusing the existingparsePagination/paginatedResponsehelpers inapps/api/src/common/pagination.tsand thePaginatedResponse<T>type from@velar/types(same pattern already used elsewhere — do not reinvent it).?role=,?search=(name/email) query params.UsersService.setRole's authorization rule.AuditService.emit().Frontend
apps/web/app/configuracion/or a new/admin/usuariosroute, gated the same way/tseand/partidoalready are inmiddleware.ts) listing users with pagination, search, role filter, bulk role assignment, and an audit-trail view per user.Tableprimitive if the design-system Table epic has already landed; otherwise build the minimal table needed and note the follow-up.ACCEPTANCE CRITERIA
GET /users?page=2&limit=20&role=comprador&search=anareturns the correct paginated/filtered slice with an accuratetotal.admin/tseroles only.npm run build,npm run lint,npm run testpass in bothapps/apiandapps/webwith NO VELAR credentials.NOTES
Relevant files:
apps/api/src/users/users.service.ts,apps/api/src/users/users.controller.ts,apps/api/src/common/pagination.ts(reuse),apps/api/src/audit/,apps/web/middleware.ts(route gating pattern),apps/web/app/configuracion/,packages/types/src/. Backend and frontend work must respect the existing split: only the backend agent editsapps/api/**logic (docs/AGENTS.md).No VELAR credentials required: verifiable locally with a mocked
SupabaseServiceand local dev — no real database or credentials.Difficulty: Advanced (full-stack)
Priority: High
PR REQUIREMENTS
Closes #<this-issue-number>(this issue's GitHub number) so merging auto-closes it.CAMPAIGN REQUIREMENTS (FWC26)
To be eligible for the reward on this issue, the contributor must: