124 lines
5.4 KiB
Markdown
124 lines
5.4 KiB
Markdown
# Copilot Instructions — Fiddy (External DB)
|
||
|
||
## Source of truth
|
||
- Always consult PROJECT_INSTRUCTIONS.md at the repo root.
|
||
- If any guidance conflicts, PROJECT_INSTRUCTIONS.md takes precedence.
|
||
- Keep this file focused on architecture/stack; keep checklists and project workflow rules in PROJECT_INSTRUCTIONS.md.
|
||
- When asked to fix bugs, follow DEBUGGING_INSTRUCTIONS.md at the repo root.
|
||
|
||
## Stack
|
||
- Monorepo (npm workspaces)
|
||
- Next.js (App Router) + TypeScript + Tailwind
|
||
- External Postgres (on-prem server) via node-postgres (pg). No ORM.
|
||
- Docker Compose dev/prod
|
||
- Gitea + act-runner CI/CD
|
||
|
||
## Environment
|
||
- Dev and Prod must use the same schema/migrations (`packages/db/migrations`).
|
||
- `DATABASE_URL` points to the external DB server (NOT a container).
|
||
|
||
## Auth
|
||
- Custom email/password auth.
|
||
- Use HttpOnly session cookies backed by DB table `sessions`.
|
||
- NEVER trust client-side RBAC checks.
|
||
|
||
## Receipts
|
||
- Store receipt images in Postgres `bytea` table `receipts`.
|
||
- Entries list endpoints must not return image bytes.
|
||
- Image bytes only fetched by separate endpoint when inspecting a single item.
|
||
|
||
## UI
|
||
- Dark mode, minimal, mobile-first.
|
||
- Dodger Blue accent (#1E90FF).
|
||
- Top navbar: left nav dropdown, middle group selector, right user menu.
|
||
|
||
## Code Rules
|
||
- Small files, minimal comments.
|
||
- Prefer single-line `if` without braces when only one line follows.
|
||
- Heavy logic lives in components/hooks/services, not page files.
|
||
- Prefer API calls via exported hooks/services for reusability and cleanliness (avoid raw fetch in components when possible).
|
||
- Add/update unit tests with changes (TDD).
|
||
- Heavy focus on code readability and maintainability; prioritize clean code over clever code.
|
||
- ie. Separating different concerns into different files, and adding helper functions to avoid nested logic and improve readability, is preferred over clever one-liners or consolidating logic into fewer files.
|
||
- ie. Separate groups of related codes by adding 3 line breaks between them
|
||
|
||
## Data Model
|
||
- Users (system_role USER|SYS_ADMIN)
|
||
- Groups + membership (group_role MEMBER|GROUP_ADMIN)
|
||
- Entries (group-scoped) + optional receipt_id
|
||
- User settings (jsonb)
|
||
- Reports for system admins
|
||
|
||
## Architecture Contract (Backend ↔ Client ↔ Hooks ↔ UI)
|
||
|
||
### No-Assumptions Rule (Required)
|
||
- Before making structural changes, first scan the repo and identify:
|
||
- the web app root (where `app/`, `components/`, `hooks/`, `lib/` live)
|
||
- existing API routes and helpers
|
||
- existing patterns already in use
|
||
- Do not invent files, endpoints, or conventions. If something is missing, add it minimally and consistently.
|
||
|
||
### Layering (Hard Boundaries)
|
||
For every domain (auth, groups, entries, receipts, etc.), keep a consistent 4-layer flow:
|
||
|
||
1) **API Route Handlers** (`app/api/.../route.ts`)
|
||
- Thin: parse input, call a server service, return JSON.
|
||
- No direct DB queries inside route files unless there is no existing server service.
|
||
- Must enforce auth & membership checks on server.
|
||
|
||
2) **Server Services (DB + authorization)** (`lib/server/*`)
|
||
- Own all DB access and authorization helpers (sessions, requireGroupMember, etc.).
|
||
- 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/session.ts`.
|
||
|
||
3) **Client API Wrappers** (`lib/client/*`)
|
||
- Typed fetch helpers only (no React state).
|
||
- Centralize `fetchJson()` / error normalization.
|
||
- Always send credentials (cookies) and never trust client-side RBAC.
|
||
|
||
4) **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’s a strong reason.
|
||
|
||
### Domain Blueprint (Consistency Rule)
|
||
For any new feature/domain, prefer:
|
||
- `app/api/<domain>/...`
|
||
- `lib/server/<domain>.ts`
|
||
- `lib/client/<domain>.ts`
|
||
- `hooks/use-<domain>.ts`
|
||
- `components/<domain>/*`
|
||
- `__tests__/<domain>.test.ts`
|
||
|
||
### API Conventions
|
||
- Prefer consistent JSON response shape for errors:
|
||
- `{ error: { code: string, message: string } }`
|
||
- Validate inputs at the route boundary (basic shape/type), and validate authorization in server services.
|
||
- When adding endpoints, mirror existing REST style used in the project.
|
||
|
||
### Non-Regression Contracts (Do Not Break)
|
||
- Entries list endpoints must **never** include receipt image bytes; image bytes are fetched via a separate endpoint only.
|
||
- Auth is DB-backed HttpOnly sessions; all auth checks are server-side.
|
||
- Groups require server-side membership checks; active group persists per user.
|
||
- Group invite codes:
|
||
- shown once immediately after group creation
|
||
- modal renders outside navbar/header so it overlays the viewport correctly
|
||
- avoid re-exposing invite code elsewhere without explicit “group settings” work
|
||
|
||
### UI Structure
|
||
- Page files stay thin; heavy logic stays in hooks/services/components.
|
||
- Dark mode, minimal, mobile-first.
|
||
- Dodger Blue accent (#1E90FF).
|
||
- Navbar: left nav dropdown, middle group selector, right user menu.
|
||
|
||
### Environment
|
||
- Dev and Prod must use the same schema/migrations (`packages/db/migrations`).
|
||
- `DATABASE_URL` points to external Postgres (NOT a container).
|
||
- `DATABASE_URL` format must be a full connection string; URL-encode special chars in passwords.
|
||
|
||
### Tests (Required)
|
||
- Add/update tests for API behavior changes:
|
||
- auth
|
||
- groups
|
||
- entries (group scoping)
|
||
- Tests must include negative cases: unauthorized, not-a-member, invalid inputs.
|