Audience and bindings
How audience tiers and data/logic bindings combine into a default-deny permission model for Apps.
An App's access to data is governed by two independent controls that both have to allow a request: the audience tier a visitor falls into, and the bindings that expose specific collections, fields, and workflows. Both default to denying access.
Audience tiers structurally limit what's possible
Audience isn't just a login gate — it also caps what operations are ever allowed, regardless of how a binding is configured:
- Just me — only you, the author, can open the App at all.
- Team — any workspace member can open it, with whatever operations their binding allows.
- Invited — people you've specifically invited can sign in through a branded auth screen; visitors get an
owner,member, orguestrole depending on how they were invited. - Public — anyone can open it without signing in. Update and delete operations are never allowed on a Public App, no matter what a data binding's
accesslist says — public visitors are structurally capped at read (and insert, if explicitly bound).
Data bindings
A data binding connects one collection to the App and defines exactly what's reachable:
- Operations — an allow-list of
read,insert,update,delete. Only the operations listed are permitted (subject to the audience cap above). - Fields — an explicit allow-list of field names. This is not a hide-list — it's the complete set of fields the App can ever see or write. An empty field list exposes the collection's existence but none of its data.
- A server-enforced filter (optional) — restricts which rows the binding can touch (e.g. only records belonging to the visitor). This filter can't be widened by anything the App's frontend sends; it's applied on the server for every request.
Example
Binding a Contacts collection with fields: ["name", "company"] and access: ["read"] lets the App display a contact's name and company — the contact's email, phone, and every other field stay invisible, even though the collection itself has them.
If a request doesn't match any of these, it's denied with a specific reason (useful if you're debugging an integration against the App's public API): no binding exists for that collection, the operation isn't in the binding's allow-list, the audience forbids the operation, no fields are exposed at all, or the specific field requested isn't in the allow-list.
Logic bindings
A logic binding connects a workflow's webhook trigger to the App, so the App's frontend can invoke that workflow directly — this is the only way an App can trigger a Wapp workflow. There's no equivalent for other trigger types (schedule, email, collection change); those keep firing independently of the App.
Continue with Branded auth and domains for how Invited-audience sign-in works.