Skip to main content

Runtime View

The Runtime View describes the dynamic behavior of the system, illustrating how components interact during execution.

6.1 Litestar (HTTP Server Lifecycle)​

StepAction
BootstrapBuild the dependency-injector Container with all discovered modules and settings.
LifespanStartup: Shared services (SQL database, NATS, Redis) are initialized from the DI container.
Request FlowDispatch incoming HTTP request → Service Layer (provided by DI) → Repository → Controller hooks → Response.

6.2 CLI Command Runtime​

秉 CLI Runtime Flow 秉

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.

秉 Background Job Runtime Flow 秉

6.4 DocType Lifecycle Hooks​

The runtime execution flow for saving a DocType:

秉 DocType Save Lifecycle 秉

  1. Controller.validate() (Business rule validation)
  2. Controller.before_save() (Pre-persistence processing)
  3. Repository.save() (Persistence to Database)
  4. Controller.after_save() (Post-persistence side-effects, e.g., Event emission)
  5. Response

6.5 ASGI Middleware Pipeline​

Incoming HTTP requests flow through the MiddlewareRegistry in priority order (lower priority runs first / outer layer).

PriorityMiddlewareResponsibility
10RateLimitMiddlewareDrops abuse traffic before request parsing.
15PayloadDecryptionMiddlewareDecrypts application/jose or application/x-encrypted-json bodies before CSRF, idempotency, auth, and route handlers see the request.
20CSRFMiddlewareValidates origin and double-submit cookie.
30IdempotencyMiddlewareManages duplicate request keys.
50AuthMiddlewareRuns the AuthChain (Session, Bearer, Header).
55FederatedRedirectMiddlewareRedirects unauthenticated federated sessions.
60LocaleResolutionMiddlewareInjects i18n locale context.
200MetricsMiddlewareObservability 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) │
└───────────────────────────────────┘
  1. Edge Sealing: Changes to tamper-proof DocTypes compute a deterministic SHA-256 digest over JCS canonicalized fields, linked to the prev_hash of the sequence stream. Envelopes carry the producing node's node_signature (via KeyProviderProtocol) and, when the application attaches one, the operator's operator_signature. There is no node_sign or dual_sign DocType flag — sealing happens in the application's write path (see the notes below).
  2. 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 originVerify?Why
Received from another nodeYesProves the sending node's identity and sequence continuity
Produced by this nodeNoThe 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. IngressVerificationService is unrelated to a Kubernetes Ingress Controller, and its operator means 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.

秉 Frontend & MFE Composition 秉

Stage 1: Build-Time Composition​

  1. Vite Scanner: The framework-m-vite-plugin scans the repository for package.json files with the framework-m metadata.
  2. Virtual Module Generation: A virtual module (virtual:framework-m-plugins) is generated, containing dynamic imports for the detected plugins.
  3. 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)​

StepAction
Shell InitThe Browser loads the Shell. The PluginSDK initializes the global PluginRegistry.
Plugin DiscoveryRegistry iterates over the virtual module and registers each plugin.
CompositionRefine.dev resources, Sidebar menus, and React Router paths are merged from all registered plugins.
AuthenticationauthProvider verifies the backend session/JWT. If valid, the Desk UI is rendered.
HydrationThe UI uses the frameworkMDataProvider to fetch DocType metadata and records from Litestar.
Live UpdatesliveProvider opens a WebSocket connection to the backend for real-time JetStream notifications.