The Power of a Single Source of Truth
SEP 8, 2026
This experiment started with an uncomfortable question: if models, APIs, permissions, and interfaces describe the same business, why does none of them understand the whole system?

Not long ago, I tried to schedule a laboratory test through a website.
The process looked simple: choose the test, select a location, pay, and receive a confirmation. Instead, the site calculated subtotal = NaN, the API rejected the request, and I ended up on WhatsApp.
That was the entrance to a different system.
A button-based bot answered first. Then a person stepped in. To find which tests were available, they had to consult an Excel spreadsheet and send me screenshots. The appointment was checked manually, payment happened through Openpay, and the confirmation arrived more than an hour later.
The curious part is that almost nothing about this process was exceptional.
It had to identify tests, check availability, calculate a price, reserve a time slot, collect payment, and confirm the appointment. It was a mostly deterministic flow. Yet the knowledge required to complete it was scattered across a website, an API, a bot, spreadsheets, a payment gateway, and the memory of whoever was answering WhatsApp.
The visible problem was NaN.
The interesting problem was that, once one piece failed, none of the others knew how to continue the entire process.
A deterministic process, scattered across tools
The page failed. The business process fell apart with it.
Expected flow
- 01Test
- 02Location
- 03NaN
- 04Time slot
- 05Payment
- 06Confirmation
The system that appeared after NaN
The work was still mostly deterministic. What disappeared was the shared representation of the process.
Many representations, no single truth
That experience reminded me of something I have encountered for years while building business software.
We define an entity in the database. Then we create a schema to validate it, a DTO to transport it, and a route to modify it. We describe it again in OpenAPI, generate types for the client, implement permissions, and build a form. Later, auditing, integrations, jobs, and processes appear and need to interpret parts of everything above.
Every piece may be well designed.
Together, they often contain slightly different versions of the same business.
A table knows the columns of an order. The backend knows how to update it. The frontend knows which fields to display. The authorization system decides who may touch it. A workflow knows what to do when it is confirmed.
But where does the concept of an order actually live?
Usually, nowhere. It lives implicitly between all those pieces.
That is why changing one rule may require updating the model, validations, endpoints, permissions, types, and interface. Not because the business has six different rules, but because we expressed one rule six times through different abstractions.
Shared types help. Generated clients help. A monorepo helps too. None of those decisions, however, automatically turns distributed knowledge into a source of truth.
Types can ensure that everyone calls a field status. They cannot explain why an order can be confirmed, who is allowed to do it, which conditions must hold, or what it means when it happens.
Structure travels. Intent still gets lost.
The same order, two architectures
Where does the business rule actually live?
Database
status + paid_at
Validation
payment check
API
POST /confirm
Permissions
regional scope
Interface
Confirm button
Audit
status changed
One rule is reconstructed from six technical descriptions.
The source of truth comes before infrastructure
For the past few months, I have been working on a framework that started with one question:
What if infrastructure did not define the system, but was instead a projection of the domain?
That does not mean removing the database, hiding PostgreSQL behind an infinite abstraction, or turning every application into a Domain-Driven Design ceremony.
It means separating business concepts from the technologies used to materialize them.
An order is not a table.
Confirming an order is not a POST endpoint.
The ability to approve orders from one region is not middleware.
Those are domain concepts. The table, endpoint, and middleware are possible implementations of those concepts.
The framework tries to make that earlier layer explicit. The domain declares what exists, what can happen, what we need to ask, what happened, and under which rules an operation may run. From that semantics, different parts of the system can produce the representations they need.
Persistence needs tables. An API needs contracts. The interface needs fields and actions. Authorization needs resources and capabilities. Auditing needs to know which operation occurred and in what context.
They are not independent sources of truth. They are different views of the same operational reality.
Model actions, not screens
This change looks small until we stop designing the business around CRUD.
Businesses do not talk about update order.
An order is confirmed. An invoice is canceled. Evidence is approved. An asset is retired.
Every verb preserves intent. It may require permissions, validate invariants, produce events, or start a process that continues later. When everything is reduced to update(), that information becomes hidden across handlers, services, and conventions that the rest of the system has to guess.
That is why this proposal does not start with models alone. It also needs explicit actions.
A declaration could communicate that an asset exists and has a serial number, a status, and a location:
const Asset = defineModel({
id: "inventory.asset",
fields: {
serial: field.string({ unique: true, searchable: true }),
status: field.selection({
values: ["active", "maintenance", "retired"],
}),
location: field.relation("inventory.location"),
},
capabilities: {
auditable: true,
},
})
But that declaration should not be a table in disguise.
Its value lies in preserving enough meaning for a table, an API contract, audit metadata, or a base interface to be derived without becoming the origin of the concept.
The same applies to an action such as inventory.asset.retire. Its name matters, but it is not enough. The system should also understand its input, who can execute it, which conditions it protects, and which observable consequence it produces.
The goal is not to write less code at any cost. It is to keep the system's meaning from depending on reconstructing several fragments of code that were never designed to explain themselves to one another.
Decisions also exist before the code
The idea of a source of truth did not appear only inside the framework.
It also changed how we are designing the project that motivated it. Before discussing tables or screens, we started with something that is often relegated to a slide deck: mission, vision, and North Star.
We call them Idealities.
Not because a mission statement can generate an application, but because technical decisions need a direction that does not originate from whatever technology is convenient that week.
From there, knowledge moves through layers:
- Idealities explain the outcome we are pursuing;
- design documents turn that direction into product and system decisions;
- ADRs preserve architectural choices and their reasoning;
- the domain expresses the concepts and operations the software must understand;
- technical representations materialize that intent.
A chain of authority
The source of truth is not a magic file.
- 01IdealitiesWhy should this system exist?
- 02Design documentsWhat outcome and behavior do we need?
- 03ADRsWhich architectural decisions support it, and why?
- 04DomainWhat exists, what can happen, and under which rules?
- 05ProjectionsHow do database, API, permissions, and UI materialize it?
Each layer answers a different question and derives authority from the layer above it.
Code remains indispensable, but it is no longer the first place where we try to discover what we were building.
A source of truth is not necessarily a single file. It is an explicit chain of authority: every decision has a place, a reason, and representations that depend on it.
The dangerous part of this idea
Talking about a single source of truth can sound like the beginning of an abstraction that wants to control everything.
That possibility worries me as much as the original idea interests me.
Software history is full of tools that promised to make us independent from infrastructure and ended up creating infrastructure that was even harder to replace. A semantic layer can also become a new coupling point, hide important capabilities, or reduce different technologies to their lowest common denominator.
The framework should not prevent a specialized PostgreSQL query, a fully custom interface, or hand-written behavior when the domain needs it.
The abstraction must end where its knowledge ends.
Repetitive cases can be derived. Known capabilities can be composed. What is truly specific must still allow specific code.
For now, the project is exactly that: an experiment to discover where that boundary lies.
Why it has to be open
There is one more condition that is not negotiable for me: the framework's core must be open source.
If the premise is that the domain should remain stable while infrastructure can change, locking its definition inside a proprietary platform would contradict the entire goal.
There would be little point in escaping coupling to an ORM only to become coupled to the vendor that defines your business.
Making the core open source does not determine how everything built around it will be distributed. That discussion belongs at a different level. The important decision here is that the core semantics an organization uses to describe its domain remain open, inspectable, and extensible.
Many questions remain open.
How much semantics can be shared without creating a gigantic language? What should the framework validate, and what should remain with the runtime? When does a projection stop being useful and require a fully specialized implementation? How does a domain evolve without breaking everything derived from it?
Those questions are part of why I want to write this series while I build the framework, not after pretending it is finished.
The initial idea, at least, is concrete.
I want a company to be able to describe how it produces outcomes without confusing that description with the screens, tables, and services it happens to use today.
I want a rule to exist once as intent, with representations that can show where they came from.
I want the process to survive when one piece fails, as that laboratory website did.
The system should understand the business it is trying to operate.
It should not make us reconstruct it every time from a NaN, an Excel screenshot, and a WhatsApp conversation.