The Book · Chapter 16

From Architecture as Code to Executable Enterprise Architecture

The previous chapters established the semantic and governance foundations of the EA Codex. This chapter turns that foundation toward execution. It asks how architectural intent becomes usable by delivery systems, policy engines, catalogs, agents, and auditors. Build-time tests live in one tool, runtime policies in another, and the decisions and authorized variations that should bind them sit in catalogs and wikis that platform teams rarely open.

Those fragments live in separate systems. The chain from intent to enforcement is interrupted at every handoff. The missing object is the chain itself: a typed connection from enterprise intent through decisions, specifications, controls, and evidence.

This chapter names the operating model that connects them. It draws on three publicly available bodies of work: Architecture as Code (Ford and Richards) for the executable layer, Software Product Line engineering (Software Engineering Institute, SEI; Pohl, Böckle, van der Linden) for the discipline of commonality and authorized variation, and the EA Codex for the typed enterprise memory that binds them.

Figure 1 shows the three movements that combine into the executable-architecture stack: architecture as code, software product lines, and the EA Codex.

Architecture as Code, Software Product Lines, and the EA Codex assembled into one operating model.

Figure 1: Architecture as Code, Software Product Lines, and the EA Codex assembled into one operating model.

1. A story most architects have lived

Consider a familiar enterprise scene. Three years ago, a senior architect spent six weeks writing a forty-page architecture document for a new customer platform. It described the component boundaries, data flows, security posture, and a section called “Architectural Principles” that included one crucial rule: European Union personal data must never leave the EU region. The document was reviewed, approved, signed, and uploaded to the wiki.

Today, a platform engineer joins the team. The original architect left eighteen months ago. The platform has been rewritten twice. The team has not opened the wiki page in over a year. Last week, a developer added an analytics pipeline that streams customer events to a US-based vendor for cost reasons. Nobody noticed. The audit team did. Now there is a meeting on Friday, and everyone is looking for the document that says this should not have happened.

The document still existed, but the system no longer matched it. The system had changed faster than the architecture record could be updated, the architecture record carried no enforcement point of its own, the delivery pipeline kept no memory of the constraint it was supposed to honor, and the audit trail could no longer say when the divergence began.

This is not an unusual failure but a recurring enterprise pattern. Architectural decisions written only in prose, even good prose, decay faster than the systems they are meant to govern, because teams move on, diagrams age, standards get interpreted locally, and constraints are remembered only during design review or audit recovery.

The arrival of AI agents has made the problem sharper still. Coding agents now propose code, modify configuration, generate infrastructure changes, and act through tools at a pace that no traditional architecture review board can monitor manually. A constraint that is not expressed in a form a pipeline, policy engine, catalog, platform, or agent can consume will eventually be ignored, and evidence that is not emitted in a form an auditor can inspect will be missing on the day the enterprise needs it most.

The architectural response is architecture as code: stop relying only on prose and diagrams for architectural control and start expressing critical architectural decisions and constraints in artifacts that machines can evaluate, delivery systems can enforce, and governance processes can trace.

2. What Architecture as Code means in practice

Ford and Richards define Architecture as Code as fitness functions, executable governance, and feedback automation across the software delivery surface. This chapter extends their vision into the enterprise scope.

Working definition. Architecture as Code, as used in this chapter, is the practice of expressing architectural decisions, constraints, and descriptions in machine-readable artifacts that are versioned, evaluated automatically, and able to produce evidence of enforcement.

Four properties must hold for an artifact to qualify.

  1. Machine-readable. More than a file a computer can open. A Markdown page is technically machine-readable, but it usually requires a human to interpret it before action can be taken. A Rego policy, an ArchUnit test, a JSON Schema, a CALM description, a Backstage descriptor, or an EA Codex object can be parsed, validated, evaluated, linked, or transformed directly by tools.
  2. Versioned. The artifact lives under change control and can be reviewed, diffed, approved, reverted, and traced. A policy that changes silently is worse than no policy at all, because it creates a false sense of control.
  3. Evaluated automatically. The artifact is not only stored; it is run. A continuous-integration (CI) pipeline, policy engine, admission controller, architecture test, platform validator, catalog rule, or agent evaluation harness checks it against a proposed or actual system state on every relevant change. A rule that is never evaluated remains a wish.
  4. Evidence of enforcement. Each relevant evaluation produces a record that shows what was checked, when, against which artifact, by which rule, and with what outcome. Without that record, the regulator, auditor, or internal governance body will eventually ask the only question that matters: prove it.

Unfortunately, executable is not a binary property. The artifacts the field uses occupy different positions on the spectrum.

  • A Rego policy and an ArchUnit test execute against a deployment or a build.
  • A CALM document is machine-checkable: tools validate, visualize, and compare it.
  • A FitnessFunction object in the EA Codex is a structured specification that governs the identity of a control and points to its executable implementations.
  • An EvidenceRecord does not execute anything; it is evidence-producing, proving that an execution occurred.

Treating all of them as the same kind of thing flattens the chain; treating them as different roles in one continuous chain makes the chain governable.

Once those properties exist and those roles are named, the constraint stops being only a sentence in a document. It becomes a living object in the delivery and governance process. The same constraint, however, can be expressed at very different levels of abstraction, with different tools and different cadences. The next section walks through the four levels at which Architecture as Code actually operates.

Figure 2 summarizes the four properties that turn a constraint into architecture as code.

The four properties that turn a constraint into architecture as code.

Figure 2: The four properties that turn a constraint into architecture as code.

3. Four levels of Architecture as Code

Figure 3 shows the four levels and the role each plays.

The four levels at which architecture becomes code, from code structure to enterprise memory.

Figure 3: The four levels at which architecture becomes code, from code structure to enterprise memory.

3.1. Code structure

