- POST /import/stage (CSV text), GET /import/status (report + first-50 problem
rows with honest totals), POST /import/commit — all owner-only, audited;
commit still refuses while ANY staged row carries problems (existing guard)
- /import page (ADMIN nav, owner-only): file pickers → problem tables →
verification stats (incl. invoice-value cross-check) → confirm-gated Commit;
re-stage freely, series seeding message surfaced
- 2 route tests (403s for staff; bad→refuse→clean→commit round-trip incl.
series seeding past legacy numbers); suite 344 green
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- QUOTATION renders one titled section per line: module name, its what's-
included block, SAC + qty × rate + amount; sections never split mid-page and
each module after the first opens a fresh page in print
- summary line up top ('This proposal covers: …'); totals/terms/signature
unchanged; INVOICE/PROFORMA/CN/RECEIPT keep the compact grid (regression-
asserted); preview-fidelity golden test untouched and green
- 3 tests; suite green
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- GET/PATCH /me (self-scoped whitelist — role/email untouchable) + POST /me/password
- changeOwnPassword: current password required; every OTHER session dies in the
same txn, the changing session survives; audited without hashes
- staff_user.phone/title additive columns, surfaced on Employees (columns + edit
dialog) and the new Profile page; user chip in the shell opens /profile
- 7 tests; suite 331/331 across 64 files
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- /reminders page: Queued/Sent/Failed/Dismissed chips mapping to ?status=,
managerial-only Mine/All toggle via ?owner= (staff are server-forced to
their own rows), kind/client/doc/due/status table with Send/Preview/
Dismiss on open rows, honest server-driven pager (rule 8).
- Extract the Dashboard queue actions into shared
components/ReminderQueue.tsx (QueueActions, RULE_LABEL, reminderTone)
with a re-entry guard on Send/Dismiss; Dashboard queue card links
"View all" to /reminders.
- api.ts: getReminders now takes { status, owner, page, pageSize } and
returns the full QueueItem rows + page metadata; login stores the
staff id (hq.id) so Mine can narrow by owner.
- Nav item under WORK + route; no backend changes. A contract test pins
the sent/dismissed chips, ?owner= narrowing and cross-chip staff scope
at HTTP level (apps/hq/test/reminders-page.test.ts).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
listDocuments now returns { documents, total, page, pageSize } (default 50,
cap 200, newest first) with the client name joined server-side — no N+1.
GET /documents passes page/pageSize through; type/status/clientId filters
compose against the same WHERE for both count and page (rule 8: no silent
caps). clientLedger walks the paginated repo in 200-row batches so the
ledger still surfaces every document. New /documents screen: type chips,
status filter, mono doc numbers, amount column, pager honouring the server
total; rows open /documents/:id. Nav entry under WORK (exact-match so New
Document keeps its own highlight).
Note: the GET /documents route hunk itself landed via 8861b46, swept into
a concurrent commit from the same working tree; this commit carries the
repo/ledger/web halves and the tests.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 5 (D-PIPE option B, spec §6b/§9): repos-pipeline.ts listPipeline unions the
latest non-cancelled QUOTATION per client with bare leads (Enquiry); stage is never
stored; age anchors on the first 'sent' document_event; next action + colour band
read resolveSchedule('quote_followup') day_offsets (no hardcoded 3/7/14); staff are
server-forced to their own rows via ownerScope; Lost hidden unless filtered; sorted
actionable-oldest-first with LIMIT/OFFSET + honest total. GET /pipeline route plus
the Pipeline page (filter chips, managerial owner dropdown, band row tones, lifecycle
action buttons, pager) wired into nav right after Dashboard.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Phase 2 of the quote-to-close funnel slice. Six /employees routes in
apps/hq/src/api.ts (GET requireAuth for the picker; POST/PATCH/deactivate/
reactivate/password owner-only, acting as the signed-in user); Employees
page (table + add/edit/reset-password forms, email immutable on edit,
count shown, no truncation); owner-only nav item beside Document Template;
typed client fns in hq-web api.ts. 6 new route tests (192 total).
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>