Axum-based API server with auth, middleware, and standardized error handling
| Tier | platform |
| Role | infrastructure |
| Path | crates/platform/api |
| Edition | 2021 |
| Targets | media_server, platform_api |
| Public items | 182 across 21 modules |
| Tests | 65 |
What it is for
Axum-based API server with auth, middleware, and standardized error handling.
This crate provides:
- Error handling that converts to standardized
ApiErrorresponses - Request ID middleware for tracing
- Auth middleware with session support
- CORS configuration
- Common extractors and response helpers
Capabilities
ApiKeysBackend
API key management handlers.
| Item |
|---|
pub trait ApiKeysBackend |
fn api_keys_routes <K : ApiKeysBackend>(backend : K) -> Router |
InMemoryApiKeysBackend
API key management handlers.
| Item |
|---|
pub struct InMemoryApiKeysBackend |
InMemoryApiKeysBackend :: fn default() -> Self |
InMemoryApiKeysBackend :: fn new() -> Self |
InMemoryApiKeysBackend :: async fn list_api_keys(& self, user_id : & str,) -> Result <Vec <ApiKeySummary>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryApiKeysBackend :: async fn create_api_key(& self, user_id : & str, req : & CreateApiKeyRequest,) -> Result <ApiKeyCreated, Box <dyn std::error::Error + Send + Sync>> |
InMemoryApiKeysBackend :: async fn get_api_key(& self, id : & str,) -> Result <Option <ApiKeySummary>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryApiKeysBackend :: async fn revoke_api_key(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> |
AuditLogsBackend
Audit log API handlers.
| Item |
|---|
pub trait AuditLogsBackend |
fn audit_logs_routes <A : AuditLogsBackend>(backend : A) -> Router |
InMemoryAuditLogsBackend
Audit log API handlers.
| Item |
|---|
pub struct InMemoryAuditLogsBackend |
InMemoryAuditLogsBackend :: fn default() -> Self |
InMemoryAuditLogsBackend :: fn new() -> Self |
InMemoryAuditLogsBackend :: fn seed(& self, entry : AuditLogDetail) |
InMemoryAuditLogsBackend :: fn make_entry(entity_type : & str, entity_id : & str, action : & str, user_id : Option <& str>, user_email : Option <& str>,) -> AuditLogDetail |
InMemoryAuditLogsBackend :: fn seed_at(& self, entity_type : & str, entity_id : & str, action : & str, created_at : chrono::DateTime <chrono::Utc>,) |
InMemoryAuditLogsBackend :: async fn list_audit_logs(& self, query : & AuditLogQuery,) -> Result <ListResponse <AuditLogSummary>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryAuditLogsBackend :: async fn get_audit_log(& self, id : & str,) -> Result <Option <AuditLogDetail>, Box <dyn std::error::Error + Send + Sync>> |
AuthSession
Authentication middleware and session management.
| Item |
|---|
pub struct AuthSession |
AuthSession :: fn new(session : Session) -> Self |
AuthSession :: async fn get_user(& self) -> Option <AuthUser> |
AuthSession :: async fn set_user(& self, user : AuthUser) -> Result <(), tower_sessions::session::Error> |
AuthSession :: async fn clear_user(& self) -> Result <(), tower_sessions::session::Error> |
AuthSession :: async fn is_authenticated(& self) -> bool |
AuthUser
Authentication middleware and session management.
| Item |
|---|
pub struct AuthUser |
AuthUser :: fn new(id : Uuid, email : String, display_name : String, roles : Vec <String>) -> Self |
AuthUser :: fn has_role(& self, role : & str) -> bool |
AuthUser :: fn has_permission(& self, permission : & str) -> bool |
AuthUser :: fn is_admin(& self) -> bool |
AuthUser :: fn to_user_info(& self) -> UserInfo |
fn require_permission(user : & AuthUser, permission : & str) -> Result <(), Response> |
fn require_role(user : & AuthUser, role : & str) -> Result <(), Response> |
fn require_admin(user : & AuthUser) -> Result <(), Response> |
OptionalAuth
Authentication middleware and session management.
| Item |
|---|
pub struct OptionalAuth |
OptionalAuth :: async fn from_request_parts(parts : & mut Parts, _state : & S) -> Result <Self, Self::Rejection> |
RequireAuth
Authentication middleware and session management.
| Item |
|---|
pub struct RequireAuth |
RequireAuth :: async fn from_request_parts(parts : & mut Parts, _state : & S) -> Result <Self, Self::Rejection> |
auth::password (other)
_No module-level documentation is present in the source._
| Item |
|---|
fn hash(password : & str) -> Result <String, argon2::password_hash::Error> |
fn verify(password : & str, hash : & str) -> Result <bool, argon2::password_hash::Error> |
CmsBackend
CMS (Content Management System) API handlers.
| Item |
|---|
pub trait CmsBackend |
fn cms_routes <C : CmsBackend>(backend : C) -> Router |
InMemoryCmsBackend
CMS (Content Management System) API handlers.
| Item |
|---|
pub struct InMemoryCmsBackend |
InMemoryCmsBackend :: fn new() -> Self |
InMemoryCmsBackend :: async fn list_pages(& self, query : & PageListQuery,) -> Result <ListResponse <PageSummary>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryCmsBackend :: async fn get_page(& self, id : & str,) -> Result <Option <ContentPage>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryCmsBackend :: async fn create_page(& self, author_id : & str, req : & CreatePageRequest,) -> Result <ContentPage, Box <dyn std::error::Error + Send + Sync>> |
InMemoryCmsBackend :: async fn update_page(& self, id : & str, req : & UpdatePageRequest,) -> Result <Option <ContentPage>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryCmsBackend :: async fn delete_page(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> |
comments (other)
Comments API handlers for threads, comments, mentions, and reactions.
| Item |
|---|
pub const SINGLE_TENANT: Uuid |
CommentsBackend
Comments API handlers for threads, comments, mentions, and reactions.
| Item |
|---|
pub trait CommentsBackend |
fn comments_routes <C : CommentsBackend>(backend : C) -> Router |
ReactionPath
Comments API handlers for threads, comments, mentions, and reactions.
| Item |
|---|
pub struct ReactionPath |
ThreadsQuery
Comments API handlers for threads, comments, mentions, and reactions.
| Item |
|---|
pub struct ThreadsQuery |
ApiError
API error handling.
| Item |
|---|
ApiError :: fn into_api_error(self) -> ApiError |
ApiErrorResponse
API error handling.
| Item |
|---|
pub struct ApiErrorResponse |
ApiErrorResponse :: fn new(error : ApiError) -> Self |
ApiErrorResponse :: fn with_request_id(mut self, request_id : impl Into <String>) -> Self |
ApiErrorResponse :: fn fmt(& self, f : & mut fmt::Formatter <'_>) -> fmt::Result |
ApiErrorResponse :: fn into_response(self) -> Response |
ApiErrorResponse :: fn from(error : ApiError) -> Self |
fn unauthenticated() -> ApiErrorResponse |
fn unauthorized() -> ApiErrorResponse |
fn not_found(resource : impl Into <String>) -> ApiErrorResponse |
fn validation_failed() -> ApiErrorResponse |
fn internal_error() -> ApiErrorResponse |
ApiResult
API error handling.
| Item |
|---|
pub type ApiResult<T>: Result <T, ApiErrorResponse> |
IntoApiError
API error handling.
| Item |
|---|
pub trait IntoApiError |
Result<T,E>
API error handling.
| Item |
|---|
Result<T,E> :: fn map_api_err(self) -> ApiResult <T> |
ResultExt
API error handling.
| Item |
|---|
pub trait ResultExt<T, E> |
serde_json::Error
API error handling.
| Item |
|---|
serde_json::Error :: fn into_api_error(self) -> ApiError |
std::io::Error
API error handling.
| Item |
|---|
std::io::Error :: fn into_api_error(self) -> ApiError |
extractors (other)
Custom extractors with better error handling.
| Item |
|---|
async fn json_body <T : DeserializeOwned>(body : axum::body::Bytes) -> Result <T, Response> |
fn parse_query <T : DeserializeOwned>(query : Option <& str>) -> Result <T, Response> |
IntoApiError
API error handling.
| Item |
|---|
pub trait IntoApiError |
Validate
Custom extractors with better error handling.
| Item |
|---|
fn validate <T : Validate>(value : T) -> Result <T, Response> |
pub trait Validate |
axum::extract::rejection::JsonRejection
Custom extractors with better error handling.
| Item |
|---|
axum::extract::rejection::JsonRejection :: fn into_api_error(self) -> Response |
axum::extract::rejection::PathRejection
Custom extractors with better error handling.
| Item |
|---|
axum::extract::rejection::PathRejection :: fn into_api_error(self) -> Response |
axum::extract::rejection::QueryRejection
Custom extractors with better error handling.
| Item |
|---|
axum::extract::rejection::QueryRejection :: fn into_api_error(self) -> Response |
InMemoryMediaBackend
Media library API handlers.
| Item |
|---|
pub struct InMemoryMediaBackend |
InMemoryMediaBackend :: fn new() -> Self |
InMemoryMediaBackend :: async fn list_assets(& self, query : & MediaListQuery,) -> Result <ListResponse <MediaSummary>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryMediaBackend :: async fn get_asset(& self, id : & str,) -> Result <Option <MediaAsset>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryMediaBackend :: async fn upload_asset(& self, uploader_id : & str, filename : & str, content_type : & str, data : Vec <u8>,) -> Result <MediaAsset, Box <dyn std::error::Error + Send + Sync>> |
InMemoryMediaBackend :: async fn update_asset(& self, id : & str, req : & UpdateMediaRequest,) -> Result <Option <MediaAsset>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryMediaBackend :: async fn delete_asset(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> |
MediaBackend
Media library API handlers.
| Item |
|---|
pub trait MediaBackend |
fn media_routes <M : MediaBackend>(backend : M) -> Router |
middleware (other)
API middleware.
| Item |
|---|
pub const REQUEST_ID_HEADER: & str |
fn propagate_request_id_layer() -> PropagateRequestIdLayer |
fn get_request_id(request : & Request) -> Option <String> |
async fn logging_middleware(request : Request, next : Next) -> Response |
CorsConfig
API middleware.
| Item |
|---|
pub struct CorsConfig |
CorsConfig :: fn default() -> Self |
CorsConfig :: fn permissive() -> Self |
CorsConfig :: fn into_layer(self) -> tower_http::cors::CorsLayer |
RequestIdLayer
API middleware.
| Item |
|---|
pub type RequestIdLayer: SetRequestIdLayer <MakeRequestUuid> |
fn request_id_layer() -> RequestIdLayer |
NotificationsBackend
Notifications API handlers for notifications, preferences, and templates.
| Item |
|---|
pub trait NotificationsBackend |
fn notifications_routes <N : NotificationsBackend>(backend : N) -> Router |
HoldsQuery
Reservations API handlers for capacity pools, holds, and reservations.
| Item |
|---|
pub struct HoldsQuery |
ReservationsBackend
Reservations API handlers for capacity pools, holds, and reservations.
| Item |
|---|
pub trait ReservationsBackend |
fn reservations_routes <R : ReservationsBackend>(backend : R) -> Router |
Accepted
Response helpers and wrappers.
| Item |
|---|
pub struct Accepted<T> |
Accepted<T>
Response helpers and wrappers.
| Item |
|---|
Accepted<T> :: fn new() -> Self |
Accepted<T> :: fn with_body(body : T) -> Self |
Accepted<T> :: fn default() -> Self |
Accepted<T> :: fn into_response(self) -> Response |
ApiJson
Response helpers and wrappers.
| Item |
|---|
pub struct ApiJson<T> |
fn paginated <T : Serialize>(response : platform_dto::ListResponse <T>,) -> ApiJson <platform_dto::ListResponse <T>> |
ApiJson<T>
Response helpers and wrappers.
| Item |
|---|
ApiJson<T> :: fn into_response(self) -> Response |
ApiJson<T> :: fn from(value : T) -> Self |
Created
Response helpers and wrappers.
| Item |
|---|
pub struct Created<T> |
Created<T>
Response helpers and wrappers.
| Item |
|---|
Created<T> :: fn new(body : T) -> Self |
Created<T> :: fn with_location(mut self, location : impl Into <String>) -> Self |
Created<T> :: fn into_response(self) -> Response |
NoContent
Response helpers and wrappers.
| Item |
|---|
pub struct NoContent |
NoContent :: fn into_response(self) -> Response |
DiffQuery
Page version API handlers.
| Item |
|---|
pub struct DiffQuery |
InMemoryRevisionsBackend
Page version API handlers.
| Item |
|---|
pub struct InMemoryRevisionsBackend |
InMemoryRevisionsBackend :: fn default() -> Self |
InMemoryRevisionsBackend :: fn new() -> Self |
InMemoryRevisionsBackend :: fn seed_page(& self, id : & str, title : & str, slug : & str, content : & str, author_id : & str, author_name : & str,) |
InMemoryRevisionsBackend :: fn update_page(& self, page_id : & str, new_title : Option <& str>, new_content : Option <& str>, editor_id : & str, editor_name : & str,) -> bool |
InMemoryRevisionsBackend :: async fn list_revisions(& self, page_id : & str,) -> Result <Vec <RevisionSummary>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryRevisionsBackend :: async fn get_revision(& self, page_id : & str, revision_id : & str,) -> Result <Option <RevisionDetail>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryRevisionsBackend :: async fn restore_revision(& self, page_id : & str, revision_id : & str, restored_by : & str,) -> Result <Option <ContentPage>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryRevisionsBackend :: async fn diff_revisions(& self, page_id : & str, from_id : & str, to_id : & str,) -> Result <Option <RevisionDiff>, Box <dyn std::error::Error + Send + Sync>> |
RevisionsBackend
Page version API handlers.
| Item |
|---|
pub trait RevisionsBackend |
fn revisions_routes <R : RevisionsBackend>(backend : R) -> Router |
AvailabilityPath
Scheduling API handlers for schedules, time slots, and appointments.
| Item |
|---|
pub struct AvailabilityPath |
CalendarViewQuery
Scheduling API handlers for schedules, time slots, and appointments.
| Item |
|---|
pub struct CalendarViewQuery |
ExceptionsQuery
Scheduling API handlers for schedules, time slots, and appointments.
| Item |
|---|
pub struct ExceptionsQuery |
SchedulingBackend
Scheduling API handlers for schedules, time slots, and appointments.
| Item |
|---|
pub trait SchedulingBackend |
fn scheduling_routes <S : SchedulingBackend>(backend : S) -> Router |
InMemorySearchBackend
Unified search API handler.
| Item |
|---|
pub struct InMemorySearchBackend |
InMemorySearchBackend :: fn default() -> Self |
InMemorySearchBackend :: fn new() -> Self |
InMemorySearchBackend :: fn seed(& self, id : & str, entity_type : & str, title : & str, content : & str, url : Option <& str>) |
InMemorySearchBackend :: async fn search(& self, query : & SearchRequest,) -> Result <SearchResponse, Box <dyn std::error::Error + Send + Sync>> |
SearchBackend
Unified search API handler.
| Item |
|---|
pub trait SearchBackend |
fn search_routes <S : SearchBackend>(backend : S) -> Router |
server (other)
Server configuration and router setup.
| Item |
|---|
fn create_router <S, A>(config : ServerConfig, domain_state : S, auth_backend : A) -> Router where S : Clone + Send + Sync + 'static, A : AuthBackend, |
AppState
Server configuration and router setup.
| Item |
|---|
pub struct AppState<S> |
AppState<S>
Server configuration and router setup.
| Item |
|---|
AppState<S> :: fn new(config : ServerConfig, domain : S) -> Self |
AuthBackend
Server configuration and router setup.
| Item |
|---|
pub trait AuthBackend |
ServerConfig
Server configuration and router setup.
| Item |
|---|
pub struct ServerConfig |
ServerConfig :: fn default() -> Self |
InMemorySettingsBackend
Site settings API handlers.
| Item |
|---|
pub struct InMemorySettingsBackend |
InMemorySettingsBackend :: fn default() -> Self |
InMemorySettingsBackend :: fn new() -> Self |
InMemorySettingsBackend :: async fn get_all(& self,) -> Result <HashMap <String, serde_json::Value>, Box <dyn std::error::Error + Send + Sync>> |
InMemorySettingsBackend :: async fn get(& self, key : & str,) -> Result <Option <SettingValue>, Box <dyn std::error::Error + Send + Sync>> |
InMemorySettingsBackend :: async fn update(& self, new_settings : & HashMap <String, serde_json::Value>, updated_by : & str,) -> Result <HashMap <String, serde_json::Value>, Box <dyn std::error::Error + Send + Sync>> |
SettingsBackend
Site settings API handlers.
| Item |
|---|
pub trait SettingsBackend |
fn settings_routes <S : SettingsBackend>(backend : S) -> Router |
FocalPointRequest
Reference Postgres + storage-backed MediaBackend (Sprint 0.26/0.27).
| Item |
|---|
pub struct FocalPointRequest |
SqlxMediaBackend
Reference Postgres + storage-backed MediaBackend (Sprint 0.26/0.27).
| Item |
|---|
pub struct SqlxMediaBackend |
SqlxMediaBackend :: fn new(pool : PgPool, storage : Arc <dyn StorageBackend>, public_base_url : impl Into <String>,) -> Self |
SqlxMediaBackend :: async fn update_focal_point(& self, asset_id : & str, x : f64, y : f64,) -> Result <Option <MediaAsset>, BoxError> |
SqlxMediaBackend :: async fn list_assets(& self, query : & MediaListQuery,) -> Result <ListResponse <MediaSummary>, BoxError> |
SqlxMediaBackend :: async fn get_asset(& self, id : & str) -> Result <Option <MediaAsset>, BoxError> |
SqlxMediaBackend :: async fn upload_asset(& self, _uploader_id : & str, filename : & str, content_type : & str, data : Vec <u8>,) -> Result <MediaAsset, BoxError> |
SqlxMediaBackend :: async fn update_asset(& self, id : & str, req : & UpdateMediaRequest,) -> Result <Option <MediaAsset>, BoxError> |
SqlxMediaBackend :: async fn delete_asset(& self, id : & str) -> Result <bool, BoxError> |
fn focal_point_routes(backend : std::sync::Arc <SqlxMediaBackend>) -> axum::Router |
TaxonomyBackend
Taxonomy API handlers for vocabularies, categories, and tags.
| Item |
|---|
pub trait TaxonomyBackend |
fn taxonomy_routes <T : TaxonomyBackend>(backend : T) -> Router |
InMemoryUsersBackend
User management API handlers.
| Item |
|---|
pub struct InMemoryUsersBackend |
InMemoryUsersBackend :: fn new() -> Self |
InMemoryUsersBackend :: async fn list_users(& self, query : & UserListQuery,) -> Result <ListResponse <UserSummary>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryUsersBackend :: async fn get_user(& self, id : & str,) -> Result <Option <UserDetail>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryUsersBackend :: async fn create_user(& self, req : & CreateUserRequest,) -> Result <UserDetail, Box <dyn std::error::Error + Send + Sync>> |
InMemoryUsersBackend :: async fn update_user(& self, id : & str, req : & UpdateUserRequest,) -> Result <Option <UserDetail>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryUsersBackend :: async fn delete_user(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> |
InMemoryUsersBackend :: async fn list_user_roles(& self, user_id : & str,) -> Result <Option <Vec <String>>, Box <dyn std::error::Error + Send + Sync>> |
InMemoryUsersBackend :: async fn update_user_roles(& self, user_id : & str, roles : & String,) -> Result <Option <Vec <String>>, Box <dyn std::error::Error + Send + Sync>> |
UserError
User management API handlers.
| Item |
|---|
pub enum UserError |
UserError :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result |
UsersBackend
User management API handlers.
| Item |
|---|
pub trait UsersBackend |
fn users_routes <U : UsersBackend>(backend : U) -> Router |
How to use it
From `examples/media_server.rs`:
#[cfg(not(feature = "sqlx-backend"))]
fn main() {
eprintln!("run with --features sqlx-backend");
}
#[cfg(feature = "sqlx-backend")]
#[tokio::main]
async fn main() {
use std::sync::Arc;
use axum::Router;
use infrastructure_storage::LocalStorage;
use platform_api::media::media_routes;
use platform_api::sqlx_backend::{focal_point_routes, SqlxMediaBackend};
use sqlx::postgres::PgPoolOptions;
use tower_http::services::ServeDir;
Module structure
platform_api
api_keysaudit_logsauthauth::passwordcmscommentserrorextractorsmediamiddlewarenotificationsreservationsresponserevisionsschedulingsearchserversettingssqlx_backendtaxonomyusers
flowchart TD n_platform_api["platform_api"] n_platform_api --> n_api_keys["api_keys"] n_platform_api --> n_audit_logs["audit_logs"] n_platform_api --> n_auth["auth"] n_auth --> n_auth__password["password"] n_platform_api --> n_cms["cms"] n_platform_api --> n_comments["comments"] n_platform_api --> n_error["error"] n_platform_api --> n_extractors["extractors"] n_platform_api --> n_media["media"] n_platform_api --> n_middleware["middleware"] n_platform_api --> n_notifications["notifications"] n_platform_api --> n_reservations["reservations"] n_platform_api --> n_response["response"] n_platform_api --> n_revisions["revisions"] n_platform_api --> n_scheduling["scheduling"] n_platform_api --> n_search["search"] n_platform_api --> n_server["server"] n_platform_api --> n_settings["settings"] n_platform_api --> n_sqlx_backend["sqlx_backend"] n_platform_api --> n_taxonomy["taxonomy"] n_platform_api --> n_users["users"]
Public surface
`api_keys`
| Item | What it is |
|---|---|
pub trait ApiKeysBackend | Backend trait for API key management operations. |
fn api_keys_routes <K : ApiKeysBackend>(backend : K) -> Router | Create API key management routes. |
pub struct InMemoryApiKeysBackend | In-memory API keys backend for testing/development. |
InMemoryApiKeysBackend :: fn default() -> Self | — |
InMemoryApiKeysBackend :: fn new() -> Self | — |
InMemoryApiKeysBackend :: async fn list_api_keys(& self, user_id : & str,) -> Result <Vec <ApiKeySummary>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryApiKeysBackend :: async fn create_api_key(& self, user_id : & str, req : & CreateApiKeyRequest,) -> Result <ApiKeyCreated, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryApiKeysBackend :: async fn get_api_key(& self, id : & str,) -> Result <Option <ApiKeySummary>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryApiKeysBackend :: async fn revoke_api_key(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> | — |
`audit_logs`
| Item | What it is |
|---|---|
pub trait AuditLogsBackend | Backend trait for audit log read operations. |
fn audit_logs_routes <A : AuditLogsBackend>(backend : A) -> Router | Create audit log routes (read-only). |
pub struct InMemoryAuditLogsBackend | In-memory audit logs backend for testing/development. |
InMemoryAuditLogsBackend :: fn default() -> Self | — |
InMemoryAuditLogsBackend :: fn new() -> Self | — |
InMemoryAuditLogsBackend :: fn seed(& self, entry : AuditLogDetail) | Seed an audit log entry (simulates internal creation by other operations). |
InMemoryAuditLogsBackend :: fn make_entry(entity_type : & str, entity_id : & str, action : & str, user_id : Option <& str>, user_email : Option <& str>,) -> AuditLogDetail | Helper to build a basic audit log entry. |
InMemoryAuditLogsBackend :: fn seed_at(& self, entity_type : & str, entity_id : & str, action : & str, created_at : chrono::DateTime <chrono::Utc>,) | Seed with a specific timestamp (for date range testing). |
InMemoryAuditLogsBackend :: async fn list_audit_logs(& self, query : & AuditLogQuery,) -> Result <ListResponse <AuditLogSummary>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryAuditLogsBackend :: async fn get_audit_log(& self, id : & str,) -> Result <Option <AuditLogDetail>, Box <dyn std::error::Error + Send + Sync>> | — |
`auth`
| Item | What it is |
|---|---|
pub struct AuthUser | Authenticated user from session. |
AuthUser :: fn new(id : Uuid, email : String, display_name : String, roles : Vec <String>) -> Self | Create a new auth user. |
AuthUser :: fn has_role(& self, role : & str) -> bool | Check if user has a role. |
AuthUser :: fn has_permission(& self, permission : & str) -> bool | Check if user has a permission. |
AuthUser :: fn is_admin(& self) -> bool | Check if user is admin. |
AuthUser :: fn to_user_info(& self) -> UserInfo | Convert to UserInfo DTO |
pub struct AuthSession | Session wrapper for auth operations. |
AuthSession :: fn new(session : Session) -> Self | — |
AuthSession :: async fn get_user(& self) -> Option <AuthUser> | Get the current user from session. |
AuthSession :: async fn set_user(& self, user : AuthUser) -> Result <(), tower_sessions::session::Error> | Set the current user in session. |
AuthSession :: async fn clear_user(& self) -> Result <(), tower_sessions::session::Error> | Clear the current user from session (logout). |
AuthSession :: async fn is_authenticated(& self) -> bool | Check if user is authenticated. |
pub struct RequireAuth | Extractor that requires authentication |
RequireAuth :: async fn from_request_parts(parts : & mut Parts, _state : & S) -> Result <Self, Self::Rejection> | — |
pub struct OptionalAuth | Extractor that optionally gets the current user |
OptionalAuth :: async fn from_request_parts(parts : & mut Parts, _state : & S) -> Result <Self, Self::Rejection> | — |
fn require_permission(user : & AuthUser, permission : & str) -> Result <(), Response> | Require that the authenticated user has a specific permission |
fn require_role(user : & AuthUser, role : & str) -> Result <(), Response> | Require that the authenticated user has a specific role |
fn require_admin(user : & AuthUser) -> Result <(), Response> | Require that the authenticated user is an admin |
`auth::password`
| Item | What it is |
|---|---|
fn hash(password : & str) -> Result <String, argon2::password_hash::Error> | Hash a password. |
fn verify(password : & str, hash : & str) -> Result <bool, argon2::password_hash::Error> | Verify a password against a hash. |
`cms`
| Item | What it is |
|---|---|
pub trait CmsBackend | Backend trait for CMS operations |
fn cms_routes <C : CmsBackend>(backend : C) -> Router | Create CMS routes that can be merged into the main router |
pub struct InMemoryCmsBackend | In-memory CMS backend for testing/development. |
InMemoryCmsBackend :: fn new() -> Self | — |
InMemoryCmsBackend :: async fn list_pages(& self, query : & PageListQuery,) -> Result <ListResponse <PageSummary>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryCmsBackend :: async fn get_page(& self, id : & str,) -> Result <Option <ContentPage>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryCmsBackend :: async fn create_page(& self, author_id : & str, req : & CreatePageRequest,) -> Result <ContentPage, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryCmsBackend :: async fn update_page(& self, id : & str, req : & UpdatePageRequest,) -> Result <Option <ContentPage>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryCmsBackend :: async fn delete_page(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> | — |
`comments`
| Item | What it is |
|---|---|
pub const SINGLE_TENANT: Uuid | This crate is the SINGLE-TENANT reference platform API (multi-tenant comments live in application-comments) |
pub trait CommentsBackend | Backend trait for comments operations. |
pub struct ThreadsQuery | Thread query parameters. |
fn comments_routes <C : CommentsBackend>(backend : C) -> Router | Create comments routes |
pub struct ReactionPath | Path parameters for reaction removal. |
`error`
| Item | What it is |
|---|---|
pub type ApiResult<T>: Result <T, ApiErrorResponse> | Result type for API handlers. |
pub struct ApiErrorResponse | Wrapper for ApiError that implements IntoResponse. |
ApiErrorResponse :: fn new(error : ApiError) -> Self | — |
ApiErrorResponse :: fn with_request_id(mut self, request_id : impl Into <String>) -> Self | — |
ApiErrorResponse :: fn fmt(& self, f : & mut fmt::Formatter <'_>) -> fmt::Result | — |
ApiErrorResponse :: fn into_response(self) -> Response | — |
ApiErrorResponse :: fn from(error : ApiError) -> Self | — |
pub trait IntoApiError | Trait for converting errors to ApiError. |
ApiError :: fn into_api_error(self) -> ApiError | — |
std::io::Error :: fn into_api_error(self) -> ApiError | — |
serde_json::Error :: fn into_api_error(self) -> ApiError | — |
pub trait ResultExt<T, E> | Extension trait to convert Results to ApiResult. |
Result<T,E> :: fn map_api_err(self) -> ApiResult <T> | — |
fn unauthenticated() -> ApiErrorResponse | — |
fn unauthorized() -> ApiErrorResponse | — |
fn not_found(resource : impl Into <String>) -> ApiErrorResponse | — |
fn validation_failed() -> ApiErrorResponse | — |
fn internal_error() -> ApiErrorResponse | — |
`extractors`
| Item | What it is |
|---|---|
async fn json_body <T : DeserializeOwned>(body : axum::body::Bytes) -> Result <T, Response> | Wrapper for axum's Json extractor that converts errors to ApiError. |
fn parse_query <T : DeserializeOwned>(query : Option <& str>) -> Result <T, Response> | Parse query parameters with ApiError on failure. |
fn validate <T : Validate>(value : T) -> Result <T, Response> | Validate a value and return ApiError on validation failure. |
pub trait Validate | Validation trait for request bodies. |
pub trait IntoApiError | Extension trait for converting axum extraction errors to ApiError responses. |
axum::extract::rejection::JsonRejection :: fn into_api_error(self) -> Response | — |
axum::extract::rejection::QueryRejection :: fn into_api_error(self) -> Response | — |
axum::extract::rejection::PathRejection :: fn into_api_error(self) -> Response | — |
`media`
| Item | What it is |
|---|---|
pub trait MediaBackend | Backend trait for media operations |
fn media_routes <M : MediaBackend>(backend : M) -> Router | Create media routes that can be merged into the main router |
pub struct InMemoryMediaBackend | In-memory media backend for testing/development. |
InMemoryMediaBackend :: fn new() -> Self | — |
InMemoryMediaBackend :: async fn list_assets(& self, query : & MediaListQuery,) -> Result <ListResponse <MediaSummary>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryMediaBackend :: async fn get_asset(& self, id : & str,) -> Result <Option <MediaAsset>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryMediaBackend :: async fn upload_asset(& self, uploader_id : & str, filename : & str, content_type : & str, data : Vec <u8>,) -> Result <MediaAsset, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryMediaBackend :: async fn update_asset(& self, id : & str, req : & UpdateMediaRequest,) -> Result <Option <MediaAsset>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryMediaBackend :: async fn delete_asset(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> | — |
`middleware`
| Item | What it is |
|---|---|
pub const REQUEST_ID_HEADER: & str | Header name for request ID. |
pub type RequestIdLayer: SetRequestIdLayer <MakeRequestUuid> | Layer for setting request IDs. |
fn request_id_layer() -> RequestIdLayer | Create request ID layer. |
fn propagate_request_id_layer() -> PropagateRequestIdLayer | Create propagate request ID layer. |
fn get_request_id(request : & Request) -> Option <String> | Extract request ID from request extensions. |
async fn logging_middleware(request : Request, next : Next) -> Response | Middleware that logs requests with timing. |
pub struct CorsConfig | CORS configuration builder. |
CorsConfig :: fn default() -> Self | — |
CorsConfig :: fn permissive() -> Self | — |
CorsConfig :: fn into_layer(self) -> tower_http::cors::CorsLayer | — |
`notifications`
| Item | What it is |
|---|---|
pub trait NotificationsBackend | Backend trait for notifications operations. |
fn notifications_routes <N : NotificationsBackend>(backend : N) -> Router | Create notifications routes. |
`reservations`
| Item | What it is |
|---|---|
pub trait ReservationsBackend | Backend trait for reservations operations. |
pub struct HoldsQuery | — |
fn reservations_routes <R : ReservationsBackend>(backend : R) -> Router | Create reservations routes. |
`response`
| Item | What it is |
|---|---|
pub struct ApiJson<T> | JSON response wrapper. |
ApiJson<T> :: fn into_response(self) -> Response | — |
ApiJson<T> :: fn from(value : T) -> Self | — |
pub struct Created<T> | Created response (201) with location header and body. |
Created<T> :: fn new(body : T) -> Self | — |
Created<T> :: fn with_location(mut self, location : impl Into <String>) -> Self | — |
Created<T> :: fn into_response(self) -> Response | — |
pub struct NoContent | No content response (204). |
NoContent :: fn into_response(self) -> Response | — |
pub struct Accepted<T> | Accepted response (202) for async operations. |
Accepted<T> :: fn new() -> Self | — |
Accepted<T> :: fn with_body(body : T) -> Self | — |
Accepted<T> :: fn default() -> Self | — |
Accepted<T> :: fn into_response(self) -> Response | — |
fn paginated <T : Serialize>(response : platform_dto::ListResponse <T>,) -> ApiJson <platform_dto::ListResponse <T>> | Pagination response wrapper. |
`revisions`
| Item | What it is |
|---|---|
pub trait RevisionsBackend | Backend trait for page version operations. |
pub struct DiffQuery | Query parameters for diff endpoint. |
fn revisions_routes <R : RevisionsBackend>(backend : R) -> Router | Create version routes (nested under /cms/pages/:id/revisions). |
pub struct InMemoryRevisionsBackend | In-memory versions backend for testing/development. |
InMemoryRevisionsBackend :: fn default() -> Self | — |
InMemoryRevisionsBackend :: fn new() -> Self | — |
InMemoryRevisionsBackend :: fn seed_page(& self, id : & str, title : & str, slug : & str, content : & str, author_id : & str, author_name : & str,) | Seed a page for testing. |
InMemoryRevisionsBackend :: fn update_page(& self, page_id : & str, new_title : Option <& str>, new_content : Option <& str>, editor_id : & str, editor_name : & str,) -> bool | Update a page, creating a version of the previous state. |
InMemoryRevisionsBackend :: async fn list_revisions(& self, page_id : & str,) -> Result <Vec <RevisionSummary>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryRevisionsBackend :: async fn get_revision(& self, page_id : & str, revision_id : & str,) -> Result <Option <RevisionDetail>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryRevisionsBackend :: async fn restore_revision(& self, page_id : & str, revision_id : & str, restored_by : & str,) -> Result <Option <ContentPage>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryRevisionsBackend :: async fn diff_revisions(& self, page_id : & str, from_id : & str, to_id : & str,) -> Result <Option <RevisionDiff>, Box <dyn std::error::Error + Send + Sync>> | — |
`scheduling`
| Item | What it is |
|---|---|
pub trait SchedulingBackend | Backend trait for scheduling operations. |
pub struct CalendarViewQuery | — |
pub struct ExceptionsQuery | — |
pub struct AvailabilityPath | — |
fn scheduling_routes <S : SchedulingBackend>(backend : S) -> Router | Create scheduling routes. |
`search`
| Item | What it is |
|---|---|
pub trait SearchBackend | Backend trait for unified search. |
fn search_routes <S : SearchBackend>(backend : S) -> Router | Create search routes. |
pub struct InMemorySearchBackend | In-memory search backend for testing/development. |
InMemorySearchBackend :: fn default() -> Self | — |
InMemorySearchBackend :: fn new() -> Self | — |
InMemorySearchBackend :: fn seed(& self, id : & str, entity_type : & str, title : & str, content : & str, url : Option <& str>) | Seed a searchable item. |
InMemorySearchBackend :: async fn search(& self, query : & SearchRequest,) -> Result <SearchResponse, Box <dyn std::error::Error + Send + Sync>> | — |
`server`
| Item | What it is |
|---|---|
pub struct ServerConfig | Server configuration. |
ServerConfig :: fn default() -> Self | — |
pub struct AppState<S> | Application state shared across handlers. |
AppState<S> :: fn new(config : ServerConfig, domain : S) -> Self | — |
pub trait AuthBackend | Auth backend trait for domain-specific user lookup. |
fn create_router <S, A>(config : ServerConfig, domain_state : S, auth_backend : A) -> Router where S : Clone + Send + Sync + 'static, A : AuthBackend, | Create the base API router with standard endpoints. |
`settings`
| Item | What it is |
|---|---|
pub trait SettingsBackend | Backend trait for settings operations. |
fn settings_routes <S : SettingsBackend>(backend : S) -> Router | Create settings routes. |
pub struct InMemorySettingsBackend | In-memory settings backend for testing/development. |
InMemorySettingsBackend :: fn default() -> Self | — |
InMemorySettingsBackend :: fn new() -> Self | — |
InMemorySettingsBackend :: async fn get_all(& self,) -> Result <HashMap <String, serde_json::Value>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemorySettingsBackend :: async fn get(& self, key : & str,) -> Result <Option <SettingValue>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemorySettingsBackend :: async fn update(& self, new_settings : & HashMap <String, serde_json::Value>, updated_by : & str,) -> Result <HashMap <String, serde_json::Value>, Box <dyn std::error::Error + Send + Sync>> | — |
`sqlx_backend`
| Item | What it is |
|---|---|
pub struct SqlxMediaBackend | Postgres + storage-backed media backend wired to the ingest pipeline |
SqlxMediaBackend :: fn new(pool : PgPool, storage : Arc <dyn StorageBackend>, public_base_url : impl Into <String>,) -> Self | Create a backend over a pool + storage backend |
SqlxMediaBackend :: async fn update_focal_point(& self, asset_id : & str, x : f64, y : f64,) -> Result <Option <MediaAsset>, BoxError> | Set an asset's focal point (clamped to 0,1) and synchronously regenerate its aspect-locked variants (Sprint 0.33) |
SqlxMediaBackend :: async fn list_assets(& self, query : & MediaListQuery,) -> Result <ListResponse <MediaSummary>, BoxError> | — |
SqlxMediaBackend :: async fn get_asset(& self, id : & str) -> Result <Option <MediaAsset>, BoxError> | — |
SqlxMediaBackend :: async fn upload_asset(& self, _uploader_id : & str, filename : & str, content_type : & str, data : Vec <u8>,) -> Result <MediaAsset, BoxError> | — |
SqlxMediaBackend :: async fn update_asset(& self, id : & str, req : & UpdateMediaRequest,) -> Result <Option <MediaAsset>, BoxError> | — |
SqlxMediaBackend :: async fn delete_asset(& self, id : & str) -> Result <bool, BoxError> | — |
pub struct FocalPointRequest | Request body for the focal-point endpoint. |
fn focal_point_routes(backend : std::sync::Arc <SqlxMediaBackend>) -> axum::Router | Dedicated admin route for setting an asset's focal point + regenerating aspect-locked variants: PATCH /:id/focal-point |
`taxonomy`
| Item | What it is |
|---|---|
pub trait TaxonomyBackend | Backend trait for taxonomy operations. |
fn taxonomy_routes <T : TaxonomyBackend>(backend : T) -> Router | Create taxonomy routes. |
`users`
| Item | What it is |
|---|---|
pub enum UserError | Domain error for user operations. |
UserError :: fn fmt(& self, f : & mut std::fmt::Formatter <'_>) -> std::fmt::Result | — |
pub trait UsersBackend | Backend trait for user management operations. |
fn users_routes <U : UsersBackend>(backend : U) -> Router | Create user management routes. |
pub struct InMemoryUsersBackend | In-memory users backend for testing/development. |
InMemoryUsersBackend :: fn new() -> Self | — |
InMemoryUsersBackend :: async fn list_users(& self, query : & UserListQuery,) -> Result <ListResponse <UserSummary>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryUsersBackend :: async fn get_user(& self, id : & str,) -> Result <Option <UserDetail>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryUsersBackend :: async fn create_user(& self, req : & CreateUserRequest,) -> Result <UserDetail, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryUsersBackend :: async fn update_user(& self, id : & str, req : & UpdateUserRequest,) -> Result <Option <UserDetail>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryUsersBackend :: async fn delete_user(& self, id : & str,) -> Result <bool, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryUsersBackend :: async fn list_user_roles(& self, user_id : & str,) -> Result <Option <Vec <String>>, Box <dyn std::error::Error + Send + Sync>> | — |
InMemoryUsersBackend :: async fn update_user_roles(& self, user_id : & str, roles : & String,) -> Result <Option <Vec <String>>, Box <dyn std::error::Error + Send + Sync>> | — |
Re-exports. Exported here, defined elsewhere.
| Export | Defined in |
|---|---|
platform_dtoasdto | platform_dtoasdto |
{Accepted,ApiJson,Created,NoContent} | response::{Accepted,ApiJson,Created,NoContent} |
{ApiErrorResponse,ApiResult} | error::{ApiErrorResponse,ApiResult} |
{IntoApiError,Validate} | extractors::{IntoApiError,Validate} |
{api_keys_routes,ApiKeysBackend,InMemoryApiKeysBackend} | api_keys::{api_keys_routes,ApiKeysBackend,InMemoryApiKeysBackend} |
{audit_logs_routes,AuditLogsBackend,InMemoryAuditLogsBackend} | audit_logs::{audit_logs_routes,AuditLogsBackend,InMemoryAuditLogsBackend} |
{cms_routes,CmsBackend,InMemoryCmsBackend} | cms::{cms_routes,CmsBackend,InMemoryCmsBackend} |
{comments_routes,CommentsBackend} | comments::{comments_routes,CommentsBackend} |
{create_router,AppState,AuthBackend,ServerConfig} | server::{create_router,AppState,AuthBackend,ServerConfig} |
{media_routes,InMemoryMediaBackend,MediaBackend} | media::{media_routes,InMemoryMediaBackend,MediaBackend} |
{notifications_routes,NotificationsBackend} | notifications::{notifications_routes,NotificationsBackend} |
{request_id_layer,CorsConfig,RequestIdLayer} | middleware::{request_id_layer,CorsConfig,RequestIdLayer} |
{require_admin,require_permission,require_role,AuthSession,AuthUser,OptionalAuth,RequireAuth,} | auth::{require_admin,require_permission,require_role,AuthSession,AuthUser,OptionalAuth,RequireAuth,} |
{reservations_routes,ReservationsBackend} | reservations::{reservations_routes,ReservationsBackend} |
{revisions_routes,InMemoryRevisionsBackend,RevisionsBackend} | revisions::{revisions_routes,InMemoryRevisionsBackend,RevisionsBackend} |
{scheduling_routes,SchedulingBackend} | scheduling::{scheduling_routes,SchedulingBackend} |
{search_routes,InMemorySearchBackend,SearchBackend} | search::{search_routes,InMemorySearchBackend,SearchBackend} |
{settings_routes,InMemorySettingsBackend,SettingsBackend} | settings::{settings_routes,InMemorySettingsBackend,SettingsBackend} |
{taxonomy_routes,TaxonomyBackend} | taxonomy::{taxonomy_routes,TaxonomyBackend} |
{users_routes,InMemoryUsersBackend,UsersBackend} | users::{users_routes,InMemoryUsersBackend,UsersBackend} |
Boundary
Reaches into content, infrastructure.
Shares tier platform with 9 other crates: platform-corpus-console, platform-customer-ui, platform-disclosure-lab, platform-dto, platform-html-components, platform-leptos-components, platform-privacy-scan-api, platform-staff-ui, … (9 total).
_What this crate deliberately does NOT own is a judgment. No committed registry records one for it, so none is stated here._
Where it sits
| Tier (ontology) | platform |
| Architectural role (taxonomy) | infrastructure |
| Location | crates/platform/api |
| Vocabulary in force (lexicon) | current |
Tier flow. Which tiers this crate's own edges cross.
flowchart LR n_platform["platform"] --> n_content["content"] n_platform["platform"] --> n_infrastructure["infrastructure"]
Dependencies
Runtime, in this workspace.
| Crate | Tier | Optional | Only on |
|---|---|---|---|
| `content-assets` | content | yes | always |
| `infrastructure-storage` | infrastructure | yes | always |
| `platform-dto` | platform | no | always |
Runtime, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
argon2 | ^0.5 | — | no | always |
async-trait | ^0.1 | — | no | always |
axum | ^0.7 | multipart | no | always |
axum-extra | ^0.9 | cookie | no | always |
base64 | ^0.22 | — | no | always |
chrono | ^0.4 | serde | no | always |
hex | ^0.4 | — | no | always |
rand | ^0.8 | — | no | always |
serde | ^1 | derive | no | always |
serde_json | ^1 | — | no | always |
serde_urlencoded | ^0.7 | — | no | always |
sha2 | ^0.10 | — | no | always |
sqlx | ^0.8 | runtime-tokio, postgres, chrono, uuid, json | yes | always |
thiserror | ^2 | — | no | always |
time | ^0.3 | — | no | always |
tokio | ^1 | full | no | always |
tower | ^0.5 | — | no | always |
tower-cookies | ^0.10 | — | no | always |
tower-http | ^0.6 | fs, trace, cors, request-id | no | always |
tower-sessions | ^0.13 | — | no | always |
tracing | ^0.1 | — | no | always |
uuid | ^1 | v4, serde | no | always |
Development, from outside the workspace.
| Crate | Requirement | Features | Optional | Only on |
|---|---|---|---|---|
tokio-test | ^0.4 | — | no | always |
Build. None.
Depended on by. Nothing in this workspace.
Signal flow — what reaches this crate, and what it reaches.
flowchart LR SELF["platform-api"] SELF -->|runtime| n_content_assets["content-assets"] SELF -->|runtime| n_infrastructure_storage["infrastructure-storage"] SELF -->|runtime| n_platform_dto["platform-dto"] classDef self fill:#1f883d,stroke:#1f883d,color:#fff; class SELF self;
Feature flags
| Feature | Enables | On by default |
|---|---|---|
default | — | yes |
sqlx-backend | dep:content-assets, dep:infrastructure-storage, dep:sqlx | no |
flowchart LR n_default["default"] n_sqlx_backend["sqlx-backend"] --> n_dep_content_assets["dep:content-assets"] n_sqlx_backend["sqlx-backend"] --> n_dep_infrastructure_storage["dep:infrastructure-storage"] n_sqlx_backend["sqlx-backend"] --> n_dep_sqlx["dep:sqlx"]
Targets
| Kind | Name | Source |
|---|---|---|
| example | media_server | `examples/media_server.rs` |
| lib | platform_api | `src/lib.rs` |
Error model
| Error type | Named by |
|---|---|
IntoApiError | declared, no public signature returns it |
UserError | declared, no public signature returns it |
Operational characteristics
| Property | Evidence |
|---|---|
| async public surface | yes |
| async runtime | yes |
| database access | yes |
| network I/O | yes |
| unsafe code | none detected |
| environment variables | yes |
No unsafe block, unsafe fn, unsafe impl or unsafe trait was found by the parser anywhere in this crate's source.
Configuration
| Variable | Read in |
|---|---|
CARGO_PKG_VERSION | src/server.rs |
DATABASE_URL | src/sqlx_backend.rs |
Related capabilities
No workspace crate depends on this one.
Verification
| Kind | Count |
|---|---|
| Unit tests | 65 |
| Integration tests | 0 |
| Examples | 1 |
| Doctests | 0 |
Evidence by module. How often each public module is named by something executable.
| Module | Tests | Examples | Consumers |
|---|---|---|---|
api_keys | 3 | 0 | 0 |
audit_logs | 3 | 0 | 0 |
auth | 7 | 0 | 0 |
auth::password | 2 | 0 | 0 |
cms | 3 | 0 | 0 |
comments | 5 | 0 | 0 |
error | 9 | 0 | 0 |
extractors | 5 | 0 | 0 |
media | 3 | 2 | 0 |
middleware | 7 | 0 | 0 |
notifications | 2 | 0 | 0 |
reservations | 3 | 0 | 0 |
response | 5 | 0 | 0 |
revisions | 4 | 0 | 0 |
scheduling | 5 | 0 | 0 |
search | 3 | 0 | 0 |
server | 4 | 0 | 0 |
settings | 3 | 0 | 0 |
sqlx_backend | 3 | 2 | 0 |
taxonomy | 2 | 0 | 0 |
users | 4 | 0 | 0 |
What the tests establish, by name:
test_create_api_key—src/api_keys.rstest_create_api_key_plaintext_only_on_create—src/api_keys.rstest_get_api_key_not_found—src/api_keys.rstest_list_api_keys—src/api_keys.rstest_list_api_keys_scoped_to_user—src/api_keys.rstest_revoke_already_revoked—src/api_keys.rstest_revoke_api_key—src/api_keys.rstest_filter_by_action—src/audit_logs.rstest_filter_by_date_range—src/audit_logs.rstest_filter_by_entity_type—src/audit_logs.rstest_filter_by_user_id—src/audit_logs.rstest_get_audit_log—src/audit_logs.rstest_get_audit_log_not_found—src/audit_logs.rstest_list_audit_logs—src/audit_logs.rstest_list_audit_logs_empty—src/audit_logs.rstest_no_create_endpoint—src/audit_logs.rstest_no_delete_endpoint—src/audit_logs.rstest_admin_has_all_permissions—src/auth.rstest_auth_user_roles—src/auth.rstest_password_hash_verify—src/auth.rstest_in_memory_backend—src/cms.rsevery_mutator_401s_without_a_session—src/comments.rssession_identity_reaches_the_backend_as_the_author—src/comments.rstest_error_response_status—src/error.rstest_in_memory_backend—src/media.rstest_diff_revisions—src/revisions.rstest_get_revision—src/revisions.rstest_list_revisions_empty—src/revisions.rstest_list_revisions_ordered—src/revisions.rstest_restore_creates_new_revision—src/revisions.rs- _… 35 more_
Documentation coverage
| Measure | Documented | Total |
|---|---|---|
| Public items with rustdoc | 93 | 182 |
Public modules with a //! block | 20 | 21 |
pie showData
title Public items with rustdoc
"Documented" : 93
"No rustdoc detected" : 89
Metrics
| Metric | Value |
|---|---|
| Rust source files | 21 |
| Source lines | 7959 |
| Code lines | 6645 |
| Public API items | 182 |
| Public modules | 21 |
| Tests | 65 |
| Examples | 1 |
| Cargo features | 2 |
| Direct runtime dependencies | 25 |
| Workspace reverse dependencies | 0 |
pie showData
title Public API by kind
"constant" : 2
"enum" : 1
"function" : 33
"method" : 97
"struct" : 29
"trait" : 18
"type alias" : 2
pie showData
title Rust source composition
"Code" : 6645
"Blank or comment" : 1314
Generation
Rendered by tools-corpus corpus readme from repository evidence alone, renderer schema 2, lexicon current. No model, network service or database was consulted. Regenerate with tools-corpus corpus readme --write; verify with --check.