Leon Capital Group · Technology & AI

Real Estate Intelligence Platform
Data Model v2.1

Canonical schema for the fully agentic deal lifecycle — from origination through closing — across Industrial, Multifamily, Office, Retail, and Land. Aligned to the Agent Creation Playbook, ADRs 0001–0003, and the IN-01 pilot: four-tenant RLS isolation, governed metrics via dbt MetricFlow, role-based approvals, and classification-driven tier routing. v2.1 adds the upstream Origination and Capital Markets domains.

8 Domains
4 Isolation Tenants
Sourcing → Closing
Metrics via MetricFlow
June 2026

Three Governance Concepts

Conflating these is the most common modeling mistake. Every table carries the first two; the third is deal data. Keeping them separate is what makes RLS, tier routing, and legal-entity reporting independently correct.

tenant_id
Isolation boundary
coe · mf · industrial · healthcare. The Postgres RLS key, sourced from the JWT — who may see the row. Never trusts a client header. Enforced by OPA 8×4 (role × module × tenant).
data_classification
Sensitivity label
internal · confidential · restricted_mnpi. A label that routes the handling agent to a deployment tier (1 relay / 2 ACA / 3 air-gapped). It is not itself a tier.
entity_owner_id
Legal owner · FK
FK → ref_entities. The legal entity holding the asset (balance-sheet LLC, fund vehicle, JV). One tenant transacts across many entities — so this is independent of tenant_id.
📐 Governed metrics are not stored as authoritative columns
NOI, DSCR, LTV, cap rate, IRR, equity multiple, and waterfall yield are computed by dbt MetricFlow over the input assumptions the tables store. Tables hold inputs; MetricFlow is the single metric source of truth. This prevents the "two NOIs that silently disagree" failure that the metric boundary exists to stop. (Platform Baseline · ADR 0003.)

Origination → Deal Pipeline

▸ Origination funnel (pre-intake) — leads, not yet deals
🔭
Source
(off-market/broker)
📡
Scout &
Score
🔎
Pre-Screen
+ AVM
🚦
Advance
/ Pass
📥
Document
Intake
📊
Under-
writing
🛡️
Compliance
Screen
🏦
Treasury
Decision
📝
Closing
Checklist
Asset Mgmt
Handoff
Gold = origination funnel (origination_leads); a lead advances into a deal
Versioned stages keep full revision history
Every stage boundary (incl. lead-advance) is a row in approval_log
MNPI stages route to Tier 3 (air-gapped)
Capital Markets (co-invest / leverage / rate intel) runs parallel to this lifecycle

Domain Architecture

🗃️
Reference Domain v2
Anchors for the isolation key, legal ownership, and RBAC sign-off. Small, slowly-changing; the target of every FK and the RLS predicate.
ref_tenants ref_entities ref_roles
🔭
Origination Domain v2.1
Pre-intake funnel. Leads are sourced, scored against the buy-box, pre-screened, and given an early AVM read. A lead that advances becomes a deal — most die in the funnel. Origination / Acquisitions / Capital Markets work here.
buy_box_criteria origination_leads lead_sources lead_screening lead_activity
🏗️
Deal Domain
Primary schema. The deal lifecycle from intake through closing — a deal enters when a lead advances (origination_lead_id links back). All agents read/write here; every table links via deal_id and carries tenant_id.
deals property_basics financial_snapshot tenants_rentroll underwriting_assumptions legal_review compliance_screen treasury_decision closing_checklist
📄
Document Store Domain
Every raw OM, rent roll, and broker doc ingested. The Document Intake Agent (archetype ②) writes confidence-scored extraction results here.
deal_documents extraction_results
💵
Capital Markets Domain v2.1
Runs parallel to the deal lifecycle, not as a stage gate. Co-investor matching, back-leverage sourcing, and rate/spread execution windows. Outputs are drafts/advisory — humans send and decide.
coinvestor_prospects leverage_matches capmarkets_intel
📈
Market Intelligence Domain
Green Street and comparable-sale reference data. Submarket aggregates are tenant-global. Underwriting agents query here for benchmarks.
market_comps submarket_trends green_street_snapshots
🏢
Asset Management Domain
Existing schema (Leon Industrial). Post-close operational data. A closed deal transitions here at closing.
assets rent_roll property_pnl capex_tracker
🔐
Audit & Compliance Domain
Cross-cutting. Every agent write and every human approval logged, then WORM-replicated to ADLS Gen2 Delta (SEC 17a-4). Append-only.
audit_trail approval_log

Entity Relationship Diagram

Layered layout, left → right: the Origination funnel feeds deals (center hub) via the advance arrow; deal-domain children sit left, versioned stages and Capital Markets sit right. All connectors are orthogonal and enter deals at distinct anchor points — no crossings. Dashed red = the tenant_id RLS scope that applies to every table.

