1. The module switch hides pages, nothing more
It is the light switch for a room's ceiling lamp — not the breaker for the room. Everything plugged into the wall keeps running in the dark.
- Readers: one layout, the sidebar, the nav list, a route guard, admin screens.
- Zero readers in any send path, background worker, or Lambda.
- The flag is set per company, not per building.
- Its own code comment says it "controls which sections are visible".
Proves: git grep getOrgEnabledModules origin/main -- src agents lambda returns only layouts, nav components and admin routes. Definition at src/lib/data/types.ts:15941.
Deeper → Appendix: the full toggle inventory
2. Thirty-eight ways out, none of them asking
A building with one front desk and thirty-eight side doors. The sign-in sheet is at the desk.
- Counted by walking back from the wire, so no lane is missed.
- Maintenance alone owns 21 message types across texts, email and calls.
- The per-building switch reaches exactly one of them, and not the broken one.
- Western Slope's tenant text came from the AppFolio sync path.
Proves: full lane table in the appendix, each row carrying its entry file:line on origin/main.
Deeper → Appendix: the 38 lanes
3. Four switches that are not switches
Four fire alarms on the wall. One is a sticker, one only rings on weekdays, one was unplugged in a refit, and one covers a single floor.
- The per-building hold has a reader but no writer anywhere in production.
- The global text kill switch is skipped whenever the message is a reply.
- Ten files text without passing the policy layer — nearly all staff-facing.
- Only email holds a not-yet-live company. SMS lost its version on 14 Sept.
Proves: verified by grep with a positive control — the company-live check appears throughout the email layer and nowhere in the SMS layer except a comment saying "nothing replaces this check" (twilio/client.ts:435).
Deeper → Appendix: toggle inventory
4. There is no single front door
We keep saying "the checkpoint". There are eight, and two of them were photocopied by hand and have since disagreed.
- The picture-message door was hand-copied and has already drifted apart.
- Email's four doors each re-implement suppression and frequency limits.
- We already ruled against one central checkpoint after four copies drifted.
- The agreed shape is one shared function called at every door.
Proves: the two SMS doors now disagree on a renewal opt-out default (client.ts:393 vs client.ts:706) — drift already happened, it is not hypothetical.
Deeper → Appendix: the door map
5. The plan — three slices, two traps, one question for you
Fit one real lock first and prove it turns, before re-keying the whole building.
- Shape: one shared fail-closed check, called at each door.
- Silence must be the default when a lane forgets to declare itself.
- Trap A would darken every recently onboarded customer at once.
- Trap B means the check must be rebuilt for workers, not reused.
- Prove it by replaying thirty days of real conversations.
Proves: 23 of 83 message types carry no module; there is no topic field at any door; the follow-up taxonomy is a different seven-member list.
Deeper → Appendix: full record
A1 · Appendix — full record
Everything the three audit lanes found, with file:line on origin/main @ b099a80f96, for whoever builds this next.
The four module flags, and what they gate
| Flag | Scope | Default if unset | Readers | Gates outbound? |
|---|---|---|---|---|
leasing.prospects | org | ON (existing) / OFF (new orgs) | nav + route guard | No |
leasing.renewals | org | ON (existing) / OFF (new orgs) | nav + route guard | No |
maintenance | org | ON (existing) / OFF (new orgs) | nav + route guard | No |
collections | org | ON (existing) / OFF (new orgs) | nav + route guard | No |
Definition src/lib/data/types.ts:15941; resolver src/lib/domain/modules/resolve-enabled-modules.ts:25; defaults types.ts:16215 (all on) vs new-org-enabled-modules.ts:30 (all off). Readers: (workspace)/layout.tsx:119, SideNav.tsx:883,1491, nav-items.tsx:662, require-module.ts:93, eight section layouts, two admin DTO routes.
Switches that read like kill switches and are not
| Switch | What it looks like | What it is | Evidence |
|---|---|---|---|
Property.capabilityStage.maintenance | per-building maintenance hold | real, but its one caller parks Clara-created work orders — the AppFolio-sync text never passes it. Absent = live. | computations.ts:112; sole caller handle-create-work-order.ts:726 |
capabilitySuppressed | transport-level capability gate | dead code — a reader with zero production writers; the documented setter was decommissioned 2026-04-30 | dispatch-envelope.ts:305; grep returns only tests |
settings.smsEnabled | global "stop all texts" | skipped for replies, and unseen by ten files that call the sender directly | dispatch-envelope.ts:511 guarded by !isReply |
Property.isTest | "a sandbox can never text anyone" | true for collections and escalation nags only; no read in the Twilio layer or the policy layer | approved-dun-send.ts:314; registry claim at arms-registry.ts:176 |
Organization.claraLive | company is not live yet | real and fail-closed, but email only; the SMS equivalent was deleted 2026-09-14 | company-live-gate.ts:122; twilio/client.ts:435 "nothing replaces this check" |
capabilityStage.leasing / .renewals | per-building holds | no reader at all; renewals still carries its original TODO | renewal.ts:113 |
The outbound doors
| Channel | Doors | Lowest shared gate | Knows the company? |
|---|---|---|---|
| SMS | 2 + 10 bypassing files | runOutboundTextComplianceGate twilio/client.ts:362 | No — property and org both optional |
| 4 (SendGrid, Outlook, Gmail, PMS) | evaluateCompanyLiveGate called at 5 routers | Yes — full property row required, org id required on it | |
| Voice | 1 | initiateOutboundCall initiate-outbound-call.ts:164 | Partly — no message-kind at all on this lane |
The picture-message door (client.ts:677-790) re-implements the text gate inline and has drifted: it defaults the renewal opt-out scope to true where the text gate defaults it to false (client.ts:706 vs :393). The ten bypassing files (nine are staff-facing; only voice/call-ended can reach a non-staff caller, and in practice it reaches a PM): canary/suppression-probe/route.ts, voice/call-ended/route.ts, renewal-notify.ts, handle-confirmation-review-reply.ts, notify-pm-stale-dial.ts, emergency-no-answer-ladder.ts, mfa-sms.ts, mass-comms.ts, tenant-confirmation-review.ts, turnover.ts.
Customer-reaching lanes, by module
| Module | Lanes | Examples (entry file) | Any read the module flag? |
|---|---|---|---|
| maintenance | 11 | notify-tenant-of-pms-creation.ts:213, rating.ts:689, tech-sms-dispatch.ts:1142, in-house-dispatch.ts:529, send-turnover-vendor-dispatch.ts:659, initiate-vendor-call.ts:357 | 0 |
| leasing.prospects | 13 | send-tour-outcome-sms.ts:466, send-application-link.ts:400, clara-guest-card-first-email-send.ts:293, process-inbound-email.ts:1635 | 0 |
| leasing.renewals | 8 | renewal-auto-start.ts:2380, send-renewal-letter-mms.ts:267, send-renewal-email.ts:243, initiate-renewal-call.ts:85 | 0 |
| collections | 1 | approved-dun-send-ops.ts:469 | 0 |
| none / cross-module | 5 | process-envelope.ts:447 (Clara replying), fulfill.ts:962, reply-release.ts:2051, mass-comms.ts:513 | n/a |
38 total. Staff-facing lanes (PM pages, digests, team reminders, MFA) were enumerated and excluded — they are internal recipients and correctly exempt from customer gates.
Why the module cannot be inferred at the door
| Candidate key | Problem |
|---|---|
| message kind | 83 kinds; 23 belong to no module, including Clara's own replies, human-typed sends and emergencies. Optional field, so omission fails open. |
| conversation topic | Not carried at any door. It is plural, optional, and a different vocabulary from the four modules. |
| follow-up scenario | A seven-member taxonomy, set on only seven lanes. |
| voice | Carries no message kind at all. |
Conclusion: the module must be declared by each send site, required and inverted so that forgetting it means silence — the doctrine already written down at dispatcher.ts:143 for recipient type. A grepable exemption list covers the 23 cross-module kinds.
Method
Three independent read-only lanes against origin/main @ b099a80f96: a toggle inventory, an outbound-path inventory walked backward from the carrier calls, and a choke-point feasibility read. Zero production writes; no data was read from any customer table for this page. The two loudest findings — SMS having no company-live gate, and ten files bypassing the policy layer — were re-verified by hand with a positive control (the same search hits throughout the email layer).