Work in progress. Lembos is pre-1.0. Follow along.

Know what is running.
And what should be.

Lembos is an internal developer platform built on versioned building blocks. It records the software you have and the shape it should take in every environment, observes what is actually there, and closes the gap between the two.

portal.lembos.dev
The Lembos Portal listing business domains, each with its type, parent, owner and status.

The Portal, showing the catalog of a sample retailer the platform seeds in development.

What it is

Not only a portal. Not only a catalog.

Lembos is the system that controls how software is deployed, configured and governed. A portal is how people reach it, and a catalog is part of what it knows — neither is the thing itself.

A catalog says

this component exists, and this team owns it.

A pipeline says

this ran, and it exited zero.

Lembos says

this is what should be running here, this is what is, and here is what closes the difference.

The catalog is purely definitional. It holds declarations and never runtime facts. That boundary is what lets one component run a different version in every place it runs, with the per-environment truth living on a runtime instance instead of forcing the catalog to describe every case.

The idea underneath

Every building block is an entity plus immutable revisions

The entity is what everything names. The revision is what a deployment pins. Blueprints, configuration, API contracts, policies and environments all work this way, which is what makes the rest of the platform expressible rather than aspirational.

Reproducibility
A published revision cannot change under anything pinned to it, so replaying a deployment a month later produces the same result.
Divergence on purpose
Staging a version ahead, a canary stamp on a newer artifact, a region on an older blueprint — environments differing is progressive delivery, not a failure to converge.
One question, one answer
“Which version is in effect here” means the same thing whether the block is a blueprint, a configuration, an API contract, a policy or a workload declaration.

platform/helm-web-service

Blueprint · Helm

  • 2.5.0-rc.1Draft
  • 2.4.0currentPublished
  • 2.3.0Withdrawn
  • 2.2.0Deprecated

pinned digest bd0c1a09b788bca1e93c18ae5b04aa86cdceb202

One status machine across every versioned thing. Draft is part of it, so everything has somewhere to sit before it is live — and a version whose artifact cannot be fetched is never handed out.

Convergence

Lembos converges rather than merely deploys

Recording current state alone answers “what is running” but not “is that what we asked for” — which is precisely the question when a configuration was published and never deployed, a rollout half-completed, or someone edited a cluster by hand.

Desired state

What was declared and published

artifact
cart-service@sha256:9f2c…
blueprint
helm-web-service 2.4.0
config
revision 17
replicas
6
drift

Observed state

What the execution target reports

artifact
cart-service@sha256:9f2c…
blueprint
helm-web-service 2.2.0
config
revision 15
replicas
6

Every building block records both what should be running and what is. The difference between the two is drift, and closing it is the work. Automated deployment is one way to close it. Reconciliation, rollback and progressive rollout are others.

The model

Five modules, each an invariant boundary

Aggregates inside a module enforce rules over each other. Anything across a boundary is referenced rather than navigated to. Read them in order: what software exists, what it is delivered with, how it gets there, whether it may, and who is involved.

Catalog

What software exists, and how is it related?

BusinessDomainSoftwareSystemComponentApiResource

Infrastructure

What is it delivered with?

BlueprintExecutionTargetArtifact

Delivery

How does a declaration become running software?

InstanceSpecEnvironmentRuntimeInstanceDeploymentRelease

Governance

Should this happen?

PolicyPolicyVersionAuditLog

Organization

Who is involved, and what may they do?

UserGroupRolePermission

The whole model

Aggregates, lifecycles, behaviours and the events they raise — documented per module and kept current with the code.

Read the domain docs

Typed by contract, not by label

A component or resource declares the blueprint that defines it, so “what is this thing” resolves to a shape the platform can act on rather than a string someone typed. What each entity provides, consumes and depends on is held as references, so the graph can be traversed without loading half the catalog.

portal.lembos.dev
A component page in the Portal showing its blueprint, owner and a relations graph of what it consumes and depends on.

Capabilities

What the platform carries

Each of these is a feature of the model rather than an integration sitting beside it.

Software catalog

Business domains nest into a validated ladder; systems group the components, APIs and resources that form a capability. Purely definitional — declarations, never runtime facts.

Configuration management

Immutable, content-hashed revisions pinned per runtime instance, layered system → component → environment → stamp. Secrets referenced by vault path, never carried.

Infrastructure orchestration

Blueprints pin their provisioner and source, and are only offered once confirmed fetchable. A version that cannot be retrieved is never handed out and then failed on.

Environments and stamps

