RL-34: replace the link CA every relay shares, without a new join on each relay.
How it goes
The API. An update of any inbuxa:Relay with replaceLinkCa (start, finish or cancel), sent on its own, acts on the shared link CA. A new JMAP object for one action on a shared key was about 600 lines of wiring, so it stays on the relay. On create, or with other properties, it is refused; an action that changes nothing is refused too.
Start makes the next CA. Each node pushes its pin as nextLinkCaPin, and the relay trusts both CAs, listing them in status.linkCaPins.
Every relay showslinkCaReplacing and its own linkCa: current, both, or old (it needs a new join; this includes a join whose token named a CA since replaced).
Finish happens by itself once every enabled, joined relay says both. The link service then emits relay.link-ca-replaced (event 659). Each node takes a certificate from the new CA and links again.
On the relay, nextLinkCaPin: null pushed over a link on the next CA makes that CA its only one. It is saved in the identity first, every link on the old CA is ended, and the event is recorded. From the current CA, null is a cancel. A link on the next CA can't name another. So the old CA is only dropped once the new one is proven end to end, and a leaked old certificate stops working.
Fix: the link service now sends settings it has cleared as explicit null. The relay merges a push, so a setting left out stayed as it was. That was also a latent bug: a certificate removed on the server stayed on the relay.
Tests
cargo fmt --check; clippy (--tests) on the changed crates; the fork checks and their tests; expr-schema --check.
Relay unit and end to end tests (28), with RL-T26 covering both CAs trusted, the refusals, the promotion, and the old CA's link cut and refused.
system::relay::relay_tests and relay_link_tests against the real relay binary. The latter covers start, the finish by itself, the relay's identity on the new CA, and the relay still joined.
Unit test link_ca_states; features and services relay tests.
The console part (a "Replace link CA…" action and the per-relay state) follows in inbuxa-admin.
RL-34: replace the link CA every relay shares, without a new join on each relay.
## How it goes
- **The API.** An update of any `inbuxa:Relay` with `replaceLinkCa` (`start`, `finish` or `cancel`), sent on its own, acts on the shared link CA. A new JMAP object for one action on a shared key was about 600 lines of wiring, so it stays on the relay. On create, or with other properties, it is refused; an action that changes nothing is refused too.
- **Start** makes the next CA. Each node pushes its pin as `nextLinkCaPin`, and the relay trusts both CAs, listing them in `status.linkCaPins`.
- **Every relay shows** `linkCaReplacing` and its own `linkCa`: `current`, `both`, or `old` (it needs a new join; this includes a join whose token named a CA since replaced).
- **Finish happens by itself** once every enabled, joined relay says `both`. The link service then emits `relay.link-ca-replaced` (event 659). Each node takes a certificate from the new CA and links again.
- **On the relay**, `nextLinkCaPin: null` pushed over a link on the next CA makes that CA its only one. It is saved in the identity first, every link on the old CA is ended, and the event is recorded. From the current CA, null is a cancel. A link on the next CA can't name another. So the old CA is only dropped once the new one is proven end to end, and a leaked old certificate stops working.
- **Fix:** the link service now sends settings it has cleared as explicit null. The relay merges a push, so a setting left out stayed as it was. That was also a latent bug: a certificate removed on the server stayed on the relay.
## Tests
- `cargo fmt --check`; clippy (`--tests`) on the changed crates; the fork checks and their tests; `expr-schema --check`.
- Relay unit and end to end tests (28), with RL-T26 covering both CAs trusted, the refusals, the promotion, and the old CA's link cut and refused.
- `system::relay::relay_tests` and `relay_link_tests` against the real relay binary. The latter covers start, the finish by itself, the relay's identity on the new CA, and the relay still joined.
- Unit test `link_ca_states`; features and services relay tests.
The console part (a "Replace link CA…" action and the per-relay state) follows in inbuxa-admin.
An update of any inbuxa:Relay with replaceLinkCa, sent on its own, acts
on the link CA every relay shares: start makes the next CA, finish makes
it the link CA, cancel drops it. Every relay shows linkCaReplacing and
its own linkCa (current, both, or old: it needs a new join).
While one is under way, each node pushes the next CA's pin as
nextLinkCaPin, and the relay trusts both, listing them in
status.linkCaPins. Once every enabled, joined relay says both, the link
service finishes it (relay.link-ca-replaced, event 659): each node takes
a certificate from the new CA and links again. Its push of
nextLinkCaPin: null, from a link on the next CA, makes that CA the
relay's only one: saved in its identity, every link on the old CA ended,
and relay.link-ca-replaced recorded. From the current CA, null is a
cancel; a link on the next CA can't name another.
The link service now sends settings it has cleared as null: the relay
merges a push, so one left out stayed as it was. That also fixes a
certificate removed here staying on the relay.
A join whose token named a CA since replaced shows linkCa old.
Tested: the relay's end to end test (both CAs trusted, the refusals,
the promotion, the old CA's link cut and refused), the server's relay
link test against the real relay binary (start, finished by itself,
the relay's identity on the new CA, still joined), relay_tests, and a
unit test of the linkCa states.
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.
RL-34: replace the link CA every relay shares, without a new join on each relay.
How it goes
inbuxa:RelaywithreplaceLinkCa(start,finishorcancel), sent on its own, acts on the shared link CA. A new JMAP object for one action on a shared key was about 600 lines of wiring, so it stays on the relay. On create, or with other properties, it is refused; an action that changes nothing is refused too.nextLinkCaPin, and the relay trusts both CAs, listing them instatus.linkCaPins.linkCaReplacingand its ownlinkCa:current,both, orold(it needs a new join; this includes a join whose token named a CA since replaced).both. The link service then emitsrelay.link-ca-replaced(event 659). Each node takes a certificate from the new CA and links again.nextLinkCaPin: nullpushed over a link on the next CA makes that CA its only one. It is saved in the identity first, every link on the old CA is ended, and the event is recorded. From the current CA, null is a cancel. A link on the next CA can't name another. So the old CA is only dropped once the new one is proven end to end, and a leaked old certificate stops working.Tests
cargo fmt --check; clippy (--tests) on the changed crates; the fork checks and their tests;expr-schema --check.system::relay::relay_testsandrelay_link_testsagainst the real relay binary. The latter covers start, the finish by itself, the relay's identity on the new CA, and the relay still joined.link_ca_states; features and services relay tests.The console part (a "Replace link CA…" action and the per-relay state) follows in inbuxa-admin.