ADVANCE (lead → deal) 1:1 1:1 1:N 1:N (docs) 1:N [versioned] RLS scope (all tables) entity_owner_id N:1 1:N 1:1 parallel (co-invest / leverage) buy_box_criteria buy_box_id PK · version asset_classes, markets, hurdles origination_leads lead_id PK tenant_id 🔒 · buy_box_id FK stage · fit/health scores lead_screening / sources / activity *_id PK · lead_id FK pre-screen · AVM (Green St) screening versioned ref_tenants tenant_id PK coe · mf · ind · hc key_vault_ref postgres_schema ref_entities entity_id PK tenant_id FK entity_legal_name entity_type ref_roles role_id PK 8 RBAC roles can_approve_stages audit_trail · approval_log All agents write · append-only approval_log keyed by approver_role → WORM ADLS Gen2 Delta (17a-4) approver_role FK → ref_roles deals deal_id UUID PK tenant_id ENUM 🔒 RLS origination_lead_id FK entity_owner_id FK asset_class · deal_stage data_classification property_basics property_id PK · deal_id FK tenant_id 🔒 address, sqft, dims… financial_snapshot snapshot_id PK · deal_id FK stated_* (broker inputs) not governed metrics tenants_rentroll rentroll_id PK · deal_id FK lessee_name, lease_terms (renamed from tenants) deal_documents → extraction document_id PK · extraction_id PK deal_id FK OM, rent_roll, PSA · confidence underwriting_assumptions underwriting_id PK · deal_id FK version [versioned] inputs: vacancy, growth… ⚠ metrics via MetricFlow legal_review legal_review_id PK · deal_id FK version · title, entity_structure ⚠ privileged_content_flag sign-off → approval_log compliance_screen compliance_id PK · deal_id FK version · mnpi_flag lp_conflicts, sanctions sign-off → approval_log treasury_decision treasury_id PK · deal_id FK version · entity_owner_id FK equity, debt, escrow sign-off → approval_log closing_checklist closing_id PK · deal_id FK (1:1) deed, funds, wire_confirm → asset mgmt handoff Capital Markets coinvestor_prospects · leverage_matches deal_id FK · capmarkets_intel co-invest / back-leverage / rates drafts/advisory · runs parallel LEGEND PK primary key FK foreign key 🔒 tenant_id RLS key (all tables) FK relationship lead → deal advance RLS isolation scope capital markets (parallel) Versioned: UW · legal · comp · treasury

Full Schema Reference

Click any table header to expand its field definitions. 🔒 RLS marks the tenant_id isolation key present on every operational table. v2 marks columns/decisions changed during the alignment pass.

