Plan for the page-speed and company-separation work: every page loads only your company's data, straight from the database, a page at a time, and nobody at one company can ever see another's.
22 Sep 2026 · DRAFT — waiting for Gera's approval · reviewed by two separate AI reviewers (Opus and Fable)
Approve this plan?
Yes, start (recommended): it first fixes the vendor data leak, then finishes the prospects speed-up. Anything that touches your live database still comes back to you first.
Change something: tell me which step to add, drop or reorder.
Checked against the actual code, not from memory. “Tested” means a test fails if the page ever starts reading another company's data.
| Page | Only your data | Tested | Loads a page at a time | Needs a new database index? |
|---|---|---|---|---|
| Prospects | Yes | No | Fix waiting | Already has one |
| Tenants | Yes | Yes | No | No: small enough to sort in memory |
| Properties | Yes | No | No | No: short list |
| Turnovers | Yes | No | No | Yes: grows forever, stored in random order |
| Work orders | Yes | Yes | No | Yes: grows forever |
| Tours / calendar | Yes | No | No | Yes: it asks for a date range |
| Conversations | No | No | No | Built, switched off: needs you |
| Vendors | Fix waiting | Fix waiting | No | Later |
Raised in the 21 Sep standup: one Western Slope prospect became four conversations, the match on a street address failed, and the wrong fee was quoted. Western Slope has one shared phone number across many homes, and prospects ask about several homes in one chat.
The idea that untangles it: every message answers three separate questions. Who is it (the person)? Which door did they use (a line or inbox, pointing to a company or building)? And what is it about (a home, a lease, a repair)? At a one-building customer all three answers are “that building”, so filing everything under the building worked. With one door and many buildings, it doesn't.
| Record | Filed under today | Right? |
|---|---|---|
| Prospect / lead | The person, with a company-wide list for the page | Yes and since this morning a lead keeps every home discussed |
| Tenant | The building, linked to the person | Yes a lease is at a building |
| Work order, turnover, tour | The building | Yes they're about a unit |
| Conversation | The building | No the one person-level record still filed under a building |
August's “one conversation per person” work grouped chats on screen, but still per building, so the flaw stayed underneath.
Western Slope has five buildings sharing one phone number. Today, a prospect who asks about three of them gets three conversations, one per building. After the change they get one conversation, filed under the person at Western Slope, with the buildings shown as tags (“asked about: Building 1, Building 3, Building 5”). Every building they mention is added to the list.
Rule of thumb: a record about a building stays under the building; talking to a person goes under the person and company.
| Record | Filed under | Changes? |
|---|---|---|
| Tenants | Building (a lease is for a unit) | No |
| Work orders | Building (a repair is in a unit) | No |
| Renewals | Building (renewing one lease) | No |
| Turnovers, tours | Building (one unit) | No |
| Prospects / leads | Already the person, with a list of homes | No (check: four homes asked about = one lead, not four) |
| Conversations | Building → person + company | Yes, the only change |
Work orders, renewals and leads already point to their conversation by its ID, and that link doesn't change: several of them can point to the same conversation. A resident at Building A with a leak, who also asks about a bigger unit at Building B, has one conversation. It shows the repair (filed under A), the renewal (A) and the new inquiry (B). Building pages look exactly as they do today. If the same person also rents from a different company, that's a separate conversation, and neither company sees the other's.
Proposal (a draft for you and Fede to test, not decided): a conversation belongs to one person at one company. The line or inbox is recorded on each message, and buildings become a list on the conversation, the way leads now carry a list of homes. It's per company, not global, so one company never sees another's chats, and it fits the conversations index, which is already split by company.
Your call: this is already on your decisions page as b90034167 (“OK to build one conversation per person per company?”). Answering it there is the ruling. It touches Clara's live messaging, so bring Fede in.
The pattern, already live on the prospects page. Every row gets two extra labels: whose data it is and the order the page shows it in. The database can then hand back “this company's newest 50” in one step, instead of us loading everything and sorting it ourselves. The cost follows what's on screen, not how much is stored.
| Page | Status | Group label | Order label |
|---|---|---|---|
| Prospects | live | PLIST#<organizationId> | <lastActivityAt>#<inquiryId> |
| Conversations | built, off | CLIST#<organizationId> | <last activity>#<conversationId> |
| Tenants | no index needed | PROPERTY#<propertyId> | OCCUPANCY#<id>, sorted in memory |
| Properties | no index needed | PROPORG#<organizationId> | PROP#<propertyId> |
| Work orders | needs one | today PROP#<propertyId> | today WO#<PMS id>: not a date |
| Tours / calendar | needs one | today PROP#<propertyId> | today TOUR#<id>: random order |
| Turnovers | needs one | today PROP#<propertyId> | today TURNOVER#<id>: random order |
For the last three, the candidate follows the prospects shape: company or building as the group label, a real date (last updated, tour start, move-out) as the order label. Final field names are part of the design step, not decided here.
Learned the hard way on prospects:
Full working notes: ~/.claude/jobs/loop/1fdb267c/PLAN-DRAFT-2026-09-22.md · Handoff: HANDOFF-2026-09-22-1700Z.md