This chapter positions infrastructure as code not as a tooling preference but as a precondition for sovereign, auditable operations at scale. It shows how Terraform, Pulumi and Ansible translate organisational intent into executable, version-controlled declarations that encode sovereign zone boundaries, encryption requirements, network segmentation and identity trust relationships directly into the codebase. Architects will find guidance on sovereign zone modules with built-in preconditions, provider aliases for multi-account and multi-cloud estates, state file residency within jurisdictional boundaries, and the composition of shared module registries that turn sovereignty patterns into reusable contracts. The chapter also covers drift detection pipelines, policy-as-code enforcement with Open Policy Agent at every stage from pull request to runtime, and the integration of IaC with agentic operations so that automated systems can reason about declared intent rather than reverse-engineering console state.
There is a particular kind of silence that falls in a war room when someone asks, “What exactly is running in production right now?” and no one can give a confident answer. People open tabs. Someone scrolls through a cloud console. Another digs out an old Visio diagram. Everyone knows that whatever is on the diagram and whatever is on the screen are only loosely correlated. More troublingly, no one knows precisely how large the gap is.
In a single cloud, at modest scale, that kind of uncertainty is irritating but survivable. In a sovereign, multi-cloud estate it is a structural risk. If you cannot say, precisely, which regions are in use, which networks connect them, which keys protect which data, and who can change any of that, then you cannot credibly claim to be in control of your own topology or your own obligations. The European Banking Authority has been explicit on this point: firms must maintain clear governance accountability for every element of their ICT supply chain, including cloud-hosted services, and that accountability requires documented, demonstrable control rather than informal familiarity [1]. Regulators have moved beyond accepting a diagram produced at audit time; they want evidence that the diagram reflects the live system and that deviations are detected and corrected in operational time.
The console is, in this context, not just an ergonomic problem but an epistemological one. When infrastructure is built through graphical interfaces, the “why” of each decision is lost. The engineer who opened port 443 on a particular security group last February did so for a reason, but that reason is not stored in the cloud provider’s database. The audit log may record that a change was made and by whom, but it cannot reconstruct the reasoning, the ticket reference, the risk assessment, or whether anyone else reviewed it. Over months and years, this accumulation of undocumented decisions becomes technical debt of the most dangerous kind: a topology that looks reasonable from a distance but whose internal logic no one fully understands.
Infrastructure as code (IaC) is the way out of that silence. It replaces informal knowledge and point-in-time diagrams with executable descriptions of reality: files that, if applied, would recreate the environment as it is meant to be. Tools such as HashiCorp Terraform, which provides a declarative language for expressing infrastructure intent across dozens of cloud providers [2], and Pulumi, which extends the same concept to general-purpose programming languages including Python, TypeScript and Go [3], have made it practical to manage an entire multi-cloud estate from a unified, version-controlled codebase. The tooling is not the point, however. What matters is the discipline: that every resource in the estate has a corresponding definition in version control, that every change to the estate flows through a review process, and that the gap between declared intent and actual reality is continuously monitored and closed.
In this chapter, we treat IaC not as a tooling choice, but as a precondition for sovereign, agentic operations.
Infrastructure as code is the difference between an organisation that can answer the question “what is running in production right now?” with confidence and one that cannot. For the CIO, this is not a tooling discussion — it is a governance and risk discussion. When every resource in the estate has a corresponding, version-controlled definition, change control becomes auditable by default, regulatory inquiries can be answered from code rather than from memory, and the organisation’s dependence on the tacit knowledge of individual engineers is structurally reduced. The cost dimension is equally compelling: codified infrastructure patterns can be reused across sovereign zones and new national deployments, turning what would otherwise be months of bespoke engineering into parameterised instantiation. Perhaps most importantly, IaC is the precondition for agentic operations — automated systems cannot reason about, or safely modify, infrastructure that exists only as undocumented console state.
If you look back at the early days of many cloud programmes, you can often find a “hero engineer.” They were the one who knew how to get the network talking to the database, how to appease the load balancer, how to get the IAM policies to line up just so. Their skill was real, and their contribution invaluable. It was also, from an operational perspective, a single point of failure—and, from a sovereign perspective, a single point of undocumented knowledge that could not be audited, handed over, or handed to an automated system.
Declarative IaC breaks that pattern. Instead of having one person who remembers which checkboxes were ticked in which console, you have code that says:
The declarative style is significant. You are not describing a sequence of steps to be followed; you are describing an end state to be achieved. The tool—Terraform, Pulumi, CloudFormation—works out the sequence of API calls needed to move from the current state to the declared state. If the resource already exists with the correct configuration, nothing changes. If it is absent, it is created. If it has drifted, it is corrected. This idempotent property means that IaC can be applied repeatedly and safely, which is the precondition for automation.
Terraform expresses that intent through provider plugins, with each provider translating Terraform’s configuration language (HCL) into the appropriate API calls for its respective platform [2]. Pulumi achieves the same outcome through familiar programming-language constructs, which appeals to organisations whose engineers are more comfortable writing Python classes than HCL blocks [3]. Ansible, maintained by Red Hat, complements this approach at the configuration layer: where Terraform defines what infrastructure should exist, Ansible defines how machines and services within that infrastructure should be configured, using an agent-less, SSH-driven model that lends itself to idempotent playbook execution [4]. Together, these tools cover the full journey from “provision this cluster” to “apply this hardening baseline to every node in it.”
For sovereign operations, the important shift is psychological as much as technical. Instead of asking, “How did we build this environment?”, you ask, “What is our declared intent for this environment?” and “Does reality match that intent?” The research captured in Accelerate by Forsgren, Humble, and Kim establishes that high-performing organisations are significantly more likely to use version-controlled configuration and infrastructure definitions, and that this practice correlates directly with improved deployment frequency, lower change failure rates, and faster recovery from incidents [5]. Sovereignty is not mentioned in that research, but the mechanism is identical: declarative intent, enforced by code, leaves less room for the kind of invisible drift that eventually surfaces as a regulatory finding or an incident whose root cause turns out to be a misconfiguration from eighteen months ago that nobody noticed.
Earlier we introduced sovereign zones as conceptual constructs: bounded slices of the estate where a particular set of legal obligations, operational authorities and data residency rules apply. At some point, those concepts must harden into IP addresses, route tables and key policies. Infrastructure as code is the medium for that hardening.
The first discipline is resource tagging. Every resource created in a sovereign zone should carry a standard set of tags that make its provenance machine-readable: the jurisdiction it operates under (for example, jurisdiction=EU, data-classification=restricted, owning-team=platform-eu). Terraform’s default_tags mechanism, available at the provider level, allows an organisation to define tags that are automatically applied to every resource a provider creates, without relying on individual engineers to remember to add them [2]. This matters because downstream systems—policy engines, cost allocation tools, observability platforms, and agents—can then query those tags to determine what constraints apply, without needing to consult a separate register. A resource that is missing its jurisdiction tag, or carries one inconsistent with the account it resides in, immediately stands out in policy scans and in agent queries. The tag is not decoration; it is a machine-readable assertion about the regulatory regime that applies to that resource, and it needs to be as reliable as the network configuration that surrounds it.
Tagging standards should be defined centrally—in a shared configuration repository or in a platform team’s module library—and enforced at two levels. The first level is the default_tags block in the Terraform provider configuration, which applies tags automatically. The second level is an OPA policy rule that fails the pipeline if any resource in a plan lacks the required tags or carries a tag value not in the approved enumeration. Between them, these two mechanisms make it structurally difficult—though not impossible—to create an untagged or mis-tagged resource. The remaining gap is closed by continuous drift detection, discussed in section 11.7.
The second discipline is provider aliases. In a real multi-cloud, multi-account codebase, a single Terraform root module may need to create resources across several AWS accounts, several Azure subscriptions, and a GCP project simultaneously. Terraform supports this through provider aliases: you declare multiple instances of the same provider type, each configured with distinct credentials, regions or accounts, and then reference the appropriate alias in each resource block [2]. For sovereign operations, this pattern is particularly powerful: you can express, in a single module instantiation, that “this resource belongs to the EU-regulated provider alias, and that resource belongs to the US-commercial alias,” making cross-boundary relationships explicit and auditable rather than implicit and accidental. The alias name is itself documentation: provider = aws.eu_regulated conveys regulatory intent in the same line that creates the resource.
Provider aliases also make it possible to create explicit Terraform rules about which resource types may appear under which provider aliases. A data source that reads existing VPC configurations from the EU-regulated account can be referenced as a validation input, confirming that any new resource being placed there meets the expected network topology. The constraint is not enforced by documentation or convention; it is enforced by data lookups that will cause terraform plan to fail if the expected structures are absent.
The third and most important discipline is the sovereign zone module. The Terraform module is the fundamental unit of reuse: a self-contained collection of resource definitions, variables, and outputs that encodes a coherent infrastructure pattern. For sovereign operations, modules go beyond technical reuse—they become sovereignty patterns. A sovereign zone module is not merely a “create a VPC” module; it is a module that creates a VPC only in approved regions, enforces encryption requirements appropriate to the jurisdiction, configures flow logging to a locally controlled log sink, and refuses to instantiate in accounts not marked for regulated use. The constraints are not advisory comments in a README; they are precondition blocks, variable validations, and Terraform data lookups that cause the plan to fail if the sovereignty requirements are not met [2].
A practical example illustrates the difference. A naive VPC module accepts a region variable and creates a VPC there. A sovereign zone VPC module accepts a region variable and a zone_classification variable, and includes a precondition block that checks whether the supplied region appears in a locally maintained list of approved regions for that classification. If an engineer, or an agent, attempts to instantiate this module in a region not on the list, the Terraform plan fails with a descriptive error before any API call is made. The constraint is enforced at the point of intent declaration, not at the point of execution—which means it is enforced before the change request even reaches a reviewer.
Module versioning is what gives this pattern its contractual force over time. Modules published to a private Terraform module registry—whether HashiCorp Terraform Cloud, a self-hosted registry, or a Git-based reference with semantic version tags—carry version numbers. Platform teams release new versions as standards evolve: a new encryption algorithm is required, a new logging destination is mandated, a new region is approved or removed. Product teams pin their stacks to specific module versions using Terraform’s version constraint syntax, and they see pending version updates through automated tooling such as Renovate or Dependabot configured to monitor the module registry. A change in privacy law that requires stronger encryption in a particular jurisdiction becomes a new module major version; product teams migrate on a planned schedule, and the migration is visible as a pull request rather than as a memo that may or may not have been read [2]. The registry also enforces discoverability: instead of reinventing sovereign networking from scratch, a team searching for a compliant networking module finds the authoritative one rather than the ad-hoc version an engineer wrote last year.
State management requires particular attention and is one of the most commonly overlooked sovereignty requirements. Terraform records the current known state of all managed resources in a state file, and that state file can contain sensitive values: resource identifiers, output secrets, database connection strings, and enough structural detail to reconstruct the entire topology of the estate. For a sovereign zone, the state file must be stored within the zone’s own boundaries. If you are managing EU-regulated infrastructure, the Terraform state backend—whether an S3 bucket, Azure Blob container, or Terraform Cloud workspace—must reside in an EU-approved account, encrypted with keys under local control [2]. Storing state cross-border would mean that the authoritative record of a sovereign zone’s topology is, itself, resident outside the jurisdiction—a situation that is difficult to defend to a regulator and potentially incompatible with the data residency requirements that the zone was created to enforce.
State file access must also be governed. Because the state file contains the full topology, read access to it is equivalent to a detailed map of the sovereign zone’s infrastructure. Terraform’s remote state data source allows one stack to read the outputs of another, which is useful for composing large environments but creates a cross-stack dependency that must be managed with the same care as a cross-zone network connection. Locking must be enabled on the state backend to prevent concurrent applies from corrupting the state; all major remote backends—S3 with DynamoDB locking, Azure Blob with lease-based locking, Terraform Cloud—support this natively [2].
This is an easy mistake to make early in a programme and a difficult one to remediate later. State migrations are possible but operationally risky, requiring careful coordination between the move of state data to a new backend and the reconfiguration of all pipelines that reference it. Addressing state residency as a first-class architectural constraint, before the first regulated resource is created, is considerably less painful than retrofitting it.
Adding a new national deployment then becomes a matter of instantiating a known pattern with different parameters, rather than inventing a new pattern from scratch. The differences are visible in code review, not hidden in console history.

