Skip to content

Security model

What the server enforces for every App, what it leaves to the database and to you, and where each line is drawn.

tablewalk.json
{
"connections": [
{ "name": "crm", "url": "${DATABASE_URL}", "writable": true }
]
}

A connection is read-only until it says "writable": true, and the server checks that in every route and tool that writes, before a statement reaches the database. The database role is the limit that holds whatever the server does: connect as one that can do no more than the App needs.

  • Every read is the reader’s own. A list, a count, an export, a rollup and a record’s history go through one authorized reader: the role’s table and field grants, its row scope and the row policy. A field the reader may not read is refused, never narrowed into an oracle.
  • A hidden column is never served. A resource’s hidden cuts it from the catalog every read goes through; a query that names it is refused as naming a column that is not there.
  • Queries compile to structure, never to SQL text. Every value is a bound parameter, and table names are checked against the catalog.
  • Writes go through the one pipeline. A save, an action and a command each check the role’s grant on the server; a role granted one fixed action writes that action and nothing else.
  • The page talks to its own server. A Content-Security-Policy keeps scripts and requests on the App’s origin and on the origins ui.csp names.
  • Every grant is written down. authority.lock lists each grant, ceiling and binding the App holds, one line each, so a change to who may do what shows in review (the authority lock).
  • The App directory is code. app.ts, commands.ts and custom components run with the server’s privileges; keep the directory writable only by the account that serves it.
  • Loopback is not a login. A server binds 127.0.0.1. An App that signs people in protects itself; one that does not belongs behind a proxy that authenticates (--auth-proxy-header).
  • Secrets live in the environment. Write ${NAME} in tablewalk.json, never the value (secrets).

Email security@tablewalk.dev rather than opening a public issue. You will get an acknowledgement within a few days. The repository’s SECURITY.md holds the whole model, point by point.