An environment subdivides into stamps — per country for residency, per region for latency — and the workload declares how many it occupies. Ephemeral ones carry a lease and expire.

Progressive delivery

Traffic weights, analysis windows and abort thresholds are blueprint parameters, not control-plane assertions. A promotion names a stamp scope, so a geographic wave is an ordered sequence.

Rollback as its own transition

A rollback is a distinct kind of event from deploying an older artifact, because policy has to tell them apart — a rollback frequently bypasses gates a forward deployment must pass.

Release provenance

A release freezes its contents when it is ready and records every promotion, so “in which environments was this version tested before production?” has an answer.

Policy that can be reconstructed

An evaluation pins the exact policy version it enforced, so a later edit cannot silently rewrite what was applied. Policy is evaluated before dispatch, not audited after it lands.

Audit by construction

Every domain event is persisted as an audit entry unconditionally, whether or not anything reacts to it. The trail is a property of the model, not a feature bolted beside it.

Feature by feature, each mapped to the module that carries it — What Lembos does.

Guardrails

Access control is three layers, not one

Each answers a different question, and collapsing them into one mechanism fails whichever mechanism is chosen. RBAC alone cannot express “production is restricted to a few people while anyone may create a dev environment”.

  1. 01

    Permission

    May this principal do this class of thing?

    Flat RBAC, carried as claims. Cheap, and invertible — “who may deploy” is a role query.

  2. 02

    Ownership

    Do they reach this particular entity?

    Group membership, inherited down the hierarchy, so a member of a parent group reaches what its children own.

  3. 03

    Policy

    Is this specific intent allowed right now?

    Conditions on facts, evaluated at the moment of the request against a pinned policy version.

And work only routes where it can run

Execution targets declare capabilities, and intent is matched against them before anything is dispatched. Adding a runtime surface means adding a target, not changing orchestration logic.

checkout/cart-servicerequirespci-dss
  • platform/aws-production

    eligible
    hardened-runtimebackup-enabledpci-dss
  • platform/aws-nonproduction

    not eligible
    no capabilities declared

How it is used

Three people, one system of record

Lembos is adopted by a whole engineering organisation rather than by one team, because the three questions below are usually answered by three different systems that disagree with each other.

A developer

“I need this service running in staging.”

Declares the component against a blueprint and names where it belongs. The configuration layers resolve, policy is evaluated, and the work is dispatched.

Because The blueprint already carries the chart, the traffic weights and the dashboards — none of the runtime has to be learned to use it.

A platform engineer

“I need to change how every service is deployed.”

Publishes a new blueprint version. Nothing pinned to the old one moves until its owner moves it, and where each version is in force stays visible.

Because Versions are immutable and pinned, so the golden path can change without a synchronised migration across every team at once.

Security and compliance

“Show me what was running in production in March.”

Reads the release, the promotions that carried it, and the policy version that was evaluated at the time.

Because Every domain event is persisted as an audit entry unconditionally, and an evaluation pins the exact policy version it enforced.

What that looks like in practice

A review environment that cleans itself up

Ephemeral environments carry a lease and a TTL, so a pull-request environment expires on its own instead of accruing cost until someone notices.

A payment provider that differs per country

A stamp-layer override, not a reason to fork the component or duplicate the environment. The narrowest layer wins and the rest is shared.

A regulated workload that cannot land anywhere

The component requires a capability; only execution targets declaring it are eligible. Policy is evaluated before dispatch, not audited after it lands.

Germany before France, with a look in between

A promotion names a stamp scope, so a geographic wave is an ordered sequence of promotions with a human able to check between them.

What you operate

A platform you run yourself

There is no hosted Lembos. It is one .NET solution composed by Aspire — an orchestrator behind a single GraphQL endpoint, an identity server, a worker running durable workflows, and the Portal — provisioning into execution targets you own.

.NET 10

Every service

Aspire

Composition and local run

HotChocolate

The GraphQL surface

Temporal

Durable workflows

PostgreSQL

Persistence, via EF Core

OpenIddict

Identity and tokens

Blazor + MudBlazor

The Portal

YARP

The gateway

OpenTelemetry

Traces, metrics, logs

Redis

Cache and subscriptions

Running it today means running the solution itself — the repository covers that. A packaged install, the chart that turns this into a platform your organisation operates, is still ahead of it, and the configuration is already shaped for it.

The reasoning is in the open too

Decision records state why the architecture is the way it is, one document per decision. Enhancement proposals hold the changes not yet decided. Both are in the repository, and both take comments.

Questions, or interested in contributing? [email protected]