Access and roles
Your users must see their own data and never someone else's. In Appbricx you say who the users are and what each kind may do; the database enforces it on every query, and verify tests it for every role on every table before you ship. You write no security policies.
When to use it
- Members should see only their own bookings, orders or messages.
- Staff should see everything; customers only what is theirs.
- Someone should see only the records assigned to them (a technician's jobs, a rep's leads).
How access is decided
- Personas. Each kind of user is a persona with a
kind.staffmanage shared records.consumerread shared records (a class timetable) and write only through the pages you give them. The first consumer persona is who a public sign-up becomes. An app with no consumer persona is invite-only. - Derived defaults. From the personas and pages, Appbricx works out read, create, update and delete for every role on every table. Everyone edits only their own booked or ordered rows. Signed-out visitors only browse.
- Explicit access where you need something else, per persona:
read,update,deleteas"own","all"or"none", andcreateas true or false. - Ownership."Own" means rows the person created, or rows assigned to them through
owner_refs.
Code
Members see only their own bookings and profile
{
"name": "member",
"fields": [{ "name": "name", "type": "text" }, { "name": "email", "type": "email", "optional": true }],
"access": { "member": { "read": "own", "update": "own" } }
},
{
"name": "booking",
"fields": [
{ "name": "member_id", "type": "ref", "ref": "member" },
{ "name": "session_id", "type": "ref", "ref": "session" }
],
"owner_refs": ["member_id"],
"actor_ref": "member_id",
"access": { "member": { "read": "own", "create": true, "update": "own", "delete": "none" } }
}owner_refs: a booking is a member's own whenmember_idpoints at their row.actor_ref: the server fillsmember_idwith the writer's own row on every write by a non-staff role. Nobody can book as someone else, whatever the screen sends.
Assigned records
{ "name": "job",
"fields": [{ "name": "technician_id", "type": "ref", "ref": "technician" }, ...],
"owner_refs": ["technician_id"],
"access": { "technician": { "read": "own", "update": "own" } } }Ownership is transitive: a message with "owner_refs": ["match_id"] is yours when its match is."owner_refs": [] means creator only.
What verify proves
✓ Permissions match the plan for 2 roles × 4 tables (read, create, update, delete)
✓ Signed-out visitors can't read the 2 private tables (member, booking);
instructor, session are public by designThat is the real report from the booking app.
Teams and invites
Add a page with the TeamAdmin block for a staff persona, and that person can invite people by email and give each a role. Who may sign up at all (open, invite only, or closed) is set under Backend, Auth. See sign-in.
Gotchas
- Check what signed-out visitors can read. Persona tables are readable by default for browsing apps. The booking app made
memberprivate with"read": "own"after verify listed it as public. - Rules run as the writer. A business rule only sees rows the writer may read, so keep counts the writer needs on a readable table (the booking app keeps
bookedonsession). - Hiding a button is not access. The data API refuses whatever the role may not do, even from a script.
- Several refs to people? List only the sides that own the row in
owner_refs(a swipe belongs to the swiper, not the swipee). - Change access later with
{ "op": "set_entity", "entity": "booking", "access": {...} }.