Codex 5.3 Refactor Note: Canonical refactor plan: docs/CODEX-5.3-REFACTOR-PLAN.md. This document is retained for historical and implementation context during the refactor.
Project Context (OfferReview)
Last updated: 2026-04-26
This file summarizes the current state, decisions, and operational notes so future Codex sessions can act quickly and safely. It now tracks both the committed baseline and the current local worktree state in prod.
What this project is
- Next.js 16.1.4 app (App Router) called OfferReview (HR/manager workflow system).
- Prisma ORM used for DB access.
- App runs locally via
npm run devand in production vianpm run build+next start(PM2 on VPS).
Key tech stack
- Next.js 16.1.4
- Prisma (6.x expected; avoid Prisma 7 unless config updated)
- Node 20.x
- DB: Postgres on VPS (current target). Local DB also Postgres.
- Resend for email sending.
Repo layout on this machine
- Primary working tree:
/srv/apps/offerreview/prod - Sibling trees:
/srv/apps/offerreview/prod_hotfix_manager,/srv/apps/offerreview/prod_deploy_smo_hotfix - Production deployment path:
/var/www/offerreview - Default branch:
main
Repo status / recent changes
- Current
prodHEAD onmain:4b9615c(feat: ground resume extraction and add evidence-based skills). - Recent history:
0f793bafeat: expand SMO analytics and interview workflowb70b127feat: enrich employer context with web search951b112feat: expand review workflow and resume insights
prodcurrently has local uncommitted changes across Prisma schema, candidate detail tabs, dashboard/settings, job-description analysis, candidate deep-dive flows, and manager-review access links.prod_hotfix_manageralso has local changes;prod_deploy_smo_hotfixis currently clean.- Future sessions should run
git status --shortbefore editing and treat this doc as the source of truth for the local workstream.
Active local workstream (2026-04-26)
- Shipped recently:
- resume extraction is now grounded to direct resume evidence and exposes evidence-based skills via
src/lib/resumeSkills.tsandsrc/components/ResumeSkillsGrid.tsx - SMO compare analytics is live through
src/app/api/analytics/smo-compare/route.tsandsrc/lib/analytics/smoCompare.ts - SMO interview questions are generated/cached through
src/app/api/candidates/[id]/smo-questions/route.ts
- resume extraction is now grounded to direct resume evidence and exposes evidence-based skills via
- Active local slice:
- candidate deep-dive questionnaire flow with new Prisma models, public questionnaire token routes, an SMO-only review tab, and an SMO-owned deep-dive question bank
- manager-review magic-link access with long-lived tokens sent on manager assignment
- position/job-description analysis and a requirement that new candidate uploads target positions with an active job description
- candidate detail expansion (
Radar,Deep Dive, richer overview/header/tabs) plus supporting dashboard/settings/API cleanup
- Candidate workflow currently represented in schema and code:
NEW -> HR_SCREENED -> MANAGER_EVAL_PENDING -> MANAGER_REVIEWED or CANDIDATE_DEEP_DIVE_PENDING -> TO_SMO -> APPROVED/REJECTED/KIV
- AI evaluation prefill remains disabled end-to-end:
GET /api/candidates/[id]/evaluation-prefillreturns a disabled status messagePOST /api/candidates/[id]/evaluation-prefillreturns410src/app/api/candidates/[id]/documents/route.tsno longer triggers evaluation analysis on upload
- Role-flow audit is stored in
docs/ROLE-FLOW-CHECK-2026-04-26.md.
Environment variables (critical)
Local .env.local (dev):
DATABASE_URL=postgresql://...(local Postgres)JWT_SECRET=...RESEND_API_KEY=...RESEND_FROM_EMAIL=...OPENAI_API_KEY=...OPENAI_MODEL=...(optional, defaults togpt-4o-mini)APP_NAME=OfferReview(optional)
VPS .env (prod):
DATABASE_URL=postgresql://offerreview_user:***@localhost:5432/offerreviewJWT_SECRET=...RESEND_API_KEY=...RESEND_FROM_EMAIL=...
Notes:
- Do NOT point local env to Hostinger MySQL. That caused login 500s.
- On VPS, ensure
.envexists and is loaded by PM2/systemd.
Database + Prisma
- Provider should be
postgresqlinprisma/schema.prisma. - Migration folder exists:
prisma/migrations/20250205_init/migration.sql. - If migrations missing on VPS, run:
npx prisma migrate deploy. - If Prisma fails with missing
DATABASE_URL,.envisn't loaded.
Postgres permissions on VPS
- If you see
permission denied for schema public, fix as postgres user:ALTER DATABASE offerreview OWNER TO offerreview_user;ALTER SCHEMA public OWNER TO offerreview_user;GRANT ALL ON SCHEMA public TO offerreview_user;ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT ALL ON TABLES TO offerreview_user;
Deployment on VPS (current path)
- VPS OS: Ubuntu (plain OS)
- App folder:
/var/www/offerreview - PM2 process name:
offerreview
Typical flow:
cd /var/www/offerreviewgit pull origin main- Ensure
.envis present npm installnpx prisma generatenpx prisma migrate deploynpm run build- Restart PM2:
pm2 delete offerreviewexport $(grep -v '^#' .env | xargs)pm2 start npm --name offerreview -- startpm2 save
PM2 logs (VPS)
pm2 logs offerreview --lines 50 --nostream- Files:
/root/.pm2/logs/offerreview-out.logand...-error.log
Common errors previously seen:
Environment variable not found: DATABASE_URL(PM2 not loading env)Cannot find module @prisma/client-...(Prisma client not generated after build)
Nginx / Adminer (VPS)
- Nginx reverse proxy to Node (port 3000).
- Adminer installed for DB inspection.
- If Adminer 404, ensure Nginx config includes:
location /adminer/ { alias /usr/share/adminer/; ... }fastcgi_pass unix:/run/php/php8.3-fpm.sock;(note php8.3)
- Access:
http://<server-ip>/adminer/
Authentication + audit log
- Audit log writes can fail if userId doesn't exist.
- Recent fix:
writeAuditEventnow allows null userId when it doesn't exist.
Resend (email)
- API key and from email required.
- Helper functions are in
src/lib/notifications/email.ts.
OpenAI / document analysis
- Resume analysis is active and updates
CandidateDocumentAI fields plus candidate snapshot fields. - SMO interview analysis is active.
- Candidate deep-dive answer analysis is present in the worktree via
src/lib/ai/deepDiveAnalysis.ts. - Evaluation document AI parsing code exists, but the user-facing prefill workflow is currently disabled. Do not assume evaluation uploads will auto-populate HR or manager review forms.
Known pitfalls
- Prisma v7 errors about datasource url: stick to Prisma 6.x unless you migrate config.
- Avoid Turbopack on low-resource servers (set
NEXT_DISABLE_TURBOPACK=1). - If login returns 500 locally, check
.env.localpoints to local Postgres. - Older docs may still mention AI evaluation prefill as if it is live. Current local truth is manual HR/Manager form completion plus a disabled prefill endpoint.
- Current local manager access logic is assignment-based, not department-wide, in the actively edited candidate flows.
src/app/page.tsxis still the default starter page; actual product entry flows are/loginand/dashboard.Settingsis linked in the global nav for all roles, but/api/settingsand/api/settings/notification-rulesare currently admin-only.- The manager dashboard currently includes unassigned
HR_SCREENEDcases even though candidate detail access remains assignment-locked. - HR can list users from
/admin/users, butGET /api/users/[id]is currently restricted to Admin/SMO. - For reasoning-model OpenAI variants, use
src/lib/ai/openaiTokenLimits.tshelpers instead of hardcodingtemperature,max_tokens, ormax_completion_tokens.
Quick local commands
- Start dev:
npm run dev - Build:
npm run build - Prisma generate:
npx prisma generate - Migrate deploy:
npx prisma migrate deploy - DB health check (Postgres):
psql "$DATABASE_URL" -c "select 1;"