pub struct AuthState {Show 27 fields
pub estop: Arc<Estop>,
pub operator: Option<Arc<OperatorAuth>>,
pub relay: Option<RelayTarget>,
pub operator_login_limiter: Arc<RateLimiter>,
pub disclosure: Disclosure,
pub oauth: OAuthState,
pub provision_rate_limiter: Arc<RateLimiter>,
pub unauthenticated_creates: bool,
pub max_accounts: u64,
pub loopback_callers_only: bool,
pub strict_transport_security: Option<StrictTransportSecurity>,
pub subscriber_limit: Arc<SubscriberLimit>,
pub park_rate_limiter: Arc<RateLimiter>,
pub sync_rate_limiter: Arc<RateLimiter>,
pub write_meter: Arc<WriteMeter>,
pub proxy: Arc<ProxyLimits>,
pub never_wrote_min_idle: Duration,
pub tree: Arc<TreeState>,
pub trust_forwarded_headers: bool,
pub lifecycle: Arc<ServerLifecycle>,
pub nudge: Arc<PollNudge>,
pub operator_records: Arc<OperatorRecords>,
pub operator_handle: Arc<OperatorHandle>,
pub handles: Arc<dyn HandleDid>,
pub handle_lookup_limiter: Arc<RateLimiter>,
pub did_lookup_limiter: Arc<RateLimiter>,
pub declared_lookups: Arc<DeclaredLookups>,
}Expand description
Session storage, the e-stop latch and the operator credential, bundled so
a caller building app_with_auth hands them over together.
Separate from Registry on purpose: neither a session nor an e-stop
engagement is provisioning, and bundling them into the same object-safe
trait every backend must implement would grow that trait for every
deployment whether or not it uses a local stop. The
default is what every other builder here gets: fresh, empty, in-memory
state and no operator credential configured, so app keeps behaving
exactly as before this existed.
Fields§
§estop: Arc<Estop>The local emergency stop.
operator: Option<Arc<OperatorAuth>>Signing in as this deployment’s operator, when it has one. None
when no --operator was given: there is no DID a sign-in could match,
so the operator routes answer that they are not configured rather
than offering a sign-in that can only fail. See
crate::operator::OperatorAuth.
relay: Option<RelayTarget>The relay an operator may announce this server to. None when no
relay was named, and under a .localhost zone regardless; see
crate::relay.
operator_login_limiter: Arc<RateLimiter>Bounds GET /dashboard/login per caller address.
That route takes no credential — signing in is how a caller gets one
— and answering it costs an identity resolution and a pushed
authorization request against a host the caller named. That is the
same shape as POST /oauth/par, which is already bounded this way,
and rather more outbound work.
disclosure: DisclosureWhich Credential::Disclosure routes this deployment has closed.
Defaults to every route open; see auth::Disclosure.
oauth: OAuthStatePAR, authorize, token and discovery; see crate::oauth::OAuthState.
Defaults to in-memory stores and every policy hook refusing — see
that type’s own doc.
provision_rate_limiter: Arc<RateLimiter>Bounds bot.did.createAccount and bot.did.createSession calls per
caller address, the two together; see this module’s
PROVISION_RATE_LIMIT and crate::rate_limit’s own doc for where
that address comes from and AuthState::trust_forwarded_headers for
when a caller-supplied header may stand in for it.
authorize is keyed this way already;
createAccount mints an account — a signing key, a hostname, a blob
quota, a permanent ledger and firehose entry — and the claim
Credential::Attested checks is verified only after this budget, so
it needs the same address-keyed budget at least as much as either.
Both routes read a proof, which can fetch an issuer’s keys or a DID
document before any signature is checked.
unauthenticated_creates: boolWhether bot.did.createAccount with no credential creates beneath
the deployment’s own account; see tree::prove.
false unless a deployment turns it on: a public deployment creates
only for a creator that proved itself. didbot-pds turns it on
under .localhost, where nothing holds a credential yet, and
nowhere else.
max_accounts: u64How many accounts this deployment may hold before
bot.did.createAccount refuses to mint another; see
this module’s DEFAULT_MAX_ACCOUNTS and create_account.
Checked against didbot_pds::RegistryStats::accounts — the same
count crate::health’s periodic line already reports — rather than a
second counter kept here, so a cap and a dashboard can never disagree
about what “how many accounts” means.
loopback_callers_only: boolWhether this deployment answers only callers on this host.
A .localhost zone is a development run: createAccount mints with
no attestation claim there, and without a --data directory every
blob is held in memory — so a run reachable from the network hands
both to anybody sharing it. The listener binds every address because
that is the only single bind answering both 127.0.0.1 and ::1
(see didbot-pds’s own comment), so the restriction is here: a
request whose peer address is not a loopback address is refused
before it reaches a route.
false unless a deployment turns it on, which is the posture a real
zone wants: a deployment nobody can reach serves no agents.
strict_transport_security: Option<StrictTransportSecurity>The Strict-Transport-Security header every response carries, if
any; see StrictTransportSecurity.
None unless a deployment turns it on. didbot-pds turns it on only
when it serves a production ACME certificate.
subscriber_limit: Arc<SubscriberLimit>Bounds how many never-ending streams — com.atproto.sync.subscribeRepos
— this server holds open at once,
in total and per caller address; see
crate::subscribers::SubscriberLimit.
crate::MAX_CONCURRENT_REQUESTS does not cover these: its permit
is released when the response head is sent, which for a stream is
before the stream has carried a single frame.
park_rate_limiter: Arc<RateLimiter>Bounds bot.did.parkKey and describeParkedKey per caller address;
see tree::PARK_RATE_LIMIT.
sync_rate_limiter: Arc<RateLimiter>Bounds the com.atproto.sync.* reads per caller address; see
routes::SYNC_READ_LIMIT. Those reads are unauthenticated and each
can rebuild and sign a repository.
write_meter: Arc<WriteMeter>Bounds each account’s record writes and blob uploads, by operation
and by request byte; see crate::write_meter.
proxy: Arc<ProxyLimits>Bounds each account’s atproto-proxy calls, and caches where their
targets live; see crate::ProxyLimits.
never_wrote_min_idle: DurationThe shortest idleFor a neverWrote account delete takes; see
crate::NEVER_WROTE_MIN_IDLE.
tree: Arc<TreeState>Parked keys, spent proofs and issuers’ keys; see crate::tree.
trust_forwarded_headers: boolWhether X-Forwarded-For/X-Real-IP may be trusted as the caller’s
address for every per-address budget this router keeps —
AuthState::provision_rate_limiter,
crate::oauth::OAuthState::par_rate_limiter and
crate::oauth::OAuthState::authorize_rate_limiter — instead of the
TCP peer address crate::rate_limit::caller_key gets by default.
false unless a deployment turns it on — see crate::rate_limit’s
own doc for why trusting a caller-supplied header by default would
make every per-address budget bypassable rather than merely
degraded. Turn this on only once a real reverse proxy sits in front
of this server and sets whichever header it reads.
lifecycle: Arc<ServerLifecycle>Where this deployment is in its own lifecycle; see
didbot_pds::ServerLifecycle and this module’s own
require_lifecycle, which is the single point every capability
question goes through.
Defaults to ServerLifecycle::claimed — a server that exists and
works — because that is what every builder in this crate other than
didbot-pds’s own path is: a test, or a .localhost run. A real
deployment hands in one built by
ServerLifecycle::booting and
driven by a store read and an operator poll.
nudge: Arc<PollNudge>Where bot.did.pollOperatorClaim delivers its “look now” request;
see crate::PollNudge and this module’s own poll_operator_claim.
Defaults to a channel with no poll task attached, which absorbs nudges and does nothing — the correct behaviour for a build with no operator repository to read.
operator_records: Arc<OperatorRecords>What the operator poll’s last listing of the operator’s repository
read, for the dashboard’s provenance panel. Shared with the poll,
which is the only thing that writes to it; see
crate::OperatorRecords.
operator_handle: Arc<OperatorHandle>The operator’s handle as the operator poll last verified it, for the
homepage. Shared with the poll, which is the only thing that writes
to it; see crate::OperatorHandle.
handles: Arc<dyn HandleDid>Where com.atproto.identity.resolveHandle looks up a handle no
account here holds; see crate::handles. Defaults to the network,
through Cloudflare’s resolver.
handle_lookup_limiter: Arc<RateLimiter>Bounds those lookups per caller address; see
routes::HANDLE_LOOKUP_LIMIT.
did_lookup_limiter: Arc<RateLimiter>Bounds com.atproto.identity.resolveDid’s lookups of DIDs hosted
elsewhere per caller address; see routes::DID_LOOKUP_LIMIT.
declared_lookups: Arc<DeclaredLookups>The lookups this deployment’s policies declare, shared with the
policy poll, which is the only thing that writes to it; see
crate::DeclaredLookups.
Trait Implementations§
Auto Trait Implementations§
impl Freeze for AuthState
impl !RefUnwindSafe for AuthState
impl Send for AuthState
impl Sync for AuthState
impl Unpin for AuthState
impl UnsafeUnpin for AuthState
impl !UnwindSafe for AuthState
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
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 moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
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