Investor roadmap · Harare
How to read
this page

The roadmap is a register, not a promise.

Every idea below exists in the repository's governance register with a written trigger, and this page is generated from that file — it cannot say more than the register says. What has shipped is listed as shipped. Nothing here is a mockup, and there are no screenshots on this page by rule: the working product is at nharaunda.co.zw, one click away, and a design that looks like a screenshot is a fake screenshot.

Provenance. Sections two to four are built from 03-STRATEGY/BANKED-IDEAS.md in the order fixed by ADR-016; a repository test fails if this page and the register disagree. The product currently runs on a demo estate carrying EXAMPLE-stamped data only — a live pilot is gated on lawful-basis and provider-verification work that is deliberately human, not code.
Now
exists, live

Shipped, deployed, and enforced in three layers.

The core loop is not a demo path — its rules hold in the database, in the API, and in the UI, and the test suite attacks all three.

  • Live at nharaunda.co.zw The ticket loop, end to end File → assign → resolve → review. A ticket cannot be resolved without an assigned provider — a database constraint, an API check, and a UI gate, independently. Every transition is an append-only event; current state is derived, never edited.
  • Vouched providers, earned ratings Managers add and vouch for providers. Ratings are computed server-side from reviews that require a resolved ticket linking reviewer to provider — one review per ticket, enforced by trigger. Jobs take bids; an award locks bidding.
  • Privacy as code paths, checked in CI Data export and anonymization are endpoints with an append-only log, mapped row-by-row to the Zimbabwe DPA policy skeleton — and a drift detector fails the build if a policy claim loses its code.
  • Operations that have been drilled, not described Health-gated deploys with automatic rollback (drilled on a deliberately broken release), off-box uptime monitoring proven by stopping the app on purpose, scrubbed JSON logs.
  • The onboarding surface Estate setup, providers and vouching, residents and handoff — the manager's own hands in the product, behind the direct relationship that remains the only door in.
Closed in the register

Rows the register has struck since — shipped, and kept here with the trigger they were banked under, so the promise and the delivery sit on the same page. The strike is the register's own mark; this page quotes it rather than tidying it away.

Owner-visible escalation

TriggerADR-006 — scoped for 6b, ranked above the job board in pilot value. Row closed — see ADR-006.

The register's rowOwner-visible escalation (stale ticket surfaces to the absentee owner) — BUILT 2026-08-16 (ADR-006): the owner role's read-only Attention list, deployed with the batched merge.

Common-area tickets

Trigger6b or later. Row closed.

The register's rowCommon-area tickets — BUILT (unit_id nullable, estate-scoped; migration 0007_common_area on adr006-owner-role).

Announcements

Trigger6b or later; low risk, no moderation load. Row closed — see ADR-019.

The register's rowAnnouncements — BUILT 2026-08-16, pulled forward by ADR-019. One-way manager broadcast, no comments, no reactions, inspection and access notices included. The row carried no demand trigger, only "6b or later", so ADR-019 records this as a scheduling decision rather than a trigger claim.

Exit survey on move-out

TriggerADR-007 — 6b or later. PULLED FORWARD by written owner ruling, 2026-08-16 ~19:28 (the Tuesday-night push; ADR-019 pattern — Tier A scheduling per ADR-016 §2's "none needs a trigger", not a trigger claim). A recorded act (one structured reason at move-out), never a score — ADR-007's constraints ride along. Row closed — the deactivation ceremony privacy claim B6 promised now has its code path too.

The register's rowExit survey on move-out — BUILT 2026-08-16, merged 2026-08-17 (migration 0012_exit_survey, app/departures.py). ("why are you leaving?" → preventable churn) — and the move-out flow it rides on: privacy claim B6 promises manager deactivation and no code path existed, so the deactivation ceremony and the survey land together (the survey is offered to the resident in person at key-handback, the walk-in doctrine's mirror — a deactivated account cannot sign in to answer later)

Multi-estate manager switcher

Trigger6b — manager_estates already supports it; only the UI is missing. PULLED FORWARD by written owner ruling, 2026-08-16 ~19:05 (the Tuesday-night push). Row closed — built the day after the UI was all that was missing.

The register's rowMulti-estate manager switcher — BUILT 2026-08-16: the board narrows to one held estate (/w/home?estate=), handlers enforce the scope, the control renders only when there is a choice.

Community fund / pooled levies

TriggerVoting module live + a pilot estate runs a real fund. PULLED FORWARD by written owner ruling, 2026-08-17 ~20:30 — the voting half of the trigger dropped (ADR-026: the fund records a decision the committee already made in the room). Custody version — holding residents' money — stays REFUSED: that's deposit-taking, an RBZ question, and makes Nharaunda a party to disputes it should only record.

The register's rowCommunity fund / pooled levies (security fund, road repairs) — ledger-only version BUILT 2026-08-17 (ADR-028, migration 0019_community_fund): append-only entries, server-derived thermometer, overspend inexpressible by trigger.

Estate decisions / voting

TriggerA pilot estate asks to run a real decision through the platform. PULLED FORWARD by written owner ruling, 2026-08-17 ~21:10 — made with the pattern-interrupt paragraph below read aloud first, which is what it is for.

The register's rowEstate decisions / voting (elected committees, levy approvals) — BUILT 2026-08-17 (ADR-029, migration 0020_estate_decisions): positions titled by the estate, self-nomination, secret-by-construction ballots, tally at close, ties refuse — the one place a decision completes inside the product, and the ADR says so.

"On my way / started" provider status

TriggerThe first pilot resident asks "is anyone coming?" — predicted week one. PULLED FORWARD by written owner ruling, 2026-08-16 ~19:05 (the Tuesday-night push): the predicted week-one ask is built ahead of being asked. Field-service canon's single most-loved feature (Housecall Pro's On My Way); it fits the paper-trail doctrine exactly because it is a recorded act, not a message. Source: field-service + resident-app survey, 2026-08-16. Row closed — state is DERIVED from the trail, so reassign and resolve reset it with nothing stored.

