# INGEST-EXTRACT-SPEC.md â answers for `mcp_report_extract` (Design â Code)
Answers your 3 asks + the rate-limit reconcile. Source of truth for FE field names = `pure-ingest.html` DOCTYPES + `pure-data-entry-schema.js`.

## (a) Field â column specs for the 5 missing target tables
Types are suggestions; keep everything nullable (extraction is partial), stamp `deal_uuid`, `source_document_id`, `created_at`, `created_by`.

**pure_documents** (generic / catch-all)
`doc_type text Â· title text Â· file_name text Â· file_url text Â· category text Â· status text Â· deal_uuid uuid Â· source_document_id uuid`

**pure_loan_apps** (mortgage / URLA-1003)
`borrower text Â· co_borrower text Â· loan_amount numeric Â· property_address text Â· loan_purpose text Â· estimated_value numeric Â· status text Â· deal_uuid uuid`

**pure_financials** (bank statement Â· pay stub Â· W-2)
`doc_kind text (bank_statement|pay_stub|w2|1099) Â· institution text Â· account_holder text Â· account_last4 text Â· statement_date date Â· ending_balance numeric Â· gross_income numeric Â· deal_uuid uuid`

**pure_legal_forms**
`form_type text Â· parties text Â· jurisdiction text Â· effective_date date Â· governing_terms text Â· status text Â· deal_uuid uuid`

**pure_identity_docs** (already exists per your note â confirming the shape we write)
`full_name text Â· dob date Â· license_no text Â· state text Â· expiration date Â· doc_side text (front|back) Â· verified boolean Â· deal_uuid uuid`

(The other 4 â offers/appraisals/inspections/utility_bills â already exist and are proven via the finding write-through.)

## (b) Is `mcp_doc_ingest` the write-through?
**No â split the two concerns, chain them:**
1. **`mcp_doc_ingest`** = file filing â DocVault (`pure_documents` row: file_url, doc_type, category, deal link). Keep as-is.
2. **`mcp_report_extract`** = the **structured write-through** â writes the parsed fields **directly to the doctype's target table** (the columns above / the existing 4), using the same field-map pattern already proven for inspection findings. 

**Flow:** upload â `mcp_doc_ingest` (files the doc, returns `document_id`) â `mcp_report_extract(doctype, document_id|file_url)` (vision â fields â target-table columns, tagged `source_document_id=document_id`). So the file always lands in DocVault, and the structured data always lands in its canonical table, cross-linked. FE already calls ingest first; just have extract accept the returned `document_id`.

## (c) Vision path â recommendation
**Dedicated Anthropic call from the ingest edge fn using the existing `ANTHROPIC_API_KEY` secret â do NOT route through the chat edge fn.** Reasons: chat is user-facing, rate-limited, and carries a conversational system prompt; extraction needs a tight JSON-only prompt, its own model tier, and its own error handling. Same secret (already confirmed present on `pure-mcp`), separate function path. Return `{fields:[{key,label,value,confidence}]}` so the FE review step can show confidence + let the human confirm before write.

## Rate-limit reconcile (your Q)
**Confirmed â `pure-ratelimits.html` passes `p_id` on edit.** Please add the `p_id` arg to `mcp_ratelimit_upsert` for id-based edits (insert when absent, update when present). FE fields already match your `scope Â· key Â· subject Â· limit Â· window Â· burst Â· enabled`.

## Change log
- 2026-06-30 â Lane A: answers for the priority-1 extract build; FE (Pure Ingest + Test Drive) already call the pattern fail-soft and light up when this lands.
