Hangar

Docs · Glidepath

Architecture Decision Records

One file per load-bearing decision: what it is, why it was made this way, and what it costs. Written after the fact from the real design/implementation history - see ../../archive/ for the original, unabridged design record these were distilled from.

ADR Decision
0001 Tekton + Pipelines-as-Code, vanilla Kubernetes
0002 CDEvents broker with TokenReview auth for inter-stage chaining
0003 Governance gates as explicit, structurally-loud extension points
0004 GitOps-only release promotion
0005 Per-cluster ArgoCD instances, event-driven outcome reporting
0006 Cluster-agnostic bootstrap, no cluster state in the app repo
0007 Testkube CE in one shared namespace, not one per tenant
0008 Kyverno ValidatingPolicy closes the Testkube shared-secret gap
0009 External Secrets Operator + self-hosted Infisical as the secrets backend
0010 Kaniko for rootless image builds under PSS restricted (superseded by 0026)
0011 Every Application is (at least) two peer namespaces, not one
0012 Ephemeral (PR-preview) environments deploy through airframe-application, TTL-swept
0013 Shared catalog distributed as a git-tag-pinned Helm chart, not a bundle resolver
0014 Keyless signing uses two separate trust roots - public Sigstore for humans, self-hosted Fulcio for workloads
0015 Provenance policy validates the attestation as input, additive to commit signing
0016 Tekton Results for long-term PipelineRun/TaskRun archival
0017 cicd.yaml is scaffolded at onboarding, not hand-authored first
0018 Glidepath owns the per-app environments folder (glidepath/) and defines the chart contract
0019 Proposed. Environments are one config model, defined once in cicd.yaml
0020 Cloud Flight environments are gated by a release pin PR on the source repo
0021 Proposed. Release events are facts from the Rollout, interpreted on dev (replaces the hook Jobs)
0022 Proposed. CDEvents conformance (v0.5.1), subject and content discipline, the rollout event set, and what stays out of the events
0023 Per-app chart through deploy.chart: Ground via glidepath-app, Flight via identity.yaml, one default per cluster
0024 Cluster taxonomy: zone (lower/upper) and roles per cluster, tier and production per environment; production runs on an upper cluster
0025 Retire the image-promotion stub check; a real promotion’s place (pre- or post-merge) follows registry topology, with event fan-in instead of polling
0026 Rootless BuildKit replaces kaniko for image builds; Pod Security baseline, not restricted
0027 The provenance gate accepts a GitHub PR merge by an allowed login (off by default, per app); the release-signing policy moves from cicd.yaml to admin-owned catalog values
0028 The policy-validation gate renders the release and evaluates it offline (Kyverno CLI) against the target cluster’s admission policies from its GitOps repo, served by the broker; only Deny/Enforce findings block
0029 Ground and Flight registries: release files pin a digest and record the source; Flight images are copied by digest (no re-signing) by a GitHub Actions workflow before the release merges; upper clusters admit only images with the promoter’s attestation (enforced on hangar-prod 2026-10-30)
0030 Proposed. A RabbitMQ topic exchange carries every Glidepath event beside the SSE stream: glidepath-api publishes once per event with confirms; each unattended consumer gets its own durable queue, bindings and user declared in Git

New decisions get a new numbered file here, not a paragraph buried in an unrelated doc.

Note on 0014/0015: distilled from image-signing.md/commit-signing.md/ provenance-policy.md as they stood 2026-09-06. A separate, concurrent session is implementing sigstore end-to-end in GitOps fashion at the time these were written - re-check both against the live mechanism before treating them as current if that work has since landed.