mirror of
https://github.com/Hestia-Homes/assessment-model.git
synced 2026-07-12 13:28:55 +00:00
The docs/adr/** ignore rule silently ate ADRs 0004-0006 that CONTEXT.md still references. Remove it so decisions actually land in the repo. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
2.9 KiB
2.9 KiB
7. Postcode search creates Properties directly, with OS-derived overrides
Date: 2026-07-06
Status
Accepted
Numbering note: 0003 is taken by the app-authored-scenarios ADR (PR #353);
0004–0006 are referenced by CONTEXT.md but were lost to a docs/adr/**
.gitignore rule (removed in this commit). 0007 avoids all collisions.
Context
Properties previously came into existence only via the BulkUpload finaliser or the backend pipeline. The "Postcode search" journey (CONTEXT.md) lets a user search a postcode (postcodes.io for validation + geography, OS Places for addresses) and add selected addresses to a Portfolio directly — before any modelling exists.
Decision
- Next.js inserts
propertyrows directly: address, postcode, uprn, per-property lat/lng, local_authority (postcodes.ioadmin_district), constituency (postcodes.ioparliamentary_constituency). Nothing inferred — no type/age/tenure guesses on the row. Energy state is derived: no EPC-graph rows ⇒ "awaiting modelling" (mirrors ADR on app-authored scenarios). - Dedup rides the existing partial unique index
uq_property_portfolio_uprnviaON CONFLICT DO NOTHING; the submit reports added vs already-existed. - Both override layers are written, mimicking the finaliser: a
VocabularyMapping upsert per distinct OS classification code and a
property_overridessnapshot per property (original description = the OS code). Newoverride_sourceenum valueos_places— the deterministic OS-code mapping is not the LLM "classifier" and provenance must stay distinguishable. - Deterministic mapping (fixed table, tested): RD02→House+Detached,
RD03→House+Semi-Detached, RD04→House (Mid/End unknowable — no built form),
RD06→Flat, RD07→House. Every other code maps nothing;
Unknownis never written (absence, not noise) — preserving the finaliser's invariant. The backend's predict-EPC service consumes these for archetype matching. - Read-through cache on the existing
postcode_searchjsonb table: serve when fresher than 30 days, else refresh from OS Places and upsert.
Alternatives considered
- Routing through the BulkUpload pipeline (synthesise a one-postcode "upload"): full provenance for free, but drags an interactive journey through an async multi-stage state machine built for files.
- Property row carries property_type directly: bypasses the override layers the Model backend actually consumes, and creates a second source of truth.
Consequences
- A third Property creator exists; anything assuming "property ⇒ came from a BulkUpload or the backend" is now wrong.
property_overridesgains a second writer withos_placesprovenance; re-classification tooling must not clobber user rows (existing rule) nor treat OS rows as user-authored.- Postcode-search-created properties render blank/awaiting-modelling in the portfolio table and reporting until a scenario is modelled against them.