Permissions
Instant permission rules for boards, events, shares, members, and more.
Permissions
Source: instant.perms.ts.
Summary
| Entity | View | Create | Update / delete |
|---|---|---|---|
boards | owner, member, or enabled share secret | auth + owner is self | owner only |
events | same as board view | owner, editor, or edit secret | same |
settings | owner | owner | owner |
shares | board owner, or token lookup via shareToken | board owner | board owner |
members | board owner or self | board owner | owner; self can delete |
boardPrefs | self | auth + self | self |
todos | owner | auth + self + rate limit | owner |
apiTokens | owner (hash field hidden) | never (server-only) | delete: owner; update: never |
Bindings (boards)
Typical bindings: isOwner, isMember, isEditor, hasShareSecret.
Share secrets
- Field rules hide
secret/editSecretfrom everyone except the board owner. - Public metadata lookup can find a share by
ruleParams.shareTokenwithout exposing secrets.passwordSaltis readable on that lookup so guests can derive the secret client-side. - Event writes for share editors must pass
ruleParams.secretmatchingshares.editSecret.
Rate limits ($rateLimits)
Event and todo writes pass through Instant rate limits — token buckets evaluated inside the permission rules:
eventWrites: 120/minute burst + 2000/day sustained. Signed-in writers are keyed byauth.id; share-link guests by theirruleParams.secret(each share link gets its own bucket).todoWrites: 300/hour keyed byauth.id.
rateLimit.limit() is the last term in each && chain: CEL
short-circuits, so a write that fails ownership checks never consumes a
token. Because the REST API impersonates the token owner,
these buckets bound API abuse too. Capacities are sized far above interactive
use — they exist to stop runaway scripts, not humans.
API tokens
apiTokens rows can be listed and revoked by their owner in the client (the
account page uses a live query), but create/update are false: secrets
are minted only by /api/tokens through the admin SDK, and the hash field
rule hides the stored digest from every client read.
Why /api/invite exists
Clients cannot safely look up arbitrary Instant users by email. Invites verify the caller’s refresh token with the admin SDK, confirm board ownership, resolve the target user, then create/update member + editor links using the same policy helpers as the client (member-policy.js).