buy_box_criteria 16 columns v2.1 · new Origination Domain · versioned
Leon's acquisition criteria, versioned per tenant. The Scout (AI-25) matches leads against the active version; scoring cites the version used. Never delete prior versions.
ColumnTypeRequiredNotes
buy_box_idPKUUID
tenant_idFK🔒 RLSENUM→ ref_tenants
buy_box_versionINTEGERIncrements on revision
is_activeBOOLEANExactly one active version per tenant
asset_classesJSONBJSONBe.g. ["industrial","multifamily"]
target_marketsJSONBJSONBMSAs / submarkets in scope
min_deal_size · max_deal_sizeBIGINTcents
min_cap_rateDECIMAL(5,4)Going-in cap-rate floor
target_irrDECIMAL(5,4)Return hurdle
target_hold_period_yearsDECIMAL(5,2)
excluded_criteriaJSONBJSONBHard exclusions (flood zone, ground lease…)
effective_dateDATEWhen this version took effect
set_byVARCHAR(255)Originator / IC who set it
data_classificationENUMconfidential
origination_leads 26 columns v2.1 · new 🔒 RLS Origination Domain · the funnel unit
One row per lead — a potential opportunity before it becomes a deal. Most leads die here. On advance, a deals row is created with deals.origination_lead_id = lead_id; the lead is not deleted (it stays the funnel record). The advance is a row in approval_log (approval_stage = origination).
ColumnTypeRequiredNotes
lead_idPKUUIDCarried onto deals.origination_lead_id on advance
tenant_idFK🔒 RLSENUM→ ref_tenants
lead_nameVARCHAR(255)e.g. "Eastvale Logistics — off-market"
asset_classENUMENUMSame enum as deals; nullable early
lead_stageENUMENUMsourced, scouting, screening, advanced, passed, dead
lead_statusENUMENUMactive, on_hold, advanced, rejected
source_typeENUMENUMoff_market_scan, broker, referral, inbound, direct, relationship
street_address · city · state · submarket · msaVARCHARMay be approximate / undisclosed early
estimated_deal_sizeBIGINTcents — rough early sizing
buy_box_idFKUUID→ buy_box_criteria · version scored against
buy_box_fit_scoreDECIMAL(5,2)0–100, set by RE-OffMarket-Scout
pipeline_health_scoreDECIMAL(5,2)0–100, set by RE-Pipeline-Scout
next_best_actionVARCHAR(500)RE-Pipeline-Scout recommendation (advisory)
assigned_originatorVARCHAR(255)Owning originator / acquisitions lead
broker_name · broker_contact_emailVARCHAR(255)If broker-sourced
sourced_dateDATEWhen the lead first appeared
advanced_dateDATEWhen promoted to a deal
pass_reasonTEXTWhy killed — kept for funnel analytics
data_classificationENUMconfidential
lead_screening 17 columns v2.1 · new (versioned) 🔒 RLS Pre-screen + early AVM
Pre-screen output (RE-PreScreen-Writer AI-08) + early AVM read (RE-AVM-Valuer AI-22). Versioned. AVM values are Green Street provenance-tagged inputs; LCG's own cap rate / IRR are still computed by MetricFlow at underwriting, never hand-stored.
ColumnTypeRequiredNotes
screening_idPKUUID
tenant_id · lead_idFK🔒ENUM / UUID→ ref_tenants · origination_leads
screening_versionINTEGERIncrements on re-screen
screening_statusENUMENUMdraft, complete, advance_recommended, pass_recommended
headline_economicsJSONBJSONBEarly figures as captured — inputs, not governed
market_fit_notesTEXTRE-PreScreen-Writer narrative
risk_flagsJSONBJSONBEarly risk flags
avm_value_estimateBIGINTGreen Street AVM point estimate, cents (source = green_street_avm)
avm_value_low · avm_value_highBIGINTAVM range, cents
avm_as_of_dateDATE
screening_memo_doc_idFKUUID→ deal_documents · generated PDF/PPTX memo
recommendationENUMENUMadvance, pass, hold
data_classificationENUMconfidential
lead_sources · lead_activity v2.1 · new 🔒 RLS Provenance + touchpoint log
lead_sources records which signals/channels surfaced a lead (one lead, many sources) — lets you measure which channels produce advancing leads. lead_activity is the touchpoint log feeding RE-Pipeline-Scout's staleness scoring and RE-Broker-CRM's follow-ups.
ColumnTypeRequiredNotes
── lead_sources ──
source_idPKUUID
tenant_id · lead_idFK🔒ENUM / UUID→ ref_tenants · origination_leads
source_agentVARCHAR(100)RE-OffMarket-Scout, RE-Broker-CRM
source_channelENUMENUMcrexi, green_street, web_signal, broker_email, crm, referral, manual
signal_payloadJSONBJSONBRaw signal that triggered the lead
signal_strengthDECIMAL(5,2)Agent confidence in the signal
── lead_activity ──
activity_idPKUUID
tenant_id · lead_idFK🔒ENUM / UUID→ ref_tenants · origination_leads
activity_typeENUMENUMoutreach, call, email, meeting, site_visit, note, status_change
activity_date · actor_idTIMESTAMP / VARCHARWhen + who (user or agent)
summaryTEXTWhat happened
suggested_followupVARCHAR(500)RE-Broker-CRM / Pipeline-Scout suggestion (advisory)
ref_tenants 5 columns v2 · new Reference Domain · isolation anchor
The four isolation boundaries. RLS is scoped on tenant_id, which matches the Entra ID JWT claim. Every operational table FKs its tenant_id here.
ColumnTypeRequiredNotes
tenant_idPKENUMENUMcoe, mf, industrial, healthcare
tenant_display_nameVARCHAR(100)"Center of Excellence", etc.
key_vault_refVARCHAR(100)kv-coe / kv-mf / kv-ind / kv-hc
postgres_schemaVARCHAR(100)Per-tenant RLS schema name
created_atTIMESTAMP
ref_entities 6 columns v2 · new Reference Domain · legal ownership
Legal ownership entities. entity_owner_id columns are FKs to this table — replacing v1's free-text entity_owner enum. Ownership is a separate axis from tenancy.
ColumnTypeRequiredNotes
entity_idPKUUID
tenant_idFK🔒 RLSENUM→ ref_tenants · owning tenant
entity_legal_nameVARCHAR(255)"Leon Industrial LLC", "VaLeon Fund III LP"
entity_typeENUMENUMbalance_sheet, fund_vehicle, jv, construction, corporate
is_activeBOOLEAN
created_atTIMESTAMP
deals 19 columns Master Record 🔒 RLS Deal Domain
One row per deal opportunity. Every other deal-domain table links via deal_id.
ColumnTypeRequiredNotes
deal_idPKUUIDPrimary key, auto-generated
tenant_idFK🔒 RLSv2ENUM→ ref_tenants · isolation key, from JWT
deal_nameVARCHAR(255)e.g. "Beaumont Pointe - IE East"
asset_classENUMENUMindustrial, multifamily, office, retail, land, mixed_use
deal_stageENUMENUMintake → underwriting → legal_review → compliance_screen → treasury_review → closing → closed → dead
deal_statusENUMENUMactive, on_hold, approved, rejected, closed
broker_nameVARCHAR(255)Originating broker or firm
intake_dateDATEDate OM or deal data was received
target_close_dateDATE
actual_close_dateDATEPopulated at closing
deal_sourceENUMENUMbroker, direct, referral, off_market
priority_tierENUMENUMhigh, medium, low
data_classificationSENSITIVITYENUMinternal, confidential, restricted_mnpi → drives deployment-tier routing
entity_owner_idFKv2UUID→ ref_entities · legal owner (was free-text enum in v1; nullable until treasury sets it)
created_byVARCHAR(255)User or agent ID
created_atTIMESTAMPAuto
updated_atTIMESTAMPAuto
notesTEXTFree-form deal notes
property_basics 28 columns FK → deals 🔒 RLS Deal Domain
Physical property attributes extracted from OM or broker input. 1:1 with deals.
ColumnTypeRequiredNotes
property_idPKUUID
deal_idFKUUID→ deals
tenant_idFK🔒 RLSv2ENUM→ ref_tenants
street_addressVARCHAR(255)
city, state, zipVARCHAR
submarketVARCHAR(100)e.g. "Inland Empire East"
msaVARCHAR(100)Metro Statistical Area
parcel_numberVARCHAR(100)APN
zoningVARCHAR(100)
land_area_acresDECIMAL(10,4)
gross_building_area_sqftINTEGERGBA
net_rentable_area_sqftINTEGERNRA
year_builtINTEGER
number_of_unitsINTEGERMultifamily specific
clear_height_ftDECIMAL(5,2)Industrial specific
dock_doorsINTEGERIndustrial specific
drive_in_doorsINTEGERIndustrial specific
property_classENUMENUMclass_a, class_b, class_c
amenitiesJSONBJSONBFlexible amenity list
extraction_confidenceDECIMAL(4,3)0.000–1.000, set by intake agent
extraction_sourceENUMENUMom_extracted, broker_provided, manual_entry
data_classificationENUMTypically internal
financial_snapshot 20 columns FK → deals 🔒 RLS Broker-stated inputs (not governed metrics)
OM-level financials as stated by the broker — provenance-tagged source data, legitimately stored. The stated_* figures are not LCG's governed metrics; LCG's cap rate / NOI come from MetricFlow. Keeping "stated" vs "governed" lexically distinct is intentional.
ColumnTypeRequiredNotes
snapshot_idPKUUID
deal_idFKUUID→ deals
tenant_idFK🔒 RLSv2ENUM→ ref_tenants
asking_priceBIGINTUSD cents — avoids float precision issues
price_per_sqftDECIMAL(10,2)
stated_cap_rateDECIMAL(5,4)As printed in OM. e.g. 0.0550 = 5.50%
stated_noiBIGINTBroker-stated T12 NOI, cents
gross_potential_rentBIGINTcents
effective_gross_incomeBIGINTcents
total_operating_expensesBIGINTcents
occupancy_rate_statedDECIMAL(5,4)e.g. 0.9500 = 95%
wale_yearsDECIMAL(5,2)Weighted Average Lease Expiry
debt_assumption_amountBIGINTcents, if assumable debt exists
pro_forma_noiBIGINTBroker's projected NOI
pro_forma_cap_rateDECIMAL(5,4)Broker-stated
snapshot_dateDATEDate of OM financials
extraction_confidenceDECIMAL(4,3)0.000–1.000
data_classificationENUMconfidential
tenants_rentroll 24 columns FK → deals (1:N) 🔒 RLS v2 · renamed
Rent roll — one row per lessee per deal. Renamed from v1 tenants to remove the collision with the platform isolation tenant. "tenant" now means the isolation boundary everywhere; the rent-roll party is a lessee.
ColumnTypeRequiredNotes
rentroll_idPKv2UUIDRenamed PK (was tenant_id in v1 — collided with RLS key)
deal_idFKUUID→ deals
tenant_idFK🔒 RLSv2ENUM→ ref_tenants · the isolation tenant, NOT the lessee
lessee_namev2VARCHAR(255)Renamed from tenant_name — disambiguates RE lessee from isolation tenant
tenant_typeENUMENUManchor, major, inline, ground_floor, office
credit_ratingVARCHAR(20)S&P / Moody's if available
leased_sqftINTEGER
lease_start_dateDATE
lease_expiry_dateDATE
lease_typeENUMENUMnnn, gross, modified_gross, absolute_net
base_rent_annualBIGINTcents
base_rent_per_sqftDECIMAL(8,2)
rent_escalation_rateDECIMAL(5,4)Annual escalation
rent_escalation_typeENUMENUMfixed, cpi, stepped
renewal_optionsJSONBJSONBOption terms and notice periods
tenant_improvement_allowanceBIGINTcents
personal_guaranteeBOOLEAN
termination_optionBOOLEAN
extraction_confidenceDECIMAL(4,3)Set by intake agent
data_classificationENUMconfidential
underwriting_assumptions 21 input columns FK → deals (versioned) 🔒 RLS v2 · inputs only
LCG's adjusted underwriting inputs, written by the Underwriting Agent. Governed output metrics are computed by MetricFlow, not stored here (v2 change 3). Versioned — never delete prior versions.
ColumnTypeRequiredNotes
underwriting_idPKUUID
deal_idFKUUID→ deals
tenant_idFK🔒 RLSv2ENUM→ ref_tenants
underwriting_versionINTEGERIncrements on revision — never delete prior versions
underwriting_statusENUMENUMdraft, in_review, approved, rejected
underwritten_byVARCHAR(255)Agent ID or user
purchase_price_lcgBIGINTLCG's target price, cents (input)
vacancy_assumptionDECIMAL(5,4)input
management_fee_pctDECIMAL(5,4)input
market_rent_per_sqftDECIMAL(8,2)LCG's market-rent view (input)
rent_growth_assumptionDECIMAL(5,4)input
expense_growth_assumptionDECIMAL(5,4)input
hold_period_yearsDECIMAL(5,2)input
exit_cap_rate_assumptionDECIMAL(5,4)Assumed at disposition (input)
loan_to_value_assumptionDECIMAL(5,4)Target LTV (input)
capex_year1BIGINTcents (input)
capex_totalBIGINTcents (input)
risk_flagsJSONBJSONBAgent-identified risks
agent_commentaryTEXTUnderwriting agent narrative
data_classificationMNPIENUMconfidential or restricted_mnpi
⚠ Governed metrics — computed by MetricFlow, NOT stored as authoritative columns:
adjusted_noistabilized_noigoing_in_cap_ratestabilized_cap_ratemarket_cap_rateirr_projectedequity_multiple_projecteddebt_service_coverage (DSCR)sensitivity_low/high_irr
These resolve through the dbt MetricFlow Semantic API at read time over the input assumptions above. If a point-in-time snapshot is ever needed, write it to a clearly-labeled uw_metric_snapshot table marked source = 'metricflow' — read-only, MetricFlow remains source of truth.
legal_review 22 columns FK → deals (versioned) 🔒 RLS Privileged → MNPI
compliance_screen 19 columns FK → deals (versioned) 🔒 RLS v2 · sign-off → approval_log
Compliance agent output — LP conflicts, MNPI screening, regulatory flags. v1's ashley_buboltz_sign_off column is removed: the gate is now a row in approval_log with approval_stage = compliance, approver_role = COMP. When mnpi_flag = true, the row's classification becomes restricted_mnpi (Tier 3).
ColumnTypeRequiredNotes
compliance_idPKUUID
deal_idFKUUID→ deals
tenant_idFK🔒 RLSv2ENUM→ ref_tenants
screen_versionINTEGER
screen_statusENUMENUMpending, in_review, cleared, hold, escalated
mnpi_flagMNPIBOOLEANtrue → classification = restricted_mnpi → Tier 3
mnpi_descriptionTEXTPopulated if flagged
lp_conflict_flagBOOLEANLP conflict of interest detected
sec_finra_flagBOOLEANSEC/FINRA regulatory concern
sanctions_screen_statusENUMENUMpass, fail, pending
aml_screen_statusENUMENUMpass, fail, pending
investment_committee_requiredBOOLEANIC approval needed
data_classificationMNPIENUMrestricted_mnpi when mnpi_flag
treasury_decision 22 columns FK → deals (versioned) 🔒 RLS v2 · sign-off → approval_log
Treasury agent output — funding structure, capital sources. v1's matt_thompson_approval column is removed: the gate is a row in approval_log (approval_stage = treasury, approver_role = TX or RE-CEO). Sets the closing legal entity via entity_owner_id.
ColumnTypeRequiredNotes
treasury_idPKUUID
deal_idFKUUID→ deals
tenant_idFK🔒 RLSv2ENUM→ ref_tenants
entity_owner_idFKv2UUID→ ref_entities · closing legal entity (replaces free-text)
decision_versionINTEGER
total_capitalizationBIGINTTotal deal cost, cents
equity_requiredBIGINTcents
debt_requiredBIGINTcents
equity_sourceENUMENUMlcg_balance_sheet, fund_vehicle, lp_capital, jv_partner, mixed
fund_vehicle_nameVARCHAR(255)Display label only — entity is entity_owner_id
lender_nameVARCHAR(255)
loan_typeENUMENUMpermanent, bridge, construction, mezzanine
interest_rateDECIMAL(5,4)
funding_scheduleJSONBJSONBMilestone-based funding timeline
wire_instructions_verifiedBOOLEANDefault false — must be explicitly set
data_classificationMNPIENUMAlmost always restricted_mnpi → Tier 3
closing_checklist 18 columns FK → deals (1:1) 🔒 RLS v2 · sign-off → approval_log
Closing agent — final execution steps. v1's matt_thompson_final_approval column is removed: recorded in approval_log (approval_stage = closing). asset_management_record_created triggers the handoff to the Asset Management domain.
ColumnTypeRequiredNotes
closing_idPKUUID
deal_idFKUUID→ deals
tenant_idFK🔒 RLSv2ENUM→ ref_tenants
closing_statusENUMENUMpre_closing, closing_in_progress, closed, failed
scheduled_closing_dateDATE
actual_closing_dateDATE
purchase_agreement_executedBOOLEANDefault false
title_insurance_boundBOOLEANDefault false
environmental_clearBOOLEANDefault false
loan_documents_executedBOOLEANDefault false
deed_recordedBOOLEANDefault false
funds_wiredBOOLEANDefault false
wire_confirmation_numberVARCHAR(255)
asset_management_record_createdBOOLEANHandoff to Asset Management Domain
post_closing_itemsJSONBJSONBOutstanding items after close
data_classificationENUM
deal_documents → extraction_results Document Store Domain 🔒 RLS
Raw docs + the Document Intake Agent's per-document output (archetype ②). The confidence fields feed the hard-commit gate and citation eval. Both tables carry tenant_id.
ColumnTypeRequiredNotes
document_idPKUUIDdeal_documents
deal_id · tenant_idFK🔒UUID / ENUM→ deals · ref_tenants
document_typeENUMENUMoffering_memorandum, rent_roll, broker_opinion_value, lease_abstract, title_report, environmental_report, purchase_agreement, loan_document, other
file_pathVARCHAR(1000)Azure Blob / ADLS path
processing_statusENUMENUMpending, processing, extracted, failed, needs_review
── extraction_results (1:1 with document) ──
extraction_idPKUUID
document_id · deal_idFKUUID→ deal_documents · deals
extraction_modelVARCHAR(100)e.g. claude-sonnet-4-6
extracted_dataJSONBJSONBFull structured extraction output
overall_confidenceDECIMAL(4,3)0.000–1.000
low_confidence_fieldsJSONBJSONBFields with confidence < 0.80
human_review_requiredBOOLEANFlagged if confidence < 0.75
corrections_appliedJSONBJSONBHuman corrections to extraction
coinvestor_prospects · leverage_matches · capmarkets_intel v2.1 · new 🔒 RLS Capital Markets Domain · parallel to deal
Co-invest / back-leverage / rate-window work running parallel to the deal lifecycle. Linked to a deal_id where deal-specific. All outputs are drafts/advisory — humans send and decide (archetype ③/① soft gates).
ColumnTypeRequiredNotes
── coinvestor_prospects (RE-CoInvest-Matcher AI-11) ──
prospect_idPKUUID
tenant_id · deal_idFK🔒ENUM / UUID→ ref_tenants · deals
coinvestor_name · coinvestor_typeVARCHAR / ENUMinstitutional, family_office, hnw, fund_of_funds, strategic
appetite_match_scoreDECIMAL(5,2)0–100 vs deal profile (FinTrx/MadeMarket)
outreach_draftTEXTNever auto-sent
outreach_statusENUMENUMdrafted, sent, responded, declined, committed
data_classification→ MNPIENUMconfidential → restricted_mnpi if LP terms attached
── leverage_matches (RE-Leverage-Matcher AI-12) ──
match_idPKUUID
tenant_id · deal_idFK🔒ENUM / UUID→ ref_tenants · deals
lender_name · lender_typeVARCHAR / ENUMbank, debt_fund, agency, clo_desk, life_co, bridge
loan_productENUMENUMpermanent, bridge, construction, mezzanine, back_leverage
criteria_fit_scoreDECIMAL(5,2)0–100 vs deal structure
indicative_termsJSONBJSONBRate/LTV/term as indicated (inputs, not governed)
term_sheet_request_draftTEXTDrafted request letter — team sends
match_statusENUMENUMidentified, requested, term_sheet_received, selected, declined
── capmarkets_intel (RE-CapMarkets-Watch AI-13) ──
intel_idPKUUID
tenant_idFKENUMNullable / shared — market data not tenant-private
deal_idFKUUIDSet only when tied to a deal's financing
intel_type · headlineENUMENUM / VARCHARrate_move, spread_change, agency_pricing, execution_window, weekly_brief
is_act_now_alertBOOLEANThreshold-triggered execution alert
source · as_of_dateVARCHAR / DATEbloomberg, web_feed, internal_rate_history
audit_trail · approval_log Audit Domain Cross-cutting · WORM → ADLS Gen2 Delta · SEC 17a-4
Every agent write and every human approval is logged, then WORM-replicated to ADLS Gen2 Delta. Append-only — never updated or deleted. approval_log is now the single home for ALL sign-offs, keyed by approver_role (v2 change 4).
ColumnTypeRequiredNotes
audit_idPKUUIDaudit_trail
deal_id · tenant_idFK🔒UUID / ENUMdeal_id nullable for system events
entity_type · entity_idVARCHAR / UUIDTable name + PK of modified record
actionENUMENUMcreate, update, delete, approve, reject, flag, read
actor_typeENUMENUMagent, human, system
old_value · new_valueTEXTBefore/after on update
worm_replicated_atv2TIMESTAMPSet when flushed to ADLS Gen2 Delta
timestampTIMESTAMPImmutable
── approval_log (single home for all sign-offs) ──
approval_idPKUUID
deal_id · tenant_idFK🔒UUID / ENUM→ deals · ref_tenants
approval_stageENUMENUMunderwriting, legal, compliance, treasury, closing
approver_roleFKv2ENUM→ ref_roles (COMP, TX, RE-CEO…). Was free-text in v1
approver_userv2VARCHAR(255)Resolved at sign-off — who acted, not schema-bound
approval_statusENUMENUMpending, approved, rejected, delegated
conditionsJSONBJSONBConditions attached to approval

