Architecture
Maekon follows Hexagonal Architecture (Ports & Adapters). The core (maekon-core) defines all traits and domain models; every other crate is an adapter implementing those ports.
Workspace layout
clients/maekon-client/
├── src-tauri/ # Tauri v2 main binary (package: maekon-app)
└── crates/
├── maekon-core # Port traits + domain models + error codes
├── maekon-network # JWT auth, HTTP/SSE, gRPC, batch upload
├── maekon-storage # SQLite (WAL) + schema migrations
├── maekon-monitor # System metrics, active window, idle detection
├── maekon-vision # Screen capture, delta encoding, OCR, PII filter
├── maekon-suggestion # SSE/gRPC reception, priority queue, feedback
├── maekon-automation # Policy-based command execution + audit
├── maekon-analysis # LLM segment summarization, vector RAG
├── maekon-embedding # INT8 quantization, similarity search
├── maekon-audio # cpal capture + Whisper STT
├── maekon-web # Local Axum dashboard + React frontend
├── maekon-api-contracts # Shared API types
├── maekon-sandbox-worker # Out-of-process action executor
└── maekon-lint # Workspace lint tool (standalone)
The dependency rule
maekon-core ← every adapter (one-way)
Adapters never depend on each other. All cross-crate communication goes through traits defined in maekon-core. This is the core invariant — see ADR-001 §1.
Key invariants
- All port traits use
&self(not&mut self); implementations needing mutable state use interior mutability (Mutex,RwLock,parking_lot) #[async_trait]on every port — required forArc<dyn Trait>DI- Manual mock implementations in
#[cfg(test)] mod tests— nomockall - Error strategy:
thiserrorin libraries,anyhowin the binary, all wrapped via#[from] - Error code field on every
CoreErrorvariant (ADR-019) — current wire snapshot is 42 codes
Image processing pipeline
Screen frames go through a 4-tier importance branching (maekon-vision::EdgeFrameProcessor):
| Importance | Pipeline |
|---|---|
| ≥ 0.8 | Full + OCR |
| ≥ 0.5 | Delta encoding |
| ≥ 0.3 | Thumbnail |
| < 0.3 | Metadata only |
PII filter runs before any image leaves the device — phone, API key, IP, email, credit card, SSN, file path masking with a 4-level cascade (Off / Basic / Standard / Strict).
Architecture Decisions
The full ADR series is documented inline. Each ADR captures one design decision the Rust compiler cannot enforce, along with the context, alternatives considered, and consequences.
| ADR | Title |
|---|---|
| ADR-001 | Rust Client Architecture Patterns |
| ADR-002 | OS GUI Interaction Boundary and Runtime Split |
| ADR-003 | Directory Module Pattern for Large Source Files |
| ADR-004 | Tauri v2 Migration |
| ADR-005 | Tauri v2 Governance |
| ADR-006 | Tauri IPC Command Contract |
| ADR-007 | Async Runtime Safety Patterns |
| ADR-008 | Network Resilience Patterns |
| ADR-009 | Client Architecture Baseline |
| ADR-010 | Local Integration Harness Boundary |
| ADR-011 | Standalone Analysis Pipeline |
| ADR-012 | Adaptive Tiered Memory |
| ADR-013 | LLM Segment Summary + Vector RAG |
| ADR-014 | Tauri Managed State Boundary |
| ADR-015 | Frame Storage Port Abstraction |
| ADR-016 | Config Change Bus |
| ADR-017 | FeedbackSignalSink |
| ADR-018 | RegimeManager Persistence |
| ADR-019 | Error Code Infrastructure |
The same files live under docs/architecture/ in the source repository — the Docs site is the rendered, link-rewritten version.