Ruslan Akchurin

The account is not the boundary

Porting an IaC operating model from GCP to AWS.

Nothing about a well-shaped infrastructure codebase depends on the cloud underneath it. Ownership decides the cut, lower tiers publish and higher tiers consume, environment issues the , shared mutations carry binding rules. Those rules name no provider; moving between GCP and AWS changes none of them.

What changes is how much of one handoff stays visible. GCP lets a workload boundary look like a single object: a project sits under a folder; one environment component creates it, enables APIs, attaches deploy federation, grants Shared VPC use, and publishes the assigned reference inside the same apply. AWS refuses to bundle that. The same boundary spreads across an asynchronous account lifecycle, several policy planes, regional networks, and audit systems that converge on their own schedules. The protocol was always there. GCP compresses it into one handoff; AWS runs each step as a separately owned system — the entire difference, and it is operational, not conceptual.

GCP earns the compression honestly. For a startup, an embedded identity provider, a shared network built into the product, and an organisation hierarchy that works on day one make GCP the better cloud — the bundle is too good to ignore, and I would pick it again for a small team that needs its first boundary this week. It is still packaging; the model is the part that ports.

Properties translate; products don't

The usual first step is a vocabulary swap — project becomes account, folder becomes OU, Shared VPC becomes the networking account — as if the port were a rename. Each of those analogies imports a GCP operating property into an AWS mechanism that does not carry it. What translates reliably is the property underneath: an isolation unit and its vending call, an inheritance plane, a shared network surface. The matrix carries all of them; the rest of this article walks the three that take the most weight.

GCP → AWSNot equivalent becauseOperational consequence
Organisation hierarchy → Organizations root and OUsFolder IAM bindings grant access down the tree; OU-attached policies restrict and never grantOU placement is policy and lifecycle metadata; the boundary is the account plus its admitted capabilities
Project as isolation unit → AWS accountAn account is a stronger security and failure boundary than a project-shaped namespace; quotas and API rates stay scoped to the unit on both cloudsAccount lifecycle stays outside application IaC, behind a separately authorised executor
Project vending → CreateAccountCreation is asynchronous, starts under the root, needs a unique root email, and installs a broad management-access roleThe call returns a request handle, not an account; the ID arrives when creation succeeds, the assigned boundary only after reconciliation completes
Managed landing zone → Control Tower Account FactoryService Catalog-backed account vending plus an enrolment lifecycle with baselines, controls, and driftStays a private implementation of the vending protocol, never the public contract
Terraform vending workflow → Account Factory for TerraformBuilds on Control Tower and Service Catalog; not an independent peerJustified by an existing Control Tower lifecycle and a real customisation fleet
Cloud Identity groups → external IdP, Active Directory, or IAM Identity Center directoryGroups reach accounts through permission sets that materialise IAM roles per accountAuthentication, group source, assignment, provisioned role, and session are separate steps to prove
Hierarchical IAM inheritance → identity, resource, trust, and key policies, plus SCPs/RCPs and boundariesAuthorisation is an intersection and union across planes; SCPs and RCPs limit and never grantGrants and limits stay separate; load-bearing paths are tested, not inferred from policy files
Workload service account → IAM role with service trust or workload federationThe permission policy is one side; trust, resource, and key policies may all be requiredWorkloads run on temporary credentials; static keys and IAM users stay outside the default
CI federation → OIDC/SAML provider plus STS assumptionTrust is account-local and has to be bootstrapped before the tenant pipeline existsBootstrap creates the tenant path, proves it, then expires its own broader authority
Global VPC → regional VPCsVPCs are regional and subnets are zonalRegion becomes an explicit contract context and failure domain
Shared VPC → RAM-shared subnetsThe owner controls the VPC, routes, NAT, endpoints, and resolver surfaces; participants own ENIs and security groups on participant quotasFits only where participants accept common operational fate and a two-stage teardown
Shared network with stronger isolation → per-account VPCs plus optional Transit GatewayConnectivity becomes explicit attachments, route tables, IP allocation, and DNS associationsBuys account-owned lifecycle and a regional blast radius; transit waits for cross-boundary reachability
Private DNS → Route 53 private hosted zones plus Resolver rules and endpointsZone ownership, VPC association, forwarding, and cross-account sharing are distinct operationsDNS admission and teardown belong in the network contract
Organisation audit roots → a CloudTrail organization trail, delegated Config/Security Hub/GuardDuty, a log-archive accountOrganisation-wide collection is opt-in per service, each with its own delegated-admin pathAudit readiness is observed per service, not assumed from the org tree
Billing and quotas → consolidated billing plus account- and region-scoped quotasThe management account pays, but limits stay account- and region-scopedReadiness distinguishes requested increases from effective limits
KMS ownership → regional keys, key policies, grants, cross-account caller policiesCross-account use needs permission on both the key policy and the caller's IAM pathKMS stays a separately owned capability, proved on the real cross-account path
IaC bootstrap → Organizations creator plus account-local execution rolesCreator credentials and account-local execution are different authorities with different lifetimesBootstrap trust is installed, proved, then expired

