axum-apcore is the Axum (Rust) integration for the apcore AI-Perceivable Core ecosystem. It exposes Axum routes as apcore modules via automatic scanning, with full execution, context mapping, and MCP serving support.
Reference implementation: ../fastapi-apcore (Python/FastAPI)
Core SDK: ../apcore-rust
Toolkit: ../apcore-toolkit-rust
- Prioritize simplicity, readability, and maintainability above all.
- Avoid premature abstraction, optimization, or over-engineering.
- Code should be understandable in ≤10 seconds; favor straightforward over clever.
- Always follow: Understand → Plan → Implement minimally → Test/Validate → Commit.
- Use precise, full-word names; standard abbreviations only when idiomatic (
buf,cfg,ctx). - Functions ≤50 lines, single responsibility, verb-named (
parse_request,build_schema). - Avoid obscure tricks, overly chained iterators, unnecessary macros, or excessive generics.
- Break complex logic into small, well-named helper functions.
- Provide explicit types on all public items; do not rely on inference for public API surfaces.
- Prefer
structover raw tuples for anything with more than 2 fields. - Use
enumfor exhaustive variants; avoid stringly-typed logic. - Implement
serde::Serialize/serde::Deserializeon all public data types.
- Favor composition over inheritance; use
traitonly for true behavioral interfaces. - Prefer plain functions + data structs; minimize trait object (
dyn Trait) indirection. - No circular module dependencies.
- Keep
pubsurface minimal — default to module-private, expose only what consumers need.
- Define domain errors with
thiserror; no bareBox<dyn Error>in library code. - Propagate errors with
?; nounwrap()/expect()in library paths (tests excepted). - Validate and sanitize all public inputs at crate boundaries.
- Runtime: Tokio (
features = ["full"]). - Traits with async methods: use
async-trait.
- Use
tracing— noprintln!/eprintln!in production code.
- Run with:
cargo test --all-features - Unit tests: in the same file under
#[cfg(test)] mod tests { ... }. - Test names:
test_<unit>_<behavior>(e.g.,test_scan_with_include_filter). - Never change production code without adding or updating corresponding tests.
- JSON:
serde_json. YAML:serde_yaml.
| Command | Purpose |
|---|---|
cargo fmt --all -- --check |
Formatting |
cargo clippy --all-targets --all-features -- -D warnings |
Lint |
cargo build --all-features |
Full build |
cargo test --all-features |
Tests |
cargo build --examples |
Example build |
| Rust Module | FastAPI Module | Purpose |
|---|---|---|
client |
client.py |
AxumApcore unified entry point |
config |
engine/config.py |
ApcoreSettings from APCORE_* env vars |
context |
engine/context.py |
ApContext extractor + AxumContextFactory |
scanner/native |
scanners/native.py |
Route metadata registry scanning |
scanner/openapi |
scanners/openapi.py |
utoipa OpenAPI spec scanning |
engine/registry |
engine/registry.py |
Singleton Registry/Executor management |
engine/extensions |
engine/extensions.py |
Discoverer + ModuleValidator |
engine/observability |
engine/observability.py |
Tracing/metrics/logging setup |
engine/tasks |
engine/tasks.py |
Async task management |
output/registry_writer |
output/registry_writer.py |
ScannedModule → Registry registration |
cli |
cli.py |
clap CLI (scan/serve/export/tasks) |
- Native scanner uses a metadata registry (not Router introspection) because Axum's Router is type-erased. The
ap_handler!macro populates metadata at compile time. - OpenAPI scanner relies on external utoipa-generated specs (compile-time generation).
- Context extraction uses Axum's
FromRequestPartstrait for ergonomicApContextextractors. - Singleton management uses
OnceLockfor thread-safe lazy initialization.
- Evaluate necessity before adding a new dependency.
- Dev-only crates go in
[dev-dependencies], never[dependencies].
- English only for all code, comments, doc comments, error messages, and commit messages.
- Fully understand surrounding code before making changes.