pub struct KeyStore { /* private fields */ }Expand description
The key store: one SQLite connection, serialised behind a mutex.
Verification is one indexed lookup per request — trivial next to the whole-graph load every query already performs — and reading the store on every request is what makes runtime issuance, rotation, and revocation visible without a restart or an invalidation protocol. The database runs in WAL mode with a busy timeout so the admin subcommand can write while the server reads.
Implementations§
Source§impl KeyStore
impl KeyStore
Sourcepub fn open(path: &Path) -> Result<Self, ApiError>
pub fn open(path: &Path) -> Result<Self, ApiError>
Opens (creating if needed) the key store database at path.
Sourcepub fn parse(contents: &str) -> Self
pub fn parse(contents: &str) -> Self
Builds a store from legacy flat-file contents.
Reads key_id:secret lines, ignoring blank lines and # comments.
A line is split on the first : so a secret may itself contain
colons. Lines without a colon are skipped. Imported keys are
active and carry plan SELF_HOSTED_PLAN. Building an in-memory
SQLite database cannot fail in any way a caller could act on, so
this keeps the infallible signature the original parser had.
Sourcepub fn import_legacy_file(&self, path: &Path) -> Result<usize, ApiError>
pub fn import_legacy_file(&self, path: &Path) -> Result<usize, ApiError>
Imports a legacy flat keys file into this store.
Keys already present (by key_id) are left untouched — an import
must never resurrect a revoked key or overwrite a rotated secret.
Returns how many keys were newly imported.
The import refuses the whole file, before importing anything,
when any entry carries DOCUMENTED_EXAMPLE_SECRET — the
example credential the README quickstart used to print. That
value is published, so importing it would provision a key whose
secret every reader of the old README knows (gate F-3). Failing
the whole import, rather than skipping the one entry, keeps the
refusal loud: a half-imported file that boots with fewer keys
than the operator wrote is a quieter failure than not booting.
Sourcepub fn issue(&self, key_id: &str, plan: &str) -> Result<String, ApiError>
pub fn issue(&self, key_id: &str, plan: &str) -> Result<String, ApiError>
Issues a new key and returns its secret — the only time the secret
exists outside the caller’s hands, so the caller must record it
now. Fails if key_id is already taken or is unusable in a bearer
token (empty, or containing : or whitespace).
Sourcepub fn rotate(&self, key_id: &str) -> Result<String, ApiError>
pub fn rotate(&self, key_id: &str) -> Result<String, ApiError>
Replaces a key’s secret and returns the new one. The old secret stops verifying with this call. The key’s plan, status, and creation time are unchanged. A revoked key cannot be rotated back to life — issue a new key instead.
Sourcepub fn revoke(&self, key_id: &str) -> Result<(), ApiError>
pub fn revoke(&self, key_id: &str) -> Result<(), ApiError>
Revokes a key: it stops verifying immediately. Idempotent for an
already-revoked key; an unknown key_id is an error, so a typo in
an admin command cannot look like a successful revocation.
Sourcepub fn list(&self) -> Result<Vec<KeySummary>, ApiError>
pub fn list(&self) -> Result<Vec<KeySummary>, ApiError>
Every key’s summary, ordered by key_id.
Sourcepub fn active_len(&self) -> usize
pub fn active_len(&self) -> usize
Number of keys that can authenticate right now.
Sourcepub fn verify(
&self,
key_id: &str,
secret: &str,
) -> Result<VerifiedKey, ApiError>
pub fn verify( &self, key_id: &str, secret: &str, ) -> Result<VerifiedKey, ApiError>
Checks a presented token and returns the key’s identity and plan.
An unknown key_id, a wrong secret, and a revoked key are all the
same 401, and the work done in each case is roughly equal (an
unknown key still burns a hash and a comparison), so the response
does not reveal which keys exist or why one failed.
Trait Implementations§
Auto Trait Implementations§
impl !Freeze for KeyStore
impl RefUnwindSafe for KeyStore
impl Send for KeyStore
impl Sync for KeyStore
impl Unpin for KeyStore
impl UnsafeUnpin for KeyStore
impl UnwindSafe for KeyStore
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
impl<ST, DT> CastableFrom<ST, Initialized, Initialized> for DT
impl<ST, DT> CastableFrom<ST, Uninit, Uninit> for DT
impl<A, B, T> HttpServerConnExec<A, B> for Twhere
B: Body,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
Source§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