Every row has the same structure: the mechanism exists on both sides, and the operating property changed thickness. Nothing in the two right-hand columns asks for a new rule. The account is the model's assigned boundary; the policy planes are its binding rule, with holder, operations, and surface finally spelled out by the provider itself; regionality is contract context.

The account exists before the boundary is ready

On GCP, the gap between "project created" and "workload can deploy" is short enough to hide inside one apply. On AWS, that gap is the design problem. CreateAccount is asynchronous: the call acknowledges a request, the account ID arrives only when creation succeeds, and the account then needs OU placement, contacts, a security baseline, audit enrolment, identity materialisation, network admission per region, and quota verification — each owned by a different system, several of them eventually consistent. An account ID in hand proves almost nothing about the boundary.

This is the , and the environment tier still owns it. The membership rule survives untouched: the lower tier issues the boundary and publishes the reference upward. What changes is that issuing stops being a create call and becomes reconciliation. Capability owners — account lifecycle, identity, security and audit, network, quota, cost — publish for what they have proved. A small coordinator validates those receipts and links them; it owns none of the underlying resources and cannot approve its own evidence. The workload-facing product is one versioned AssignedAccountRef that appears only after every required claim holds. READY names that publication; every earlier state is platform-internal. Before READY there is no reference to consume, which is exactly how the resolver wants composition to fail: before any provider call, with the missing claim named.

The request is a product

A product team requests a boundary product: owner, environment, cost identity, required regions, and . The platform derives the access and network profiles from that product. A team that needs something different gets an explicit exception with its own approver; the default never widens. The product carries a version, and the derived profiles advance by generation. Acceptance is synchronous: the platform validates the request, checks the caller against the recorded owner, and stores the request durably before any provider call. It is also the last synchronous answer the requester gets.

One AssignedAccountRef covers one workload environment account. A workload that needs several accounts receives several references and composes them above the boundary; a shared account is a common-fate exception with its own tenancy and exit contract.

Acceptance sets the pattern, and every later lifecycle operation repeats it. A request to change profile, quarantine, retire, or close arrives from a caller the platform can authenticate — a person signing in through the workforce path, or a pipeline presenting its federated identity — and has to match the owner recorded at acceptance. The match alone is not enough: each operation carries a separate permission, so owning a boundary does not by itself authorise closing it. OU and policy exceptions, root-posture changes, and closure go further and require an authority independent of the coordinator. Behind the checks sit two records: the and the . Both are control-plane data in their own right: if that history can be rewritten, the receipts stop being evidence.

Choose the account factory deliberately

Three implementations can stand behind the same protocol; choosing one is an ownership comparison.

Direct Organizations plus a reconciler. The default here. It is the smallest machinery that exposes the true lifecycle: CreateAccount requests issued, account states observed, delegated stacks establishing security, audit, identity, and network readiness. The cost is that the platform itself owns the durable request record, recovery, drift classification, and evidence probes — the default holds only while that custom surface stays materially smaller than the managed alternatives.

Control Tower Account Factory. A managed landing-zone lifecycle built on Service Catalog provisioning: baselines, controls, enrolment, drift detection. It earns its second lifecycle when governance evidence and managed OU baselines are requirements rather than conveniences. Brownfield enrolment needs prerequisite cleanup, keeps existing VPCs, and fails outright on existing Config records unless AWS allow-lists the account; auto-enrolment is eventually consistent and can take hours. Its default VPC design must not decide the network boundary by accident.

Account Factory for Terraform. AFT adds a GitOps request-and-customisation workflow on top of Control Tower: repositories, pipelines, Step Functions, Terraform state, failure notifications. It pays for itself against a real fleet of repeatable account customisations, not as a reflexive Terraform preference.

Direct Organizations avoids the Control Tower lifecycle; it does not avoid lifecycle work. A like-for-like comparison counts workflow state, baseline installation, drift detection, brownfield handling, evidence, recovery tooling, and staffing on both sides. Whichever side wins, a common adapter wrapping every factory stays unbuilt. The vending protocol is already the abstraction: a request goes in, an AssignedAccountRef comes out, and the factory between them stays private. An adapter interface earns its place only when a second implementation actually runs.