Agent Read / Write Map

Aligned to the six archetypes. All agents write audit_trail; sign-offs are rows in approval_log. The Underwriting Agent writes inputs only — governed metrics resolve through MetricFlow. Gold-icon agents work the origination funnel; green-icon are Capital Markets.

🔭
RE-OffMarket-Scout (AI-25)
Archetype ① / ⑥ · soft gate
▸ Reads
buy_box_criteriaownership/market signalsGreen Street
▸ Writes
origination_leadslead_sources
📡
RE-Pipeline-Scout (AI-01)
Archetype ① · advisory
▸ Reads
origination_leadslead_activityCRM / pipeline
▸ Writes
origination_leads (scores, NBA)
🔎
RE-PreScreen-Writer (AI-08)
Archetype ② / ③ · soft gate
▸ Reads
origination_leadsfinancial_snapshotmarket data
▸ Writes
lead_screeningdeal_documents (memo)
🏷️
RE-AVM-Valuer (AI-22)
Archetype ① · soft gate
▸ Reads
origination_leads / property_basicsGreen Street AVM
▸ Writes
lead_screening.avm_* (provenance)
🤝
RE-Broker-CRM (HY-10)
Archetype ⑥ · advisory
▸ Reads
CRMemail threadslead_activity
▸ Writes
lead_activity (follow-ups)
🤲
RE-CoInvest-Matcher (AI-11)
Archetype ③ · drafts only
▸ Reads
dealsFinTrx / MadeMarket
▸ Writes
coinvestor_prospects
🏛️
RE-Leverage-Matcher (AI-12)
Archetype ③ · drafts only
▸ Reads
dealstreasury_decision
▸ Writes
leverage_matches
📉
RE-CapMarkets-Watch (AI-13)
Archetype ① · informational
▸ Reads
Bloomberg / web feedsinternal rate history
▸ Writes
capmarkets_intel
📥
Document Intake Agent
Archetype ② · hard-commit gate
▸ Reads
deal_documents
▸ Writes
extraction_resultsproperty_basicsfinancial_snapshottenants_rentroll
📈
Market Research Agent
Archetype ① / ⑥
▸ Reads
property_basicssubmarket_trendsgreen_street_snapshots
▸ Writes
market_compssubmarket_trends
📊
Underwriting Agent
Archetype ① · per asset class
▸ Reads
financial_snapshottenants_rentrollmarket_compsMetricFlow API
▸ Writes
underwriting_assumptions (inputs)
⚖️
Legal Agent
Archetype ② · Tier 3 if privileged
▸ Reads
property_basicsdeal_documentsextraction_results
▸ Writes
legal_reviewapproval_log
🛡️
Compliance Agent
Archetype ⑤-gated · COMP role
▸ Reads
dealsunderwriting_assumptionstreasury_decision
▸ Writes
compliance_screenapproval_log
🏦
Treasury Agent
Archetype ② / ⑤ · TX role · Tier 3
▸ Reads
underwriting_assumptionscompliance_screen
▸ Writes
treasury_decisionapproval_log
📝
Closing Agent
Archetype ③ / ⑤ · final handoff
▸ Reads
All upstream tables
▸ Writes
closing_checklistapproval_log→ asset mgmt domain
🔐
All Agents
Cross-cutting · always on
▸ Reads
approval_log (pending)
▸ Writes
audit_trail (WORM)

