Skip to main content

ApiKeys

Struct ApiKeys 

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

A store of API keys over the Database port; the owning app ships create_table_sql as a migration. Timestamps are RFC 3339 TEXT from the Clock port, the house shape (cratefield_core::SendCooldown documents why lexicographic order on that format is chronological order).

Implementations§

Source§

impl ApiKeys

Source

pub fn new( db: Arc<dyn Database>, clock: Arc<dyn Clock>, rng: Arc<dyn RandomBytes>, table: impl Into<String>, ) -> Self

A key store over db, timed by clock, keyed by rng.

Source

pub fn create_table_sql(&self) -> String

The portable DDL for the key table (SQLite/D1/Postgres, ADR 0004), shipped as a forward-only migration. Only the hash and the public prefix are ever stored.

Source

pub async fn issue( &self, namespace: &str, subject: &str, scopes: &[&str], mode: ApiKeyMode, ) -> Result<IssuedKey, ApiKeyError>

Mints a key for subject with scopes, and stores its hash; the returned IssuedKey::token is shown exactly once.

§Errors

ApiKeyError::Namespace or ApiKeyError::Scope on a caller mistake, ApiKeyError::Random or ApiKeyError::Db — in every failure case no key was issued.

Source

pub async fn verify( &self, token: &str, ) -> Result<Option<ApiKeyPrincipal>, DbError>

Verifies one presented token: parse, look the prefix up, re-derive the hash, compare in constant time; on success touch last_used_at (once per window, best effort — logged, never a failed request).

Ok(None) is every auth failure there is — malformed, unknown, revoked, wrong secret — deliberately indistinguishable, so probing a gate built on this learns nothing. A database failure is Err, and nothing about it says “unauthorized”.

§Errors

DbError when the lookup fails.

Source

pub async fn revoke(&self, prefix: &str) -> Result<(), ApiKeyError>

Marks a key revoked: every later verify answers Ok(None). The row stays, so a later rotate of the same prefix is refused and an audit can still see the key existed. Idempotent.

§Errors

ApiKeyError::UnknownKey when the prefix names no key, ApiKeyError::Db when the write fails.

Source

pub async fn rotate(&self, prefix: &str) -> Result<IssuedKey, ApiKeyError>

Rotates a key: mints a fresh token for the same namespace, mode, subject and scopes and revokes the old one, both statements in one Database::batch_atomic batch (issue #126) — the old key never keeps working while the new one does not exist yet, nor the reverse. The copy is an INSERT ... SELECT keyed to the old row still being active, so a rotate racing a revoke — or a second rotate — mints nothing instead of a second live key.

§Errors

ApiKeyError::UnknownKey when the prefix names no active key (a revoked one included — rotate the replacement instead), ApiKeyError::Random or ApiKeyError::Db as Self::issue.

Trait Implementations§

Source§

impl Clone for ApiKeys

Source§

fn clone(&self) -> Self

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

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

Performs copy-assignment from source. 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
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.

Source§

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

Source§

fn from_ref(input: &T) -> T

Converts to this type from a reference to the input type.
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> 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 = !

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