Commit Graph

145 Commits

Author SHA1 Message Date
0f7da79a64 docs(launch): Financial report SHIPPED (Phase 4) — payments-model reframe
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 00:44:27 +02:00
75fdb9fab4 docs(launch): reconcile tracker — mark shipped rep/source filters + 3 stale-deferred items
- rep + source multi-select filters → SHIPPED in b97f6e94
- Waiting List + Maintenance Log tabs → SHIPPED in 8be7a6e2 (were still
  listed deferred)
- contract/reservation paper-upload misroute fix → SHIPPED in d98aa5cc
  (was still listed deferred)

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-02 00:25:34 +02:00
7dba1a47bb fix(migration): modernize stale NocoDB→CRM pipeline stage map to current 7 stages
The 2026-05-03 migration pipeline (src/lib/dedup/*) predates the 9→7
pipeline-stage refactor; its STAGE_MAP emitted invalid stages
(open/details_sent/eoi_sent/…) that would write bad pipeline_stage values
on --apply. Remap to the current PIPELINE_STAGES (enquiry/qualified/
nurturing/eoi/reservation/deposit_paid/contract) + a deposit-received →
deposit_paid override. Frozen-fixture test expectations updated (17/17 pass).

Validated: live --dry-run = 239 clients / 255 interests / 41 EOI docs
(matches independent snapshot analysis; pipeline is more conservative and
flags 3 borderline pairs for review).

Adds the migration design spec (source map, scope lock to Port Nimara +
Expenses bases, EOI coverage 48/48, in-flight Documenso state, remaining
gaps: interest eoiStatus, expenses, doc-blob backfill).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 19:03:32 +02:00
31ba72f344 chore(launch-prep): hide unfinished report/import surfaces, defer big builds
Ship-what's-done prep ahead of the prod cutover (launch ~today):

- Hide Financial + Marketing report cards from the reports landing
  (both were "Builder in development" placeholders gated on unbuilt
  data sources). Sales/Operational/Custom + templates/scheduling/
  exports remain live.
- Trim the Custom-report card copy to match the shipped basic builder
  (no group-by/filters yet; the builder page header was already honest).
- Hide the Bulk Import mockup from search-nav-catalog + the admin
  sections browser; /admin/import is now unreachable from the UI.
- Correct client-facing doc over-claims (waiting-list "next-in-line
  notification", Import) in features-list.md + new-system-feature-summary.md.
- Un-stale BACKLOG.md (Documenso phases 2-7 confirmed shipped).
- Log decisions + deferred work (full importer, full custom-builder,
  waiting-list, maintenance-log, paper-upload bug) to launch-readiness.md.

Deferred-importer design spec added at
docs/superpowers/specs/2026-06-01-bulk-import-design.md.

Verified: tsc --noEmit clean, eslint clean on changed files,
1512/1519 vitest pass (7 failures are Redis-down, unrelated).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-01 16:39:51 +02:00
681b94a8ef feat(reports): prior-period comparison toggle on the Sales report
Adds a "Compare to prior period" toggle to the Sales report header.
When on, the API recomputes the KPI window for the equal-length window
immediately preceding the selected range (previousPeriodBounds) behind
`?compare=1`, and the five window-derived KPI tiles (Won, Lost, Win
rate, Avg time-to-close, New leads) render colour-correct "vs prior"
deltas. Point-in-time tiles (Active interests, Pipeline value) have no
prior-window analogue and intentionally show no delta. The prior-window
query runs in parallel with the main batch and resolves to null when the
toggle is off (zero cost). Toggle state persists in the saved-template
config.

Closes the spec's "period comparison on every report" gap for Sales;
Operational already rendered period-start deltas.

Pure helpers TDD'd: previousPeriodBounds (range.ts) +
computeSalesKpiComparison (sales-comparison.ts), 7 unit tests. tsc +
lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 18:49:35 +02:00
172af02f81 feat(residential-toggle): port-level module gate for Residential
Adds a `residential_module_enabled` port setting (default ON) that
hides/disables the entire Residential surface when an admin turns it
off, mirroring the Tenancies / Invoices / Expenses module-toggle
pattern. Disabling is a soft hide — residential clients/interests are
preserved and reappear on re-enable.

Surfaces gated:
- Route guard: new residential/layout.tsx renders ModuleDisabledPage
  (covers all 5 residential pages)
- Sidebar "Residential" section + mobile more-sheet tile (SSR-resolved
  residentialModuleByPort threaded layout → app-shell → sidebar)
- Global search: residential client/interest buckets early-return at
  the shared chokepoint so disabled-port records don't dead-end
- Public intake: /api/public/residential-inquiries 404s when off
- Admin Switch in settings-manager (writes via settings PUT)

Service TDD'd (residential-module.test.ts, 6 tests) plus a
disabled-port rejection test on the public endpoint. tsc + lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-05-31 18:49:16 +02:00
cb8292464c feat(launch-readiness-batch): UAT drains, navigation refactor, launch infra, trackers
Bundles the rest of the in-flight work from this UAT round into one
checkpoint. Each sub-area is independent; see the headings below.

UAT polish (drained 11 findings from active-uat.md):
- Dialog primitive default bumped sm:max-w-xl/lg:max-w-3xl →
  sm:max-w-2xl/lg:max-w-4xl so multi-field forms + PDF previews
  aren't cramped at 1440-1920px.
- Notes tab badge aggregation: new countFor{Client,Yacht,Company}
  Aggregated helpers in notes.service mirror the listFor*Aggregated
  symmetric-reach joins. yacht-tabs + company-tabs render the
  badge; client-tabs already had badge support.
- Supplemental-info form polish bundle: BrandedAuthShell gains a
  `width: 'sm' | 'md'` prop (md uses min-h-dvh scroll instead of
  fixed inset-0 pin so long forms scroll naturally). Form picks up
  port branding (logoUrl + backgroundUrl + appName) via
  loadByToken. Address fields completed (street + city + region +
  postal + country). Port name eyebrow + success-state copy added.
- new-document-menu Upload-file landing toast: per-file completion
  emits toast.success with action link to the destination entity
  or folder.
- interest-tabs OverviewTab "from client" pill on Email + Phone
  rows via new EditableRow `inheritedFrom` prop.
- create-document-wizard subject picker → segmented button strip
  (5 types visible at once).

Launch infra:
- UTM column wiring (Init 1b step 4): migration
  0089_website_submissions_utm.sql adds utm_source/medium/campaign/
  term/content + composite index (port_id, utm_source, received_at)
  for per-campaign rollups. website-inquiries intake accepts the
  five fields. Residential intake intentionally untouched per audit
  scope.
- Invoicing module gate (Init 1c spike): new
  invoices-module.service + invoices layout guard + registry entry
  invoices_module_enabled (default false). Audit conclusion in
  launch-readiness.md: payments table is canonical money path;
  /invoices flow is parallel infrastructure now hidden by default.

Smart-back navigation refactor:
- Replaced breadcrumb component with history-aware Back button.
  New route-labels.ts + use-smart-back hook +
  navigation-history-tracker so back falls through to the parent
  route when there's no prior page in history.
- Sidebar / topbar / mobile-topbar adopt the new pattern; old
  breadcrumb-store kept for back-compat consumers but the
  breadcrumbs component is gone.
- 6 detail pages (admin/errors per-id + codes, invoices/
  upload-receipts, reports kind, tenancies detail, analytics
  metric, client detail) migrated.

Trackers + docs:
- docs/launch-readiness.md — master pre-launch tracker. Includes
  the reports gap audit (cross-cutting filter set, Marketing +
  Financial blockers, custom builder remaining entities, scheduled
  CSV/XLSX, template scope picker).
- docs/superpowers/audits/active-uat.md — 15 findings flipped
  OPEN → SHIPPED locally with fix-applied notes; 4 OPEN remaining
  (each blocked on user input or cross-repo).
- CLAUDE.md — minor session notes carried forward.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 22:42:37 +02:00
3bdf59e917 feat(reports-overhaul): sales + operational + custom reports, templates, schedules, exports
End-to-end reports build covering Phases 1, 2, 5, 6, 7 of Initiative 1
in docs/launch-readiness.md. Phases 3 (Marketing) + 4 (Financial)
remain deferred per the gap audit at the bottom of that doc.

Highlights:
- Sales performance report: 7 KPI tiles, pipeline funnel + stage
  velocity + win-rate-over-time + source conversion + rep leaderboard
  charts, deal-heat section, 5 detail tables, stage / lead-cat /
  outcome filters.
- Operational report: 7 KPIs, 7 charts (heatmap, status mix, tenancy
  churn, tenure histogram, signing box plot, occupancy by area, docs
  in pipeline), 4 tables. Module-OFF banner when tenancies disabled.
- Custom (ad-hoc) builder v1: 4 entities (clients, interests, berths,
  tenancies), column-whitelist composer, date filter, CSV download,
  save-as-template. Registry-only extension path for the remaining 6
  entities documented at src/lib/reports/custom/registry.ts.
- Templates: load / modify / save / save-as on Sales / Operational /
  Custom. ?templateId= URL deep-link hydration via useRef guard.
  Active-template badge clears when the user drives view-state via
  wrapped setters; raw setters used on template apply so the badge
  survives.
- Scheduled runs: BullMQ poll fires due schedules, mints report_runs,
  renders, optionally emails. Recipients optional (zero-recipient
  schedules archive without sending). PDF-only output for v1.
  Schedule dialog re-mounts via key prop on schedule.id transitions
  to avoid setState-in-effect reset patterns.
- Server-side PDF endpoint + shared payload renderer
  (lib/pdf/reports/payload-report.tsx) so client + scheduler share
  one rendering path.
- Shared currency formatter (lib/reports/format-currency.ts)
  consolidates 5 duplicated formatMoney helpers; fixes hardcoded
  'USD' in detail tables; pre-formats money rows so PDF export
  (which strips column.format callbacks at the JSON boundary)
  renders consistently with CSV / XLSX.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-27 22:41:53 +02:00
b6c27b506d feat(documenso-audit-phase-1): persist documensoId early + preflight + state machine + reconciliation + tests
Phase 1 of the comprehensive Documenso upload audit per the
2026-05-26 locked-decisions block in docs/superpowers/audits/active-uat.md.

P1.1 — persist documensoId immediately after create
Was set only at the late `status: 'sent'` commit. Any throw between
documensoCreate and the late update left an orphaned Documenso
envelope the CRM had no link to. Now the UPDATE runs right after
documensoCreate succeeds; rollback paths can find and void the
envelope.

P1.2 — pre-flight validation hard-blocks Submit
UploadForSigningDialog computes a submissionErrors memo over
recipients + fields. Submit button disabled when errors > 0. Inline
amber summary lists every issue (missing email, invalid email,
missing name, field assigned to non-existent recipient, no fields
placed). Service layer mirrors the same email + name checks so
direct API hits reject early. No override path per locked decision.

P1.3 — cancel/delete affordance audit + sweep
Document-list per-row Delete + Send for Signing actions now:
- Wrapped in PermissionGate (documents.delete + send_for_signing).
- Surface toast on success + toastError on failure (were silently
  swallowing errors).
- Use a broader predicate-based query invalidation so every doc
  list across the app refreshes, not just the local key.
EOI tab Regenerate + Cancel EOI buttons + reservation/contract
tab Cancel buttons wrapped in PermissionGate (documents.edit, the
cancel route's auth check).

P1.4 — Documenso webhook URL auto-PATCH (env-gated)
scripts/update-documenso-webhook.ts written. Reads
DEV_AUTO_UPDATE_DOCUMENSO_WEBHOOK env flag (when 1, runs; otherwise
no-op). Lists every webhook on the Documenso instance via v2 (with
v1 fallback), identifies webhooks pointing at trycloudflare.com
hosts OR /api/webhooks/documenso paths, PATCHes them to the new
tunnel URL. scripts/tunnel-url.sh chains the script after the URL
print so a re-tunnel auto-rotates the webhook (when flag set).

P1.5 — state-machine refactor with rollbackTo() helper
custom-document-upload.service.ts:
- Single try around create → send → place steps.
- state.step tracks which step is current; state.documensoDocId
  records the envelope id once we have it.
- rollbackTo(reason) composes the recovery: status='cancelled' on
  the CRM row, documensoVoidSafe on the envelope when applicable.
  Idempotent — calling twice is safe.
- Removes three independent try/catches.

P1.6 — recipient ↔ Documenso identity reconciliation
After documensoSend, validates every distinct email we sent
appears in sentDoc.recipients. If Documenso silently dropped one,
a ConflictError fires before field placement so the rollback path
triggers. Explicit message names the missing emails for the rep.

P1.7 — vitest extension + per-failure audit-log entries
- 5 new vitest cases (blank email, whitespace email, malformed
  email, blank name, duplicate-emails-OK semantic).
- rollbackTo writes a structured audit_log entry with failedStep,
  documensoEnvelopeId, errorClass, errorMessage. Post-mortem
  investigation has structured data instead of just logger lines.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 21:09:50 +02:00
b00cc24565 docs(audit): lock decisions from the 2026-05-26 question round
User answered 11 blocking + clarifying questions across the audit doc.
Decisions inlined as a summary block in the audit doc prelude so any
session reading the doc sees the answers up front before drilling into
individual findings.

Highlights:
- Documenso comprehensive audit ships as 5 discrete sub-PRs.
- Pre-flight validation hard-blocks Submit; no override path.
- `/documents/new` wizard refactor: delete upload branch, drop inapp
  pathway, per-port doc-type template defaults, surface flow 3 from
  dropdown, drop the route entirely.
- Automate Signing: pick-up on mid-flow enable; broadcast to all
  recipients; single combined mode; manual override stays visible.
- Webhook URL auto-PATCH env-flag-gated.
- documenso_signing_order becomes a tri-state setting.
- OverviewTab inheritance writes to interest, prompt to also update
  yacht record.
- Public-map flag inheritance applies across every map-flip dialog.
- Cancel/Delete affordance audit sweeps EVERY remove route.
- Orphan-scan script deferred; dev DB nuke acceptable.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 20:46:21 +02:00
2f1eba3e57 docs(audit): start active-uat.md as the persistent live findings doc
Every UAT finding the user surfaces during a live walkthrough now lands
in docs/superpowers/audits/active-uat.md regardless of which session
captured it. Persists across sessions until the user explicitly says to
wrap a round and archive (rename to YYYY-MM-DD-uat.md, start fresh).

CLAUDE.md's "Manual UAT" guidance updated to point at the new file +
documents the status-tag taxonomy and the append-protocol detail level
(file:line, React-grab anchor, root cause, fix proposal walking each
layer, effort estimate, alternatives + rejection reasons, open
questions, bundle-with notes, cross-refs, acceptance criteria). Historical
alpha-uat-master.md retained as the previous master through 2026-05-26.

This commit seeds the doc with the full body of findings captured during
this live session — Documenso reliability work, dialog width sweep,
recipient UX, recommender card polish, tenancy + notes plumbing, the
larger Documenso upload audit and Automate Signing feature specs. Each
entry follows the detail contract documented in the file footer.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 20:05:47 +02:00
e9509dc45c chore(audit-drain): rip out next-intl, RTL lint, sweeps, polish
Drain the long-tail audit queue captured in alpha-uat-master.md.

- next-intl ripped out (zero useTranslations callers ever existed):
  package.json, next.config.ts plugin wrap, src/i18n/, messages/, and
  the layout NextIntlClientProvider all gone; <html lang="en"> hardcoded.
- RTL lint nudge added: warn-only no-restricted-syntax on physical
  Tailwind utilities (ml-/mr-/pl-/pr-/text-left/text-right/border-l/
  border-r/rounded-l-/rounded-r-) inside JSX className literals.
  Existing ~1,000 sites grandfathered; new code trends toward logical.
- Icon-only button accessibility lint: jsx-a11y/control-has-associated-
  label enabled at warn; 4 empty <th>/<td> action placeholders gain
  sr-only labels.
- Currency: SUPPORTED_CURRENCIES drops the hardcoded English labels;
  new currencyLabel(code, locale?) helper resolves via Intl.DisplayNames.
  CurrencySelect + settings-manager migrated.
- Date locale sweep: 7 surfaces flip from toLocaleString('en-GB'|'en-US')
  to toLocaleString(undefined, ...) so dates honour runtime locale.
- Dialog/Sheet width: 10 document/EOI/entity-form dialogs gain a
  lg:max-w-4xl or lg:max-w-5xl step so wide desktops get breathing room.
- PaymentsSection collapsed-bar: slim one-line bar showing
  "Payments - Not received yet" or "Payments - \$X received - N payments
  - Expand"; per-interest collapse state persists in localStorage; the
  RecordPayment flow auto-expands.
- muted-foreground opacity sweep: 10 text-bearing
  text-muted-foreground/{60,70,80} hits dropped to plain
  text-muted-foreground for AA contrast on muted bg. Icon-only
  (aria-hidden) opacity hits left as-is.
- Micro-type bump: text-[10px] and text-[11px] -> text-xs (12px)
  across 87 files in src/components + src/app. Pure mechanical sweep.
- Audit-doc cleanup: alpha-uat-master.md stale 2026-05-25 summary
  rewritten with cumulative state through today. Items genuinely still
  open are now a short long-tail list.
- New docs/marketing-site-followups.md: Umami Phase 4a/3/5, email
  pixel E2E verification, and website-cutover work parked here so
  they don't get lost in the CRM audit doc.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 18:48:46 +02:00
353a31323e fix(tenancies): unblock first-tenancy chicken-and-egg in webhook
Webhook auto-create on signed Reservation Agreement was gating itself on
isTenanciesModuleEnabled, but autoCreatePendingTenancies never enabled
the module — so the very first tenancy on a fresh port was unreachable
even though the row-exists fallback in isTenanciesModuleEnabled was
designed exactly for this lazy auto-surface case. Drop the gate; the
inserted row now flips the module on automatically via the fallback.

docs/tenancies-design.md §"When disabled" and the P3 PR-table row
updated to reflect the new contract.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-26 18:48:15 +02:00
c549622af4 feat(b3-2): bulk-price editing UI — inline cell + bulk-edit sheet
Lands the UI half of the bulk-price feature (backend already shipped).
Reps with berths.update_prices can retune pricing without unlocking the
rest of the berth schema, both one-at-a-time and in bulk.

- berth-columns: PriceCell wraps InlineEditableField, gated by
  can('berths', 'update_prices'). Click → input → save through
  PATCH /api/v1/berths/[id]/price. stopPropagation so row click
  doesn't navigate while editing.
- bulk-price-edit-sheet: right-side Sheet listing selected berths from
  the React Query cache. Per-row price + currency inputs with dirty-
  highlight. "Set all to" + "Adjust by %" shortcuts. Diff-only POST to
  /bulk-update-prices reports updated/unchanged/missing. Body is keyed
  on the selection so useState initializes fresh per open.
- berth-list: new "Update prices" bulk action gated by the same
  permission, sits between Remove tag and Archive.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 17:44:14 +02:00
dd25ccfb53 fix(tenancies-audit): resolve findings from 7-agent system-wide rename audit
MUST-FIX:
- src/app/api/v1/admin/users/[id]/permission-overrides/route.ts:70 — the
  PUT allowlist still gated `reservations: {view,create,activate,cancel}`.
  Stale: would reject valid `tenancies.{view,manage,cancel}` writes and
  silently accept ghost `reservations.*` writes that never land. Replaced.
- src/lib/services/alert-rules.ts:68 — `reservation.no_agreement` alert
  emitted `entityType: 'reservation'`. Every other tenancy-related
  audit/socket/dashboard label is `'berth_tenancy'`. Inconsistent dedupe
  + activity-feed label miss.
- tests/e2e/exhaustive/08-portal.spec.ts:6 — hardcoded /portal/my-reservations
  navigates to a 404 every run.
- tests/e2e/exhaustive/03-reservations.spec.ts — entire spec renamed to
  03-tenancies.spec.ts; tab + button locators updated to match renamed UI.

SHOULD-FIX (consistency):
- src/components/clients/client-detail.tsx — useRealtimeInvalidation only
  caught 3 of the 4 berth_tenancy:* events; added the `:created` listener.
- src/lib/services/client-merge.service.ts — MergeResult.movedRows.reservations
  + snapshot.reservations + local loserReservations / movedReservations
  renamed to tenancies / loserTenancies / movedTenancies. No external
  consumers grep-confirmed.
- src/lib/services/gdpr-bundle-builder.ts — GdprBundle.reservations field
  renamed to .tenancies; user-facing HTML section "Reservations" → "Tenancies";
  local reservationRows → tenancyRows.
- 6 UI copy strings: gdpr-export-button, bulk-archive-wizard,
  bulk-hard-delete-dialog, hard-delete-dialog, admin-sections-browser ×2,
  admin/import/page, won-status-panel — all "reservations" prose updated
  to "tenancies" (occupancy-record sense).
- tests/integration/api/tenancies.test.ts — handler import aliases
  `createReservationHandler` etc renamed to `createTenancyHandler` etc.
- tests/unit/services/berth-tenancies.test.ts — local helper makeReservation
  → makeTenancyLocal (avoids shadow of the renamed factory).
- scripts/audit-permissions.ts — stale allowlist entry for
  /berth-reservations/[id]/route.ts removed (path no longer exists).
- docs/runbooks/permission-audit.md — stale row for same path removed.
- docs/tenancies-design.md — fixed factual error
  ("tenancies.service.ts" → "berth-tenancies.service.ts").

Verified: tsc clean, 1493/1493 vitest.

Dev-server note: the running `next dev` process started before P2 and
shows Turbopack cached compile errors against the renamed schema files.
Source is correct (./tenancies); restart `next dev` to clear the cache.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 16:03:14 +02:00
4f350d1fbd docs(audit): refresh 2026-05-25 tally with Reports P2 + form-error sweep + Wave G cleanup
Captures the second execution pass:
- Reports P2 CRUD landed on report_runs + report_schedules.
- Form-error sweep complete platform-wide (16 remaining callsites adopted).
- Audit-doc cleanup: dock-letters / email-test / cancelMode were already
  shipped earlier and should not have been listed as queued.

Total ~25 commits across this date; ~110 h still queued for follow-up
(Reports P3-P7, Tenancies P2-P7, UploadForSigning field metadata, B3 wave).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 14:29:04 +02:00
35bd8c45d8 docs(audit): refresh 2026-05-25 tally with B4 sweep + B2 Wave F ships
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 13:16:20 +02:00
13834afa46 docs(audit): tally 2026-05-25 execution pass — shipped vs queued
Top-of-doc status block summarising what landed during the autonomous
execution pass (~12 commits across Bucket 1/2/3/4) + what remains
queued for follow-up sessions. Lets future sessions skip directly to
deferred items without re-triaging.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 04:02:53 +02:00
c7dbe0bb10 docs: lock Reports page + Tenancies module designs
docs/reports-page-design.md: ~400 lines covering
- Routing: /{portSlug}/reports landing + builder/templates/runs/schedules
- 3 new tables (report_templates_shared, report_runs, report_schedules)
  with full schema + indexes
- API surface (12 routes) gated on reports.export / reports.admin
- BullMQ queues (reports-render, reports-email) + cron scheduler
- UI plan for landing + two-panel builder + 3 sub-pages
- Quick-path dashboard button rewire
- 7-PR phased plan (~43h total)

docs/tenancies-design.md: ~350 lines covering
- Vocabulary split (Reservation vs Tenancy)
- Platform-wide module-enabled rule (auto-flips on first insert,
  admin Operations toggle, warning on disable)
- Rename migration berth_reservations -> tenancies + self-FKs
- Tenure-type behaviour matrix (renewals + public-map flip)
- Transfer flow (end + mint linked rows)
- 3 new perms (view/manage/cancel)
- Webhook auto-create branch (gated)
- Public-map status precedence (permanent-class only)
- Sidebar entry + top-level page + entity-tab CTAs
- All 4 reporting widgets (module-gated)
- Service layer additions
- API surface (10 routes)
- 7-PR phased plan (~42h total)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 03:54:32 +02:00
14ae41d0fa feat(uat-b1): ship Wave A-E of Bucket 1 audit findings
Wave A (Interest+EOI form quick wins):
- Auto-select yacht after inline-create from interest form
- EOI generate dialog: "View EOI" action toast
- Interest form berth picker: formatBerthRange compact label
- Remove "Generate EOI" button from Documents tab (clean removal)
- Interest auto-assign: only sales_agent/sales_manager auto-claim
  ownership on create (explicit role check via user_port_roles join)
- LinkedBerthRowItem dims: drop "D" suffix + "L × W" format
- ExternalEoiUploadDialog: prefillSignatories prop threaded from
  active EOI signers
- EOI signature progress on Overview milestone card footer

Wave B (a11y + i18n sweeps):
- aria-live on supplemental-info error state
- text-[10px] -> text-xs in client-pipeline-summary
- Currency formatter: locale default removed (Intl uses runtime)
- en-US/en-GB hardcoded toLocaleString swept across 13 components

Wave C (Primary berth always in EOI bundle):
- Service guard strengthened on update path
- Migration 0083 backfills historical primary rows

Wave D (Onboarding super_admin discoverability):
- /api/v1/admin/onboarding/status endpoint + shared service
- Topbar OnboardingBanner (super_admin, session-dismissible)
- OnboardingTile dashboard widget (rail group, self-hides at 100%)
- Celebration toast + invalidate of shared status on last tick

Wave E (Branded post-completion email idempotency):
- Verified handleDocumentCompleted already owns the email fan-out
- Added regression test for the polling path + idempotency

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 03:40:37 +02:00
41737fa950 feat(audit-session): legacy-stage canonicalization + multi-berth label sweep + PDF/UI polish
Critical data-correctness fixes
- external-eoi.service: stage-advance list rewritten against canonical
  7-stage vocab (enquiry/qualified/nurturing → eoi). Was hardcoded to
  legacy 9-stage names (open/details_sent/in_communication/eoi_sent), so
  EOI uploads from 'qualified' silently skipped the stage flip. Now also
  writes eoiDocStatus='signed' alongside eoiStatus='signed'.
- public-interest.service + api/public/interests/route: pipelineStage
  'open' → 'enquiry' for new public interests.
- interests.service: legacy 'open' gate → 'enquiry'; inline-stage-picker
  comments updated.
- Display fallbacks canonicalized: dashboard.service, dashboard-report-data,
  pdf/templates/{interest,client}-summary, interest-picker, timeline route
  all route through canonicalizeStage / stageLabelFor.

Multi-berth interest label sweep
- New helper src/lib/templates/interest-berth-label.ts with 9 unit tests
  (deriveInterestBerthLabel reuses formatBerthRange + caps at 5 segments,
  falls back to 'first + N more').
- New batched aggregator getAllBerthMooringsForInterests on the
  interest-berths service.
- BoardInterestRow + listInterests + getInterest extended with
  berthMoorings: string[].
- Swept render sites: interest-detail-header, pipeline-card +
  pipeline-column (kanban), interest-columns (list), interest-card,
  interest-detail (breadcrumb), client-pipeline-summary +
  client-interests-tab, yacht-tabs, shared interest-picker.
- PDF report "New interests (in period)" Source column → Berth column.

Dashboard PDF report fixes
- Hardcoded EUR → reads ports.default_currency once at the top of
  resolveDashboardReportData. Falls back to USD.
- 'maintenance' berth-status bucket removed everywhere (wasn't in
  canonical BERTH_STATUSES); cleaned from dashboard.service,
  dashboard-report-data, occupancy-report, berth-status-chart, fixture.
- Berth demand ranking: dropped placeholder Tier column (resolver
  hardcoded 'A' — heat-tier never plumbed through).
- Deal pulse distribution: tier values capitalized (hot → Hot etc.).
- Validator widgetIds.max 20 → 40 (catalog has 25 entries; was throwing
  "Validation failed" when all sections checked).
- Export dialog: badges tightened (text-[8px] py-px whitespace-nowrap, no
  more 2-line wraps on "needs date range"); accepts initialRange?:
  DateRange so the dashboard's active range pre-fills dateFrom/dateTo via
  rangeToBounds.

Interest banner overcounts fix
- interest-berth-status-banner: filters out self-caused under-offer
  berths (where the only active deal touching the berth IS this same
  interest). Waits for all competing-queries before committing the
  count. Was showing "3 berths unavailable" when only 1 actually had a
  competitor.

Sessions list ordering
- sessions-list: client-side sort by lastAt desc + displays lastAt
  instead of firstAt so visible timestamp matches the sort key.

Audit log polish
- Details button: side Sheet → Popover anchored to the button (in-place
  inline dropdown). Works with the virtualized table.
- From/To date pickers: width w-44 → w-52, wrapper gap-3 → gap-x-4 gap-y-3.

EntityFolderView (Documents Hub entity view)
- Per-row Download button (hover-reveal icon).
- File-type icon prefix + tighter row layout.
- Per-row interest-berth badge: files.ts attaches interestBerthLabel via
  one batched getAllBerthMooringsForInterests call across all groups.
  AggregatedFile type + EntityFolderView render the badge linking back
  to the parent interest.

External EOI upload dialog
- Title input pre-fills from the derived default via controlled
  displayTitle = title || defaultTitle (no setState-in-effect).

EOI Generate dialog
- Success toast on mutation success.
- Primary berth's "Include in EOI" checkbox is now forced-on + disabled
  with tooltip: the primary IS the canonical "berth for this deal",
  excluding it is semantically nonsense.

Primary berth must always be in EOI bundle (service + backfill)
- interest-berths.service: insert path forces is_in_eoi_bundle=true
  whenever is_primary=true; update path coerces back to true when the
  caller tries to set false on a primary. Backfilled 7 existing rows.

Documenso redirect URL fallback
- port-config getPortDocumensoConfig: resolution chain extended to
  documenso_redirect_url → public_site_url → null. Operators with
  public_site_url configured (most ports) now get sensible signer
  landing without setting two settings.

World-map click → navigate
- website-analytics-shell: country click navigates to the nationality-
  filtered Clients page via router.push instead of copying a URL to
  clipboard.

Documents Hub: subfolder grid in main panel
- Subfolder cards rendered above the documents list when the current
  folder has children. Lets reps drill into subfolders from the main
  content area, not only via the sidebar tree.

Interest list initial sort
- usePaginatedQuery gains initialSort option (used when URL has no sort
  param). Interest list passes updatedAt desc so the table header
  surfaces the active sort visibly + most-recently-added/edited bubble
  to the top.

Interest auto-assign on create
- interests.service createInterest: three-tier owner resolution chain
  — explicit input → port's default_new_interest_owner setting →
  creator (when not super-admin). Super-admins skipped since they often
  create on behalf of other reps.

Backfills
- 12 interests with eoi_status='signed' + missing eoi_doc_status='signed'
  aligned.
- 7 interest_berths rows with is_primary=true but is_in_eoi_bundle=false
  flipped to true.

Verified
- pnpm tsc --noEmit: clean
- pnpm exec vitest run: 1463 / 1463 passed

Captured 25+ additional UAT findings to docs/superpowers/audits/alpha-uat-master.md
across all 4 buckets, including two OPEN QUESTIONS (Reservations module
re-imagine, Reports dedicated page promotion).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-24 20:41:27 +02:00
70d1e7e9b2 feat(docs): nested-entity 'This deal' / 'From client' split (B4 #8 phase 4)
Finishes B4 #8 by completing the UI half of the per-interest filing
model. Backend foundations (files.interest_id column, ensureEntityFolder
for 'interest', upload-zone scope radio, outcome rename hook, backfill)
shipped earlier in this audit cycle.

- listFiles validator + service: optional interestId filter
- listFilesAggregatedByEntity: routes entityType='interest' to a new
  helper that returns "THIS DEAL" + "FROM CLIENT" + symmetric-reach
  company/yacht groups
- InterestDocumentsTab: Attachments section now renders two cohorts
  via two paginated queries, with client-side de-duplication so files
  filed under this deal don't double-count under "From client"
- FileRow type exposes the optional interestId so the de-dupe filter
  doesn't need a re-fetch
2026-05-23 01:06:45 +02:00
5bd0e1ad9a feat(documents): universal upload-with-fields UI wiring (B3 #11)
Backend foundations were already in place ('generic' CustomDocumentType,
storage-path routing). This wires the UI surface across Documents Hub +
entity file tabs.

- UploadForSigningDialog: interestId now string | null; new entity?,
  folderId?, onCreated? props. Generic path POSTs to new endpoint
  /api/v1/upload-for-signing; interest-scoped paths unchanged.
- uploadDocumentForSigning service: interestId nullable; skips interest
  lookup, pipeline-stage advance, doc-status flip on the generic path.
  Routes file FK + auto-filed folder via either interest.clientId or the
  caller-supplied entity. Validation enforces the matching invariant
  (generic must be interestId=null, type-specific must carry one).
- New menu item in NewDocumentMenu ("Upload & send for signature") on
  Documents Hub root + folder views.
- Upload & send-for-signature button on ClientFilesTab + CompanyFilesTab,
  gated by documents.send_for_signing.

Existing unit tests for the service still pass (validation paths unchanged).
2026-05-23 01:01:52 +02:00
221ae5784e chore(autonomous-session): consolidate uncommitted work from prior session
Bundles the prior autonomous-session output that was sitting unstaged:

- Em-dash sweep across src/ + tests/ (en-dash/em-dash to hyphen, ~2280 instances)
- country-flag-icons rollout (CountryFlag component, replaces emoji glyphs that
  never rendered on Windows; lazy-loads the 3x2 SVG index as a single chunk
  after the per-subpath dynamic-import approach silently failed in webpack)
- Admin IA Phase 1+2: 7-domain regroup, 41 to 38 pages, /admin/berths index,
  redirects (ocr to ai, reports to dashboard, invitations to users),
  docs/admin-ia-proposal.md
- Per-template email tester (registry + endpoint + UI on Email admin page)
- Cancel-document mode picker (delete-from-Documenso vs keep-for-audit)
- Dashboard PDF report: 25 widgets, SVG charts, date-range picker, 11 resolvers
- Customize-widgets per-region sortables at xl+ (charts/rails/feed); single
  flat sortable below xl when the layout stacks; per-viewport saved orders
- Audit doc updates capturing each shipped item
- Lint fixes: react-compiler immutability in DonutChart (reduce instead of
  let-reassign), set-state-in-effect disables in CountryFlag and
  UploadForSigning preview-bytes effect, unused 'confirm' destructures in
  interest contract + reservation tabs, unescaped apostrophe in test-template
  card copy
2026-05-23 00:52:59 +02:00
9ae7940a04 fix(layout): migrate date pickers to useViewportTier mobile-only
All checks were successful
Build & Push Docker Images / lint (push) Successful in 2m33s
Build & Push Docker Images / build-and-push (push) Successful in 6m59s
Final Bucket 1 visual-audit follow-up. Audit of all 4 useIsMobile
callers:
- pipeline-chart.tsx + pipeline-funnel-chart.tsx → keep useIsMobile
  (short x-axis stage labels apply on tablet too — bar charts can't
  fit full "Reservation" / "Deposit Paid" text at narrow widths).
- date-picker.tsx + date-time-picker.tsx → migrate to useViewportTier.
  Tablet (768-1023) has plenty of room for the desktop Popover
  Calendar; only the smallest phone widths now fall back to the
  native datepicker input.

1454/1454 vitest, tsc clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 14:06:50 +02:00
c24f9e5508 docs(uat): annotate the two Bucket 1 layout fixes as SHIPPED in 2f1e1b5
Some checks failed
Build & Push Docker Images / lint (push) Has been cancelled
Build & Push Docker Images / build-and-push (push) Has been cancelled
PageHeader stack point + tablet topbar trigger fixes verified via
Playwright re-screenshot at 768 + 1024.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 14:04:05 +02:00
d0639421bd docs(uat): append visual breakpoint audit findings to master doc
Some checks failed
Build & Push Docker Images / lint (push) Successful in 2m51s
Build & Push Docker Images / build-and-push (push) Has been cancelled
Captured 2026-05-22 from a Playwright MCP pass at 5 viewports × 20
surfaces (375 / 768 / 1024 / 1440 / 1920 px). The tablet tier
infrastructure shipped in 6d665d0 + the dashboard PageHeader
stacking fix lit up the tier — these are the residual bugs the
audit surfaced.

3 Bucket 1 quick-fixes:
- Tablet topbar logo trigger doesn't render visibly (search-bar
  translate shifts over leading slot + center column min-width
  too wide).
- Dashboard PageHeader at exactly 1024 viewport (sidebar present +
  lg:flex-row kicks in, crushing the title).
- useIsMobile call-site audit needed (kept as tier !== desktop
  alias; some sites want strict mobile-only).

4 Bucket 2 mediums:
- Documents Hub folder rail truncates to 3 chars at tablet.
- Website analytics 6-KPI row too cramped at 1024.
- Pipeline Value mobile (375) per-stage rows overflow right margin.
- Berths list 1024 — only 5-6 of 14 columns fit before h-scroll.

Screenshots local at tmp/visual-audit-2026-05-22/ (gitignored).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 13:59:50 +02:00
6af75eda01 docs(uat): backfill SHIPPED markers across master doc
Previous "annotate plan with per-group SHIPPED commits" pass (6aaccb6)
touched only the per-session plan doc; the long-lived
alpha-uat-master.md was missing markers for ~20 ships across Groups
C-T and two regression catches from the current session.

Added markers for: 991e222 (C21+C22+C23 ft/m + bulk), 431375d (D24
wizard ft/m + D25 dock letters + E26 regenerate/resend/history),
94c24a1 (F28 past-milestones + F29 watchers + G30 invitations merge
+ H32 email explainer + H33 branded supplemental email), 989cc4d
(I34 residential header + I35 interests parity + I36 partner forward
+ I37 auto-link), 03a7521 (J38 set-X-to-Y + J39 link company + K40
resolver chain), 65ff596 (L41 upload-for-signing rework), 0ddaf46
(M42 universal preview), a147cbc (N44/45/46), a7cbee0 (O48/52/53/54),
0ed03fc (P56 phases 2/3), c14f80a (Q58/59/61), aa1f5d2 (R62/T64/T65).
Two fresh entries: be261f3 LAN-dev fix, adf4e2b dashboard PDF widget
split.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 13:30:25 +02:00
589be0bfed docs(uat): annotate U66 SHIPPED in plan + master doc
Some checks failed
Build & Push Docker Images / lint (push) Failing after 1m36s
Build & Push Docker Images / build-and-push (push) Has been skipped
Plan item 66 (EOI bundle UX rework) fully closed:
- (a) defaults flip — 05e727f (prior session)
- (b) LinkedBerthsList rename — PR10 (prior session)
- (c) picker inside EoiGenerateDialog — ef37901 (this session)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 13:08:17 +02:00
f6cb733424 docs(uat): annotate M43 + plan with SHIPPED markers
Closes plan item 43 in the remaining-plan doc; alpha-uat-master annotated
with the SHA. Per CLAUDE.md's "annotate the master doc" rule after a
batch ships.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-22 12:53:12 +02:00
6aaccb6d33 docs(uat): annotate plan with per-group SHIPPED commits
Some checks failed
Build & Push Docker Images / lint (push) Failing after 1m56s
Build & Push Docker Images / build-and-push (push) Has been skipped
Stamps the 2026-05-21 plan with the SHA of every group's landed
commit. Groups A through T are worked end-to-end across this
session; Group U (EOI bundle UX rework) is the only remaining
parked item with reasoning in its commit.

Per-group commit notes document what shipped fully vs. what stayed
parked within each group (e.g. Q57 recharts→ECharts deferred,
M43 form-template editor UI deferred, O47-O50 marketing-site
phases deferred). Vitest 1454/1454 + tsc clean across all groups.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 23:53:48 +02:00
a0a4a5d487 docs(uat): annotate master doc for Group B ships (7ecf4ee)
5 master-doc entries now carry the `SHIPPED in 7ecf4ee` line:
  - Interest Overview Email + Phone contact picker (Design A)
  - Inline phone editor on the Contact row (reuses InlinePhoneField)
  - Client Overview interest summary (Wants L × W × D · Source)
  - InterestBerthStatusBanner names + links competing deal
  - Notes Latest-note teaser stage pill (current-stage variant)

2 entries already shipped / no annotation needed:
  - B13 (Inbox embedded filter) — pre-shipped, marker already present
  - B19 (intent auto-confirm on EOI+) — already shipped in 51ca875

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 22:10:17 +02:00
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
a263a202d9 docs(backlog): per-port branded login (section K) + next-env regen
Section K documents the recommended path for multi-tenant branded auth
screens: a single Next.js app behind `*.crm.example.com` wildcard DNS
that derives the active portSlug from the Host header (instead of the
current "first active port wins" fallback in resolveAuthShellBranding).
Includes the open work: wildcard cert, parent-domain cookie scope,
middleware host-resolver, switcher UI, and bootstrap seed.

next-env.d.ts is auto-regenerated by Next typegen with double-quote
formatting; included so the diff stays clean for the next dev session.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-21 19:18:22 +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