The public catalog: a closed set of shared tables
Orbit resolves tenancy two ways: inbound, from an API key or session; and the reverse, from the destination of an inbound event. The reverse direction needs a small set of tables every tenant and every edge node can read without a tenant context — the public catalog. This page is its hub: it lists the closed set, links each table’s owning design page, and gives the engineering checklist for adding a new one. Tenant isolation documents the schema-per-tenant split; this page documents the deliberate exception to it.Section 1 — What reaches the edge unauthenticated
Three inbound surfaces reach Orbit before any tenant context exists:- Voice. A SIP INVITE addressed to a dialed number. The dialed number is the only input — there is no API key, no caller credential, no session. The edge must decide where the call terminates before media flows.
- Mobile-originated SMS. An inbound SMS carries a destination DID and a sender. The resolver must answer “which tenant owns this number” before routing rules or inbox assignment run.
- Delivery receipts. A carrier DLR arrives with no bearer token. Like MO SMS, it resolves tenant from the destination number alone.
Section 2 — The closed set
The public schema holds catalog and routing rows — one row per platform artifact or per org — never per-tenant working data. The full set, closed at eight tables (the platform DID pool and assignments count as one pair):
This set is closed. Nothing else joins it unless a concept page documents the reason — the same ownership discipline this page applies. If you are reading this to answer “is a public table allowed?”, the answer is only yes when a concept page exists for the exception.
Section 3 — Where each owning concept sits
Each table or pair above has one owning design page. These pages own the rationale; this page fetches, it does not repeat.- Inbound voice routing: why the tables are shared —
dnis_routesandinbound_routes: resolution before tenancy exists, and the org-first + stale-route guards. - Inbound message resolution —
phone_number_owners: the O(1) reverse map that resolves MO SMS and DLR events to one tenant, plus the bounded fallback scan. - Tenant isolation —
organizationsand the catalog-level ownership guards that apply to every public table on read and on write.
Section 4 — The four tests a new public-schema table must pass
When you consider adding a table to the public schema, every one of these must hold:- It resolves tenant from payload alone. The edge has no credential context, so the row must carry enough by itself to pin the owning org. If resolution needs anything outside the payload, the table does not belong here.
- Resolution is O(1) per event. A public-catalog read is on the inbound hot path. Bounded fallback scans exist to cover drift, not as the steady state — a new row must index its lookup key, not contribute to a scan.
- Ownership is re-validated per event. Never cached, never “owned forever.” A recycled DID changes hands; the guard that re-checks ownership on every event is what keeps the new owner’s inbound from landing on the previous owner’s endpoint.
- Writes are tenant-bounded. A purchase, admin action, or reconcile backfills rows; it never writes on behalf of no-owner. If a row cannot be attributed to exactly one org at write time, it must not be written.
inbound-reverse-map reconcile (reverse-map section) plus the operator CLI that runs the same backfill for one tenant or as a dry run. Any new public table that resolves inbound traffic must have an equivalent reconcile before it can go live.
Section 5 — Checklist: adding a public table
Run this before touching the schema, and link the three artifacts it names in your change description:- A concept page documents the design rationale, and the table is added to the closed set above — same commit.
- The read guard is in place: an index on the lookup key, ownership re-checked per event, ambiguity dropped rather than guessed.
- The write guard is in place: writes are tenant-bounded, and idempotent so the reconcile can converge any drift.
- A reconcile scheduler and a CLI backfill exist and are wired to converge the reverse-map-like index the table maintains.
- Tenant isolation Section 1 lists the new table, and this page was updated — because the set is closed, adding to it is a documented decision, not a migration side effect.