Files
alkcall/docs/architecture/decisions/054-outgoing-only-x509-three-remote-roles.md
T
glm-5.3-flash 5f019c02f1 docs: re-key architecture docs off the alknet mono-repo — speak as alkcall
The ported docs still framed alknet siblings (alknet-core/-call/-channels/
-http/-tls/-client) as live load-bearing context of this crate. With the
extraction complete and alknet headed for glue-level replacement, the docs
now speak as alkcall and cite the real sibling crates (alkhttp, alktls,
alktty, alktunnels, alktrader).

- ADR-054 (new): re-own the verifier-selection rule in-crate — three
  remote roles (public X.509 endpoint / transport relay / hub),
  ServerCertVerifier by PeerEntry presence, RemoteIdentity None
  load-bearing. Provenance: alknet ADR-034 (never ported), demoted to
  footnote. Resolves OQ-21's cross-repo authority gap.
- OQ-43 (new, deferred(scope)): composition-layer ownership and shape
  after the alknet replacement — the named receiver for the
  downstream-side deferrals (OQ-33 endpoint layer, OQ-41 QUIC-native
  substrate, OQ-42 hub broker, OQ-19 persistence adapters, ADR-045 dial
  seam). README layering diagram redrawn with the composition layer as
  TBD-ownership instead of "alknet / alknode" in concrete.
- Spec docs reframed: titles, self-references, dial/TLS/from_jsonschema
  homes, malformed legacy cite rows removed; dead relative research
  paths qualified as source-repo paths.
- ADR amendments (append-only): 027 (alknet-http -> alkhttp), 031 (post-
  extraction state), 044 (split landed as modules in alkcall), 045
  (name normalization; citation-space note).
- Citation hygiene: unprefixed/colliding source-repo cites prefixed
  ("alknet ADR-NNN (provenance)") across 009/011/022/034/035/038/040/
  043/044/045; stale OQ cites corrected (session registries OQ-04, batch
  semantics OQ-03, verifier rule ADR-054); stale anchors fixed.
- README provenance note consolidated; citation conventions documented.

Verification: markdown link check (all local links resolve, all in-crate
ADR cites point at existing decisions/ files); table integrity check
(uniform row widths across open-questions.md and edited tables); residual
alknet-mention sweep (only provenance/historical/intentional framing
remains); architecture review subagent pass with zero remaining criticals.
Docs-only change — no code paths touched.
2026-10-13 10:53:47 +00:00

5.6 KiB

ADR-054: Outgoing-Only X.509 and the Three Remote Roles (Re-Owned In-Crate)

Status

Accepted (re-owns the verifier-selection rule for alkcall's surface; provenance: alknet ADR-034, not ported)

Context

alkcall's connection surface depends on a verifier-selection rule and a role taxonomy that were decided while this crate was a subdirectory of the alknet mono-repo. The deciding ADR (alknet ADR-034, "Outgoing-Only X.509 and Three Peer Roles") was never ported, so the rule's authority lives in a cross-repo link — a dependency on a document outside this crate for a constraint that binds this crate's public surface:

  • ConnectionCredentials.remote_identity: None semantics (ADR-022 §7, (ADR-022 §7; alknet ADR-034 §2/§3, provenance): None is a load-bearing state — the public-X.509-endpoint path, not a missing field.
  • Client-side ServerCertVerifier selection is by PeerEntry presence, not by key type alone (OQ-14 #2).
  • PeerEntry asymmetry: a pure-client connection to a public X.509 endpoint is not in the call-protocol peer graph on the client side (no PeerEntry, no PeerId, no PeerRef::Specific routing).

The alknet mono-repo is being rewritten as a thin glue layer over this crate and its siblings; cross-repo ADR links will not survive that rewrite as authority. The rule must be owned here.

Decision

alkcall re-owns the rule in-crate. Three things are adopted:

1. Three remote roles

The single label "X.509 endpoint" conflated three structurally different remote roles:

  • Public X.509 endpoint — a remote server reachable by domain name, authenticated by a CA-issued X.509 cert. The local node is a client of it (a third-party API, a public hub dialed over the open internet, a peer that exposes domain + X.509 instead of an Ed25519 raw key). The client authenticates to the server by bearer token (auth_token payload field when riding the call protocol); the server authenticates to the client by CA verification (WebPKI), not fingerprint pinning.
  • Transport relay — a connectivity-assistance node (iroh's DERP-equivalent) that forwards encrypted datagrams between peers who cannot directly connect. It is infrastructure, not an application peer: no registered operations, no peer graph participation, no PeerEntry. Its identity is the transport's concern, not this crate's.
  • Hub / hosting node — an application peer acting as a hub in a hub-and-spoke topology. An ordinary PeerEntry holding mixed fingerprints (Ed25519 raw key and/or X.509) — fingerprint pinning applies on both cert paths.

2. Verifier selection is by PeerEntry presence, not key type

The client-side ServerCertVerifier is selected by whether the local node holds a PeerEntry for the remote:

Local PeerEntry for remote? Remote cert Verifier Peer graph?
yes Ed25519 or X.509 fingerprint pin in (PeerId resolved from client-cert fingerprint — ADR-025 §5)
no X.509 WebPkiServerVerifier (CA) not in (no PeerId)
no Ed25519 raw key fail closed (no CA to fall back to) not in

3. remote_identity: None is load-bearing

Some(fingerprint) means "pin this" (known peer). None means "no PeerEntry for this remote" — CA verification for X.509 remotes, hard failure for Ed25519 raw-key remotes. An implementation must not default remote_identity to a placeholder to satisfy the field, and must not treat None as "skip verification."

4. Scope of the re-own

This ADR is the deciding authority for alkcall's surface (ConnectionCredentials, RemoteIdentity, the ServerCertVerifier selection the dial-composer implements, PeerEntry asymmetry in the peer graph). It does not re-own alknet ADR-034's other content (ACME issuance, cert rotation, the alktls config surface) — those remain properties of the transport/composition layer (see OQ-43, composition layer). alknet ADR-034 is demoted to provenance: historical origin of this rule, cited as such.

Consequences

Positive:

  • The constraint binding alkcall's public surface is decided in this crate's decision log; cross-repo link rot cannot strip the authority.
  • OQ-21's "deciding ADR (alknet ADR-034, not ported)" caveat is resolved — the surviving surfaces (client-and-adapters.md §credentials, ADR-025's PeerEntry asymmetry) now cite an in-crate ADR.
  • The alknet rewrite can proceed without a documentation dependency from this crate on the old repo's ADR numbering.

Negative:

  • One more rule with a historical origin story in a different numbering space; the provenance note (README §References) is the single place that maps old to new.

References

  • client-and-adapters.md — the working spec carrying these semantics (§Credential sources for connections, §Constraints "Pure-client X.509 connections", remote_identity load-bearing rule)
  • ADR-022 §7 — transport-identity dimensions on the call protocol
  • ADR-025 — PeerEntry asymmetry, PeerId source, client-cert fingerprint → peer_id resolution
  • ADR-012 — ConnectionCredentials shape (the dial consumes it; verifier selection is applied there)
  • OQ-21 (resolved by this ADR), OQ-43 (composition-layer ownership — the transport/composition half mentioned in §4's scope carve-out)
  • Provenance: alknet ADR-034, "Outgoing-Only X.509 and Three Peer Roles" (/workspace/@alkdev/alknet/docs/architecture/decisions/), retained as history, not authority