A single POST endpoint that accepts an action, a table, data and filters. It runs against an explicit allowlist of tables and actions, applies role gates per table, ignores any org_id the client sends, stamps the authenticated caller's org id onto outgoing rows, and appends the org filter last so it cannot be overridden by anything the caller passed.
Also called: api/db · org_id stamping · database proxy · row level scoping
- 1The table must be in ALLOWED_TABLES and the action in ALLOWED_ACTIONS, otherwise the request is refused outright.
- 2Read gates: some tables are admin-only, some exclude the field 'worker' role, and anything not explicitly readable is refused.
- 3Write gates: some tables are forbidden entirely (use the dedicated endpoint), some are admin-only config, deletes default to admin with a small named exception list.
- 4stampOrg() overwrites any client-supplied org_id with the caller's; stampSelf() does the same for per-user tables; stampAuthor() records who created a version or took a photo.
- 5On select/update/delete, .eq('org_id', caller's org) is applied after every user filter so it always narrows and never widens.
- 6Selects are further narrowed by per-rep lead visibility, and updates and deletes mirror that same narrowing.
- 7Every write is audited with a before-snapshot and the affected row count.
The hard rule in this codebase is that the browser must never hold a database key — every query goes through this proxy. The comments say why each guard exists rather than describing what it does. On stamping: 'Any client-supplied org_id is ignored — the authenticated user's id always wins, so there's no way to write into another org's namespace.' On ordering: org scoping is 'added LAST so it can't be overridden.' On the write-side lead scope: read-scope alone was not enough, because org-scoped tables permit filterless updates, 'so a restricted rep could POST a filterless update and overwrite EVERY lead in the org.' Even the error text is a control: raw database errors 'echo the data' on constraint violations, so production clients get a generic message and the real error goes to the server log.
- A client-supplied account id could otherwise write rows into another company's namespace.
- A filterless update on a shared table could rewrite every row in the account.
- Database error text can leak schema details and row values to the browser.
See it on your own jobs
Twenty minutes, your numbers, no slide deck. We’ll build one of your real buildings in front of you and send you the estimate link at the end — yours to keep either way.
or keep browsing features →