At the code-structure level, the architectural rule governs which parts of the codebase can reach which other parts. A modern codebase is organized into packages or modules, and the architect decides which packages are allowed to depend on which other packages. A common rule says that the layer that handles incoming requests must not reach directly into the layer that talks to the database. Other rules might say that domain code must not import infrastructure code, or that only the identity module is allowed to use a cryptographic library.

These rules are easy to state in prose and difficult to keep alive. A new contributor adds an import, the build still passes because the import compiles, the reviewer misses the line, and over a few months the layering quietly dissolves. The intent of the rule was correct; the means of enforcement was a paragraph in a wiki nobody opens.

The architecture-test pattern turns the rule into an automated check that runs every time the code is built. The check inspects the relationships between packages in the codebase and fails the build when one of those relationships violates the rule. It lives in the same repository as the application, runs in the same continuous-integration pipeline as the regular tests, and produces a failure with the same finality as a missing unit test. Whoever introduced the forbidden link sees the failure on their pull request before the change is merged.

ArchUnit is the most established tool for this on the Java Virtual Machine. In Java code, the convention is to name the request-handling layer controller and the database-access layer repository, which is why those two names appear in the test that follows. The fragment presented in Figure 4 expresses the rule in twelve lines. Read as English, the check imports every class in the application packages of com.acme.customer, picks the subset whose package name contains controller, and asserts that none of those classes depends on any class whose package name contains repository. The @Test annotation tells the build system to run the assertion as part of the normal test suite, so it runs alongside the rest of the tests rather than as a separate exercise.

@Test
void controllers_should_not_depend_on_repositories() {
    JavaClasses classes = new ClassFileImporter()
        .importPackages("com.acme.customer");
 
    noClasses().that().resideInAPackage("..controller..")
        .should().dependOnClassesThat()
        .resideInAPackage("..repository..")
        .check(classes);
}

Figure 4: ArchUnit test enforcing the controller-to-repository dependency rule (Java).

When a code change introduces a forbidden link, the test produces a failure message naming the source class, the target class, and the rule that was violated. Equivalent libraries cover other language ecosystems: NetArchTest for .NET, PyTestArch for Python, and arch-go for Go. The mechanism is identical across languages: a test inside the codebase reads the structure of the codebase and fails the build when a structural rule is broken.

The strength of this level is that the rule sits inside the same workflow as the code it governs. The architectural decision and its enforcement live one folder apart, get reviewed in the same pull request, and run on the same pipeline. The limitation is equally clear: a code-structure test can inspect what the codebase contains, but it cannot see what the running system does. Deployment decisions, data flows, regulatory boundaries, and the enterprise reasons that justified the rule in the first place are invisible to this layer. That is why the next level exists.

3.2. Runtime policy

At the runtime-policy level, the concern shifts from how the code is organized to what the running system is allowed to do. A deployment plan, a service configuration, a routing rule, or an infrastructure change can each break an architectural intent without ever altering the code that the build tested. The code may be perfectly layered, the architecture test at the previous level may pass, and a configuration change can still send EU personal data to a region the enterprise has decided to forbid.

The policy-as-code pattern moves the rule out of prose and into a small engine that evaluates structured inputs against a typed rule set. The engine sits in the pipeline: during pull-request review, during admission to a Kubernetes cluster, at the Application Programming Interface (API) gateway, or against an infrastructure plan before it is applied. It reads a description of the proposed action, runs it through the rule set, and either allows it, warns about it, or denies it with a reason the responsible team can read.

Several engines occupy this layer in practice. Open Policy Agent (OPA) is used in the worked example that follows because it has the broadest cross-stack coverage today. Equivalent engines exist for vendor-specific contexts: HashiCorp Sentinel for Terraform, CloudFormation Guard for Amazon Web Services (AWS) infrastructure templates, Azure Policy for Microsoft cloud resources, Kyverno for Kubernetes admission. The choice of engine matters less than the discipline: the rule lives as code, runs in the pipeline, and produces a structured pass-or-deny outcome.

OPA is configured through a small declarative language called Rego. A Rego file declares one or more rules. Each rule reads a structured input (usually JSON describing the proposed action), checks one or more conditions, and contributes either to an allow decision or to a violation list. The fragment presented in Figure 5 expresses the EU personal-data residency rule. Read as English, the policy starts from a default position: nothing is allowed unless proven otherwise. The allow condition is then declared: the action is allowed when the data classification is personal, the customer's home region is EU, and the target region of the transfer is also EU. A separate violation condition records the failing case: the data is personal and the customer region is EU but the target region is anything else, in which case the violation message names the offending target region.

package egress.eu_pii
 
default allow := false
 
allow if {
  input.resource.data_classification == "personal"
  input.resource.customer_region == "EU"
  input.resource.target_region == "EU"
}
 
violation contains msg if {
  input.resource.data_classification == "personal"
  input.resource.customer_region == "EU"
  input.resource.target_region != "EU"
  msg := sprintf(
    "Non-EU egress forbidden for EU personal data (target=%s)",
    [input.resource.target_region]
  )
}

Figure 5: Rego policy enforcing EU personal data residency at the runtime layer.

When the proposed action passes (an EU customer's personal data going to an EU region), the policy returns allow == true and the pipeline lets the change through. When the action fails (an EU customer's personal data going to a non-EU region), the policy returns the violation message, and the pipeline blocks the change with a structured reason.

This policy protects a different surface from the architecture test at the previous level. The architecture test catches the contributor who imports the wrong package at build time. The runtime policy catches the deployment, routing rule, infrastructure change, or service configuration that would have sent data to a prohibited region. Both checks live as code, both run automatically, both fail with a structured message. They differ in what they can see. The architecture test sees package relationships in the source repository. The runtime policy sees the proposed shape of the running system. Each level protects what the others cannot.

