macula_direct_dial (macula v9.5.0)
View SourceDirect-dial resolve-and-call: shared internals for macula_request/macula_response (and, when they grow a direct-dial mode, macula_streamer/macula_stream_sink).
Not a public API on its own — macula_request:start_link_direct/6,7,8 and macula_response:advertise_direct/6,7 are the entry points. Factored out because both the RPC and streaming supervised pairs need the identical resolve sequence (find_records -> verify -> read_procedure_advertisement -> find_record -> read_station_endpoint -> build a quic:// dial URL), and the identical provider-side publish (sign + put_record a procedure_advertisement).
The resolve side retries: a record just published on the provider's station has not necessarily replicated to the caller's station yet, and treating the first miss as failure would make every direct-dial call racy against DHT propagation lag. macula_station_cert_chain_SUITE (macula-station) proved this exact resolve+dial sequence works cross-station against the live fleet; this module is that sequence, lifted out of the test and made reusable.
Trust model
Two independent checks, both mandatory, cover what the QUIC/TLS layer cannot: (1) every candidate procedure_advertisement must carry a valid Ed25519 signature before its serving_station is trusted at all — otherwise any identity able to sign SOME record could name a real, legitimate station as the server for a procedure it has no authority over, and the station_endpoint check below would still pass (it only proves we reached the station we were told to reach, not that whoever told us so was authorized to); (2) the resolved station_endpoint must be signed by the station itself (verify_and_build/2, unchanged). The actual QUIC dial trusts NEITHER the TLS certificate (pin_tls_cert => false — a production station's TLS is terminated by an unrelated PKI, e.g. Let's Encrypt, so pinning the cert key can never succeed) NOR nothing (verify => none alone would trust whoever answers): trust is enforced at the application layer instead, via the cryptographically signed CONNECT/HELLO handshake (macula_peering_conn:bind_peer_identity/2) checked against the exact pubkey the signed DHT chain above resolved.
A third check is available but OPT-IN, via Opts (managed realms only — see macula_record:verify_advertisement_cert_chain/3): verify_cert_chain => {RealmCaPem, Org} additionally requires the advertisement's embedded X.509 service-cert chain to verify to RealmCaPem under Org (Slice 7c Direction B), proving the ADVERTISER — not just the station it names — is an org/realm- authorized identity. Without it, (1) above still rejects an unsigned or badly-signed advertisement, but not one signed by an unauthorized (if self-consistent) identity; unmanaged realms have no realm CA to check against, so this stays opt-in rather than mandatory.
Summary
Functions
As call/6 with no cert-chain verification.
Resolve Procedure's provider and call it there directly. Same return shape as macula:call/5; resolve failures surface as {error, {unresolved, Reason}} so a caller can tell "nobody has advertised this via direct-dial yet" apart from a real call failure. Opts may include verify_cert_chain => {RealmCaPem, Org} — see the module doc's "Trust model" section.
As publish_advertisement/5 with no cert chain embedded.
Publish a signed procedure_advertisement for Procedure, naming Pool's currently-connected station as the serving station. Identity signs it — the pool itself has no identity to sign with, so the caller supplies one (reuse the same one across re-advertises; a fresh identity per call is valid but needless DHT churn). Opts may include cert_chain => ChainPem (leaf ++ org CA, PEM) so a verifying consumer's verify_cert_chain opt (see call/6) can check this advertiser's org/realm authorization — Slice 7c Direction B, managed realms only.
Functions
-spec call(macula:pool(), macula:realm(), macula:procedure(), term(), pos_integer()) -> {ok, term()} | {error, term()}.
As call/6 with no cert-chain verification.
-spec call(macula:pool(), macula:realm(), macula:procedure(), term(), pos_integer(), map()) -> {ok, term()} | {error, term()}.
Resolve Procedure's provider and call it there directly. Same return shape as macula:call/5; resolve failures surface as {error, {unresolved, Reason}} so a caller can tell "nobody has advertised this via direct-dial yet" apart from a real call failure. Opts may include verify_cert_chain => {RealmCaPem, Org} — see the module doc's "Trust model" section.
-spec publish_advertisement(macula:pool(), macula:realm(), macula:procedure(), macula_identity:key_pair()) -> ok | {error, term()}.
As publish_advertisement/5 with no cert chain embedded.
-spec publish_advertisement(macula:pool(), macula:realm(), macula:procedure(), macula_identity:key_pair(), map()) -> ok | {error, term()}.
Publish a signed procedure_advertisement for Procedure, naming Pool's currently-connected station as the serving station. Identity signs it — the pool itself has no identity to sign with, so the caller supplies one (reuse the same one across re-advertises; a fresh identity per call is valid but needless DHT churn). Opts may include cert_chain => ChainPem (leaf ++ org CA, PEM) so a verifying consumer's verify_cert_chain opt (see call/6) can check this advertiser's org/realm authorization — Slice 7c Direction B, managed realms only.