macula_station_check (macula v14.9.0)
View SourceThe client's station-authorization check (macula-station#63, hook 3).
A client about to dial a node as a station reads that station's authorization slot — station_authorization_key(Realm, Station) — through its own station link (the find_record it dials with) and requires a live authorization. The check is mode-aware, and the mode is fleet configuration (application:get_env(macula, station_authorization_mode)); S1/S2 ship in open, the flip to closed is S4:
open— the check runs, the dial proceeds, and awould_refusecounter (the pool'sstation_checksstatus) increments when there is no live authorization;log— asopen, plus one log line per would-be refusal;closed— no live authorization refuses the dial.
The first dial a pool makes is its configured seed, from config trust: there is no link yet to read a slot through. Every later dial of a node as a station — the stations macula_direct_dial resolves — is slot-verified here. Nothing is presented on the wire (presentation decision (c), DHT-lookup-only), so the check has no replay surface.
Summary
Types
What one slot read is judged against: the dialed pair, the realm key the pool pinned for the realm (the realm's signing key, the one that signs its station authorizations and their tombstones), and the verifier's clock.
Functions
The check: read Station's authorization slot for Realm — through Dial's find_record, within TimeoutMs — judge it against the realm key the pool pinned for Realm, and settle it under the configured mode. ok admits the dial; {error, {station_not_authorized, Verdict}} refuses it (mode closed only). A pool that pinned no key for Realm has nothing to judge a record by: its verdict is unanchored and the slot is not read. Every check is counted on the pool's station_checks.
What one slot read means, judged against Trust. A record counts only when the pinned realm key signed it: the read verified a signature and the signer's purpose, and any process can mint a key of purpose realm, so the signer itself must be the realm's. Then an authorization for exactly the dialed realm and station is live inside its validity window (with the records' clock tolerance) and stale outside it; one for another realm or station is none; the realm's tombstone over the type is tombstoned; nothing at all is none; anything else — a record or tombstone another key signed, a record of another type, or a failed lookup — is unreadable. So live is the only verdict that admits a dial under closed.
What a verdict means under a mode: live admits under every mode; anything else is a would-be refusal under open/log and a refusal under closed.
The mode the client checks in, from fleet config. Unset reads as open (S1/S2 ship open); a value that is none of the three also reads as open, reported as an error — returning to open needs no release, so the configured value must be one of the three deliberately.
Types
-type mode() :: open | log | closed.
-type verdict() :: live | tombstoned | stale | none | unanchored | unreadable.
What one slot read is judged against: the dialed pair, the realm key the pool pinned for the realm (the realm's signing key, the one that signs its station authorizations and their tombstones), and the verifier's clock.
Functions
-spec authorized(#{pool := macula:pool(), find_record := fun((macula:pool(), binary(), pos_integer()) -> {ok, macula_record:m_record()} | {error, term()}), realm_key := {ok, binary()} | none}, <<_:256>>, <<_:256>>, pos_integer()) -> ok | {error, {station_not_authorized, verdict()}}.
The check: read Station's authorization slot for Realm — through Dial's find_record, within TimeoutMs — judge it against the realm key the pool pinned for Realm, and settle it under the configured mode. ok admits the dial; {error, {station_not_authorized, Verdict}} refuses it (mode closed only). A pool that pinned no key for Realm has nothing to judge a record by: its verdict is unanchored and the slot is not read. Every check is counted on the pool's station_checks.
-spec classify({ok, macula_record:m_record()} | {error, term()}, trust()) -> verdict().
What one slot read means, judged against Trust. A record counts only when the pinned realm key signed it: the read verified a signature and the signer's purpose, and any process can mint a key of purpose realm, so the signer itself must be the realm's. Then an authorization for exactly the dialed realm and station is live inside its validity window (with the records' clock tolerance) and stale outside it; one for another realm or station is none; the realm's tombstone over the type is tombstoned; nothing at all is none; anything else — a record or tombstone another key signed, a record of another type, or a failed lookup — is unreadable. So live is the only verdict that admits a dial under closed.
What a verdict means under a mode: live admits under every mode; anything else is a would-be refusal under open/log and a refusal under closed.
-spec mode() -> mode().
The mode the client checks in, from fleet config. Unset reads as open (S1/S2 ship open); a value that is none of the three also reads as open, reported as an error — returning to open needs no release, so the configured value must be one of the three deliberately.