3.3. System description

At the system-description level, the architectural rule is about the shape of the system itself: which parts make up the system, how they connect, in which regions they are allowed to run, and which controls govern them. These are questions a code-structure test cannot answer (it sees only the source repository) and a runtime policy cannot answer either (it sees only one proposed action at a time). The shape lives one level higher, in a written description of the system that machines can read.

A system description names the components, the relationships between them, the constraints they must respect, and the controls that enforce those constraints. Until recently, this kind of description lived in diagrams drawn in PowerPoint, Visio, or a modeling tool. The diagrams were periodically updated and gradually fell out of sync with reality. The system-description level addresses the same need but produces a machine-readable artifact that other tools can validate, visualize, compare, and reason over.

Fintech Open Source Foundation (FINOS) CALM, the Common Architecture Language Model, is the most visible community effort in this space. CALM gives an organization a shared way of writing down architectural nodes (the parts of the system), the relationships between them, and the controls attached to them, all in a single structured document. Other tools occupy adjacent positions at this layer: Backstage for component ownership and catalog metadata, Score for portable workload requirements, CUE for structured-configuration validation, and Structurizr for textual architecture diagramming. Each addresses a narrower problem inside the same shift: architecture moves out of the diagram and into a machine-readable file.

Figure 6 describes a simplified payment service in CALM. Read as English, the document declares one service called payment-api that may run in two EU regions, one database called payment-store that may run in only one EU region, a relationship between the two that uses a secured Postgres protocol, and one control named eu_data_residency whose enforcement points at the OPA package introduced at the previous level. The control entry is the bridge: the system description does not enforce the residency rule itself, but it names the engine that will, and that named engine is the RegoPackage from §3.2.

$schema: https://calm.finos.org/schemas/2025-10/architecture.json
metadata:
  name: payment-service
  owner: payments-platform-team
nodes:
  - id: payment-api
    type: service
    region-allowed:
      - eu-west-1
      - eu-central-1
  - id: payment-store
    type: database
    region-allowed:
      - eu-west-1
relationships:
  - source: payment-api
    target: payment-store
    protocol: postgres-tls
controls:
  - rule: eu_data_residency
    enforced-by: opa://egress.eu_pii

Figure 6: CALM-style architecture description for a payment service.

A description in this shape is useful precisely because more than one tool can consume it. The same document feeds a validator that compares it against an approved baseline, a visualization tool that renders the architecture as a diagram, a governance tool that inspects the declared controls and checks each one points at a real enforcement engine, and a search tool that answers portfolio questions like which services hold personal data and which regions they are allowed to run in.

This level sits between the code structure and the running system. It does not catch the contributor who imports the wrong package, and it does not block the deployment that would send data to the wrong region. What it does is record the intended architecture in a form that the rest of the chain can read. The architecture test sees only the source repository, and the runtime policy sees only one proposed action at a time. The system description sees the whole system as the architect declared it, and it is the artifact the next level refers to when it asks: what system are we actually talking about?

3.4. Enterprise memory

At the enterprise-memory level, the architectural concern is no longer one codebase, one runtime policy, or one system description in isolation. The concern is the chain that connects enterprise intent to its decisions, specifications, controls, and evidence, and that the same chain must survive across many systems, teams, jurisdictions, and years. The three previous levels each enforce a rule. None of them remembers why the rule exists, who authorized it, which capability it protects, which other rules it depends on, or where the evidence that the rule ran is stored. Enterprise memory is the layer that holds all of that.

An organization that operates without this layer can have perfect code-structure tests, well-tuned runtime policies, and accurate CALM descriptions for every service, and still fail an audit. Without enterprise memory, no one can answer the questions an auditor or a regulator actually asks: when was this control put in place, by whom, against which decision, and where is the proof that the control fired in the last twelve months? The three lower levels know the present state of the system. Enterprise memory knows the history and the authority behind every rule the present state carries.

EA Codex is the typed object family that holds this memory. It groups every architectural artifact into kinds, each of which is a small, structured document with a stable identity and explicit links to the other kinds it depends on. The kinds the rest of this book introduces group naturally:

  • EnterpriseIntent and DecisionRecord hold the architectural intent and the decisions that follow from it.
  • The next pair, ArchitecturePackage and VariabilitySpecification, carries those decisions into a specific capability scope and declares which variations are permitted inside it.
  • Controls and the engines that run them sit one step further, in FitnessFunction and RegoPackage.
  • The cross-cutting artifacts (the agents that act on the system, the data they consume, the sovereignty boundaries they respect, and the evidence that they did) anchor at AgentContract, DataContract, SovereigntySpecification, and EvidenceRecord.

A single rule typically touches one object from each group: a DecisionRecord authorizes it, an ArchitecturePackage scopes it, a FitnessFunction declares it, a RegoPackage executes it, and an EvidenceRecord proves it ran.

Figure 7 presents one such object: the FitnessFunction for the EU data-residency rule. The YAML does not execute anything. It records the architectural identity of the rule, the DecisionRecord that authorized it, the ArchitecturePackage it lives inside, the executable implementations that enforce it (the ArchUnitTest from §3.1, the RegoPackage from §3.2, and the CALMControl from §3.3), and the evidence sink where each evaluation lands. The YAML fragments throughout this chapter are illustrative; the canonical schema is published at github.com/welkaim/ea-codex and the field names there should be considered authoritative.

apiVersion: ea.codex/v1
kind: FitnessFunction
metadata:
  id: ACP-FF-EU-DATA-RESIDENCY-001
  name: eu-data-residency
  title: EU personal data residency fitness function
  status: approved
  version: "1.0"
  owners:
    chiefPrivacyArchitect: cpa@acmepharma.eu
