7.4 KiB
7.4 KiB
Project Instructions — Fiddy (External DB)
1) Core expectation
This project connects to an external Postgres instance (on-prem server). Dev and Prod must share the same schema through migrations.
2) Authority & doc order
- PROJECT_INSTRUCTIONS.md (this file) is the source of truth.
- DEBUGGING_INSTRUCTIONS.md (repo root) is required for bugfix work.
- Other instruction files (e.g.
.github/copilot-instructions.md) must not conflict with this doc.
If anything conflicts, follow this doc.
3) Non-negotiables (hard rules)
External DB + migrations
DATABASE_URLpoints to on-prem Postgres (NOT a container).- Dev/Prod share schema via migrations in:
packages/db/migrations. - Active migration runbook:
docs/DB_MIGRATION_WORKFLOW.md(active set + status commands).
No background jobs
- No cron/worker jobs. Any fix must work without background tasks.
Security / logging
- Never log secrets (passwords, tokens, session cookies).
- Never log receipt bytes.
- Never log full invite codes — logs/audit store last4 only.
Server-side authorization only
- Server-side RBAC only. Client checks are UX only and must not be trusted.
4) Non-regression contracts (do not break)
Auth
- Custom email/password auth.
- Sessions are DB-backed and stored in table
sessions. - Session cookies are HttpOnly.
Receipts
- Receipt images are stored in Postgres
byteatablereceipts. - Entries list endpoints must never return receipt image bytes.
- Receipt bytes are fetched only via a separate endpoint when inspecting a single item.
Request IDs + audit
- API must generate a
request_idand return it in responses. - Audit logs must include
request_id. - Audit logs must never store full invite codes (store last4 only).
5) Architecture contract (Backend ↔ Client ↔ Hooks ↔ UI)
No-assumptions rule (required)
Before making structural changes, first scan the repo and identify:
- where
app/,components/,features/,hooks/,lib/live - existing API routes and helpers
- patterns already in use Do not invent files/endpoints/conventions. If something is missing, add it minimally and consistently.
Single mechanism rule (required)
For any cross-component state propagation concern, keep one canonical mechanism only:
- Context OR custom events OR cache invalidation Do not keep old and new mechanisms in parallel. Remove superseded utilities/imports/files in the same PR.
Layering (hard boundaries)
For every domain (auth, groups, entries, receipts, etc.) follow this flow:
- API Route Handlers —
app/api/.../route.ts
- Thin: parse/validate input, call a server service, return JSON.
- No direct DB queries in route files unless there is no existing server service.
- Server Services (DB + authorization) —
lib/server/*
- Own all DB access and authorization helpers.
- Server-only modules must include:
import "server-only"; - Prefer small domain modules:
lib/server/auth.ts,lib/server/groups.ts,lib/server/entries.ts,lib/server/receipts.ts,lib/server/session.ts.
- Client API Wrappers —
lib/client/*
- Typed fetch helpers only (no React state).
- Centralize fetch + error normalization.
- Always send credentials (cookies) and never trust client-side RBAC.
- Hooks (UI-facing API layer) —
hooks/use-*.ts
- Hooks are the primary interface for components/pages to call APIs.
- Components should not call
fetch()directly unless there is a strong reason.
API conventions
- Prefer consistent JSON error shape:
{ error: { code: string, message: string }, request_id?: string }
- Validate inputs at the route boundary (shape/type), authorize in server services.
- Mirror existing REST style used in the project.
Next.js route params checklist (required)
For app/api/**/[param]/route.ts:
- Treat
context.paramsas async andawaitit before reading properties.- Example:
const { id } = await context.params;
- Example:
Frontend structure preference
- Prefer domain-first structure:
features/<domain>/...+shared/.... - Use
components/*only for compatibility shims during migrations (remove them after imports are migrated).
Maintainability thresholds (refactor triggers)
- Component files > 400 lines should be split into container/presentational parts.
- Hook files > 150 lines should extract helper functions/services.
- Functions with more than 3 nested branches should be extracted.
6) Decisions / constraints (Group Settings)
- Add
GROUP_OWNERrole to group roles; migrate existing groups so the first admin becomes owner. - Join policy default is
NOT_ACCEPTING. Policies:NOT_ACCEPTING,AUTO_ACCEPT,APPROVAL_REQUIRED. - Both owner and admins can approve join requests and manage invite links.
- Invite links:
- TTL limited to 1–7 days.
- Settings are immutable after creation (policy, single-use, etc.).
- Single-use does not override approval-required.
- Expired links are retained and can be revived.
- Single-use links are deleted after successful use.
- Revive resets
used_atandrevoked_at, refreshesexpires_at, and creates a new audit event.
- No cron/worker jobs for now (auto ownership transfer and invite rotation are paused).
- Group role icons must be consistent: 👑 owner, 🛡️ admin, 👤 member.
7) Do first (vertical slice)
- DB migrate command + schema
- Register/Login/Logout (custom sessions)
- Protected dashboard page
- Group create/join + group switcher (approval-based joins + optional join disable)
- Entries CRUD (no receipt bytes in list)
- Receipt upload/download endpoints
- Settings + Reports
8) Definition of done
- Works via
docker-compose.dev.ymlwith external DB - Migrations applied via
npm run db:migrate - Tests + lint pass
- RBAC enforced server-side
- No large files
- No TypeScript warnings or lint errors in touched files
- No new cron/worker dependencies unless explicitly approved
- No orphaned utilities/hooks/contexts after refactors
- No duplicate mechanisms for the same state flow
- Text encoding remains clean in user-facing strings/docs
9) Desktop + mobile UX checklist (required)
- Touch: long-press affordance for item-level actions when no visible button.
- Mouse: hover affordance on interactive rows/cards.
- Tap targets remain >= 40px on mobile.
- Modal overlays must close on outside click/tap.
- Use bubble notifications for main actions (create/update/delete/join).
- Add Playwright UI tests for new UI features and critical flows.
10) Tests (required)
- Add/update tests for API behavior changes (auth, groups, entries, receipts).
- Include negative cases where applicable:
- unauthorized
- not-a-member
- invalid input
11) Agent Response Legend (required)
Use emoji/icons in agent progress and final responses so status is obvious at a glance.
Legend:
🔄in progress✅completed🧪test/lint/verification result📄documentation update🗄️database or migration change🚀deploy/release step⚠️risk, blocker, or manual operator action needed❌failed command or unsuccessful attemptℹ️informational context🧭recommendation or next-step option
Usage rules:
- Include at least one status icon in each substantive agent response.
- Use one icon per bullet/line; avoid icon spam.
- Keep icon meaning consistent with this legend.