inbuxa Relay: the downstream's link service #253

Merged
jcoffey-dev merged 2 commits from relay/link-service into main 2026-10-30 05:49:12 +00:00
Owner

The second server-side part of docs/spec/features/relay.md ("The link",
"Recipients", "Joining and reset"):

  • Every node dials each enabled relay over JMAP on WebSocket, with TLS
    1.3 and a client certificate signed by the downstream's link CA. Node
    certificates last 30 days and are renewed after 20; the relay pins
    the CA, not the node.
  • Joining: while a relay waits for its join, a node posts Relay/join
    with a fresh nonce, checks the proof against the token's secret and
    the relay's key, and records the pin by compare-and-set, so two nodes
    joining at once agree. An expired token reports joinFailed. Once
    joined, a node only talks to the pinned key.
  • Settings: the relay's settings are pushed whole when they change,
    with the domains, the sealing key, the recipient key and the SMTP
    certificate filled in by the downstream.
  • Recipients: the relay's domains (all enabled local domains, or the
    ones it names), with catch-all and the sub-address separator; every
    account, list and alias address at each domain name, and masked
    emails that take mail. The first push is the whole hashed set as a
    blob (Recipient/replace); after that, deltas through Recipient/set,
    falling back to a whole push past 2000 changes.
  • A relay change wakes the links at once; otherwise they resync every
    15 s and on the relay's Relay push. Moving a relay restarts its link;
    turning one off closes it.
  • Each node's link (state, since, last seen, last error, the relay's
    own status and recipient count) is kept per node and read back as
    the relay's links property; destroying a relay clears it.
  • A system test runs the real inbuxa-relay binary: join, pin, recipient
    push, RCPT accept and reject, a new user reaching the relay, a
    settings push, and turning it off.

Checks run locally: the relay and relay link system tests, the
features relay unit tests, rustfmt, clippy on the changed files, and
the fork checks.

Open question: domains answered by an external directory (LDAP, SQL,
OIDC) can't be listed, so only the accounts this server has already
seen from it are pushed. Other real users there would be refused at the
relay until they first sign in.

The second server-side part of docs/spec/features/relay.md ("The link", "Recipients", "Joining and reset"): - Every node dials each enabled relay over JMAP on WebSocket, with TLS 1.3 and a client certificate signed by the downstream's link CA. Node certificates last 30 days and are renewed after 20; the relay pins the CA, not the node. - Joining: while a relay waits for its join, a node posts Relay/join with a fresh nonce, checks the proof against the token's secret and the relay's key, and records the pin by compare-and-set, so two nodes joining at once agree. An expired token reports joinFailed. Once joined, a node only talks to the pinned key. - Settings: the relay's settings are pushed whole when they change, with the domains, the sealing key, the recipient key and the SMTP certificate filled in by the downstream. - Recipients: the relay's domains (all enabled local domains, or the ones it names), with catch-all and the sub-address separator; every account, list and alias address at each domain name, and masked emails that take mail. The first push is the whole hashed set as a blob (Recipient/replace); after that, deltas through Recipient/set, falling back to a whole push past 2000 changes. - A relay change wakes the links at once; otherwise they resync every 15 s and on the relay's Relay push. Moving a relay restarts its link; turning one off closes it. - Each node's link (state, since, last seen, last error, the relay's own status and recipient count) is kept per node and read back as the relay's links property; destroying a relay clears it. - A system test runs the real inbuxa-relay binary: join, pin, recipient push, RCPT accept and reject, a new user reaching the relay, a settings push, and turning it off. Checks run locally: the relay and relay link system tests, the features relay unit tests, rustfmt, clippy on the changed files, and the fork checks. Open question: domains answered by an external directory (LDAP, SQL, OIDC) can't be listed, so only the accounts this server has already seen from it are pushed. Other real users there would be refused at the relay until they first sign in.
jcoffey-dev added 1 commit 2026-10-30 05:23:23 +00:00
inbuxa Relay: the downstream's link service
github/ci (branch) GitHub Actions
ci / fork-checks (pull_request) Skipped
ci / build (pull_request) Skipped
ci / github (pull_request) Canceled after 30s
30c83c8ef7
The second server-side part of docs/spec/features/relay.md ("The link",
"Recipients", "Joining and reset"):

- Every node dials each enabled relay over JMAP on WebSocket, with TLS
  1.3 and a client certificate signed by the downstream's link CA. Node
  certificates last 30 days and are renewed after 20; the relay pins
  the CA, not the node.
- Joining: while a relay waits for its join, a node posts Relay/join
  with a fresh nonce, checks the proof against the token's secret and
  the relay's key, and records the pin by compare-and-set, so two nodes
  joining at once agree. An expired token reports joinFailed. Once
  joined, a node only talks to the pinned key.
- Settings: the relay's settings are pushed whole when they change,
  with the domains, the sealing key, the recipient key and the SMTP
  certificate filled in by the downstream.
- Recipients: the relay's domains (all enabled local domains, or the
  ones it names), with catch-all and the sub-address separator; every
  account, list and alias address at each domain name, and masked
  emails that take mail. The first push is the whole hashed set as a
  blob (Recipient/replace); after that, deltas through Recipient/set,
  falling back to a whole push past 2000 changes.
- A relay change wakes the links at once; otherwise they resync every
  15 s and on the relay's Relay push. Moving a relay restarts its link;
  turning one off closes it.
- Each node's link (state, since, last seen, last error, the relay's
  own status and recipient count) is kept per node and read back as
  the relay's links property; destroying a relay clears it.
- A system test runs the real inbuxa-relay binary: join, pin, recipient
  push, RCPT accept and reject, a new user reaching the relay, a
  settings push, and turning it off.
jcoffey-dev added 1 commit 2026-10-30 05:23:43 +00:00
Name PR #253 in the relay spec's implementation status
ci / fork-checks (pull_request) Skipped
ci / build (pull_request) Skipped
github/ci (branch) GitHub Actions
ci / github (pull_request) Successful in 9m46s
29ee08c9cb
jcoffey-dev merged commit 8ee4787c2c into main 2026-10-30 05:49:12 +00:00
jcoffey-dev deleted branch relay/link-service 2026-10-30 05:49:12 +00:00
Sign in to join this conversation.