Nothing to connect — the four-screen run when PropFlow owns the address

Wave 2, lane G2: the inbox step leaves the wizard when a CENTRALIZED company does not own the address Clara writes from. Review continues straight to Add your team, the counter says four, and the typed URL lands there too. A per-building company keeps its screen — its rows are its buildings'.

17 Sept 2026 · branch onboarding/g2-skip-propflow-owned · captured against propflow-stage · at e1c78f8ca4

Data note. Every name and balance below comes from propflow-stage, which is anonymized by construction (ADR-0097/0110 — phones in the impossible +1000 NPA, emails @example.test). The identical capture against prod would carry real tenants' names and balances and is not safe to attach anywhere, which is why the generator refuses to run against one.

1 · Here's what we imported — step 3 of 4

Signed in as a real customer admin (org_admin at a stage company that is centralizedoperatingModel: 'centralized' — and whose staff have not chosen an address, emailSetup unset). The founders' ruling (flow map ch.9 row 1, 2026-09-17) reads an unchosen address the same way as a PropFlow-owned one: there is nothing for the admin to connect, so the Channels step is not in this run. The progress bar on the Review screen counts 3 of 4, not 3 of 5.

Why centralized is load-bearing here. Review round 2 caught the first version of this change gating the whole /onboarding/channels route on the address owner. That route renders two screens, and the owner describes only one of them — a per-building company's screen is its buildings' SMS, Email and Calendar rows, which read no emailSetup. The fact is now scoped to the company shape it speaks to, so these frames are captured at the shape the ruling is about.

The portfolio is the demo preview (28 buildings invented without calling AppFolio), the same walk the whole-flow page uses.

Asserted in the captured DOMHere's what we imported · Imported properties · Continue. The Review screen's own title and count label, and its Continue. The step counter is the bar's accessible name ("Step 3 of 4"), which is not body text — the frame carries it; the unit tests pin the number.

Here's what we imported — step 3 of 4

2 · Continue from Review lands on Add your team — the inbox step is skipped

Pressing Continue on Review goes straight to Add your team, step 4 of 4 with a full bar. Before this PR the same company walked Review → Connect the email you want Clara to reply from → Add your team, with the middle screen showing a card and a Continue and nothing to connect (the interim state #9312 named). The run now reads emailSetup.owner for a centralized company, not only the module flags.

Asserted in the captured DOMAdd your team · They'll get an email invite. You can add more later in Settings. · Finish. The last screen's title, its lead, and the Finish button that a full-bar last step carries — reached from Review in one Continue, with no inbox screen between.

Continue from Review lands on Add your team — the inbox step is skipped

3 · The typed URL — /onboarding/channels at a company with nothing to connect

An admin who types the inbox step's address at this company does not get a blank frame or a bar-less orphan of the screen: the gate reads its own position off the run, finds none, and replaces the URL with the screen after Review — Add your team — before either shape mounts or the status is read. replace, not push, so Back does not bounce through a screen that does not exist. (Today's maintenance-only behaviour was render with no bar; this replaces it with the redirect for both cases.)

Asserted in the captured DOMAdd your team · They'll get an email invite. You can add more later in Settings. · Finish. The same last screen, reached by typing the inbox step's own URL: the gate replaced it before anything mounted.

The typed URL — /onboarding/channels at a company with nothing to connect

How this was captured, and what it does not show

Captured as a real customer admin (--identity=non-staff), against a dev server bound to propflow-stage; the run's own guards confirmed the table and the identity before a browser launched. The company is a stage TEST company that is centralized and whose staff have not chosen an address (emailSetup unset) — the ruling treats that exactly as PropFlow-owned. An explicitly PropFlow-owned centralized company takes the same branch; wizard-company-facts.test.ts pins both rows, and wizard-steps.test.ts pins that neither shape is ever routed back into the step. One stage row WAS written to produce these frames: an org_admin evidence identity in that TEST company, minted through the repo's own scripts/seed-evidence-identity.ts (the back-office invite path), because the previous evidence identity belongs to a company whose operatingModel is unknown — and after round 2's fix that company correctly KEEPS its Channels screen, so it can no longer demonstrate the skip.

Not on this page: a client-owned company still walking five screens, and a PER-BUILDING company keeping its screen whatever the address owner says — both unchanged or restored by this PR, and both pinned by the unit matrix in wizard-company-facts.test.ts rather than by pixels.

PropFlow Docs