⚖️ TrueTrade
MVP — build plan & flows

The smallest end-to-end loop: Lindora Village, a few pros, real payments

This page captures everything we need to review before building: the full revised workflow, each new mechanic drawn out as its own flow, the condo white-label pilot scope, and what we reuse, build, and defer. It supersedes the earlier connection-unlock flow.

What we're building first

The MVP in one paragraph

Start with the condominium white-label wedge. We hand-pick a few pros who already work in one condo, onboard them ourselves, and let a handful of that building's tenants request jobs and pay through the platform. One building, a closed loop, real money — the cheapest way to prove the whole flow end-to-end before we automate anything.

1 buildingwhite-label pilot ~3–5 prosalready working there Hand-onboardedwhite-glove, by us A few tenantsreal job requests Real paymentsthrough the platform

What the pilot proves

  • Tenants will request & pay through the platform instead of going direct.
  • Pros accept intermediated comms + on-site cost verification + a 24h payout hold.
  • The condo is a real, pre-clustered acquisition channel.
  • Both sides come back — the review → cadence loop actually fires.

Why a condo wedge

A building is a ready-made dense cluster with a trusted brand (the administration) and pros who are already on-site. It collapses the two hardest cold-start problems — supply and demand density — into a single, warm, bounded environment we can support by hand.

🧭 The calls this rests on (launch market, processor, fee model) live on Decisions → · the money math on Economics →
End to end

The main workflow

The full loop for one job, with the NEW mechanics highlighted. Each new step gets its own section below.

