
Open-sourced and graded against 34 categories
Why I open-sourced a production .NET framework and scored it against a 34-category architecture rubric, gaps and all.
Writing
A long-form series that turns the MMCA framework's architecture decisions into teachable patterns, every claim grounded in real source. Read in order it is a curriculum: the first few orient you, the middle ones cover the core patterns, data, and the API edge, and the last group is proof and getting started.
The series is rolling out on Medium. Titles and summaries are below; each "Read on Medium" link activates as that piece publishes.

Why I open-sourced a production .NET framework and scored it against a 34-category architecture rubric, gaps and all.

The cornerstone idea: build the monolith now and extract a service later with no rewrite, via module discovery, gRPC contracts, and a YARP gateway.

A two-axis rubric for scoring architecture on maturity and implementation, so 'good architecture' stops being a vibe.

Model expected failures as Result values with a transport-agnostic error type, and keep exceptions for the genuinely exceptional.

Push behavior into rich aggregates with factory methods and invariants instead of bags of public setters.

Compose queries from reusable specification objects instead of scattering LINQ across handlers.

Thin command and query handlers wrapped by a Scrutor decorator chain whose order is load-bearing.

A validation kit that composes FluentValidation rules instead of copy-pasting them across features.

Events that survive a crash: persist them atomically with your data, then dispatch at least once.

Give each module its own database and outbox before you extract it, so extraction changes hosting, not data.

SQL Server, Cosmos, and SQLite behind a single entity model, with the engine chosen by attribute.

Eager-load relationships that cross containers and data sources without N+1 or a leaky abstraction.

Carry the RowVersion from database to DTO and back, so a concurrent edit fails fast as a conflict instead of silently overwriting.

Modules declare their dependencies and load in topological order, so registration is never hand-sequenced.

Every integration event carries a schema version; breaking changes get a new event type and an upcaster, never a silent reshape.

Validate another service's RS256 tokens via JWKS discovery, with no shared secret crossing a boundary.

The non-negotiables of password storage in .NET, done correctly and tested.

Dedup client retries with an Idempotency-Key header and cached replay, plus a consumer-side inbox for brokers.

A caching decorator where commands invalidate and queries populate, plus an authenticated output-cache tier at the API edge.

One error contract mapped consistently to HTTP Problem Details and gRPC status.

A notifications feature built as a clean vertical slice across every layer.

Sub-second ephemeral events (polls, Q&A, live counts) fanned out over the existing notification hub, with nothing persisted.

Why source-generated, per-entity mappers beat reflection-based mapping for clarity and speed.

A capability layer over RBAC: permission policies that resolve on demand from a central registry.

HttpOnly session cookies and an SSR-time scheme so [Authorize] passes during prerender, with the API still the boundary.

Sign in with Google or GitHub without leaking provider tokens: external identity exchanged for your own JWTs at the boundary.

A short-lived JWT plus one server-stored refresh token that rotates on every use, with reuse detection that makes a stolen token end its own session.

A write-once REST surface every entity inherits, plus a bounded dynamic query contract that is never open SQL.

Beyond roles and permissions: which rows you may touch, enforced per resource.

Two layers that cover the whole API edge: endpoint rate limits plus lockout-based brute-force defense on identity.

Model services, databases, and the broker as one Aspire graph that runs from laptop to Azure with one command.

A step-by-step extraction of an in-process module into its own gRPC service, database, and auth.

Standard resilience on every outbound client, plus declared RTO/RPO and a drilled restore.

Architecture rules that fail the build: a compile-time layer guard plus a shared NetArchTest rule library.

How the framework's tests stack up: fast unit and architecture tests at the base, E2E at the tip.

Soft-delete for lifecycle, anonymization plus outbox purge for GDPR/CCPA erasure, and why both exist.

A shared Blazor and MudBlazor UI layer with accessibility enforced by axe in CI.

A culture choice and a theme choice ride the same cookie, profile column, and login reconciliation: one persistence path, two switches.

A hands-on walkthrough of building a new module across all five layers.

Author your first architecture fitness test and watch it fail the build on a violation.

A case study: a conference platform and an e-commerce store built on the same kernel.

The same Blazor components run in a browser and inside a MAUI hybrid app; small per-capability contracts reach native hardware without ever asking 'am I on mobile?'.

Attacker-controlled bytes become safe avatars: content sniffing, metadata stripping, re-encoding, and pluggable blob storage.

Header-based versioning introduced without breaking a single caller, plus a fitness contract that proves two live versions coexist.

Gate commands and queries at the outermost decorator, so a handler never checks a flag and a disabled feature is rejected before any work runs.

An AES-256-GCM value converter that keeps a PII column ciphertext even for someone who can query the database.

One middleware stamps hardened response headers on every host, with the Blazor CSP resolved through a pluggable provider.

A shared OpenTelemetry baseline with CQRS duration metrics, correlation IDs, and outbox-poll span filtering, exported to Azure Monitor.

Undo as a first-class event handler: give back stock a committed transaction already took, with a periodic sweep as the saga-timeout backstop.

The full series index and recommended reading order.
One message per article, no digests and no other mail.