7.2 KiB
7.2 KiB
Backend Fastify / Prisma
Scope
Server work lives under server/. Prefer existing route, service, utility and
QA script patterns over new abstractions.
Rules
- Validate Prisma changes with
cd server && npm run prisma:validate. - For route/service edits, run
node --checkon the touched files and the focused regression listed in the current Trellis task. - Prisma migrations require rollback notes in the Trellis task design or PRD.
- Do not resolve migration drift, reset databases, or rewrite migration history without explicit approval.
- Workflow, approval and permission behavior must be verified at process level, not only syntax level.
Common Checks
cd server && node --check src/routes/reimbursements.jscd server && node --check src/routes/workflow.jscd server && ./scripts/regression-workflow-actions.shcd server && ./scripts/regression-all.sh
Scenario: Local Regression Migration Drift
1. Scope / Trigger
- Trigger: a local or attached E2E fails with Prisma
missing column,column does not exist, enum missing, or route 500 immediately after a schema-backed feature was added. - Applies to
server/prisma/schema.prisma,server/prisma/migrations/, local regression databases such ashyb_oa_regression, and Playwright tests that use real API/database flows.
2. Signatures
- Read-only drift check:
cd server && npx prisma migrate status. - Apply committed migrations after explicit confirmation:
cd server && npx prisma migrate deploy. - Local service smoke for attached E2E:
HOST=127.0.0.1 PORT=3000 JOBS_ENABLED=false SERVE_CLIENT_DIST=true npm run dev. - Server entrypoints that call
getConfig()beforebuildApp()must loaddotenv/configbefore reading config.
3. Contracts
migrate statusis safe and read-only; it may be run before asking the user.migrate deploywrites database schema state and requires explicit user confirmation unless the current task already approved that exact local DB.- Do not use
prisma migrate resetfor E2E recovery without separate backup and destructive-action approval. - Attached local E2E should disable background jobs with
JOBS_ENABLED=falseunless the test explicitly validates job behavior.
4. Validation & Error Matrix
migrate statusreports pending migrations -> record the migration names, inspect whether they are additive/destructive, then ask before applying.- Missing
JWT_SECRETduringnpm run devwhile.envexists -> verify the entrypoint loadsdotenv/configbeforegetConfig(). - Missing column after
migrate deploy-> inspect actual columns and migration history; do not patch tests to hide schema drift. - E2E selector failure after schema is fixed -> treat as page/test contract drift and update the focused E2E assertion, not the database.
5. Good/Base/Bad Cases
- Good: run
migrate status, apply only committed migrations after approval, seed dev users, then rerun the focused Playwright flow. - Base: if migrations are already current, skip DB writes and debug the test failure directly.
- Bad: use
migrate resetor manually add columns to unblock a test. - Bad: start the server with an ad hoc
node -r dotenv/configworkaround and leavenpm run devbroken.
6. Tests Required
cd server && npm run prisma:validate.bash scripts/qa/check-local-migration-drift.shwhen local DB drift was the cause.cd server && node --check src/index.jsif server bootstrap changed.- Focused Playwright flow that previously failed.
- Frontend
npm run buildwhen Playwright or client behavior changed.
7. Wrong vs Correct
Wrong
cd server && npx prisma migrate reset
Correct
cd server && npx prisma migrate status
# after explicit approval for the local regression database only
cd server && npx prisma migrate deploy
Scenario: Portal Announcement Acknowledgement
1. Scope / Trigger
- Trigger: extending
announcements_v1from read-only announcements into formal employee acknowledgement. - Applies to
server/prisma/schema.prisma,server/src/routes/announcements.js,client/src/api/announcements.ts, employee/announcements, and admin/system/announcements. - Use this only for lightweight policy acknowledgement; do not treat it as electronic signature, CA signing, contract signing, or full policy CMS.
2. Signatures
- DB:
PortalAnnouncementmay carrycategory,requires_acknowledgement,acknowledgement_statement,acknowledgement_due_at. - DB:
PortalAnnouncementAcknowledgementstores one receipt per(announcement_id, employee_id)with statement/title/summary snapshots andactor_id. - API:
GET /api/announcements?manage=0returns visible announcements and the current employee's acknowledgement status. - API:
GET /api/announcements?manage=1requiressystem.settingsand returns acknowledgement summary plus minimal pending employees. - API:
POST /api/announcements/:id/acknowledgeaccepts{ "confirmed": true }.
3. Contracts
- Required acknowledgement status values:
not_required,pending,acknowledged,overdue. - Employee response must not include other employees' acknowledgement rows or pending lists.
- Admin pending list may include only
id,employeeNo,name, andstatus; do not include phone, email, WeCom userid, account identifiers, or sensitive profile fields. - Acknowledgement is explicit only: opening an announcement or clicking its link must never create a receipt.
- Policy content changes after any acknowledgement require a new announcement version; do not mutate title, summary, category, required flag, or statement in place.
4. Validation & Error Matrix
announcements_v1disabled ->409 VALID_001.- policy acknowledgement without statement ->
400 VALID_001. manage=1withoutsystem.settings->403 PERM_001.- acknowledge invisible/missing announcement ->
404 ANN_404. - acknowledge normal announcement ->
409 VALID_001. - acknowledge without
{ confirmed: true }->400 VALID_001. - edit protected policy fields after acknowledgement exists ->
409 VALID_001.
5. Good/Base/Bad Cases
- Good: admin creates a policy announcement, employee checks the confirmation box, server creates one receipt and one audit log.
- Base: normal announcement remains compatible and returns
not_required. - Bad: frontend displays another employee's receipt status on
/announcements. - Bad: admin updates an acknowledged policy title instead of creating a new version.
6. Tests Required
- Prisma validate after schema/migration changes.
- Route focused tests for required statement, permission, idempotency, normal/invisible announcement rejection, admin summary, and protected edit rejection.
- Frontend typecheck and build.
- Playwright flow for admin create -> employee acknowledge -> admin summary update when UI changes.
7. Wrong vs Correct
Wrong
await prisma.portalAnnouncement.update({
where: { id },
data: { title: "制度 V2" },
});
Correct
const acknowledgementCount = await prisma.portalAnnouncementAcknowledgement.count({
where: { announcement_id: id },
});
if (acknowledgementCount > 0) {
throw new AppError({ code: "VALID_001", message: "参数校验失败", statusCode: 409 });
}