The register's row"On my way / started" provider status — BUILT 2026-08-16, merged 2026-08-17 (migration 0015_en_route, renumbered off 0011 when payments took that slot). One append-only event on the ticket trail (ticket_events, the spine already built for this), resident-visible on their card

Landlord / owner dashboards

TriggerA real landlord or managing agent, having seen the demo, asks for the view across more than one property — the request written down, dated, with their name (ADR-016). PULLED FORWARD by written owner ruling, 2026-08-16 ~19:05 (the Tuesday-night push): the portfolio width builds now, inside the row's own constraints — read-only rollups, query scope not feature fork, no per-tier split.

The register's rowLandlord / owner dashboards — BUILT 2026-08-17 night (ADR-027, /w/portfolio): one row per property, most-stale first, on ADR-025's own VIEW_PORTFOLIO gate (Max tier). The wide ruling's landlord-PMS exclusion dissolved when ADR-025 opened the PMS; the owner ruled the build. (added 2026-08-16). The floor is already settled: ADR-006's amendment makes the owner a fourth can()-governed role whose home screen is the ledger month view — that IS the single-home landlord's dashboard, simple by construction, and it ships with the role, not with this row. What this row banks is the width: the same server-derived reads rolled up across a portfolio — one card per property for the landlord with three, a list with stale-counts for the managing company with thirty (the manager_estates precedent: scaling is a query scope, never a feature fork). Constraints carried in the row: read-only rollups of what the ledger already derives — no money columns, no new write paths, no per-tier product split; "property-manager happy" means the month view and stale list at portfolio width, not a second product.

Offline write-queue

TriggerADR-002 — a real pilot resident reports losing a ticket to a dead connection. PULLED FORWARD by the wide build ruling, 2026-08-16 ~19:36. Row closed — law and code moved in the same commit, the full loop walked in a browser.

The register's rowOffline write-queue (file a ticket offline, syncs later) — BUILT 2026-08-16 (ADR-002 Revision 2): the resident file form queues to this phone and flushes on reconnect, leaving the queue only on a 201; everything else stays blocking-only. The promise-to-send copy ban inverted lawfully — the promise appears only on the surface that keeps it, guard-tested.

Month-end estate report

TriggerA pilot committee or managing agent asks for the written artifact. PULLED FORWARD by written owner ruling, 2026-08-16 ~19:05 (the Tuesday-night push). Row closed — built the same day the ruling opened it.

The register's rowMonth-end estate report (filed / resolved / days-open / who did the work, per estate — the managing agent's "report that ends arguments at the AGM", 01-PRODUCT/APPFLOW.md) — BUILT 2026-08-16: /w/month/report/{estate}, per estate for any named month, printable, from the same rows the live board reads.

Provider work-history export

TriggerPost-pilot, trigger unchanged — priority note raised 2026-08-16. The macro thesis made concrete; philosophically identical to CareerMate's credentials. The field-service + resident-app survey confirms the visible accumulating record is the supply-side retention mechanism; the gig-economy finding sharpens why: the inDrive Zimbabwe market-entry pattern (negotiation over algorithm, cash-native, driver-as-person) shows the platform that serves the worker rather than extracts from them wins this market — and the outward-shareable record is the serving, made concrete. The provider seeing their own card shipped 2026-08-16. PULLED FORWARD by the wide build ruling, 2026-08-16 ~19:36. BUILT the same evening: /w/record — the printable CV, provider-only, derived from provider_ratings and the events spine, no new writes. The no-places rule (estate names and unit labels never appear on the outward-shareable document) and the own-record gate were each bitten before being trusted. Row closed — the export exists; whether a provider can carry it to another estate is the post-pilot question this row leaves open.

The register's rowProvider work-history export — BUILT 2026-08-16, merged 2026-08-17 (/w/record). (the informal-economy CV — a portable, verifiable record) and, more broadly, the provider's own record as a first-class motivation surface

People-home counts row

TriggerThe first onboarding where a manager loses track of who has activated. Row closed — pulled and built by ADR-039, the month-end-report precedent.

The register's rowPeople-home counts row (added 2026-08-26, the admin-borrow reading — M365 Users / Zoho Directory dashboard at estate level; ADR-039) — BUILT 2026-08-26 under ADR-039's owner-ordered exception. Residents · not joined yet · pending requests, one mono row on the manager's residents screen: onboarding state a manager must act on (chase the key handover, answer the join request). Constraints carried in the row: operational state only, never activity analytics — resident sign-in charts and most-signed-in tables are refused in the same reading (ADR-008: a landlord watching tenants), and this row does not open that door.

Portfolio direction

TriggerConsole v2's own trigger at landlord width: enough real history that direction is honest, or a landlord asks what changed. Row closed — pulled and built by ADR-039.

The register's rowPortfolio direction (added 2026-08-26, same reading — console v2's "a number becomes insight when it carries direction", first slice at landlord width; ADR-039) — BUILT 2026-08-26 under the same exception. Filed-this-month gains last month beside it with a direction mark, rendered only where the prior month holds real history — the honesty condition travels with the borrow: no trend theater over an estate's first weeks.

Accounting-lite

TriggerOPENED — builds now under ADR-040. Row closed 2026-08-27: the three surfaces landed — the arrears tile and list (board and month view), the expense form (month view), and the income-and-spending chart (month view), each gate-answered rather than role-tested. The Gate 3 questions still verify rather than precondition. Two figures went BEYOND the row as written and are recorded here rather than left for a future session to find: aging buckets (current / 31–60 / 61–90 / 90+) and a spend-by-category ranking — both enumerations of rows already held, both inside §1's "enumerated and summed", and neither multiplies a debt by the time it has been owed.

