Files
pn-new-crm/12-IMPLEMENTATION-SEQUENCE.md
Matt 67d7e6e3d5
Some checks failed
Build & Push Docker Images / build-and-push (push) Has been cancelled
Build & Push Docker Images / deploy (push) Has been cancelled
Build & Push Docker Images / lint (push) Has been cancelled
Initial commit: Port Nimara CRM (Layers 0-4)
Full CRM rebuild with Next.js 15, TypeScript, Tailwind, Drizzle ORM,
PostgreSQL, Redis, BullMQ, MinIO, and Socket.io. Includes 461 source
files covering clients, berths, interests/pipeline, documents/EOI,
expenses/invoices, email, notifications, dashboard, admin, and
client portal. CI/CD via Gitea Actions with Docker builds.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 11:52:51 +01:00

762 lines
47 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Port Nimara CRM — Implementation Sequence & Dependency Map
**Compiled:** 2026-03-11
**Timeline:** 1 month (target)
**Executor:** Claude Code (via Git worktrees for parallel streams)
**Planners:** Codex AND Claude Code — both produce competing medium-level implementation plans per layer/stream. Matt reviews both proposals and selects the best approach (or merges the best parts of each) before development begins.
**Constraint:** Team actively uses current system daily. No partial rollout — everything ships together. NocoDB migration is the final step, executed over a weekend.
**Security posture:** ALL data in this system is highly sensitive — wealthy individuals' personal information, financial records, legal documents, vessel details, internal communications. Security is not a polish layer — it is baked into every layer from Day 1. See "Security Requirements" section below.
---
## Timeline Overview
| Phase | Duration | What |
| --------------------------------------- | ---------- | -------------------------------------------------------------------------------------------------------------------------------------- |
| **Planning** (us + Codex + Claude Code) | Days 15 | Finish high-level docs (us), Codex AND Claude Code each produce competing medium-level implementation plans. Matt reviews and selects. |
| **Layer 0: Foundation** | Days 69 | Project scaffolding, database, auth, base layout |
| **Layer 1: Core CRUD** | Days 1014 | Clients, berths, interests — the three pillars |
| **Layer 2: Business Workflows** | Days 1519 | EOI/signing, expenses/invoices, email, files |
| **Layer 3: Operations & Features** | Days 2023 | Reminders, calendar integration, notifications, search, dashboard, admin |
| **Layer 4: Advanced & Polish** | Days 2427 | New features (webhooks, templates, AI, import/export), dark mode, mobile, QoL |
| **Layer 5: Testing & Hardening** | Days 2528 | Vitest + Playwright, security hardening, performance (overlaps with Layer 4) |
| **Migration Weekend** | Days 2930 | NocoDB data migration, cutover, smoke testing |
---
## Dependency Graph (Visual)
```
LAYER 0: FOUNDATION (sequential — everything depends on this)
├── Project scaffold (Next.js 15, TypeScript, Tailwind, Docker Compose)
├── Database (PostgreSQL + Drizzle ORM — all 49 tables)
├── Auth (Better Auth + multi-port middleware + role system)
├── Infrastructure (Redis, Socket.io, BullMQ, MinIO connection)
└── Layout shell (sidebar, port switcher, navigation, base pages)
LAYER 1: CORE CRUD (3 parallel worktrees)
├── [Stream A] Client management (CRUD, contacts, relationships, notes, tags, duplicate detection)
├── [Stream B] Berth management (CRUD, map data, specs, tags, comparison view, tenure tracking)
└── [Stream C] Auth admin (user management, role builder, port management, onboarding wizard)
LAYER 2: BUSINESS WORKFLOWS (4 parallel worktrees, depends on Layer 1)
├── [Stream A] Interest management (CRUD, pipeline, berth linking, recommendations, waiting list)
├── [Stream B] EOI & Document signing (Documenso integration, 3-party signing, webhook receiver)
├── [Stream C] Expenses & Invoices (CRUD, receipt scanner, invoice generation, payment tracking, exports)
└── [Stream D] File management (MinIO integration, client folders, upload/download/preview)
LAYER 3: OPERATIONS (4 parallel worktrees, depends on Layers 1-2)
├── [Stream A] Email system (SMTP/IMAP, provider presets, thread viewer, composer)
├── [Stream B] Reminders, calendar integration & notification system (reminders, Google Calendar sync, notification center, preferences)
├── [Stream C] Search & views (global search, saved filters, bulk operations)
└── [Stream D] Dashboard & analytics (charts, pipeline summary, revenue forecast, upcoming reminders + calendar events)
LAYER 4: ADVANCED FEATURES (5 parallel worktrees, depends on Layer 3)
├── [Stream A] Webhooks & scheduled reports
├── [Stream B] Document templates & record PDF export
├── [Stream C] AI features (berth spec import, recommendation engine, S3 file migration)
├── [Stream D] Data import/export center & custom fields
└── [Stream E] UX polish (dark mode, mobile responsive, scratchpad, archiving, multi-currency)
LAYER 5: HARDENING (2 parallel worktrees, overlaps with Layer 4)
├── [Stream A] Testing (Vitest unit tests, Playwright E2E tests)
└── [Stream B] Security audit & performance (penetration testing mindset, final hardening pass)
LAYER 6: MIGRATION & CUTOVER (sequential, final weekend)
├── NocoDB data export + transform + PostgreSQL seed
├── MinIO file reorganization (AI-assisted)
├── Smoke testing + security verification
├── DNS/proxy switchover
└── Old system decommission
```
---
## Security Requirements (Mandatory — Every Layer)
**This system stores data about high-net-worth individuals: personal identities, financial records, legal agreements, vessel ownership, and private communications. A breach would expose extremely sensitive information. Security is not optional and not a final polish step — it is a hard requirement enforced at every layer from Day 1.**
### Threat Model
| Threat | Risk | Impact |
| ---------------------------------- | ------ | --------------------------------------------------------------------------------- |
| Unauthorized access to client PII | HIGH | Exposure of wealthy individuals' personal data, yacht ownership, contact details |
| Financial data exposure | HIGH | Expense records, invoice amounts, payment details, banking references |
| Legal document leakage | HIGH | Signed EOIs, contracts, NDAs — legally binding documents with personal signatures |
| Internal communication exposure | MEDIUM | Email threads, notes, internal assessments of clients |
| Session hijacking | HIGH | Attacker gains full CRM access with victim's permissions |
| Privilege escalation | HIGH | Regular user gains admin access, sees cross-port data |
| Data exfiltration via API | HIGH | Bulk extraction of client records through API abuse |
| Injection attacks (SQL, XSS, SSRF) | HIGH | Code execution, data theft, internal network access |
| Insider threat | MEDIUM | Disgruntled employee exports or leaks client data |
| Supply chain attack | LOW | Compromised npm package or Docker image |
### Security Architecture (Built Into Layer 0)
**Encryption at rest:**
- PostgreSQL: `pgcrypto` extension enabled, sensitive columns (email credentials) encrypted with AES-256-GCM before storage
- MinIO: server-side encryption enabled (SSE-S3) — all stored files encrypted on disk
- Redis: password-protected, bound to Docker internal network only (no external access)
- Backups: pg_dump output encrypted before storage in MinIO
**Encryption in transit:**
- TLS 1.3 enforced on nginx (no TLS 1.0/1.1)
- All inter-service communication over Docker internal network (not exposed to host)
- HSTS header with 1-year max-age + includeSubDomains
- MinIO, PostgreSQL, Redis connections use TLS within Docker network where supported
**Authentication hardening:**
- Argon2id password hashing (not bcrypt — Argon2id is the current recommendation)
- Minimum password length: 12 characters
- Rate limiting on login: 5 attempts per 15 minutes per IP, then temporary lockout
- Rate limiting on password reset: 3 requests per hour per email
- Session cookies: httpOnly, secure, SameSite=Strict, CSRF token required on all mutations
- Session timeout: configurable (default 8 hours idle, 24 hours absolute)
- Session invalidation on password change (all other sessions terminated)
- No session data in URL parameters, ever
**Authorization enforcement:**
- Every API endpoint checks permissions via middleware BEFORE any business logic executes
- Port scoping enforced at the database query level (Drizzle query builder), not just application level
- Super admin actions logged with elevated audit detail
- No "god mode" endpoints — super admin still goes through permission checks (just passes them all)
- Object-level authorization: verify the requested entity belongs to the user's current port
**Input validation:**
- Every API endpoint validates input through Zod schemas — no raw user input reaches the database
- Zod schemas define maximum lengths, allowed characters, format patterns for every field
- File uploads: mime type validation (allowlist), file size limits, filename sanitization, malware scanning consideration
- No user input interpolated into SQL (Drizzle ORM handles parameterization)
- HTML sanitization on any rich text input (document templates, notes) to prevent stored XSS
**Output security:**
- API error responses never leak internal details (no stack traces, no SQL errors, no file paths in production)
- Paginated responses capped at configurable max (default 100 records) — no unlimited bulk extraction
- Presigned MinIO URLs expire after 15 minutes (configurable)
- Sensitive fields stripped from API responses where not needed (e.g., email credentials never returned)
**Audit logging (every layer):**
- Every data mutation (create, update, delete, archive, restore, merge) logged to audit_logs
- Every authentication event logged (login, logout, failed login, password change, session creation)
- Every file operation logged (upload, download, delete, rename)
- Every permission-denied event logged (who tried to access what they shouldn't have)
- Audit logs are append-only — no endpoint exists to delete audit entries
- Audit logs include: timestamp, user ID, IP address, user agent, action, entity type, entity ID, old value, new value, port context
**Network security (Docker/nginx):**
- PostgreSQL, Redis, MinIO not exposed to host — only accessible via Docker internal network
- Only nginx exposes port 443 (HTTPS) to the outside world
- nginx rate limiting: global request limit + per-endpoint overrides for sensitive routes
- CORS: strict origin allowlist (CRM domain + website domain only)
- Content Security Policy (CSP) header: restrict script sources, frame ancestors, connect sources
- X-Frame-Options: DENY
- X-Content-Type-Options: nosniff
- Referrer-Policy: strict-origin-when-cross-origin
**Secrets management:**
- All secrets in environment variables (never in source code, never in database)
- .env files excluded from git (enforced in .gitignore + pre-commit hook)
- Docker secrets or bind-mounted env files in production (no env vars visible in `docker inspect`)
- Credential rotation plan documented: which secrets, how to rotate, what breaks if expired
**Data protection policies:**
- Client data export requires `admin.export` permission
- Bulk export operations logged with full detail (who exported what, how many records, when)
- Data deletion is soft-delete only (archived_at) — hard deletion requires super admin + audit entry
- Database backups encrypted and stored in MinIO with 30-day retention
- No client PII in log files (structured logger configured to redact sensitive fields)
### Per-Layer Security Checklist
Every layer's implementation plan (from both Codex and Claude Code) must address:
- [ ] **Layer 0:** TLS configuration, auth hardening, session security, CSRF protection, security headers, Docker network isolation, secrets management, encrypted backup pipeline, audit log middleware
- [ ] **Layer 1:** Input validation on all CRUD endpoints, object-level authorization (entity belongs to port), audit logging for all mutations, XSS prevention in notes/tags, rate limiting on public API
- [ ] **Layer 2:** Documenso webhook signature verification, email credential encryption/decryption, file upload validation and sanitization, receipt image processing isolation, presigned URL expiry, EOI document integrity (no tampering after generation)
- [ ] **Layer 3:** Email content sanitization (inbound HTML emails), reminder permission checks, Google Calendar OAuth token encryption, notification delivery authorization (no sending notifications to wrong users), search result scoping (never return cross-port data), dashboard data scoped to port
- [ ] **Layer 4:** Webhook payload signing (HMAC-SHA256), scheduled report delivery authorization, template merge field injection prevention (no executing code via merge fields), import file validation (CSV/Excel injection prevention), custom field value sanitization
- [ ] **Layer 5:** Security audit — attempt to break every endpoint: auth bypass, privilege escalation, cross-port data leaks, SQL injection, XSS, CSRF, IDOR (insecure direct object reference), rate limit bypass. Fix everything found.
## Layer 0: Foundation
**Duration:** 4 days
**Parallelism:** None — this is the shared base that everything builds on
**Must be complete before Layer 1 begins**
### 0.1 Project Scaffolding (Day 1)
- Initialize Next.js 15 (App Router) project with TypeScript strict mode
- Configure Tailwind CSS with Port Nimara design tokens from `15-DESIGN-TOKENS.md` (brand colors, semantic tokens, typography scale, spacing system)
- Set up shadcn/ui component library
- Docker Compose: `crm-app`, `postgres`, `redis`, `minio`, `documenso`, `nginx`
- Environment variable structure (.env.example with all service connections)
- ESLint + Prettier configuration
- Gitea CI/CD pipeline configuration (build + test stages)
- Project directory structure:
```
src/
├── app/ # Next.js App Router pages
├── components/ # Shared UI components
│ ├── ui/ # shadcn/ui base components
│ └── domain/ # Business-specific components
├── lib/ # Utilities, helpers, constants
│ ├── db/ # Drizzle schema + connection
│ ├── auth/ # Better Auth config
│ ├── services/ # Business logic services
│ ├── queue/ # BullMQ job definitions
│ └── socket/ # Socket.io setup
├── hooks/ # Custom React hooks
└── types/ # TypeScript type definitions
```
### 0.2 Database Layer (Days 12)
- PostgreSQL container with named volume
- Drizzle ORM configuration (connection, config file, migration directory)
- **All 49 table schemas** defined in Drizzle (matching 07-DATABASE-SCHEMA.md exactly)
- Run initial migration to create all tables
- Seed data: default super admin user, default global roles (super_admin, director, sales, readonly), default port (Port Nimara)
- Database utility functions: transaction wrapper, soft-delete helper, port-scoped query builder
### 0.3 Authentication (Day 2)
- Better Auth integration (installed, configured with PostgreSQL adapter)
- Login page (email + password form, CRM-styled — not a redirect)
- Session management (httpOnly cookies, CSRF protection)
- Password set flow (admin creates user → email sent → user sets password)
- Password reset flow (request → email → reset page)
- Auth middleware for API routes (extract session, validate, attach user context)
- Multi-port middleware (extract `X-Port-Id` header, validate user has access, attach port context)
- Super admin bypass (can access all ports)
### 0.4 Infrastructure (Day 3)
- Redis connection (shared across BullMQ, Socket.io adapter, session cache)
- Socket.io server alongside Next.js (port-scoped rooms, user rooms)
- Socket.io client provider (React context, auto-connect on auth, auto-join port room)
- BullMQ queue definitions (10 queues as defined in 11-REALTIME-AND-BACKGROUND-JOBS.md)
- BullMQ worker scaffold (one worker per queue, empty processors to be filled per feature)
- MinIO client initialization (env-based credentials)
- Structured logger (pino) with request ID tracking
- Error handling middleware (consistent error response shape)
### 0.5 Layout Shell (Days 34)
- App layout with sidebar navigation
- Sidebar sections: Dashboard, Clients, Interests, Berths, Expenses, Invoices, Files, Email, Reminders, Admin
- Port switcher component (hidden in single-port mode; shown only when 2+ active ports exist and user has multi-port access)
- Top bar with: user avatar, notification bell (placeholder), search trigger (placeholder), dark mode toggle (placeholder)
- Mobile-responsive nav (hamburger → slide-out sidebar)
- TanStack Query provider with default configuration
- Zustand store for UI state (sidebar collapsed, current port, user preferences)
- Breadcrumb component
- Loading states (skeleton screens)
- Empty states (consistent "no data" patterns)
- Toast notification system
- Confirmation dialog component (used for destructive actions)
**Layer 0 Deliverable:** A running Next.js app with auth, an empty database with all tables, a working layout, and all infrastructure connected. You can log in, see the sidebar, switch ports, and navigate to empty pages.
---
## Layer 1: Core CRUD
**Duration:** 5 days
**Parallelism:** 3 worktrees (Streams A, B, C)
**Depends on:** Layer 0 complete
### Stream A: Client Management (5 days)
**Priority:** HIGH — clients are the anchor entity. Interests and everything else reference clients.
Build order:
1. **Client list page** — paginated table with search, sort, filter by name/nationality/source/archived status
2. **Client detail page** — full record view with all fields, edit inline
3. **Client create/edit forms** — Zod-validated, handles proxy/representative fields
4. **Multi-contact management** — add/edit/remove contact entries (email, phone, WhatsApp, other) with labels and primary flag
5. **Client relationships** — link clients to each other (referral, broker, family, same vessel)
6. **Client notes** — timestamped notes with @mention support, 15-min edit window, then lock
7. **Client tags** — assign/remove color-coded tags, tag filter on list view
8. **Duplicate detection** — on create: same-email auto-merge, fuzzy name/phone match alert with merge UI
9. **Client merge** — select master record, merge contacts/notes/relationships/interests, log to merge_log
10. **Activity timeline** — aggregated feed of all actions related to a client (from audit log)
11. **Audit trail tab** — per-client audit log viewer
**API endpoints:** All 22 client endpoints from 08-API-ENDPOINT-CATALOG.md
**Socket.io events:** `client:created`, `client:updated`, `client:archived`, `client:merged`
**Audit logging:** Every create/update/delete/merge writes to audit_logs
### Stream B: Berth Management (5 days)
**Priority:** HIGH — berths are the product being sold. Website berth map depends on public API.
Build order:
1. **Berth list page** — table with filter by area, status, size range, price range
2. **Berth detail page** — full spec sheet view with all 30+ fields
3. **Berth create/edit forms** — Zod-validated, dual unit display (imperial + metric)
4. **Berth map visualization** — SVG-based interactive map using berth_map_data (click berth → detail)
5. **Berth map data management** — admin can update SVG coordinates per berth
6. **Berth tags** — assign/remove tags, filter on list
7. **Berth comparison view** — select 2-3 berths, side-by-side spec comparison, export as PDF
8. **Berth tenure tracking** — permanent vs fixed-term fields, expiry date display, tenure status indicators
9. **Berth maintenance log** — CRUD for maintenance/repair/inspection entries with photo upload
10. **Berth gallery** — photo gallery per berth from maintenance log photos and uploaded images
11. **Public API** — `GET /api/public/berths` and `GET /api/public/berths/:id` (no auth, CORS, rate limited)
12. ~~**Berth availability calendar**~~ — **CUT FROM V1** (tenure data and expiry checks remain; only the Gantt-style UI is deferred to post-V1)
**API endpoints:** All 22 berth endpoints + 2 public endpoints
**Socket.io events:** `berth:statusChanged`, `berth:updated`, `berth:maintenanceAdded`
**Audit logging:** All berth mutations
### Stream C: Auth Admin (5 days)
**Priority:** HIGH — admin must be able to manage users and roles before the team can use the system.
Build order:
1. **User list page** — all users with status, last login, assigned ports/roles
2. **User create flow** — admin enters name + email → system creates account → sends "set password" email via Poste.io
3. **User edit** — update details, deactivate/reactivate
4. **User port assignment** — assign user to port(s) with role(s), remove assignments
5. **Role list page** — all roles with permission summary
6. **Role builder** — create/edit roles with granular permission toggles (matching 10-AUTH-AND-PERMISSIONS.md permission structure)
7. **Port role overrides** — customize a global role for a specific port
8. **Port management** — create/edit/deactivate ports, port settings (name, slug, branding, currency, timezone)
9. **Permission enforcement** — middleware checks on every API route (matching route protection map from doc 10)
10. **Permission-aware UI** — hide/disable UI elements based on user's effective permissions at current port
11. **System settings page** — key-value settings management (email config, Documenso connection, MinIO connection, backup settings)
**API endpoints:** Admin user (6), admin roles (9), admin ports (6), admin system (9) = 30 endpoints
**Critical dependency:** Poste.io SMTP must be configured for "set password" emails
**Layer 1 Deliverable:** You can manage clients (full CRUD with contacts, notes, tags, duplicate detection, merge), manage berths (full spec sheets, map, comparison, maintenance), manage users/roles/ports, and the public berth API works for the website.
---
## Layer 2: Business Workflows
**Duration:** 5 days
**Parallelism:** 4 worktrees (Streams A, B, C, D)
**Depends on:** Layer 1 Streams A + B complete (clients and berths must exist)
### Stream A: Interest Management (5 days)
**Priority:** CRITICAL — this is the core sales pipeline. The team tracks every prospect through interests.
Build order:
1. **Interest list page** — table with filter by pipeline stage, lead category, berth, client, date range
2. **Interest detail page** — full record view with pipeline stage, berth link, EOI status, milestones
3. **Interest create** — select client (or create inline), optional berth link, set initial stage
4. **Interest edit** — update all fields, manual stage override (system never forces workflow)
5. **Pipeline board view** — Kanban-style drag-and-drop across 8 pipeline stages
6. **Berth linking** — link interest to berth → configurable status rules engine fires (suggest/auto/off per BR-001). Default: suggest "Change to Under Offer?"
7. **Berth unlinking** — configurable rules engine fires (suggest/auto/off). Default: suggest "Reset to Available?" if no other active interests linked
8. **Interest notes** — timestamped notes with @mentions, edit window
9. **Interest tags** — assign/remove tags
10. **Interest milestones** — display and manual edit of all date fields (first contact, EOI sent, signed, etc.)
11. **Berth recommendation engine** — input vessel dimensions → rank berths by fit, power, access, price (BR-050)
12. **Recommendation display** — show ranked berth suggestions with match scores on interest detail
13. **Waiting list** — per-berth queue with position, priority, notification preferences (BR-060 through BR-063)
14. **Lead category management** — manual + auto-classification (general, specific qualified, hot lead)
15. **Public interest registration** — `POST /api/public/interests` (website form → auto-create interest, trigger notifications)
**API endpoints:** All 19 interest endpoints + 1 public endpoint
**Socket.io events:** `interest:created`, `interest:updated`, `interest:stageChanged`, `interest:recommendationsGenerated`, `interest:leadCategoryChanged`
**Business rules:** BR-001 through BR-013, BR-050 through BR-063
### Stream B: EOI & Document Signing (5 days)
**Priority:** CRITICAL — EOI generation and signing is a daily workflow.
Build order:
1. **Document list page** — all documents filterable by type, status, client, interest
2. **Document detail page** — status, signers, signature events timeline
3. **EOI generation** — from interest: validate required data (client name, email, yacht, linked berth) → generate PDF via @pdfme → create Documenso document → assign 3 signers → store signing URLs
4. **Documenso webhook receiver** — `POST /api/webhooks/documenso` with deduplication (signature hash), process DOCUMENT_SIGNED and DOCUMENT_COMPLETED events
5. **Signature status tracking** — real-time updates via Socket.io when webhook fires
6. **Signed PDF retrieval** — on DOCUMENT_COMPLETED: download from Documenso, store in MinIO, email all parties
7. **Manual document upload** — bypass Documenso, upload signed doc directly → update statuses
8. **Signing reminders** — configurable reminder schedule, time-gated (morning/afternoon), per-interest toggle
9. **Signing progress UI** — embedded signing URLs, status per signer, resend capability
10. **Document events log** — created, sent, viewed, signed, completed, expired, reminder_sent
11. **Milestone auto-population** — BR-133: EOI sent → auto-set date_eoi_sent, completed → date_eoi_signed, same for contracts
**API endpoints:** All 12 document endpoints + Documenso webhook
**Socket.io events:** `document:sent`, `document:signed`, `document:completed`
**BullMQ jobs:** Signature polling fallback (every 6 hours — rare safety net, webhooks are primary), EOI reminder check (every 10 min)
### Stream C: Expenses & Invoices (5 days)
**Priority:** HIGH — expense tracking and invoice generation used daily.
Build order:
1. **Expense list page** — filterable by date range, payer, category, payment status, currency
2. **Expense create/edit** — all fields, receipt image upload to MinIO
3. **Receipt scanner (standalone PWA)** — `/scan` route with PWA manifest (`display: "standalone"`), service worker (offline queueing via IndexedDB), minimal UI (no sidebar/nav chrome): capture photo → AI extraction (establishment, amount, currency, date, items) → review → save. `/expenses/scan` redirects to `/scan`.
4. **Multi-currency handling** — store original currency + USD conversion, exchange rate from Frankfurter API
5. **Expense payment tracking** — status, date, method, reference, notes
6. **Expense export** — CSV export, PDF export with receipt images, parent company export (EUR subtotal + 5% fee)
7. **Invoice list page** — filterable by status, date, client
8. **Invoice creation** — select expenses → generate invoice with auto-number (INV-YYYYMM-###), line items, payment terms
9. **Invoice detail/edit** — full view with line items, discount, fees, total calculation
10. **Invoice PDF generation** — @pdfme styled PDF, stored in MinIO
11. **Invoice payment tracking** — status updates, payment recording
12. **Invoice send** — email invoice PDF to billing email via Poste.io
**API endpoints:** Expenses (9) + Invoices (12) = 21 endpoints
**BullMQ jobs:** Currency refresh (every 6 hours)
### Stream D: File Management (5 days)
**Priority:** HIGH — files are attached to everything (clients, expenses, EOIs).
Build order:
1. **File browser page** — MinIO-backed, organized by client folders
2. **File upload** — drag-and-drop + click upload, progress indicator, auto-categorize by context
3. **File download** — presigned MinIO URLs
4. **File preview** — inline preview for images and PDFs
5. **File rename/delete** — with confirmation dialogs
6. **Folder management** — create/rename folders, move files between folders
7. **Client file tab** — on client detail page, show all files for this client
8. **File categories** — eoi, contract, image, receipt, correspondence, misc
9. **File audit logging** — all upload/download/delete operations logged
10. **Socket.io events** — `file:uploaded`, `file:deleted` for real-time updates
**API endpoints:** All 10 file endpoints
**Layer 2 Deliverable:** Full sales pipeline (interests with berth linking, EOI generation, Documenso signing, milestone tracking), expense management with receipt scanner, invoice generation, and file management. This replicates the core of the current system.
---
## Layer 3: Operations & Features
**Duration:** 4 days
**Parallelism:** 4 worktrees
**Depends on:** Layer 2 complete
### Stream A: Email System (4 days)
Build order:
1. **Email account setup** — connect SMTP/IMAP with provider presets (Google, Outlook, custom), encrypted credential storage
2. **IMAP sync** — background job to fetch and store email threads linked to clients (by email address matching)
3. **Email thread viewer** — conversation view on client detail page
4. **Email composer** — TipTap rich text editor (full toolbar + merge fields), send via user's SMTP, auto-link to client thread
5. **Email templates** — MJML template files for system emails (password set/reset, EOI notifications, follow-up reminders, invoice)
**API endpoints:** All 9 email endpoints
**BullMQ jobs:** Email sync (configurable interval)
### Stream B: Reminders, Calendar & Notifications (4 days)
Build order:
1. **Reminder CRUD** — create, edit, complete, snooze, dismiss reminders linked to client/interest/berth
2. **Reminder list page** — filterable by assignee, status, priority, due date, entity. Unified view with Google Calendar events.
3. **Reminder overdue check** — BullMQ job checks for overdue reminders, creates notifications
4. **Follow-up auto-reminder** — BullMQ hourly job checks interest inactivity → creates auto-generated reminders
5. **Google Calendar OAuth** — connect/disconnect flow, calendar list selection, encrypted token storage
6. **Google Calendar sync** — BullMQ background poll (every 30 min) + event-driven sync on login and navigation to calendar-displaying pages (if stale > 5 min). Fetches events, upserts cache, detects CRM-pushed event changes
7. **Push to Calendar** — on reminder create/update with sync toggle, create/update Google Calendar event
8. **Notification center** — bell icon dropdown with unread count, mark as read, link to entity
9. **Notification preferences** — per-user, per-type toggles (in-app, email)
10. **Email notification delivery** — BullMQ sends notification emails via Poste.io
11. **Real-time notifications** — Socket.io pushes new notifications and calendar sync updates instantly
**API endpoints:** Reminders (11) + Google Calendar (7) + Notifications (6) = 24 endpoints
**BullMQ jobs:** Reminder check (hourly), reminder overdue check (every 15 min), calendar sync (every 30 min + event-driven on login/navigation), invoice overdue check (daily), tenure expiry check (daily)
### Stream C: Search & Views (4 days)
Build order:
1. **Global search** — search across clients, interests, berths, expenses, invoices — results grouped by entity type
2. **Search UI** — Cmd+K trigger, recent searches, quick-jump links
3. **Saved filters/views** — on any list page: configure filters → save as named view → reuse
4. **Shared views** — views can be shared with other users
5. **Bulk operations** — select multiple records → bulk status change, tag assignment, export, delete
6. **Bulk job processing** — BullMQ handles bulk ops with progress indicator
**API endpoints:** Search (2) + Saved Views (4) + Bulk (4) = 10 endpoints
### Stream D: Dashboard & Analytics (4 days)
Build order:
1. **Dashboard page** — port-scoped overview landing page
2. **Pipeline summary widget** — count and value per pipeline stage, bar/funnel chart
3. **Recent activity feed** — latest actions across all entities
4. **Berth occupancy widget** — available/under offer/sold breakdown, visual map summary
5. **Expense summary widget** — month-over-month, by category, by payer
6. **Revenue forecast** — projected based on pipeline stages with weighted probabilities
7. **Upcoming reminders + calendar widget** — CRM reminders and Google Calendar events in a unified list, tenure expirations, invoice due dates
8. **Overdue items widget** — overdue reminders, overdue invoices, expired EOIs
**API endpoints:** Dashboard (5) endpoints
**Layer 3 Deliverable:** Email integration, CRM reminders with Google Calendar integration, notification system, global search, saved views, bulk operations, and a full analytics dashboard. The system is now feature-complete for daily use.
---
## Layer 4: Advanced Features & Polish
**Duration:** 4 days
**Parallelism:** 5 worktrees
**Depends on:** Layer 3 complete
### Stream A: Webhooks & Scheduled Reports (4 days)
1. Webhook CRUD (admin: create, edit, delete, enable/disable)
2. Webhook delivery engine (BullMQ, HMAC signing, retry logic, dead letter)
3. Webhook delivery log viewer
4. Scheduled report configuration (admin: create schedule, select type, add recipients)
5. Report generation engine (BullMQ, PDF output, email delivery)
6. Report types: pipeline summary, expense summary, berth occupancy, activity log, overdue items, revenue forecast
### Stream B: Document Templates & PDF Export (4 days)
1. Template CRUD (admin: create/edit/delete templates with TipTap rich text editor)
2. Merge field insertion UI (dropdown to pick field, inserts `{{token}}`)
3. Template generation (select template + context → resolve merge fields → generate PDF)
4. Generated document delivery (download, email, sign via Documenso, store in client files)
5. Record PDF export — client summary, berth spec sheet, interest summary (branded with port logo/colors)
### Stream C: AI Features (4 days)
1. Berth spec sheet import (upload PDF/Excel → AI parsing → preview → confirm → save)
2. Import job tracking (background processing with status updates)
3. S3 file migration tool (scan existing MinIO files → AI-assisted client association → preview → execute)
4. Recommendation engine refinement (additional ranking factors, manual recommendation support)
### Stream D: Data Import/Export & Custom Fields (4 days)
1. CSV/Excel import for clients, interests, berths, expenses (column mapping UI, validation, duplicate detection)
2. Import history log
3. Entity list export (CSV/Excel with configurable columns)
4. Custom field definitions (admin: create per entity type — text, number, date, boolean, select)
5. Custom field rendering on entity forms and detail pages
6. Custom fields in exports
### Stream E: UX Polish (4 days)
1. Dark mode (Tailwind dark classes, toggle in settings, persisted per user)
2. Mobile-responsive refinement (all pages usable on phone/tablet, touch targets)
3. Quick notes/scratchpad (personal notes, drag onto client record)
4. Archiving (archive button on all entity types, archive view in each section)
5. Multi-currency price book (berth prices in USD/EUR/GBP/ECD, auto-convert)
6. Tags system polish (color picker, rename, delete with cascade)
7. Berth availability/tenure calendar (timeline view of tenure periods)
8. Audit export for parent company (bundled report: expenses + receipts + revenue + occupancy)
9. Onboarding wizard for new ports (step-by-step setup flow)
**Layer 4 Deliverable:** All ~82 features implemented.
---
## Layer 5: Testing & Hardening
**Duration:** 4 days (overlaps with Layer 4, starts Day 25)
**Parallelism:** 2 worktrees
### Stream A: Testing (4 days)
1. Vitest setup with test utilities (mock auth, mock port context, test database)
2. Unit tests for all business rule functions (BR-001 through BR-152)
3. Unit tests for permission resolution algorithm
4. API integration tests for critical workflows (create interest → link berth → generate EOI → receive webhook → complete)
5. Playwright E2E setup
6. E2E tests for: login flow, client CRUD, interest pipeline, EOI signing, expense creation, invoice generation
7. CI pipeline integration (tests run on every push)
### Stream B: Security & Performance (4 days)
1. Rate limiting on all public endpoints + auth endpoints (Redis-backed)
2. CSP headers, CORS configuration, security headers via nginx
3. Input sanitization audit (all user inputs pass through Zod, no raw SQL, no XSS)
4. Audit logging final pass (verify every entity type + every action type writes to audit_logs)
5. Query performance audit (N+1 detection, add missing indexes, optimize slow queries)
6. Socket.io connection limits and authentication
7. BullMQ job monitoring (dead letter queue alerting, queue size alerting)
8. System monitoring dashboard (admin: health checks for all services, job dashboard)
---
## Layer 6: Migration & Cutover
**Duration:** 2 days (weekend)
**Parallelism:** None — sequential, careful execution
### Pre-Migration (Week Before)
- Run migration script against a TEST copy of NocoDB data
- Verify all data transforms correctly
- Test the full cutover process end-to-end in staging
- Prepare rollback plan (keep NocoDB running, DNS switch back if needed)
### Migration Weekend
**Friday evening:**
1. Announce maintenance window to team
2. Set current CRM to read-only (if possible) or note the freeze time
3. Take final NocoDB data snapshot
**Saturday morning:** 4. Run NocoDB → PostgreSQL migration script:
- Export all Interests (with all 60+ fields) → transform to `clients` + `client_contacts` + `interests` + `interest_notes`
- Export all Berths → transform to `berths` + `berth_map_data`
- Export all Expenses → transform to `expenses`
- Export all Invoices → transform to `invoices` + `invoice_line_items` + `invoice_expenses`
- Export Audit Logs → transform to `audit_logs`
- Export Reminder/Alert Settings → transform to `system_settings`
5. Run MinIO file reorganization (AI-assisted: scan files → associate with clients → move to new folder structure)
6. Verify data counts match (record counts per entity, spot-check key records)
**Saturday afternoon:** 7. Create user accounts in new system (Better Auth) 8. Assign users to Port Nimara with roles 9. Send "set password" emails to all users 10. Configure Poste.io connection 11. Verify Documenso connection 12. Verify MinIO connection
**Sunday:** 13. Full smoke test — walk through every major workflow: - Log in → navigate dashboard → view client list → open client → check contacts, notes, files - Open interest → check pipeline stage → check linked berth → verify EOI docs - Create test expense → generate test invoice → verify PDF - Search for a client → verify results - Check berth map → verify public API 14. Update website to point at new public API (`GET /api/public/berths`) 15. Update DNS/nginx to point at new CRM app 16. Decommission NocoDB (keep backup, don't delete for 30 days)
**Monday:** 17. Team logs in, sets passwords, starts using new system 18. Matt + dev available for rapid hotfixes if issues found 19. Monitor system alerts, check for errors
---
## Critical Path
The critical path (longest sequential chain determining minimum build time) is:
```
Layer 0 Foundation (4 days)
→ Layer 1 Stream A: Clients (5 days)
→ Layer 2 Stream A: Interests (5 days) [depends on clients + berths]
→ Layer 3 Stream D: Dashboard (4 days) [depends on all entities]
→ Layer 4 any stream (4 days)
→ Layer 5 testing (4 days)
= 26 days minimum + 2 day migration = 28 days
```
This fits within 1 month. The parallel worktrees compress work that would otherwise be sequential — without parallelism, this would take 3+ months.
---
## Risk Mitigations
| Risk | Mitigation |
| -------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------- |
| Layer 0 takes longer than 4 days | Database schema is pre-defined (49 tables). Auth and layout are well-documented. Minimal design decisions left. |
| Worktree merge conflicts | Each stream touches different files/directories. Merge at layer boundaries, not mid-stream. |
| Documenso integration breaks | Test against existing Documenso instance early (Day 15). Keep manual upload fallback. |
| NocoDB data is messier than expected | Run migration script on test copy during Week 3 (before migration weekend). Fix transforms early. |
| Team can't adapt to new system | UI mirrors current system workflows. Same pipeline stages, same EOI flow, same expense structure. |
| Performance issues at scale | Data volume is small (hundreds of berths, thousands of interests). Optimize only if needed. |
| AI features (spec import, recommendations) prove complex | These are in Layer 4. If they slip, everything else already works. Can be post-launch additions. |
---
## Competing Medium-Level Plans (Codex vs Claude Code)
For each Layer and Stream in this document, **both Codex and Claude Code independently produce a medium-level implementation plan**. Matt reviews both proposals, selects the best approach, or merges the best parts of each. This ensures:
- Two different "perspectives" on how to approach each problem
- Codex may propose more structured/formal patterns, Claude Code may propose more pragmatic/battle-tested patterns
- Blind spots from one planner are caught by the other
- Matt gets a real choice, not a rubber stamp
**ALL plans must be produced and approved BEFORE any development begins.**
### What Each Plan Must Cover
Both Codex and Claude Code produce plans with these sections:
1. **Approach** — how to tackle the stream: build order within the stream, key integration points, architectural patterns chosen, and why
2. **Data flow** — for each major feature: user action → API → service → database → real-time event → UI update
3. **Security implementation** — how this stream implements the security requirements below: input validation approach, authorization checks, data protection, audit logging, and any stream-specific threats
4. **Edge cases & failure modes** — race conditions, validation quirks, service integration gotchas (Documenso API behavior, MinIO presigned URL expiry, IMAP connection failures, etc.), and how each is handled
5. **Cross-stream integration points** — where this stream's code touches another stream's code, what interfaces/contracts must be respected, what shared utilities are consumed or produced
6. **Acceptance criteria** — what "done" looks like for each feature, including security verification
7. **Merge strategy** — how this stream's worktree merges back to main, in what order relative to other streams, and what integration tests to run post-merge
### Review Process
1. Codex produces its plan for a Layer/Stream
2. Claude Code produces its competing plan for the same Layer/Stream (independently — not having seen Codex's plan)
3. Matt reviews both side-by-side
4. Matt selects one, or tells Claude Code / Codex to merge specific parts
5. Final approved plan becomes the implementation spec
6. Only then does Claude Code begin building
---
## Client Portal
**Status:** Built last, deprioritized. If time permits within the month, implement basic client portal. If not, it ships in a fast follow-up (not a separate "v2" — just a deferred feature).
Build:
1. Separate auth flow (client accounts created from CRM admin)
2. Client dashboard (their berths, outstanding documents, invoice history, uploaded files)
3. Document signing (embedded Documenso view)
4. Form submissions (data collection forms from CRM)
5. File upload (requested by salesperson)
---
## Appendix: Feature-to-Layer Mapping
Every feature from 06-MASTER-FEATURE-SPEC.md mapped to its implementation layer:
| Feature Spec Section | Layer | Stream |
| ------------------------------ | --------------------------------- | ------ |
| 1. Client Management | L1 | A |
| 2. Interest Management | L2 | A |
| 3. Berth Management | L1 | B |
| 4.14.5 EOI & Document Signing | L2 | B |
| 4.6 Document Templates | L4 | B |
| 4.7 Record PDF Export | L4 | B |
| 5. Expenses & Invoicing | L2 | C |
| 6. File Management | L2 | D |
| 7. Email System | L3 | A |
| 8. Dashboard & Analytics | L3 | D |
| 9. Reminders & Calendar | L3 | B |
| 10. Notification Center | L3 | B |
| 11.1 Global Search | L3 | C |
| 11.2 Saved Filters | L3 | C |
| 11.3 Bulk Operations | L3 | C |
| 12. Admin Panel | L1 | C |
| 13. Audit System | L0 (middleware) + L5 (final pass) | |
| 14. Multi-Port Tenancy | L0 | — |
| 15. Auth & Authorization | L0 + L1C | — |
| 16. Public API | L1 | B |
| 17.1 Berth Spec Import | L4 | C |
| 17.2 Receipt Scanner | L2 | C |
| 17.3 Recommendation Engine | L2 | A |
| 17.4 S3 File Migration | L4 | C |
| 18. Data Import/Export | L4 | D |
| 19. Webhooks | L4 | A |
| 20. Scheduled Reports | L4 | A |
| 21. System Monitoring | L5 | B |
| 22. Client Portal | L4+ (deprioritized) | — |
| 23.1 Mobile Responsive | L4 | E |
| 23.2 Dark Mode | L4 | E |
| 23.3 Quick Notes | L4 | E |
| 23.4 Tags | L1 | A+B |
| 23.5 Archiving | L4 | E |
| 23.6 Multi-Currency | L4 | E |
| 23.7 Audit Export | L4 | E |