Every large organisation has its own internal map: lines between departments, domains, environments and risk levels. Without care, a multi-cloud estate flattens that map into a tangle of resources sprinkled across accounts and subscriptions, with no structural expression of the organisational hierarchy that determines who owns what and who is accountable for what. IaC gives you a way to pull organisational structure into the cloud, making it visible in the codebase rather than relying on the personal knowledge of those who built the estate.
The foundational move is account-level separation. Rather than placing all environments and domains within a single cloud account or subscription—with access managed entirely through IAM policies—well-governed estates use separate accounts for different environments and domains, provisioned through code. An AWS Control Tower or Azure Landing Zone deployment represents exactly this: a codified template for the account structure, identity baseline, networking skeleton and logging configuration that should exist in every account before a workload lands there. For sovereign operations, this template includes zone-specific configuration: which logging destinations are approved for this account, which identity providers it trusts, which regions it is permitted to use.
Clear naming and tagging conventions, enforced in modules, mean that from any resource an engineer—or an agent—can infer the environment, domain and sovereign zone without consulting an out-of-date register. This matters operationally: when an alert fires at 03:00, the responder should not need to cross-reference the resource identifier against a spreadsheet to determine whether they are looking at a regulated or unregulated environment, or whether the data involved requires special handling. That information should be readable from the resource’s own metadata.
From a sovereign perspective, structural account separation has two further effects. First, it becomes obvious when something is in the wrong place: a regulated workload in a general-purpose account, or a shared service bleeding into a zone where it does not belong, is visible in the resource hierarchy rather than buried in flat resource lists. Second, it gives agentic systems something to stand on: an agent can see that this Terraform stack corresponds to “EU retail prod,” with all the constraints that implies, without needing to reverse-engineer the cloud provider’s internal models. The account structure is itself a sovereignty assertion, and it should be treated as such.
If sovereignty has a heartbeat, it pulses through three layers: network, identity, and keys. Those are the layers where a single misconfiguration can turn a carefully designed sovereign architecture into a hollow promise. A network rule that allows unexpected traffic to cross a zone boundary, an IAM policy that grants broader trust than intended, a key rotation schedule that was quietly disabled: any of these can undermine the sovereignty guarantees that the rest of the architecture is built to provide.
Beyer and colleagues observe in Site Reliability Engineering that the reliability of complex systems is ultimately determined not by their average behaviour but by their worst-case failure modes, and that the only reliable way to manage those failure modes is to make them visible and testable [6]. Nowhere in the cloud estate are the failure modes more consequential than in networking, identity and key management—and nowhere is visibility more difficult to maintain without code. A VPC route table altered through the console leaves no trace in Git; an IAM policy updated through the AWS web interface does not trigger a pull request review; a KMS key whose deletion protection was disabled by a well-meaning engineer pursuing a different goal may not be noticed until a recovery operation requires that key.
Codifying these three layers brings several properties that are directly relevant to sovereign operations.
Networks managed as code can be reasoned about statically, before deployment. A Terraform plan for a network change shows, in human-readable form, every subnet, route, security group and peering connection that will be modified. Automated tools can parse that plan and verify that it does not introduce any cross-zone paths that violate sovereignty policy—long before the change is applied. Network segmentation between sovereign zones becomes an architectural assertion, encoded in code and validated by policy, rather than a convention that is upheld through operational discipline and violated the moment an engineer is under pressure.
Identity managed as code allows trust relationships to be reviewed with the same rigour applied to network changes. Every IAM role, every trust policy, every permission boundary is visible in version control. Pull requests that attempt to grant sts:AssumeRole to principals from a different account or a different zone trigger a policy check that fails the pipeline if the trust relationship is not in the approved list. Excessive permissions that would be invisible in a console—a role with Action: "*" and Resource: "*" that was created for debugging two years ago and never removed—become visible during a pull request review and can be detected by automated scanning.
Keys managed as code ensure that every KMS key, HSM partition, and secret has a corresponding resource definition, with its rotation schedule, deletion protection, and key policy explicitly stated. Terraform’s aws_kms_key resource, for example, accepts a key_policy argument that specifies the full JSON policy governing who may use, manage and delete the key [2]. When that policy is reviewed in a pull request, it is clear whether the right principals have been granted the right permissions. When the key is deployed, the rotation schedule is enabled by default because the module’s default value is set to enable_key_rotation = true; disabling it requires an explicit override that is visible in code review.
Policy-as-code tools sit naturally on top of this. Open Policy Agent (OPA), a policy engine maintained under the CNCF umbrella, provides a general-purpose language (Rego) for expressing rules against structured data, including Terraform plan output as JSON [7]. An OPA policy for sovereign operations might contain rules such as: “no resource may specify a region not in the approved list for its zone classification,” “no KMS key may be created without automatic rotation enabled,” “no security group may allow inbound traffic from 0.0.0.0/0 on any port other than 443,” and “no IAM role may trust a principal from an account outside the approved set for this zone.” These rules run in the CI pipeline, against the Terraform plan, before any reviewer sees the pull request. They run again in the GitOps controller’s admission webhook before any change is applied to the cluster. They run in a scheduled scan against the live environment to catch drift. Rules written once enforce themselves continuously, without requiring anyone to remember to run a checklist.
The DORA Regulation reinforces this requirement from the regulatory side, mandating that financial entities implement ICT risk management frameworks that operate continuously rather than periodically [8]. Policy-as-code is the technical implementation of that requirement: it transforms the periodic checklist into a continuous enforcement mechanism that cannot be skipped under time pressure.