The register's rowAccounting-lite — the ledger learns to add — BUILT 2026-08-27 (migrations 0029_expenses / 0030_expense_category, app/money.py, the three can() rows, and the three surfaces on the board and month view). (opened 2026-08-26 by written owner ruling, ADR-040 — the incumbent-dashboard comparison; ADR-030's second recorded exception, made with the refusals it overrides read back first). Three surfaces on existing screens: the arrears list and total (unpaid charges enumerated and summed — never penalty or interest math), monthly income/expense summaries from acknowledged records, and estate_expenses — an append-only expense ledger (a correction is a further entry, the rent discipline; joins MONEY_TABLES_ALLOWED as the ADR-040 admission). Constraints carried in the row: server-derived and acknowledged-only; current-landlord visibility only (ADR-008's named alternative — nothing travels, aggregates across estates, or scores); custody, collection, and every tax-shaped output stay banned exactly as before (ADR-038 parts 2–4, ADR-020 §2).

Next
pre-approved

The queue is ruled in advance, in this order.

Building resumes on a finding from a real human — a lawyer's answer, a provider's reaction, a landlord's objection, a tester's stumble — not on enthusiasm and not on an empty queue (ADR-016). Rows wait here pre-approved, in pilot-value order, and move up to the shipped record when they close. Only a written ruling adds a row; nothing joins the queue by momentum.

Every pre-approved row has shipped. The queue is empty until a written ruling refills it (ADR-016) — nothing joins it by momentum. What still waits on evidence is below.

Unlocked
by data

Banked until a named trigger fires.

Each of these waits on evidence — usually a real user asking, in writing — not on a hunch. Banked is not rejected: the row records the idea and its trigger so nothing is re-litigated from scratch. Tap a row for the register's full text.

Rent collection via Paynow

TriggerA paying pilot estate requests it in writing + Gate 3 names Paynow as processor. OPENED 2026-08-26 by written owner ruling (ADR-041, the market opening) — the demand trigger dropped, the risk acceptance recorded in the ADR; the processor-naming half survives as a LAUNCH condition, not a build condition: the privacy policy names Paynow before the first real transaction. The 2026-08-16 technical-readiness note governs the build: per-landlord merchant integration (the landlord's own integration ID/key = structurally zero custody), redirect + status-webhook, EcoCash/OneMoney/cards, §9 state machine, ADR-015 throttle on initiation. Custody and escrow stay banned with no trigger (ADR-020 §2). Build: market-opening plan Phase 1. Row closes when a real charge is payable end to end.

The register's rowRent collection via Paynow — zero-custody

Attachments

TriggerPULLED FORWARD in part by the wide build ruling, 2026-08-16 ~19:36: the mechanism builds, with the work-evidence and inspection-report faces. The lease-PDF and proof-of-payment faces stay gated — the same ruling excludes landlord-PMS features by name, and those two are its clearest cases. Build it once, when the first demand trigger fires. Sources: field-service + resident-app survey and the lease/roles session, both 2026-08-16.

The register's rowAttachments — ONE upload mechanism, post-pilot infrastructure (consolidated 2026-08-16, absorbing the former proof-of-payment and photo-attachment rows). Four use cases feed the same mechanism: (1) the lease PDF on the tenancy; (2) proof-of-payment — resident submits, landlord verifies: a two-act record, ledger-only, no custody; (3) work-evidence photos (before/after on a resolved ticket); (4) inspection reports. Tenant-facing faces: the lease view and a house-rules page (announcements' static sibling).

Resident types: owner vs renter

TriggerGenuinely new, genuinely sound. Revisit when a pilot estate actually contains both, since the flows differ only if both exist.

The register's rowResident types: owner vs renter (different app flows — a renter raises issues to a landlord; an owner-occupier has no landlord above them)

Provider categories beyond the current trades

TriggerDemand-pulled only: a resident of a live estate requests the category through the platform. job_category is a Postgres enum — adding one is a deliberate migration, which is the discipline. Never supply-pushed to look fuller. Naming note (2026-08-26, Gumtree survey): when a category is added — or an existing label questioned — check the wording against Gumtree ZA's services taxonomy, years of encoded evidence of what ordinary people actually type; the "Borehole and water" relabel is the precedent, and app/copy.py is where labels live.

The register's rowProvider categories beyond the current trades (barbers, dressmakers, fitness coaches, wedding planners…)

Delegated / limited roles

TriggerA real pilot manager asks to delegate a subset. The SELF-SERVE delegation UI (a manager appointing and scoping caretakers themselves) keeps the original trigger: a real pilot manager asks. Source: lease/roles session, 2026-08-16; ADR-031.

The register's rowDelegated / limited roles (caretaker-tier) — a manager hands a subset of their permissions to someone else. Constraint carried in the row: any new role expresses as data the ONE can() function reads — never per-route logic. BUILT in its fixed-kit form 2026-08-17 (ADR-031, owner-ruled): the caretaker role, one join table, ticket kit + notices, operator-created accounts.

Native mobile app / Play Store

TriggerA pilot resident reports being unable to do something the PWA can't (e.g. photo attachment). PULLED FORWARD by the wide build ruling, 2026-08-16 ~19:36 — queued last: the PWA already gives home-screen install, offline shell and low data, so this ships value only at the store-listing margin. In-repo half BUILT 2026-08-17 (stable manifest id, honest-404 /.well-known/assetlinks.json, twa/twa-manifest.json, runbook 06-OPERATIONS/TWA.md, guarded by tests/test_twa.py; the web manifest KEEPS display: browser — the shared-phone address-bar security choice stands, and the TWA's chrome is removed by asset-link verification, not by that field); the row stays open only on the Play listing: the owner half ran 2026-09-01 (keystore created — SECRETS-TRACKER — signed .aab/.apk built, fingerprint live at /.well-known/assetlinks.json), and a sideloaded install opened without a URL bar the same morning — the asset link verifying on a real phone. Closes when the Play listing is live. No service worker, deliberately: ADR-002's read-cache trigger is unchanged.

Manager-account operator script

Trigger"The first time a real estate onboards" — verbatim from the runbook (01-PRODUCT/APPFLOW.md). The first onboarding is manual by design: the notes from doing it by hand are the script's spec, and a script written before them would encode guesses.

