mae
Opinionated async Rust framework for building Mae-Technologies micro-services.
Pair with mae_macros for proc-macro helpers (#[run_app], #[schema], #[mae_test]). Request/response DTOs live in your service or in a shared models crate — not in mae itself.
Install
[]
= "0.3"
= "0.1"
[]
= { = "0.3", = ["test-utils"] }
What you get
| Module | Purpose |
|---|---|
app |
Config loading, context builder, Actix server runner |
context |
RequestContext<YourAppContext> — pool, session, custom config per request |
repo |
Typed Postgres repository layer (WithExecutor, filters, DomainStatus) |
route |
Success / ServiceError / ServiceResult HTTP envelope + health routes |
middleware |
Session and micro-service auth extractors (wired by #[run_app]) |
session |
Session identity (user_id, sys_client_id) |
service |
HttpServiceClient for service-to-service HTTP calls |
crypto |
AES-256-GCM field encryption for secrets at rest |
totp |
RFC 6238 TOTP generate / verify / otpauth URI |
util |
Small helpers (e.g. query-string builder) |
testing |
Integration-test helpers (test-utils feature only) |
Internal wiring (repo::__private__, container refcount guards, etc.) is not part of the public API — depend only on the modules above.
Quick start — new service
1. Configuration
use DeriveContext;
use Deserialize;
Load config in main.rs:
use get_configuration;
use run;
async
2. HTTP routes (#[run_app])
use web;
use *;
use run_app;
#[run_app] expands into a full run() that attaches Redis sessions, CORS, tracing, health checks, and your routes.
3. Domain repository (#[schema])
Define only business fields — audit columns are injected by the macro:
use schema;
use *;
// Use WithExecutor in usecases:
// WidgetRepo::find().filter(...).fetch_one(&ctx).await?
Use #[schema_root] for the sys_client table (no sys_client FK column).
4. Controllers — standard response envelope
use ;
pub async
Clients always receive { "data": ... } on success; errors map to consistent HTTP status codes.
5. Usecases — transactions
use WithExecutor;
use ServiceError;
pub async
6. Service-to-service calls
use ContextAccessor;
use ;
let client = new;
let body: QueueStatus = client.get.await?;
Downstream services should expose the same ServiceResult JSON envelope.
7. Encrypted fields + TOTP (optional)
use ;
use ;
Integration testing (test-utils)
use ;
use mae_test;
async
Run docker-gated tests:
MAE_TESTCONTAINERS=1
Postgres helpers also support a fallback mode (connect to an existing instance) when MAE_TESTCONTAINERS is unset. See environment variables in DEVELOPMENT.md.
Built-in health endpoints
Registered automatically by #[run_app]:
GET /health— process livenessGET /health/pg— Postgres connectivityGET /health/neo— Neo4j connectivity
Related crates
mae_macros— proc macros used throughout the examples abovestatbook_models— shared API DTOs for Statbook.io services (separate crate; not re-exported bymae)
Development
See DEVELOPMENT.md for local setup, smoke tests, and contribution rules.
License
MIT