Every organisation that embraces IaC eventually discovers the joy and pain of modules. On the one hand, modules allow reuse and consistency: instead of re-writing the same VPC configuration in seventeen different stacks, you write it once, test it, and reference it. On the other hand, a wild module ecosystem can become just as messy as a wild console: dozens of modules, written at different times, with different conventions, different levels of quality and different assumptions about what is and is not enforced. The trick is deliberate curation.
The platform engineering model—a dedicated team responsible for the internal developer platform, including the IaC module library—is the appropriate organisational answer to this curation problem. Platform teams own the sovereign zone modules, set the standards they encode, version them with care, and communicate breaking changes through established channels. Product teams are consumers, not authors, of sovereign infrastructure; their job is to choose the right module from the library and configure it with the parameters appropriate to their workload.
A regulated database module, built and maintained by the platform team, might enforce encryption of data at rest using a KMS key managed by the zone’s key management team; require that audit logging be enabled and directed to the zone’s approved log sink; mandate that automated backups be enabled with retention periods meeting regulatory minimums; and restrict which IAM roles may administer or query the database to a list derived from the zone’s approved operator groups. A product team instantiating this module inherits all of those properties without needing to understand the regulatory requirements that motivated them. If the regulation changes—say, a new retention period is mandated—the platform team releases a new module version, product teams are notified through the dependency management tooling, and they update their stacks. The update is a pull request, visible to reviewers, tested by the CI pipeline, and auditable indefinitely.
A sovereign cluster module—providing a Kubernetes or OpenShift cluster suitable for regulated workloads—might stand up the cluster with standard admission controllers that reject non-compliant pod specifications; connect the cluster to the correct identity providers and key services for the zone; configure network policies that enforce east-west segmentation between namespaces of different sensitivity levels; integrate with the zone’s log forwarding infrastructure; and enable the audit log, directing it to an immutable log sink outside the cluster’s own namespace. As with the database module, product teams get all of this by default. The cluster they receive is not a blank Kubernetes cluster with a note saying “please configure this securely”; it is a cluster that is, by construction, in the correct configuration for its zone.

