- StorageProvider interface with LocalProvider (S3 placeholder)
- File table with entity_type/entity_id references, content type, path
- POST /v1/files (multipart upload), GET /v1/files (list by entity),
GET /v1/files/:id (metadata), GET /v1/files/serve/* (content),
DELETE /v1/files/:id
- member_identifier drops base64 columns, uses file_id FKs
- File validation: type whitelist, size limits, per-entity max
- Fastify storage plugin injects provider into app
- 6 API tests for upload, list, get, delete, validation
- Test runner kills stale port before starting backend
- Address field on member table (jsonb, same format as account)
- Members inherit email, phone, address from account when not provided
- State normalization: "Texas" → "TX", "california" → "CA" via shared util
- Member form drops zodResolver to fix optional field validation flashing
- Account name auto-format: "First Last - Account"
- US state lookup with full name + code support
- GET /v1/members with search across all members (includes account name)
- POST /members/:id/move with optional accountId (creates new account if omitted)
- primary_member_id on account table, auto-set when first member added
- isMinor flag on member create (manual override when no DOB provided)
- Account search now includes member names
- New account form includes primary contact fields, auto-generates name
- Members page in sidebar with global search
Replace unit_status and item_condition pgEnums with company-scoped lookup
tables that support custom values. Add account_payment_method table,
tax_exemption table with approve/revoke workflow, and CRUD routes for
processor links. Validate inventory unit status/condition against lookup
tables at service layer.
- category table with hierarchical parent_id, sort ordering, soft-delete
- supplier table with contact info, account number, payment terms
- CRUD routes for both with search on suppliers
- Zod validation schemas in @forte/shared
- Products will link to suppliers via join table (many-to-many)
- 26 tests passing
- account table (billing entity, soft-delete, company-scoped)
- member table (people on an account, is_minor from DOB)
- account_processor_link table (maps accounts to any payment
processor — stripe, global_payments — instead of stripe_customer_id
directly on account)
- Full CRUD routes + search (name, email, phone, account_number)
- Member routes nested under accounts with isMinor auto-calculation
- Zod validation schemas in @forte/shared
- 19 tests passing