spec:
  controlType: ci-check
  evaluates:
    - input.resource.data_classification
    - input.resource.customer_region
    - input.resource.target_region
  implementation:
    language: rego
    packageRef: ACP-RGO-EGRESS-EU-PII
  enforcementMode: deny
  enforces:
    decisionRefs: [ACP-DEC-GDPR-DATA-RESIDENCY-001]
    policyRefs: [ACP-POL-GDPR-ARTICLE-44]
  scope:
    capabilityRefs: [ACP-ARC-CUSTOMER-PLATFORM-2026-Q2]
    jurisdictions: [EU]
  evidenceProfile:
    resultEnum: [pass, fail]
    retainEvidenceFor: 7y

Figure 7: EA Codex FitnessFunction binding a decision to its executable implementations and evidence stream.

In the YAML above, each reference field carries one fact about the rule. The decisionRefs and policyRefs identify the authority behind the control. The scope identifies the capability and jurisdiction where the control applies. The implementation field points to the executable package that evaluates the rule. The evidenceProfile defines the form and retention of the results that prove the rule ran. None of these fields executes a rule. Each of them carries one fact about why the rule exists, where it lives, how it is enforced, and what evidence proves it ran.

EA Codex:

  • is not the execution engine. It is the memory and authority layer above the other three. The execution stays where it already runs well: in the architecture-testing libraries, in the policy engines, in the platform pipelines, in admission controllers. The Codex stays one layer up, holding the chain.
  • is not defined by a repository product. The objects may live in Git, an EA platform, a software catalog, a policy repository, or a graph store, or in a combination of those. What matters is that the chain from intent to evidence remains addressable, versioned, and governable. A team becomes EA-Codex-shaped not by adopting a particular store but by accepting the integrity of the chain as a non-negotiable architectural property.

CALM and EA Codex solve different problems. CALM is a FINOS community specification for portable software-architecture description: nodes, relationships, controls. EA Codex is enterprise memory: intent, decisions, variability, evidence. EA Codex can reference a CALM document as the system-description view inside an ArchitecturePackage, but it does not absorb CALM's community remit. The two are co-located, not stacked.

The wider toolchain follows the same rule. Each tool does one thing: ArchUnit enforces code structure at build time, OPA enforces runtime policy, CALM describes the system, Backstage catalogs ownership, and EA Codex holds the memory and authority that binds the rest. None replaces the others. The chapter's argument is that they should be composed.

4. The fitness function binds the four levels

The fitness-function concept is the hinge between Architecture as Code and the EA Codex.

4.1. The fitness function as the cross-level construct

In Building Evolutionary Architectures, Neal Ford, Rebecca Parsons, and Patrick Kua introduced the fitness function as a way to provide an objective check for an architectural characteristic, not to mechanize architectural judgment but to protect the qualities that matter while the system changes around them.

That idea becomes much more powerful when it travels across the four levels. A fitness function can be a code-structure test, a runtime policy, a system-description control, or a governed enterprise object that points to all three. It can protect coupling, resilience, security, latency, accessibility, jurisdictional boundaries, or data quality. It can fail a build, block a deployment, trigger a warning, or create an exception workflow.

The public Architecture as Code material associated with Neal Ford and Mark Richards extends this idea across a broader architectural surface. Fitness functions are no longer confined to implementation structure. They can apply to engineering practices, infrastructure, generative AI, team topology, business concerns, enterprise governance, data, and integration architecture. The same discipline that once protected code structure can now protect the wider software delivery ecosystem.

4.2. Three artifact roles, not one

This chain also answers a common objection. A Rego file is executable. An ArchUnit test is executable. A FitnessFunction object in YAML is not executable in the same sense. That does not make it useless. It plays a different role. It is the structured specification of the control, the governed reference point that links the architectural reason to the executable implementation and the evidence stream.

Architecture as Code therefore contains three artifact roles that should not be confused as shown in Figure 8.

Artifact roleWhat it doesExample
Structured specificationDefines what is constrained, why, by whom, and against which evidence.FitnessFunction YAML object
Executable ruleRuns and fails, warns, or blocks when violated.Rego policy, ArchUnit test, NetArchTest rule
Feedback evidenceRecords that a rule was evaluated against a specific artifact at a specific time.EvidenceRecord, CI report, audit log

Figure 8: The three artifact roles in Architecture as Code: descriptions, executables, and memory.

Calling all three roles “code” without distinction is what creates confusion; keeping them separate is what makes the architecture stronger. The FitnessFunction object gives the control a governed identity, the executable rule evaluates the condition, and the EvidenceRecord proves that the evaluation took place.

The same logic prevents tool confusion:

  • CALM can describe architecture portably without replacing policy enforcement;
  • OPA can enforce policy without maintaining enterprise memory;
  • Backstage can expose ownership and component metadata without explaining which decision authorized a constraint;
  • EA Codex can connect those surfaces without executing the runtime rule itself.

The enterprise needs the chain that runs through them, not a single fantasy tool that pretends to do everything.

4.3. The operating model

The chain runs through seven steps:

  1. an intent defines why the enterprise wants something
  2. a decision records what the architecture function decided
  3. a package carries the decision into delivery
  4. a FitnessFunction declares what must be checked
  5. an executable rule runs the check
  6. an EvidenceRecord proves that the check happened
  7. feedback updates future decisions

The chain becomes a converging process when Brief, Map, Act, Double-check (BMAD) drives it through the Seed-Validation-Feedback attractor. Both are defined in Chapter 7: BMAD as the architect's operating flow, the attractor as the agent execution loop adopted from the StrongDM Software Factory. The architect's flow gives each iteration its structure; the attractor gives it its convergence. Together they turn what would otherwise be a one-shot artifact chain into a repeatable loop that humans and agents can both execute.