The register's rowManager-account operator script (narrowed 2026-08-16, ADR-017: the onboarding surface moved estate, units and resident creation into the manager's own hands — what remains manual is the one insert that IS the self-serve wall: the manager users row)

OTP sign-in

Triggerv1 trigger unchanged: the first pilot onboarding shows manager-set passwords actually failing — residents locked out faster than a manager can reset. Until then: passwords, walked in person — which is also the founder in the room, which the pilot wants anyway. Source: onboarding runbook 01-PRODUCT/APPFLOW.md + gig-economy findings, 2026-08-16.

The register's rowOTP sign-in — sequenced design, still trigger-gated (amended 2026-08-16). v1 = SMS via a local gateway (txt.co.zw class). Requirements when the trigger fires, in order: (1) Gate 3 closed AND the specific gateway named in the privacy policy as a processor — ask where their infrastructure sits, because a Zimbabwe-domiciled processor shrinks the cross-border consent brief; (2) ADR-015's throttle wrapped around the OTP-request endpoint before it answers its first request — an unthrottled OTP sender is an SMS-cost amplifier, and the throttle's design already covers it; (3) a channel-agnostic send_otp interface so a second channel slots in without rework. v2 = WhatsApp, additive never replacing — SMS stays the floor because every phone works; v2 keeps its own separate trigger (a real tester failing on the current surface + the volume to justify Meta verification and BSP costs).

AI triage / provider suggestion

TriggerRung 3 evals exist AND the AI beats the deterministic baseline. Even then it proposes to a human; it never auto-assigns.

Public-sector ticket recipients

TriggerGenuinely new. Needs an actual government counterparty willing to receive tickets — and it is architecturally closer to ZAX than to Nharaunda. Revisit as a ZAX vertical, not a Nharaunda feature.

The register's rowPublic-sector ticket recipients (council, police station, school receiving issues)

Renovation project beyond job → bids → award

TriggerA pilot landlord runs a real renovation through the job board and the existing flow proves insufficient. The job board itself is built — this row is only what would sit on top of it.

The register's rowRenovation project beyond job → bids → award (phases, milestones, progress for a landlord's build)

Estate reputation as public asset

TriggerPhase 1 PULLED FORWARD by written owner ruling, 2026-08-16 ~19:05 (the Tuesday-night push). Phase 1 BUILT 2026-08-16: /lookup, public, exact-match confirm-only, every ask throttled (app/throttle.py reused as ADR-015 predicted), a miss reveals nothing. The exact-match and throttle guards were each bitten before being trusted. Phase 2 trigger: an estate ASKS to show its record off-platform (predicted: the first committee that wants to justify its levies or its rents) — and, carried from the absorbed row, only once the ledger has enough real history for the numbers to be honest. Phase 3 carries no trigger of its own: it is what Phase 2 at scale may become, governed by the rules already written in this row.

The register's rowEstate reputation as public asset — phased (expanded 2026-08-16, absorbing the former "Estate reputation page" row; this is the mover's question, answered by records). Phase 1 — the lookup, banked earlier and unchanged: "is my estate on Nharaunda?" answered confirm-only; no browsing. Phase 2 — the estate MAY opt to publish its own operational record: median resolve time, tickets handled, tenure of providers — a public proof page THE ESTATE controls, like a restaurant framing its certificate. Aggregate facts only; no individual reviews exposed; no ranking, no comparison UI, no browsing index. Phase 3 — the horizon, explicitly NOT a commitment: if dozens of estates publish, discovery emerges — and the rule is set NOW, before any incentive exists to break it: reputation pages are estate-owned, fact-derived, never purchasable, never ranked by us. The mover finds a greatly-run place because the place PROVED it, not because anyone paid. Refused, restated: building the browse/search/compare consumer product ahead of the supply that makes it honest — the mover's answer at estate-one is the truth: "not yet — the records have to exist before anyone can settle by them." (The NEVER-table rows on listings/discovery and paid placement govern every phase.)

Operator console v2

TriggerPULLED FORWARD by written owner ruling, 2026-08-16 ~18:10 — the register amendment this row's own doctrine requires. Scope of the pull: the four-layer v2 ("the company, thinking" — KPI deltas, server-side SVG charts from the events spine, rules-engine insight sentences with the AI-adviser data contract, action queue) builds NOW on branch operator-console-v2, exercised against a synthetic 12-month seed for the Tuesday projection screen. The honesty condition that made the original trigger is not waived, it is relocated: live data still cannot power these charts, so the seeded console is labelled as projection on the screen itself (§4 — fabricated rows never render unstamped), and the insight layer's rules run on real data from day one at whatever sparseness exists. Original trigger retained for switching the Tuesday projection OFF: 60+ days of usage_events AND a second estate make the projection seed unnecessary.

The register's rowOperator console v2 — from counters to insight (banked 2026-08-16, from the owner's M365-admin comparison on the v1 console). Four upgrades in one row: (1) deltas and sparklines on MRR, signups and usage — a number becomes insight when it carries direction; (2) per-estate engagement with a going-quiet early warning — the stale-ticket doctrine applied to the vendor's own customers, the churn signal every B2B admin product lives on; (3) every tile a door — the unpaid-invoice count opens the invoice and its mark-paid act, usage rows open their estate; (4) box health inline beside adoption (the UptimeRobot signal on the company screen). v1's scalars-only form is correct today, not a gap: trends over one estate's first weeks would be theater, which §4's honesty doctrine refuses.

Declared SLA

TriggerA committee asks for a stated promise, or pilot latency data (the time-to-assign / time-to-first-action derivations) shows the need. Written down, dated, named (ADR-016). Source: owner instruction, 2026-08-18.

