pub struct WriteGuards {
pub captcha_modules: Vec<String>,
pub signature_modules: Vec<String>,
pub payments_signature_modules: Vec<String>,
pub hmac_signature_modules: Vec<(String, &'static str)>,
pub signed_link_modules: Vec<String>,
pub has_public_writes: bool,
pub has_admin_routes: bool,
pub rate_limiter_modules: Vec<(String, Vec<String>)>,
pub signature_routes: Vec<(String, String, SignatureVerification)>,
}Expand description
What the composed modules demand of the runtime, module by module.
Fields§
§captcha_modules: Vec<String>Modules with a RoutePolicy::HumanForm-guarded write (or the
conservative fallback: public_writes and no declared policy at all).
signature_modules: Vec<String>Modules with a RoutePolicy::Signature-guarded write (webhooks),
however they verify them.
payments_signature_modules: Vec<String>The signature modules that prove their deliveries through
Payments::verify_webhook — the default SignatureVerification.
hmac_signature_modules: Vec<(String, &'static str)>The signature modules proving their deliveries with a
webhook_signature scheme (issue #533), paired with the
ModuleConfig suffix of the key
holding each secret; Self::hmac_signature_secrets composes the
full keys.
signed_link_modules: Vec<String>Modules whose public writes are proved by an artifact this service
issued (RoutePolicy::SignedLink, issue #143).
has_public_writes: boolWhether the composition exposes any public write at all
(issue #437): a declared guarded action of any kind — a captcha
form, a webhook, a signed link — or the module-level
public_writes flag for modules that predate surfaces. Broader
than the three lists above by design: a webhook is an
unauthenticated endpoint too, and the rate-limiter leg of
production_readiness cares that something is writable, not
by which proof. A RoutePolicy::ApiKey write demands no
RateLimiter here: per-key limiting happens only where a handler
calls check_rate_limit with
ApiKeyPrincipal::rate_limit_key and a limiter is wired.
has_admin_routes: boolWhether any declared action is the admin plane (issue #437):
an Audience::Admin action, or any path under /admin. An
admin route’s bearer token is guessed rather than submitted, so
it needs a budget even when the venture has no public writes —
which is why this is its own answer and not a byproduct of
Self::has_public_writes.
rate_limiter_modules: Vec<(String, Vec<String>)>Modules that declare Port::RateLimiter — in requires() or
optional() — and expose public routes, each paired with those
routes named METHOD /v1/<module><path> (issue #562). A module
saying it throttles is a claim about the routes it publishes, so
the readiness gate reads both halves: the declaration from the
module, the routes from its surface. Public here is
Surface::public’s renderer
answer minus Audience::Subject — reachable without an
authenticated principal, the admin plane excluded
(has_admin_routes already speaks for it), webhooks and API-key
routes excluded (has_public_writes already speaks for the
webhook, and an API-key route’s budget is the per-key hook).
Empty for sidecar surfaces (Self::from_surface): a merged
document carries no requires()/optional() to read, and its
public writes and admin routes stay under the two legs above.
signature_routes: Vec<(String, String, SignatureVerification)>Every declared RoutePolicy::Signature route, named the way the
readiness error names it (METHOD /v1/<module><path>), with the
verifier it resolved to (issue #595) — the action’s own
verification when it
names one, else the module’s
signature_verification. The
production gate and fz doctor read this to name the exact route a
missing Payments port or HMAC secret blocks, instead of blaming
the whole module. A module that reached the signature gate through
the surface-less fallback declares no route and contributes none.
Implementations§
Source§impl WriteGuards
impl WriteGuards
Sourcepub fn collect(modules: &[Arc<dyn Module>]) -> Self
pub fn collect(modules: &[Arc<dyn Module>]) -> Self
Reads each module’s declared surface. A module whose surface has
no policy-guarded write but still sets public_writes counts as
needing a CAPTCHA — the undeclared-public-writer fallback keeps
out-of-tree and surface-less modules (the auth crates predate
ADR 0010 surfaces) under the same gate instead of silently
exempting them.
Sourcepub fn from_surface(module: &str, surface: &Surface) -> Self
pub fn from_surface(module: &str, surface: &Surface) -> Self
The guards a declared surface demands (issue #131). A sidecar’s
merged surface is not a Module this process can ask
public_writes or
signature_verification of, so
whatever the document declares is exactly what it needs, and a
signature route that names no verifier verifies through Payments,
the default (issues #533, #595). Same per-action reading as
Self::collect
through the one Action::demands_captcha predicate and the one
declares_admin_routes predicate — a sidecar’s admin plane needs
the limiter floor as much as an in-process module’s.
Sourcepub fn needs_signer(&self) -> bool
pub fn needs_signer(&self) -> bool
Whether any module proves a public write with an artifact this
service issued, and so needs a usable Signer (issue #143).
Sourcepub fn needs_captcha(&self) -> bool
pub fn needs_captcha(&self) -> bool
Whether any module needs the Captcha port.
Sourcepub fn needs_payments(&self) -> bool
pub fn needs_payments(&self) -> bool
Whether any module proves a public write with
Payments::verify_webhook. Since issue
#533 this is no longer “some module receives signed webhooks”: a
module may declare SignatureVerification::Hmac and verify with
the core webhook_signature scheme instead, and this answers
false for it — its production requirement is its secret key, not a
port (see webhook_secret_readiness). The STRIPE_WEBHOOK_SECRET
doctor rule is keyed on this, correctly.
Sourcepub fn hmac_signature_secrets(&self) -> Vec<(String, String)>
pub fn hmac_signature_secrets(&self) -> Vec<(String, String)>
The HMAC-verified signature modules and the full config key each
reads its secret from, composed through
ModuleConfig’s {MODULE}_{SUFFIX}
rule — the one place the prefix logic lives (issue #533).
Sourcepub fn hmac_signature_routes(&self) -> Vec<(String, String, Vec<String>)>
pub fn hmac_signature_routes(&self) -> Vec<(String, String, Vec<String>)>
The HMAC-verified signature modules, the full config key each
reads its secret from, and the METHOD /v1/<module><path> routes
that read it (issue #595) — the shape webhook_secret_readiness
and fz doctor name a missing secret by, so a module with a Stripe
route and a RevenueCat route says which one the unset key blocks.
Sourcepub fn signature_routes_for(
&self,
module: &str,
verifier: SignatureVerification,
) -> Vec<String>
pub fn signature_routes_for( &self, module: &str, verifier: SignatureVerification, ) -> Vec<String>
The routes module verifies with verifier, named
METHOD /v1/<module><path> (issue #595), so a readiness error can
point at the route instead of the whole module. Empty when the
module declared no surface route (the surface-less fallback).
Sourcepub fn signature_module_named(
&self,
module: &str,
verifier: SignatureVerification,
) -> String
pub fn signature_module_named( &self, module: &str, verifier: SignatureVerification, ) -> String
module (METHOD /v1/<module><path>, ...), or the bare module name
when it declared no route (the surface-less fallback) — the way the boot
gate and fz doctor name a signature module in a message
(issue #595).
Sourcepub fn needs_rate_limiter(&self) -> bool
pub fn needs_rate_limiter(&self) -> bool
Whether any route in the composition needs a limiter sitting in
front of it (issues #437, #562): a public write, an admin route,
or a module that declares Port::RateLimiter over public routes.
The admin plane is enough on its own — a bearer token is guessed,
not submitted, so a venture that publishes nothing still needs the
budget before its /admin/* routes — and a module declaring the
port is a claim to throttle that the gate holds the venture to
even when nothing it publishes is a write.
Trait Implementations§
Source§impl Clone for WriteGuards
impl Clone for WriteGuards
Source§impl Debug for WriteGuards
impl Debug for WriteGuards
Source§impl Default for WriteGuards
impl Default for WriteGuards
impl Eq for WriteGuards
Source§impl PartialEq for WriteGuards
impl PartialEq for WriteGuards
impl StructuralPartialEq for WriteGuards
Auto Trait Implementations§
impl Freeze for WriteGuards
impl RefUnwindSafe for WriteGuards
impl Send for WriteGuards
impl Sync for WriteGuards
impl Unpin for WriteGuards
impl UnsafeUnpin for WriteGuards
impl UnwindSafe for WriteGuards
Blanket Implementations§
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,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key and return true if they are equal.