Who owns which side

The split is the one the membership rule drew, with AWS nouns. The platform owns:

  • the root-email namespace and contact automation;
  • the boundary-product version, request record, account ID, OU placement, billing metadata, and observed lifecycle;
  • bootstrap trust, delegated administrators, audit enrolment, the security baseline, network admission, and readiness evidence;
  • suspension, quarantine, retirement, and closure.

The product team owns:

  • the workload intent: owner, environment, required regions, reachability, cost identity, and the lifecycle decision;
  • application resources, bounded runtime identities, workload-local policies, security groups, and records on delegated surfaces;
  • detaching its consumers during retirement, before the contract is withdrawn;
  • nothing in the Organizations management plane.

The provisioning sequence, stage by stage

Thirteen stages turn a request into a published boundary, and every stage names an owner. Owner means a responsibility, not a squad, a division, or a department: in a startup one person usually holds all of them, and the collapse loses nothing — the responsibilities stay distinct however few heads carry them. All but one stage existed on GCP too, folded invisibly into a single apply. The exception is root posture: a GCP project has no root user to secure, and every AWS account ships with one.

From accepted request to published boundary Thirteen owned stages connect an accepted request to a published AssignedAccountRef: each stage carries its owner and a timing pill whose tint groups the same timing, a failed stage parks in quarantine with evidence kept and resumes, and rejection happens only at acceptance, before any provider call. It shows Accept request (boundary coordinator), Allocate account identity (platform), Create account (organisation lifecycle), Place account (organisation lifecycle), Set contacts and root posture (platform and security), Apply baseline (platform and security), Materialise workforce access (identity platform), Establish CI and workload trust (platform and identity), Join required regional networks (network platform), Prove audit and KMS paths (security and platform), Verify cost and effective quotas (FinOps platform), Retire the bootstrap bridge (platform and security), Publish the boundary (boundary coordinator), and quarantined (any failed stage). The Accept request feeds the Allocate account identity. The Allocate account identity feeds the Create account. The Create account feeds the Place account. The Place account feeds the Set contacts and root posture. The Set contacts and root posture feeds the Apply baseline. The Apply baseline feeds the Materialise workforce access. The Materialise workforce access feeds the Establish CI and workload trust. The Establish CI and workload trust feeds the Join required regional networks. The Join required regional networks feeds the Prove audit and KMS paths. The Prove audit and KMS paths feeds the Verify cost and effective quotas. The Verify cost and effective quotas feeds the Retire the bootstrap bridge. The Retire the bootstrap bridge feeds the Publish the boundary. PROVISIONING SEQUENCE accept → publish · quarantine resumes Accept request boundary coordinator sync 1 Allocate account identity platform sync 2 Create account organisation lifecycle async 3 Place account organisation lifecycle eventual 4 Set contacts and root posture platform and security async 5 Apply baseline platform and security async 6 Materialise workforce access identity platform eventual 7 Establish CI and workload trust platform and identity eventual 8 Join required regional networks network platform async 9 Prove audit and KMS paths security and platform eventual 10 Verify cost and effective quotas FinOps platform eventual 11 Retire the bootstrap bridge platform and security sync 12 Publish the boundary boundary coordinator sync 13 unauthorised or duplicate: rejected, no provider call quarantined any failed stage parks here evidence kept resume · re-prove READY
From accepted request to published boundary

Completion is observed, never inferred:

  1. Accept request. Actor, immutable request ID, owner, and product version recorded.
  2. Allocate account identity. Unique root email, account name, and profile generation reserved.
  3. Create account. Creation status succeeds; the account reaches an active state.
  4. Place account. The observed OU matches the desired one, with inherited controls enumerated.
  5. Set contacts and root posture. Primary and alternate contacts observed; centralised root posture recorded.
  6. Apply baseline. Delegated services, logging, security reporting, and required roles observed.
  7. Materialise workforce access. The permission-set role exists and a human sign-in probe passes.
  8. Establish CI and workload trust. Bounded tenant roles pass positive probes; excluded origins fail the negative ones.
  9. Join required regional networks. Every required region shows its network cell, DNS, egress, and passing reachability claims.
  10. Prove audit and KMS paths. Events arrive at the intended sink; key use succeeds while administration stays denied.
  11. Verify cost and effective quotas. The cost owner is observed; every required quota is effective, not merely requested.
  12. Retire the bootstrap bridge. Routine and emergency paths work without it; broad creator access removed or constrained.
  13. Publish the boundary. The versioned AssignedAccountRef links account, access, network, quota, cost, and audit claims, each independently issued.

