Commit Graph

52 Commits

Author SHA1 Message Date
670ca16a05 docs(uat): annotate master doc + plan for Group A ships (e33313b)
7 master-doc entries now carry the `SHIPPED in e33313b` line:
  - Admin Documenso env-fallback pills
  - WatchersCard empty-state padding (follow-up bump)
  - /invoices/upload-receipts copy rewrite
  - Pageviews chart X-axis tick thinning
  - CommandList scroll-cap (popover-aware max-h)
  - DropdownMenu max-h cap (Radix-aware)
  - Residential InterestsTab standalone-list whole-row navigate
  - StageStepper visible stage names

3 master-doc entries verified pre-shipped (A3, A6, A8) — already
carrying SHIPPED markers from earlier commits; A6 + A8 confirmed
in the new commit notes for cross-reference.

Plan doc (`2026-05-21-remaining-plan.md`) Group A section
collapsed to a 12-line ✓ list pointing at the verifying commits.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 21:38:27 +02:00
a555798cfe docs(uat): structured plan for remaining master-doc items
Captures all 66 still-open items from `alpha-uat-master.md` (Buckets
1-4 plus the deferred bugs and DEFERRED-tagged features) into a
single sequential plan. Items grouped so logically-related work
lands as one PR rather than scattered commits.

Groups (suggested execution order):
  A — Tiny copy / UI fixes (12 items, ~1 h)
  B — Interest detail polish (7 items, ~2 h)
  C — Berth list features (4 items incl. bulk-edit, ~2.5 h)
  D — BulkAddBerthsWizard polish (2 items, ~1.5 h)
  E — Supplemental-info-request (1 item, ~1 h)
  F — DocumentsHub + signing flow polish (3 items, ~3 h)
  G — Admin sections consolidation (2 items, ~6 h)
  H — Email + branding (2 items, ~2 h)
  I — Residential parity (4 items, ~10 h)
  J — Activity feed + EntityActivityFeed (2 items, ~2 h)
  K — OnboardingChecklist + nudges (1 item, ~6-8 h)
  L — UploadForSigningDialog rework (1 item, ~12-16 h)
  M — Universal preview + form-templates (2 items, ~12-16 h)
  N — Dashboard upgrades (3 items, ~10-14 h)
  O — Umami phases 3 / 4 / 5 (9 items, ~14-18 h)
  P — Nested document subfolders phases 2/3 (1 item, ~5-6 h)
  Q — Platform-wide refactors (5 items, ~14-18 h)
  R — Documenso-first templates (1 item, ~6-8 h)
  S — AI extraction (deferred, ~10-14 h)
  T — Deferred bugs (2 items)
  U — EOI bundle UX rework (1 item, ~10-14 h)

Per-item: scope summary, file pointers, effort estimate, blocks-on /
pairs-with annotations. Execution discipline section at the bottom
describes the per-item workflow (quote source bullet → verify not
already shipped → implement + test → annotate master doc → tick
off plan).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 21:18:52 +02:00
d879188322 docs(uat): SHIPPED annotations for session — 12 items closed across all buckets
Brings the master UAT doc in sync with this session's actual ship state.

Annotated (commit SHA after each):
  - Em-dash sweep + lint bump to error (f0dbefc)
  - Berth-list active-interests popover + density tokens (292a8b5)
  - LinkedBerthsList "Add berth" CTA (3999d4b)
  - BulkAddBerthsWizard mooring-exists pre-flight (ca172fa)
  - Email / SMTP admin "Send test email" (7881da6)
  - Smart-search pipeline-stage fuzzy match (d912f02)
  - External-EOI edit-metadata UI (235e064) — closes the (e) sub-item
  - Date-input migration sweep, remaining 14 sites (0c6e7b7)
  - Nested document subfolders foundation only (e91055f)
  - PDF report exporter, full 4-phase build (3b199c2, 47c2ba9, 1cdc2fd, 5a9b5f6)

Yacht ft↔m + click-to-preview on EntityFolderView/HubRootView were
already annotated earlier in the session (5320398, 1f591ff).

