Security model
What the server enforces for every App, what it leaves to the database and to you, and where each line is drawn.
{ "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.
What the server enforces
Section titled “What the server enforces”- 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
hiddencuts 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.cspnames. - Every grant is written down.
authority.locklists 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).
What it leaves to you
Section titled “What it leaves to you”- The App directory is code.
app.ts,commands.tsand 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}intablewalk.json, never the value (secrets).
Report a vulnerability
Section titled “Report a vulnerability”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.
Related
Section titled “Related”- Resources and fields: what each resource and field grants.
- Roles: what a role may read, write and run.
- Row access: the policy every read and write passes.
- Build and deploy: binding, allowed hosts and the proxy in production.