The modules become contracts between risk, platform and product: codified, versioned, reviewable. Risk teams can audit the modules to confirm they encode the required controls. Platform teams can evolve the modules as standards change without requiring product teams to understand the underlying regulatory driver. Product teams can deploy with confidence that the infrastructure they are using meets the organisation’s sovereign posture, because the code they reference is the same code that the risk team has approved.
Pulumi offers an alternative model worth noting. Rather than HCL modules, Pulumi allows organisations to publish reusable infrastructure components as ordinary library packages—installable via pip, npm, or NuGet—with full support for typing, documentation and testing frameworks familiar to software engineers [3]. For organisations whose platform teams are more comfortable in software engineering patterns than in HCL, this can lower the barrier to creating high-quality, well-tested sovereignty modules. The underlying principle is identical: encode sovereign constraints once, distribute them as a versioned artefact, and let consumers inherit them by reference.
So far, IaC has sounded like something that happens at “build time.” In practice, infrastructure changes constantly: new services appear, old ones are retired, capacity is adjusted, networks are refactored, security patches require configuration changes, and compliance requirements evolve. GitOps is how we extend the discipline of IaC from initial provisioning to continuous change management: the ongoing, day-to-day process of keeping a complex, multi-cloud estate aligned with its declared intent.
The definitive articulation of GitOps comes from the CNCF GitOps Working Group, which published GitOps Principles v1.0 and identified four foundational principles [9]. Understanding them precisely matters, because “we use Git for our infrastructure code” is a much weaker claim than “we practise GitOps.” The former describes a version control habit; the latter describes a complete operational model in which the version control system is the authoritative source of truth and automated controllers are responsible for bridging the gap between declared and actual state.
The first principle is declarative. A GitOps-managed system describes its desired state declaratively, in files, rather than through imperative scripts or sequences of commands. This is the IaC foundation already established in earlier sections: Terraform HCL, Kubernetes manifests, Helm chart values, Ansible playbooks stored in structured form. The system can always be asked “what should this look like?” and produce a complete, human-readable answer. There is no ambiguity about whether a given resource should or should not exist; the answer is in the file.
The second principle is versioned and immutable. The desired state is stored in Git, which provides an immutable, append-only history. Every change carries a commit hash, an author, a timestamp and a human-readable diff. There is no such thing as a change without an author. Reverting is not an emergency operation requiring specialised knowledge; it is a git revert commit that is itself subject to the same review and approval process as any other change. For sovereign operations, this creates an audit trail that is both technically tamper-resistant—Git’s cryptographic hashing makes undetected modification of history extremely difficult—and operationally legible: an auditor can examine the history of any file in the repository and reconstruct exactly how the system evolved.
The third principle is pulled automatically. Rather than a CI pipeline pushing changes into the target environment—a model that requires the pipeline to hold administrative credentials for every target—GitOps controllers pull from Git and apply changes within their own scope of authority. This inversion of the trust model is significant for sovereign operations. No external system needs write access to production environments, which means that a compromise of the CI pipeline does not automatically translate into a compromise of the production estate. Controllers run inside each environment, authenticate to Git with read-only credentials, check for new desired state, and apply it locally. The blast radius of a pipeline compromise is confined to the credentials the pipeline holds, which, in a pull model, are readers rather than writers.
The fourth principle is continuously reconciled. Controllers do not merely apply changes on commit and then wait for the next commit; they continuously compare actual state with desired state and correct divergence. The reconciliation interval—typically between 30 seconds and five minutes in most controller implementations—defines the maximum time that drift can persist before it is detected. A manual change made through the cloud console—perhaps a network engineer adjusted a security group rule in response to an incident—will, within the next reconciliation cycle, be detected and either reverted automatically or surfaced as a conflict requiring human attention. In a sovereign architecture, this is not merely a useful feature; it is a control. Console access by a cloud provider’s support engineer, whether authorised by a support ticket or not, creates drift that is detected and recorded rather than silently persisting. The GitOps controller becomes, in effect, a sovereignty watchdog.
The two dominant GitOps controllers at infrastructure scale are Argo CD and Flux, both of which are CNCF projects with production deployments at significant scale. Argo CD provides a rich web interface presenting the reconciliation state of every managed application as a graph of resources, making it immediately visible when any component has drifted from its desired state [9]. Its application model—in which a named Argo CD Application resource binds a Git source to a target cluster and namespace—is intuitive and aligns well with team-oriented ownership. Flux is more modular in its architecture, composing separate controllers for source management, kustomizations and Helm releases, which makes it easier to adopt incrementally and to customise for non-standard deployment patterns [9]. Both implement the four GitOps principles; both support multi-cluster deployment; and both are production-grade tools with active communities and commercial support options. The choice between them is largely one of operational style, existing toolchain investment, and the team’s preference for a unified UI versus a composable controller model.
GitOps is not limited to Kubernetes application delivery, despite its early associations with that space. For infrastructure itself—the Terraform stacks that define sovereign zones—there are two established patterns. Terraform Cloud (now HashiCorp Cloud Platform) provides a managed remote execution environment where plans and applies are triggered by pull requests or Git push events, with a full run history, approval gates, policy-as-code integration (Sentinel or OPA), and an audit log integrated into the workflow [2]. For organisations comfortable running their Terraform execution environment as a SaaS service, this is a mature and well-integrated option. Atlantis is a self-hosted alternative: it runs as a small, stateless service inside your own environment, listens for pull request events from GitHub, GitLab or Bitbucket, runs terraform plan and comments the output directly onto the pull request, and requires explicit approval before executing an apply [2]. For sovereign operations, Atlantis is particularly attractive precisely because it runs inside the zone: the system that holds authority to modify EU-regulated infrastructure resides within the EU environment, authenticated to EU-resident state backends, and does not depend on a SaaS control plane whose data residency may be ambiguous.
The approval workflow in a well-designed GitOps pipeline for sovereign infrastructure has three stages that build on each other without substituting for each other. The first stage is peer review: a human engineer—not the author of the change—reads the Terraform plan output attached to the pull request, understands what resources will be created or destroyed and what arguments will change, and approves at the pull request level. This is the professional judgement gate: the reviewer is checking that the change makes sense, aligns with architectural intent, and is not accidentally destructive. The second stage is automated policy validation: a step in the CI pipeline that runs OPA, Checkov, Trivy, or a comparable policy-as-code engine against the Terraform plan to verify that no rules are violated—no disallowed regions, no encryption gaps, no privilege escalation paths, no missing tags. The policy check runs without human involvement and fails the pipeline before a merge is even possible if any rule is breached. The third stage is explicit human approval for production: for changes to production or regulated environments, a named individual from the appropriate authority group—distinct from the original pull request reviewer—provides a second, explicit approval within the GitOps controller’s approval mechanism (an Argo CD AppProject approval annotation, or an Atlantis atlantis apply comment from an authorised user). This three-stage model means that no single person and no single automated system can unilaterally authorise a change to a sovereign zone. Accelerate identifies the combination of automated quality gates and peer review as a key differentiator of high-performing engineering organisations, finding that it reduces change failure rates without sacrificing deployment frequency—demolishing the oft-made claim that governance and velocity are in fundamental tension [5].
Drift detection is the GitOps property that most directly supports continuous compliance, and it closes the loop between the governance enforced at change time and the governance of the live environment. If someone creates a resource through the console—whether out of necessity, convenience, or error—the GitOps controller detects, within its next reconciliation interval, that actual state has diverged from desired state. In Argo CD, this surfaces as an “Out of Sync” status on the application, visible in the UI, queryable via API, and configurable to trigger an alert [9]. In the Terraform/Atlantis model, a scheduled plan run produces a non-empty diff—resources that exist in reality but not in code, or resources that exist in code but differ from reality—which becomes an alert or a ticket in the incident management system. In either case, the drift is not invisible: it generates a signal that can feed into observability pipelines, trigger human review and, if policy dictates, auto-revert without human intervention. For DORA compliance, this continuous reconciliation directly addresses the regulation’s requirement to “continuously monitor, log and report on ICT-related incidents” and to maintain systems in their approved configuration [8]. Deviations from the declared secure baseline are surfaced automatically rather than discovered in a quarterly audit by which point they may have persisted for months.

