Architecture decision records¶
These records capture Tend's architecture decisions — what was decided, the forces behind it, the alternatives rejected, and the consequences — sourced from the product brief (2026-06), the walking skeleton (001, 2026-06), governance depth (003, 2026-07), and Gemini inference (004, 2026-07). ADRs are numbered in the order the decisions took effect. They are not rewritten to change a decision: a reversal gets a new ADR that supersedes. Corrections and later amendments are recorded in the Status line. Statuses are Accepted, Accepted (interim) (a deliberate stand-in with a recorded destination), and Deferred (decided not to decide, with recorded re-evaluation triggers).
| ADR | Title | Status | Principles | Decision in one line |
|---|---|---|---|---|
| 0001 | CNCF components only | Accepted | I, VII, Baseline | Build from the named CNCF stack; anything outside it must be justified and recorded; new dependencies must be justified against portability and no-lock-in. |
| 0002 | Enforce the contract, never review generated code | Accepted | II | Governance is enforced at the platform layer; generated app code is never reviewed or trusted. |
| 0003 | Go operator, App CRD as single source of truth | Accepted | IV, V | Kubebuilder operator; the App CR in etcd is the only authoritative state — no platform database. |
| 0004 | GitOps everything; promotion is a platform-raised PR | Accepted | VI | Argo CD delivers apps and the policy baseline; promotion PR + merge = approval; no workflow engine in v1. |
| 0005 | Tekton + Chains for in-boundary attestation | Accepted | III, I | Chains emits cosign-signed SLSA provenance stored in Harbor; the pipeline's sign-and-attest task adds the Tend fields; Rekor and Fulcio disabled. |
| 0006 | Kyverno as the single admission engine | Accepted | II, III, V | One engine for the attestation gate, contract validation, and governance-field defaulting at App create. |
| 0007 | Generated Cilium perimeter, gateway-only egress | Accepted | I, II | Operator-rendered default-deny floor plus gateway/identity egress and an edge-ingress allow — one static shape for every app namespace. |
| 0008 | The data gateway is the sole data path | Accepted | I, II, III | New connector-based service enforces declared scopes per request, logs every decision, fails closed. |
| 0009 | App identity via projected SA tokens | Accepted | II | Audience-scoped projected tokens validated by TokenReview (≤2 min cache); no per-app secrets minted. |
| 0010 | Embedded SQLite for the access-log store | Accepted | III, IV | Pure-Go SQLite on a PVC, append-only, lifetime retention, exposed only via the gateway query API. |
| 0011 | Builder authentication via Keycloak OIDC | Accepted | VII, III | Client-credentials JWT validated at the inference gateway; static-token path deleted; fail closed 401. |
| 0012 | Operator-direct cost suspension | Accepted | II, V (VI deviation) | Suspend at breach by pausing Argo sync then scaling to zero; warn once per crossing; unknown telemetry never enforces. |
| 0013 | Thin, replaceable builder behind a three-clause contract | Accepted | VII, I, VI | Integrate an OSS builder behind a narrow contract: gateway only, never deploy, no git credential; keep two candidates viable. |
| 0014 | Gitea as the in-boundary git host | Accepted | I, VI | In-cluster git with a PR API the operator drives; pluggable for a customer's own in-boundary git. |
| 0015 | Kargo (promotion tooling) deferred | Deferred | VI | No promotion engine until one of four recorded triggers fires; git-native promotion is audit-equivalent. |
| 0016 | Evidence assembled on demand, no materialized store | Accepted | III, IV | Parallel fan-out over live sources with a 60 s cache and explicit per-category degradation; no second store. |
| 0017 | Two boundary tiers, Tier 1 cloud-private default | Accepted | I | Private managed endpoints by default, self-hosted vLLM-class as Tier 2 (reserved, not exercised); jurisdiction claims scoped honestly. |
| 0018 | Minimal estate viewer now, Backstage later | Accepted (interim closed) | III | Stateless read API + SSR Go viewer ship now; the Backstage plugin later renders the same UI-agnostic contract. |
| 0019 | Bifrost as the in-boundary model gateway | Accepted | I, II, IV, Baseline | Self-hosted Bifrost enforces hard per-app LLM budgets (GCP cannot cap Gemini spend); replaceable behind the model-gateway contract. |