4.6 KiB
Debug Protocol (Repo)
You are debugging an issue in this repo. Do not implement features unless required to fix the bug.
0) Non-negotiables
- Source of truth:
PROJECT_INSTRUCTIONS.md(repo root). If anything conflicts, follow it. - No assumptions: First scan the repo for existing patterns, locations, scripts, helpers, and conventions. Don’t invent missing files/endpoints unless truly necessary—and if needed, add minimally and consistently.
- External DB:
DATABASE_URLpoints to on-prem Postgres (not a container). Dev/Prod share schema via migrations inpackages/db/migrations. - Security: Never log secrets, full invite codes, or receipt bytes. Invite codes in logs/audit: last4 only.
- No cron/worker jobs: Any fix must work without background tasks.
- Server-side RBAC only: Client checks are UX only.
1) Restate the bug precisely
Start by writing a 4–6 line Bug Definition:
- Expected behavior
- Actual behavior
- Where it happens (page / route / service)
- Impact (blocker? regression? edge case?)
If any of these are missing, ask for them explicitly.
2) Collect an evidence bundle before changing code
Before editing anything, request/locate:
A) Runtime signals
- Exact error text + stack trace (server + browser console)
- Network capture: request URL, method, status, response body
- Any
request_idreturned by the API for failing calls
B) Repo + environment
- Current branch/commit
- How app is started (
docker-compose+ which file) - Node version + package manager used
- Relevant env vars (sanitized):
DATABASE_URLhost/port/dbname only (no password)
C) Involved code paths
Identify actual files by searching the repo:
- The page/component triggering the request
- The hook used (
hooks/use-*.ts) - The client wrapper (
lib/client/*) - The API route (
app/api/**/route.ts) - The server service (
lib/server/*.ts)
Do not guess file names. Use repo search.
3) Determine failure class (choose ONE primary)
Pick the most likely bucket and focus there first:
- DB connectivity / docker networking
- Migrations/schema mismatch
- Auth/session cookie flow (HttpOnly cookies, session table, logout)
- RBAC / group membership / active group
- Request validation / parsing (route boundary)
- Client fetch wrapper / hook state
- UI behavior / event handling / mobile UX
- Playwright test failure (timing, selectors, baseURL, auth state)
Write a 3–5 bullet hypothesis list ordered by likelihood.
4) Reproduce locally with the smallest surface area
Prefer reproducing via:
- A single API call (
curl/ minimalfetch) before full UI if possible - Then UI repro
- Then Playwright repro (if it’s a test failure)
If scripts are needed, inspect package.json for actual script names (don’t assume). Common ones may exist (lint, test, db:migrate) but confirm.
5) Add targeted observability (minimal + removable)
If evidence is insufficient, add temporary, minimal logs in server services (not in UI):
- Always include
request_id - Log only safe metadata (
user_id,group_id, route name, timing) - Never log secrets/full invite code/receipt bytes/passwords/tokens
- If touching invite logic: log last4 only
Prefer:
- One log line at service entry (inputs summary)
- One log line at decision points (auth fail / membership fail / db row missing)
- One log line at service exit (success + timing)
Remove or downgrade noisy logs before final PR unless clearly valuable.
6) Fix strategy rules
- Make the smallest change that resolves the bug.
- Respect layering:
- Route: parse + validate shape
- Server service: DB + authz + business rules
- Client wrapper: typed fetch + error normalization
- Hook: UI-facing API layer
- Don’t introduce new dependencies unless absolutely necessary.
- Keep touched files free of TS warnings and lint errors.
7) Verification checklist (must do)
After the fix:
- Re-run the minimal repro (API and/or UI)
- Run relevant tests (unit + Playwright if applicable)
- Add/adjust tests for the bug:
- At least 1 positive + 2 negatives (unauthorized, not-a-member, invalid input)
- Confirm contracts:
- Spendings list never includes receipt bytes
- Sessions are HttpOnly + DB-backed
- Audit logs include
request_idand never store full invite code
8) Next.js route params checklist (required)
For app/api/**/[param]/route.ts:
- Treat
context.paramsas async andawaitit before reading properties. - If you see errors about sync dynamic APIs, update handlers to unwrap params:
Example:
const { id } = await context.params;