Skip to content

feat: admin API layer, split CI, PR previews and contributor docs (#709, #686, #687, #695) - #828

Merged
amina69 merged 1 commit into
amina69:mainfrom
ZeePearl56:feat/709-695-687-686-admin-ci-docs
Oct 25, 2026
Merged

amina69 merged 1 commit into
amina69:mainfrom
ZeePearl56:feat/709-695-687-686-admin-ci-docs

Conversation

@ZeePearl56

Copy link
Copy Markdown
Contributor

Summary

Four Phase 3 backlog items in one PR: the typed admin API layer, a split CI pipeline, PR preview deployments, and contributor docs.

Closes #709
Closes #695
Closes #687
Closes #686


#709 — Admin types, schemas and adminService

File What
src/features/admin/schemas/paginated.ts paginatedSchema(item) factory → { items, total, page, pageSize }
src/features/admin/schemas/adminSchemas.ts adminUserSchema, auditLogEntrySchema (id, actorId, actorName, action, entityType, entityId, createdAt, metadata), adminStatsSchema, and the two paginated list schemas
src/features/admin/types/admin.types.ts Types inferred from the schemas so the two cannot drift
src/api/adminService.ts listUsers, getAuditLog, getStats; every response is Zod-parsed
src/lib/forbidden.ts, src/components/ForbiddenNotifier.tsx Global 403 handling
  • Paginated<T> is reusable: both admin lists are built from the one factory.
  • 403 never renders a raw error: adminService raises ForbiddenError (the class already in lib/api-errors). The query client reports any 403 to a small channel, and ForbiddenNotifier (mounted once in main.tsx) shows a fixed "You don't have permission to do that." toast. The backend's message is never shown. userFacingMessage(error) is exported for screens that render an error inline.
  • Endpoints are an assumption: GET /admin/users, /admin/audit-log, /admin/stats, with the page/pageSize/filter params listed in admin.types.ts. Please confirm with whoever builds the backend.

⚠️ Overlap with #820

Open PR #820 also adds src/api/adminService.ts and src/types/admin.ts, with a different shape (plain arrays, plus suspend/reinstate/role methods). Whichever merges second will conflict on adminService.ts. I followed #709's spec (paginated envelope, Zod parsing, ForbiddenError) rather than guessing at #820's, so the two will need reconciling: #820's hooks would move to { items, total } results and I'd suggest keeping its mutation methods in this file. Happy to rebase onto whichever lands first.

#686 — Core CI workflow (.github/workflows/ci.yml)

Jobs, each reporting its own check:

Install (cached node_modules, audit, lockfile check) → Type check · Lint · Unit tests (coverage, uploaded as an artifact) · Build, plus the existing e2e job, and a final CI success gate.

  • Node 20; concurrency group cancels superseded PR runs (runs on main are never cancelled).
  • New scripts: type-check (tsc -b) and test:coverage; new dev dependency @vitest/coverage-v8@4.1.12 (matching the locked vitest; package-lock.json only gains the coverage packages). Coverage config is in vite.config.ts; coverage/ is git-ignored. No coverage threshold is enforced, since none was specified.
  • test:coverage uses --testTimeout=30000. With coverage on, 13 existing tests timed out at the 5 s default in a full local run. I also gave one existing wait (realtimeNotifications.test.tsx, the lazy-loaded dropdown) a 10 s timeout.

Needs a repo admin ("PRs can't merge red"): a workflow file can't enforce merge rules. Require the CI success check in branch protection for main. It is red if any job failed, was cancelled or was skipped. Steps are in the new docs/ci.md.

Heads-up: the old validate job was split into Install, Type check, Lint, Unit tests and Build. If validate is currently a required check it must be replaced, or PRs will wait on it forever.

#687 — PR preview deployments (.github/workflows/preview.yml)

  • Deploys each PR to a Vercel preview (same build steps as deploy.yml), posts one sticky comment with the URL and updates it on each push, and removes the deployment when the PR closes (the URL is stored in the comment as a hidden marker).
  • Uses a GitHub Environment named preview; required secrets/variables are in the new "Pull request previews" section of docs/deploy.md. Previews point at the staging API.
  • Fork PRs are skipped (GitHub gives them no secrets).

MSW is not supported in previews. The issue mentions MSW configurable by label. MSW only runs in the dev server (import.meta.env.DEV in main.tsx), and scripts/check-msw-production.mjs deliberately fails any production build with VITE_MSW=true (#526). Enabling it in a deployed preview would mean weakening that guard, so I left it off and documented why. Analytics are also forced off in previews.

#695 — Contributing guide, changelog, release checklist

  • CONTRIBUTING.md: setup, branch/commit conventions (taken from the repo's actual history), how to add a feature folder (mirrors src/features/approval), local checks, PR checklist (type-check, lint, test, build, a11y, Figma comparison screenshots), and the release checklist (version bump, tag, staging smoke test, production approval, rollback).
  • CHANGELOG.md: Keep-a-Changelog, Phase 3 under [Unreleased], written from the merged history.
  • .github/pull_request_template.md (picked up automatically for new PRs) and .github/ISSUE_TEMPLATE/ bug + feature forms (blank issues disabled).
  • README: contributing section now points at the guide; scripts table lists the new commands. docs/ci.md is new.

The release steps match docs/deploy.md (push main to staging, tag v*, approve in the production environment).


Tests

New: 23 tests in 3 files — adminService (params, schema rejection, 403 → ForbiddenError, other errors pass through), paginatedSchema (reuse + invalid envelopes), and the 403 channel (including that the raw server text is never rendered).

  • ✅ tsc -b clean; ESLint clean on all changed code
  • ✅ Full suite under npm run test:coverage: 141/142 files, 1144/1145 tests; the one failure was the lazy-dropdown timeout fixed above, and that file passes with coverage on its own
  • ✅ Both workflow files parse as valid YAML

Not verified

  • The workflows haven't run on GitHub. ci.yml and preview.yml were only YAML-validated locally; the first CI run is their real test, and preview.yml additionally needs the preview environment configured with Vercel credentials.
  • I did not re-run the entire coverage suite after the last one-line test change (that file was re-run alone).
  • The new CONTRIBUTING docs have not been walked through by someone fresh to the repo.

…ina69#709, amina69#686, amina69#687, amina69#695)

amina69#709 Admin types, schemas and adminService
- Zod schemas/types for AdminUser, AuditLogEntry, AdminStats and a reusable
  paginatedSchema factory; adminService parses every response
- 403 raises ForbiddenError; a global handler shows a fixed friendly message

amina69#686 Core CI workflow
- Separate Install, Type check, Lint, Unit tests (coverage), Build and e2e jobs
- Concurrency group cancels superseded PR runs; CI success gate job

amina69#687 PR preview deployments
- preview.yml deploys each PR to Vercel, keeps one sticky comment, and removes
  the deployment when the PR closes

amina69#695 Contributing guide, changelog and release checklist
- CONTRIBUTING.md, CHANGELOG.md, PR template and bug/feature issue templates
@vercel

vercel Bot commented Oct 25, 2026

Copy link
Copy Markdown

@ZeePearl56 is attempting to deploy a commit to the sheriffamina1-9497's projects Team on Vercel.

A member of the Team first needs to authorize it.

@amina69
amina69 merged commit 103c836 into amina69:main Oct 25, 2026
9 of 11 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

2 participants