First slice of Phase 3 (Epics B/C/D shipped as stacked sub-PRs). Adds the
CrewMember talent-pool spine and the Candidates screens. Behind
NEXT_PUBLIC_CREWING_ENABLED; production unchanged. Stacks on the requisitions
branch (Phase 2).
What's in
- Schema (crewing_candidates migration): CrewMember (spine) + CrewStatus,
CandidateType, CandidateSource enums; CrewAction gains a nullable crewMemberId;
CrewActionType += CANDIDATE_ADDED/UPDATED. employeeId is assigned at onboarding
(3c), so it's nullable here.
- Actions (crewing/candidates/actions.ts): addCandidate / updateCandidate —
guard flag + manage_candidates, write a CrewAction, optional CV upload via
buildStorageKey("cv", …) + uploadBuffer (no parsing — A2 deferred). EX_HAND
source ⇒ type/status EX_HAND; edits never downgrade an EMPLOYEE.
- Screens: /crewing/candidates (master list with search/source/rank-applied/
min-experience filters as removable chips + match count + Clear all; Add-candidate
modal) and /crewing/candidates/[id] (profile; pipeline stepper is 3b). Candidates
added to the flag-gated Crewing nav (Manager + MPO).
Tests & docs
- Integration: candidates.test.ts (7) — add/update, ex-hand derivation, employee
no-downgrade, permission gating. type-check clean; full unit (225) + integration
(153) suites green.
- CLAUDE.md "Crewing" section updated with the Phase 3a surface.
Deferred: public careers intake API (A2, §13 open question); CV parsing.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Companies can upload a logo and a stamp/seal (Admin → Companies → Edit →
Branding); both render on exported PDF and XLSX purchase orders. A fixed
brand-colour bar (#92D050, matching the sample PO) runs along the bottom of
every export.
- Company.logoKey / stampKey + migration
- buildCompanyAssetKey() deterministic storage keys (overwrite-in-place)
- uploadCompanyAsset / removeCompanyAsset server actions (≤4MB PNG/JPG/WebP,
manage_vessels_accounts gated)
- CompanyBrandingUploader in the company edit dialog with live previews
- Export route embeds logo (top-left), stamp (signatory block) and brand bar
in both ExcelJS and print-HTML paths
- Unit test (storage keys) + integration test (branding actions)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>