aboutsummaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
authortv <tv@krebsco.de>2026-11-12 05:58:57 +0000
committertv <tv@krebsco.de>2026-11-12 15:26:45 +0100
commitdf766dea6c4d8fd527af323b6ad101c682b9d104 (patch)
tree3e5ea23da0761d70502fc71cd222aca1e31602d1 /docs
parenta4da3a94cb51b893dc259a1741df0071c46e1ac3 (diff)
docs: federation: numbers without constraint, names by a decision
What the maintainer answered to the questions the design had left: * Every quantity of the design is a number of the policy, in one table with what the design recommends (the times, the limits, how much a remake's base may lack, how long the root's node lets a claim wait). The genesis policy sets each, and a decision changes any to any value: nothing constrains them. The fractions aren't numbers. * While a user is out, the voters free its names or give them to another by a decision, whatever `gone` says; a policy without `gone` has the names wait until a vouch or a decision. * Nobody is put out by a vote, said where unvouching is, with what there is against a user that harms within the rules. * A node keeps the epochs it left for as long as its operator says, `archiveRetention` at least, and says which; so a node coming back, or one joining from the genesis root, walks every epoch where an archive is within reach, and shows where the walk doesn't end at its peers' epoch. * Settled, and listed so: who votes, from where an unvouch undoes, gone for good, first keys by a decision, what the root holds unsigned. Two questions remain: whether the fractions are numbers too, and whether a decision gives a user name with its namespace. future-work.md: an archive of every epoch.
Diffstat (limited to 'docs')
-rw-r--r--docs/federation.md335
1 files changed, 164 insertions, 171 deletions
diff --git a/docs/federation.md b/docs/federation.md
index d3183d7..96bbc21 100644
--- a/docs/federation.md
+++ b/docs/federation.md
@@ -73,7 +73,8 @@ but for what the voters can do to a user, said with each and below):
that shows, with the changes that did it. And a claim made after another user
released the name stands as long as that release does (Cuts). A claim stands
while its user does: the names of a user nobody vouches for any more wait for it,
- 30 days by the voters' clocks, and are free after (Unvouching).
+ for as long as the policy says by the voters' clocks, unless a decision frees them
+ or gives them away before (Unvouching).
6. **Nobody waits for anybody.** An honest user's valid write needs no vote and no
other party's consent; it counts at once, and reaches every honest node its nodes
reach.
@@ -83,13 +84,13 @@ present malicious, then or later (the voters are the users an epoch starts with,
those the root brought in):
7. **Decisions by two thirds.** A remake, a new root, first keys for a user that lost
- its own, a change of the numbers counts only once more than two thirds of the
- voters present, and more than half of all the voters, voted for it and their nodes
- took it up while the votes ran. No two decisions of one matter both count, and none
- counts that no honest voter voted for. With no voter malicious, no two do whatever
- the network does. A remake changes nothing in what counts: every node builds the
- next epoch itself, from the changes it holds. Nobody is moved to other rules: a
- change of policy is followed by choice.
+ its own, the names of a user that is out, a change of the numbers counts only once
+ more than two thirds of the voters present, and more than half of all the voters,
+ voted for it and their nodes took it up while the votes ran. No two decisions of
+ one matter both count, and none counts that no honest voter voted for. With no
+ voter malicious, no two do whatever the network does. A remake changes nothing in
+ what counts: every node builds the next epoch itself, from the changes it holds.
+ Nobody is moved to other rules: a change of policy is followed by choice.
What is not promised:
@@ -108,11 +109,14 @@ What is not promised:
the voters make them.
* **A name against the voters.** Two thirds of them give a user's first keys anew.
Meant for a user that lost them, it hands a name to whoever they say: in the open,
- over the days a vote takes. And a third of them, lying about the time, make a user
- that is out gone at once.
+ over the days a vote takes. The same two thirds free the names of a user that is
+ out, or give them to another. And a third of them, lying about the time, make a
+ user that is out gone at once.
* **A name through a long partition, for a user that is out.** Unvouched on one side
- of a partition that outlasts the 30 days, it is gone, though someone vouched for it
- in time on the other.
+ of a partition that outlasts `gone`, it is gone, though someone vouched for it in
+ time on the other.
+* **A user put out by the swarm.** Nobody is put out by a vote: a user is in while
+ one user that counts vouches for it (Unvouching).
* **Decisions against a third of the voters present.** A third or more of them,
together, can make two decisions of one matter count, and can push the swarm's
time. So can fewer, across a partition that outlasts the absence period and splits
@@ -135,8 +139,8 @@ depends on a change and its history alone converges whatever the faulty nodes do
(*Making CRDTs Byzantine Fault Tolerant*, 2022): high, given the conditions under Why
it holds. 6: high. 5 is this design's own construction, argued below: medium. 7 is the
classic two-thirds argument carried over to votes that take days, with a clock read
-from the document: medium, less for the clock. A user gone after 30 days out reads
-the same clock. 5 and 7 want the tests named under
+from the document: medium, less for the clock. A user gone after being out for long
+reads the same clock. 5 and 7 want the tests named under
Attacks, and someone trying to break them.
## The design
@@ -153,10 +157,8 @@ its voters' votes.
A federated swarm's policy is `{"version": 2, "values": "signed", "users": "vouched"}`,
with what the rules read beside it in `_continuum/access`: the kinds of names
(`claims`), the paths in namespaces whose values are signed (`userSigned`, as today),
-and the **numbers**: the limits (how many keys, nodes, users and names of a kind a
-user may have) and the times (`window`, 7 days; `absent`, 30 days; `gone`, 30 days;
-`archiveRetention`, 90 days). All of it is in the swarm's root, its genesis change,
-with the root user, its keys and its nodes:
+and the **numbers**. All of it is in the swarm's root, its genesis change, with the
+root user, its keys and its nodes:
* Nothing is ever written before the policy, so nothing is judged by none.
* Every node is given a root and takes no other: the genesis root (`--genesis-root`),
@@ -165,8 +167,31 @@ with the root user, its keys and its nodes:
* A node that doesn't know the policy's version doesn't sync at all. (Today it
receives without judging *(docs)*, which here would let anything in.)
-The numbers change by a decision. Anything else in the policy changes by a change of
-policy, which is a fork (below).
+**The numbers.** The quantities of this design are numbers of the policy. The design
+recommends; the genesis policy sets each, and a decision changes any of them to any
+value:
+
+| Number | Recommended | What it says |
+|---|---|---|
+| `window` | 7 days | how long a vote runs |
+| `absent` | 30 days | after how long without a stamp a voter is absent |
+| `gone` | 30 days | after how long out a user is gone; none: its names wait until a vouch or a decision |
+| `archiveRetention` | 90 days | how long a node answers for an epoch it left, at least |
+| `baseAge` | 10 minutes | how much of what a voter's node holds a remake's base may lack |
+| `witness` | 1 minute | how long the root's node lets a claim wait before it writes |
+| `limits.keys` | 64 | keys a user has at once |
+| `limits.nodes` | 64 | nodes carrying for a user at once |
+| `limits.users` | 16 | users a user created that stand; the root: no limit |
+| `limits.vouches`, `limits.bans` | 64 | vouches, and bans, of a user that stand |
+| a kind's `limit` | none | names of the kind a user holds |
+
+Nothing constrains them: a number that makes no sense has the result it has (an
+`absent` of nothing leaves nobody to decide). The fractions aren't numbers: two
+thirds of those present, more than half of all, a third for the swarm's time and for
+a user gone are what the promises are argued from. And what a node does for itself
+alone (how fast it takes a party's changes) is its own setting.
+
+Anything else in the policy changes by a change of policy, which is a fork (below).
### Users: statements, keys, nodes
@@ -193,16 +218,16 @@ grows. A statement is signed by one user and says one thing:
envelope names.
* **Keys form a tree.** A user's first keys are those its creation names. A `key`
statement adds one, signed with a key the user has, which is **above** the new one,
- as are the keys above itself. Any number over time; 64 at once at most (a limit in
- the policy). Use: the first keys stay offline, a key added below them is on each
+ as are the keys above itself. Any number over time; at once as many as
+ `limits.keys` says. Use: the first keys stay offline, a key added below them is on each
device.
* **A node carries for a user** that named it. A node commits changes only while it
carries for a user, and an envelope is taken only in a change committed by a node
that carries for its signer (a `node` statement also in one by the node it names;
what a decision is made of, in any node's: Decisions). So every change is some
party's: its node's signature proves the node ([`access.md`](access.md),
- signatures required), and the user's statement binds the node to the user. 64 nodes
- a user at once (a limit).
+ signatures required), and the user's statement binds the node to the user. At once
+ as many nodes a user as `limits.nodes` says.
* **A user without a node** names another party's, which carries for it too if it
agrees (it commits the `node` statement). That node's changes witness for both,
its alive stamp is the presence of both, and it takes decisions up for both. The
@@ -214,12 +239,12 @@ grows. A statement is signed by one user and says one thing:
### Vouching, the line, the root
-A user creates whom it likes, within a limit (16, in the policy), and vouches for whom
-it likes. The new user signs, claims and creates in turn from its creation on: in any
-change that has the creation in its history. A user is **vouched for** if its creator
-is, down from the root, and the creation counts; or if a user vouched for it whose
-own line doesn't pass through it. So vouches form a graph, and rings away from the
-root hold nobody.
+A user creates whom it likes, within a limit (`limits.users`), and vouches for whom it
+likes, within another. The new user signs, claims and creates in turn from its
+creation on: in any change that has the creation in its history. A user is **vouched
+for** if its creator is, down from the root, and the creation counts; or if a user
+vouched for it whose own line doesn't pass through it. So vouches form a graph, and
+rings away from the root hold nobody.
A user's **line** is the users from the root down to its creator, then itself: fixed
when it is created. (If its creation stops counting and a `vouch` keeps it, its line
@@ -235,13 +260,12 @@ node (Bans). It changes nothing else.
Bringing someone in means handing over, out of the document, what a party needs: the
swarm key, the root to start from, some seeds; and writing the `create`.
-
-**What the root is.** A user like any other, but for three things. It is in the root
+ **What the root is.** A user like any other, but for three things. It is in the root
change, so nobody vouched for it, and its name can't be created again. It is on every
line, so its nodes' changes are what settles claims. And the users it creates are the
-**first users**, who come to vote for the swarm (Decisions). It can't write in another's
-namespace, nor take a settled name. It can contest any name, in the open. Who the
-root is can be decided anew (The root's seat).
+**first users**, who come to vote for the swarm (Decisions). It can't write in
+another's namespace, nor take a settled name. It can contest any name, in the open.
+Who the root is can be decided anew (The root's seat).
### Unvouching
@@ -267,12 +291,15 @@ exactly:
* **A vouch brings a user back whole,** with its names and what it signed in
between, as long as it isn't gone.
* **Out for long is gone.** A user is **gone**, at a set of changes, once a third of
- the voters each have a node with two alive stamps `gone` (30 days) or more apart,
+ the voters each have a node with two alive stamps `gone` or more apart,
the user out at both and at every stamp of that node between. Then its claims and
its creation stand no more: whoever comes first claims its names, and no vouch
brings it back. It comes in again by being created anew. Gone is read from the
changes alone and never goes away. Fewer than a third of the voters can't bring it
about early, and the time between two stamps is by one node's own clock.
+* **Or by a decision.** While a user is out, the voters free its names or give them
+ to another (Decisions), at once and whatever `gone` says. Where the policy sets no
+ `gone`, the names wait until a vouch or a decision.
* **What it did before stays done.** A name it released and another claimed stays the
other's; a user it created and another vouched for stays.
* **Out of sight.** What the user signs with dependencies from before the unvouch (on
@@ -281,8 +308,16 @@ exactly:
user's nodes only as part of another party's history, not from those nodes, so they
can't fill the document.
-So whoever relied on a user that is out has 30 days to find another who vouches: for
-itself, and for those it brought in. Until then nothing it holds can be taken.
+So whoever relied on a user that is out has that long to find another who vouches:
+for itself, and for those it brought in. Until then nothing it holds is taken, but
+by a decision.
+
+**Nobody is put out by a vote.** A user is in while one user that counts vouches for
+it, and no decision changes that. Against a user that keeps within the rules and
+harms all the same (squats names up to its limits, gets others' names contested)
+there is: each party's ban, which changes what that party reads (Bans); its vouchers
+unvouching it; and the root unvouching the first user above it, with all below, who
+then need other vouches. A vouch from anyone brings it back.
A user gives itself up by a `release` of its own creation: from that release on it is
gone, and its names are free at once.
@@ -329,10 +364,12 @@ What must be unique across users (a host's name, an address, a top-level domain)
`_continuum/claims/<kind>/<name>/<digest>` holds the statements about one name, again
only growing: `claim` (by the user who wants it) and `release` (by that user, of its
claim: how a name is given up). A claim **stands** while it counts, isn't released,
-and its user isn't gone. A claim is taken, as its writer saw the document, if a rule
-lets the user, the user is within the kind's limit, and no claim of that name stands
-there. That is first come, first served wherever one claim was made in sight of the
-other: the later one is refused by every node.
+its user isn't gone, and no decision freed the name or gave it away. A name a decision
+gave is a claim of the user it names, made where the decision counts. A claim is
+taken, as its writer saw the document, if a rule lets the user, the user is within the
+kind's limit, and no claim of that name stands there. That is first come, first served
+wherever one claim was made in sight of the other: the later one is refused by every
+node.
A claim says nothing else. What the name is for is in the namespace: a host's entry
names its addresses and names, and they count while its user holds them.
@@ -365,7 +402,7 @@ What this gives:
no other of that name that isn't released, every claim of the name surfacing later
is late against it, however old its dependencies look: the claim is settled. A node
tells (`settled`, below). The root's node writes when a claim reaches it that it
- hadn't seen, a minute apart at most, so a claim is settled within a minute of
+ hadn't seen, `witness` apart at most, so a claim is settled within that long of
reaching it.
* A user that is up is bound by its own node: after its node wrote once with a claim
in its history, it never holds that name against it.
@@ -523,8 +560,8 @@ Taking up is their nodes', and takes as long as syncing does.
**What is decided.**
-* **The numbers**: a limit or a time of the policy, named by its place there. It
- holds for what is made in sight of the decision. A lowered limit takes nothing
+* **The numbers**: any number of the policy, named by its place there, to any value.
+ It holds for what is made in sight of the decision. A lowered limit takes nothing
away: what a user has stays, and it gets no more until it is below.
* **The root's seat** (below).
* **A user's first keys**, for a user that lost them or had them stolen. The proposal
@@ -534,6 +571,13 @@ Taking up is their nodes', and takes as long as syncing does.
under another name, so that it has a voice and the voters know whom they give the
name back to. Decided, it signs under its name as before, with its names, its line
and those it brought in, and releases the other name.
+* **The names of a user that is out**, while they wait. The proposal names the user
+ and, for each name it deals with, its user name among them, that it is free or who
+ is to have it. A name freed is anyone's to claim from the decision on. A name
+ given is held by the user the decision names as by a claim: it counts toward that
+ user's limit, and that user releases it like one. A user name given brings its
+ namespace, where the new holder signs over what is there, and the names kept for
+ it. A user that is vouched for again has back what no decision dealt with.
* **A remake** (below).
* **A change of policy** (below): proposed and voted on the same way, made and
followed by choice.
@@ -575,7 +619,7 @@ holds isn't voted on: it is the registry as it resolves, which every node works
itself.
* **The base** is the history of the decision. A voter takes a remake up only
- if that holds all its node holds but the last ten minutes, so a decision can't
+ if that holds all its node holds but the last `baseAge`, so a decision can't
leave out what the swarm has.
* **Every node builds the snapshot** itself once the decision counts, from the base
as it holds it, and switches after the switch delay, as today. The snapshot holds
@@ -617,10 +661,18 @@ federated node never rejoins because peers advertise an epoch, however many do.
gets there in one of two ways:
1. **By the archives, on nobody's word.** A peer answers for an epoch it left as long
- as it keeps that epoch's document (`archiveRetention`). From such a peer the node
- syncs the rest of the epoch it is in, judging every change; sees the remake's
- decision count; builds the snapshot itself; and is in the next epoch, whose ID is
- the snapshot's hash. So on, epoch by epoch, as far as peers keep them.
+ as it keeps that epoch's document: `archiveRetention` at least, longer if its
+ operator says, and every epoch on a node kept as an archive. Peers say in the
+ handshake which epochs they keep. From such a peer the node syncs the rest of the
+ epoch it is in, judging every change; sees the remake's decision count; builds
+ the snapshot itself; and is in the next epoch, whose ID is the snapshot's hash.
+ So on, epoch by epoch, as far as peers keep them: with an archive within reach,
+ from any epoch to the swarm's, and for a node that joins, from the genesis root.
+ Where an epoch holds two remakes that count, or the walk ends in another epoch
+ than the node's peers are in, the node stops and shows it, for its operator to
+ say which: an archive can keep changes back, and a decision of long ago can be
+ made up with keys stolen since. Keeping an archive is an application's; continuum
+ answers for what a node keeps.
2. **By an ID, on its operator's word.** Where no peer keeps the epoch any more, the
node can't check how the swarm got from there to here. Its operator gives it the
ID of the epoch to go to (`POST /admin/epochs/rejoin`), from a party it trusts:
@@ -728,8 +780,9 @@ of a name is known can't scribble over the namespace, and one whose name a liar
contested goes on writing, for those who ban the liar to read.
Judging reads the registers at the change's dependencies, and nothing else: no cut is
-applied beyond a retiring or an unvouch that is there, and the numbers, the root and
-the first keys are as the decisions that count there leave them. A statement in a
+applied beyond a retiring or an unvouch that is there, and the numbers, the root, the
+first keys and the names freed or given are as the decisions that count there leave
+them. A statement in a
register was valid when it was taken, so judging the next needs no look further back.
### Resolving
@@ -740,8 +793,9 @@ the steps before:
1. **Decisions.** Which count (Decisions), one after the other as each names the one
of its matter before it, two following the same one undoing each other: the
- numbers, who the root is, and the first keys given. They are read from statements
- valid as written and from what the nodes recorded, so nothing below changes them.
+ numbers, who the root is, the first keys given, the names freed or given. They are
+ read from statements valid as written and from what the nodes recorded, so
+ nothing below changes them.
2. **Who counts, and where.** The first root counts. A user counts at a statement if
a `create` or `vouch` for it counts whose signer counts there (nearer the root, so
this ends), and the statement is within what every `unvouch` of that one leaves.
@@ -754,9 +808,10 @@ the steps before:
those made in sight of the others come first, then by digest. A user is **out**
where no `create` or `vouch` for it counts any more, and **gone** as said under
Unvouching.
-3. **Users' names.** A creation stands while it counts, isn't released, and its user
- isn't gone. Of the creations of a name that stand: the one that remains (Two
- claims) has the name, or has it wait while it is out.
+3. **Users' names.** A creation stands while it counts, isn't released, its user isn't
+ gone, and no decision freed the name or gave it away. Of the creations of a name
+ that stand: the one that remains (Two claims) has the name, or has it wait while it
+ is out.
4. **Names.** A claim stands the same way, where a rule lets its user: anyone vouched
for where the rule says `"*"`, else the user that has the name the rule gives. Of
the claims of a name that stand: one that has another in its history loses to it;
@@ -907,12 +962,12 @@ released (c is settled). Let c' be any other claim of that name. It isn't in the
history of s. The root is on every line, so s is a change by the side of c' with c in
its history and not c': c' is late against c, in every set of changes holding s, for
good. A late claim never holds a name while a rival stands, and c stands until it is
-released or its user is gone: out for 30 days by a third of the voters' own stamps,
-one of them honest. So nobody takes the name by a claim out of its sight. (A claim in
-its sight is one c was made after, released then: c loses to it if that release stops
-counting, which is the release's signer cutting off the key that signed it.) A new
-root changes nothing in this: the old one stays on the lines of everyone it was on,
-and its changes stay what they are.
+released, its user is gone (out for `gone` by a third of the voters' own stamps, one
+of them honest), or a decision deals with it. So nobody takes the name by a claim out
+of its sight. (A claim in its sight is one c was made after, released then: c loses to
+it if that release stops counting, which is the release's signer cutting off the key
+that signed it.) A new root changes nothing in this: the old one stays on the lines of
+everyone it was on, and its changes stay what they are.
What is left to an adversary: making c late too, so that none remains. That takes a
change by a node of c's own side with c' in its history and not c. An honest node
@@ -1044,7 +1099,8 @@ In the application, for the registry: which kinds there are and their rules (dat
the root), what a host's entry holds, the client that signs (an extension of
`scripts/continuum-signed`), moving the repository in, and writing out the files the
consumers read. Whether a host's entry may use a name is the application's check
-against the resolved registry, when it writes the files out.
+against the resolved registry, when it writes the files out. So are a node kept as
+an archive of every epoch, and whatever brings a vote from a person to a node.
More policies later are more data where a rule has a parameter, and a new rule in
continuum, with a policy version, where it hasn't; either way a change of policy.
@@ -1092,8 +1148,8 @@ Unvouching:
| 14 | The unvouched user signs on, with dependencies from before, or across a partition | Hold it as part of another's history only; it doesn't count; after healing every node finds the same | 2, 3 | unit: `past_an_unvouch`; sim: `an_unvouch_across_a_partition` |
| 15 | A user is unvouched: what of those it brought in, and its names? | They are out from the same point unless another vouches for them; a vouch after brings them back whole. Their names wait | 4 | unit: `those_it_brought_in`, `a_vouch_brings_back` |
| 16 | An unvouched user's nodes keep sending | Refused as peers; nothing taken from them | 6 | sim: `nothing_from_an_unvouched_node` |
-| 17 | Claims a name of a user that is out, or creates its user name | Refuse: the names wait until the user is gone | 5 | unit: `names_wait_while_out` |
-| 18 | Has a user unvouched, then stamps its nodes 30 days apart at once, to free the names | Gone takes a third of the voters | 5 | unit: `gone_by_a_third_of_the_voters` |
+| 17 | Claims a name of a user that is out, or creates its user name | Refuse: the names wait until the user is gone, or a decision frees them or gives them away | 5 | unit: `names_wait_while_out`, `a_decision_frees_or_gives` |
+| 18 | Has a user unvouched, then stamps its nodes `gone` apart at once, to free the names | Gone takes a third of the voters | 5 | unit: `gone_by_a_third_of_the_voters` |
| 19 | Vouches for a gone user with old dependencies, over a name claimed since | Gone stays: no vouch brings it back | 4 | unit: `gone_stays_gone` |
Namespaces:
@@ -1142,10 +1198,10 @@ Decisions, the root, remakes:
| 44 | Crafts or keeps back a decision until its votes ran out, then shows it | No honest voter takes it up: it doesn't count. One that counts by its makers' own records, long after (two thirds of their node keys stolen), is held back by every node that was up, and shown | 7 | unit: `taken_up_while_the_votes_run`; sim: `a_decision_from_the_past` |
| 45 | Two decisions of one matter, out of each other's sight | Each node takes up the first it receives; at most one counts | 7 | sim: `one_decision_a_matter` |
| 46 | Stamps its nodes far ahead, to make the others absent | The swarm's time stays at a stamp a third reached | 7 | unit: `the_swarms_time_by_a_third` |
-| 47 | Stays away to hold decisions up | Absent after 30 days: it doesn't count. Half the voters staying away do hold them up: the rest fork | 7 | unit: `absent_users_dont_count`, `more_than_half_of_all` |
+| 47 | Stays away to hold decisions up | Absent after `absent`: it doesn't count. Half the voters staying away do hold them up: the rest fork | 7 | unit: `absent_users_dont_count`, `more_than_half_of_all` |
| 48 | Asks the voters for another user's first keys, saying it is that user | It takes two thirds of them, and the days a vote takes, shown to all; the user signs on meanwhile | not promised | argued (Decisions) |
| 49 | Puts a voter's vote into a change of its own node; keeps one back; offers one again | Taken: the signature is the voter's. It counts while it runs; the register holds it once | 7 | unit: `a_vote_by_any_node` |
-| 50 | A decision lowers a limit below what users have | Nothing is taken away; no more is taken until below | 6 | unit: `a_lowered_limit_takes_nothing` |
+| 50 | A decision lowers a limit below what users have, or sets a number that makes no sense | Nothing is taken away, and no more is taken until below; the number has the result it has | 6 | unit: `a_lowered_limit_takes_nothing` |
| 51 | Decides a remake at a base that leaves out what the swarm holds | No honest voter's node takes it up | 7 | sim: `a_stale_base_is_not_taken_up` |
| 52 | Runs most of the nodes; serves a snapshot of its own | Nothing reads a count of nodes; every node builds the snapshot itself | 7 | sim: `every_node_builds_the_snapshot` |
| 53 | Signs a claim "in the epoch before" after a remake, to pass as carried over | It contests only what the snapshot holds unsettled, until the root's node wrote in the new epoch; then it is late | 5 | unit: `carried_over_or_pretending` |
@@ -1153,7 +1209,7 @@ Decisions, the root, remakes:
| 55 | Tells a node that was away of an epoch that isn't the swarm's | The node rejoins no epoch that peers advertise: it finishes the old one from archives and builds the next itself, or takes the ID its operator gave | 1 | sim: `away_over_a_remake`, `back_by_an_id` |
| 56 | A node back after several remakes offers what its user signed epochs ago | Refuse: an envelope is taken in its epoch and the next. Quarantined, for the user to sign again | 3 | unit: `carried_over_one_epoch_only` |
| 57 | The old root comes back after its seat went; crafts users "from before" | It is a first user; what the decision's history doesn't hold of it is an ordinary user's | 7 | unit: `the_old_root_comes_back` |
-| 58 | Two thirds of the voters turn on the rest | They remake, seat a root, set the numbers, and give a user's first keys to another: a name taken, in the open. They forge no signature and move nobody to other rules; the rest ban, stay, or fork | not promised | argued (A change of policy is a fork) |
+| 58 | Two thirds of the voters turn on the rest | They remake, seat a root, set the numbers, and give a user's first keys to another, or the names of a user that is out: a name taken, in the open. They forge no signature and move nobody to other rules; the rest ban, stay, or fork | not promised | argued (A change of policy is a fork) |
| 59 | Offers a statement signed on the other side of a fork | Refuse: it names its epoch | 3 | unit: `signed_for_its_user_id_and_epoch` |
| 60 | A change of policy with two thirds; a fork naming its proposer the only voter | A node follows only by its operator's word, which names the decision; what that says shows | 7 | sim: `a_fork_by_choice` |
@@ -1257,16 +1313,17 @@ the existing tests pass untouched (76).
10. **The registry.** Import, export, and a federated swarm of the simulations with
the registry's kinds and a few hundred hosts. From here it can be used; it only
grows.
-11. **Decisions.** The voters a root change names, the swarm's time and who is
- absent, `propose`, `vote` and `decide` taken from any node, taking up, what
- counts, `GET /registry/decisions`. What is decided: the numbers, a user's first
- keys. A user gone. The simulations start from a root change naming several
- voters, as a remake's does. Tests: 18, 19, 36, 40 to 47, 49, 50, 75.
+11. **Decisions.** The voters a root change names, the swarm's time and who is absent,
+ `propose`, `vote` and `decide` taken from any node, taking up, what counts, `GET
+ /registry/decisions`. What is decided: the numbers, a user's first keys, the names
+ of a user that is out. A user gone. The simulations start from a root change
+ naming several voters, as a remake's does. Tests: 18, 19, 36, 40 to 47, 49, 50,
+ 75.
12. **The root's seat.** Tests: 57.
13. **Remakes.** The base, the snapshot every node builds, carrying over from the
- epoch before and no further, what becomes final; peers answering for an epoch
- they left; a node rejoining by an ID its operator gave, and by none that peers
- advertise. Tests: 51 to 56.
+ epoch before and no further, what becomes final; peers answering for the epochs
+ they keep, and saying which; a node walking them, or rejoining by an ID its
+ operator gave, and by none that peers advertise. Tests: 51 to 56.
14. **A change of policy.** The fork, followed by an operator's word, with who votes
on its side. Tests: 59, 60.
@@ -1274,104 +1331,40 @@ the existing tests pass untouched (76).
Each with the options, and what I'd choose.
-1. **Who has a vote, and from when?** Two things pull: votes must not be multiplied by
- whoever brings users in, and whoever adds voters at will is never voted out.
- * *The first users an epoch starts with* (as designed). The root brings them in,
- and each votes from the first remake after it came, which two thirds of the
- voters before it decide. Nobody fills the votes. The price: until the first
- remake the root decides alone, a first user waits for a remake, and a user
- someone else brought in never votes.
- * *The first users, as soon as they are created.* No waiting. But the root creates
- as many as it likes: it carries every decision, and is never replaced against
- its will.
- * *The first users, let in by a decision of the voters*, without a remake. No
- waiting for a remake, and nobody fills the votes. But the voters of before can
- make a decision "of then" later (the root alone, for the time it was the only
- one), which only nodes that were up can tell: a remake is what puts that out
- of reach.
- * *Every user*, or users down to a depth. Then whoever creates users creates
- votes, and it takes a weight that thins out down the line to mean anything.
-
- *The first.*
-2. **Should the voters be able to put a user out against those who vouch for it?**
- As designed a user is in while one user that counts vouches for it. One that
- squats names up to its limits, or gets others' names contested, stays as long as
- a friend stands by it: a party bans it for itself, which changes what that party
- reads; the root can unvouch a first user and with it all below, who then need
- other vouches; and a vouch from anyone brings it back.
- * *No* (as designed): who is in is the vouchers' business, and what a party reads
- its own.
- * *Yes, a decision bars a user*: it is out for everyone, and no vouch brings it
- back until another decision says so. Two thirds of the voters then judge who is
- in.
-
- *No for now*; the second if bans prove too weak.
-3. **From where does an unvouch undo?** Its signer chooses its dependencies and can
- make them old: an unvouch written in June with January's dependencies looks like
- one from January, with everything the user signed since coming after it. What
- comes after doesn't count through that vouch, which matters for what stays done
- (a name the user released and another claimed) and for what a vouch brings back.
- * *From what the unvoucher's own nodes, or the root's, had seen* (as designed).
- What the user signed stays if one of those nodes committed a change on top of
- it without the unvouch. They write daily, so backdating undoes a day at most.
- * *Everything the user ever signed.* Simple, and nothing to backdate. But an
- unvouch then takes back the user's releases, and no vouch brings it back as it
- was.
- * *Only what the user signs in sight of the unvouch.* Then the user goes on by
- never building on it, which is no unvouch.
- * *From where each node received it.* What one would expect day to day, but it is
- in no document: two nodes would resolve the same changes differently.
-
- *The first.*
-4. **Is a user that was out for 30 days gone for good?** As designed, yes: its names
- are free, no vouch brings it back, it is created anew. That costs a user who was
- vouched for in time on the far side of a partition as long as that.
- * *For good* (as designed): whoever claims a name after can rely on it.
- * *Back by a vouch made before it was gone*, names claimed since contested: then
- a vouch crafted with old dependencies blocks any name claimed in good faith
- after a user went.
- * *No end*: the names wait until someone vouches. Nothing is lost by mistake, and
- nothing a user held is ever free again unless it releases it.
+1. **Are the fractions numbers too?** Two thirds of the voters present, more than
+ half of all, a third for the swarm's time and for a user gone.
+ * *No* (as designed): the promises are argued from them, and they change by a
+ change of policy, which each party follows or not.
+ * *Yes*, like every other number: then two thirds of the voters decide that a
+ majority decides, or that one voter does, for everyone.
- *For good*, and 30 days.
-5. **First keys by a decision: is the price right?** It is the way back for a user
- that lost its first keys, and the one way a name is taken against its user: two
- thirds of the voters give any user's keys to whoever they say, in the open, over
- a week.
- * *The voters* (as designed).
- * *Those who vouch for the user*, all of them signing: fewer to convince, but
- then a user's creator takes its name where nobody else vouched.
- * *Nobody*: a lost first key is a lost name, free once the user is unvouched and
- gone.
+ *No.*
+2. **What a decision gives of a user that is out.**
+ * *Any of its names, its user name among them* (as designed): a namespace goes to
+ another user, who signs over what is there.
+ * *Only names it claimed*: a namespace then comes back to its user, or is free for
+ whoever creates the name anew, and is never handed on.
- *The voters*; several first keys of which a number must sign, later, make it
- rare.
-6. **What the root holds unsigned.** The registry starts from the repository, and no
- user of it has a key in the swarm yet. What of their hosts, names and addresses?
- * *They count unsigned* (as designed). The root change holds every namespace's
- hosts as plain values and its addresses as claims in the namespace's name.
- Every party is given the root's hash, and the root is the repository, which is
- what is trusted today. Nobody changes a host until its user came: the root
- creates the user for the name (kept for the root to create), and the user signs
- over what is there. The price: the root says who gets which namespace, as the
- maintainer does today, and what nobody ever comes for stays, unsigned.
- * *Only what is signed.* The import takes the users who handed in a key, each
- signs its hosts, the rest stays in the repository until its user comes. Nothing
- unsigned ever counts; the registry is incomplete for as long as users take, and
- what reads it needs both sources meanwhile.
- * *Unsigned until a day*, then left out and its names free. A clean end, and
- hosts that work today stop working because their user didn't look.
+ *As designed.*
- *They count unsigned.*
+Settled, as the design has it:
-Settled: a name is contested, not the senior's, with `release` to give it up; one
-root, whose seat is decided anew; votes by users, over days, two thirds of those
-present and more than half of all, the absent left out; unvouching as above, with a
-cut taking back what others relied on and their names waiting meanwhile; first keys
-by a decision, several first keys later; the limits in the genesis policy, changed
-by a decision; a node back after many epochs as said under Coming back after
-remakes; a user without a node voting at any node; a change of policy as a fork; the
-mode optional.
+* a name is contested, not the senior's, with `release` to give it up;
+* one root, whose seat is decided anew;
+* votes by users, over days: two thirds of those present and more than half of all,
+ the absent left out;
+* who votes: the first users an epoch starts with;
+* nobody is put out by a vote;
+* an unvouch undoes from what its signer's nodes, or the root's, had seen;
+* what a cut or an unvouch takes back leaves those who relied on it out, their names
+ waiting; out for `gone` is gone for good, and the voters free or give names before;
+* first keys by a decision, several first keys later;
+* every number in the genesis policy, changed by a decision without constraint;
+* a node back after many epochs walks the archives, or is given an ID;
+* a user without a node votes at any node;
+* what the root holds unsigned counts until signed over;
+* a change of policy is a fork;
+* the mode is optional.
## What was checked, and what is assumed