Skip to main content

PairingGuard

Struct PairingGuard 

pub struct PairingGuard { /* private fields */ }

Implementations§

Source§

impl PairingGuard

Source

pub fn new( require_pairing: bool, existing_tokens: &[String], code_policy: PairingCodePolicy, ) -> Self

Build a guard, minting the startup code under code_policy.

The policy is not retained. PairingGuard outlives any number of config writes, and root AGENTS.md forbids snapshotting live policy into a long-lived handle — a code minted after an operator strengthens [gateway.pairing_code] must use the new policy without a restart. Every later mint therefore takes the policy the caller resolved from live config at that moment.

Source

pub fn rotate_admin_token(&self, data_dir: &Path) -> Result<String>

Start a new admin-token generation: forget the current token, mint a fresh one, write it owner-only into data_dir, and accept it only once the file is in place. On any failure the guard accepts no admin token at all, and whatever file an earlier run left behind never matches, so the pairing-code admin routes fail closed.

Source

pub fn admin_token_matches(&self, presented: &str) -> bool

True only when presented equals this run’s admin token, compared in constant time. With no successful rotation, nothing matches.

Source

pub fn pairing_code(&self) -> Option<String>

The one-time pairing code (generated only on first startup when no tokens exist).

Source

pub fn require_pairing(&self) -> bool

Whether pairing is required at all.

Source

pub async fn reserve_pair_unkeyed( &self, code: &str, ) -> Option<PairingReservation>

Code check WITHOUT per-client lockout accounting, for callers whose peers all share one network identity and which apply their own class-wide rate policy instead. The relay enrollment bridge is the canonical case: every relay-routed client reaches the daemon from loopback, so keying lockout on the peer address would let five wrong codes from ONE hostile client lock out EVERY relay-routed enrollee (shared-fate lockout). Never expose this to a caller that has a real per-client identity - use PairingGuard::reserve_pair there.

Source

pub async fn reserve_pair( &self, code: &str, client_id: &str, ) -> Result<Option<PairingReservation>, u64>

Source

pub async fn try_pair( &self, code: &str, client_id: &str, ) -> Result<Option<String>, u64>

Attempt to pair with the given code. Returns a bearer token on success. Returns Err(lockout_seconds) if locked out due to brute force. client_id identifies the client for per-client lockout accounting.

Source

pub fn is_authenticated(&self, token: &str) -> bool

Check if a bearer token is valid (compares against stored hashes).

Source

pub fn token_is_paired(&self, token: &str) -> bool

Strict membership check for inbound authentication: whether token hashes to a currently-paired token, regardless of require_pairing. The gateway’s is_authenticated convenience fails OPEN when pairing is disabled, which is only correct on surfaces that already treat the transport as trusted — an auth provider must use this instead, so an empty token set denies everything.

Source

pub fn token_hash_is_paired(&self, token_hash: &str) -> bool

Strict membership check by pre-computed SHA-256 hash (see Self::token_is_paired). Lets an established connection re-check liveness of its pairing without retaining the bearer itself.

Source

pub fn hold_paired_tokens(&self) -> HeldPairedTokens<'_>

Hold the paired-token set still: no token can be paired or revoked until the returned guard is dropped, while other readers proceed.

For a caller that must keep a liveness decision true through the effect it guards. Keep the hold short, and do not call this guard’s other methods while holding it: a pairing or revocation queued behind the hold makes a second read on the same thread wait forever.

Source

pub fn is_paired(&self) -> bool

Returns true if the gateway is already paired (has at least one token).

Source

pub fn tokens(&self) -> Vec<String>

Get all paired token hashes (for persisting to config).

Source

pub fn revoke_token(&self, token: &str) -> bool

Source

pub fn revoke_token_hash(&self, token_hash: &str) -> bool

Revoke a paired token by its SHA-256 hash. Returns true if removed.

Source

pub fn revoke_all_tokens(&self) -> usize

Source

pub fn generate_new_pairing_code( &self, code_policy: PairingCodePolicy, ) -> Option<String>

Generate a new pairing code that pairs an additional client. Does not revoke existing tokens. To rotate a compromised token, pair with revoke_token/revoke_token_hash + a config persist pass.

code_policy is passed per call, resolved by the caller from live config at this moment — the guard holds no policy of its own, so an operator who strengthens [gateway.pairing_code] sees the next code follow the new policy without a restart.

Source

pub fn generate_pairing_code_if_vacant( &self, code_policy: PairingCodePolicy, ) -> Result<String, GeneratePairingCodeError>

Issue a code only if no code is currently pending.

code_policy is resolved per call for the same reason as Self::generate_new_pairing_code.

Source

pub fn token_hash(token: &str) -> String

Get the token hash for a given plaintext token (for device registry lookup).

Source

pub fn authenticate_and_hash(&self, token: &str) -> Option<String>

Check if a token is paired and return its hash.

Trait Implementations§

Source§

impl Clone for PairingGuard

Source§

fn clone(&self) -> PairingGuard

Returns a duplicate of the value. Read more
1.0.0 (const: unstable) · §

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for PairingGuard

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
§

impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
where ST: ?Sized, DT: ?Sized,

§

impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
where ST: ?Sized, DT: ?Sized,

Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> DynClone for T
where T: Clone,

Source§

fn __clone_box(&self, _: Private) -> *mut ()

Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self> ⓘ

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self> ⓘ

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> IntoEither for T

Source§

fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ

Converts self into a Left variant of Either<Self, Self> if into_left is true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
Source§

fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
where F: FnOnce(&Self) -> bool,

Converts self into a Left variant of Either<Self, Self> if into_left(&self) returns true. Converts self into a Right variant of Either<Self, Self> otherwise. Read more
§

impl<T> PolicyExt for T
where T: ?Sized,

§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] only if self and other return Action::Follow. Read more
§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Sized + Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns [Action::Follow] if either self or other returns Action::Follow. Read more
§

impl<T> Read<Exclusive, BecauseExclusive> for T
where T: ?Sized,

Source§

impl<T> Same for T

Source§

type Output = T

Should always be Self
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<V, T> VZip<V> for T
where V: MultiLane<T>,

§

fn vzip(self) -> V

§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self> ⓘ
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self> ⓘ

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more