UI side of the smart-archive backend that shipped in d07f1ed.
- SmartArchiveDialog renders the dossier as a sectioned modal:
Pipeline interests, Berths (with next-in-line listed), Yachts,
Active reservations, Outstanding invoices, In-flight Documenso
envelopes, Auto-handled summary. Each section has a per-row decision
dropdown with sensible defaults (release for available/under-offer
berths, retain for sold berths and yachts, cancel for active
reservations, leave for invoices and documents).
- High-stakes deals show an amber warning panel + require a reason in
the textarea before the Archive button enables. Signed-document
acknowledgment checkbox blocks submission until checked.
- Wires into client-detail-header in place of the previous dumb
ArchiveConfirmDialog (the simple confirm dialog is kept for the
restore case until the smart-restore wizard ships).
- Pre-flight blocker banner surfaces dossier.blockers (e.g. active
reservation on a sold berth) and disables the Archive button entirely.
Two side fixes from CSP rollout:
- next.config CSP allows unpkg.com in dev so the react-grab devtool
loads. Stripped in prod via the existing isProd flag.
- middleware whitelist now passes /manifest.json + icon-*.png +
apple-touch-icon through unauthenticated, so PWA installability
isn't blocked by the auth redirect.
Bulk variant + restore wizard + hard-delete-with-email-code land in
follow-on commits.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Two audit-pass-#3 prod-readiness gaps.
Security headers
next.config.ts now emits CSP, X-Frame-Options=DENY,
X-Content-Type-Options=nosniff, Referrer-Policy, Permissions-Policy
on every response, plus HSTS in production. CSP allows the small
set of inline-style/inline-script + unsafe-eval (dev-only) needed
by Tailwind, Radix, and Next dev HMR; img-src/connect-src kept
reasonably wide for s3.portnimara.com branding + Socket.IO. Verified
via curl -I that headers ship and that the dashboard route still
serves correctly.
website_submissions retention
Adds 'website-submissions-retention' case to the maintenance worker
with a 180-day window and schedules it at 07:00 daily. Raw inquiry
payloads include reCAPTCHA + IP + UA metadata; keeping them
indefinitely was a privacy + storage gap that audit-pass-#3 flagged.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
When the in-app pathway is used for EOI templates, we now load the same
source PDF that the Documenso template uploads and fill its AcroForm
fields with values from EoiContext via pdf-lib. Field names mirror the
Documenso template's formValues keys exactly (Name, Email, Address,
Yacht Name, Length, Width, Draft, Berth Number + Lease_10 / Purchase
checkboxes), so both pathways produce equivalent legal documents — only
the renderer differs.
The form is left interactive (not flattened) so a recipient can still
adjust values before signing. Non-EOI templates (welcome letters,
acknowledgments, etc.) keep using the existing HTML→pdfme path.
Adds:
- pdf-lib direct dep
- src/lib/pdf/fill-eoi-form.ts — load + fill helpers, EOI_TEMPLATE_PDF_PATH
env override
- assets/ + README documenting the expected source PDF
- next.config outputFileTracingIncludes so the asset is bundled in the
standalone build
Tests: 8 new (4 fill-form unit + 2 source-PDF route + 2 fallback);
645/645 green.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>