0074 — Detect tenant transfers vs move-outs (don't turn a transfer into a move-out)

Context

How a move-out becomes a turnover today (verified from code, 2026-07-01). A notice-to-vacate / move-out tenant_status change on an AppFolio occupancy is ingested by the sync and parsed (src/lib/integrations/appfolio/email-ingestion/parse-appfolio-ntv.ts, handle-appfolio-ntv.ts); the ntv / decline-renewal-on-ntv automation handlers (src/lib/domain/automations/handlers/) mark the occupancy former, and the turnover bridge auto-creates a turnover whose move-out inspection is a move_out ConditionReport (ADR-0034 slice 3, captureMoveOutInspection). There is no transfer-awareness anywhere in this path — any move-out/NTV is treated as a terminal departure.

What a transfer actually looks like in our data (verified from live prod, 2026-07-01, on two real Camellia transfers).

Root cause

The move-out → turnover path commits a move-out (spurious move-out inspection + turnover, and downstream the wrong deposit handling — a transfer's deposit carries to the new unit, it is not disposed) whenever an NTV/move-out fires, without checking whether the same person has (or is about to have) an occupancy at another unit in the same property.

Decision

Classify move-out vs transfer at the point the move-out/NTV signal is turned into a turnover, using our own personId as the correlation key.

Entity classification (see ADR-0027)

No new canonical entity. This adds a classification branch plus a link field on the existing TenantOccupancy.

Entity Class Naming Spine trace / derived-from
TenantOccupancy.transferredToOccupancyId / .transferredFromOccupancyId (new fields) canonical bare field Spine trace: via personId directly; single writer = the occupancy sync/classifier
TenantTransfer (optional, deferred) derived * (audit record) from: the source+destination TenantOccupancy pair · Rebuilt by: the classifier on sync · Drift tolerance: ≤ one sync cycle. Add only if a first-class audit/reporting surface is later needed.

Consequences

Alternatives considered

Verification