Everything we have said so far about IaC and GitOps sets the stage for one of this book’s central arguments: agentic operations. AI-driven agents can only operate safely at scale if they have something stable and principled to hold on to. Infrastructure as code, combined with policy-as-code and GitOps, is precisely that something.
The fundamental reason agents must act through IaC rather than directly against cloud APIs is not primarily technical; it is a question of accountability, reversibility, and the integrity of the declared estate. A direct API call made by an agent is difficult to distinguish from a direct API call made by a compromised credential: both arrive at the cloud provider’s control plane with valid authentication, both succeed or fail with only a provider audit log entry as evidence, and both leave a change in production that may not be reflected anywhere in the declared estate. The agent’s intentions—however well-formed at the time—cannot be verified after the fact, and the change cannot be safely reversed without understanding everything else the agent modified in the same session. If the agent made ten changes in rapid succession, as agents are inclined to do, the combined effect may be deeply entangled by the time a human reviews the audit log. Beyer and colleagues describe this as the core tension in operational automation: systems that can act faster than humans can review create reliability risk, and the answer is not to slow the automation but to route it through channels that preserve visibility and control [6].
The IaC-and-GitOps model resolves this tension by making the agent’s proposed changes inspectable before they execute. Consider the two agent archetypes introduced in this book’s architecture—the Concert and Orchestrate agents, operating within the IBM Concert and IBM Orchestrate platforms respectively. When a Concert agent, monitoring the performance of a regulated workload, identifies that the service has been under-provisioned relative to its SLO targets and determines that additional compute resources are required, the correct action is not to call ec2:RunInstances directly. The correct action is to generate a Terraform change—a modified instance count or node pool size in the relevant HCL file—commit it to a feature branch, open a pull request against the zone’s infrastructure repository, and wait. The Terraform plan output is automatically generated and attached to the pull request as a comment. Policy checks run in CI. A human reviewer reads the plan, confirms it is sensible, and approves. If everything is consistent with the zone’s constraints, the GitOps controller or Atlantis workflow applies the change. If the agent’s reasoning was subtly wrong—perhaps it chose an instance type not approved for the jurisdiction, or its capacity calculation was based on a signal anomaly—the policy gate catches the type mismatch before any change reaches production, and the human reviewer catches the reasoning error.
The same pattern applies to configuration changes. An Orchestrate agent responding to a security event—perhaps anomalous API call patterns suggesting an over-privileged role is being abused—might determine that a particular IAM role needs its trust policy tightened immediately. Rather than calling iam:UpdateAssumeRolePolicy directly and leaving a change that is neither in Git nor reflected in the Terraform state, it generates an Ansible playbook task or a Terraform resource modification, proposes it as a pull request to the identity management repository, and attaches its reasoning as a PR description: the specific alert that triggered the response, the API calls that were flagged, the confidence level, and the recommended remediation. The human reviewer sees both the proposed change and the chain of evidence that led the agent to propose it. Approval is explicit, attributable, and—because the change flows through the normal GitOps pipeline—automatically applied to the Terraform state and reflected in all downstream audit artefacts.
The agent-to-Git workflow can be implemented with varying levels of autonomy calibrated to the risk of the target environment. At the most conservative end, the agent generates a draft change and opens a pull request, but human approval is required for every apply regardless of environment or risk level. This is appropriate for any zone carrying a regulated or sensitive classification, and for any change affecting network topology, identity, or key management. At a less conservative setting, the agent may be permitted to auto-apply changes in non-regulated development environments if all policy checks pass—a setting appropriate for routine capacity adjustments or dependency updates in sandboxed environments. The sovereignty constraints embedded in the module registry and the OPA policy library do the heavy lifting in both cases: because agents reference the same shared modules as human engineers, the sovereignty constraints are enforced by design rather than by agent intelligence. An agent that generates a Terraform change referencing the eu-regulated-cluster module cannot place that cluster in a non-EU region, because the module’s own variable validations and precondition blocks will fail the plan before it is even proposed as a pull request. The agent does not need to understand, explicitly, that “EU regulated means EU regions only”; that knowledge is encoded in the module it is calling, and the module enforces it without delegation.

