Matt d32e557e56 feat(tenancies-renew-transfer): tenure-aware renewal + transfer actions
- renewTenancy service:
  - permanent / fee_simple / strata_lot → mutate-in-place (startDate
    moves forward, endDate may extend or null out)
  - fixed_term / seasonal → end the current row at its existing endDate
    + mint a successor with previousTenancyId chain. newEndDate required.
- transferTenancy service: end-and-spawn — end current row at
  transferDate, mint fresh active row with transferredFromTenancyId
  pointing back. New client + yacht cross-validated against port +
  ownership constraint (assertClientOwnsOrRepresentsYacht).
- POST /api/v1/tenancies/[id]/renew + /transfer routes gated on
  tenancies.manage + module-enabled.
- TenancyRenewDialog (tenure-aware copy explains in-place vs successor),
  TenancyTransferDialog (ClientPicker + YachtPicker with owner-scoped
  filter). Both mounted on tenancy-detail.tsx alongside Edit + End.
- Validators: renewTenancySchema + transferTenancySchema in
  src/lib/validators/tenancies.ts.

Verified: tsc clean, 1493/1493 vitest.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 17:13:34 +02:00
Description
No description provided
25 MiB
Languages
TypeScript 98.7%
HTML 1%
CSS 0.1%
Shell 0.1%