.govern, and Bijection runs it at commit for every
transaction that inserts, patches, replaces or deletes documents in that
table, whichever mutation made the change.
bijection/schema.ts
bijection/access.ts
What the rule receives
The rule receiveschanges, the net changes the transaction made to the
table, one per document:
A document inserted and then patched in the same transaction is one change
with
before: null. The TableChange type from bijection/server describes
one change.
The rule runs on the committing transaction and sees its complete tentative
state. By default its reads see the database as it will be after the
transaction.
What the rule returns
The rule returns one result per change, in order, and[] when there are no
changes. Each result is null, { validUntil }, { reason } or
{ validUntil, reason }, as for a read rule.
Throw to refuse: a refusal fails the whole transaction, and nothing it wrote
commits.
A missing result, an extra one, or a bare value instead of an array refuses.
The rule’s returns must be readAccessResults; a deployment whose write rule
declares anything else is refused. Every push of your code runs each write rule
once with no changes, which checks this before any real write depends on it.
When the rule reads the clock, each permission must carry validUntil, at
most 366 days ahead. The transaction must then commit before that instant.
Private inputs and the original state
Pass an object instead of a bare reference to give the rule private inputs or to choose which state it decides against:bijection/schema.ts
readslists the tables the rule may read privately, at most 32 ordinary tables of your schema, exactly like a read rule’s policy inputs. Withreads, the rule may read those tables and nothing else.basischooses the state the rule’s reads see."final", the default, is the state at commit."original"is the state before the transaction started.
basis: "original" on tables that hold authority, such as memberships or
grants. Deciding a new membership against the original state means the
authority to add it must already exist before the transaction: a caller can’t
grant themselves a role and use it to approve their own grant in the same
commit.
Errors
When a write rule refuses, the mutation fails with aGoverningRuleRejected
error. What the caller sees depends on whether the rule declares inputs:
A rule with private inputs could mention them in its message, so Bijection
keeps its message private. To record why such a rule refused, audit the table
with
.access({ audit: true }), which records the why of a thrown
BijectionError({ kind: "AccessRefused", why }). See
Auditing decisions.
Where write rules apply
- Only on tables your app owns. Synced tables hold
a provider’s data, and views are computed, so neither
accepts
.govern. - A table has at most one write rule. To combine several conditions, check them all inside that rule.
- A write rule checks the changes of each transaction. It isn’t a standing
constraint: a rule on
tasksthat looks at a project doesn’t run when the project changes.