The register's rowDeclared SLA — an estate states a response promise; the record witnesses it (banked 2026-08-18 by owner instruction — the router question: everything depends on the manager, and the current answer is visibility, not promises). The estate itself declares a response promise ("acknowledged within 48 hours"); the record derives compliance from ticket_events; the month report carries the derived compliance figure beside median-resolve; chronic breach is what the ADR-006 owner escalation already surfaces. An SLA witnessed, never enforced: the product records the promise and the facts against it — it does not act on breach. Constraints carried in the row: the promise is the estate's own declaration, never a platform default and never nudged; compliance is server-derived from the append-only trail, never self-reported or client-computed; breach triggers nothing beyond the visibility surfaces that already exist (stale list, attention list, month report) — no auto-escalation, no penalties, no dispatch. The measurement floor this row stands on — time-to-assign and time-to-first-action derived on the month report — is truth-work on what is already built and ships ahead of any promise (2026-08-18).

Resident direct engagement

TriggerA real resident of a live estate asks to engage a provider directly through the platform. Written down, dated, named (ADR-016). Never supply-pushed to look busier. Source: owner instruction, 2026-08-18.

The register's rowResident direct engagement — non-structural only, from the vouched pool (banked 2026-08-18 by owner instruction — the router question's second relief valve). A resident may engage a provider from the vouched pool for work that does not modify the property — the structural/consumable line, drawn per category as a deliberate act, not per ticket ad hoc. Manager routing stays mandatory for structural, common-property, and owner's-asset work: the router is relieved of consumables, never of the building. Recorded as an assignment event authored by the resident on the same ticket_events trail; resolve and review rules unchanged (provider gate, one review per resolved ticket). Constraints carried in the row: the pool stays vouched — this is NOT an open marketplace (the NEVER table governs); directory order stays deterministic — no ranking, no suggestion; no payment enters the product; the manager sees every resident-authored engagement on the same board, because the record is the point.

Quarterly tenant-register / rent-record export

TriggerA real landlord asks in writing (ADR-016 form). Predicted asker: the first pilot landlord with a business tenant — a shop unit or registered home business — since residential-only landlords sit outside the regime as reported.

The register's rowQuarterly tenant-register / rent-record export (added 2026-08-17, ADR-038 — written as ADR-028 before the renumber). ZIMRA's 2026 presumptive regime requires registrable proprietors (business tenancies) to file quarterly tenant registers and occupancy lists — and Nharaunda already holds the facts that would populate one. Constraints carried in the row: an export of acknowledged facts stamped as records — never formatted as a tax return or filing, never computing a liability, never sent anywhere by the platform itself. The landlord downloads their own facts and decides what to do with them; anything more is tax intermediation, which the perimeter (05-GOVERNANCE/NHARAUNDA-REGULATORY-PERIMETER.md) refuses.

Appointment window on assignment

TriggerA pilot resident or manager asks when someone is coming — predicted early, the en-route row's sibling ask. Written down, dated, named (ADR-016).

The register's rowAppointment window on assignment (added 2026-08-26, Zoho Desk/FSM concept survey — DR-2's sanctioned pattern: inspired-by, never resold). When a manager assigns, an optional expected-visit window ("Tuesday morning") the resident sees on their card — the answer to the WhatsApp group's single most-asked question, recorded as a fact on the assignment. Constraints carried in the row: one field on the assign act, never a calendar engine, never a dispatch console, never technician tracking (the FSM features this row deliberately does not import — live GPS and timesheets are worker surveillance, and the /w/record thesis serves the worker instead); the window is the manager's stated expectation, a recorded act on the trail, not a platform promise.

Structured closure

TriggerA pilot committee or owner asks what a resolved ticket actually got them, or a review dispute turns on what was done. Written down, dated, named (ADR-016).

The register's rowStructured closure — "what was done" (added 2026-08-26, same survey; FSM's job sheet cut to its honest core). Resolve gains a short completion note in the resolver's own words, stamped into ticket_events detail — the record of the act in the actor's voice, beside the work-evidence photos the attachments row already carries. Constraints: free text, never a scored checklist (a checklist grades; a note witnesses); required-ness is the estate's choice, not a platform default.

Duplicate-ticket merge

TriggerThe first real duplicate pair in a live estate — predicted for common-property failures (gate, borehole, wall).

The register's rowDuplicate-ticket merge (added 2026-08-26, same survey; Desk's merge, append-only-shaped). Two residents report the same broken gate; the manager marks one ticket as duplicate-of the other with an event on BOTH trails — both filers keep visibility of the surviving ticket's progress, nothing is deleted, the boring list stops double-counting. related_ticket_id (0010) is the schema seed.

On-behalf filing with a source stamp

TriggerThe pilot manager reports tickets arriving by phone or in person that never reach the app — predicted week one, the walk-in doctrine's ticket-shaped case. Written down, dated, named (ADR-016).

The register's rowOn-behalf filing with a source stamp (added 2026-08-26, same survey; multi-channel intake domain-shaped — the phone call and the corridor conversation captured without the banned WhatsApp surface). A manager or caretaker files for a unit, and the ticket carries "filed by the manager for Unit 4" as a visible fact — never impersonation, and the resident sees their ticket like any other.

Estate assets and preventive schedules

TriggerPhase 1: a manager asks "what's the history on this borehole?" — the question the append-only trail exists to answer. Phase 2: a manager asks for a service reminder, or an asset fails for want of scheduled service a pilot estate can name. Written down, dated, named (ADR-016).

The register's rowEstate assets and preventive schedules (added 2026-08-26, same survey; FSM's asset history + recurring work orders, the category's largest true gap). Phase 1: the borehole, the gate motor, the pump as first-class records — each common asset carrying its own ticket history, which the common-area spine (0007) already almost gives. Phase 2: a service schedule on an asset generates the recurring ticket ("borehole service due") into the normal loop — filed, assigned, resolved, reviewed, no new lifecycle. Positioning note, honestly carried: COMPETITIVE-POSITIONING.md currently marks preventive maintenance out-of-category ("—"); building Phase 2 amends that mark, an owner positioning decision this row does not make.

Job-post friction pass

TriggerA pilot poster struggles with or abandons the job form — observed in person or reported. Written down, dated, named (ADR-016).

