Skip to main content

Module pairing_posture

Module pairing_posture 

Source
Expand description

Pairing posture: the data-plane auth primitives shared by the agent’s native surfaces.

The agent is paired-or-unpaired. Physical presence on the LAN is the gate for an UNPAIRED agent (the claim window); once paired, a data-plane caller reaching the agent from off-box must present the stored pairing key. The local operator (a loopback peer that was not relayed by a proxy or tunnel) already holds shell-level privilege that exceeds API auth and is trusted past the gate.

Who the caller is gets decided ONCE per request, at the transport edge, by classify_caller: the peer address plus the request’s forwarding headers give one CallerClass. Every gate (the HTTP unpaired-node gate, the dashboard-PIN first set, the pairing claim, the direct MAVLink proxies) is a function of that value and the pairing state, so no two gates can read the same caller differently.

These primitives are protocol-level on purpose: more than one native surface enforces the same posture (the HTTP control surface and the direct MAVLink proxies), and a single implementation keeps them from drifting. Surface-specific concerns (request-rate limiting, the HTTP public-path exempt set, the short-TTL caching wrapper) live with each surface, not here.

The pairing state is the agent’s pairing.json ({ "paired": bool, "api_key": "..." }). Read it with load_pairing: an absent file, or one that is not paired:true, reads as Pairing::Unpaired (open). A file that exists but cannot be read or parsed, or claims paired:true with no key, is Pairing::Unreadable and fails closed: it may be a paired node’s record on a failing card, and reading it as unpaired would open the claim to anyone.

Enums§

Access
A data-plane access decision for a paired-or-unpaired agent.
CallerClass
Who is on the other end of a request, derived once at the transport edge by classify_caller.
Pairing
The resolved pairing posture read from pairing.json.

Constants§

FORWARDED_HEADERS
Proxy / tunnel relay headers. Their presence means the request was forwarded by a reverse proxy or tunnel (e.g. a Cloudflare Tunnel terminating on 127.0.0.1) rather than originating on this host, so it must NOT qualify for on-box loopback trust.
LIFELINE_LOCAL_ADDRS
The agent-owned first-boot addresses: the AP hotspot gateway and the USB gadget address. A private-LAN peer is a lifeline only when it reached one of these.
RELAY_FORBIDDEN_CONFIG_KEYS
Config subtrees no radio lane may write: the node’s trust roots.

Functions§

classify_caller
Classify a caller from its peer address, the local address it reached, and its request headers.
constant_time_eq
Compare two byte slices in time independent of where they first differ, so the bearer-secret check leaks no timing signal about a partial match. A length mismatch is rejected up front (the length of the stored key is not itself a secret); equal-length slices are then folded together with a running difference accumulator that always visits every byte. The compiler is told via std::hint::black_box not to short-circuit the loop once a difference is seen.
data_plane_access
Decide whether a data-plane connection may be admitted, independent of any transport:
load_pairing
Load the pairing posture from a pairing.json. An absent file, or a state that is not paired:true, is Pairing::Unpaired (open). A file that exists but cannot be read or parsed as a JSON object, or that says paired:true without a key, is Pairing::Unreadable (closed).
local_addr_toward
The local address this host would use to reach peer: the kernel’s route choice, read by connecting an unbound UDP socket (no packet is sent). For a transport that has no per-connection local address (a UDP listener bound to the wildcard), this is the address a reply to the peer leaves from, which is the interface the peer sits on. None when no route exists.
relay_config_key_forbidden
Whether a config write arriving over a radio lane may not touch key (a dotted path): the key is one of RELAY_FORBIDDEN_CONFIG_KEYS or lies beneath one.