Skip to content
esc

Search pages and sections. Try a tool name, an error code, a route.

↑↓ navigate↵ openesc close

Guides · Concepts

Access presets

Every table carries one preset that says who may list, read, create, update and delete its rows. Presets replace row-level security policies: there are eight of them, they cannot be misconfigured, and the API applies them to every request.

The eight presets#

Preset (wire id)Dashboard labelIn one sentenceList / readCreateUpdateDelete
prive (default)privateEach user only sees their own rows.ownerusersownerowner
partagesharedEveryone reads everything; each user edits only their own rows.usersusersownerowner
collaboratifcollaborativeEveryone reads and edits everything.usersusersusersusers
espacesspacesRows belong to a space; only its members can access them.spacespacespacespace
espace_moderemoderated spacesMembers read and create; only the author or the space admin can edit.spacespaceowner or space adminowner or space admin
lecture_publiquepublic readReadable without an account.anonusersownerowner
journaljournalAppend-only — no end user can edit or delete, ever. Your sk_ / ak_ keys still can.ownerusersnobodynobody
formulaireformAnyone can submit; submissions are readable only with your sk_ / ak_ key.nobodyanon (rate-limited)nobodynobody

The cells:

ValueWho satisfies itWhat it does
ownerthe author of the rowfilters — owner_id = me
usersanyone signed in to the appimposes nothing beyond being signed in
anoneveryone, session or notimposes nothing
spacethe members of the row's spacefilters — space_id in my spaces
space adminthe admin of the row's spacefilters, restricted to the role
nobodyno end user, everrefuses

A nobody on list or read answers 401 to an anonymous caller and the neutral 404 to a signed-in one; on update or delete, a row the caller can see answers 403.

Rules that apply to every preset#

  • Refusal by default. Anything not explicitly allowed is refused. A table with no declared preset is prive.
  • owner_id is set by the API, never read from the client. A body carrying owner_id or id is refused.
  • Spaces membership is checked before any query; outside the space, 404.
  • An anonymous caller on a non-public preset gets 401 with the hint "session required".
  • Your own keys ignore the matrix. An sk_ (your server) and an ak_ (your agent) read and write everything, on every preset. Rows they create have owner_id: null and are invisible to end users on prive and journal.
  • Files follow the same matrix: a private file behaves like a row on prive, a public file like a row on partage.
  • journal is append-only for the users of the app, not for you. No end user can rewrite the past, not even a row's author; your keys are not bound by the matrix. It is not a tamper-proof ledger.
  • formulaire is a mailbox. Anyone deposits, nobody reads from the app; submissions are read and deleted with your keys — from your server or the dashboard. It is the one preset with server-side abuse limits: 10 creations per minute per IP (429) and 10 000 rows per table (402), for anonymous and signed-in callers alike.

Changing a preset#

The preset is the only thing standing between your users' data and each other, so changing it is the most consequential change in the product. It always confirms in two steps: the first call answers 428 with a summary — who gains or loses reading, who gains or loses writing, how many rows become invisible — and a token valid five minutes; the second call, with the token, applies. In the dashboard this is the Definition tab of a table; from an agent, the set_table_preset tool.

Three more rules:

  • Opening a table that already holds rows to the public requires a signed-in human. When the change opens reading to users (everyone signed in) or anon (everyone) and the table is not empty, an agent is refused with 401 and no token: the rows were deposited under a promise, and only a human can revoke it, from the dashboard. An empty table needs no human — there is nothing to expose. Closing a preset, moving to a spaces preset, or widening writes never need a human.
  • Switching a non-empty table to espaces or espace_modere is refused (409): existing rows have no space. Create the table on a spaces preset from the start, or empty it first. Switching between the two spaces presets always passes; switching out of one resets the rows' space_id.
  • A new table can take any preset: the create_table tool declares the preset at creation and confirms the switch itself, because a table that was just created is empty.

Every preset change is written in the request log at level warn.

A limit is not a rule#

The publishable key is public: anyone can send any request with it, ignoring your interface. A "one check-in per day" enforced by your front end is a display convention, not a rule. Server-side rules belong in an edge function; the only preset with a server-side limit of its own is formulaire.