The "Remaining" notes on each entry call out what stays parked
(e.g. nested-subfolders phases 2/3 — UploadZone scope radio,
lifecycle hooks, list-query rewrite, tree rendering, backfill).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 21:13:06 +02:00
5320398501 docs(uat): SHIPPED annotation for PR25 (yacht ft↔m round-trip)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:26:00 +02:00
1f591ff7ae docs(uat): SHIPPED annotation for PR24 (click-to-preview sweep complete)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:21:30 +02:00
b7533fee3e docs(uat): SHIPPED annotation for PR23 (supplemental-info Generate / Send split)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:56:10 +02:00
d97a08bf5f docs(uat): SHIPPED annotation for PR21 (auth link contrast)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:47:57 +02:00
28eb76a9d8 docs(uat): SHIPPED annotation for PR20 (form-error UX primitives)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:45:23 +02:00
7d48349a75 docs(uat): SHIPPED annotations for PR19 (a11y + i18n micro-fixes)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:41:12 +02:00
5a2dabea05 docs(uat): SHIPPED annotations for PR18 (interest-berths defaults + a11y)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:36:47 +02:00
1f8bd47a7b docs(uat): SHIPPED annotations for PR17 (layout polish)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:32:43 +02:00
9adb80ada4 docs(uat): SHIPPED annotations for PR16 (Overview cleanup)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:27:59 +02:00
348dc94858 docs(uat): SHIPPED annotation for PR15 (reusable supplemental token)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:24:06 +02:00
4d3d7489bf docs(uat): SHIPPED annotations for PR14 (signature docs rename + tooltip + yacht Transfer)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:19:21 +02:00
610154395a docs(uat): SHIPPED annotation for PR13 (activity feed UUID resolution)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:14:52 +02:00
f99d2cd9ec docs(uat): SHIPPED annotations for PR12 (env-reveal + stage sortable)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:12:04 +02:00
901fc363a5 docs(uat): SHIPPED annotations for PR11 (picker polish + currency + breadcrumb)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:07:40 +02:00
c18dbbd61b docs(uat): SHIPPED annotations for PR10 (copy polish + a11y)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 18:02:04 +02:00
5f937b4551 docs(uat): SHIPPED annotations for PR9 (milestone classifier + backfill)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:55:12 +02:00
535ff69fc4 docs(uat): SHIPPED annotations for PR8 (qualification rework)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:48:31 +02:00
b9d388a362 docs(uat): SHIPPED annotations for PR7 (Wave-2 polish batch)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:42:44 +02:00
a673b6cec2 docs(uat): SHIPPED annotations for PR6 (structured signatories + signers)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:35:32 +02:00
7cdfed27fa docs(uat): SHIPPED annotations for PR5 (UI polish batch)
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:29:53 +02:00
70c7d84dea docs(uat): SHIPPED annotations for PR4 (a11y primitives + click-to-preview)
Annotate 4 finding entries:
- em-dash lint guard (sweep parked)
- DocumentList Download in kebab
- WatchersCard empty-state padding
- EOI empty-state Mark Signed button
- Platform-wide click-to-preview (FileGrid + DocumentList; 2 remaining surfaces parked)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:21:33 +02:00
6a4f4ea1dd docs(uat): SHIPPED annotations for PR3 (primitives)
Annotate ColumnPicker, FileInputButton, and DatePicker / DateTimePicker
entries with the 8f42940 summary. Notes the deferred sweeps:
- 15+ remaining date-input sites
- raw-input file sweep was a no-op (audit showed only 1 actual
  default-UI site, already migrated)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:11:02 +02:00
69444878ab docs(uat): SHIPPED annotations for PR2 (external-EOI bundle)
Annotate B4 #5 with the 6cdb9af summary of what landed (a/b/c/d +
default title) and what's deferred (e — edit metadata UI bundles with
later signing-flow rework).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 17:02:12 +02:00
abbaf406ab docs(uat): SHIPPED annotations for PR1 batch + accumulated UAT findings
PR1 batch (2d57417) covered 7 Wave-1 blockers; each finding entry now
carries an inline `**SHIPPED in 2d57417:**` line summarizing what
landed and (where applicable) what remains parked for later waves
(backfill scripts, nested-folder migration, platform-wide form-error
audit).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 16:52:59 +02:00
449b9497ab fix(uat): batch — timeline overshoot, name-sync, reset-password, dashboard cleanup, queue/seed hygiene + alpha UAT findings doc
UAT findings landed across the last few Playwright + React Grab passes;
single grouped commit so the index doesn't fragment into 30 one-liners.

User & auth:
- `user-settings`: name now updates the avatar + topbar menu after save
  (was reading stale session).
