# Admin / settings UX backlog — STATUS Living tracker for the admin/UX backlog. Items are marked DONE or REMAINING based on what landed in the autonomous-push session. --- ## DONE in the autonomous push ### Foundations - **Currency API verified end-to-end**. `scripts/test-currency-api.ts` fetches live Frankfurter rates → upserts → reads back → converts. Inverse-rate drift confirmed at ≤0.001. - **Storage abstraction audit complete**. Every byte path (signed EOIs, contracts, brochures, berth PDFs, files, avatars, branding logos) goes through `getStorageBackend()`. `/api/ready` and the system-monitoring health probe now check the active backend (S3 or filesystem) instead of always probing MinIO. ### User settings - Country + Timezone selectors with cross-defaulting + auto-detect banner ("Looks like you're in Europe/Paris — Update?") - Email change with verification flow (`user_email_changes` table, `/api/v1/me/email/confirm/`, `/api/v1/me/email/cancel/`) - Password reset triggered via better-auth `requestPasswordReset` - Profile photo upload + crop (square 256×256) via shared `` + `/api/v1/me/avatar` ### Branding - Logo upload + crop modal in admin/branding (uses the same shared cropper, persists via `/api/v1/admin/settings/image` → storage backend) - Email header/footer HTML defaults injectable via "Insert default" button - Brand colour picker, app-name field, logo URL all in one card ### Storage admin - New layout: S3 config form FIRST, swap action SECOND - Test connection button before any switch - Two-button switch: "Switch + migrate" vs "Switch only" with warning modal - `runMigration()` honours `skipMigration` flag ### Backup management - Real `/admin/backup` page driven by new `backup_jobs` table - `runBackup()` service spawns `pg_dump --format=custom`, streams to active storage backend, records size + path - Download button presigns the .dump for offline restore - Super-admin gated ### AI admin panel - Dedicated `/admin/ai` page consolidating master switch + monthly token cap + provider credentials - Per-feature settings (OCR, berth-PDF parser, recommender) linked from the same page ### Onboarding - Real `/admin/onboarding` page with auto-checked steps - Reads each setting key + lists endpoint (roles / users / tags) to decide completion - Manual checkboxes for steps without an auto-detect signal - Progress bar + "Mark done"/"Mark incomplete" buttons - State persisted in `system_settings.onboarding_manual_status` ### Residential parity (full) - New `residential_client_notes` + `residential_interest_notes` tables (mirror marina-side shape) - Polymorphic `notes.service.ts` extended with two new entity types through verifyParent + listForEntity + create + update + delete - New `` accepts `residential_clients` / `residential_interests` entity types - Activity endpoints: `/api/v1/residential/clients/[id]/activity` + `/api/v1/residential/interests/[id]/activity` - Notes endpoints: 4 new routes covering GET/POST/PATCH/DELETE - `residential-client-tabs.tsx` + `residential-interest-tabs.tsx` built using the marina-side `DetailLayout` pattern (Overview + Notes + Activity tabs, Interests tab on the client) - Detail header components mirror the marina-side strip - `useBreadcrumbHint` wired into both detail components ### Residential pipeline stages — configurable - New `residential-stages.service.ts` with list/save + orphan-check - `/api/v1/residential/stages` GET/PUT - `/admin/residential-stages` admin UI with reassign-on-remove modal (select new stage per affected interest before save) - Validators relaxed from `z.enum(...)` to `z.string()` so any admin-defined stage id round-trips ### Documenso Phase 1 (EOI generate flow polish) - Schema migrations applied: `document_signers.invited_at / opened_at / last_reminder_sent_at / signing_token`, `documents.completion_cc_emails / auto_reminder_interval_days` - `transformSigningUrl()` now maps SignerRole → URL segment correctly (approver→cc, witness→witness) so emails don't land on `/sign/error` - New `POST /api/v1/documents/[id]/send-invitation` endpoint with next-pending-signer auto-pick - Per-port settings added: `documenso_developer_label`, `documenso_approver_label`, `documenso_developer_user_id`, `documenso_approver_user_id` (Phase 7 RBAC binding fields) ### Misc UI/UX - Sidebar collapse removed (always expanded) - Audit log filter inputs sized + dates widened - Custom Settings section got a long-form description - Reminder digest timezone uses `TimezoneCombobox` - Port form: currency dropdown + timezone combobox + brand color - Permissions count badge opens a modal with granted/denied - Role names display-normalized via `prettifyRoleName` - Sales email config: token list + tooltips on threshold + body fields - Custom Fields page: amber heads-up about non-integration with search / recommender / audit / merge tokens - Tag form: native `` - FilterBar Select crash fixed (no empty-string item values) --- ## REMAINING — large pieces that didn't fit this push ### 1. Documenso Phase 2 — Webhook handler enhancement (~3-4 hours) Cascading "your turn" emails when each signer completes; on-completion PDF distribution; token-based recipient matching; idempotency lock. File to extend: `src/app/api/webhooks/documenso/route.ts`. The schema columns are already in place (Phase 1). ### 2. Documenso Phase 3 — Custom doc upload-to-Documenso (~6-8 hours) Backend service `custom-document-upload.service.ts` + endpoint `POST /api/v1/interests/[id]/upload-for-signing`. Accepts a PDF + recipient list + field-placement JSON, calls `createDocument` → `placeFields` → `sendDocument` on the per-port Documenso client. Persists a row in `documents` table. ### 3. Documenso Phase 4 — Field placement UI (~10-14 hours) The biggest piece. Needs: - 4a: Recipient configurator dialog (~2-3h) - 4b: PDF rendering with `react-pdf` (~3-4h) - 4c: Auto-detect anchor scanner via `pdfjs-dist.getTextContent` (~4-6h) - 4d: Drag-drop overlay using `dnd-kit` (~3-4h) - 4e: Send button → calls Phase 3 endpoint (~1h) Plan locked in `docs/documenso-build-plan.md` Phase 4 — the field-detector regexes, the anchor patterns, and the type-to-bbox sizing table are all spelled out. ### 4. Documenso Phase 5 — Embedded signing URL emission verification (~1-2 hours) Verify the website's `/sign//` page handles every signer role + every documentType combination. Update website's `signerMessages` map keyed on `(documentType, role)`. Apply the nginx CORS block from `docs/documenso-integration-audit.md`. ### 5. Documenso Phase 6 — Polish items (deferred) Auto-send delay, audit-log additions, per-document customisation, document expiration, reminder rate-limit display, failed-webhook recovery UI. Each ~2-3 hours; all deferred until Phases 1-4 ship. ### 6. Project Director — UI binding for the developer-user fields Schema + setting keys are now in place (`documenso_developer_user_id`, `documenso_approver_user_id` + `documenso_developer_label` / `_approver_label`). The remaining work is: add a "Linked to CRM user" dropdown in `/admin/documenso/page.tsx` that lists port users; when bound, auto-fill name/email from the user profile and mark name/email fields read-only. Webhook handler can then match against the linked user's email for in-CRM signing-status updates. ### 7. Custom-fields hardening (~ongoing) Remediation paths for the heads-up banner concerns: - **Search index**: extend the GIN tsvector to include customFieldValues content - **Audit diff**: extend `diffEntity` to walk the customFieldValues blob - **Merge tokens**: add `{{custom.}}` handling at template-render time, plus surface them in the merge-tokens UI ### 8. Documenso v2 webhook payload audit (small) Risk #4 from `docs/documenso-build-plan.md` — confirm v2 payload shape (`payload.documentId` vs `payload.id`, recipient.token vs `recipient.recipientId`) against a live v2 instance before relying on Phase 2 cascading emails.