Chapter 12 places this operating flow inside The Open Group Architecture Framework (TOGAF): BMAD runs as a production and validation loop inside each Architecture Development Method (ADM) phase, the attractor explains why each loop converges instead of freezing at design time, and ADM remains the macro governance cycle. What changes is what fills the phases. Documents reviewed in committee become typed Codex objects produced and validated by BMAD loops. EvidenceRecord aggregations feed Phase G as governance evidence, while ArchitectureChangePacket objects provide a typed trigger for Phase H when implementation feedback requires architectural change.

Figure 9 places the BMAD loop inside the TOGAF ADM and shows the attractor pattern that closes each iteration.

TOGAF ADM, BMAD, and the Seed-Validation-Feedback attractor as nested cycles: macro phases, micro loop, convergence principle.

Figure 9: TOGAF ADM, BMAD, and the Seed-Validation-Feedback attractor as nested cycles: macro phases, micro loop, convergence principle.

5. Variability changes what fitness functions enforce

A fitness function becomes more useful when it can distinguish intentional variation from accidental divergence. In most enterprises, architecture does not fail only because teams violate standards. It also fails because nobody can clearly say whether a difference is an approved variant, a temporary exception, a local configuration, an evolutionary transition, or uncontrolled drift.

A simple runtime rule may say that all study data must remain in approved hosting regions. That is useful, but it does not explain whether Japan, France, and Germany may use different consent text, whether a legacy Representational State Transfer (REST) integration is still allowed during migration, or whether a local team can change audit retention. These are variability questions, not only compliance questions.

The VariabilitySpecification (introduced in Chapter 5 and generalized to the portfolio in Chapter 9) is the typed envelope that makes variability explicit: where difference is allowed, which values are permitted, who must approve them, how long they remain valid, and which invariants must not change. Inside Chapter 16's frame, the FitnessFunction evaluates whether a concrete implementation, configuration, interface, DataContract, or AgentContract stays inside that permitted design space.

Software evolution provides one example. ACME Pharma may be moving a regulated digital-study platform from synchronous REST calls to asynchronous event publication. During the transition, existing capabilities may keep REST until a sunset date, while new capabilities must publish events. A VariabilitySpecification records that rule. A fitness function blocks new REST integrations while still allowing registered legacy exceptions before the sunset date.

Software product line configuration provides another example. Country-specific consent wording may vary by jurisdiction and study protocol, while audit retention should not vary by local team preference. A VariabilitySpecification can classify consent text as configurable and audit retention as a core invariant. A fitness function can accept French consent wording when medical-legal approval exists and reject any attempt to shorten audit retention.

This turns fitness functions away from blind standardization. The goal is not to make every system identical. The goal is to enforce the boundary between legitimate difference and uncontrolled drift.

Figure 10 shows the VariabilitySpecification for the digital-study capability.

apiVersion: ea.codex/v1
kind: VariabilitySpecification
metadata:
  id: ACP-VAR-DIGITAL-STUDY-001
  name: regulated-digital-study-variability
  title: Regulated digital-study variability envelope
  status: approved
  version: "1.0"
  owners:
    productLineArchitect: pla.digital-study@acmepharma.eu
spec:
  scope:
    family: regulated-digital-study
    appliesTo: [clinical-development]
  variationPoints:
    - id: consentText
      classification: configuration
      bindingTime: deployment
      allowedValues: [default, jurisdiction-variant]
      constraints:
        - allowedBy jurisdiction or studyProtocol
        - approvalRequiredFrom medical-legal-review
    - id: dataResidency
      classification: regulated-configuration
      bindingTime: deployment
      constraints:
        - allowedBy jurisdiction
        - approvalRequiredFrom data-protection-office
    - id: integrationStyle
      classification: time-bound-transition
      bindingTime: design
      allowedValues: [rest_legacy, event_publication]
      constraints:
        - rest_legacy allowed only for existing capabilities, sunset 2026-12-31
        - event_publication required for new capabilities
    - id: auditRetention
      classification: core-invariant
      bindingTime: design
      allowedValues: [P10Y]
      constraints:
        - core invariant, changeAllowed false
    - id: safetyEventReporting
      classification: core-invariant
      bindingTime: design
      constraints:
        - core invariant, changeAllowed false
  exceptionPolicy:
    allowed: true
    approverRole: ea-council
    maxDurationDays: 365
    requiredCompensatingControl: medical-legal-review

Figure 10: VariabilitySpecification declaring variation points, allowed values, and invariants for a digital-study capability.

The matching FitnessFunction points to the VariabilitySpecification and makes selected variation rules executable through OPA.

apiVersion: ea.codex/v1
kind: FitnessFunction
metadata:
  id: ACP-FF-STUDY-VARIABILITY-001
  name: study-variant-conformance
  title: Study variant conformance fitness function
  status: approved
  version: "1.0"
  owners:
    productLineArchitect: pla.digital-study@acmepharma.eu
spec:
  controlType: ci-check
  evaluates:
    - input.kind
    - input.spec.integrationStyle
    - input.spec.consentText.variantApplied
    - input.spec.regulatoryClassification
    - input.spec.retentionPeriod
  implementation:
    language: rego
    packageRef: ACP-RGO-STUDY-VARIABILITY
  enforcementMode: deny
  enforces:
    standardRefs: [ACP-VAR-DIGITAL-STUDY-001]
  scope:
    factSheetTypes: [ArchitecturePackage, DataContract, AgentContract, Interface]
  evidenceProfile:
    resultEnum: [pass, fail]
    retainEvidenceFor: 7y

Figure 11: FitnessFunction binding the VariabilitySpecification to executable evaluation by an OPA package.

Figure 12 shows the Rego policy that enforces the variation envelope.

package acme.study.variability
 
