fiddy/.github/copilot-instructions.md
2026-02-11 23:45:15 -08:00

124 lines
5.4 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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 theres 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.