Failure handling inverts the . A partially provisioned account is never rolled back into non-existence: AWS accounts do not have a transactional lifecycle, and even closure is a durable state. A failed stage leaves the account in the catalogue — quarantined, observable, resumable from the stage that failed. The platform fails closed by withholding the reference, not by pretending the account never happened. Recovery stays narrow: creation retries only the failure reasons the docs mark transient, and a failed audit or KMS probe is classified first — eventual consistency still propagating, or a policy that is actually wrong. The first gets a retry with backoff; the second gets a fix; neither gets a weaker contract.

One consequence lands directly on IaC layout. The provider configuration for the new account needs an account ID and a role to assume, and neither exists until CreateAccount succeeds mid-apply. The apply that creates the account therefore cannot also deploy into it. The organisation lifecycle, the platform's member-account baseline, and the workload each keep their own stack and their own owner — the same downward dependency direction the model already required, now enforced by the tooling itself.

Identity separates grants from limits

GCP flattens authorisation into one visible granting plane: a grant at the folder flows down the hierarchy, and reading the policy tree reads the access. AWS splits the same question into a granting plane (identity policies, resource policies, role trusts, ) and a limiting plane (SCPs, RCPs, permissions boundaries, session policies). The planes compose by intersection, with documented exceptions, and the exceptions are why probes beat policy reading.

The expensive translation error lives here. An SCP looks like the AWS spelling of a folder-level grant, and it is nothing of the kind: an SCP can make access impossible, and it cannot make access possible. A platform that ships guardrails believing it shipped access has built an account nobody can use — or one that works only through a leftover bootstrap role, which is worse. The binding rule already named the request, operations, surface, and holder for every shared mutation; AWS makes each of those a separate artefact and adds a plane that only subtracts.

Five flows, one limiting plane

Each flow authenticates at a different place and carries its own proof. Permission sets materialise IAM roles in each account for people; everything else is a role with a trust to a specific authenticator. The emergency flow alone can fall back to root.

FlowAuthenticates atMaterialised in the accountGranted byLimited by
Human workforceIdentity Center directory, Active Directory, or external IdPAWSReservedSSO_* role from a permission-set assignmentPermission-set policies plus relevant resource and key policiesSCP/RCP, session duration, explicit deny
Workload runtimeAWS service identity or workload federationWorkload-owned role carrying the platform permissions boundaryRole policy plus resource and KMS policiesTrust conditions, constrained iam:PassRole, SCP/RCP, session policies
External CI / IaCOIDC or SAML IdPBounded tenant deploy role with federated trustRole policies plus cross-account target permissionsProvider-pinned issuer; audience and subject claims encoding repository, workflow, and ref; fork and PR exclusions; boundary
Cross-account platformSTS role assumptionPlatform-owned role in the member accountCaller permission plus target trust and target-role policyExternal-ID and source conditions, SCP/RCP, session policy
Break glass / rootSeparately tested emergency identity; centralised root sessions for supported tasksTime-bounded privileged session, or recovered root credential when unavoidableNarrow emergency policy or root capabilityApproval, monitoring, MFA where credentials exist, rapid removal

The planes do not compose politely everywhere. Under the documented evaluation logic, a same-account resource policy can grant directly to an IAM user or role-session principal around an implicit deny in a permissions boundary or session policy; explicit denies and applicable organisation controls still win. Protected resource policies therefore reject direct user and session principals unless the contract admits them, and the negative probes cover the permitted principal form.

KMS stays a separately owned capability rather than a sixth flow. Key administrators own policy changes, rotation, grants, and deletion; workload key users receive the required cryptographic operations and nothing else. A tenant role that can call PutKeyPolicy or ScheduleKeyDeletion owns the key, whatever the org chart says, and cross-account use needs permission on both the key policy and the caller's IAM path — so the probe has to run the real cross-account path.

Bootstrap trust expires

