This page is for the engineers who will live with this platform — the ones who own production, sign off on architecture reviews, and inherit the codebase. We will not soften anything for marketing here.
What follows is the truth about how Clever Initiative is engineered: the layering, the data isolation guarantees, the runtime module loading, the security model, the test discipline, and the operational shape. Every claim below is enforced in code, in CI, or in a hard boundary that cannot be silently crossed.
These rules are non-negotiable. Each one is enforced in code review, in CI, or by the type system.
Domain ← Application ← Infrastructure ← API. Inner layers never reference outer. Adding a using of an outer layer in an inner project is a compile-time bug, not a shortcut.
Commands change state. Queries read state. They flow through separate pipelines (Logging → Validation → CacheInvalidation → Transaction). One handler per operation, validators co-located.
Result and Result<T> for every expected failure. Domain exceptions for invariant violations. No throw new Exception ever. Failure paths are explicit and typed.
Zero exceptions on every read. No tracked entities returned to controllers. No N+1. Every list endpoint returns PagedResult<T> with pageSize capped at 100.
Permissions are checked twice — at the controller via [HasPermission] and inside the handler via IPermissionService. Passing the controller alone is not sufficient.
Architectural commitment, not a configuration flag. Each tenant gets its own SQL Server database. AES-256-encrypted connection strings stored in the host database. Zero shared rows.
Cross-process events are written into the same DB transaction as the state change. A worker publishes them via MassTransit + RabbitMQ. At-least-once delivery. Consumers idempotent by design.
Passwords, tokens, OTP codes, connection strings, mandate refs, card last-fours, raw webhook bodies — never logged at any level. The payment-gateways module ships its own ILogScrubber for this reason.
Every numeric or string limit in a validator references DomainConstants.*. New limit groups become a nested static class. No 100, 255, or 4096 ever inlined.
dotnet build and ng build both exit with 0 errors and 0 warnings. dotnet test CleverInit.slnx exits with 0 failed. Anything less is incomplete work, not a partial victory.
The dependency arrows in the diagram below are enforced at the project-reference level. Cross them and the build fails — there is no convention-only layer policing here.
Every command flows through this pipeline. Queries skip the transaction step.
Database-per-tenant is an architectural commitment, not a configuration option. Each tenant gets its own SQL Server database. There are no shared tables and no row-level filters substituting for real isolation.
On every request, the platform identifies which tenant the request belongs to via this fallback chain. Resolution happens once per request, in middleware ordered after authentication so the JWT claim is available.
Authentication and authorization are layered. Every request passes through both, and authorization is checked twice — at the HTTP boundary and again in the handler.
Never username. Forms, models, error messages, and tests all match. Lockout after 5 failed attempts.
HMAC-SHA256, carries the user's full permission set as a string-array claim. Authorization decisions are O(1) in-memory lookups — zero DB hits per request.
Random 256-bit, persisted in the database, rotated on use. Compromise window is bounded; refresh tokens can be revoked at any time.
≈ 100 ms per hash on production hardware. Tuned to stay slow as Moore's law advances; cost is reviewed annually.
OTP delivered via email or SMS, configurable per tenant. Otp.NET implementation; OTP codes never logged.
[HasPermission("Foo.Bar")] on the controller AND permissionService.HasAsync(...) re-checked in the handler. Permission strings must match the seeder exactly — wrong strings make actions silently invisible.
Business operations that span system boundaries — sending a welcome email, provisioning a module database, notifying a third-party webhook — are dispatched through events. The platform never makes a synchronous call to an external service in the request path.
Modules ship as signed .tar.gz artifacts. The host loads each module's assemblies into a private AssemblyLoadContext. Tenants install modules independently into their own dedicated databases. No host redeploy is required to make a new module available, and no host redeploy is required when a tenant installs one.
A module developer runs the marketplace publish pipeline; out comes a signed {slug}-{version}.tar.gz. The artifact is dropped into the host's Modules:RootPath. On first request that needs the slug, the host verifies the RSA-4096 signature, extracts the artifact, loads its assemblies into a private ALC, and registers the manifest. The module becomes available for tenants to install. No tenant starts using it yet.
A tenant admin clicks Install on the marketplace page. The platform writes a TenantModule row, runs the module's migrations against the tenant's dedicated database, seeds the module's permissions for that tenant, fires an integration event, and the feature becomes live for that tenant's users on their next request. Installation does not load any new code — that already happened at publish time.
The admin panel is intentionally on the latest Angular stable. Every architectural decision pushes toward signal-based reactivity and OnPush change detection.
provideZonelessChangeDetection() is active. zone.js is never imported. Change detection is driven entirely by signals.
Every component is standalone with ChangeDetectionStrategy.OnPush. @if / @for / @switch only — never *ngIf / *ngFor / *ngSwitch. No NgModules anywhere.
Feature stores scoped via providers: [Store] on the host component — never providedIn: 'root'. Only LayoutStore and AuthStore are intentional global singletons.
Every UI primitive — page header, filter card, table, modal, form input, save button, empty state, loading — is a ci-* component from @cleverinit/panel-shared. Hand-rolling a kt-input is a PR-blocking violation.
Each module's frontend is a federation remote that exposes exactly one thing: a routes.ts. Routes are mounted under /m/<slug>/... by the host. Every @angular/* package is exact-pinned to the host's identical version.
Vitest for unit tests with flushEffects() in zoneless mode. Playwright for E2E. Karma, Jasmine, and Jest are explicitly forbidden.
Versions are pinned. Adding a new library requires explicit approval. Below is what is in the solution today.
Every commit must clear these gates. CI enforces what review cannot, and review enforces what CI cannot.
dotnet build CleverInit.slnx, ng build --configuration=production, npm run lint — all exit clean. A warning is incomplete work.
dotnet test CleverInit.slnx executes the entire backend test pyramid on every commit. Coverage targets: Domain >95%, Application >85%, Infrastructure >70%, API >70%.
Vitest for components, services, and stores. Playwright for end-to-end journeys. flushEffects() after every state change in zoneless mode.
Every module ships a parity test that fails the build if a controller demands a permission missing from module.json. Wrong strings cannot ship past CI.
Every significant state change is captured automatically — before/after values, who, when, IP. Sensitive fields are excluded by allow-list. Audit rows are immutable once written.
Domain exceptions map to typed problem responses: ValidationException → 400 + field-level errors, EntityNotFound → 404, Duplicate → 409, BusinessRuleViolation → 422. detail strings are complete sentences in plain language — never class names, never SQL fragments.
Operations are deliberate. The signing pipeline is the most operationally sensitive part of the platform — it gates every module that loads in production.
Local development runs on docker-compose; production runs on Azure Kubernetes Service. Health checks, readiness probes, and graceful shutdown are first-class.
Per-repo workflows for api, panel, and modules. Modules use a reusable workflow that builds, signs, and publishes the artifact in a single deterministic step.
Every module artifact is signed with a private key held only in repository secrets. The host verifies signatures with the public key bundled in CleverInit.ModuleHost.Lifecycle.ArtifactSignatureVerifier. Unsigned artifacts will not load in production.
On a v* tag push, the workflow asserts module.json:version matches the tag exactly. A mismatch fails the build with a clear error. The version bump is part of the same PR as the schema migration that requires it.
Every entity or configuration change ships an EF migration in the same commit. Migrations are append-only after release — never edited, only superseded by a new migration.
Structured logging via Microsoft.Extensions.Logging. PII / secrets / OTP / webhook bodies excluded by ILogScrubber. Correlation IDs propagated through MediatR pipeline and MassTransit consumers.
Architecture deep-dives, security questionnaires, performance characteristics, integration design — we are happy to go further than this page does.
Tell us where you want to take your business. We'll show you the fastest path to get there — whether you want a fully managed platform, the source code in your hands, or a fully branded product to sell to your own clients.