This architecture has a further advantage that is easily overlooked: it makes agent behaviour auditable in the same system as human behaviour. The Git history of an infrastructure repository does not need a separate “agent action log”; the agent’s pull requests are commits, authored under the agent’s service identity, with descriptions written by the agent that explain its reasoning. An auditor—or a post-incident reviewer—can look at the repository history and see, interleaved with human commits, the agent’s proposed changes, the policy check results, the human approvals, and the apply records. There is no separate system to query, no log format to translate, and no gap in the audit trail.
This is the world GitOps and policy-as-code practitioners describe: automated actors—human or machine—operating within a closed-loop control system, with Git as the ledger and policy engines as the conscience [9]. For sovereign operations, that ledger and conscience encode not only technical safety but also regulatory and jurisdictional constraints. An agent that tries to move a workload into a non-compliant region will find its pull request failing checks within seconds of being opened. An attempt to open a cross-zone network path that violates policy will be blocked by gates that do not care whether the actor is a shell script, a platform engineer, or a large language model running within an orchestration framework.
IaC gives agents a grammar for topology; policy-as-code and GitOps give them rules; sovereignty gives them boundaries. Together, the three create an operating environment in which agentic action is not dangerous but genuinely useful: fast enough to respond to operational signals, constrained enough to remain within sovereign obligations, and transparent enough to be audited after the fact without special tooling or reconstruction effort.
If you look back across the chapters so far—zero-copy integration, sovereign zones, observability, events and lineage, continuous compliance—a pattern emerges. Many of the desirable properties we seek depend on knowing, and being able to change, the structure of the estate with confidence. Observability without a reliable description of what is being observed is contextless. Continuous compliance without an executable definition of the compliant state is aspirational. Agentic operations without a principled substrate to act upon are ungoverned.
Infrastructure as code is the spine that holds that structure upright. It performs this role across five dimensions that are worth making explicit.
First, it turns topology from a sketch into executable intent. Every resource, relationship and constraint in the estate is expressed in a language that machines can apply and humans can review [2]. The topology is not a diagram that may or may not reflect reality; it is code, and the gap between the code and reality is what the GitOps controller exists to close.
Second, it makes networks, identities and keys visible to machines and humans in the same way, removing the asymmetry of information between those who built the system and those who must operate or audit it. A new engineer joining the platform team can read the repository and understand the sovereign architecture without asking anyone; an auditor can query the IaC codebase and the state files without needing an explanation tour.
Third, it provides the substrate on which policy-as-code and GitOps can build continuous compliance. You can only enforce rules against something that is expressed as data [7]. The OPA policy that checks whether resources are in approved regions only works if the resources are declared in Terraform plans that OPA can parse; the GitOps controller that detects drift only works if there is a declared desired state to drift from.
Fourth, it gives observability something to annotate and lineage something to map against. When an observability platform surfaces an anomaly on a resource tagged jurisdiction=EU, data-classification=restricted, it knows which constraints govern the response and which operators are authorised to act. When a lineage system traces a data flow, it can look up the IaC definition of each component in the flow and understand its sovereign properties.
Fifth, it gives agents something safe to manipulate. Not safe in the sense of harmless—IaC changes can destroy resources if wrongly constructed—but safe in the sense of governed: subject to the same review, policy and approval processes that govern human changes, and auditable in the same system as human changes.
Without IaC and GitOps, sovereign operations remain aspirational, held together by diagrams, trust and the personal knowledge of senior engineers who may not be available at three in the morning. With them, sovereignty becomes a tangible property of the running system, encoded not only in contracts and policies but also in the very code that describes where and how the system lives.
default_tags and OPA policy, and provider aliases made explicit in every cross-boundary resource.Infrastructure as code is not the most glamorous topic in a book about agentic AI and sovereign cloud operations, but it is arguably the most foundational. Without it, every other capability described in this book—event-driven observability, continuous compliance, conversational interfaces, and autonomous agents—operates against a substrate that is only partially known and imperfectly controlled. The sovereign zones that regulators require us to maintain, the data residency boundaries we are obligated to enforce, and the jurisdictional constraints that distinguish one deployment from another: none of these can be reliably upheld if the infrastructure that expresses them lives only in consoles, wikis and the memories of senior engineers who may be unavailable, unreachable, or simply mistaken about what they remember.
With a mature IaC and GitOps foundation in place, the estate becomes something that can be precisely described, continuously verified, safely modified by authorised actors—human or agentic—and confidently audited. The Terraform module registry becomes a library of vetted sovereignty patterns, each version a recorded agreement between risk, platform and product. The GitOps pipeline becomes the sole authorised path through which changes reach production, with every step logged, every approval attributable, and every deviation from approved configuration detected in operational time. The policy-as-code layer becomes the standing, continuous enforcement of regulatory requirements, running on every plan and every reconciliation cycle rather than appearing only in the quarterly audit report.
The next chapter turns from the skeleton to the muscles. If IaC defines the structure of the estate and GitOps governs how that structure changes, runbooks and configuration automation define how the estate responds to events: how it heals under pressure, how it escalates edge cases to human judgement, and how it enforces consistent, sovereignty-aware behaviours across thousands of nodes and services without requiring a human hand on every keyboard. The same principles that make IaC governable—declarative intent, version control, policy enforcement, human approval gates—apply with equal force to the automation of operational response.
[1] European Banking Authority, “Guidelines on ICT and Security Risk Management,” EBA/GL/2019/04, November 2019. [Online]. Available: https://www.eba.europa.eu/regulation-and-policy/internal-governance/guidelines-on-ict-and-security-risk-management
[2] HashiCorp, Terraform Documentation, 2024. [Online]. Available: https://developer.hashicorp.com/terraform/docs
[3] Pulumi Corporation, Pulumi Documentation, 2024. [Online]. Available: https://www.pulumi.com/docs/
[4] Red Hat, Ansible Documentation, 2024. [Online]. Available: https://docs.ansible.com/
[5] N. Forsgren, J. Humble, and G. Kim, Accelerate: The Science of Lean Software and DevOps: Building and Scaling High Performing Technology Organizations. Portland, OR: IT Revolution Press, 2018.
[6] B. Beyer, C. Jones, J. Petoff, and N. R. Murphy, Eds., Site Reliability Engineering: How Google Runs Production Systems. Sebastopol, CA: O’Reilly Media, 2016. [Online]. Available: https://sre.google/sre-book/table-of-contents/
[7] Cloud Native Computing Foundation, Open Policy Agent Documentation, 2024. [Online]. Available: https://www.openpolicyagent.org/docs/latest/
[8] European Parliament and Council of the European Union, “Regulation (EU) 2022/2554 of the European Parliament and of the Council on digital operational resilience for the financial sector (DORA),” Official Journal of the European Union, vol. L 333, pp. 1–79, December 2022. [Online]. Available: https://eur-lex.europa.eu/legal-content/EN/TXT/?uri=CELEX:32022R2554
[9] CNCF GitOps Working Group, “GitOps Principles v1.0,” Cloud Native Computing Foundation, 2021. [Online]. Available: https://opengitops.dev/
Sovereign Cloud Operations: AI-Driven Management of Sovereign Estates
© 2026 by Alan Hamilton
is licensed under CC BY-SA 4.0