- `me/password-reset`: 3 bugs (token validation, error response shape,
  redirect chain).
- Admin user permission-overrides route honours the same envelope as
  the rest of the admin surface.

Dashboard:
- Removed obsolete `revenue-breakdown-chart` + `dashboard-widgets-card`
  (replaced by the customisable widget grid).
- Strip `revenue_breakdown` from analytics route + use-analytics +
  service + integration test so nothing renders an empty card.
- Activity log timeline overshoot fix (`interest-timeline` +
  `entity-activity-feed`).
- Tightened tiles: active-deals, berth-heat-widget, pipeline-value, kpi-tile.
- `dev-mode-banner`: derive dismissed state synchronously instead of
  via an effect (set-state-in-effect lint rule).

Forms & lists (assorted polish):
- client / company / yacht / interest / reminder forms — validation +
  empty-state copy + tab transitions.
- companies/yachts list tweaks; berth recommender panel; qualification
  checklist; supplemental info request button.

Infra & misc:
- Queue workers (ai / email / notifications) — log shape +
  per-job timeout consistency.
- Auth / brochures / users schema small adjustments; seeds reflect
  permissions matrix changes.
- Scan shell + scanner manifest + AI admin page small fixes.
- `next.config.transpilePackages` adds `echarts`/`zrender`/`echarts-for-react`
  (recommended config from echarts-for-react inside Next).

Docs:
- `docs/superpowers/audits/alpha-uat-master.md` — single rolling
  cross-cutting UAT findings doc (per CLAUDE.md convention).
- `docs/BACKLOG.md`: dashboard stats cards (§I) + activity-log
  normalization (§J).
- 2026-05-18 audit log updated with this batch.
- `CLAUDE.md` — small manual UAT scaffold notes.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-20 15:56:11 +02:00
1b8dacfa54 docs(audit): full codebase audit — 128 findings across 16 areas
Spawned 16-agent sonnet[1m] audit team covering schemas (people/orgs,
pipeline, docs+infra), APIs (public, admin, v1 CRUD, webhooks/auth/
storage), services (EOI/Documenso, domain, observability), background
jobs, UI (admin, entity), and cross-cutting security/performance/tests-
deps. 13 of 16 agents delivered detailed JSON reports; A1/F1/B3 audited
inline after their agents stalled. E1/E2 (admin + entity UI) couldn't
complete in a single spawn — flagged for re-attempt with narrower scope.

