Runtime View
The Runtime View describes the dynamic behavior of the system, illustrating how components interact during execution.
6.1 Litestar (HTTP Server Lifecycle)
| Step | Action |
|---|---|
| Bootstrap | Build the dependency-injector Container with all discovered modules and settings. |
| Lifespan | Startup: Shared services (SQL database, NATS, Redis) are initialized from the DI container. |
| Request Flow | Dispatch incoming HTTP request → Service Layer (provided by DI) → Repository → Controller hooks → Response. |
6.2 CLI Command Runtime
秉
秉
6.3 Background Jobs (Taskiq Flow)
Background jobs use the same DI container mechanism as HTTP and CLI contexts, ensuring consistent logic across all environments.
秉
秉
6.4 DocType Lifecycle Hooks
The runtime execution flow for saving a DocType:
秉
秉
- Controller.validate() (Business rule validation)
- Controller.before_save() (Pre-persistence processing)
- Repository.save() (Persistence to Database)
- Controller.after_save() (Post-persistence side-effects, e.g., Event emission)
- Response
6.5 ASGI Middleware Pipeline
Incoming HTTP requests flow through the MiddlewareRegistry in priority order (lower priority runs first / outer layer).
| Priority | Middleware | Responsibility |
|---|---|---|
| 10 | RateLimitMiddleware | Drops abuse traffic before request parsing. |
| 15 | PayloadDecryptionMiddleware | Decrypts application/jose or application/x-encrypted-json bodies before CSRF, idempotency, auth, and route handlers see the request. |
| 20 | CSRFMiddleware | Validates origin and double-submit cookie. |
| 30 | IdempotencyMiddleware | Manages duplicate request keys. |
| 50 | AuthMiddleware | Runs the AuthChain (Session, Bearer, Header). |
| 55 | FederatedRedirectMiddleware | Redirects unauthenticated federated sessions. |
| 60 | LocaleResolutionMiddleware | Injects i18n locale context. |
| 200 | MetricsMiddleware | Observability and latency tracing. |
INCOMING REQUEST
│
▼
┌─────────────────────┐
│ Rate Limit (10) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Payload Decryption │ ← application/jose → cleartext JSON
│ (15) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ CSRF / Idempotency │
│ (20 - 30) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Auth (50) │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Route Handler │
└─────────────────────┘
Placing PayloadDecryptionMiddleware at priority 15 ensures encrypted authentication payloads are decrypted before AuthMiddleware (priority 50) and route DTO validation run, while abusive traffic is still dropped early by rate limiting.
6.6 Zero-Trust Outbox Sealing & Ingress Verification Runtime
For distributed nodes and tamper-proof ledger DocTypes:
EDGE NODE CENTRAL INGRESS CLUSTER
┌──────────────────────────────┐ ┌───────────────────────────────────┐
│ 1. Controller before_insert │ │ IngressVerificationService │
│ - Compute RFC 8785 hash │ │ 1. O(1) Key Active/Revoked Check │
│ - Dual-sign (WebAuthn │ │ (Drops revoked keys instant) │
│ + Node KeyProvider) │ │ 2. Sequence Watermark Pre-check │
│ - Chained prev_hash │ │ 3. Canonical hash verification │
│ 2. OutboxWorker polls DB │ │ 4. Ed25519 & WebAuthn P-256 verify│
│ 3. Dispatches signed envelope│ ──── NATS/HTTP ──>│ 5. Commit to Central Ledger │
└──────────────────────────────┘ │ (Or route to _quarantine_dlq) │
└───────────────────────────────────┘
- Edge Sealing: Changes to tamper-proof DocTypes compute a deterministic SHA-256 digest over JCS canonicalized fields, linked to the
prev_hashof the sequence stream. Envelopes carry the producing node'snode_signature(viaKeyProviderProtocol) and, when the application attaches one, the operator'soperator_signature. There is nonode_signordual_signDocType flag — sealing happens in the application's write path (see the notes below). - Central Ingress: Incoming envelopes enter a fast-reject pipeline. Inactive/revoked keys and duplicate sequences are rejected before running asymmetric cryptography, preventing CPU exhaustion.
Who calls IngressVerificationService.verify_envelope()
Framework M ships no node-to-node transport. The edge → central sync (NATS, HTTP, file drop, replication — your choice) is application territory, so there is no default call site and nothing in the framework invokes the verifier on your behalf.
Call it in the code that receives a synced envelope, before persisting or dispatching it:
# Your edge -> central sync consumer (NATS handler, HTTP endpoint, importer...)
from framework_m_standard.services.ingress_verification_service import (
IngressVerificationService,
)
verifier = IngressVerificationService(key_registry, sequence_tracker)
result = await verifier.verify_envelope(incoming_entry)
if not result.valid:
... # your policy: drop, divert to _quarantine_dlq, or alert
| Envelope origin | Verify? | Why |
|---|---|---|
| Received from another node | Yes | Proves the sending node's identity and sequence continuity |
| Produced by this node | No | The signature is checked against the same key that made it — it always passes, and the verification is theatre |
Do not call it from DbEventBus or process_outbox: those consume envelopes this node produced.
On operator (dual) signatures
There is deliberately no dual_sign flag in Meta. A class-level boolean is copied by anyone — or any code generator — scaffolding a new DocType, and if it leaked onto OutboxEntry, every background write would demand a human signature and the application would stop running. No authenticator is present at 3 a.m.
Operator signatures are therefore an explicit call where a human actually is:
from framework_m_core.crypto.dual_signature import verify_dual_envelope
if not verify_dual_envelope(
payload_hash=payload_hash,
node_sig=node_signature,
node_pubkey=node_public_key,
operator_sig=assertion.signature, # from POST /webauthn/verify
operator_pubkey=operator_record.public_key_bytes,
):
... # refuse the write
verify_dual_envelope() accepts Ed25519 node keys and both Ed25519 and ECDSA P-256 operator keys, so FIDO2 authenticators (TouchID, YubiKey, Secure Enclave) work without server-side secrets. IngressVerificationService runs the same operator check automatically when an incoming envelope carries operator_signature.
Naming note.
IngressVerificationServiceis unrelated to a Kubernetes Ingress Controller, and itsoperatormeans a human cashier, not a Kubernetes operator. It verifies envelopes arriving from other nodes; it does not route HTTP traffic.
6.7 Frontend & MFE Lifecycle (The Browser)
The frontend application (The Desk) follows a two-stage composition process to unify the core framework with modular plugins.
秉
秉
Stage 1: Build-Time Composition
- Vite Scanner: The
framework-m-vite-pluginscans the repository forpackage.jsonfiles with theframework-mmetadata. - Virtual Module Generation: A virtual module (
virtual:framework-m-plugins) is generated, containing dynamic imports for the detected plugins. - Monolith vs. MFE: Depending on configuration, Vite either optimizes these into a single shared bundle or produces separate JS entry-points for distributed loading.
Stage 2: Runtime Execution (Boot)
| Step | Action |
|---|---|
| Shell Init | The Browser loads the Shell. The PluginSDK initializes the global PluginRegistry. |
| Plugin Discovery | Registry iterates over the virtual module and registers each plugin. |
| Composition | Refine.dev resources, Sidebar menus, and React Router paths are merged from all registered plugins. |
| Authentication | authProvider verifies the backend session/JWT. If valid, the Desk UI is rendered. |
| Hydration | The UI uses the frameworkMDataProvider to fetch DocType metadata and records from Litestar. |
| Live Updates | liveProvider opens a WebSocket connection to the backend for real-time JetStream notifications. |