The register's rowJob-post friction pass — photo-first, progressive disclosure (added 2026-08-26, Gumtree pattern survey — the classifieds incumbent read for mechanics, never model: its open-marketplace core sits on the NEVER table already). Gumtree survives on a stranger completing a post in under a minute — photo first, few required fields, everything else optional. The ticket form already carries the fifteen-second doctrine; the job-post form (title, category, description, budget) is the Gumtree-shaped surface. Constraints carried in the row: fewer required keystrokes, never more machinery — no new required fields, no draft-autosave engine; the attachments mechanism (0014/0015) is the photo path; forms doctrine (master §5) governs throughout.

Provider responsiveness on the directory card

TriggerThe pilot ledger holds enough real assignment history for the figure to be honest, or a resident asks how quickly a provider responds. Written down, dated, named (ADR-016).

The register's rowProvider responsiveness on the directory card (added 2026-08-26, same survey — Gumtree's "replies within a few hours", rebuilt on the trust ledger's terms). The directory card gains a typical-response figure — derived server-side from the same events spine the time-to-assign / time-to-first-action work (2026-08-18) already reads — beside the star average: a second decidable fact computed from real, completed work, never hand-edited. Constraints carried in the row: server-derived only, the client never computes it; a displayed fact, never a directory-ordering input — order stays deterministic; renders nothing until the history is honest (the estate-reputation row's own condition) — a sparse ledger shows no figure rather than a false one.

Report / flag on the trust surface

TriggerThe first disputed or abusive review or profile in a live estate. Written down, dated, named (ADR-016).

The register's rowReport / flag on the trust surface (added 2026-08-26, same survey — the flag-this-listing valve, table stakes on any surface strangers read). A resident or provider flags a review or a profile; the flag routes to the manager as a recorded act and the manager's disposition is recorded beside it — nothing auto-hides, no AI moderation, deterministic end to end. Review integrity is the product (master §3.3), and today the directory and its review quotes carry no abuse valve at all. Constraints carried in the row: append-only — the flag and its disposition are events, and the review row itself is never edited or deleted by a flag; manager-resolved, never platform-adjudicated.

Zero-custody caution at award

TriggerThe first real award in a live estate, or a poster–provider payment dispute reaching a manager — whichever arrives first. Written down, dated, named (ADR-016).

The register's rowZero-custody caution at award (added 2026-08-26, same survey — Gumtree's safety interstitial at the handover moment, cut to one sentence). The award act gains one line of display copy: "Agree scope and payment terms directly — Nharaunda records the work, never the money." The perimeter (ADR-038) restated at exactly the moment USD amounts are on screen, reinforcing the zero-custody position instead of undermining it. Constraints carried in the row: copy only — no payment fields, no terms capture, no acknowledgment checkbox (a checkbox manufactures consent theatre; the sentence informs).

Trade-matched job alerts for providers

TriggerChained, both required: the push-notification line lands (its own sequencing, behind Gate 3), AND a provider reports missing a job they would have bid on. Written down, dated, named (ADR-016).

The register's rowTrade-matched job alerts for providers (added 2026-08-26, same survey — the saved-search alert narrowed to one operational case). A provider is told when a job matching their trade posts in an estate they serve — the supply side of the board finding out work exists, which is the board working. Constraints carried in the row: operational notification, never re-engagement — fires only on a new matching job, no digests, no reminders, no "come back" (the NEVER table's engagement-mechanics row governs); the trade match is deterministic — no ranking, no suggestion; the payload is a scoped projection (master §2 — a lock screen never leaks another unit's issue).

Lease e-signing

TriggerThe Gate 3 engagement (or a successor) confirms an enforceable form, AND a landlord asks for signing in-app. Written down, dated, named (ADR-016).

The register's rowLease e-signing (added 2026-08-26, the incumbent's "automate rentals" read — e-agreements on the lease record). The lease-PDF attachment face exists gated; e-signing would add a signature act on it. Banked, not opened with ADR-041, because validity is a legal question before it is a feature: whether an in-app signature act binds under Zimbabwe's electronic-transactions law is a lawyer's answer, and a signature people believe in but courts do not is worse than no signature.

Self-serve estate signup

TriggerOPENED — builds as market-opening Phase 2. Row closes when a stranger can lawfully reach a working estate without an operator insert.

The register's rowSelf-serve estate signup (opened 2026-08-26, ADR-041 — the market opening; formerly on the NEVER-shaped end of master §1 with the 3+-estates condition). A landlord or manager registers and onboards their estate through the ADR-017 wizard, operator-free; botguard + ADR-015 throttle wrap registration; the operator console reviews new estates rather than gatekeeping.

In-app messaging

TriggerOPENED — builds as market-opening Phase 3. Row closes when the two thread kinds work end to end with flag and export coverage.

The register's rowIn-app messaging — scoped as records (opened 2026-08-26, ADR-041; formerly the NEVER table's DM refusal, whose moderation warning is carried as an accepted operating cost). Threads only inside schema-held relationships — resident ↔ their estate's manager, manager ↔ assigned provider on a ticket; never open DMs, never cross-estate, never resident ↔ resident. Append-only rows; the report/flag valve ships in the same phase (the Gumtree row's design, pulled in); export_user_data covers messages from day one; retention enters the privacy skeleton with the build.

Own-inventory listings and inquiry capture