deny[msg] {
  input.kind == "Interface"
  input.spec.capabilityLifecycle == "new"
  input.spec.integrationStyle == "rest_legacy"
  msg := sprintf("New capability %s cannot use legacy REST integration", [input.metadata.id])
}
 
deny[msg] {
  input.kind == "Interface"
  input.spec.integrationStyle == "rest_legacy"
  input.spec.exception.sunsetDate > "2026-12-31"
  msg := sprintf("Legacy REST exception for %s exceeds the approved sunset date", [input.metadata.id])
}
 
deny[msg] {
  input.kind == "ArchitecturePackage"
  input.spec.variant.jurisdiction == "FR"
  input.spec.consentText.variantApplied == true
  not input.spec.approvals.medicalLegalReview
  msg := sprintf("French consent-text variant in %s lacks medical-legal approval", [input.metadata.id])
}
 
deny[msg] {
  input.kind == "DataContract"
  input.spec.regulatoryClassification == "regulated-study-evidence"
  input.spec.retentionPeriod != "P10Y"
  msg := sprintf("DataContract %s violates the ten-year audit retention invariant", [input.metadata.id])
}

Figure 12: Rego policy enforcing the authorized variation envelope of the digital-study product line.

The resulting control permits French consent wording when the medical-legal approval is present, accepts legacy REST during the controlled migration window, rejects REST for new capabilities, and rejects any attempt to weaken the audit-retention invariant. The fitness function is no longer in the business of enforcing sameness; it is in the business of enforcing disciplined difference.

6. Agentic AI raises the cost of ambiguity

AI agents are the pressure test for executable enterprise architecture. The four levels above describe where architectural rules live; they do not define the actor that moves across them. AI agents are such actors. They navigate code, retrieve context, generate specifications, and trigger operational workflows. Each of those actions is a question to the architecture: is this allowed? Architecture as Code answers with executable boundaries. EA Codex answers with governed context. Together they make the chain readable by the actors that now consume it.

Agents force the architecture to be more explicit than human teams typically required. Humans can sometimes infer architectural intent from conversation, history, and informal norms. Agents cannot. They consume only the artifacts that are written down, typed, and reachable through their context surface. Where the surface is ambiguous, the agent fills the gap with whatever interpretation maximizes its task signal, which is rarely the interpretation the enterprise intended.

Consider the ACME Pharma pharmacovigilance AI Triage Service. The agent receives an adverse-event report, extracts entities (patient reference, drug, event description, seriousness), classifies the report (seriousness, validity, prior history), and routes it to the correct downstream queue. Each step touches all four levels of the chain.

  • Code-structure. The agent's deployment code must not import the safety-system schema directly. Only the approved data-product layer is allowed. An ArchUnit test fails the build if a developer imports the wrong module.
  • Runtime-policy. The agent's data access must respect EU patient-data residency. A Rego policy blocks any agent runtime that attempts to read patient data from a non-EU region.
  • System-description. The AgentContract declares what the agent may know and do. Its purpose is AI-assisted intake of adverse-event reports. Its permitted context is the curated knowledge graph plus the EU-resident case database. Its tool boundaries permit extract, propose, and route. They forbid approve, confirm, and direct write to the system of record.
  • Enterprise-memory. The AgentContract is bound to the DecisionRecord that authorized it, to the ProductLineSpecification that scopes it, and to the EvidenceRecord stream that proves what it did. Every action the agent takes is traceable to a typed boundary in the Codex, with full lineage back to enterprise intent.

The distinction between a guardrail and a contract makes this concrete. A guardrail blocks a class of failure: no patient data outside the EU region. A contract defines the authorized operating space: this agent may extract and propose but not approve; it may invoke these three tools but not those; it must emit evidence for every classification. The agent needs both. The Rego policy provides the guardrail; the AgentContract provides the contract.

Model Context Protocol (MCP) is one visible expression of a broader shift: agents increasingly access enterprise tools and context through standardized connectors. The architectural issue does not depend on MCP alone. Any protocol that exposes tools and context to agents raises the same question: which architectural memory, policies, and evidence surfaces are safe to expose, and under which authority? A Codex, an EA repository, a policy store, or a software catalog can each become agent-consumable surfaces. Where the exposed architecture is weak, agents spread ambiguity faster than any earlier protocol could carry. Where the exposed architecture is governed, the same protocols turn typed memory into directly usable constraints and context for every agent that consults it.

Because agents cross every layer, they need a typed boundary rather than a separate layer. In EA Codex, that boundary is the AgentContract. Chapter 10 developed the AgentContract in its own right; here it functions as the typed boundary agents need when they cross the executable architecture stack.

7. One real constraint across all four levels

The rule EU personal data must never leave the EU region can travel through all four levels without losing its identity.

  1. At the code-structure level, an architecture test ensures that the routing component never selects a non-EU endpoint when the payload is tagged as EU personal data.
  2. At the runtime-policy level, the Rego policy runs in CI, in Kubernetes admission control, and against infrastructure plans. It blocks non-EU egress even if a developer bypasses a local code path.
  3. At the system-description level, the CALM document declares the payment API, store, allowed regions, and the control that enforces EU residency.
  4. At the enterprise-memory level, EA Codex links the rule to the DecisionRecord, SovereigntySpecification, FitnessFunction, implementations, and EvidenceRecord stream.
apiVersion: ea.codex/v1
kind: DecisionRecord
metadata:
  id: ACP-DEC-GDPR-DATA-RESIDENCY-001
  title: EU personal data residency
  status: accepted
  date: "2024-09-01"
  owner: chief-data-officer@acme-pharma.example
  version: "1.0"
