0136 — Launch criteria: org-scoped reads everywhere, attachment resolves person → property → org, old paths kept through the bake, one Settings page
- Status: Accepted
- Date: 2026-09-14
- Deciders: Gera (chat with the driver-aid, ~20:00 CT), from the founders' standup the same day (Fede, Gera, Sean; Slack
C0BE1NFTA0Kthread1789405138.416749)
Context
The multi-org architecture is switched on for two bought test lines with a one-week bake (row
p5-bake-signals: every old-path and head-path read emits a signal and increments a durable counter).
Three customer companies onboard within four to seven weeks. The standup changed some product shapes —
most visibly, a tour is assigned to a leasing person's calendar rather than a building's — and the same
evening an engineer, filtered to one property, opened the Clara Conversations tab and saw several
properties. Gera's instruction, verbatim: "everything open could be driven to completion … we don't want
to delete the old architecture just yet … every page needs to be clearly aware of the new org strategy,
so we don't do table scans and pulls; everything should be pulled strictly from its org … the design
changed, but that means the architecture should still support the old one, just in case — per person
calendar or per org or per property, we're that flexible." Companion ruling: ADR-0135.
Decision
- Every read is scoped to the selection, everywhere. No page, route, tab or job reads outside the
org(s) and building(s) the viewer has selected; no table scans on user-facing paths. "The selection
is the read scope" (PR #8474, #8502) is the rule for the whole app, not for the routes that happen to
have been swept. A drift guard fails when a route reads outside the selection. The Conversations tab
report is the first named consumer to fix (row
ui-s-d, the consumer sweep). - Attachments resolve person → property → org, and all three levels stay supported. The standup moved tour booking onto the leasing person's calendar. That is a default resolution order, not a replacement: a calendar (and the same shape for phone lines, mailboxes, knowledge) may be attached to a person, a property, or an org, and the resolver walks person, then property, then org. The previous building- and company-level attachment work is not scratched; it is the lower rungs of the same ladder. A future customer with one shared calendar per building, or one per company, is served by the same code path with nothing new built.
- The old architecture stays through the bake. No deletion row (
p9-deletions, the config-file retirement inp5-config-dumps/v6-config-dumps, the catch-all mailbox inp5-catchall) executes its deletion until the bake readout shows the flipped lines' old-path reads at zero and Gera says the new architecture is running smoothly. Building the dumps and the guards proceeds; the delete waits. - One Settings entry, four sub-navs. The main navigation carries a single Settings; inside it a
sub-navigation with Admin, Property, Organization, Profile. Every existing settings page is placed
under one of those four — placed, not redesigned. Organization and Property may later gain a nested
sub-nav of their own. Per ADR-0135 every page under Settings is visible and editable to every
signed-in person in the company; Admin alone stays behind
platform_admin. Gera's designs for the page's inner UI follow later and are out of scope here. - Drive everything open to completion; Gera tests after. The dock is driven to the finisher's count with the criteria above as acceptance; polishing (the settings redesign among it) starts only when the open rows are closed and the founders have tested the result.
What a future reader should check code against
- A user-facing read that touches rows outside the current selection, or scans a table where a selection exists, violates (1).
- Code that assumes a calendar (or line, mailbox, knowledge) must hang off a person — or must hang off a building — violates (2); the resolver, not the caller, decides the level.
- A deletion of an old-path map, config file or mailbox before the bake readout and Gera's word violates (3).
- A settings page reachable outside the single Settings entry and its four sub-navs violates (4).
Consequences
ui-s-dgains a concrete acceptance: the Conversations tab honours a one-property selection, and a guard proves every consumer does.p9-calendar("an assignment per building and person, and the round-robin two leasing people need") is the per-person rung and stays;v9-tour-calendar-resolved("building's own, else the company's") is the lower rungs and stays; the resolver is one function with a fixed order.p9-deletionsis gated on the bake readout plus a founder's word, recorded on the row.- A new row carries the Settings placement (one entry, four sub-navs, everything placed under them).
- Rows that presumed a single attachment level are re-read against (2) before more is built on them.