TriggerCLOSED — BUILT 2026-08-27. A vacancy can be published from the unit record (PUBLISH_LISTING, vacancy enforced by 0032's trigger, one live listing per unit by partial index) and an inquiry lands on the manager's desk at /w/inquiries. The public half is two pages that take no principal at all — app/listings.py has no function whose arguments could name a second estate, which is what makes "no portal" structural rather than promised. Guards, each proved on its own: honeypot, render-time form token, and a throttle that charges every ask hit-or-miss because what is limited here is WRITING, not guessing. noindex on both pages plus a robots.txt refusal, because a set of single-estate pages becomes an inventory the moment somebody else's crawler assembles it. Inquirer PII entered the skeleton with the build (A1.13, A2.11, A3.9) and the 90-day purge runs on the desk's own read — no scheduler on this box. tests/test_listings_surface.py.

The register's rowOwn-inventory listings and inquiry capture (opened 2026-08-26, ADR-041; the NEVER table's listings refusal narrows — the PORTAL is still not our fight). An estate or landlord publishes their own vacant units (vacancy derives from tenancies); a public unit page carries an inquiry form (name, contact, message) to the landlord's desk. No search index, no crawling, no ranking, nothing purchasable — the estate-reputation rules govern the public face; inquirer PII enters the skeleton with the build; throttle on the form.

Scheduled reminders

TriggerADR-040's arrears figure is live on a real estate AND a landlord or manager asks to be told before the date rather than read it after. Written down, dated, named (ADR-016).

The register's rowScheduled reminders — one primitive, not three features (added 2026-08-27, the self-manager incumbent read; the incumbent sells the same mechanism three times over — rent due, lease renewal, general reminders — which is the tell that it is one thing). A notice that fires on a date already held on a record: a rent charge's due date, a lease term's end, a preventive schedule's next visit. Rides the existing rails — the 2026-08-25 projection + outbox architecture and the one-way announcement face — never a new channel. Constraints carried in the row: a reminder is about a dated obligation on a record, never about pulling someone back to the app (engagement mechanics stay banned by name, and this row is the exact place that line gets tested); one-way, no reply surface; the recipient can see which record fired it; no dunning sequence, no escalation ladder, and no penalty or interest math ever (ADR-040 keeps that out). The gap is real: today the product knows a date has passed only when a human looks.

Rental application forms

TriggerOwn-inventory listings (ADR-041 Phase 4) is live AND a landlord asks how to take applications, AND Gate 3 covers applicant data. Written down, dated, named (ADR-016).

The register's rowRental application forms — the honest half of the applicant flow (added 2026-08-27, same read). An applicant submits facts about themself against a published own-inventory listing — contact, employment, references they nominate — and the landlord reads what was submitted. Banked separately from screening precisely because the incumbent fuses them: an application is a record of what a person chose to say about themself, a screen is a judgment about them bought from a third party. Constraints carried in the row: no score, no ranking, no credit, criminal or eviction lookup (ADR-008 is untouched and is the reason this row must stay narrow); referees are the applicant's own nomination, contacted by the landlord not by us; a declined application leaves no portable mark on the person. The applicant is a data subject before they are a tenant, so lawful basis and a retention period are Gate 3's answer, not a build decision.

Per-property profitability

TriggerADR-040's income and expense summaries are live AND a landlord asks in writing what the property actually returns. The self-declared-figure question gets its own ADR first.

The register's rowPer-property profitability — ROI and P&L by property (added 2026-08-27, same read; the incumbent sells per-property profitability as a headline report). ADR-040 derives from the acknowledged ledger; this derives from something we do not hold — purchase price, financing, holding costs. Constraints carried in the row: whichever way it goes, MONEY_TABLES_ALLOWED governs and no balance becomes expressible; the unresolved question is whether a landlord-entered acquisition cost is admissible at all, because it would be the first figure in the system that is self-declared rather than a recorded act, and that is an ADR before it is a line of code; no valuation estimate and no market comparison, which are judgments about an asset we have no basis to make; no tax output ever (ADR-038 parts 2–4 stand).

Accounting-package export and bank-feed import

TriggerA pilot landlord's accountant asks for the figures in a format their package reads, AND the privacy policy can name exactly what leaves and to whom. Bank-feed import needs its own ADR before any work.

The register's rowAccounting-package export and bank-feed import (added 2026-08-27, same read; the incumbent ships accounting-package export and automatic bank reconciliation). Banked as one row because they share one question and may not share one answer. Export hands the landlord their OWN estate's figures in a format their accountant's package reads; import pulls bank transactions in, which means an aggregator holding the landlord's bank credentials. Constraints carried in the row: "we do not share personal data with third parties" is load-bearing on the privacy claim and on the standing public API refusal, so an export the landlord initiates for their own figures is a different act from an integration that streams data to a vendor, and only the first is plausibly buildable; the existing export_user_data() mechanism is the shape to extend, never a new outward pipe; resident-identifying detail does not travel with an accounting export. The import half is the harder one and may resolve as a refusal — split this row if the halves diverge.

Listing syndication

TriggerOwn-inventory listings is live AND a landlord says the in-app listing is not where their tenants actually come from. Needs a written ruling on whether any outward push survives the public API refusal.

