costco-grocery-list/PROJECT_INSTRUCTIONS.md
Nico 77ae5be445
All checks were successful
Build & Deploy Costco Grocery List / build (push) Successful in 1m10s
Build & Deploy Costco Grocery List / verify-images (push) Successful in 3s
Build & Deploy Costco Grocery List / deploy (push) Successful in 11s
Build & Deploy Costco Grocery List / notify (push) Successful in 1s
refactor
2026-02-22 01:27:03 -08:00

203 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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.

# 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
1) **PROJECT_INSTRUCTIONS.md** (this file) is the source of truth.
2) **DEBUGGING_INSTRUCTIONS.md** (repo root) is required for bugfix work.
3) 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_URL` points 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 `bytea` table `receipts`.
- **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_id`** and 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:
1) **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.
2) **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`.
3) **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.
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 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.params` as **async** and `await` it before reading properties.
- Example: `const { id } = await context.params;`
### 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_OWNER` role 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_at` and `revoked_at`, refreshes `expires_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)
1) DB migrate command + schema
2) Register/Login/Logout (custom sessions)
3) Protected dashboard page
4) Group create/join + group switcher (approval-based joins + optional join disable)
5) Entries CRUD (no receipt bytes in list)
6) Receipt upload/download endpoints
7) Settings + Reports
---
## 8) Definition of done
- Works via `docker-compose.dev.yml` with 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.
- For every frontend action that manipulates database state, show a toast/bubble notification with basic outcome details (action + target + success/failure).
- Progress-type notifications must reuse the existing upload toaster pattern (`UploadQueueContext` + `UploadToaster`) for consistency.
- 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.
---
## 12) Commit Discipline (required)
- Commit in small, logical slices (no broad mixed-purpose commits).
- Each commit must:
- follow Conventional Commits style (`feat:`, `fix:`, `docs:`, `refactor:`, `test:`, `chore:`)
- include only related files for that slice
- exclude secrets, credentials, and generated noise
- Run verification before commit when applicable (lint/tests/build or targeted checks for touched areas).
- Prefer frequent checkpoint commits during agentic work rather than one large end-state commit.
- If a rule or contract changes, commit docs first (or in the same atomic slice as enforcing code).