A production-inspired cloud platform on AWS, designed from first principles and implemented step by step with evidence. Terraform provisions the AWS foundations and an Amazon EKS runtime, GitLab CI builds, scans and publishes immutable container images to Amazon ECR, Argo CD deploys them by digest from Git, and an OpenTelemetry-based stack observes the workload and delivers alerts. Every runtime is created for a bounded, approved window, exercised, evidenced and destroyed.
The platform is the product. Its workload, AstroShop, is derived from the OpenTelemetry Demo and exists to validate the platform.
Status as of 2026-10-16. Nothing in this repository is a production-readiness claim.
- No runtime is running. The Dev runtime (EKS control plane, managed node group and NAT gateway) exists only inside an approved window. Between windows only the persistent foundations, the retained Dev baseline, and the datastore's network boundary, credential containers and final snapshot remain.
- Validated on AWS in six Dev windows, 2026-08-14 to 2026-09-13. They are the publicly documented historical validation set in Runtime Validation, not necessarily the complete window history. Each created the runtime from Terraform and destroyed it with a zero-residual census; one was aborted at its first gate on a measured defect. Argo CD reconciled a three-service workload slice and its observability stack from Git, the running shipping image matched its published digest on four independent signals, an alert reached the operator, and an induced fault was restored through Git.
- Delivery coverage is partial. All seventeen project-built components are wired through build, scan and SBOM in CI. Five have published images to Amazon ECR, and three of them, checkout, shipping and quote, ran in the validation windows. No image built from the container definitions hardened in October 2026 is recorded as published or run (SERVICE-INVENTORY.md).
- Not yet proven: the full fleet on EKS, which ADR-0017 makes the programme target; the public HTTPS entry and a real external request; rollback; promotion between environments; and the Validation and Production Validation environments, which have not been built.
Select the diagram for full size. Its status labels date from 2026-10-13; current results are in Runtime Validation and SERVICE-INVENTORY.md.
The decided platform is one AWS account in us-east-1 with three environment roles, Dev,
Validation and Production Validation, each with its own VPC, EKS cluster, Terraform state and
telemetry; only Dev has been built. Nodes run in private subnets, and one managed HTTPS entry per
environment is decided but not yet built. Each application change becomes one image, promoted
through Git by its immutable digest rather than rebuilt. Recovery rebuilds from authoritative
sources, and backup covers only Terraform state, workload data, secret-store contents and exported
evidence.
Detailed views:
- Exported, like the overview, from aws-platform-reference-architecture.drawio: the GitLab CI Pipeline (full size) and the Repository Model
- Earlier renderings, not exported from that file: Control, Delivery and GitOps, AWS Platform and Request Flow, and Identity, Secrets, Observability, Evidence and Lifecycle
The twenty Accepted records in docs/decisions are the architecture authority, and this summary changes none of them.
| Area | Records |
|---|---|
| Delivery method, cloud provider, Terraform and state, account and environments, identity | ADR-0001, ADR-0002, ADR-0003, ADR-0004, ADR-0005 |
| EKS runtime, networking and traffic, secrets and workload identity | ADR-0006, ADR-0007, ADR-0008 |
| Software delivery, observability, backup and recovery | ADR-0009, ADR-0010, ADR-0011 |
| Operations and cost | ADR-0013 |
| Reference workload and its implemented scope | ADR-0012, ADR-0014, ADR-0016, ADR-0017 |
| Security admission and image controls | ADR-0015, ADR-0019, ADR-0020 |
| Public entry, DNS and certificate | ADR-0018 |
Accepted records are never edited; a later record narrows an earlier one and states exactly how far it reaches. ADR-0013 replaces the continuously running Dev runtime that ADR-0004 assumes and ADR-0006 and ADR-0007 restate. ADR-0014, ADR-0016 and ADR-0017 change the implemented workload scope in turn. ADR-0019 narrows ADR-0017's pin-and-mirror requirement for AWS-managed add-on images, and ADR-0020 narrows ADR-0017 and ADR-0019 for the sandbox image baked into the node AMI.
PROVEN rests on retained evidence for the scope stated, whether from a runtime window, a pipeline run or an AWS exercise, and PARTIALLY PROVEN names its boundary. IMPLEMENTED means the code exists, and is applied where stated, with no validation claimed. DESIGNED means decided in an Accepted ADR and not built. Raw evidence stays private; the linked pages are its sanitized summaries.
| Capability | What is built | Status | Evidence |
|---|---|---|---|
| Infrastructure as code | Four Terraform roots split by responsibility, S3 remote state, a reviewed plan before every apply | IMPLEMENTED and applied; the root READMEs record AWS read-back for the registry, CI push identity, DNS zone, certificate, Dev network baseline and datastore, and a clean post-apply plan with recorded settings for the state and evidence buckets | Root READMEs |
| Runtime lifecycle and teardown | The 17-resource Dev runtime, created for each window and removed by a targeted destroy and an orphan census by resource class | PROVEN in all six documented windows; evidence read back after destruction in the last two of them | Windows |
| Build and scan | Shared GitLab CI templates: image build, Trivy image and source-dependency gates that block fixable HIGH and CRITICAL findings, SBOM, container health check | Build, scan and SBOM IMPLEMENTED for 17 of 17 components; health checks vary by component | trivy-scan.yml, SERVICE-INVENTORY.md |
| Publication by digest | OIDC token exchange with no stored AWS credential, immutable ECR tags, a manual publish job on main |
PROVEN for the checkout push path; 5 of 17 components published | ecr-publish.yml, SERVICE-INVENTORY.md |
| GitOps delivery | Argo CD with three value layers, digest pins and manual sync | Reconciliation PROVEN; image identity PROVEN for shipping, PARTIALLY PROVEN for quote and checkout | GitOps Delivery, Results |
| Workload identity and secrets | EKS Pod Identity, External Secrets Operator reading AWS Secrets Manager, IMDSv2 with a hop limit of 1 | PROVEN for the alerting publisher; secret synchronisation PARTIALLY PROVEN; an ordinary pod observed failing to obtain node credentials | Dev identity, Results |
| Telemetry | OpenTelemetry Collector gateway; Prometheus, Loki and Tempo; Grafana views; 2-hour retention | Kubernetes identity on metrics, logs and traces PROVEN; retention PROVEN as combined evidence; views PARTIALLY PROVEN | Results |
| Alerting | Grafana alert rule to an Amazon SNS email, published under Pod Identity | Delivery PROVEN; a cardinality clause added later failed and is withdrawn | Results |
| Recovery | Fault and restore merged as Git changes and proven by tree equality with the anchor; Terraform state restored from a prior object version | Git restore PROVEN, 7m41s after the fault ended against a 30-minute requirement; state recovery PROVEN on an isolated copy of the foundation state only | Recovery pattern, State recovery |
| Cost guardrails | Monthly budget with a 100 USD target, a 150 USD review threshold and a 200 USD ceiling; runtime only inside windows | IMPLEMENTED; budget read back, alert delivery untested | ADR-0013, Budget check |
| Public entry | Route 53 zone and ACM certificate; an ALB through the AWS Load Balancer Controller | Zone and certificate IMPLEMENTED and read back; the entry DESIGNED, not built | Foundation status, ADR-0018 |
| Datastore | RDS PostgreSQL 17.11 with its network boundary and credential containers | IMPLEMENTED and read back, no workload connected; decommissioned 2026-10-06, final snapshot kept | Datastore status |
| Security admission | ADR-0015 gate per component, digest and window, with exceptions that expire with their window | Exercised in the observability windows: five platform images ran under exceptions, now expired | ADR-0015, Limitations |
The platform spans three repositories, each with one responsibility and one authoritative host (ADR-0009). This one is the place to start.
| Repository | Authoritative host | Holds | Visibility |
|---|---|---|---|
| cloud-platform-reference (this repository) | GitHub | Architecture, decisions, Terraform, implementation, runbooks and validation summaries | Public |
| cloud-platform-workload | GitLab, where merge requests and CI run. The GitHub copy is a one-way mirror for browsing | AstroShop source, container definitions, and the CI that builds, scans and publishes images: .gitlab-ci.yml and shared templates |
Public |
| cloud-platform-gitops | GitLab, not mirrored | The desired state Argo CD reconciles: value layers and the image digest each environment runs | Private, because its pins carry live registry coordinates. GitOps Delivery documents the model |
Mirror updates can lag behind GitLab; Repository Model draws the hosting model. The platform, meaning the Terraform, the CI templates, the GitOps desired state and the validation harness, is this project's work. Several CI templates were adapted from a prior project by the same author, while registry publication, federated pipeline credentials and SBOM generation are new here. AstroShop is a derivation of the OpenTelemetry Demo. The workload repository's DERIVATION.md records what was carried from the prior project and what was taken from upstream, changed and excluded.
| Path | Contents |
|---|---|
| docs/ | The foundation documents: Project Charter, Platform Capability Model, Requirements Baseline, System Context, Logical Architecture, Architecture Baseline |
| docs/decisions/ | Accepted architecture decision records |
| docs/diagrams/ | Architecture views and their draw.io source |
| docs/implementation/ | How a source change becomes a running container |
| docs/runbooks/ | Operating procedures, validation labels and known gaps |
| docs/validation/ | The sanitized runtime validation summary |
| terraform/ | One root per responsibility: bootstrap, foundation, dev and dev-datastore |
You need one dedicated AWS account, Terraform and an operator identity as described in
operator access. Each root reads its private inputs from an
untracked terraform.tfvars; the tracked terraform.tfvars.example beside it lists what must be
supplied, and nothing requires the owner's account identifier, addresses, state or evidence. To
check the code without AWS, follow
Validate locally, without AWS. Apply the
roots in order, each from its own directory with a reviewed plan; the runbook
build order is the procedure for steps 1 to 4.
- terraform/bootstrap: the remote-state backend. Applied once with local state, then migrated.
- terraform/foundation: resources that outlive every environment, meaning the evidence store, the container registry, the CI push identity, and the public DNS zone with its certificate, applied in two steps around the registrar delegation.
- terraform/dev: the Dev environment, split into a retained baseline and a runtime created for each approved window and destroyed at its close.
- terraform/dev-datastore: the Dev datastore, a PostgreSQL instance with its network boundary and credential containers, kept outside every runtime window's teardown. The instance was decommissioned on 2026-10-06 and its final snapshot kept.
- Cluster bootstrap and GitOps: Argo CD reconciles the private desired-state repository against the running cluster; the bootstrap order, the value layering and the digest pin are in GitOps Delivery, and the decision behind them in ADR-0009.
- The workload is built and published by the workload repository's pipelines and deployed by digest through step 5.
Warning: Do not run a plain
terraform applyinterraform/dev: it creates the billable runtime; its first build is targeted.
Some steps stay manual by design, as owner or operator boundaries rather than gaps in automation: the Identity Center and account prerequisites, the budget and its alerts, the registrar name-server change, placing secret values out of band, the explicit authorization and execution of every infrastructure apply, and the merges the protected branches require.
Current gaps:
- The build order has not been run end to end from a fresh clone of the current configuration, and with every item supplied it ends at a built datastore, not a running cluster.
- Steps 5 and 6 are outside the runbooks. What they need that is not published, such as the runtime window that creates the cluster and the mirroring of platform images into the registry, is under Known reproducibility gaps.
- Some tools are not published, such as those the datastore's secret placement requires; What these runbooks are lists what you supply yourself.
- The validation windows ran an earlier revision of
terraform/dev, and its current worker-mode definition has not been applied (Lifecycle and current state).
- Scope. Results cover Dev, the three-service slice and the named windows only. The three fleet-scale properties ADR-0016 names stay declared limitations until the full fleet runs, a condition ADR-0017 leaves in force.
- Security exceptions. The observability and alert-delivery results were observed while five platform-managed images, Prometheus, kube-state-metrics, Grafana, Loki and Tempo, ran under bounded, per-digest ADR-0015 exceptions approved only for those windows and expired with them, so they are reported as observed under exception, not as clean, vulnerability-free or security-gate-passed.
- Point-in-time scans. Each published digest carries the scan result of its own build. The checkout artifact deployed in the windows had no fixable HIGH or CRITICAL finding at its 2026-08-15 publication scan; a HIGH gRPC finding, CVE-2026-84445, was later fixed in source with grpc v1.83.2, and that artifact has not been rebuilt or rescanned.
- SBOM and provenance. The SBOM comes from the image, so for a statically linked or single-file service it describes the base image, not the application's dependencies. Pipeline-retained provenance exists only for publications that have not run in a window, and frontend-proxy's bundle failed verification; the shipping digest that ran had its scan and SBOM recovered by hand.
- Observability. The trace-store selection ADR-0010 defers is open, trace-to-logs traversal in the operational view is NOT PROVEN, telemetry enrichment is uneven across services, and object deletion under retention was not observed on EKS. One continuous fault produced six alert notifications in about nineteen minutes, for a reason not isolated (declared limitations).
- Identity and network. The synchronised secret read is not attributed to the controller's own role, the workload IAM role has not been used by any pod, and NetworkPolicy enforcement is untested. A deactivated legacy IAM access key still exists, and the identity configuration still deviates from the ADR-0005 target model (operator access).
- GitOps. The automatic CI-to-GitOps Dev pin ADR-0009 describes is not implemented, so every
pin so far is a manual reviewed change; sync is manual, and the
defaultAppProject is a declared limitation. - Recovery. ADR-0011 is incomplete: workload-data restore, secret deletion recovery, datastore recreation and snapshot restore are unexercised (recovery obligations). One induced memory fault did not produce its intended effect and is INDETERMINATE.
- Cost. Window costs are rate-derived upper bounds, not billing statements, and AWS Budgets notify rather than prevent spend.
Apache License 2.0. See LICENSE.