Files
pn-new-crm/docs/admin-ux-backlog.md
Matt a0e68eb060 docs: comprehensive audits + Documenso build plan + admin UX backlog
Six audit documents capture the 2026-05-06 review pass (comprehensive,
frontend, missing-features, permissions, reliability) along with the
Documenso integration audit + locked build plan that drove the bulk
of subsequent feature work.

Adds `docs/admin-ux-backlog.md` as a living tracker for the autonomous
push — every item marked DONE or REMAINING with file pointers and
scope estimates so future sessions can pick up where this one stopped.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-07 20:57:53 +02:00

8.0 KiB
Raw Blame History

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/<token>, /api/v1/me/email/cancel/<token>)
  • Password reset triggered via better-auth requestPasswordReset
  • Profile photo upload + crop (square 256×256) via shared <ImageCropperDialog> + /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 <NotesList> 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 <input type="color">
  • 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 createDocumentplaceFieldssendDocument 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/<type>/<token> 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.<fieldName>}} 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.