RHELS LAB
Contents · the agent book

Agent book · Operations

SRE Assessment — IaC, DR, Upgrades, SLO/SLA

Assessed 2026-10-29 by four read-only audits (IaC, disaster recovery, upgrades, SLO/SLI) against the live mini and pro clusters, the git trees, and the health-suite reports. CRC was not started for this assessment; everything CRC-side is git-defined or last-known and is labelled as such. Every number on this page is labelled measured (observed live or in a dated record), inferred (derived from measured data), or unproven (no evidence found — a restore that was never drilled is stated as never drilled, not estimated away).

Headlines:

  • IaC: 53 of 88 audited units are fully git-defined — 60% (measured for mini/pro, inferred for CRC). Counting content that is in git but hand-delivered, 86% (same basis). The debt is delivery automation and host/DB state, not missing manifests.
  • DR: the rebuild-from-git story is drill-proven where exercised (CRC 27m24s, Vault milestones, pro standups). The worst gap is concentrated: the Vault unseal key exists only on the mini — losing that host makes the off-host Vault archives undecryptable. Harbor and StackRox Central, both promoted to pro on 2026-10-29, have no backup at all.
  • Upgrades: the most overdue item is not an upgrade but a migration — ingress-nginx v1.15.1 is the final release of a retired project (repo archived 2026-03-24) with a critical unpatched CVE, and it is the mini’s front door. Behind it: Prometheus v2.55.1 (security support ended 2024-12-03), Logstash 8.17.3 (minor EOL 2025-08-12), Vault 2.0.4 (predates the October 2026 security-fix line), and Docker Desktop 4.96.3 on the mini (one release behind a credential-in-logs security fix).
  • SLOs: of the proposed SLOs below — 4 MET, 6 MISSED, 5 UNMEASURABLE with today’s measurement. The misses are mostly measurement defects (CRC stopped, inconsistent infra-down gating), but two are real: the LDAP bind matrix at 93.8% and the front-door sweep at 92.9%.

This page supersedes the placement details in the Disaster Recovery chapter (verified 2026-10-24, pre-migration: Harbor, the observability trio, and the logging stack have since moved to pro).

1. IaC coverage

Denominator: 88 units = 48 live Argo CD Applications (measured) on the mini’s Argo CD (29 destined for the mini, 19 for pro) + ~28 git-defined CRC Applications (inferred count; CRC stopped) + 12 named non-Argo platform components. At audit time the mini’s Argo CD showed 48 Applications, 47 Synced/Healthy, 1 OutOfSync/Healthy (pro-harbor) (measured).

ClassCountShare
Fully git-defined (manifest in git and delivered by a live root/ApplicationSet)5360%
Git-defined content, hand-applied delivery (no live root owns the Application CR)2326%
Partial / exception (some code; a manual step or DB/host state remains)9 of the 12 non-Argo components—
No git home3 of the 12—

Exceptions and drift

