Architecture Decision Records¶
This directory is the canonical record of HybridCloudWorks architecture decisions. The architecture describes the system as a whole; an ADR explains why a material choice was made, its purpose, its tradeoffs, and when it must be reconsidered.
Policy¶
Create an ADR before implementing a decision that changes any of the following:
- cloud service, hosting model, data store, network boundary, identity model, or trust boundary;
- availability, recovery, security, performance, observability, or cost posture;
- Terraform state, module strategy, deployment authority, or GitHub governance;
- migration, compatibility, cutover, decommission, or repository ownership;
- external integration contract or irreversible operational behavior.
ADR numbers are never reused. The register carries one historical exception: 0021 was assigned twice, first to the deferred Container Apps CI runner record and then to Key Vault purge protection, before this rule was written down; both records are kept and marked so the collision cannot be mistaken for a revision. Accepted ADRs are immutable except for spelling, links, and status. A changed decision gets a new ADR that supersedes the old one. Pull requests implementing architecture must link the applicable ADRs. If no ADR applies, the pull request must say why the change is not architecturally significant.
Status lifecycle¶
Proposed → Accepted → Superseded or Deprecated
- Proposed: under review and not authorized for implementation.
- Accepted: approved direction; implementation may still be incomplete.
- Superseded: replaced by a newer ADR, which must be linked.
- Deprecated: retained for history but no longer applicable.
Required sections¶
Every ADR includes:
- status and decision date;
- context and problem;
- purpose and decision drivers;
- decision;
- consequences and accepted risks;
- alternatives considered;
- validation and revisit triggers;
- related decisions and references.
Decision register¶
| ADR | Decision | Status | Primary purpose |
|---|---|---|---|
| 0001 | Consolidate HCW into one repository | Accepted | Prevent application/platform drift |
| 0002 | Retain Cloudflare as the initial edge | Accepted | Preserve edge capability within budget |
| 0003 | Start with Cosmos DB Serverless | Accepted | Match document workload and spiky demand |
| 0004 | Separate API, worker, and labs Function Apps | Superseded by 0019 | Enforce trust and permission boundaries |
| 0005 | Use AVM Terraform and GitHub OIDC delivery | Accepted; module clause superseded by 0020 | Make infrastructure changes reviewable and credentialless |
| 0006 | Use Entra ID for administrators only | Accepted | Protect administration without requiring public accounts |
| 0007 | Preserve static-first rendering on Static Web Apps | Accepted | Keep public content fast and backend-independent |
| 0008 | Use selective Private Link | Accepted | Secure sensitive data while containing network cost |
| 0009 | Use one production workload state | Accepted | Match current operating scale without environment sprawl |
| 0010 | Centralize bounded observability | Accepted; alerting layer delivered by 0022 | Make health and change outcomes measurable |
| 0011 | Use single-region, zone-aware recovery | Accepted | Balance reliability with the USD 150 ceiling |
| 0012 | Use queues and idempotent workers for side effects | Accepted | Make publishing and integrations retry-safe |
| 0013 | Use Azure OpenAI as a feature-gated default | Accepted; provisioning gate ratified by 0018 | Remove the Vertex dependency without making AI critical path |
| 0014 | Keep source media private in ZRS Blob Storage | Accepted; ZRS amended to LRS by 0018 | Protect and recover media economically |
| 0015 | Enforce a USD 150 monthly design ceiling | Accepted | Make cost an implementation constraint |
| 0016 | Use reversible migration and explicit decommission gates | Accepted; decommission gate closed by 0023 | Prevent premature data or rollback loss |
| 0017 | Re-root the default branch after credential rotation | Accepted | Remove reachable secret-bearing Git history |
| 0018 | Supersede plan v0.1 with the as-built v0.2 plan | Accepted; two debt rows closed by 0021 and 0022 | Make the approved plan describe the real system; disposition every deviation |
| 0019 | One Function App execution boundary | Accepted | Ratify least-privilege-by-contract over process separation |
| 0020 | Flat native-provider Terraform root module (no AVM) | Accepted | Keep resource addresses stable on a live state |
| 0021 | Key Vault purge protection stays disabled | Accepted | Keep teardown-and-recreate available on a single-environment estate |
| 0021 (number reused) | Container Apps self-hosted CI runner failover | Superseded — deferred 2026-08-18 before the number was reassigned to Key Vault purge protection | Kept because infra/ci-runner.tf still holds the gated-off resources it describes |
| 0022 | The alerting fabric, and the signal it does not cover | Accepted | Make failure visible without competing with the telemetry that explains it |
| 0023 | Retire the migration-era estate, grants and reverse path | Accepted | Close the decommission gate deliberately rather than by neglect |
| 0024 | Reachability probing from a Cloudflare Worker | Proposed | Give T-519's signal a path that runs on the current Cloudflare plan |
| 0025 | The Cosmos datacenter-IP sentinel — kept, then removed | Accepted; recommendation reversed by its own addendum | Weigh closing T-718 against its cost — then remove the sentinel once a cheaper route appeared |
| 0026 | Required checks filter inside the job, not at the trigger | Accepted | Keep every merge gate while paying only for checks that can fail |
| 0027 | Documentation is a MkDocs site under docs/, published to docs.hybridcloudworks.com |
Accepted | One reviewed, validated, redaction-gated source for every page; the Wiki is retired |
Template¶
Copy the ADR template for new decisions. Do not edit an accepted ADR to represent a new decision; create the next numbered record and mark the earlier ADR superseded.