You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: changes/v0.5.0.md
+30-22Lines changed: 30 additions & 22 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -1,20 +1,12 @@
1
1
# v0.5.0
2
2
3
-
Breaking. The CLI is overhauled: six commands are replaced, and `expose` now requires a grantee.
3
+
If you are on 0.4, two things stop working when you upgrade.
4
4
5
-
## Where this came from
5
+
- Six commands are gone: `ticket`, `grant-token`, `add-peer`, `pin`, `remove-peer`, `surfaces`.
6
+
- Four take their place: `invite`, `accept`, `forget`, `key`. What `surfaces` printed is in `list`.
7
+
-`expose` will not run without a grantee. `expose 3000` on its own is an error; pass `--to <key>`, or `--all` for every peer the daemon knows right now.
6
8
7
-
The CLI had grown a command at a time, as features landed. By 0.4, five of them covered one job: getting two machines to talk to each other. `ticket`, `grant-token`, `add-peer`, `pin`, `remove-peer`.
8
-
9
-
So we stopped adding to it. We wrote down what you actually type, on both machines, to get a link up. That became `docs/scenarios.md`.
10
-
11
-
The first flow did not work. Reaching a shared build box from a laptop already running a daemon meant sending two values out of band, a key and a token. Neither was ever used without the other. `add-peer` could not present a token. `--enroll` existed only on `pai-sho daemon`, so a laptop already serving other peers had to restart to admit one more. None of it was hidden in the code. It just never came up until the whole flow was on one page.
12
-
13
-
The names took several rounds. `pin` was tried and dropped, along with `grant-key` and `allow`/`connect`. Each described a mechanism rather than the thing happening, which is closer to: hi, be friends. And: yeah, be friends. That is `invite` and `accept`, and the rest followed from the pair. An invitation collapsed into one value instead of two, since both halves always travelled together anyway. The grant moved onto the invitation: both steps happen on the same machine and express one intention. And naming went local. A name is what you type into a URL, so it belongs to whoever is typing.
14
-
15
-
The same exercise turned up the `expose` default-allow. Writing "and then nothing is reachable until you grant it" one paragraph away from a command that granted to every peer you knew is hard to miss once both are on the page.
16
-
17
-
We think this is much nicer to use, and hope you do too.
9
+
The table has the replacement for each.
18
10
19
11
## Migrating
20
12
@@ -23,30 +15,46 @@ We think this is much nicer to use, and hope you do too.
23
15
|`pai-sho ticket`|`pai-sho key`, or `pai-sho invite` for a one-time invitation |
|`pai-sho expose <port>`|`pai-sho expose <port> --to <key>` or `--all`|
30
22
|`pai-sho daemon -a <key> --enroll <token>`|`pai-sho daemon --accept <invite>`|
31
23
32
-
## Highlights
24
+
## Why the commands changed
25
+
26
+
The commands for linking two machines grew one release at a time. [0.1](https://github.com/cablehead/pai-sho/blob/v0.5.0/changes/v0.1.0.md) had `ticket` and `add-peer`: print your key, hand it over, the other side adds you. [0.3](https://github.com/cablehead/pai-sho/blob/v0.5.0/changes/v0.3.0.md) gave peers a stable identity and made every grant name the peer it is for, and with that came two more ways to admit a peer: `grant-token`, a one-time code, and `pin`, for a key the host vouches for. By [0.4](https://github.com/cablehead/pai-sho/blob/v0.5.0/changes/v0.4.0.md) there were five commands for one job, and which ones you used depended on which side was dialing.
27
+
28
+
0.5 started from the flows, written down in `docs/scenarios.md` before any code changed, as the commands a person types, machine by machine. The one that showed the problem is a laptop reaching a shared build box, with the laptop's daemon already up and serving other peers. In 0.4 commands it goes like this. On the build box, run `ticket` and `grant-token`, and carry both values to the laptop. On the laptop, the only command that takes a token is `pai-sho daemon --enroll`, and the laptop's daemon is already running. `add-peer` takes a key and nothing else.
33
29
34
-
-**`invite` and `accept`.** One side extends an invitation and the other takes it up. Neither works alone. An invitation is one value, `<key>.<code>`: who to dial, and the proof you may. `accept` also takes a bare key. That is the host-attested path from ADR 0003, where no secret travels into the guest. A running daemon can admit a peer without restarting ([ADR 0006](https://github.com/cablehead/pai-sho/blob/v0.5.0/docs/adr/0006-invitations.md)).
30
+
Linking two machines is one asking and the other agreeing. Hi, can we be friends? Yes, friends. None of the 0.4 names said that. `add-peer` read like it finished the job, and when the other side had not said yes, the only sign was a log line on its machine.
31
+
32
+
So the five commands became two, one for each half. `invite` asks, `accept` agrees, and nothing connects until both have run. The key and the code travel as one string, `key.code`, since a code was never any use without the key to present it to. The grant can ride on the invitation, `invite --expose 8080`, because both steps happen on the same machine. And each side picks the name it will type in URLs for the other, with `--as`. In 0.4 the inviter chose it, with `grant-token --label`, and the inviter was the side that never typed it.
33
+
34
+
`surfaces` and `list` printed overlapping JSON. `list` now has one row per peer with all of it.
35
+
36
+
I think this is much nicer to use, and hope you do too.
37
+
38
+
## Why `expose` changed
39
+
40
+
`expose 3000` on its own used to grant the port to every peer the daemon knew. The rule since [ADR 0001](https://github.com/cablehead/pai-sho/blob/v0.5.0/docs/adr/0001-directed-grants.md) is that a port is reachable only by the peers you grant it to. Bare `expose` granted it to everyone at once without you naming anyone, so adding a peer to reach its ports silently made it a recipient of every port you exposed afterwards. Now you name the grantee, with `--to <key>` or `--all`. `--all` grants to the peers the daemon knows at that moment, and a peer you admit later gets nothing until you expose to it.
41
+
42
+
## Highlights
35
43
36
-
-**`expose` requires `--to <key>` or `--all`.**Bare `expose <port>` used to grant to every peer the daemon knew, a default-allow inside a system whose first ADR opens with default deny. `--all` is explicit now, and it means every peer known at that moment, never a standing rule for peers admitted later.
44
+
-**Bare keys on both sides.**For a workload that cannot safely be handed a secret, such as a VM whose invitation would sit on its kernel cmdline: it generates its own keypair, the host reads off the public half and runs `invite <key>`, and the workload runs `accept <host-key>`. No code is minted and nothing secret travels into the workload ([ADR 0003](https://github.com/cablehead/pai-sho/blob/v0.5.0/docs/adr/0003-host-attested-enrollment.md), [ADR 0006](https://github.com/cablehead/pai-sho/blob/v0.5.0/docs/adr/0006-invitations.md)).
37
45
38
-
-**A pure core.** Admission and authorization moved to `src/core/session.rs`, a state machine with no IO that returns actions for the shell to carry out. The decisions are now reachable from unit tests that run in microseconds, where before they needed two live endpoints and a real listener ([ADR 0007](https://github.com/cablehead/pai-sho/blob/v0.5.0/docs/adr/0007-pure-core.md)).
46
+
-**A pure core.** Admission and authorization moved out of `peer.rs` into `src/core/session.rs`, a state machine with no IO that returns actions for the networking code in `peer.rs`to carry out. In `peer.rs` those decisions had no tests, because testing them meant two daemons and a network. Now they are unit tests that run in microseconds ([ADR 0007](https://github.com/cablehead/pai-sho/blob/v0.5.0/docs/adr/0007-pure-core.md)).
39
47
40
-
-**`list` says how each peer arrived**, by code or by key, since the two carry different weight when auditing who is on your network.
48
+
-**`list` says how each peer arrived**, by code or by key. The two carry different weight when you are auditing who is on your network.
41
49
42
50
## Fixes
43
51
44
-
-`add_peer` dialed before recording the peer. A failed dial left nothing behind, so there was no peer and nothing to retry, and a flow `docs/scenarios.md` said should work silently didn't. It records first now.
45
-
- A failed port bind was logged and dropped, on the theory that the next announce would retry it. A peer with a stable port set never re-announces, so the port stayed dark until something else changed. Binds now retry.
52
+
-A peer added while its daemon was down was lost. The dial happened before anything was recorded, so a failed dial left no peer and nothing to retry. The peer is recorded first now and the connection loop does the dialing, which also makes the first dial immediate instead of after a backoff.
53
+
- A port that failed to bind once stayed unreachable. The failure was logged and dropped, on the theory that the peer's next announce would retry it, but a peer whose ports do not change never re-announces. Binds now retry five times, 200ms apart.
46
54
47
55
## Tests
48
56
49
-
72 tests, from a suite that could not reach the security decisions at all. Unit tests in `core` cover admission, grants, and tunnel authorization;`live_tests.rs` runs two real daemons over loopback with relays disabled for dialing, reconnection, binding, and eviction. Mutation testing confirms they bite: replacing the grant check with `if true` fails five tests.
57
+
72 tests, up from 19. The 19 all lived in the modules that happened to be pure, and deleting the authorization check in `peer.rs` would have kept them green. Unit tests in `core`now cover admission, grants, and tunnel authorization.`live_tests.rs` runs two real daemons over loopback with relays disabled, for dialing, reconnection, binding, and eviction. Replacing the grant check with `if true` fails five of them.
0 commit comments