Data Classification → Deployment Tier

data_classification is a column; the tier is where the handling agent runs. The mapping below is the routing rule — not a redefinition of the column. (Tier 3 = air-gapped private LLM, the one runtime Foundry cannot serve — ADR 0001.)

Data TypeClassificationTierRuntime
Property basics, broker info, market comps, submarket trendsinternalTier 1 / 2Claude Enterprise relay / API
Capital-markets intel (rates/spreads, public market data)internalTier 1 / 2Claude Enterprise relay / API
Origination leads, buy-box, screening, lead activityconfidentialTier 2Claude API + LangGraph on Azure Container Apps
Co-investor prospects, leverage matchesconfidentialTier 23Tier 3 if LP terms attached
Financial snapshot (OM), rent roll, underwriting inputsconfidentialTier 2Claude API + LangGraph on Azure Container Apps
LP capital structure, fund-vehicle termsrestricted_mnpiTier 3Air-gapped private LLM, mTLS
Privileged legal content (privileged_content_flag)restricted_mnpiTier 3Air-gapped — no external API
Compliance MNPI flags (mnpi_flag)restricted_mnpiTier 3Air-gapped — no external API
Treasury / wire detailsrestricted_mnpiTier 3Air-gapped — Farhan + Matt exec gate
Audit trailinheritedTier 2Append-only, WORM → ADLS Gen2 Delta (17a-4)