The flow worth walking end to end is tenant CI — the pipeline a product team deploys its workload with. Every workload depends on it, and it is the flow bootstrap contaminates most easily: a pipeline that keeps deploying through the creation-time role never gets narrower. Trust is account-local. The OIDC provider and the bounded deploy role live inside the member account, and until the platform creates them the pipeline has nothing to authenticate with and nothing to assume. The account is born with the opposite already in place: a management-access role with authority over everything in it. A new account has exactly one usable path in, and it is the widest it will ever have. Bootstrap therefore has a direction: install the narrow paths, prove them, expire the broad one.

  1. Organizations creates the account and the broad role. The platform records who created the account, the CloudTrail event that proves it, the account ID, and the role's name. That role is a skeleton key to everything in the account, so it goes on the books from its first second — a key that is not tracked cannot later be proved gone.
  2. A narrow platform session installs the steady state. The steady state is every path that will outlive bootstrap: roles for the security and audit tooling, the Identity Center wiring for human sign-in, the OIDC trust tenant CI will deploy through, the network operator role, and the emergency controls. Each arrives as its own named installation, so each can be proved — and later withdrawn — on its own.
  3. Probes exercise every declared path, both ways. What must work: the assigned human signs in, an admitted CI origin assumes its tenant role and nothing else, KMS use succeeds with both halves in place — the key policy and the caller's IAM. What must fail: forks, pull requests, excluded repositories, wrong refs, and wrong workflows assume nothing; protected resource policies turn away direct principals the contract never admitted; forbidden Organizations actions stay denied. A passing probe proves the path is reachable; only the failing probes prove the boundary.
  4. Broad bootstrap trust is removed or sharply constrained. The order matters: routine and emergency paths have to work without the skeleton key before it is removed, so that removing it is not the step that locks the platform out. While that key still turns, the boundary cannot reach READY.
  5. Rotation and containment stay explicit. There are no long-lived keys to rotate in this design — trust moves by changing the provider configuration. Containment is concrete: quarantine removes the assignments and the trust, applies deny controls, revokes sessions where AWS supports it, and records how long the credentials it cannot revoke will keep working.
One tenant CI path, both planes A tenant pipeline reaches its account only through matched origin claims: the OIDC trust admits or refuses before any session exists, the bounded deploy role is the entire granting plane, and the SCP, RCP, permissions boundary, and session policies subtract from that grant without granting anything. It shows tenant CI run (presents its federated identity), OIDC trust · member account (every admitted origin claim must match), bounded tenant deploy role (granting plane · role and resource policies), limiting plane (subtracts from the grant), admitted account-local surface (what the grant keeps after the limits), and no session (fork · pull request). The ID token path runs from the tenant CI run to the OIDC trust · member account. The claims match path runs from the OIDC trust · member account to the bounded tenant deploy role. The granted actions path runs from the bounded tenant deploy role to the limiting plane. The what survives path runs from the limiting plane to the admitted account-local surface. The OIDC trust · member account passes refused to the no session. GRANTS AND LIMITS origin claims → grant ∩ limit tenant CI run presents its federated identity issuer repository ref workflow OIDC trust · member account every admitted origin claim must match bounded tenant deploy role granting plane · role and resource policies limiting plane subtracts from the grant SCP RCP boundary session admitted account-local surface what the grant keeps after the limits ID token claims match granted actions what survives no session fork · pull request wrong ref · workflow nothing to assume refused an SCP grants nothing limits cap the grant; access comes from the role
One tenant CI path, both planes

Networks are regional before they are shared

A GCP VPC is global with regional subnets; an AWS VPC is regional with zonal subnets. That one line moves region out of implementation detail and into contract context. A second region is not another subnet in the same network — it is another admitted cell, with its own VPC or share, DNS association, egress posture, and failure domain. The NetworkRef survives; its cardinality changes. The assigned boundary carries one per required region, and the reference is withheld until all of them hold.

"Shared VPC becomes the networking account" is the shortcut that fails: naming an account decides nothing. The operating model is who owns routes, DNS, endpoints, and egress; which mutations application accounts are admitted to make; and how a participant leaves.

Two ownership profiles

The profile choice is an ownership decision before it is a topology one. Shared subnets keep the strongest Shared VPC resemblance and the strongest coupling: participants inherit the owner's operational decisions, and exit is two-stage by construction, because unsharing stops new placement without removing what participants already built. Per-account VPCs trade the noun resemblance for an account-owned lifecycle, with the platform owning transit, shared DNS, and the IP plan. Both patterns are documented AWS practice; neither is a universal default.

