Skip to main content

DeviceAuth

Struct DeviceAuth 

Source
pub struct DeviceAuth { /* private fields */ }
Expand description

The device authorization grant (RFC 8628) over the harness’s own ports.

Implementations§

Source§

impl DeviceAuth

Source

pub fn builder() -> DeviceAuthBuilder

A builder with no clients, no hooks and the RFC 8628 defaults. It is not a working composition until .client(..), .issuer(..) and .random(..) are set; Module::self_check names what is missing.

Source

pub fn new() -> Self

Trait Implementations§

Source§

impl Default for DeviceAuth

Source§

fn default() -> Self

Returns the “default value” for a type. Read more
Source§

impl Module for DeviceAuth

Source§

fn requires(&self) -> &'static [Port]

The codes live in the database, and the polling route is public: the limiter is the abuse control it actually has. Both are requirements rather than options — a deployment without a limiter mounted would serve an unthrottled public poll endpoint, which is what production readiness exists to refuse (issue #562).

Source§

fn optional(&self) -> &'static [Port]

The Clock decides “now” for expiry and the poll interval. The Auth port is what the stock CallerApprover identifies callers with; a deployment that builds its own approver does not need it, so it is optional rather than required.

Source§

fn personal_data(&self) -> &'static [PersonalDataSet]

One row per request, and the row is the approver’s: it names who approved the device (approver_subject) and carries the label the client put on it (name, which is whatever the client chose to call the device — “Alice’s laptop”).

The codes themselves are stored only as hashes and are not the subject: a device_code is a bearer credential with no person behind it, and a user_code is eight letters off a screen. The subject is the person who pressed Approve, and an erasure request that names them deletes the row.

Source§

fn validate_config(&self, _cfg: &dyn Config) -> Result<(), ConfigError>

No configuration keys of its own: the composition is what a venture decides, and self_check reports a composition that cannot serve a device sign-in.

Source§

fn self_check(&self) -> Vec<String>

The composition a build must refuse. A device grant with no clients can authorize nobody; one with no issuer mints nothing; one with no entropy source cannot draw a code. Reported here rather than in validate_config because none of it comes from the environment — it is what the venture composed, and the fix is in the composition.

Source§

fn surface(&self) -> Surface

The two machine routes, the browser page and the two decision forms.

All four writes are RoutePolicy::Open, and deliberately so. /code and /token are called by a program, so a CAPTCHA is meaningless and a signed link would demand a Signer key ring this module never issues from — their proof is the single-use device_code the module itself minted, and their abuse control is the RateLimiter the module requires (plus the poll interval /token enforces). /approve and /deny are the browser’s, and the handler authenticates them itself: they need a signed-in approver, which is Audience::Subject here, and the same-origin check runs before the body is trusted.

Source§

fn scheduled<'a>( &'a self, ctx: &'a ModuleContext, cron: &'a str, ) -> BoxFuture<'a, Result<(), AnyError>>

The scheduled purge: rows past their expiry are deleted, because an expired code is useless to both sides — the client is told expired_token and the approver is told the code is gone. One statement, so it spends one unit of the invocation’s budget (ADR 0023) and leaves the rest to the modules behind it.

Source§

fn name(&self) -> &'static str

Kebab-case name; mounted at /v1/<name>.
Source§

fn version(&self) -> &'static str

env!("CARGO_PKG_VERSION"), surfaced by /__health.
Source§

fn tables(&self) -> &'static [&'static str]

Table names this module owns; duplicates across modules are a build error.
Source§

fn migrations(&self) -> Migrations

The module’s migrations, embedded per dialect.
Source§

fn router(&self, ctx: ModuleContext) -> Router

The module’s router, nested under /v1/<name>.
Source§

fn harness_api(&self) -> u32

Contract version, checked by Harness::build.
Source§

fn depends_on(&self) -> &'static [&'static str]

Modules this one’s schema sits on top of, by name. Read more
Source§

fn actor_kinds(&self) -> &'static [&'static str]

Actor kinds this module owns, each [a-z0-9_-]; duplicates across modules are a build error, and so is a kind with no handler registered through HarnessBuilder::actor. Read more
Source§

fn emits(&self) -> &'static [&'static str]

Event names this module emits ("<module>.<event>"), listed by /__health.
Source§

fn public_writes(&self) -> bool

Whether the module has public write endpoints. Read more
Source§

fn public_write_policy(&self) -> RoutePolicy

What actually protects those public writes, for a module with no ADR 0010 surface to hang a per-action RoutePolicy on (issue #143). Read more
Source§

fn signature_verification(&self) -> SignatureVerification

Which verifier proves this module’s RoutePolicy::Signature deliveries (issue #533): how a webhook handler checks a machine signature before acting. Read more
Source§

fn max_body_bytes(&self, _cfg: &dyn Config) -> usize

The largest request body any route of this module accepts, so a runtime can refuse an oversize body before buffering it (issue #440). Read more
Source§

fn streaming_routes(&self) -> &'static [StreamRoute]

Routes this module serves in streaming mode (issue #585), each with its own StreamRoute::max_bytes ceiling. Opt-in: the default is empty, and every existing route keeps the buffered behaviour it always had. Read more
Source§

fn max_blob_object_bytes(&self) -> u64

The largest object this module’s streamed and multipart blob writes may produce (issue #586), enforced by the ScopedBlob the harness hands the module on put_stream, upload_part and complete_multipart. Read more
Source§

fn well_known(&self) -> Option<Router>

Routes this module serves at the root under /.well-known, for spec-mandated discovery documents (OIDC openid-configuration, jwks.json) that must live outside /v1 (issue #46). Paths are relative to the prefix: register /jwks.json, not /.well-known/jwks.json. Read more
Source§

fn events( &self, ) -> Vec<(String, Arc<dyn Fn(&Scope, Value) -> Pin<Box<dyn Future<Output = Result<(), Box<dyn Error + Sync + Send>>> + Send>> + Sync + Send>)>

Handlers for events other modules emit; registered at Harness::build.

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
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

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

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

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> Same for T

Source§

type Output = T

Should always be Self
Source§

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

Source§

type Error = !

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

fn try_from(value: U) -> Result<T, !>

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.
Source§

impl<T> WithSubscriber for T

Source§

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
Source§

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

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