148 lines
9.6 KiB
Markdown
148 lines
9.6 KiB
Markdown
|
|
# Handoff prompt for new Claude Code session
|
||
|
|
|
||
|
|
Copy everything below the `---` line into the new chat as your first message.
|
||
|
|
|
||
|
|
---
|
||
|
|
|
||
|
|
I'm continuing work on a comprehensive multi-feature push that was fully designed in a prior session but not yet implemented. The complete plan lives at `docs/berth-recommender-and-pdf-plan.md` (~1030 lines). **Read that file end-to-end before doing anything else — every design decision, schema change, edge case, and confirmed answer to a product question is captured there.** Don't re-litigate decisions; if something seems unclear, the answer is almost certainly in the plan.
|
||
|
|
|
||
|
|
## What the project is
|
||
|
|
|
||
|
|
A multi-tenant marina/port-management CRM at `/Users/matt/Repos/new-pn-crm`. Next.js 15 App Router, React 19, TypeScript strict, Drizzle ORM on Postgres, MinIO for files, BullMQ on Redis, better-auth, shadcn/ui, Tailwind. See `CLAUDE.md` for the conventions.
|
||
|
|
|
||
|
|
## What we're building (high level)
|
||
|
|
|
||
|
|
The plan bundles 8 capabilities into one branch (`feat/berth-recommender`):
|
||
|
|
|
||
|
|
1. **/clients + /interests list-column fix** (the original bug — list views show `-` everywhere because the service didn't join contacts/yachts)
|
||
|
|
2. **Full NocoDB Berths import** + seeding + mooring-number normalization (current CRM has `A-01..E-18`; canonical is `A1..E18`)
|
||
|
|
3. **Schema refactor** to many-to-many `interest_berths` with role flags (`is_primary`, `is_specific_interest`, `is_in_eoi_bundle`)
|
||
|
|
4. **Berth recommender** (SQL ranking, tier ladder, heat scoring, UI panel) — no AI; pure SQL
|
||
|
|
5. **EOI bundle** support (multi-berth EOIs + range formatter for the Documenso PDF: `["A1","A2","A3","B5","B6"]` → `"A1-A3, B5-B6"`)
|
||
|
|
6. **Pluggable storage backend** (s3-compatible OR local filesystem) so admins can run without MinIO if they want
|
||
|
|
7. **Per-berth PDFs** (versioned uploads, OCR-based reverse parser, conflict-resolution diff dialog)
|
||
|
|
8. **Sales send-out emails** (berth PDF + brochure) with full audit + size-aware fallback to download links
|
||
|
|
|
||
|
|
## Phase ordering (from plan §2)
|
||
|
|
|
||
|
|
```
|
||
|
|
Phase 0: Full NocoDB berth import + mooring normalization + 5 new pricing columns
|
||
|
|
Phase 1: /clients + /interests list column fix
|
||
|
|
Phase 2: M:M interest_berths schema refactor + desired dimensions on interests
|
||
|
|
Phase 3: CRM /api/public/berths endpoint + website cutover
|
||
|
|
Phase 4: Recommender SQL + tier ladder + heat + UI panel
|
||
|
|
Phase 5: EOI bundle + range formatter
|
||
|
|
Phase 6a: Pluggable storage backend + migration CLI + admin UI
|
||
|
|
Phase 6b: Per-berth PDF storage (versioned) + reverse parser
|
||
|
|
Phase 7: Sales send-outs + brochure admin + email-from settings
|
||
|
|
Phase 8: CLAUDE.md updates + final validation
|
||
|
|
```
|
||
|
|
|
||
|
|
**Start with Phase 0**.
|
||
|
|
|
||
|
|
## Working tree state at handoff
|
||
|
|
|
||
|
|
- Branch: `main` (you'll create `feat/berth-recommender` from here)
|
||
|
|
- Recent commits (already pushed):
|
||
|
|
- `8699f81 chore(style): codebase em-dash sweep + minor layout polish`
|
||
|
|
- `d62822c fix(migration): NocoDB import safety + dedup helpers + lead-source backfill`
|
||
|
|
- `089f4a6 feat(receipts): upload guide page + scanner head-tag fix`
|
||
|
|
- `77ad10c feat(dashboard): custom date range + KPI port-hydration gate`
|
||
|
|
- `e598cc0 feat(layout): unified Inbox + UserMenu extraction`
|
||
|
|
- `f5772ce feat(analytics): Umami integration with per-port admin settings`
|
||
|
|
- `49d34e0 feat(website-intake): dual-write endpoint + migration chain repair`
|
||
|
|
- Untracked / uncommitted at handoff:
|
||
|
|
- `docs/berth-recommender-and-pdf-plan.md` (the plan — read this first)
|
||
|
|
- `docs/berth-feature-handoff-prompt.md` (this file)
|
||
|
|
- `berth_pdf_example/` (two reference files — see below)
|
||
|
|
- `.env.example` (modified — adds `WEBSITE_INTAKE_SECRET=`; pre-commit hook blocks `.env*` files so user adds this manually)
|
||
|
|
- Dev DB state:
|
||
|
|
- 245 clients (210 with no `nationality_iso` — Phase 1 backfills from primary phone's `value_country`)
|
||
|
|
- 4 test rows in `website_submissions` (from a previous live audit; safe to ignore)
|
||
|
|
- 90 berths with `mooring_number` in `A-01` format (Phase 0 normalizes to `A1`)
|
||
|
|
- vitest: 956 tests passing
|
||
|
|
- tsc: clean (one pre-existing issue in `scripts/smoke-test-redirect.ts` that's unrelated)
|
||
|
|
|
||
|
|
## Reference files
|
||
|
|
|
||
|
|
- `berth_pdf_example/Berth_Spec_Sheet_A1.pdf` (358 KB) — sample per-berth PDF. **0 AcroForm fields** (confirmed via pdf-lib) so OCR with positional heuristics is the primary parser tier; the AcroForm tier is built defensively. Plan §9.2 captures the layout structure.
|
||
|
|
- `berth_pdf_example/Port-Nimara-Brochure-March-2025_5nT92g.pdf` (10.26 MB) — sample brochure. Sized so it ships as an attachment under the 15 MB threshold. Plan §11.1 covers brochure handling.
|
||
|
|
|
||
|
|
## NocoDB access
|
||
|
|
|
||
|
|
You have `mcp__NocoDB_Base_-_Port_Nimara__*` tools available. Tables you'll touch most:
|
||
|
|
|
||
|
|
- `mczgos9hr3oa9qc` — Berths (Phase 0 imports from here; mooring numbers are stored as `A1..E18`)
|
||
|
|
- `mbs9hjauug4eseo` — Interests (the combined client+deal table the old system used)
|
||
|
|
|
||
|
|
## Branch & commit conventions
|
||
|
|
|
||
|
|
- Create the branch: `git checkout -b feat/berth-recommender`
|
||
|
|
- Commit messages match recent history style: `<type>(<scope>): <subject>` lowercase, terse subject, body explains why not what.
|
||
|
|
- **Pre-commit hook blocks any `.env*` file** including `.env.example`. If you need to update `.env.example`, leave it staged and tell the user to commit manually with `--no-verify` (they're aware of this).
|
||
|
|
- **Don't push without explicit user permission.** Commits are fine; pushes need approval.
|
||
|
|
- **Don't run `git rebase`, `git push --force`, or anything destructive without checking.** The branch is solo-owned but the repo's `main` is shared.
|
||
|
|
|
||
|
|
## User communication preferences (from prior session)
|
||
|
|
|
||
|
|
- Direct, no fluff. If something is a bad idea, say so — don't sycophant.
|
||
|
|
- When proposing changes, include trade-offs explicitly.
|
||
|
|
- For multi-question decisions, use `AskUserQuestion` rather than long bulleted lists.
|
||
|
|
- Run validation (vitest + tsc) at logical checkpoints. Don't ship a commit with regressions.
|
||
|
|
- The user prefers small focused commits over mega-commits. Within Phase 0 alone there will probably be 2-3 commits (e.g. mooring normalization, schema additions, NocoDB import script).
|
||
|
|
|
||
|
|
## Critical rules (from plan §14)
|
||
|
|
|
||
|
|
Eleven 🔴 critical items requiring tests before their phase ships:
|
||
|
|
|
||
|
|
1. NocoDB mooring collisions → unique constraint + ON CONFLICT
|
||
|
|
2. Non-PDF disguised upload → magic-byte check
|
||
|
|
3. Recipient email typos → pre-send confirmation
|
||
|
|
4. XSS in email body markdown → DOMPurify + payload tests
|
||
|
|
5. SMTP credentials silently failing → loud error + failed `document_sends` row
|
||
|
|
6. Wrong-environment `CRM_PUBLIC_URL` → health-check env match
|
||
|
|
7. Mooring format drift breaking `/berths/A1` URLs → Phase 0 normalization gates Phase 3
|
||
|
|
8. Multi-port isolation in recommender → explicit `port_id` filter + cross-port test
|
||
|
|
9. Permission escalation on SMTP creds → per-port admin only, no rep visibility
|
||
|
|
10. Filesystem backend in multi-node deployment → refuse to start; documented + health-check enforced
|
||
|
|
11. Path traversal via storage key in filesystem mode → strict regex validation + path realpath check
|
||
|
|
|
||
|
|
## Pending items (from plan §9)
|
||
|
|
|
||
|
|
These are non-blocking but worth knowing:
|
||
|
|
|
||
|
|
- Sample brochure already provided (the 10.26 MB file above).
|
||
|
|
- SMTP app password for `sales@portnimara.com` — not yet obtained; expected close to production cutover. Phase 7 ships the admin UI immediately and the credential gets entered when available.
|
||
|
|
- `CRM_PUBLIC_URL` confirmed as `https://crm.portnimara.com` once live; configurable via env.
|
||
|
|
- GDPR cascade behavior for `document_sends` (delete vs. anonymize-PII vs. keep) — left `OPEN` in §14.10, default lean: anonymize-PII. Revisit when Phase 7 schema lands.
|
||
|
|
|
||
|
|
## Scope reminder
|
||
|
|
|
||
|
|
- **No prod data depends on the current CRM schema** — refactors don't need backwards-compatibility shims. But every schema change still ships as a Drizzle migration with `pnpm db:generate`.
|
||
|
|
- **Pluggable storage** rejects Postgres `bytea` as an option (§4.7a). The two backends are s3-compatible (MinIO/AWS/B2/R2/etc.) and local filesystem. Filesystem is single-node only.
|
||
|
|
|
||
|
|
## What to do first
|
||
|
|
|
||
|
|
1. Read `docs/berth-recommender-and-pdf-plan.md` end-to-end. Don't skim. The edge-case audit in §14 alone is critical context.
|
||
|
|
2. Confirm you've understood the plan by stating back the 8-phase outline and the 11 critical items, then ask the user if they want to proceed with Phase 0.
|
||
|
|
3. Once approved, create `feat/berth-recommender` and start Phase 0.
|
||
|
|
|
||
|
|
Phase 0 deliverables (per plan):
|
||
|
|
|
||
|
|
- One commit normalizing existing CRM mooring numbers from `A-01` → `A1` form (via `regexp_replace` migration). Delete the offending `scripts/load-berths-to-port-nimara.ts`.
|
||
|
|
- One commit adding the 5 new berth columns (`weekly_rate_high_usd`, `weekly_rate_low_usd`, `daily_rate_high_usd`, `daily_rate_low_usd`, `pricing_valid_until`, `last_imported_at`). Run `pnpm db:generate`. Verify `meta/_journal.json` prevId chain stays contiguous.
|
||
|
|
- One commit adding `scripts/import-berths-from-nocodb.ts` — the idempotent NocoDB import (handles updates, preserves CRM-side edits via `last_imported_at vs updated_at` check, `pg_advisory_lock`, dry-run flag, etc. per §4.1 and §14.1).
|
||
|
|
- Update `src/lib/db/seed-data.ts` with the imported berth set so fresh installs get them.
|
||
|
|
- Final vitest + tsc validation at the end of Phase 0.
|
||
|
|
|
||
|
|
## Don't
|
||
|
|
|
||
|
|
- Don't push to remote during this session (user will batch the push later).
|
||
|
|
- Don't commit `.env*` files (hook blocks them anyway).
|
||
|
|
- Don't edit `.gitignore` to exclude generated artifacts; the repo's existing ignores are correct.
|
||
|
|
- Don't add documentation files unless the plan asks for them — the plan itself is the doc.
|
||
|
|
- Don't add features not in the plan. If something seems missing, ask.
|
||
|
|
- Don't use AI for the recommender (plan §1 + §13). Pure SQL ranking.
|
||
|
|
|
||
|
|
Once you've read the plan and confirmed understanding, ask me whether to proceed with Phase 0.
|