QuestionShared subnets via RAMPer-account VPC plus transit
What it isThe network account runs one VPC per region and shares subnets into application accounts; workloads deploy onto a network someone else operatesEvery application account runs its own regional VPC; the platform connects them through Transit Gateway only where reachability is earned
What the network account ownsEverything about the network: the VPC, subnets, routes, NACLs, NAT, endpoints, Resolver endpoints, and the Transit Gateway attachmentThe connective tissue: transit route domains, shared DNS, the IP plan, and optional central egress and inspection
What the application account ownsOnly what sits on the shared subnets: workload resources, ENIs, security groups, and flow logs for its own ENIsIts whole VPC — subnets, routes, security groups, endpoints — inside the platform contract
Who can break whomA route or NAT change by the owner lands on every participant at onceTransit and shared-service changes still fail wide; VPC-local changes stay inside one account
How a region joinsChoose which shared network the account belongs in, share the subnet, observe the association, prove placement, DNS, and egress, then publish the regional NetworkRefAllocate a CIDR, create the VPC, attach transit, associate the route domain, wire DNS and egress, probe, publish
How it tears downThe share is revoked first, which only blocks new placement; participants drain what they built; the owner surfaces come down lastWithdraw admission, drain, detach DNS, endpoints, transit, and IPAM, then delete the VPC once recorded consumers reach zero
When it fitsParticipants accept central ownership and common fate: sandboxes, centrally operated platformsAccounts need an independent lifecycle or their own regional policy

The admission contract replaces the bag of IDs

A project-shaped handoff passes a bag of raw VPC and subnet IDs and lets the consumer infer the rest. The replaces the bag with claims a reviewer can read. It names where the account landed: the region, the topology class, the VPC or route-domain identity, the admitted subnets or placement class. It names how traffic is meant to behave: the intended reachability, the DNS path, the egress and endpoint policy actually selected. It names who governs the edges: attachment authority, the readiness evidence behind each claim, and the detachment procedure for leaving. An AssignedAccountRef carries one NetworkRef for every required region; a region added later advances the profile generation instead of weakening the existing cells.

Workload code declares connectivity intent; the network owner applies changes to shared routes, DNS, endpoints, inspection, and egress. Organisation and account-local controls block unapproved internet gateways, peerings, transit attachments, and shared-route mutations, and reconciliation reports every route or association outside the published contract. That split is the model's binding rule applied to a regional surface.

IPAM, central inspection, shared endpoints, Transit Gateway, and Cloud WAN stay conditional capabilities. Transit is not a default: an isolated account needs no attachment, cross-VPC or on-premises reachability earns a Transit Gateway, and global segmentation has to earn Cloud WAN separately.

A layout that keeps the owners apart

The tree that satisfies every section above is ordinary:

AWS Organizations
├─ management account
# irreducible Organizations · billing · account lifecycle
├─ Security OU
│  ├─ security tooling account
│  │  # delegated security services · findings
│  └─ log archive account
# organization trails · immutable retention
├─ Infrastructure OU
│  ├─ network account
│  │  # transit · shared DNS · optional egress/inspection
│  ├─ platform account
│  │  # boundary coordinator · catalogue · CI
│  └─ shared-services account
# optional common registries/endpoints
├─ Workloads OU
│  ├─ product-a-nonprod
│  │  # workload state · bounded runtime roles · regional VPC
│  ├─ product-a-prod
│  │  # workload state · bounded runtime roles · regional VPC
│  └─ ...
├─ Sandbox OU
# reduced account product · bounded connectivity
└─ Quarantine / Suspended OU
   # failed onboarding or retirement isolation

The management account stays thin because nothing constrains it: SCPs do not apply to it, and AWS's own guidance is to use it only for tasks that require it. Irreducible Organizations, billing, and account-lifecycle operations stay; metadata, security tooling, log archive, and baseline execution sit behind delegated administrators and member-account roles. Delegation is uneven across services, so the small set of management-account automation that remains is recorded as such rather than wished away.

The two-party split from the vending section sharpens into eight boundaries: what each owns, what it publishes, and what it must never own. As with the stage owners, eight boundaries are not eight teams — all eight can sit with one person, and the table still names which responsibility is in play when a change lands.

BoundaryOwnsPublishesMust not own
Organisation lifecycleManagement-account executor, root, OUs, accounts, policy attachmentsAuthorised account-operation receipts and observed lifecycleApplication resources or tenant release state
Boundary coordinatorRequest state, product version, receipt validation, quarantine and retirement coordinationAssignedAccountRef linking separately owned claimsUnderlying IAM, network, audit, or account mutations; self-approved evidence
Identity platformIdentity source, groups, permission sets, assignments, emergency policyHuman-access and platform-role readinessWorkload runtime policies
Security and auditDelegated services, organization trails, findings, log retention, root postureEnrolment, reporting, and containment readinessOrdinary workload deployment
Network platformIP plan, optional transit, shared DNS, admission, optional egress and inspectionRegional NetworkRef and detach receiptsApplication ENIs, runtime security groups, workload services
FinOps platformCost-identity mapping, quota requests and verification, from the platform accountCost-owner and effective-quota claimsWorkload spend decisions or release state
Workload platform stackBounded tenant CI role, platform permissions boundary, approved VPC-local surfacesStable inputs for workload IaCOrganizations mutations, protected principals, shared transit or DNS changes
Workload stackServices, data, bounded runtime roles, workload policies, records on delegated surfacesBackends and endpoints for admitted consumersAccount creation, OU movement, shared routing, federation, audit principals