spec:
  trigger:
    type: external-regulator-notice
    source: GDPR Article 44 — transfers of personal data outside the EU
  context: |
    GDPR restricts unjustified transfers of personal data outside the European Union.
    Customer-facing services must respect that jurisdictional boundary.
  decision: |
    EU personal data must remain in EU-approved regions across all customer-facing
    services. Cross-border transfers are prohibited without a documented legal basis
    and a compensating control.
  relatedPrinciples:
    - ACP-PRI-PRIVACY-BY-DESIGN
  relatedSpecs:
    - ACP-SOV-EU-PII-RESIDENCY
  affectedFactSheetTypes:
    - ArchitecturePackage
    - DataContract
    - Interface
  doubleCheck:
    fitnessFunctions:
      - id: ACP-FF-EU-DATA-RESIDENCY-001
        rule: No EU personal data may exit EU regions
        check: Rego package ACP-RGO-EGRESS-EU-PII in CI
---
apiVersion: ea.codex/v1
kind: FitnessFunction
metadata:
  id: ACP-FF-EU-DATA-RESIDENCY-001
  name: eu-data-residency-fitness-function
  title: EU data residency fitness function
  status: approved
  version: "1.0"
  owners:
    enterpriseArchitect: enterprise-architecture@acme-pharma.example
spec:
  controlType: ci-check
  evaluates:
    - input.resource.data_classification
    - input.resource.target_region
  implementation:
    language: rego
    packageRef: ACP-RGO-EGRESS-EU-PII
  enforcementMode: deny
  enforces:
    decisionRefs: [ACP-DEC-GDPR-DATA-RESIDENCY-001]
  scope:
    jurisdictions: [EU]
---
apiVersion: ea.codex/v1
kind: SovereigntySpecification
metadata:
  id: ACP-SOV-EU-PII-RESIDENCY
  name: eu-personal-data-residency-boundary
  title: EU personal data residency boundary
  status: approved
  version: "1.0"
  owners:
    dataProtectionOfficer: data-protection-office@acme-pharma.example
spec:
  intent:
    objectiveRef: ACP-INT-GDPR-COMPLIANCE-2024
    statement: Preserve EU jurisdictional control over personal data across processing, storage, and derived context.
    relatedDecisions: [ACP-DEC-GDPR-DATA-RESIDENCY-001]
  appliesTo:
    capabilityScopes: [customer-platform]
    dataProductRefs: [ACP-DPC-CUSTOMER-PII]
  sovereigntyObjectives:
    controlOfMeaning:
      required: true
      defaultPolicy: enterprise-business-object-glossary
    controlOfDataLocation:
      required: true
      defaultPolicy: eu-only
      enforcementPattern: opa-rego-region-check
    controlOfAccess:
      required: true
      defaultPolicy: deny-non-eu-roles
    controlOfExecution:
      required: true
      defaultPolicy: eu-resident-runtimes-only
    controlOfEvidence:
      required: true
      evidenceStore: ACP-EVD-EU-DATA-RESIDENCY-STREAM
    controlOfExit:
      required: true
      providerSubstitutionTarget: eu-resident-cloud-or-on-prem
  validation:
    deterministicRules:
      engine: opa
      rulePackages:
        - ACP-RGO-EGRESS-EU-PII

Figure 13: EA Codex chain linking the GDPR data-residency DecisionRecord, its FitnessFunctions, and the SovereigntySpecification that holds the residency boundary.

Figure 14 shows the three roles in one frame.

The Codex specification governs, the RegoPackage executes, and the EvidenceRecord closes the loop.

Figure 14: The Codex specification governs, the RegoPackage executes, and the EvidenceRecord closes the loop.

8. How to start without creating a metamodel program

An enterprise that wants the chain to actually run starts in one of two places, depending on the size and maturity of what already exists.

  1. A new program can begin top-down, starting at enterprise intent and projecting it through decisions, specifications, and controls.
  2. A team modernizing a system that already runs is better off going bottom-up, lifting the constraints already enforced in the code back into typed enterprise memory.

The two paths converge on the same operating model: executable enterprise architecture, the chain from intent through enforcement running end to end. The rest of the book has walked the top-down path chapter by chapter; the section that follows walks the bottom-up path, which fits the more common situation, in which the enterprise must retrofit the operating model onto systems that already exist.

Adopting the whole ontology in one motion is the surest way to fail. A team that begins by implementing every Codex kind typically produces a metamodeling exercise rather than a working chain, and that exercise quietly stalls the moment its first deliverable misses a real delivery deadline. The practical starting point is one constraint that already matters in the team and is currently enforced only informally, often through reviewer goodwill rather than through any artifact a machine can read.

We must also note that not every constraint deserves to be made executable. A constraint earns its way into the chain when it is frequently violated, costly to discover late, regulatorily sensitive, applicable to more than one system, objectively evaluable, and consumable by pipelines or agents. A team that applies all six tests will produce a small set of chains that pay for themselves, instead of a large set of controls that nobody reads.

A first working chain often fits inside a single sprint. The shape is the same in every adoption, whatever the starting condition.

  • Step 1: pick the constraint. Choose a rule that is important, repeatedly discussed, and currently stored only in prose. Good candidates include “public APIs must declare stable schemas,” “database migrations must include rollback evidence,” “PII fields must be tagged at source,” or “EU personal data must not leave approved EU regions.”
  • Step 2: write the executable rule. Pick the easiest enforcement surface. It may be an ArchUnit test, a Rego policy through Conftest, a GitHub Actions check, or a catalog validation rule. Test it against one known-good input and one known-bad input.
  • Step 3: wire it into the pipeline. Make the rule run on relevant changes. Decide whether it blocks, warns, or opens an exception workflow. Make bypasses explicit.
  • Step 4: capture evidence. Store the result of each evaluation with timestamp, artifact identifier, rule identifier, and outcome. A structured CI artifact is enough to start.
  • Step 5: register the chain. Write the DecisionRecord that authorizes the rule. Write the FitnessFunction that points to the executable rule. Link both to the evidence sink. Put the chain in a repository that architecture and platform teams both watch.

