Guards.me's Source: the one row, me, as the asker is, with may
answered by policy. signedIn is whether the server answered as
someone; key is their key. Any other id is no row.
An EntitySource.filter for entity: each requested member with a Read
rule is decided per record, omitted or redacted where the rule refuses.
The fields a rule reads are read too, so it can be decided.
RemoteServer.memory's readable and filter for entities, the
Entities as Guards.attach returned them. A row's Read is decided per
stored row, an inherited Read by looking the related row up; an Entity
not listed is read by everyone.
writer with entity's write rules checked before each write lands, for
RemoteServer.write. An update or a delete reads the row first under
the writer's own read (its Source's read rule): a row the writer may not
see is refused as one that is not there, and a delete of it changes
nothing. Then the row's rule for the command must hold over the row (an
update's over the row as it would be after it too, so a write cannot move
a row out of its writer's reach), each member it sets must allow setting
it, and each relation it points elsewhere must allow the unlink and the
link. A create's rules hold over the values it proposes, where a field the
create leaves unset matches no guard, not even one for an empty value. A refusal is
Forbidden, with the sentence an explain gave; the write never runs.
presets are fields a create takes from who is asking, never from the
client (ownerId: user => user.id): set before the rules are checked, so
a rule over them holds of the creator. A visitor has nothing to preset
from, and a create whose input sets a preset field is a mistake of the
server's, refused.
A handler's Source (RemoteServer.mutation's) with entity's rule for
interaction checked before it runs. The row the input names (id) is
read through source, which must apply the Entity's Read rules, and the
rule must hold over it; a row its writer may not see is refused. With no
id (a create), the rule must hold of who is asking alone, a field it
reads matching no guard. run is given the row as read: its fields the
rule reads, its id, and fields. A refusal is Forbidden; run never
runs. What run writes is its own: check members it sets there. Each
row of entity its answer carries is read back through source, so the
answer shows its writer only what they may see, a row it hid from them
as deleted.
Checks, at startup, that server applies the guards of entities, the
Entities as Guards.attach returned them: each one's Source and each
query listing it apply its row's Read rules (GuardDrizzle.visible, or
GuardServer.memory), its Source applies its members' and relations'
(GuardServer.filter), and each declared write of it lands through
GuardServer.writer, all built from policy; and that no query's body
filters or orders by a member with a Read rule, which would answer for the
value it hides. A hand-written Source over a guarded Entity would serve
every row, and a bare writer would take every write; this throws instead,
naming each. A handler (RemoteServer.mutation) writes what its code
writes, which no check at startup can read.
ts
GuardServer.validate(Policy,{entities: [Todo, Project],domain: Data,server: Server })