Tenant / customer Pro Admin Platform New MVP mechanic
flowchart TD
  A1["Tenant requests a job
(building-branded portal)"]:::cust --> A2["Chat intake → brief + photos"]:::cust A2 --> S1{"Pro sourcing"}:::new S1 -->|"1 · in-platform pros (priority)"| OUT["Outreach to matched pros"]:::admin S1 -->|"2 · fallback: Google API"| OUT S1 -->|"3 · last resort: admin manual"| OUT OUT --> E["Pros submit free initial estimates"]:::pro E --> CMP["Tenant compares & selects a pro"]:::cust CMP --> ACC["Pro accepts the connection"]:::pro ACC --> COMMS["Platform-intermediated chat opens
(no contact details shared)"]:::new COMMS --> FQ["Pro sends firm quote → tenant accepts
(price locked, before dispatch)"]:::new FQ --> ARR["Pro travels & arrives"]:::pro ARR --> VER["On-site scope confirmation
reality matches the brief?"]:::new VER -->|"scope changed → no agreement"| CX["Clean cancel · trip fee by fault"]:::sys VER -->|"confirmed / re-quote accepted"| PAY["Tenant pays now (card on file)
captured via ONVO"]:::new PAY --> WORK["Pro does the work"]:::pro WORK --> HOLD["24-hour refund window
customer protection"]:::new HOLD --> REL["Window closes · payment final
(pro settled, minus fee)"]:::sys REL --> REV["Two-sided reviews"]:::sys REV --> Q{"Both positive?"}:::sys Q -->|"yes + both agree"| CAD["Set a recurring cadence
(card on file)"]:::new Q -->|"no"| DONE(["Done"]):::sys classDef cust fill:#EAF6F2,stroke:#0F7458,color:#08382C; classDef pro fill:#FDF6EA,stroke:#C57D17,color:#7a4d09; classDef admin fill:#EBE2D3,stroke:#6B7B77,color:#1B2A28; classDef sys fill:#ffffff,stroke:#1C8F73,color:#1B2A28; classDef new fill:#EFE9FB,stroke:#7C5CBF,color:#3f2a73;
Five new mechanics vs. the original flow: tiered pro sourcing · intermediated comms (replaces contact unlock) · firm quote before dispatch → on-site scope confirmation · pay-now / release-after-24h · mutual-consent cadence.

Step by step

  1. Request. A tenant opens the building-branded portal and describes the job via chat intake (brief + photos).
  2. Source pros. The platform looks for in-platform pros first, then Google API, then admin manual — see Pro sourcing.
  3. Estimate. Matched pros submit free initial estimates.
  4. Select. The tenant compares and picks a pro; the pro accepts the connection.
  5. Intermediated comms. Instead of unlocking contact details, the platform opens a relayed chat — see Comms.
  6. Firm quote before dispatch. After any clarifying chat, the pro locks a firm quote and the tenant accepts it — the real commitment, before the pro travels.
  7. On-site scope confirmation. On arrival the pro confirms reality matches the brief; re-pricing only on an evidenced scope change — see below.
  8. Pay on start, 24h window. On confirmation the tenant is charged (captured); the pro is settled promptly and the tenant has 24h to flag a problem (refund) — see Payment.
  9. Work. The pro completes the job.
  10. Review → cadence. Both review; if both are positive and both agree, they set a recurring cadence — see Reviews.
New mechanic 1
1

Pro sourcing & fallback

When a job comes in, we prioritise pros already on the platform; only if none fit do we reach outward.

flowchart TD
  J["New job brief"]:::sys --> P1{"In-platform pros match
category + building/area?"}:::new P1 -->|"yes"| USE["Use in-platform pros
(priority)"]:::new P1 -->|"none"| P2{"Google Places API
find local candidates"}:::new P2 -->|"found"| IMP["Import as candidate pros"]:::admin P2 -->|"none / low quality"| P3["Admin manual review
(hand-source)"]:::admin USE --> OUT["Outreach → estimates"]:::sys IMP --> OUT P3 --> OUT classDef sys fill:#ffffff,stroke:#1C8F73,color:#1B2A28; classDef admin fill:#EBE2D3,stroke:#6B7B77,color:#1B2A28; classDef new fill:#EFE9FB,stroke:#7C5CBF,color:#3f2a73;
Why
In-platform pros are vetted, already paid-in, and (in a condo) already on-site — they convert best and keep supply tight.
Edge cases
No match anywhere → admin hand-sources. Google candidate must still be onboarded before they can be paid.
MVP shortcut: the in-platform tier is the only live path — we hand-seed the condo's pros. Google API and admin-manual are designed now but stubbed (admin manual is just "we add a pro by hand"). This keeps the architecture honest without building the Google integration yet.
New mechanic 2
2

Intermediated communications

We no longer unlock phone/email on connection. All tenant↔pro communication runs through the platform.

sequenceDiagram
  actor T as Tenant
  participant TT as True Trade
  actor P as Pro
  T->>TT: Message (scheduling, access notes)
  TT->>P: Relayed — no phone / email shared
  P->>TT: Reply
  TT->>T: Relayed
  Note over TT: Full thread retained for safety & dispute evidence
      
Why
Keeps the platform in the relationship (anti-leakage), creates a safety + dispute record, and means a bad actor can be cut off instantly. Replaces the old "contact unlock".
Edge cases
Pro asks for the tenant's number off-platform → flag/soft-block. Tenant needs the pro fast → in-app push/notification.
MVP build: a simple in-app message thread on the connection (one thread per connection, both sides + admin can see it). Web launch: in-app notifications (+ optional email nudge). WhatsApp notifications are a fast-follow — a "new message / pro on the way" push that pulls people back into the app, while the thread itself stays in-app so it remains intermediated. Admin can read threads for support/disputes.
New mechanic 3
3

Firm quote before dispatch → on-site scope confirmation

We bind the price before the pro travels. After selection the pro turns the estimate into a firm quote the tenant accepts; on arrival the step is a quick scope check, not a renegotiation — so a pro never drives out on an un-agreed price.

flowchart TD
  SEL["Tenant selects pro"]:::cust --> FQ["Pro sends firm quote
(pre-dispatch)"]:::new FQ --> ACK["Tenant accepts → price locked"]:::new ACK --> ARR["Pro travels & arrives"]:::pro ARR --> CHK{"Scope matches
the brief?"}:::new CHK -->|"yes"| GO["✅ Confirm → payment captured → work begins"]:::new CHK -->|"no · evidenced
scope change"| REP["Pro re-prices with photo"]:::new REP -->|"tenant accepts"| GO REP -->|"declines · good faith"| WV["Clean cancel · trip fee waived / split"]:::sys CHK -.->|"tenant backs out
at locked price"| FEE["Trip fee → pro"]:::new classDef cust fill:#EAF6F2,stroke:#0F7458,color:#08382C; classDef pro fill:#FDF6EA,stroke:#C57D17,color:#7a4d09; classDef sys fill:#ffffff,stroke:#1C8F73,color:#1B2A28; classDef new fill:#EFE9FB,stroke:#7C5CBF,color:#3f2a73;
The estimate becomes a firm, pre-dispatch commitment. On-site only re-opens price on an evidenced scope change — and a wasted trip is compensated by fault.
Why
The old flow re-negotiated price on arrival, so a pro could drive out and leave with nothing. Locking the quote before dispatch removes that: on-site becomes a scope check, while both sides keep the right to walk if reality genuinely differs from the brief.
Trip fee (by fault)
Tenant backs out at a locked, unchanged price → small trip fee compensates the pro. Pro hikes without an evidenced scope change → no fee + reputation hit. Genuine scope mismatch, no deal → trip fee waived or split (good faith).
Edge cases
Tenant not present (exterior jobs) → firm quote + scope check done remotely in-app from photos. Scope smaller than described → charge the lower amount.
MVP build: turn the accepted estimate into a locked firmQuote at selection. On arrival the pro taps "scope matches → start" (captures payment) or "scope changed → re-quote" (photo required, tenant re-accepts).
✅ Trip fee deferred for the pilot. Our condo pros are already on-site/clustered, so a "wasted trip" is walking next door, and gardening/car-wash scope barely deviates from a photo brief. We keep the fault policy on paper and handle any rare case as an admin-mediated manual call — the trip-fee machinery is built later, at scale.
New mechanic 4
4

Pay on start, 24-hour protection window

The tenant pays the moment work starts (on cost agreement) and has 24 hours to flag a problem — a protection window backed by a refund. Same safety for both sides; for the pilot it's built as an immediate charge + refund window rather than a literal held payout.

stateDiagram-v2
  [*] --> awaiting_confirmation: pro on site (price already locked)
  awaiting_confirmation --> cancelled: scope mismatch · trip fee by fault
  awaiting_confirmation --> captured: scope confirmed → tenant charged, pro settled
  captured --> refund_window: work begins (24h window)
  refund_window --> final: +24h, no dispute → settled, window closes
  refund_window --> disputed: tenant flags an issue in-window
  disputed --> final: admin resolves for pro
  disputed --> refunded: admin resolves for tenant → refund
  final --> [*]
  refunded --> [*]
  cancelled --> [*]
      
Charge at start · 24h refund window · admin-adjudicated disputes → refund. The pro is settled by ONVO on its normal cadence.
Why
Paying at start protects the pro from a ghosting customer; the 24h window protects the tenant (time to flag a problem and get refunded). Trust flows both ways, and the customer fee funds the satisfaction guarantee.
Edge cases
Dispute in-window → admin mediates → stands or refund. No dispute → window closes clean. The service was rendered, so disputes are reviewed, not auto-refunded.
Payment rail: card on file (SINPE Móvil is push-only and can't auto-charge). Charge is captured immediately on cost agreement via ONVO's marketplace split, and the 24h window is enforced as a refund window.
Decided: immediate capture + refund for the pilot — simpler and depends on no unverified ONVO behaviour. A true 24h payout hold (pro doesn't see the money until the window clears) is a later refinement. Full reasoning + audit on Build plan →
💰 Fee model and why recurring needs a card on Economics → · payment build detail on Build plan →
New mechanic 5
5

Two-sided reviews → mutual cadence

After the job, both rate each other. Only if both reviews are positive — and both opt in — does the job become a standing cadence.

flowchart LR
  REL["Payment final"]:::sys --> R1["Tenant reviews pro"]:::cust
  REL --> R2["Pro reviews tenant"]:::pro
  R1 --> Q{"Both positive?"}:::sys
  R2 --> Q
  Q -->|"no"| END(["Done — one-off"]):::sys
  Q -->|"yes"| OFFER["Offer a recurring cadence"]:::new
  OFFER -->|"both agree"| PLAN["Standing plan
(card on file, auto-scheduled)"]:::new OFFER -->|"either declines"| END classDef sys fill:#ffffff,stroke:#1C8F73,color:#1B2A28; classDef cust fill:#EAF6F2,stroke:#0F7458,color:#08382C; classDef pro fill:#FDF6EA,stroke:#C57D17,color:#7a4d09; classDef new fill:#EFE9FB,stroke:#7C5CBF,color:#3f2a73;
Why
A mutual-positive gate means cadences only form on relationships that actually worked — quality control on both sides, no forced lock-in. This is the retention engine.
Edge cases
One side negative → no cadence offered. Both positive but one declines cadence → stays one-off, can rebook later. Recurring charges run on the card on file.
MVP build: reuse the existing two-sided review + recurring-plan models (already in the demo); add the "both positive AND both opt-in" gate before a plan can be created.
Who does what

Roles in the MVP — manual vs automated

At pilot scale we do a lot by hand on purpose. This is what each role does, and what's automated vs. a human (us) in the loop.

RoleIn the MVP they…Mode
Tenant (customer)Request a job, compare, select, chat in-app, verify cost on-site, pay, review, opt into cadence.Self-serve
ProGet onboarded by us, receive outreach, estimate, accept, chat, confirm cost on-site, do the work, get paid +24h, review.Hand-onboarded then self-serve
Admin (us)Seed pros, qualify jobs, run sourcing fallback by hand, monitor threads, mediate disputes, release/verify payouts.Hands-on
Building (condo admin)Lend the brand, greenlight the pilot, point tenants to the portal. Sees privacy-safe activity only.Partner
Scope

What we reuse, build, and defer

Much of the loop already exists as a demo. The MVP is mostly the new mechanics + real payments on top.

CapabilityStatusNotes
Chat intake → brief + photosReuseExists; add building-branded entry.
Building-branded portal (white-label)ReuseOrg/building model + /b/:slug exist.
Compare → select → pro acceptsReuseExists in demo.
Two-sided reviews + recurring plansReuseAdd the mutual-positive + opt-in gate.
Admin console (jobs, pros, connections)ReuseAdd sourcing-fallback + payout controls.
Pro sourcing priority + fallbackBuildIn-platform live; Google + manual stubbed.
Intermediated comms threadBuildIn-app thread per connection; no SMS yet.
Firm quote (pre-dispatch) + on-site scope confirmBuildLock quote at selection; scope check triggers payment; trip-fee backstop.
Real payments + 24h refund windowBuildCard on file; immediate capture + refund window.
Pro payout onboardingBuildProcessor sub-account / KYC, done with us.
Dispute handling (in 24h window)BuildMinimal: freeze + admin decides.
Google Places integration (live)DeferStub now, build when supply needs it.
SMS / phone maskingDeferIn-app messaging is enough for pilot.
Self-serve pro onboardingDeferWhite-glove by hand at pilot scale.
Native apps · multi-building · automationDeferMobile web; one building; humans in loop.
Under the hood

Data model deltas

What the new mechanics add on top of the existing entities (Job, Pro, Connection, Estimate, Review, RecurringPlan, Organization, Home).

New / changedShape
Job.sourcingsource: in_platform | google | admin_manual + sourcing status, so we can see how each job was filled.
MessageThread (new)One per Connection. messages[] (sender, body, ts), visible to tenant, pro, admin.
Connection.quote (new)firmQuote, quoteLockedAt (pre-dispatch), scopeConfirmedAt, reprice{amount, photo}, status: quoted|locked|confirmed|repriced|cancelled, tripFee{amount, owedBy}.
Payment (new)amount, fee, state: captured|refund_window|refunded|disputed, capturedAt, refundWindowUntil (+24h), processorRef.
Pro.payoutAccount (new)Processor sub-account id + KYC/onboarding status (can they receive payouts yet?).
RecurringPlan.gateRequire bothReviewsPositive && bothOptedIn before a plan can be created.
Dispute (new, minimal)connectionId, raisedBy, reason, resolution: upheld|refunded, decidedBy.
Sequencing

A build sequence

A suggested order — each milestone is independently demoable, so we can review as we go.

M0
Pilot setup (no code). Sign one building, hand-pick & interview ~3–5 pros, confirm the processor + fee model on Decisions, validate ONVO onboarding for these pros.
M1
Seed + branded intake. Manually load the condo + its pros; building-branded portal → intake → admin qualifies. (Mostly reuse.)
M2
Sourcing + select + accept. In-platform sourcing (priority), compare, select, pro accepts. Google/manual stubbed.
M3
Intermediated comms. In-app thread per connection, admin-visible.
M4
Firm quote + scope confirmation. Lock the quote before dispatch; on-site scope check (re-quote only on evidenced change) → unlocks payment; trip-fee backstop (manual at pilot).
M5
Payments + 24h window. Card on file, immediate capture on agreement, 24h refund window, admin-adjudicated disputes.
M6
Reviews → cadence. Two-sided reviews + mutual-positive opt-in gate → recurring plan on card on file.
M7
Run the pilot. Real tenants, real jobs, real money. Watch leakage, disputes, repeat rate. Decide what to automate next.
Resolve before / during build

Open questions

  1. Settlement & clawback: how fast does ONVO settle the pro, and how does a refund claw back within the 24h window if the pro is already settled?
  2. Pro KYC: can our condo pros actually onboard for payouts (tax/bank docs)? This gates everything — validate first.
  3. Trip fee: what amount + fault rules? → Deferred for the pilot (pros are on-site; handled manually if it ever comes up).
  4. Scope-confirmation UX: what happens if the tenant isn't physically present when the pro arrives (exterior jobs)? Remote confirm via the app from photos?
  5. 24h dispute scope: what counts as a valid in-window dispute, and who decides (us, by hand, at pilot scale)?
  6. Fee model: with recurring on cards (~3.5%), is processing passed to the tenant, tiered to the pro, or absorbed? (Decision 3.)
  7. Comms guardrails: how hard do we discourage off-platform contact-sharing without making the pilot feel heavy?
  8. Building agreement: what does the condo administration get/expect, and what privacy-safe view do they see?
🧭 These roll up into Decisions →