The register's rowListing syndication — pushing your own unit to someone else's index (added 2026-08-27, same read; the incumbent pushes a landlord's listing out to the major search portals). Distinct from the PORTAL refusal on the NEVER table, which refuses building an index of everyone's inventory here; this is a one-way push of a landlord's own vacant unit out to property.co.zw or propertybook. Constraints carried in the row: the unit and its photos are the landlord's to publish, but estate names, unit labels and anything resident-derived never leave — the /w/record export is the precedent, a shareable document that carries neither; push only, never an inbound listing feed, which would rebuild the portal by the back door; no paid placement bought by us on the destination, because that refusal follows the data and not the surface. Undecided in both directions today, which is the defect this row closes.

Durable auth-event record, and the operator's read of it

TriggerA real account's sign-in security is questioned — a resident or manager reports activity they did not perform, or a live estate's operator needs to answer "was this account under attack last night" and finds the evidence already evaporated. Written down, dated, named (ADR-016). ADR-030 applies at full force: banked, not queued — the gap is real, and it is still infrastructure for a pilot that has not started.

The register's rowDurable auth-event record, and the operator's read of it (added 2026-08-27, OneLogin console-IA survey — the IAM incumbent read for its admin surface, never its model: an app catalog, an integrations marketplace and branded end-user portals are a different business). Two halves, banked as one row because the second is meaningless without the first. (1) The record: sign-in failures become append-only rows on the anonymization_log / capability_grants pattern every other ledger here already uses. Today they exist only as in-memory counters in app/throttle.py, which reset on every redeploy and are per-process — ADR-015 states both limits honestly rather than pretending them away, and this row is what would close them. (2) The read: a section on /w/access beside the impersonation ledger, showing recent failures by account and by address — the ledger rendered, nothing more. Constraints carried in the row: it records the auth EVENT and never a judgment about the person ("anomaly detection" pointed at residents is tenant scoring wearing a technical hat, and stays refused below); delay, never lockout — ADR-015's central design, because a resident's phone number is known to their whole estate and a lockout is therefore weaponisable against them, so a durable record must not become the thing that enables one; no automated action of any kind; retention enters the privacy skeleton and export_user_data() coverage is answered BEFORE it lands, not after.

Product two — not a feature

Everything in this block is one deferred product, not a set of features: local news feed, message board, interest groups and clubs (chess, hobbies, social), business/professional pages for local shops and services, area discovery (gyms, restaurants, things to do), "settling into a new area" tools, open marketplace for service providers, pre-colonial nharaunda social structures as organising metaphor (chief/mambo-style community roles).

Trigger: 3+ self-sustaining estates on the core product. Built as a separate product if ever — different atomic network (a suburb, not an estate), different cold-start problem, different monetisation. Running two cold starts at once is how marketplaces die.

Why it isn't a Nharaunda feature: Nharaunda's loop is transactional (ticket → provider → resolution → rating). A feed is an engagement loop. It inherits moderation load, unverifiable claims, and liability, and it dilutes the positioning that everything here is tied to real, completed work.

Never
the moat

Refused with reasoning. No trigger exists.

Of 15+ community and property products surveyed, all bundle broad and do maintenance averagely. The refusals are the differentiation: a trust ledger stays an asset only while none of it is purchasable, and these lines are written down precisely so they cannot quietly move.

  • No
    Tenant rating / scoring / cross-estate tenant reputationA provider review records an act (a specific resolved job). A tenant score is a judgment about a person, portable across the thing they need to live — a housing blacklist with a friendly UI, under severe power asymmetry (the landlord holds the home). Also squarely DPA profiling territory. Legitimate alternative if tenant risk is the real concern: a factual ledger of a tenant's own payment/ticket history, visible only to their current landlord — records of acts, never portable scores.
  • No
    Sentiment analysis on residentsSame species as tenant rating: an inferred judgment about a person rather than a record of an act.
  • No
    Paid placement / promoted providers / pay-to-suppress-reviewsThe moment visibility is purchasable, the trust ledger — the entire asset — is worthless. Directory order stays deterministic.
  • No
    AdvertisingAn ad model requires an engagement loop, which is the banned product. They are the same decision.
  • No
    Open, uncurated provider marketplaceAlready exists (classifieds.co.zw, Facebook groups) and nobody trusts it. Curation IS the product.
  • No
    Property search PORTAL / cross-inventory discoveryproperty.co.zw, propertybook and pamgolding own the search-and-browse network effect. A landlord showing their own vacant unit is ours; an index of everyone's is still not our fight.
  • No
    Land title / zoning / development-legitimacy verificationReal problem (the parallel-development demolitions), wrong product. That's ZAX-shaped: governed AI over a regulated government workflow.
  • No
    OPEN direct messagingResident ↔ resident DMs, cross-estate messaging, and any thread outside a schema-held relationship stay refused — that is the WhatsApp failure rebuilt, with a moderation surface no scoping can contain.
  • No
    WhatsApp Business API integrationTrigger existed (a real tester says the web app is the wrong surface); no tester exists yet.
  • No
    Facebook Marketplace integrationNo legitimate API access path exists. Meta closed it years ago.
  • No
    Engagement mechanicsBanned by name, permanently.
  • No
    Integrations marketplace / third-party app directoryDistinct from the open-provider-marketplace row above, which refuses an uncurated directory of PEOPLE; this refuses a catalog of SOFTWARE, and it fails on the same clause for a different reason. A marketplace is a placement surface — something is listed above something else — and once placement exists the question of who pays for it arrives on its own. Paid placement is refused above precisely because a purchasable position destroys the trust ledger that is the whole asset, and there is no version of a vendor catalog that stays immune to that gravity. The second reason is data: every integration is an outward pipe, and "we do not share personal data with third parties" is load-bearing on the privacy claim. What this does not refuse: a specific, named, individually-ruled integration — Paynow is one (ADR-041) — is a decision with an ADR behind it. The catalog is refused, not the concept of ever connecting to anything. The public API ✗ for now positioning mark is a scheduling position and stays soft; this row is not.
  • No
    White-labelAn estate serving Nharaunda from its own domain under its own logo is asking for the record to appear to be theirs. The entire trust position is that the referee is independent — the ledger is believed because Nharaunda holds no stake and no estate can edit it. A white-labelled deployment inverts exactly that: the resident is now reading a record that appears to be published by the party the record is about, which is the credibility the append-only schema exists to protect, given away at the presentation layer for a branding fee. It also breaks the estate-reputation rules (master §1 listings row, ADR-041) — those figures are fact-derived and never purchasable, and a paid-for branded skin is the first purchasable thing on the page. Not refused here: a managing agent's own name on their own portfolio view, which is a different question about a private screen.
  • No
    "Anomaly detection" / behavioural monitoring pointed at residentsThe same species as tenant rating and sentiment analysis above, recorded separately because neither of those rows would match a search for "anomaly detection", and a refusal nobody can find gets re-litigated as a novel idea. Flagging a resident whose behaviour "looks unusual" is an inferred judgment about a person — DPA profiling, under the power asymmetry where the landlord holds the home. What is NOT refused, and is banked with a trigger above: anomaly signals about CREDENTIALS — failed sign-ins, an impersonation session running long. Same technique, opposite object. The test is whether the output is a fact about an authentication event or an inference about a human being.