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 (Full)
Last updated: 2026-02-05
This is the full, high‑signal context for OfferReview. It’s meant to be used by Codex or engineers for fast onboarding, troubleshooting, and safe modifications.
1) Project summary
- Product: OfferReview (HR/manager hiring workflow system).
- Stack: Next.js 16.1.4 (App Router), Prisma ORM, Node 20.x.
- Email: Resend API.
- AI: OpenAI for resume analysis.
- Storage: Local uploads directory + optional S3 (presigned) support.
- Preferred DB: PostgreSQL (both local and VPS).
2) Current repository state
- Default branch:
main. - Latest known commit:
0a7cb7e(Resend email helpers + resend-setup sends email). - Build script:
prisma generate && NEXT_DISABLE_TURBOPACK=1 NEXT_FORCE_WEBPACK=1 next build.
3) Top‑level structure
/ (repo root)
src/ Next.js app + API routes
prisma/ Prisma schema + migrations + seed
scripts/ Seed helpers
docs/ Project docs (W1…W12)
uploads/ Local file storage target (dev/prod if UPLOADS_DIR unset)
4) Key routes (App Router)
App pages
/login,/request-access,/forgot-password/dashboard/notifications,/settings/candidates,/candidates/[id]/upload-resume/admin/access-requests/admin/roles,/admin/users,/admin/organization/admin/templates/admin/audit,/admin/notifications
API endpoints (selected)
- Auth:
/api/auth/login,/api/auth/logout,/api/auth/me - Access requests:
/api/access-requests,/api/access-requests/[id] - Candidates:
/api/candidates,/api/candidates/[id] - Documents:
/api/documents,/api/documents/[docId] - Uploads:
/api/uploads/local,/api/uploads/presign - Templates:
/api/templates,/api/templates/[id] - Settings:
/api/settings,/api/settings/notification-rules - Admin outbox:
/api/admin/outbox - Health:
/api/health/openai
5) Environment variables (required/optional)
Required for app startup
DATABASE_URL(Postgres for local/VPS)JWT_SECRET
Email (Resend)
RESEND_API_KEYRESEND_FROM_EMAIL(orRESEND_FROM)APP_NAME(optional, default “OfferReview”)
OpenAI (resume analysis)
OPENAI_API_KEYOPENAI_MODEL(optional; defaultgpt-4o-mini)
Misc
NEXT_PUBLIC_APP_URL(used for invite links)JOB_SECRET(for/api/jobs/outbox-dispatch)OUTBOX_BATCH_SIZE(optional)UPLOADS_DIR(optional; defaults to<repo>/uploads)
6) Prisma models (overview)
Models:
User,Permission,RolePermission,InAppNotification,Outbox,OutboxLog,SystemSettings,NotificationRule,AuditLog,AccessRequest,Candidate,Department,Position,CandidateDocument,HrScreening,ManagerReview,EvaluationTemplate,AuthToken,Decision.
Enums (current values):
Role: ADMIN | HR | MANAGER | SMO
UserStatus: ACTIVE | DISABLED | PENDING_INVITE
RequestedRole: HR | MANAGER | SMO | ADMIN
AccessRequestStatus: PENDING | APPROVED | REJECTED
CandidateStatus: NEW | HR_SCREENED | MANAGER_EVAL_PENDING | MANAGER_REVIEWED | TO_SMO | APPROVED | REJECTED | KIV | COMPLETED
DecisionType: APPROVED | REJECTED | KIV
DocumentCategory: RESUME | PORTFOLIO | CERT | OTHER | SCREENING_NOTES | EVALUATION | DECISION | OFFER
DocumentStatus: AVAILABLE | PENDING_SCAN
AuditEventType: (see schema for full list; includes login, candidate, template, access request, outbox)
NotificationChannel: EMAIL | IN_APP | BOTH
OutboxStatus: QUEUED | SENT | FAILED | RETRYING
OutboxProvider: RESEND | IN_APP
TemplateStatus: DRAFT | PUBLISHED | ARCHIVED
HrScreeningMode: QUICK
HrOutcome: PASS | KIV | REJECT
ManagerReviewMode: QUICK
ManagerRecommendation: PROCEED | KIV | REJECT
AuthTokenType: INVITE | RESET_PASSWORD
7) Seeds
package.json:
- Seed command:
node prisma/seed.js
prisma/seed.js creates or updates:
admin@example.com/admin123(ADMIN)hr@example.com/hr123(HR)manager@example.com/manager123(MANAGER)smo@example.com/smo123(SMO)
Additional scripts in scripts/:
seed-settings.tsseed-permissions.tsseed-demo.ts
8) File uploads
- Local storage helpers:
src/lib/storage/local.ts(usesuploads/by default). - S3 support exists via
src/lib/storage/s3.ts(needs AWS envs + @aws-sdk deps). - Upload routes:
/api/uploads/local,/api/uploads/presign.
9) AI resume analysis
src/lib/ai/resumeAnalysis.tsextracts text from PDF/DOC/DOCX, calls OpenAI.- Writes results into
CandidateDocumentAI fields and updates candidate snapshot fields. - Requires
OPENAI_API_KEY.
10) Email
- Resend client:
src/lib/notifications/resend.ts. - Helper templates:
src/lib/notifications/email.ts. /api/users/[id]/resend-setupsends invite email (best effort; logs failures).
11) Build + runtime notes
- Build uses Webpack (Turbopack disabled in build script).
- On low‑resource servers, Turbopack may panic; keep
NEXT_DISABLE_TURBOPACK=1. - If you see
@prisma/client-xxxxmissing module errors, Prisma client wasn’t generated after install/build.
12) Local dev workflow
# from repo root
npm install
npx prisma generate
npx prisma migrate deploy
npm run dev
13) VPS deployment (Postgres)
Assumes Ubuntu, app in /var/www/offerreview, PM2 process offerreview.
Steps:
cd /var/www/offerreviewgit pull origin main- Ensure
.envexists (DATABASE_URL + JWT_SECRET + Resend keys). npm installnpx prisma generatenpx prisma migrate deploynpm run buildpm2 delete offerreviewexport $(grep -v '^#' .env | xargs)pm2 start npm --name offerreview -- startpm2 save
14) VPS Postgres permissions
If permission denied for schema public:
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;
15) Logs
Local
tail -n 200 /tmp/next-dev.log
VPS (PM2)
pm2 logs offerreview --lines 50 --nostream/root/.pm2/logs/offerreview-out.log/root/.pm2/logs/offerreview-error.log
16) Nginx + Adminer (VPS)
Adminer installed for DB inspection.
- Path:
/adminer/ - Needs php-fpm socket:
/run/php/php8.3-fpm.sock
If 404 on /adminer/, ensure:
location /adminer/ {
alias /usr/share/adminer/;
index adminer.php;
include snippets/fastcgi-php.conf;
fastcgi_param SCRIPT_FILENAME /usr/share/adminer/adminer.php;
fastcgi_pass unix:/run/php/php8.3-fpm.sock;
}
17) Common failure patterns
- 500 on login (local):
.env.localpointing to remote MySQL. - Prisma errors on VPS:
.envmissing or not loaded by PM2. - Missing
@prisma/client-xxx: Prisma client not generated after install. - Turbopack panics on VPS: keep Webpack build flags.
18) Docs in repo
W1-LOGIN-IMPLEMENTATION.md,W2-*,W3-*,W4-*,W6-*,W9-*,W10-*,W11-*,W12-*contain detailed implementation notes.
If you need this to include extra details (e.g., full API contract, UI screenshots, or complete schema), specify the scope and I’ll expand it.