Implementation Notes

🗄️ System of Record
Postgres with per-tenant RLS schemas is the transactional source of truth. DuckDB provides read-side analytics views over Postgres — an accelerator, not a parallel SoR. dbt handles migrations, one model group per domain.
📐 Governed Metrics
dbt MetricFlow Semantic API is the single source for NOI, DSCR, LTV, cap rate, IRR, EM, waterfall yield. No table stores these as authoritative. WrenAI resolves governed metrics through MetricFlow (ADR 0003).
🔒 RLS / OPA
Every table's tenant_id is the RLS predicate; OPA 8×4 authorizes role × module × tenant. No cross-tenant joins. Per IN-01 pilot G3: no isolation guarantee rests on a system prompt — RLS + OPA are structural.
🔐 Audit / WORM
audit_trail + approval_log replicate to ADLS Gen2 Delta, WORM, SEC 17a-4. Append-only — never updated or deleted. All sign-offs live in approval_log, keyed by role.
💰 Money & Rates
All monetary values stored as BIGINT in USD cents (e.g. $5,500,000 = 550000000) to avoid float precision issues. Rates as DECIMAL(5,4) (0.0550 = 5.50%).
📑 Versioned Tables
underwriting_assumptions, legal_review, compliance_screen, treasury_decision keep an integer version column — never delete prior versions. Extraction schema versioned separately (evolves faster).