#ItemRiskState
1Mini’s own argocd/ tree has no live root app; root.yaml points at a personal fork while every live app points at the org repo; the kustomization lists apps that are not live and omits most live tooling-* apps. Bootstrap is a documented manual procedure.MedMeasured
2CRC AlertmanagerConfig conversion-webhook backends (Service + Endpoints + admission cert pair in openshift-monitoring) were hand-made in a 2026-10-25 live repair — not in git; a durable GitOps fix is still owed. The AlertmanagerConfig itself is in git.MedMeasured (2026-10-25 record); live state unproven, CRC stopped
3Classic ARC controller-manager Secret on the mini is hand-applied; its last-applied-configuration annotation embeds the credential payload. This is the burned classic PAT now being replaced by a GitHub App (lab-monorepo#46).HighMeasured
4Vault server is a manual Helm install (chart 0.34.1, values in git), not Argo-managed. Its contents are increasingly code: access policies in the lab-monorepo infrastructure/vault-access/ tree; the PKI mount, root CA, and lab-health-issuer role exist (measured, 2026-10-25 record) but have no git definition — treat their creation as bootstrap/manual.MedMeasured
5Harbor LDAP configuration is Harbor DB state, not git. A durable converge script exists on an unmerged branch; until it merges and runs, a pro Docker Desktop reset loses LDAP auth (today it works only because the DB survived the flip).MedMeasured, fix in flight
6Tailscale Serve fronts on pro: 11 fronts, only 2 codified in the registration script; the other 9 exist as documented commands plus check-script expectations. No re-assertion mechanism on the host.MedMeasured
7Docker Desktop VM settings are GUI-set on both hosts, in no repo. Pro sizing is recorded in its README; the mini has no memory/disk keys recorded at all (defaults).MedMeasured
8The pf-ldap port-forward loop on the mini (behind the LDAP front door) is a shell loop with no LaunchAgent and no git home for its script directory. Three sibling pf loops are host-only LaunchAgents, also not in git.MedMeasured
9The Cursor worker Deployment on the mini is labelled git-managed but its last-applied annotation proves hand kubectl apply; no Argo Application; hand-created auth Secret.MedMeasured
10Hand-synced platform Secrets (Vault → cluster) are delivered by git-resident scripts run manually; actuation, not content, is the gap. Rebuild order matters: several Secrets must be synced before Argo can start their pods.Low–MedMeasured
11OpenLDAP seed LDIF is codified (inline in the ldap module, idempotent seed Job) — Low risk; caveat: edits, member adds, and deletions need a live ldapmodify plus a seed update; seed alone does not propagate them.LowMeasured
12cert-manager ClusterIssuer is git; the Cloudflare DNS token lives only in an out-of-band Secret (by design). Argo repo/cluster Secrets are hand-created bootstrap exceptions, documented; the pro cluster Secret is rendered from Vault by script.LowMeasured
—The mini’s retained Harbor namespace (workloads scaled 0/0, Secrets/PVCs kept) is an intentional rollback snapshot from the 2026-10-29 flip, not drift. Delete only on the owner’s word.LowMeasured

Cheapest wins: merge + run the Harbor LDAP script (#5); write one idempotent pro Serve assertion script (#6); LaunchAgent-or-retire pf-ldap (#8).

2. Disaster recovery

RTO/RPO are inferred unless a drill measured them. “Last proven restore” means evidence — a dated drill or restore record — not a belief.

ServiceBackupRetentionRTORPOLast proven restore
Vault (mini)Daily tar of the file-storage tree, two copies (mini + Spark VM), sha256-verified identical14 days (dailies); milestone archives never pruned~1–3 h (inferred)24 h by design (measured)2026-10-24 (measured) — archive restored, tree diffed 215/215 identical; full unseal proof rests on the 2026-10-18 drill. Dailies since 10-25 are sha-verified but never restore-drilled
↳ Unseal keymacOS Keychain + a key file — both on the mini only; no off-host escrow, by explicit owner decision 2026-10-24——Mini loss = total Vault lossUnseal from backup proven 2026-10-18
CRC / OpenShift (m4)Stateless by doctrine; recover.sh rebuilds from git + Vault escrowGit history27m24s best / ~46–55 min typical (measured)~0 for desired state2026-10-25 (measured) — 3 scripted drills in one day (36/36 live apps — the ~28 git-defined Applications plus ApplicationSet-generated ones — health suite 9/9)
Harbor (pro)None. No backup job, dump, or export found anywhereNone~1–2 h to an empty registry (inferred)Total loss of post-flip content on a pro DD resetNever — unproven
↳ Mini’s retained Harbor PVCsPre-flip DB (~13 MB) + ~1.3 GiB blobs / 55 artifacts, still Bound on the miniUndefined; no expiry recordedRollback to the pre-flip instance onlyProtects nothing pushed after the flip; dies with the mini DD disk it would roll back fromn/a
StackRox Central (pro)None. No backup scheduling in the Central CR, no roxctl backup evidenceNone~1–3 h, rebuild-empty (inferred)Total for Central-internal state (policies, users, alert history, tokens)Never — unproven (nothing exists to restore)
OpenLDAP (mini)Seed LDIF in git; credentials of record in VaultGit history~30–60 min (inferred)Post-seed live changes not captured in git are lostRebuild-from-seed never drilled — unproven. Seed fidelity inferred strong (full live directory codified 2026-10-24, bind-verified). One manual seam: the svc-stackrox search ACL lives in cn=config, not the seed
Argo CD (mini; manages all 3 clusters)State is git; first install + root apply are manual seamsGit history~1–2 h (inferred)~0 for app statePartially proven (measured): CRC’s bootstrap rebuilt 3× in the 10-25 drills; pro registration is scripted. A cold rebuild of the mini’s own Argo CD has never been drilled
Prometheus / Grafana / AlertManager (pro)No PVCs by construction; dashboards/datasources are git ConfigMaps; TSDB is emptyDirn/a<30 min (inferred)Metrics history + Grafana UI state: total, by designRebuild-from-git proven 2026-10-29 (measured) — the trio was stood up fresh on pro in the migration
Loki / Tempo / Logstash (pro)None — by design; Loki retention 72 h in values (measured in git)72 h rolling (Loki)<30 min (inferred)All stored logs/traces on a DD reset — acceptedRebuild-from-git proven at standup (measured)
MCP / agentops platform (pro)Stateless services; Secrets sync from Vault by script; images re-pushable from the mini or rebuilt from DockerfilesGit history<1 h (inferred)Group-request truth lives in the ServiceNow PDI (external, no lab-controlled backup, reclaim cycle applies) + git recordsRebuild proven at the 2026-10-29 pro standup (measured)
Memory MCP PostgreSQL (mini)pg_dump script + restore test existNone set~30 min (inferred)Stale (measured): newest dump 2026-09-06, ~7 weeks old, single on-host copy, no scheduleRestore test passed once (~Sep 2026, doc record)
GitHub repos (the source of truth)None beyond GitHub itself; local clones are partial and of varying freshness; no mirror or export jobn/aDays (inferred)Loss of the org = loss of the canonical source every other row rebuilds from (issues/PRs/Actions secrets are in no clone)Never — unproven
Spark VMspark-vm-config repo + install scriptGit historyTunnel <1 h (documented); full workspace unprovenWorkspace content not in a git repo or a mirror is unprotectedScoped: the repo restores the CRC-tunnel tooling only — by design, not the whole VM
The two Mac hostsNo Time Machine on either — measured (“No destinations configured” on mini and pro; m4 unproven, unreachable with CRC stopped)—Host replacement + full cold rebuildEverything host-local: DD VM disks (all PVCs), the Keychain (the unseal key), Tailscale Serve state, Docker image stores — including the Cursor worker image, for which no build path exists in any repoNever

Host-loss blast radius

  • Mini dies — the big one. Vault (primary and its unseal key), OpenLDAP (the IdP behind Dex, ACS SSO, Harbor LDAP, CRC OAuth), Argo CD (control plane for all three clusters), the front door + cert-manager, the retained Harbor rollback PVCs, lab-docs. Pro’s workloads keep running but unmanaged and unhealed. The Spark VM’s Vault archive copy survives as sealed ciphertext with no key anywhere off the dead host — every Vault-escrowed rebuild step (CRC pull secret, Argo repo creds, Harbor/Grafana admin, pro cluster token) then fails and must be re-created from original sources, several of which are Vault itself.
  • Pro dies — painful, survivable. StackRox Central (ACS dark for the mini + CRC sensors), Harbor (now the primary registry — a CRC recover.sh run cannot complete its image pulls without it), pro logging, the observability trio, the agentops platform, pro CI runners. The mini plane (Vault, LDAP, Argo) survives, which is what makes this recoverable. Accepted losses: Harbor and Central return empty; logs/metrics gone by design. Full sequence inferred at ~half a day, dominated by image re-pushes — never run end-to-end as a drill (unproven as a whole); every individual app was proven at standup.

3. Upgrade posture

Current versions are measured live unless noted. “Latest” claims are vendor/endoflife.date figures checked 2026-10-29/30; where a latest could not be verified it says unproven rather than guessing.

ComponentCurrentLatest / statusRiskMechanism · cadence
ingress-nginx (mini front door; CRC git)chart 4.15.1 / controller v1.15.1Final release. Project retired, repo archived 2026-03-24; CVE-2026-42533 (critical NGINX heap overflow, 2026-07-15) is unpatched in 1.15.1; tested only to K8s 1.35 (clusters run 1.36)CriticalMigration, not a bump — Gateway API / another controller; no drop-in exists. Planned project
Prometheus (pro)v2.55.13.13 LTS (supported to 2027-07-31); 3.15 newestHigh — 2.55 security support ended 2024-12-03 (~23 months unpatched), two majors behindManifest image bump; 2.55 is the documented downgrade-safe bridge to 3.x, so the clean-jump window is now. Then LTS annually
Logstash (mini + pro)8.17.38.19.x supported to 2027-07-15; 9.x currentHigh — the 8.17 minor went EOL 2025-08-12Manifest image bump to 8.19.x (cheap, same-major); evaluate 9.x quarterly
Vault (mini)2.0.4 (chart 0.34.1)2.2.1 (2026-10-22); four security bulletins fixed in 2.1.2 (2026-10-07)High — the credential root predates the October security-fix line; highest blast radius per patch in the inventoryImage bump + unseal procedure (standing authorization). Patch on security bulletins; minor quarterly
Docker Desktop appmini 4.96.3, pro 4.97.04.97.0 (2026-10-26)High-ish (mini) — 4.97.0 fixes CVE-2026-114409 (third-party API keys/OAuth tokens in cleartext in logs/diagnostics) + a VM-kernel CVE; 4.96.x logs may already hold credentials — sanitise per Docker’s advisory, then updateManual host update. Weekly check; security releases immediately
macOSmini 27.0.1; pro 15.8.2macOS 27 lineHigh, structural (pro) — the 2018 Intel host is at its inferred hardware ceiling at 15.x; no path forwardNot an upgrade task: hardware-replacement plan for pro; patch while offered
OpenLDAP image (mini)osixia/openldap:1.5.0No newer line verified — long-dormant community image (inferred)Medium-High — every SSO path roots here; unpatched base accumulates silentlyImage migration (maintained slapd image), not a bump; quarterly CVE review until then
Harbor (pro)chart 1.19.2 / app v2.15.2v2.15.4; v2.15.3 reportedly carried a webhook-SSRF security fix (secondary source — inferred)Medium — 2 patches behind incl. a security patch; app was OutOfSync/Healthy at audit timeGitOps chart bump. Monthly patch roll
Tempo (mini + pro)chart 1.24.4 / 2.9.03.1 (GA 2026-09-30)Medium — a full major behind; 3.1 changes the default block format, so the jump needs a planGitOps chart bump ×2. Plan this quarter
Grafana (pro)11.3.1CRC in the same lab runs 13.2.3 (git pin) — internal proof 11.3 is ~2 majors staleMedium-High (inferred: 11.x out of support)Manifest image bump; align pro to CRC’s 13.2.3 baseline; quarterly
AlertManager (pro)v0.27.0Unproven (~0.28+ expected, not verified)Medium — 2024-era, bundled with the Prometheus problemManifest bump, with the Prometheus work
Vector aggregator (CRC, git)0.43.10.61.0 (2026-10-29)Medium — 18 minors behind; the logging dual-delivery proof re-runs on this build at the next CRC startGitOps image bump before the next CRC start; quarterly
CRC / OpenShift (m4)4.22.7 (inferred from git calibration)4.22.18 (2026-10-19); 4.22 Full Support ends 2026-12-31, Maintenance to 2027-12-31Medium — 11 z-patches behind; lag on a stopped cluster compounds at next startCRC bundle update on m4 (owner start call). Bump before next start; quarterly
Kyverno (mini, pro; CRC git)chart 3.9.1 / v1.19.1v1.19.2 (2026-10-21)Medium (compat) — 1.19 is tested on K8s 1.33–1.35; both DD clusters run 1.36 (inferred risk)GitOps chart bump ×3. Monthly; watch the compat matrix
StackRox (Central pro; sensors mini/pro; CRC staged)4.11.6Unproven for the upstream 4.11 line (the lab runs community images; the Red Hat build’s notes are a different lineage)Medium — cannot be assessed until the upstream latest is pinnedGitOps chart bump ×3. Monthly; first pin down the upstream latest
Docker Desktop Kubernetesmini v1.36.4, pro v1.36.1K8s 1.37 current; 1.36 supportedLow — same supported minor; pro 3 patches behind miniVia Docker Desktop app updates. Monthly; keep patch parity
Argo CD (mini)v3.5.3v3.5.6 (2026-10-20)Low — 3 patches behind, same supported minorGitOps. Monthly patch roll
cert-managerv1.21.21.21.3 (2026-10-23)Low — 1 patch behindGitOps chart bump. Monthly
Tailscale operator / clientoperator 1.104.2; clients mini 1.104.1 / pro 1.104.2Latest unverified; 1.104.x is an Oct-2026-era line (inferred current)Low — ≤1 patch skew between hostsGitOps chart bump / manual host update. Monthly, hosts in lockstep
Lokichart 7.3.0 / 3.6.11 (canary 3.6.12 — skew inside one install)Later minors unprovenLowGitOps chart bump ×2. Quarterly; fix the canary tag
ARC scale sets (pro)0.14.20.15.0 (2026-10-01)Low — 1 minor behindGitOps chart bump ×3. Quarterly
ARC classic (mini)chart 0.23.7 / controller v0.27.6Superseded by the scale-set generation (inferred)Medium — legacy duplicate alongside pro scale setsRetire, don’t upgrade (drained fallback; removal is GitOps)
OpenShift GitOps (CRC)channel gitops-1.22, automatic (measured in git)Channel-current by constructionLow-Med — the repo doc still claims channel 1.21 / v1.21.4: doc-vs-git drift that will mislead recoveryOLM subscription. Channel review quarterly; fix the doc
OpenShift Logging (CLF) (CRC)channel stable-6.6, automaticLatest 6.x unprovenLowOLM subscription. Review at CRC starts
kube-prometheus-stack (CRC, git)chart 91.8.2 (slim)UnprovenLow-Med — unverifiable while CRC is stoppedGitOps chart bump. Check at next CRC start
Dexstandalone v2.46.0; Argo-bundled v2.45.1UnprovenLow — 1-patch internal skewGitOps chart bump. Quarterly
Pushgateway (pro)v1.9.0 (CRC git pins v1.11.1 — newer than pro)UnprovenLowManifest bump, with the observability sweep
m4 macOS / CRC appUnproven — host unreachable with CRC stopped—UnknownVerify at the next m4 session

Cross-cutting finding (inferred): everything stood up in October 2026 is within 1–3 patches of latest. Everything inherited from the original mini observability manifests (Prometheus 2.55.1, Grafana 11.3.1, AlertManager 0.27.0, Logstash 8.17.3) was copied to pro unchanged during the migration — the migration modernised placement, not versions.

4. SLOs, error budgets, and the internal SLA

How the SLIs are computed today (measured, from the suite code)

  • Auth suite (report.py): availability = passes / executed runs, infra-down excluded per target. Windows: 394 runs, 2026-10-15 → 2026-10-30 (15 days, not 30 — the “last 30 days” table is currently identical to all-runs).
  • Service suite (service_report.py): passes / executed, infra-down and pending excluded; 152 runs over 5 days only. It applies a flat 99% to every check — treated as a real SLO, that would produce 17 simultaneous false “MISSED” verdicts.
  • Critical inconsistency (measured + inferred): the auth suite gates CRC checks on the tunnel and marks a dead tunnel infra-down (excluded); the service suite calls the CRC API directly and records a refusal as fail. That one difference manufactures most of the 34–65% service numbers while CRC is intentionally stopped. Likewise, in-flight E2E runs graded fail instead of pending inflate the miss.

Definitions adopted by this assessment (proposed)

  1. Two denominators, always. Conditional SLI (infra-down excluded) answers “does it work when its host is up?”; unconditional SLI (passes / all attempts) answers “could a user actually use it?”. Report both.
  2. Declared-down exclusion — honestly. A check is excluded only if the target was in a pre-declared stopped/maintenance state (a declared_status.yaml committed before or at the stop; a third status declared-down, counted and reported separately). Retroactive edits are not allowed; undeclared down stays a failure in the unconditional SLI. CRC — stopped since 2026-10-26 by owner decision — is exactly this case: CRC SLOs apply only to declared-up windows. If declared-down exceeds 50% of a window, the verdict is UNMEASURABLE, not MET.
  3. 99% everywhere is abandoned — unachievable for browser-through-tunnel checks, too lax for a negative security control, meaningless for a headroom gauge.
  4. Minimum-n rule: no MET/MISSED verdict on <100 executed runs in the window or <14 days of declared-up data — UNMEASURABLE instead.

SLO table (targets over rolling 30 days)

Current values are measured over the windows that exist today — auth suite 15 days, service suite 5 days — not a full 30. The statuses below are the assessment’s baseline call on that data; rows below the minimum-n rule (front doors n=99, log delivery n=62, oauth-only n≈73, and every service-suite row on its 5-day window) are provisional until a full window accrues, and are marked as called on short windows rather than silently treated as settled.

ServiceSLI sourceCurrent (measured)TargetStatus
Harbor — auth/API availabilityAuth suite harbor-ldap-login, n=35299.4%99.0%MET
Harbor — latencySame check, composite p953,968 msp95 ≤ 5 s (track the ldap_login step separately, ≤ 2 s)MET
Argo CD (mini) — loginAuth suite mini-argocd-ldap-login, n=36999.5% (exact 99.46%)99.0%; latency diagnostic only, p95 ≤ 25 s (now 18.4 s)MET
Vault — availability + unsealedService suite vault-availability, n=11999.2%99.0%, plus backup freshness ≤ 2 days as its own 100%-of-days target (the check currently allows 14 d)MET (fragile) — one further in-window failure breaks it
Front doors (*.rhels.com)Service suite front-door-sweep, n=9992.9% aggregate99.0% per vhost, from two vantages (aggregate kept as a 95% diagnostic)MISSED — the aggregate also misses its own 95% diagnostic level, and per-vhost data isn’t published yet
LDAP — bind matrixService suite ldap-bind-matrix, n=11393.8%99.0% conditional, reported per legMISSED — 7 failures ≈ 6× budget, unexplained; highest-priority investigation
MCP roundtripService suite mcp-roundtrip, n=12592.8%95.0% conditional on the PDI being available (raw SLI also reported)MISSED
Log delivery (dual-Loki)Auth suite grafana-cloud-log-delivery, n=6291.9% combined95.0% to each sink, reported per sink; declared-up windows only; no latency SLO (poll interval dominates)MISSED
CRC console / Argo authAuth suite, n=223 each95.1% / 95.1% conditional (unconditional 54.5% — 43% of attempts excluded as infra-down)95.0%, declared-up windows onlyUNMEASURABLE (provisional: at the line) — no declared-status record exists to build the window from
CRC Grafana authAuth suite, n=22294.6% conditional95.0%, declared-up onlyUNMEASURABLE (provisional: missed)
OAuth-only posture checksAuth suite, n=73/7486.3% / 86.5%Split out as security controls: 100%, reported as pass/fail events, never averagedMISSED / investigate — the SLI conflates posture regressions with login flakiness; cannot tell if any failure was a real breach
Wrong-password rejectionAuth suite console-wrong-password, n=22397.8% (5 failures)100% — zero tolerance; any failure is a security incident, not budget spendMISSED — treat as security events
E2E pipeline / CI runnersService suite e2e-* stagesStage numbers 34–83% — not service availability (cross-correlated stopped-era artefacts; no run-level composite exists)90% of triggered runs fully succeed + p95 trigger→complete ≤ 90 min (declared-up only); runners: 95% of jobs start ≤ 5 minUNMEASURABLE — no run-level SLI; runner queue time is not recorded at all
Cert headroomService suite cert-expiryBinary pass/fail only (39.8%, CRC-conflated)Not an availability SLO: 100% of days with min headroom ≥ 21 days; alert at 30 daysUNMEASURABLE — the days-left value exists in check detail but is never aggregated
Grafana / Docs / Prometheus / Alerts (per-vhost)Front-door sweep aggregate only—99.0% front-door availability via the per-vhost SLIUNMEASURABLE — no per-vhost or login checks exist

Latency SLOs explicitly not proposed: all CRC browser flows (median 18–41 s is tunnel + Chromium + OAuth settle waits — a latency SLO there would optimise the test harness), the LDAP matrix median (12.6 s is SSH/kubectl exec overhead), the sweep median (a sum of sequential probes), E2E stage “durations” (observer runtime), and the Vault median (SSH overhead). The only user-meaningful latency numbers today are the Harbor API and, loosely, MCP roundtrip (2.6 s median, PDI-tainted).

Error budgets and burn policy (proposed)

30 days = 43,200 minutes; for an hourly synthetic, the probe count is the operative budget.

SLO levelBudget / 30 d≈ failed hourly probesConsumed by current data (inferred)
99.0% (Harbor, mini-Argo, Vault, LDAP, front doors)432 min (7.2 h)~7 of 720Harbor ~29% · mini-Argo ~29% · Vault ~84% of its in-window allowance · LDAP ~620% — exhausted ~6× · front doors ~700% — exhausted
95.0% (CRC auth, MCP, log delivery)2,160 min (36 h)~36CRC console/Argo at the line · Grafana over · MCP over (7.2% errors) · log delivery over (8.1%)
90.0% (E2E pipeline)4,320 min (72 h)per-runUnmeasurable
TriggerAction
Any negative-auth-control failure; Vault sealed; cert headroom < 21 dImmediate incident, bypasses budget math: GitHub issue via the alert bridge + owner notification the same day
Fast burn: > 25% of the 30 d budget in 7 days, or 3 consecutive failed runsAlert via AlertManager → bridge → GitHub issue (the lab’s de-facto paging). Owner triages within 24 h; no new feature work on that service until triaged
50% of budget consumed (≥ 7 days left in window)Reliability work takes priority for that service; the next change must be a fix or carry an explicit owner waiver on the issue
100% consumedChange freeze on that service (reliability fixes and rollbacks only) + a short post-mortem note (cause, declared-vs-undeclared split, budget reset date); owner explicitly lifts the freeze. No spillover to unrelated services
Budget exhausted solely by infra-down misclassificationFix the measurement first, annotate the window measurement-invalid; never retroactively rewrite history or silently reset the budget
Declared-down periodsNever consume budget, never trigger burn — but declared-down days are reported next to every SLI

Internal SLA (proposed) — one-operator lab

RHELS Lab — Internal Service Commitments (draft, not a contract)

Who this covers. The lab owner (operator) commits to the app/platform teams and agents who build on the lab, and to the owner’s own projects. There is one operator. There is no on-call rotation, no NOC, and no vendor behind this.

What is committed (rolling 30 days, declared-up windows): Vault available & unsealed 99%; Harbor registry auth/API 99%; mini Argo CD login 99%; *.rhels.com front doors 99% per vhost; LDAP binds 99%. CRC/OpenShift platform, when declared up: console/Argo/Grafana auth 95%. MCP roundtrip 95% (PDI-dependent); dual-Loki log delivery 95%. Security controls (wrong-password rejection, oauth-only posture, signed-image policy) are not percentage commitments: a failure is an incident, full stop.

Support reality. Best-effort during the operator’s waking hours, America/Chicago. Alerts route to GitHub issues via the alert bridge — notification, not a guaranteed page. Target response: same day for Vault/Harbor/LDAP/front-door incidents; next 1–2 days for CRC, MCP, pipeline, and log-delivery issues. No response-time guarantee outside waking hours, weekends, or the operator’s absence.

Exclusions — these do not count against the commitments:

  1. Declared stops & maintenance — e.g. CRC stopped by owner decision since 2026-10-26; the chess-time CRC auto-stop (Mon/Wed evenings); any stop declared in advance in the lab repo.
  2. Host hardware / host OS — host failure, sleep, or power; Docker Desktop failure on the host.
  3. Connectivity the lab doesn’t control — home ISP (including its inbound 80/443 block), Tailscale/tailnet, the egress proxy, power at the house.
  4. External services — ServiceNow PDI (incl. its sleep/wake), Grafana Cloud, Let’s Encrypt, GitHub Actions availability.
  5. Tenant/demo workloads — the app1001-series and namespace-request experiments; reported, not masked, and not covered.

What “support” does not include. Data recovery beyond the existing Vault backup regime; guaranteed E2E pipeline turnaround; any availability claim for a service with no SLI.

Review. SLOs, budgets, and this SLA are reviewed when (a) a budget is exhausted, (b) CRC’s declared status changes, or (c) 30 days of clean declared-up data exists — whichever comes first. Changes are owner-approved and committed to the lab repo.

CI runners, as a commitment: best-effort with queue transparency — the proposed 95%-of-jobs-start-≤5-min objective becomes a commitment only once queue wait is actually measured (today it is not recorded at all).

Measurement gaps — cheapest fix first

  1. Declared-status record (declared_status.yaml + a third status in both suites). Blocks every honest CRC verdict. Do first — it unblocks half the table.
  2. Consistent infra-down gating in the service suite — preflight the CRC API once, as the auth suite preflights the tunnel.
  3. E2E run-level composite SLI — join stages by the run id already on disk; in-flight runs count pending until the 90-minute timeout (this also fixes the known observer defect where mid-cycle runs grade FAIL).
  4. Harbor push/pull success from real CI — report job-level step conclusions from the Actions API; login at 99.4% does not prove pulls work.
  5. CI runner queue wait — the Actions API timestamps on runs the trigger already dispatches.
  6. Cert headroom as a number — the check already fetches every cert’s expiry; emit days-left and aggregate min/p25. Report-side only.
  7. Front-door second vantage + per-vhost rows — the probe code already exists; run it from a second host.
  8. Real LDAP bind latency (on-mini) — time the bind calls inside the existing on-mini script instead of timing the SSH around them.
  9. Per-sink log-delivery SLI + delivery lag — the check already queries both Lokis separately; record per-sink results.
  10. Vault API latency + backup age as separate SLIs — emit backup age in days; tighten the freshness threshold from 14 d to 2 d.
  11. Argo census split (mini vs CRC) — the data is already fetched per cluster; mini GitOps health currently has no clean trend.
  12. Step-level p95 for Harbor ldap_login — the composite p95 is dominated by the deliberate wrong-password step (2 s median), masking real login-latency drift.

5. Where the fixes live

The gaps above are tracked as a checklist backlog in rhels/lab-monorepo (label spark): Vault unseal-key escrow decision, Harbor + StackRox backups, the ingress-nginx migration, Prometheus 3.13 LTS, Logstash 8.19.x, the Vault security line, Docker Desktop 4.97.0 on the mini, the mini root app + fork fix, the pro Serve assertion script, pf-ldap, the mini-Argo and LDAP-seed rebuild drills, Vault daily restore drills, a GitHub mirror/export, classic-ARC retirement, the OpenLDAP image migration, the Vector bump before the next CRC start, observability version alignment on pro, the stale DR/CRC-GitOps docs, and the twelve measurement gaps. Nothing on this page was changed silently — assessment and definitions only.