minca

Warrants

A warrant (std.warrant) is proof that an account's key signed something every peer refuses and no honest app would sign. Your app uses warrants to show the members of a space that someone broke the rules, so whoever may remove members can decide what to do.

Nodes write warrants for you, and every member's node checks the proof itself before it shows an account as flagged. Nothing happens to the account automatically. A peer that has never heard of warrants syncs and judges everything the same. It just shows no flags.

Showing who is flagged

spaces.access(id).flagged lists every account this node has checked proof against:

const { flagged } = await node.spaces.access(space.id);
// [{ account, key, kind, by, offence }]

Each entry is one warrant:

Field
accountThe account accused
keyThe key that signed it: one device or app of theirs
kindWhat it broke: chain, standing or access
byThe account that brought the proof
offenceThe id of the offending version

Several members may bring proof against one account, so an account can appear more than once.

Show the flag to the space's members. One granted /member/remove may remove the person with spaces.removeMember(id, did).

Show it to the account itself too. A flag against your own account usually means one of your keys is being used somewhere it shouldn't be. Revoking that key with spaces.revoke takes back what it signed.

When a warrant counts

A warrant flags someone only when it:

  • is a first version, standing as a record;
  • is in std.warrant, and not against its own writer;
  • has evidence that is exactly what its ids name, envelope and body;
  • proves its kind's check.

Anything else flags nobody. That covers false, malformed and unknown kinds, and it earns the writer nothing either. Each warrant is judged once, whether it holds or not, so a false one costs a node one check.

The record

std.warrant at a fresh key of its writer's
{ kind, evidence: [<version>, <version>?] }        retain: true

evidence[0] is the offending version. Its signer's root is the accused account.

The record's key is the writer's own, so nobody can write its first version but the writer, the accused least of all. Only that first version counts as proof. Whoever the space's grants allow may write a later version or delete it, as for any record, but neither takes the proof back. The writer sets retain, so the first version is kept whole.

One offence counts once per writer, however many records say it.

Kinds

kindevidenceProves
chain[v, p], both without bodiesp.id = v.prev, and v doesn't follow p
standing[v], without its body; not an access collectionIn v's own view: its root was no member, the rules said final, or a first version's root had no grant to write it
access[v], whole; an access collectionIn its own view, v's event is refused by its author's power

For standing, policies on the body are left out of the grant check.

A version's own view is the access changes its seen names, and everything they saw, replayed alone. That's what its writer's node had when it signed. Nothing outside it can change the verdict, so an honest writer never fails it.

See spec 02 §4 and spec 03 §4.5 for the checks themselves.

How a node writes one

When your node refuses a version that proves one of the kinds above, it writes a warrant of its own. It skips this if one of its own warrants against that account already stands. So one account's misconduct costs each member one warrant at a time.

The node looks through the cheap global view first, and replays the own view only for what that finds broken. A flag can be missed, but is never false. A race, like a write that crossed a removal it hadn't seen, is withdrawn rather than refused, so it earns no warrant.

When a warrant goes away

Like any record, a warrant is withdrawn when its writer is removed by a change whose cutoff doesn't cover it, or revokes the key that signed it (#166).

More kinds are planned after v1, in #148.

On this page