Top findings:
- 5 CRITICAL: send-invoice and invoice-overdue-notify silently no-op
  (D1#1); 5 maintenance crons including database-backup scheduled but
  unimplemented (D1#2); tenure-expiry-check ditto (D1#3); GDPR export
  bundles not deleted on RTBF (C3#1, gap in A.7 shipped today);
  residential_clients has no hard-delete path at all (C3#2).
- 15 HIGH including: /api/public/interests doesn't validate portId
  (B1#1, cross-tenant injection); documents.documenso_id has zero
  index (A3#1, every webhook is a full scan); better-auth rate limit
  is in-memory (B4#1, multi-replica bypass); generateAndSignViaInApp
  omits portId on Documenso calls (C1#1); custom-doc-upload calls
  placeFields after distribute (C1#2); {{eoi.berthRange}} +
  {{reservation.*}} tokens never resolved (C1#3); recommender SQL/JS
  stage-scale off-by-one (C2#1); getClientById runs 6 queries serial
  (F2#1); no CI pipeline + zero tests on client-hard-delete (F3#1,2).
- 36 medium, 53 low, 19 info.

Triage groups in the doc:
  Tier S: 7 ship-stopping bugs (today)
  Tier 1: ~12 high-severity items (this week)
  Tier 2: ~36 medium (next sprint)
  Tier 3: ~53 low (rolling)
  Tier 4: re-spawn E1+E2 with narrower scope

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:38:10 +02:00
b3f87563c6 feat(audit-cleanup): finish all 15 outstanding items from verified backlog
Audit cleanup completion plan, all tiers shipped:

Tier 1 (security + data integrity)
- A.7 RTBF true wipe: redact email_messages body/subject/addresses for
  threads owned by deleted client; redact document_sends.recipient_email;
  collect file storage keys + delete blobs post-commit.
- A.8 user_permission_overrides FK: documented inline why cascade is
  correct (not set-null as audit suggested) — overrides have no value
  without their user.
- W2.14 PII redaction: camelCase normalization in audit.ts +
  error-events.service.ts isSensitiveKey; added city/postal/country/
  birth fragments. firstName/lastName/dateOfBirth/postalCode etc. now
  caught in BOTH masker paths. 12 new test cases lock the coverage.

Tier 2 (Documenso completion + refactor)
- C.2: documentEvents.recipient_email column + partial unique index for
  per-recipient webhook dedup (migration 0075). handleDocumentSigned
  now sets recipient_email on insert.
- Phase 2: completion_cc_emails distribution. handleDocumentCompleted
  reads documents.completionCcEmails, filters out signer-duplicates
  case-insensitively, fans signed PDF out to non-signer recipients.
- C.4: extracted createPublicInterest() service from the 346-line
  api/public/interests route. Route becomes a thin shell (rate-limit,
  port resolution, audit log, email fan-out). The trio creation logic
  is now unit-testable without an HTTP fixture.
- Phase 4: POST /api/v1/document-templates/[id]/detect-fields wired
  to document-field-detector.detectFields(). Sparkles "Auto-detect"
  button added to template-editor.tsx — maps DetectedField → marker
  with best-guess merge token (DATE / NAME / EMAIL); user retags.

Tier 3 (reporting + recommender snapshot lockfiles)
- W7.reports: extracted rollupStageRevenue / rollupStageCounts /
  computeTotalForecast / computeOccupancyRate / rollupBerthStatusCounts
  into src/lib/services/report-math.ts (pure functions). 16 new tests
  including an inline-snapshot lockfile on a representative 7-stage
  forecast. report-generators.ts now delegates.
- W7.recommender: 18 new toMatchSnapshot tripwires on classifyTier
  boundaries + computeHeat at canonical input points.

Tier 4 (rolling)
- W6.attach: fixed outdated CLAUDE.md claim — threshold banner is
  informational and never depended on IMAP; bounce monitoring (the
  IMAP poller) is separate.
- D.1 + D.2: documented deferral inline with full why-not-build-it
  reasoning so a future engineer sees the rationale.
- G.1: representative formatDate sweep (audit-log-list, user-list,
  document-templates merge tokens, document-signing email). Rest of
  the ~100 sites stay rolling.

Quality gates: 1420/1420 vitest (46 new tests above baseline of 1374),
tsc clean, 0 lint errors.

Plan: docs/superpowers/plans/2026-05-18-audit-cleanup-completion.md
Migration: 0075_c2_document_events_recipient_email.sql (applied to dev DB).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-18 18:22:36 +02:00
397dbd1490 docs(spec): env-to-admin migration design
Design spec for moving tenant-configurable env vars into the per-port
admin UI via a settings registry. Covers scope decisions, registry
shape, resolver, encryption, admin UI generation, env catalog by
disposition, migration plan, and testing.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-15 14:22:39 +02:00
81a98c6695 docs(superpowers): pdf stack overhaul design (react-pdf + unpdf)
Lays out the plan to replace pdfme with @react-pdf/renderer, add unpdf
for berth-PDF tier-2 rasterization, and add port-level logo upload
(sharp normalization + react-image-crop UI + svgo sanitization +
rasterize-SVG-to-PNG-on-upload).

Scope locked to internal-only PDFs (reports, expenses, record exports).
Invoice + admin TipTap-to-PDF removed entirely; in-app EOI pathway
(pdf-lib AcroForm fill) stays untouched.

14 commits planned. Single source of truth for tokens. Three orthogonal
PDF paths post-migration with no overlap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-12 20:36:54 +02:00
638000bb58 chore: prettier format audit report markdown
Lint-staged reformat after the previous commit added the file. Same
content, prettier's preferred line wrap.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:59:43 +02:00
1bdc856589 feat(documents-hub): NewDocumentMenu dropdown + FolderDropZone drag-drop
Replaces the bare "+ New document" Button on the documents hub with a
NewDocumentMenu dropdown so reps explicitly pick between:
- "Upload file" → opens a Dialog with FileUploadZone scoped to the
  current folder + entity context. No signing flow attached.
- "Generate document for signing" → navigates to /documents/new wizard.

Avoids the prior ambiguity where reps clicked "+ New document" intending
to attach a file and were dropped into the Documenso signer wizard.

Also adds FolderDropZone wrapping FlatFolderListing and EntityFolderView.
Dragging files from the OS over the current folder shows a drop overlay;
drop fires N parallel uploads carrying the folder + entity context.
Mirrors the per-entity Files tab UX but works in-place on the hub.

Both surfaces hit /api/v1/files/upload with folderId + entityType/Id +
the legacy clientId/companyId/yachtId FKs so files land on the right
entity AND inside the correct folder.

Also includes the in-flight prettier reformat from lint-staged on a
few previously-touched files (create-document-wizard, file-upload-zone,
admin/documenso/page) and adds the standalone prod-readiness audit
report to docs/superpowers/audits/ for permanent reference.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 17:59:34 +02:00
0e8feb1073 chore: prettier format pass on branch files
Auto-format all files modified during the documents-hub-split feature
branch that were not yet aligned with the project's Prettier config
(single quotes, semicolons, trailing commas).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 13:01:47 +02:00
40e3db237d docs(plans): documents hub split + auto-filed client folders
19-task implementation plan layering on top of Wave 11.B. Builds three
system-managed roots (Clients/Companies/Yachts), per-entity auto-
subfolders, Documenso auto-deposit on completion, owner-aggregated
projection (symmetric reach, file-FK source of truth, defense-in-depth
port_id), and the hub UI rebuild. Hard cutover; backfill via idempotent
script.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:57:46 +02:00
5422f11747 chore: prettier formatter drift across recent commits
Prettier reformatting on files touched in the wave 11.B sequence —
markdown italics _underscore-style_, single-line conditionals, minor
whitespace fixes. No semantic changes. .env.example reformatting left
unstaged (blocked by pre-commit hook).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-11 10:57:37 +02:00
286eb51f81 docs(specs): documents hub split + auto-filed client folders
Design for unifying /documents and /documents/files under a single hub
with stacked Signing/Files sections, owner-grouped aggregation across
the relationship graph, and three system-managed entity-folder roots
(Clients/Companies/Yachts) with lazy per-entity subfolders. Documents
hub stays anchored on document_folders; files gain folder_id; signed
PDFs auto-deposit on Documenso completion. Includes 14+ edge-case
decisions, schema deltas, backfill plan, and implementation surface.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-10 22:50:31 +02:00
f286c4ef5f docs(plan): progress snapshot at Task 7 — backend complete, UI next
Tasks 1-7 done in subagent-driven mode (11 commits 5bed62da0ffa1b).
The entire DB + service + API layer for folders is shipped: schema,
manage_folders perm, listTree/createFolder/renameFolder/moveFolder/
deleteFolderSoftRescue, validators, all 4 folder routes, the per-doc
move endpoint, and the listDocuments folder filter (with descendant
expansion). Reps can already manage folders end-to-end via direct
API calls.

Records the design decisions made mid-execution: hybrid storage
strategy (UUID-flat + path-style download URLs), permission split,
soft-rescue delete semantics, cycle prevention with port-scoped
ancestor walk, PATCH-body exclusivity via .strict(), and the
updatedAt bump rule (per-doc move yes, bulk soft-rescue no).

Tests at pause: 1213/1213 vitest, tsc clean. Resume prompt + task
ordering for Task 8 onwards included so a fresh session can pick up
without context.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 20:08:28 +02:00
9f3e739c76 docs(plan): add Tasks 18-19 (path-style URLs + organized-bucket importer)
User chose the hybrid storage strategy after reviewing the cost
analysis: storage paths stay UUID-flat (preserves the established
pattern across brochures, berth PDFs, invoices, reports, templates,
expense receipts, and the migrate-storage byte-verbatim copy), but
documents gain a path-style download URL so reps see meaningful
paths in shared links and browser tabs.

Task 18 wires the new /api/v1/documents/[id]/download/[...slug]
catch-all route + a downloadUrl field on list/detail responses.
The slug is validated for truth so a hand-edited URL with a
stale path 404s instead of silently serving the wrong file.

Task 19 is the importer the user mentioned: a one-shot script
that walks an organized legacy bucket, creates matching folder
tree + document rows pointing at existing storage keys verbatim.
Idempotent via the sibling-uniqueness index.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 19:50:28 +02:00
51a60c1b9e docs(plan): documents folders implementation plan
17-task TDD plan covering schema + migration, service (listTree,
create, rename, move with cycle prevention, soft-rescue delete),
validators, API routes, hook, sidebar tree, breadcrumb, actions menu,
move-to-folder dialog, hub wiring (drop signature-only pill, In-
progress tab, dynamic type chips), admin-configurable Expired tab,
Playwright smoke, and CLAUDE.md update. Decisions locked: port-wide
tree, hub tabs stay flat, documents.manage_folders new perm, soft-
rescue on delete (never CASCADE), folder watchers out of scope.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-09 18:59:30 +02:00
Matt Ciaccio
d7ec2a8507 Merge docs/dedup-migration-design: client dedup + NocoDB migration design doc
Some checks failed
Build & Push Docker Images / lint (push) Successful in 1m18s
Build & Push Docker Images / build-and-push (push) Failing after 3m57s
2026-05-03 16:24:30 +02:00
Matt Ciaccio
36b92eb827 docs(spec): client deduplication and NocoDB migration design
Captures the audit findings from a 2026-05-03 read-only NocoDB review
plus the algorithm and migration plan for porting the legacy data
into the new client / interest / contacts / addresses model.

Highlights:
- 252 NocoDB Interests rows ≈ ~190–200 unique humans (~20–25% dup
  rate). Six duplicate patterns documented from real data, including
  "same person, multiple yachts" — exactly the case the new
  client/interest split is designed to handle.
- Reuses the battle-tested `client-portal/server/utils/duplicate-
  detection.ts` algorithm (blocking + weighted rules) with additions:
  metaphone for non-English surnames, compounded confidence when
  multiple rules match, negative evidence for split-signal cases.
- Three runtime surfaces (at-create suggestion, interest-level
  same-berth guard, background scoring + admin review queue) plus a
  one-shot migration script with --dry-run / --apply / --rollback.
- Configurable thresholds via per-port system_settings so the merge
  policy can be tuned (defaults to "always confirm" — never
  auto-merges out of the box).
- Reversible: every merge writes a clientMergeLog row with the
  loser's full pre-state JSON, enabling 7-day undo without engineering.

Implementation decomposes into three plans (P1 library / P2 runtime /
P3 migration) sequenced after the mobile branch lands.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-03 14:10:08 +02:00
Matt Ciaccio
fbb1f1f366 scaffold(mobile): branch setup — audit harness, spec, plan, gitignore + client-portal cleanup
Pre-execution baseline for the mobile foundation PR:

- Mobile audit harness (tests/e2e/audit/mobile.spec.ts + mobile-audit Playwright project) — visits every page at four anchor iPhone viewports (375/393/402/440), screenshots full-page to .audit/mobile/, generates index.md
- Design spec (docs/superpowers/specs/2026-04-29-mobile-optimization-design.md) — adaptive shell + responsive content; full active-iPhone-range coverage; foundation + per-page migration phases
- Implementation plan (docs/superpowers/plans/2026-04-29-mobile-foundation.md) — 24 TDD tasks for the foundation PR
- .gitignore: ignore /client-portal/ (legacy nested Nuxt repo) and /.audit/ (regenerable screenshots)
- Remove phantom client-portal gitlink (mode 160000 with no .gitmodules)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 13:49:38 +02:00
Matt Ciaccio
d9557edfc5 docs(spec): GWS inbox-triage exploratory design (not approved for build)
Surveys what it actually takes to ship the AI inbox-triage feature
gated on Google Workspace integration. Walks through three deployment
models with their real costs:

- Model A (Marketplace OAuth app): 4-6 months calendar, $15k-$75k for
  the required CASA security assessment, recurring re-verification
- Model B (per-customer Internal OAuth app): ~5 weeks engineering, $0
  Google-side, scoped to one workspace per customer
- Model C (forward-to-CRM mailbox): ~1 week, receive-only, no reply
  drafts possible

Recommends Model B for the current customer profile, with B → A
promotion only if 3+ customers ask unprompted.

Documents what's already scaffolded (email_accounts/threads/messages
tables, syncInbox stub, BullMQ email queue, ai_usage_ledger, per-port
aiEnabled flag, withRateLimit('ai')) vs what's new (OAuth flow, Pub/
Sub push receiver, gws_user_tokens + email_triage tables, /inbox UI).

End-to-end flow, schema additions, AI cost interaction with the
Phase 3b token budgets, 5-phase build plan (G1-G5), and 5 open
decisions to resolve before scheduling the build. Explicitly out of
scope: M365, sentiment analysis, smart-drafts, cross-staff triage
queue.

No code changes — this is a design doc to drive a go/no-go decision.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-29 01:18:15 +02:00
Matt Ciaccio
f1ed2a5f87 docs(spec): Phase B — insights, alerts, and operational awareness
All checks were successful
Build & Push Docker Images / lint (pull_request) Successful in 1m4s
Build & Push Docker Images / build-and-push (pull_request) Has been skipped
Full execution plan for the next phase. Closes the seven priority gaps
the 2026-04-28 Nuxt→Next audit surfaced (analytics, alerts,
interests-by-berth, expense dedup, EOI queue, OCR, audit log read view).

Scope:
- Analytics dashboard with KPI tiles, pipeline funnel, occupancy
  timeline, revenue breakdown, lead-source attribution; cached via
  `analytics_snapshots` recurring job.
- Alert framework: 10-rule v1 catalog, rule engine evaluates on cron,
  fingerprint dedupes, auto-resolves when condition clears, surfaces
  in dashboard right rail + dedicated /alerts page.
- Interests-by-berth tab on berth detail.
- Expense duplicate detection (vendor + amount + date ±3d) with
  merge action.
- OCR for expense receipts via Claude Vision (Haiku 4.5 + ephemeral
  system-prompt cache).
- Audit log admin read view with tsvector search + cursor pagination.
- EOI queue: saved-view tab on the documents hub.

11 PRs, ~10-13 dev days, calendar 2.5-3 weeks. Critical path
graphed. Risk register includes alert false-positive mitigation,
OCR cost ceiling via Haiku + cache, and audit-log scale.

Four open questions for the user in the spec footer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 14:00:01 +02:00
Matt Ciaccio
4036c16f39 test(infra): vitest globalSetup teardown purges test-port-* leaks
Integration tests use makePort() which writes ports with slug 'test-port-{rand}'
and never cleans up. Result: 17,564 leaked rows in dev that slowed every page
load fetching the port-switcher list (and was contributing to smoke flakes).

Adds tests/global-setup.ts with a teardown() that DELETEs every 'test-port-%'
row plus its dependent rows across 30+ tables in one CTE. Wires it into
vitest.config.ts via globalSetup. Adds closeDb() helper so the teardown can
end the postgres-js pool cleanly (kills the 'Tests closed but Vite server
won't exit' warning).

Also lands docs/superpowers/specs/2026-04-28-country-phone-timezone-design.md
— full-scope agenda for the country dropdown / E.164 phone input /
country-driven timezone autofill work, ~7 dev days across 10 PRs. Per
user request: 'let's do this full-fledged if we're gonna do it'.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 13:28:15 +02:00
Matt Ciaccio
d8ac62f6f4 docs(spec): documents hub + reservation agreements + visual polish (Phase A)
Captures the brainstorm output covering:
- Documents hub at /[port]/documents replacing existing list
- Document detail page with vertical signers panel, watchers, timeline
- Generalised create-document wizard (HTML / PDF AcroForm / PDF overlay /
  Documenso-rendered + ad-hoc PDF upload)
- Reservation agreements as a doc type with new CRM-side detail page
- Email composer attachments + System-vs-User From selector (admin-gated)
- Reminder framework polish (per-template cadence, per-doc override, per-doc
  disable, per-signer manual reminders); drops interests.reminderEnabled gating
- Documenso v1.13.1/v2.x version-aware abstraction for field placement + void
- System-wide visual polish (token additions, primitive components, sweep)
- Test plan including click-everything sweep + expanded realapi round-trip
- Build sequence: 11 PRs, ~3.5 weeks critical path

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 01:51:41 +02:00
Matt Ciaccio
11969c0d8a docs(plan): add data-model refactor implementation plan (Spec 1)
15-PR sequenced plan covering schema migration, services, API,
seeder, UI, EOI dual-path, exhaustive click-through tests,
documentation updates, and final merge.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:17:02 +02:00
Matt Ciaccio
1c0a16fd59 docs(spec): add data-model refactor design (Spec 1 of 3)
Introduces yachts and companies as first-class entities with memberships,
ownership history, berth reservations, and dual-path EOI templates.
Explicit non-goals (importer, merge endpoint) carved out as Specs 2 and 3.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-23 17:04:41 +02:00