diff --git a/Admin-and-Operations-Guide.md b/Admin-and-Operations-Guide.md new file mode 100644 index 0000000..43f7860 --- /dev/null +++ b/Admin-and-Operations-Guide.md @@ -0,0 +1,123 @@ +# Admin and Operations Guide + +This page is for system admins and operators. + +## System Admin Panel + +The `/admin` page is available to users with the `system_admin` role. + +The admin panel includes: + +- User management. +- Global store management. + +Household owners/admins manage household-scoped members, invite links, stores, locations, zones, and catalog items from **Manage**. System admins manage cross-household/global records from **Admin**. + +## Runtime Layout + +Local and production runtime pieces: + +- Backend API: Express, default port `5000`. +- Frontend: Vite/React, Docker-mapped dev port `3010`, direct Vite default `5173`. +- Database: external Postgres, not a container. +- Dev compose: `docker-compose.dev.yml`. +- Production compose: `docker-compose.yml`. + +## Environment Variables + +Do not commit real `.env`, `backend.env`, or `frontend.env` values. + +Important backend variables: + +| Variable | Purpose | +| --- | --- | +| `DATABASE_URL` | Preferred Postgres connection string for backend and root migration scripts. | +| `DB_USER`, `DB_PASS`, `DB_HOST`, `DB_PORT`, `DB_NAME` | Backend fallback database settings when `DATABASE_URL` is absent. | +| `JWT_SECRET` | Required for token-compatible auth paths. | +| `ALLOWED_ORIGINS` | Comma-separated allowed frontend origins for CORS. | +| `SESSION_COOKIE_NAME` | Optional session cookie name. | +| `SESSION_TTL_DAYS` | Optional session lifetime in days. | + +Important frontend variables: + +| Variable | Purpose | +| --- | --- | +| `VITE_API_URL` | Frontend API base URL. Defaults to the local backend URL. | +| `VITE_ALLOWED_HOSTS` | Optional Vite host allowlist. | + +## Local Operations + +Install: + +```bash +npm ci +npm --prefix backend ci +npm --prefix frontend ci +``` + +Run with Docker: + +```bash +docker compose -f docker-compose.dev.yml up +``` + +Run in separate terminals: + +```bash +npm run dev:backend +npm run dev:frontend +``` + +Health checks: + +```bash +curl http://127.0.0.1:5000/ +curl http://127.0.0.1:5000/config +``` + +## Deployment + +Gitea Actions build and deploy this app. + +- Pushes to `main` build and tag images as `latest`. +- Pushes to `main-new` build and tag images as `main-new`. +- Workflows install dependencies, run reliability checks, build backend/frontend images, push images to the configured registry, then deploy through SSH. + +Deployment secrets are stored in Gitea Actions secrets. Do not print or paste them into logs. + +## Reliability Gate + +The workflow currently runs: + +```bash +npm run audit +npm run lint +npm run typecheck +npm test +npm run db:migrate:stale:check +npm run build:backend +npm run build:frontend +``` + +Use the same commands locally before pushing risky changes. + +## Operational Safety + +- Do not run migrations against production or shared databases unless that is the explicit operator task. +- Do not add a Postgres container; the app expects an external database. +- Do not log secrets, tokens, session cookies, DB URLs, receipt bytes, or full invite codes. +- Invite code logs/audit entries may include last 4 characters only. +- Backend/API changes in Docker dev usually require rebuilding/restarting the backend service. + +Useful dev backend restart: + +```bash +docker compose -f docker-compose.dev.yml up -d --build backend +``` + +Useful env/CORS reload: + +```bash +docker compose -f docker-compose.dev.yml up -d --force-recreate --no-deps backend +``` + diff --git a/Architecture-and-API.md b/Architecture-and-API.md new file mode 100644 index 0000000..34057bb --- /dev/null +++ b/Architecture-and-API.md @@ -0,0 +1,182 @@ +# Architecture and API + +This page summarizes the current app architecture and active API shape. + +## High-Level Flow + +```text +React/Vite SPA + -> frontend/src/api shared Axios client + -> Express route + -> controller + -> middleware/services/models + -> external Postgres +``` + +The active grocery flow is: + +```text +User -> Household -> Store Location -> Zones -> List Items / Available Items +``` + +## Frontend + +Routes: + +| Route | Page | +| --- | --- | +| `/login` | Login | +| `/register` | Register | +| `/invite/:token` | Invite link summary and acceptance | +| `/` | Grocery list | +| `/manage` | Household and store management | +| `/settings` | User settings | +| `/admin` | System admin panel | + +Core providers: + +- `AuthProvider`: login state. +- `HouseholdProvider`: user households and active household. +- `StoreProvider`: household stores, active store/location, and zones. +- `UploadQueueProvider`: queued image uploads and retry/discard behavior. +- `ActionToastProvider`: user-visible action outcomes. +- `SettingsProvider`: per-user local settings. + +## Backend + +Route families: + +| Prefix | Purpose | +| --- | --- | +| `/auth` | Register, login, logout. | +| `/users` | Current user profile, password change, username availability. | +| `/admin` | System admin user operations. | +| `/config` | Public frontend config such as image limits. | +| `/households` | Households, members, stores, locations, zones, lists, and available items. | +| `/stores` | Global store records and legacy household store helpers. | +| `/api/groups` | Invite links, join requests, and join policy. | +| `/api/invite-links` | Public invite link summary and authenticated acceptance. | +| `/list` | Legacy/global list routes; prefer scoped household/location routes for new work. | + +## Active Scoped Endpoints + +Households: + +```text +GET /households +POST /households +GET /households/:householdId +PATCH /households/:householdId +DELETE /households/:householdId +GET /households/:householdId/members +PATCH /households/:householdId/members/:userId/role +DELETE /households/:householdId/members/:userId +``` + +Stores, locations, and zones: + +```text +GET /households/:householdId/stores +POST /households/:householdId/stores +PATCH /households/:householdId/stores/:householdStoreId +DELETE /households/:householdId/stores/:householdStoreId +POST /households/:householdId/stores/:householdStoreId/locations +PATCH /households/:householdId/locations/:locationId +DELETE /households/:householdId/locations/:locationId +PATCH /households/:householdId/locations/:locationId/default +GET /households/:householdId/locations/:locationId/zones +POST /households/:householdId/locations/:locationId/zones +PATCH /households/:householdId/locations/:locationId/zones/:zoneId +DELETE /households/:householdId/locations/:locationId/zones/:zoneId +``` + +Location-scoped list: + +```text +GET /households/:householdId/locations/:locationId/list +GET /households/:householdId/locations/:locationId/list/item +POST /households/:householdId/locations/:locationId/list/add +PUT /households/:householdId/locations/:locationId/list/item +PATCH /households/:householdId/locations/:locationId/list/item +DELETE /households/:householdId/locations/:locationId/list/item +GET /households/:householdId/locations/:locationId/list/suggestions +GET /households/:householdId/locations/:locationId/list/recent +GET /households/:householdId/locations/:locationId/list/classification +POST /households/:householdId/locations/:locationId/list/classification +POST /households/:householdId/locations/:locationId/list/update-image +``` + +Available items: + +```text +GET /households/:householdId/locations/:locationId/available-items +POST /households/:householdId/locations/:locationId/available-items +PATCH /households/:householdId/locations/:locationId/available-items/:itemId +DELETE /households/:householdId/locations/:locationId/available-items/:itemId +POST /households/:householdId/locations/:locationId/available-items/import-current +``` + +Invite links: + +```text +GET /api/groups/invites +POST /api/groups/invites +GET /api/groups/join-requests +POST /api/groups/join-requests/decision +POST /api/groups/invites/revoke +POST /api/groups/invites/revive +POST /api/groups/invites/delete +GET /api/groups/join-policy +POST /api/groups/join-policy +GET /api/invite-links/:token +POST /api/invite-links/:token +``` + +Group invite management uses a `X-Group-Id` header from the frontend wrapper when the user manages multiple groups. + +## Auth And Authorization + +Authentication: + +- Login validates a lowercase username and password. +- Login creates a DB session and sets an HttpOnly cookie. +- Login also returns a JWT-compatible token used by existing client code. +- Protected routes accept valid session or token credentials. + +Authorization: + +- System admin routes require the `system_admin` role. +- Household routes require membership in the target household. +- Household admin routes require owner/admin membership. +- Location/list routes also verify access to the selected store location. + +## Request IDs And Errors + +Every API response includes a request ID and sends it as the `X-Request-Id` response header. + +Error responses are normalized to: + +```json +{ + "error": { + "code": "bad_request", + "message": "Readable message" + }, + "request_id": "generated-request-id" +} +``` + +Frontend API wrappers unwrap `{ data, request_id }` success payloads when needed. + +## Image Handling + +Image uploads use Multer and Sharp. + +Configuration is exposed by `/config` and includes: + +- Maximum image file size. +- Maximum image dimension. +- Image quality. + +Frontend uploads use `UploadQueueContext`, which persists queued jobs and lets users retry failed uploads. + diff --git a/Database-and-Migrations.md b/Database-and-Migrations.md new file mode 100644 index 0000000..b2a15a7 --- /dev/null +++ b/Database-and-Migrations.md @@ -0,0 +1,103 @@ +# Database and Migrations + +Fiddy uses an external on-prem Postgres database. Do not add or assume a database container. + +## Canonical Migration Directory + +Canonical migrations live in: + +```text +packages/db/migrations +``` + +Legacy SQL under `backend/migrations` is reference-only. Do not add new canonical migrations there. + +## Required Environment + +Migration commands need: + +- `DATABASE_URL` set in the shell. +- `psql` installed and available on `PATH`. +- The command run from the repo root. + +Do not print or commit the value of `DATABASE_URL`. + +## Commands + +Show status: + +```bash +npm run db:migrate:status +``` + +Create a migration: + +```bash +npm run db:migrate:new -- +``` + +Apply pending migrations: + +```bash +npm run db:migrate +``` + +Verify clean state: + +```bash +npm run db:migrate:verify +``` + +Check stale legacy SQL: + +```bash +npm run db:migrate:stale:check +``` + +Update stale tracking: + +```bash +npm run db:migrate:stale +``` + +## Operator Flow + +1. Confirm which database `DATABASE_URL` targets. +2. Run `npm run db:migrate:status`. +3. Create a new migration file if the code change needs schema changes. +4. Review the SQL. +5. Apply pending migrations only when the operator intends to change that database. +6. Run `npm run db:migrate:verify`. +7. Run the relevant app tests/builds. + +## Tracking Table + +Applied migrations are recorded in: + +```text +schema_migrations(filename text unique, applied_at timestamptz) +``` + +Migrations apply in lexicographic filename order. + +## Current Data Areas + +The current app stores data for: + +- Users and DB-backed sessions. +- Households and household members. +- Invite links, join requests, join policy, and audit events. +- Stores, household stores, locations, and zones. +- Location-scoped list items. +- Available/catalog items. +- Item images and metadata. +- Item classification and notes. + +## Safety Rules + +- Never run migrations against production/shared data unless explicitly asked. +- Never edit applied migration history manually unless performing a planned database repair. +- Do not log secrets, DB URLs, tokens, cookies, receipt bytes, or full invite codes. +- Invite-code logging may include last 4 characters only. +- Add tests for API behavior that depends on a new schema contract. + diff --git a/Home.md b/Home.md new file mode 100644 index 0000000..34e1822 --- /dev/null +++ b/Home.md @@ -0,0 +1,65 @@ +# Fiddy Wiki + +Fiddy is a collaborative grocery list app for households. It lets people keep a shared shopping list, organize items by store location and zone, add product images, track recently bought items, and manage who can access each household. + +This wiki is written for two audiences: + +- Users who shop with the app and manage households. +- Programmers and operators who run, maintain, or extend the app. + +## Start Here + +| Audience | Page | Use it for | +| --- | --- | --- | +| Users | [User Guide](User-Guide) | Sign in, create or join a household, use the grocery list, upload images, and adjust settings. | +| Household owners/admins | [Households, Roles, and Invites](Households-Roles-and-Invites) | Manage members, invite links, join policies, and household roles. | +| Store/list managers | [Stores, Zones, and Catalog Items](Stores-Zones-and-Catalog-Items) | Add store locations, choose defaults, organize zones, and maintain reusable item suggestions. | +| Operators | [Admin and Operations Guide](Admin-and-Operations-Guide) | Manage system users, deployment, environment variables, and health checks. | +| Programmers | [Programmer Guide](Programmer-Guide) | Set up the repo, run the app locally, follow coding conventions, and verify changes. | +| Programmers | [Architecture and API](Architecture-and-API) | Understand the Express API, React client, auth, request IDs, and active route families. | +| Programmers/operators | [Database and Migrations](Database-and-Migrations) | Work with the external Postgres database and canonical migration workflow. | +| Everyone | [Troubleshooting](Troubleshooting) | Fix common login, household, store, image upload, CORS, and deployment issues. | + +## What The App Does + +Fiddy supports: + +- Email/password accounts with DB-backed sessions and an HttpOnly session cookie. +- Multiple households per user. +- Household roles: owner, admin, and member. +- Invite links with join policies for closed, automatic, or approval-based joining. +- Store locations per household, including default locations. +- Ordered store zones so the list can match the shopping path. +- Location-scoped grocery lists with quantities, notes, classification, and images. +- Recently bought items for the last 24 hours. +- Search and suggestions from the household/location catalog. +- User settings for theme, list display, recent item count, confirmation behavior, haptics, and debug mode. +- System administration for users and global store records. +- Gitea Actions based build/deploy workflows. + +## Current Stack + +- Frontend: React 19 and Vite in `frontend/`. +- Backend: Express 5 CommonJS API in `backend/`. +- Database: external on-prem Postgres. +- Package manager: npm. +- Migrations: canonical SQL files in `packages/db/migrations`. +- CI/CD: Gitea Actions in `.gitea/workflows`. + +## Important Concepts + +The active app flow is household and location scoped: + +1. A user signs in. +2. The user creates or joins a household. +3. The user selects a household store location. +4. The grocery list, item suggestions, zones, images, and recently bought items are scoped to that household and location. + +Programmers should prefer the current scoped API routes under: + +```text +/households/:householdId/locations/:locationId/... +``` + +Some legacy global list routes still exist for compatibility, but new work should follow the household/location model unless the task explicitly says otherwise. + diff --git a/Households-Roles-and-Invites.md b/Households-Roles-and-Invites.md new file mode 100644 index 0000000..9428e89 --- /dev/null +++ b/Households-Roles-and-Invites.md @@ -0,0 +1,82 @@ +# Households, Roles, and Invites + +Households are the main collaboration boundary in Fiddy. Lists, stores, locations, zones, catalog items, and membership are scoped to a household. + +## Household Roles + +| Role | Can shop | Manage household | Manage stores/zones | Manage invites | Manage member roles | +| --- | --- | --- | --- | --- | --- | +| Owner | Yes | Yes | Yes | Yes | Yes, including ownership transfer | +| Admin | Yes | Yes | Yes | Yes | Yes, except protected owner actions | +| Member | Yes | No | Limited/no admin actions | No | No | + +Rules enforced by the backend: + +- Only household members can access a household. +- Owner/admin actions require a household owner or admin role. +- A member cannot promote themselves. +- Owner role changes are protected. +- Server-side authorization is required; client UI checks are only convenience. + +## Create A Household + +1. Sign in. +2. Use the household create flow. +3. Enter a household name. +4. The creator becomes the household owner. + +## Rename Or Delete A Household + +Open **Manage > Household**. + +Owners/admins can rename a household. Owners/admins can also delete a household, which removes that household's lists and related data. Treat deletion as permanent. + +## Invite Links + +Owners/admins can create invite links from **Manage > Household > Invite Links**. + +Invite link behavior: + +- Links have a time-to-live from 1 to 7 days. +- Link settings are immutable after creation. +- Expired links are retained and can be revived. +- Reviving a link resets its expiration and creates a new audit event. +- Single-use links are deleted after successful use. +- Single-use does not bypass approval-required joining. +- Logs and audit records must never expose full invite codes; use last 4 characters only. + +When copying or sharing invite links, send them only to people who should join the household. + +## Join Policy + +Owners/admins choose how invite link joins work: + +| Policy | Meaning | +| --- | --- | +| Not accepting | New joins are closed. Existing members continue to use the household. | +| Auto accept | A valid invite link adds the user automatically. | +| Approval required | A valid invite link creates a pending join request that an owner/admin must approve. | + +## Join Requests + +When approval is required: + +1. A user opens an invite link. +2. The app creates a pending join request. +3. Owners/admins review pending requests from the household management screen. +4. Owners/admins approve or deny each request. + +Approved users become household members. + +## Member Management + +Owners/admins can: + +- View members. +- Promote members to admin. +- Demote admins to member. +- Transfer ownership where allowed. +- Remove members. + +Members can leave a household. If a user belongs to multiple households, they can switch to another household after leaving. + diff --git a/Programmer-Guide.md b/Programmer-Guide.md new file mode 100644 index 0000000..12ee411 --- /dev/null +++ b/Programmer-Guide.md @@ -0,0 +1,132 @@ +# Programmer Guide + +This page is for people changing the code. + +## Stack + +- Backend: Express 5, CommonJS, Node.js. +- Frontend: React 19, Vite, partial TypeScript. +- Database: external Postgres through `pg`. +- Tests: Jest/Supertest for backend, Playwright for e2e. +- Package manager: npm. + +Use Node.js 20.19+ or 22.12+ for frontend/Vite commands. + +## Repository Map + +Key paths: + +| Path | Purpose | +| --- | --- | +| `backend/app.js` | Express middleware, CORS, route mounting, and error handler. | +| `backend/routes` | Route registration. Keep these thin. | +| `backend/controllers` | Request parsing and response handling. | +| `backend/models` | Database query modules. | +| `backend/services` | Domain service logic. | +| `backend/middleware` | Auth, RBAC, household access, request IDs, rate limits, image processing. | +| `frontend/src/api` | Axios API wrappers. Use these instead of direct component fetches. | +| `frontend/src/context` | Auth, household, store, settings, toast, and upload queue state. | +| `frontend/src/pages` | Route-level screens. | +| `frontend/src/components` | Shared and feature UI components. | +| `packages/db/migrations` | Canonical SQL migrations. | +| `.gitea/workflows` | Gitea Actions workflows. | + +## Setup + +```bash +npm ci +npm --prefix backend ci +npm --prefix frontend ci +``` + +Copy env examples as needed, but never commit real values: + +```bash +backend/.env.example -> backend/.env +frontend/.env.example -> frontend/.env +``` + +Root migration scripts read `DATABASE_URL` from the shell environment. + +## Run Locally + +Docker dev stack: + +```bash +docker compose -f docker-compose.dev.yml up +``` + +Separate terminals: + +```bash +npm run dev:backend +npm run dev:frontend +``` + +Default endpoints: + +- Backend: `http://localhost:5000` +- Frontend through Docker compose: `http://localhost:3010` +- Frontend direct Vite: `http://localhost:5173` + +## Coding Conventions + +- Preserve the current Express/Vite stack. +- Keep route files thin. +- Put DB-heavy logic in models/services. +- Enforce RBAC and household access server-side. +- Keep frontend network calls in `frontend/src/api`. +- Use the shared Axios client so credentials are sent consistently. +- Use context/hooks for UI state. +- Frontend DB-mutating actions should show toast or bubble outcome notifications. +- Progress notifications should reuse `UploadQueueContext` and `UploadToaster`. +- Do not introduce cron, workers, polling daemons, or background job frameworks. +- Do not add production dependencies unless the task clearly requires one and there is no practical existing option. + +## Auth Notes + +The current login flow returns a token for compatibility and also creates a DB-backed session. The backend sets an HttpOnly session cookie. The Axios client sends credentials and also attaches the stored token when present. + +When changing auth: + +- Keep sessions DB-backed. +- Keep session cookies HttpOnly. +- Do not log tokens or cookies. +- Preserve redirect behavior for expired sessions. + +## Verification + +Choose the narrowest useful checks first, then broaden when risk warrants it. + +Common commands: + +```bash +npm test +npm run lint +npm run typecheck +npm run audit +npm run build:backend +npm run build:frontend +npm run build +npm run test:e2e +``` + +Migration checks: + +```bash +npm run db:migrate:status +npm run db:migrate:verify +npm run db:migrate:stale:check +``` + +Do not run `npm run db:migrate` unless an operator explicitly intends to apply migrations to the selected external database. + +## Tests To Add + +Add or update tests when behavior changes: + +- API behavior: Jest/Supertest in `backend/tests`. +- Authz, membership, invalid input, and not-a-member cases: include negative coverage. +- UI behavior: focused Playwright tests in `frontend/tests`. +- Pure docs changes: validate Markdown/content where practical. + diff --git a/Stores-Zones-and-Catalog-Items.md b/Stores-Zones-and-Catalog-Items.md new file mode 100644 index 0000000..fa8afd9 --- /dev/null +++ b/Stores-Zones-and-Catalog-Items.md @@ -0,0 +1,75 @@ +# Stores, Zones, and Catalog Items + +Store management controls how grocery lists are organized for a household. + +## Store Model + +Fiddy separates: + +- Global store records: system-level store templates. +- Household-owned stores: stores configured for a specific household. +- Locations: concrete shopping locations under a household store. +- Zones: ordered areas inside a location. +- Available items: location-specific catalog items used for suggestions and defaults. + +The active shopping list is scoped to a household and one location. + +## Add A Household Store And Location + +Open **Manage > Stores**. + +Owners/admins can: + +1. Add a household store. +2. Add one or more locations for that store. +3. Rename stores or locations. +4. Set the default shopping location. +5. Remove stores or locations when they are no longer needed. + +The main list uses the active/default location when showing list items and suggestions. + +## Manage Zones + +Zones represent store areas such as produce, dairy, freezer, household, or checkout. + +Owners/admins can: + +- Add zones. +- Rename zones. +- Set zone order. +- Delete zones. + +Users see list items grouped by the active location's zones. Zone order should match the route people normally walk through the store. + +## Manage Available Items + +Available items are reusable household/location catalog entries. They power suggestions and default details when users add groceries. + +From **Manage > Stores > Manage Items**, owners/admins can: + +- Search the catalog. +- Add catalog items. +- Edit item names, defaults, notes, classification, and images. +- Delete catalog items. +- Import current list items into the catalog. + +Members can use catalog-backed suggestions while adding items. Admin-only catalog deletion is enforced by the backend. + +## Good Catalog Hygiene + +Use stable, simple item names: + +- Prefer `milk` over `need milk`. +- Prefer `eggs` over `12 eggs` because quantity is tracked separately. +- Use notes for brand, size, or special instructions. +- Keep zones broad enough to be useful while shopping. + +## When A Store Is Missing + +If the list says no stores are found: + +1. Confirm the correct household is selected. +2. Ask an owner/admin to open **Manage > Stores**. +3. Add a store and at least one location. +4. Set the location as default if it should open automatically. + diff --git a/Troubleshooting.md b/Troubleshooting.md new file mode 100644 index 0000000..5343b18 --- /dev/null +++ b/Troubleshooting.md @@ -0,0 +1,148 @@ +# Troubleshooting + +Use this page for common user, admin, and developer problems. + +## I Cannot Log In + +Check: + +- Username is lowercase or can be lowercased by the app. +- Password is correct. +- Backend is running. +- `JWT_SECRET` is configured. +- The browser can reach the backend API URL. +- Cookies are not blocked for the app origin. + +For developers, inspect the response status and `request_id`. Do not log session cookies or tokens. + +## I Am Logged Out Unexpectedly + +Possible causes: + +- Session expired. +- Session row was deleted. +- Backend `SESSION_COOKIE_NAME` changed. +- Browser cookie storage was cleared. +- Frontend and backend origins changed and cookies no longer match CORS/cookie rules. + +Log in again after confirming the backend is healthy. + +## I Have No Household + +Create a household or open an invite link. If invite links fail: + +- Confirm the link has not expired. +- Confirm the household join policy accepts new joins. +- If approval is required, wait for an owner/admin to approve the request. + +## I See No Stores + +This means the active household has no usable store location. + +1. Confirm the active household is correct. +2. Ask an owner/admin to open **Manage > Stores**. +3. Add a store and location. +4. Set a default location if needed. + +## Suggestions Or Zones Look Wrong + +Check: + +- Active household. +- Active store location. +- Location zones in **Manage > Stores**. +- Available items in **Manage > Stores > Manage Items**. +- Whether current list items should be imported into the catalog. + +## Image Upload Failed + +Check: + +- Browser network status. +- File type and size. +- `/config` image limit values. +- Upload toaster state. +- Retry the queued upload. + +Developers should check the backend image middleware and the request ID from the failed response. Do not log image bytes. + +## CORS Error + +Backend CORS uses `ALLOWED_ORIGINS`. + +Add the exact frontend origin, for example: + +```text +http://localhost:3010 +http://127.0.0.1:3010 +http://localhost:5173 +``` + +After backend env/CORS changes in Docker dev, recreate the backend service: + +```bash +docker compose -f docker-compose.dev.yml up -d --force-recreate --no-deps backend +``` + +Then verify: + +```bash +curl http://127.0.0.1:5000/ +curl http://127.0.0.1:5000/config +``` + +## Migration Or Store Management Is Unavailable + +Some store/catalog features require the latest database schema. + +Check: + +```bash +npm run db:migrate:status +npm run db:migrate:verify +``` + +Only run `npm run db:migrate` when the operator intends to apply migrations to the selected external Postgres database. + +## Gitea Actions Failed + +Check the failing job: + +- Install dependencies. +- Audit. +- Lint. +- Typecheck. +- Backend tests. +- Migration stale check. +- Backend build. +- Frontend build. +- Docker image build/push. +- SSH deploy. + +For deployment failures, verify Gitea secrets exist and are current. Do not print secret values in logs. + +## API Returned 401 Or 403 + +401 means the request is not authenticated. 403 means the authenticated user lacks the required role or membership. + +Check: + +- User is logged in. +- Session cookie is present. +- Token in local storage is current. +- User belongs to the target household. +- User has owner/admin role for management actions. +- System admin user has the `system_admin` role for `/admin`. + +## API Returned 500 + +Use the `request_id` in the response and backend logs to trace the failure. + +Common causes: + +- Missing environment variable. +- Database connection failure. +- Pending migration. +- Invalid data shape not handled by the route/controller. +- Image processing failure. + diff --git a/User-Guide.md b/User-Guide.md new file mode 100644 index 0000000..04389a7 --- /dev/null +++ b/User-Guide.md @@ -0,0 +1,101 @@ +# User Guide + +This guide explains the normal shopping workflow. + +## Sign In Or Register + +1. Open the app in a browser. +2. Use **Register** to create an account, or **Login** if you already have one. +3. Usernames are normalized to lowercase. +4. Passwords must be at least 8 characters. + +The app keeps you signed in with a secure session cookie. If your session expires, the app redirects you back to login. + +## Create Or Join A Household + +A household is the group that owns lists, stores, locations, invite links, and members. + +If you have no household: + +1. Open the household prompt from the main list or manage area. +2. Choose **Create Household** to start a new household. +3. Choose **Join Household** if someone sent you an invite link. + +If you belong to multiple households, use the household switcher in the navigation bar. The app remembers the active household in your browser. + +## Choose A Store Location + +The grocery list is scoped to a household store location. + +1. Use the store tabs near the top of the grocery list. +2. Pick the location you are shopping at. +3. If there are no stores, ask a household owner/admin to add one from **Manage > Stores**. + +The app remembers the active store location for each household. + +## Add Grocery Items + +On the main list: + +1. Type an item name. +2. Set the quantity. +3. Choose **Add** or **Create + Add**. +4. If the item already exists, confirm whether to add to the existing quantity. +5. Optionally add item details, classification, notes, or an image when prompted. + +Suggestions appear from the household/location catalog and previous items. + +## Mark Items Bought + +Use the item action to mark an item as bought. Depending on your settings, the app may ask you to confirm before buying. + +Bought items move out of the active list and can appear in **Recently Bought (24HR)**. This section helps recover accidental purchases or review what was just picked up. + +## Search The List + +Use **Search list** to filter visible list items. Search works on the current household/location list. + +When search is active: + +- Matching items remain visible. +- Empty zone sections are hidden. +- Collapsed zones are expanded for easier scanning. + +## Images + +Items can have product images. Images are uploaded through the app and processed by the backend. + +If the network drops during an image upload: + +- The upload queue keeps track of the failed upload. +- The upload toaster shows progress, success, or failure. +- You can retry or discard a failed upload. + +Do not upload sensitive photos or receipt images unless the feature you are using explicitly expects them. + +## Settings + +Open **Settings** from the user menu. + +Available settings include: + +- Theme: light, dark, or auto. +- Recently bought visibility. +- Number of recently bought items to show. +- Whether recently bought starts collapsed. +- Confirm before marking bought. +- Auto reload interval. +- Haptic feedback. +- Debug mode. + +Settings are stored in your browser for your username. + +## Permissions You May See + +Fiddy has two role layers: + +- System role: normal users generally use the app; system admins can access the admin panel. +- Household role: owner, admin, or member within each household. + +Household owners/admins can manage members, invite links, stores, locations, zones, and catalog defaults. Members can use the list and participate in household shopping. +