Estate-Level Prediction Offsets
Per-estate overrides for the title-prediction and street-addressing offset windows
Overview
Two numeric offsets control the platform's predicted-title-date calculation:
- Title offset days - how many days to add to a parcel's Statement of Compliance (SOC) date to estimate title.
- Street addressing offset months - the fallback window when SPEAR has a street-addressing milestone but no SOC.
Before 3.8 these were global env-var-or-default values (28 days / 9 months). Different estates have radically different cadences - some consistently title 14 days post-SOC, others closer to 60 days. One global default produced wrong predictions for almost every estate.
Release 3.8 makes both offsets per-estate configurable, with env-var and hardcoded-default fallbacks in that order.
What Changed
Estate entity gains two fields
On the Estate entity:
$titlePredictionDays(existing field, now authoritative) - nullable integer. Per-estate override for SOC-plus-N-days. Falls back toTITLE_PREDICTION_DAYSenv var, then28.$streetAddressingOffsetMonths(new in 3.8) - nullable integer column added viadoctrine:schema:update. Per-estate override for Street Addressing-plus-N-months fallback prediction. Falls back toSTREET_ADDRESSING_OFFSET_MONTHSenv var, then9.
Both fields are editable on the Estate CRUD form in EasyAdmin. A NULL value means "use the fallback chain".
Enrichment flow refactor
ProjectInsightEnrichmentService::enrich() now resolves both offsets from the estate (using the fallback chain) and passes them as query parameters to dossier-api:
GET https://dossier-api.ftsonline.com.au/api/insights?spi=...&titleOffsetDays=28&streetOffsetMonths=9dossier-api owns the date math - the platform is a pure consumer. The platform does not perform any SOC-plus-N or street-plus-N arithmetic itself. This keeps the rule "dossier-api is the source of truth" intact.
dossier-api consumes the overrides
dossier-api parses titleOffsetDays and streetOffsetMonths from the URL and falls back locally to TITLE_PREDICTION_DAYS / STREET_ADDRESSING_OFFSET_MONTHS env vars, then to the same hardcoded defaults. Neither side of the pipe relies on the other for the fallback chain; both enforce their own.
Why not persist the resolved offsets on the project
Tempting to compute and store the offsets at project save time. Rejected because:
- Estate-level offset changes would then require re-saving every project to take effect.
- Dossier-api already caches insights per SPI - recomputing offsets on each call is cheap.
- Estate offsets change rarely enough that query-param on every enrichment call costs nothing.
Related
- Daily SPEAR Refresh Cron - the cron that exercises these offsets every 24h
- Enrichment Guard Rails - the checks that stop bad offset math from producing bad output