In April we audited our own tenancy model and found something worth writing down: eight tables were described, in their own migrations, as "enforced at API layer."
What that phrase means in practice is that the database has no opinion. There is no row-level security, no tenant predicate, no policy — only the hope that every query reaches the database through code that remembers to add WHERE tenant_id = ....
Why it is not a fair defence
"Enforced at the API layer" is not wrong as a design. Plenty of systems are built that way and are careful about it. But it is a claim about every caller, forever, including the ones not written yet — and it fails silently in the direction that hurts.
The tables that made this urgent were not the interesting ones. They were servers and ssh_keys.
What the audit produced
The fix enabled row-level security and added tenant-scoped policies across eleven tables in two databases: the team tables, invitations, servers, SSH keys, the audit log, uptime checks, the auth event log, and the agent action logs. Also a duplicate auth-events table in a second application's database that had drifted along with its copy.
The mechanism that let this happen is mundane: two databases, two migration streams, and a schema that was copied rather than shared. Nothing was hidden. Nobody had asked the question.
The same lesson, the next day
The day after the RLS work, we finished a WebRTC SFU for SocialSphere — designed, scaffolded, and patched in a day — and found an authentication bypass in it. The sequence is worth noting because of the order: an audit, then the bypass the audit found, then the patch. Not a bug report; a deliberate look.
JWT authentication on the signalling path landed before the patch commit, and the patch commit's message is a list rather than a title: "patch critical auth bypass and resource leaks." The room and peer metrics follow-up enforced the secret as a required environment variable, which is the same idea one layer down — a missing secret must stop the service, not quietly change its behaviour.
What we took from it
Two things, and we are still living with both.
The first: a tenancy control that lives in code has an owner, and the owner is a convention rather than a mechanism. When a table holds credentials — SSH keys, server records, tokens — the convention is not enough, because the consequence of a missed predicate is not a confusing page, it is someone else's access.
The second: the phrase itself is the smell. "Enforced at the API layer" is an accurate description of a decision and an inaccurate description of a property. If a control is real, it can be asserted somewhere — a policy, a test, a constraint. If it can only be described in prose, it is a habit.
Four months later
These posts have a thread running through them, and this is where it starts. The four authorization gaps we found in September were the same class of finding, four months on — read paths this time rather than tables, but the same underlying question: not "is the code careful?" but "is there anywhere that knows?"
