SPA ENGINE — BUILD SPEC
**For:** Claude Code (eyes on the live `uniestate` repo — source of truth)
**Target:** add an **SPA Engine** to the Cockpit — draft-generation + lifecycle tracking for the reservation → contract → Oqood pipeline
**Format mirrors:** `OUTREACH-ENGINE-SPEC.md` and `CRM-ENGINE-SPEC.md` — paste-ready, reuse the live store/tokens/patterns, all AI/e-sign/registration simulated and marked `// API`
**Governing thesis:** the engine turns a booking into a *draft* SPA and then *drives and tracks* the legal lifecycle — it does not replace the developer's signature, the DLD, the escrow trustee, or a lawyer. Getting that boundary right is what makes it credible to Uniestate rather than a liability.
---
0. THE ONE THING TO READ FIRST — what "autonomous" can and cannot mean here
The vendor marketing that inspired this ("instant SPA generation," "autonomous SPA creator") blurs a legal line. An SPA is a **binding contract registered with a government authority.** Deep research into the 2026 DLD/RERA framework gives hard limits that the engine must encode as *guardrails*, not ignore as friction:
- **Off-plan uses an SPA from the developer** (registered via **Oqood**). **Secondary/resale uses Form F** (the RERA unified contract, generated in the **DLD REST app**, signed with **UAE PASS**). *These are two different legal instruments — the engine must branch on transaction type and never generate the wrong one.* [DLD/RERA 2026]
- **Off-plan SPAs must be on RERA-approved templates.** A contract "not recorded on the official RERA forms is not recognized by the DLD." So the engine drafts against the **approved template structure** — it does not invent contract language. [westgatedubai, egsh 2026]
- **Form F must be generated inside the DLD REST app and signed via UAE PASS** (biometric, blockchain-logged). An engine **cannot** mint a legally valid Form F outside REST — it can only *prepare and stage* the data, then hand off. Asserting otherwise would be false. [westgatedubai 2026]
- **Oqood registration is the developer's submission**, due **within 90 days of SPA signing**; an unregistered off-plan sale is **void**; late filing carries a penalty. The engine *tracks and prompts* this deadline — it does not "auto-register" without the developer's authenticated portal action. [egsh, DLD, interim-register 2026]
- **Escrow is mandatory and milestone-linked.** Buyer funds go **only** to the project's RERA-approved escrow account (never the developer's operating account); releases are certified by a trustee engineer. The engine **references the escrow IBAN and maps the payment plan to it** — it never routes or holds money. [DLD FAQ, RERA 2026]
- **AML/KYC + (for corporates) TRN / 9% corporate-tax check** are normal 2026 pre-contract gates. The engine collects and validates presence, doesn't adjudicate. [westgatedubai, sheridama 2026]
**Design consequence — the engine is a "draft + drive" system, not an "auto-execute" system.** Every legally-operative act (developer signature, UAE PASS signing, DLD/Oqood submission, escrow movement) is a **HUMAN/AUTHORITY GATE** rendered explicitly in the UI. The engine's job is to make everything *up to* each gate instant, correct, and verified — and to track what happens after. Marketing it as "no human needed" would be both false and a compliance risk; **market it as "minutes not days, with every legal gate visible and enforced."** That honesty is the sell to a 30-year developer.
---
1. What this adds — one paragraph
An **SPA Engine** that, the moment a unit is reserved (from the CRM allocation flow), assembles a **compliant draft SPA** from verified buyer KYC + unit record + the project's payment plan + escrow reference, branching correctly between **off-plan SPA** and **secondary Form F**. It runs a **pre-flight compliance checklist** (project registered, escrow active, KYC/AML complete, TRN for corporates), routes the draft through **simulated e-signature**, then **tracks the post-signing legal lifecycle** — Oqood 90-day countdown, escrow milestone mapping, and handover/title conversion — every government/human step shown as an explicit gate. Reuses the CRM's `unit`, `milestone`, and lead store; writes status back so the pipeline and inventory stay in sync (one brain).
---
2. Data model — extend the existing store
Builds directly on `CRM-ENGINE-SPEC.md` objects (`unit`, `milestone`, `project`, lead). Add:
```
transactionType = "off_plan_spa" | "secondary_form_f" // BRANCH EVERYTHING ON THIS
kyc = {
leadId,
buyerType, // "individual" | "company"
// individual
passportOnFile, emiratesIdOnFile, visaOnFile, // booleans — presence only, no doc storage in demo
// company
tradeLicenseOnFile, moaOnFile, trn, // TRN required for corporate (2026)
amlScreened, // bool — sanctions/PEP screen ran // API
poaOnFile, // if signing by power of attorney
minorGuardian, // if buyer is a minor, guardian record required (DLD rule)
}
spaDraft = {
id, leadId, unitId, transactionType,
status, // see lifecycle §4
// populated fields (from verified sources, never invented):
partiesBlock, // buyer legal name/ID refs + developer/SPV legal entity
propertyBlock, // project name, DLD project no., plot, unit ref, floor, size sqft, view, parking
priceBlock, // total AED, payment plan label
scheduleBlock, // milestone rows (from `milestone[]`)
escrowBlock, // project escrow IBAN + trustee bank (reference only)
clauseBlock, // delay penalty, force majeure, spec-change, termination, assignment, defect-liability (12mo), 5% retention
feesBlock, // 4% DLD, Oqood AED 1,000 self-reg, who-pays flags
generatedAt, templateVersion,
}
legalLifecycle = {
spaId,
preflightPassed, // bool — all §3 gates green
developerSigned, // HUMAN GATE
buyerSigned, // HUMAN GATE (UAE PASS for Form F)
oqoodSubmittedAt, // AUTHORITY GATE (developer's portal action)
oqoodDeadline, // = buyerSigned date + 90 days
oqoodCertificate, // provisional e-cert ref once issued // API
escrowLinked, // bool — plan mapped to escrow IBAN
handoverAt, titleDeedAt, // far-future, tracked
}
```
**Never invent contract clause text or legal entity names.** Clause block uses the **standard RERA-approved SPA structure** as labelled section headers with plain-language summaries; the authoritative wording comes from the developer's approved template (a `templateVersion` pointer). Where real Uniestate SPV / DLD project numbers aren't known, render the field as **`[ — pending client template ]`** and surface it in a "fields awaiting source" list — same discipline as the PDF photography gap. Do not fabricate a DLD project number.
---
3. Pre-flight compliance checklist (the gate before any draft is "ready")
Render as a visible checklist on each draft. Draft can be *assembled* anytime, but cannot advance to "Ready to sign" until all green. Each item is real 2026 law:
1. **Project registered with DLD** (off-plan) — project has a DLD registration no. + approval cert. *Unregistered project = cannot sell.*
2. **Escrow account active** — project escrow IBAN present + trustee bank named. *No escrow = cannot take buyer funds.*
3. **RERA-approved template selected** — `templateVersion` set (off-plan SPA) OR REST/Form-F path selected (secondary).
4. **KYC complete** — individual: passport (+ Emirates ID / visa if resident); company: trade licence + MOA + **TRN**; minor → guardian; POA if applicable.
5. **AML screen passed** — sanctions/PEP check ran clean `// API`.
6. **Payment plan mapped** — milestone schedule exists and ties to escrow (from CRM `milestone[]`).
7. **Fees assigned** — 4% DLD + Oqood self-reg fee: who-pays flagged.
A red item shows the **exact real-world action** to clear it (e.g. "TRN required — corporate buyers must provide Tax Registration Number before contract, 2026 rule").
---
4. Lifecycle state machine (statuses + gates)
Render as a horizontal tracker (reuse the CRM stage-tracker component). Gate types are visually distinct: **⚙ engine (auto)** vs **✋ human** vs **🏛 authority**.
```
1. ⚙ Reserved — unit allocated (from CRM); SPA draft auto-assembled
2. ⚙ Pre-flight — compliance checklist run; blockers surfaced
3. ✋ Ready to sign — all gates green; draft locked for signature
4. ✋ Developer signed — HUMAN GATE (authorised Uniestate/SPV signatory)
5. ✋ Buyer signed — HUMAN GATE (UAE PASS if secondary/Form F)
6. 🏛 Oqood submitted — AUTHORITY GATE (developer's Oqood portal action) → 90-day clock starts at step 5
7. 🏛 Oqood registered — provisional e-certificate issued by DLD // API
8. ⚙ Escrow linked — payment plan bound to escrow IBAN; installments tracked vs milestones
9. 🏛 Handover / Title — far-future; Oqood → permanent title deed at completion
```
- Between 5 and 7, show a **live 90-day Oqood countdown**; if it approaches expiry, push a next-best-action into the existing Digest ("Oqood filing due in 6 days — unregistered off-plan sale is void").
- **The engine never auto-advances a 🏛 or ✋ gate.** It can *prepare the submission package* and mark it "ready to submit," but a human/authority completes it. State this in a tooltip on every gated step.
---
5. Surfaces to build (under the Cockpit)
5.1 SPA Generator
5.2 Lifecycle Tracker
5.3 Compliance & Escrow panel
5.4 Document register
---
6. Guardrails (visible UI, not buried) — reuse the Outreach-lane pattern
- **Transaction-type branch is mandatory** — the UI refuses to generate until off-plan-vs-secondary is chosen; each renders the *correct* instrument (SPA vs Form F). Never generate a Form F outside the REST hand-off.
- **Legal gates are non-skippable** — signatures, Oqood submission, and any escrow action are human/authority steps; the engine stages but never fakes them.
- **Draft ≠ executed** — every un-signed document is watermarked **DRAFT — not a binding contract** in the UI.
- **No invented legal text or IDs** — approved-template pointer only; unknown fields flagged, not fabricated.
- **Developer-only** — the off-plan SPA path is Uniestate-as-developer. The Form F / secondary path belongs to the **Uniestate Capital** brokerage lens (reuse the CRM's Capital toggle) since resale + Form F + UAE PASS is broker-side.
- **"Draft + drive, not auto-execute"** disclaimer in the engine header. This is the honest, defensible framing.
---
7. "One brain" wiring
- SPA status writes back to the `unit` (Reserved → Sold on execution) and the lead's activity feed; inventory sell-through updates automatically.
- Oqood countdown + overdue → existing Digest next-best-action (don't build a second alert system).
- Attribution unchanged: a closed SPA is the terminal event the demand-engine funnel was driving toward — connect it so Analytics can show lead-source → reserved → SPA executed → Oqood registered.
---
8. Build order (verify at each step)
1. Extend store (transactionType, kyc, spaDraft, legalLifecycle) + seed 2–3 drafts across both branches. Clean build, exit 0.
2. SPA Generator — assembly from unit/milestone/kyc; missing-field flagging. Verify no invented data renders.
3. Pre-flight checklist with real blocker actions. Verify gating (can't reach "Ready to sign" with a red item).
4. Lifecycle Tracker + 90-day Oqood countdown + Digest hook.
5. Compliance & Escrow panel (reference-only notices).
6. Document register + export stub.
7. Capital toggle wires the Form F / secondary path.
8. Bundle grep for new strings; per-surface screenshots; flag mobile/real-device as the open human check.
---
9. Acceptance checklist
- [ ] Off-plan → **SPA/Oqood** path; secondary → **Form F/REST/UAE PASS** path; engine never mixes them.
- [ ] No draft reaches "Ready to sign" until all 7 pre-flight gates are green.
- [ ] Every signature / Oqood / escrow step is an explicit ✋human or 🏛authority gate the engine cannot auto-complete.
- [ ] Unsigned docs watermarked **DRAFT — not a binding contract**.
- [ ] No invented clause text, SPV names, or DLD project numbers; unknowns flagged `[ — pending client template ]`.
- [ ] Escrow shown as reference-only; explicit "engine never holds/moves funds" notice.
- [ ] 90-day Oqood countdown pushes to existing Digest; "unregistered sale is void" messaging present.
- [ ] Corporate buyers gated on TRN; minors gated on guardian; POA supported.
- [ ] Writes back to unit status + lead activity + attribution (one brain), no forked store.
- [ ] Clean build (exit 0); live-bundle grep; per-surface screenshots; mobile flagged as open human check.
---
10. Copy anchors (brand-true, defensible)
- Engine header: **"From booking to contract in minutes — with every legal gate visible."**
- Honesty line (leave-behind): **"The engine drafts and drives. The developer, the DLD, and the escrow trustee still hold the pen — as the law requires."**
- Pre-flight: **"Compliant before it's contractual."**
- Oqood tracker: **"Registered within 90 days — or the sale is void. We count the days for you."**
- Escrow notice: **"Funds go to the project escrow account, never to an operating account. Always."**