v1 → v2 → v2.1 Alignment Changes

v1 predated the Agent Creation Playbook + ADRs 0001–0003 + the IN-01 pilot; v2 (rows 1–7) reconciled the model against them. v2.1 (rows 8–10) adds the upstream Origination and Capital Markets domains the original model omitted — the sourcing/scouting funnel before a deal exists.

#ChangeWhy
1Added tenant_id (4 tenants) to every table; new ref_tenantsv1 had no isolation key; RLS can't scope rows it can't see
2entity_owner enum → entity_owner_id FK → ref_entitiesLegal ownership is a separate axis from tenancy
3Governed metrics removed as stored columns; table holds inputs only"No agent computes its own NOI" — metrics from MetricFlow
4Person-named approval columns → role-based rows in approval_logNames in schema = migration on every role change
5Classification vs. deployment tier separatedv1 conflated a sensitivity label with a runtime tier
6tenantstenants_rentroll; tenant_namelessee_name"tenant" was overloaded (isolation vs RE lessee)
7Named green_street_snapshots; WORM/ADLS audit replication statedProvenance to greenstreet/; SEC 17a-4
8Added Origination domainbuy_box_criteria, origination_leads, lead_sources, lead_screening, lead_activityThe model began at intake; the sourcing/scouting funnel before a deal existed was unrepresented (AI-25/01/08/22, HY-10)
9Lead → deal promotiondeals.origination_lead_id FK; leads kept separate from dealsMost leads die in the funnel; deal pipeline must not carry dead scouting noise. Advance is one-way + an approval_log gate
10Added Capital Markets domaincoinvestor_prospects, leverage_matches, capmarkets_intelCo-invest / back-leverage / rate-window work runs parallel to the deal lifecycle and was unmodeled (AI-11/12/13)