By the end of that set of steps, a constraint that previously lived only in a wiki page now lives in a decision that authorizes it, a rule that runs against every change, an evidence stream that captures every outcome, and a memory object that connects them all. That is architecture as code in the form that actually changes the way delivery operates.

From there, the second chain can involve a cross-system integration, the third can govern an agent, and the fourth can introduce a VariabilitySpecification for a regulated capability. The ontology grows because the enterprise accumulates working chains over time, not because a program mandated the full metamodel up front.

9. Risks and trade-offs

The strongest risk in Architecture as Code is metric capture. Teams may test what is easy to test and confuse test coverage with architectural integrity. Coupling rules, complexity thresholds, dependency constraints, policy checks, and contract validations matter, but they do not exhaust architecture. Some architectural concerns require scenario reasoning, business judgment, risk analysis, organizational design, and human accountability.

The strongest risk in EA Codex is modeling overreach. A semantic system becomes heavy when every concept is modeled with the same rigor. The right approach is selective formality. Regulated data, AI agents, sovereignty boundaries, high-risk integrations, vendor policy changes, reusable platform standards, and product-line variants justify stronger specification. Low-risk exploration can begin with lighter artifacts and weaker gates.

Lifecycle burden is real and cumulative. Controls decay, policies grow stale, catalog metadata drifts, DecisionRecord entries lose relevance, AgentContract definitions become inaccurate the moment tool access changes, and VariabilitySpecification objects become outright dangerous when sunset dates and allowed options are no longer maintained. Executable architecture therefore needs ownership, a review cadence, deprecation rules, regression checks, and active evidence maintenance, in the same way running software needs operations and observability.

Beyond the lifecycle, the toolchain itself is a source of fragmentation. OPA, Backstage, Crossplane, Score, CUE, CALM, GitOps controllers, architecture testing libraries, EA repositories, data catalogs, and agent runtimes each carry their own internal model, and if each tool becomes a separate island, the enterprise gains automation without architectural coherence. EA Codex is useful only insofar as it reduces that fragmentation by connecting decisions, controls, and evidence into a single chain. When it becomes another disconnected repository, it repeats the failure it was meant to solve.

The deepest trade-off is one of authority. Blocking controls can protect the enterprise but slow delivery when they are poorly scoped; advisory controls reduce friction but risk becoming invisible; agents can accelerate work but amplify ambiguity when their context is weak; and variability supports local adaptation but can mask drift when the allowed envelope is not actively maintained. The goal is not maximal automation but calibrated authority, applied where the cost of ambiguity is highest.

Beyond these general trade-offs, five failure modes are common enough to anticipate explicitly, because each one attacks a specific joint in the chain.

9.1. False confidence

Because a rule passes, the team concludes that the architecture is sound. The rules only cover what has been modeled, and the unmodeled surface remains invisible. The remedy is to track coverage as a first-class quantity, name what is not covered, and treat green dashboards as a partial signal rather than a verdict.

9.2. Governance laundering

A weak or political decision is encoded as a FitnessFunction and presented as objective because it is now automated. The remedy is to keep the DecisionRecord honest about context, alternatives, and authority. A control that cannot trace back to a defensible decision is an opinion in machine-readable form, not governance.

9.3. Control sprawl

Every team adds its own checks, nobody retires them, the pipelines slow down, and exceptions multiply. The remedy is to give the FitnessFunction library an owner, a deprecation policy, and a regular audit of which controls still trace to a live decision and a live system.

9.4. Evidence without interpretation

EvidenceRecord objects accumulate, but nobody maps them to audit questions, business risks, or architectural decisions. The remedy is to require, for every regulated control, an explicit mapping from evidence to the obligation it serves. Without that mapping, evidence is data, not assurance.

9.5. Agent overfitting to visible rules

Agents can optimize their output to clear the visible gates while drifting from the wider architectural intent the gates were meant to protect. The remedy is to combine visible scenarios with hidden holdout sets that are governed but not exposed to the generation process, and to read the divergence between the two sets as an architectural signal.

10. Conclusion

Architecture as Code makes architecture executable wherever execution is possible. Fitness functions, code-structure tests, policy engines, system descriptions, and platform validations together give architecture a working presence in delivery rather than a paper presence in committee. CALM contributes a community-owned path for machine-readable architectural descriptions, and EA Codex contributes the typed enterprise memory that links those executable controls to intent, decisions, policies, agents, variability, evidence, and feedback in one continuous chain.

These approaches do not compete for the same role; they fit together as layers in a single operating model. The architecture-testing family protects code structure, OPA and related tools protect runtime and policy surfaces, CALM and adjacent formats describe systems in machine-readable form, and EA Codex keeps the enterprise decision chain intact across time, systems, agents, vendors, and audits.

A single team can carry the test out in a single sprint. Pick one real constraint, express it at the levels that matter for your stack, make at least one rule genuinely executable, capture the evidence the rule produces, and link the rule back to the decision that authorized it. Once that chain works end to end, architecture is no longer only described. It is specified, enforced, evidenced, and remembered.

The contribution of this chapter, in one line: Architecture as Code makes constraints executable; the EA Codex makes the reason, the authority, the variation envelope, the agent boundary, and the evidence chain durable across the time horizons the enterprise actually lives on.

11. Sources

Architecture as Code and fitness functions

The comparison between Architecture as Code, CALM, the EA Codex, and the wider field is interpretive. It should not be read as a claim that the cited authors, publishers, communities, standards bodies, or organizations endorse the EA Codex approach.

Policy-as-code and architecture testing

System description and platform descriptors

Agent context and MCP

Software Product Line foundations

Enterprise architecture frameworks and regulations

EA Codex references