The platform applies in order

  1. Organisation stack. Organizations itself, OUs, baseline policies, integrated services, delegated administrators, the root and contact namespace.
  2. Account lifecycle executor. A minimal management-account path that creates and observes the member account, moves it, and returns signed operation receipts. Control Tower remains a separate selected implementation, not a pre-built adapter.
  3. Security, audit, and identity stacks. Enrol services, create steady-state roles and assignments, prove reporting and human and platform access.
  4. Regional network publishers. Create or admit each required cell, adding transit, DNS, endpoints, or egress only when the boundary product selects them, then prove declared reachability.
  5. Bootstrap handoff. Prove tenant CI and emergency paths, then remove or narrow broad creator trust.
  6. Boundary publication. The coordinator validates account, access, network, quota, cost, audit, and proof-expiry claims before publishing.
  7. Workload release. Resolves the boundary reference and stays inside the admitted account-local surfaces.

Drift has classes

Capability owners keep observing their claims after publication, and the coordinator keeps evaluating receipts. Blocking drift prevents first publication. Security-critical drift withdraws the affected capability, blocks new releases and role assumptions, applies containment, and quarantines the boundary until containment evidence holds. Repairable drift reconciles behind the published contract only while every published claim stays true; a stale or failed proof withdraws the claim. Accepted drift advances the desired profile through review. Control Tower's drift detection is one signal inside this model, not the model.

Failure modes, owners, containment

The machinery above fails in ordinary ways, and each failure already has an owner. The rows follow the boundary's own path — request, creation, placement, access, networks, audit and KMS, bootstrap retirement, closure — so every failure sits beside the stage that produces it. Each row answers the same three questions: what notices the failure, who owns the recovery, and how the platform fails closed while it is broken. Across all of them one rule holds: no recovery widens a trust, a route, or a policy to get unstuck.

FailureDetected byRecovery ownerFail-closed behaviour
Unauthorised boundary transitionCaller-to-owner binding, independent approval receipt, immutable audit eventPlatform and securityReject before provider calls; the coordinator cannot approve its own request
Account creation stallsCreation-status polling, CloudTrail, timeout SLOOrganisation lifecycleNo reference; the request stays retryable or terminal with evidence
Wrong OU or policy inheritanceObserved parent and inherited-controls enumerationOrganisation lifecycleNo publication; quarantine intent until corrected
Permission set exists, role unusableProvisioned-role observation plus an STS or console probeIdentity platformNo IAM-user fallback; the separately tested emergency path stands
SCP mistaken for a grantGrant-versus-limit labelling in the access profile; the positive probe failsIdentity and securityRefuse readiness with the missing grant or trust named
Tenant role exceeds its boundaryBoundary conformance, iam:PassRole inventory, protected-principal driftIdentity and platformBlock the change or assumption; quarantine the tenant deploy path
Transit route or DNS association missingReachability and resolution probes from both sidesNetwork platformThe network claim stays unready; workload apply does not start
Workload creates an unadmitted pathRoute, peering, gateway, and endpoint reconciliationNetwork and workload platformDeny where possible; withdraw the network claim until the path is removed
Shared subnet unshared with residual resourcesShare state plus inventory of participant-owned ENIsNetwork owner and participantStop placement, drain, then remove the owner surface
KMS use or administration mismatchKey-policy inspection, constrained use probe, grant checksKey administrator and key userRefuse the capability; tenant roles cannot mutate policy or schedule deletion
Audit events miss the archiveCanary event and sink observationSecurity and auditThe account is not ready for governed workloads
Bootstrap trust cannot be retiredSteady-state access proof and trust inventoryPlatform and securityAccount stays quarantined; recovery exceptions never satisfy READY
Closure requested with live consumersRecorded consumers reconciled against provider-side relationshipsCoordinator and capability ownersUnexplained relationships block zero-consumer proof and closure

READY states exactly what holds

The assigned reference on AWS says more than its GCP ancestor because it has to. It names the account, the access paths that were proved, the regional network cells that were admitted, the effective quotas, the cost owner, the audit sink observed receiving events, and the contract version all of it was proved against. It also names what was not proved, when the proof expires, and which failure withdraws it. READY is bounded assurance for listed claims, not an explanation of every AWS authorisation decision; nobody can honestly sell the latter.

A product team can preview its workload when the reference resolves and every claim it names is current at once; a finished apply proves one publisher's claim and nothing above it.

The reference links claims it never embeds One published AssignedAccountRef names the account, the contract version, and the proof expiry it was proved under, and links each capability claim by reference: every linked claim keeps its own owner and version, so republishing one claim never rewrites its siblings. It shows AssignedAccountRef (one workload environment), AccessRef (identity platform · v4), NetworkRef · eu-central-1 (network platform · v9), NetworkRef · ap-southeast-2 (network platform · v3), and audit · cost · quota claims (each with its own owner). The AssignedAccountRef feeds the AccessRef. The AssignedAccountRef feeds the NetworkRef · eu-central-1. The AssignedAccountRef feeds the NetworkRef · ap-southeast-2. The AssignedAccountRef feeds the audit · cost · quota claims. READY linked · versioned · owned AssignedAccountRef one workload environment account · observed ACTIVE contract version 7 proof expiry recorded AccessRef identity platform · v4 NetworkRef · eu-central-1 network platform · v9 NetworkRef · ap-southeast-2 network platform · v3 audit · cost · quota claims each with its own owner links, not embeds: each claim keeps its owner and version — republishing one never rewrites the rest
The reference links claims it never embeds

Removal keeps the model's order: vacate first, then destroy. AWS adds its own weight. Retirement marks the boundary RETIRING and blocks new admission while existing references stay resolvable for teardown; consumers detach their cross-account edges; closure is requested only when the recorded reverse edges reach zero. Then the account still does not disappear — closure keeps a 90-day reopen window and rolling closure quotas. Even destruction is an observed lifecycle, which is the claim this article has made about every other boundary.

Rejected defaults, and what would overturn them

AlternativeWhy rejected hereWhat would overturn it
Control Tower as the defaultAdds enrolment, baselines, Service Catalog, controls, and a shared-account lifecycle before a need exists; direct Organizations still owns its own workflow, evidence, and staffingAn existing Control Tower estate, mandated managed controls, a regulated evidence regime, or custom ownership cost approaching the managed lifecycle's
AFT as the defaultDepends on Control Tower and adds a GitOps workflow, repositories, pipelines, and stateA real fleet of repeatable account customisations already on Control Tower
Shared subnets everywhereCentral control and residual participant resources weaken independent workload lifecycleA dense, centrally operated common-trust domain
Per-account VPC everywhereDNS, IP allocation, endpoints, and cost can outweigh isolation for sandboxes and shared platformsIndependent lifecycle earns the VPC profile; reachability separately earns transit
Cloud WANNo established global policy or segment scale to justify another control planeMulti-region, multi-site segmentation beyond Transit Gateway's manageable scope

The rest do not trade off against a baseline; they violate the model itself, and no condition overturns them. The first table's defaults return once the estate or the scale changes; these return only if the model is wrong.

AlternativeWhy it violates the model
One apply creates account and workloadCreation and readiness are asynchronous and cross several owners; tooling can orchestrate stages, but the boundary remains
Workload creates its own accountReverses the dependency graph and hands tenant automation organisation authority — no credible normal case
Permanent OrganizationAccountAccessRole as deploy pathConflates bootstrap with steady-state deployment and keeps fleet-wide blast radius; recovery admits only a temporary, owned, audited exception — never workload pipelines
SCPs as access policySCPs limit the maximum permission set; they grant nothing, skip the management account, and stay guardrails beside real grants
One mega-orchestrator owns every transitionAccount, identity, network, audit, and teardown have different owners and cadences; owners publish receipts, the coordinator validates their composition

Five decisions stay with each estate, because no documentation can settle them: whether Control Tower is already deployed and brownfield accounts must be enrolled rather than rebuilt; how many accounts and regions are coming, and whether a managed control catalogue is mandated; which identity provider is authoritative on day one; which workloads actually need cross-boundary connectivity, inspection, or global segmentation; and which data, logs, and keys must outlive the account, and who owns the retained copies. None of them blocks the protocol; each can overturn an implementation choice behind it.

The port added no new rule; it added receipts — the work moves from designing the handoff to proving each stage of it. A platform that runs this model on one cloud already holds it for the other; what it does not yet hold is the evidence the second cloud refuses to waive.