Uh oh!
There was an error while loading. Please reload this page.
fix(chart): resolve serviceDbAccounts per environment — unbreak dev + staging ingestion (backend#1752) - #676
Conversation
… staging ingestion (backend#1752) dev and staging ingestion are broken right now. Verified by running the published images, not inferred: ghcr.io/tracebloc/ingestor:dev -> 0.8.5, DB_USER raises ValueError ghcr.io/tracebloc/ingestor:stg -> 0.8.5, DB_USER raises ValueError prodDigest sha256:9098b3c9… -> 0.7.7, DB_USER = 'edgeuser', works data-ingestors#468 removed the ingestor's edgeuser fallback on the stated precondition that this flag was "on fleet-wide". It was on NOWHERE. dev and staging edges float on the :dev/:stg channels and took the change the same day, so every ingestion Job fails at Config() before reading a byte. Prod escaped only because its ingestor is digest-pinned to the 0.7 line --- a caution engineered for D16, not for this, and one client#490 is about to spend. #1151 records the rollout as "flip per environment, dev first". There was no MECHANISM for that: one global boolean meant "per environment" was hand-editing every edge and remembering which fleet was where. The fleet's posture could not be read in one place and nothing tested it. So the flag now resolves like `channelTags` already does --- an explicit `serviceDbAccounts` override wins, otherwise `serviceDbAccountsByEnv` keyed on the RESOLVED CLIENT_ENV: dev: true both are already running the ingestor that requires the stg: true per-Job credentials, so this is what makes them work again prod: false explicitly. Prod runs the 0.7-line ingestor, which still has the fallback; flipping prod is a separate windowed decision (#1528 S0 drill) and must happen BEFORE prod's ingestor is repinned past 0.8.2. Resolved through `tracebloc.clientEnv`, so a documented alias like `staging` maps to `stg` rather than silently missing its entry --- that is backend#1723, one env-name spelling away, and it has its own test. The Secret and the jobs-manager env are gated on the same resolver, so a flip stays atomic: jobs-manager fail-fasts when the flag is on and the Secret is unwired, and a half-flip would crash-loop it. 384 chart tests (was 375). Mutation-checked: reverting the templates turns the dev/stg cases red, and swapping the resolver for a raw CLIENT_ENV lookup turns the `staging` alias case red on its own. One note for review, PRE-EXISTING and not from this change: with the flag on, secrets.yaml renders TWO Secrets both named `<release>-secrets`. Identical on develop with `serviceDbAccounts=true`, so out of scope here, but worth a look. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ackend#1752) Org rule: a statement my change falsifies travels with the change. Four claims in docs/SECURITY.md were wrong the moment S2 shipped and the flag started resolving per environment: * `tb_meta` / `tb_ingest` were listed as "not yet consumed" --- S2 shipped (client-runtime#305/#308, client#664); they ARE consumed where the flag is on * `edgeuser` was listed as the default identity for jobs-manager, requests-proxy and ingestion pods "today" --- true only on prod now * "gated on serviceDbAccounts (default off) ... purely additive ... a default install authenticates exactly as it did before" --- wrong on both counts * the S1/S2 rollout steps still read as pending AND THE DOCUMENT DID NOT MENTION THE HAZARD AT ALL, which is the part that actually cost us a day. The ingestor REQUIRES DB_USER/DB_PASSWORD from 0.8.0 (data-ingestors#468) and jobs-manager injects them only when the flag is on, so a fleet on an ingestor >= 0.8.0 with the flag OFF fails every ingestion Job at Config(). §4.1.1 now states the ordering as an explicit constraint --- turn the flag on for a fleet BEFORE its ingestor moves to 0.8.x, never after --- names the prod-specific form of it (before prodDigest moves past 0.8.2, client#490), and points at the CI check that enforces it (backend#1754). A security doc that describes a retired fallback as present is worse than one that says nothing: it is the document someone reads before flipping a prod fleet. 384 chart tests, style guard and fact-check clean. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
LukasWodka
commented
Aug 11, 2026
Added
And the document didn't mention the hazard at all, which is the part that actually cost a day. §4.1.1 now carries it as an explicit ordering constraint:
with a pointer to the CI check that enforces it (backend#1754). A security doc describing a retired fallback as present is worse than one that says nothing — it's the document someone reads before flipping a prod fleet. 384 chart tests, style guard, fact-check and drift all clean. |
Uh oh!
There was an error while loading. Please reload this page.
Fixesbackend#1752. dev and staging ingestion are broken right now — this unbreaks them.
Verified, not inferred
I ran the published images rather than reasoning from PR descriptions:
DB_USERwith the flag offghcr.io/tracebloc/ingestor:devghcr.io/tracebloc/ingestor:stgprodDigest sha256:9098b3c9…'edgeuser'— worksdata-ingestors#468 removed the edgeuser fallback on the stated precondition that this flag was "on fleet-wide". It was on nowhere. dev and staging edges float on the
:dev/:stgchannels and took the change the same day, so every ingestion Job fails atConfig()before reading a byte.Prod escaped only because its ingestor is digest-pinned to the 0.7 line — a caution engineered for D16 (#1151), not for this, and one that client#490 is about to spend.
The actual gap
backend#1151 records the rollout as "flip per environment, dev first". There was no mechanism for that. One global boolean meant "per environment" was hand-editing every edge and remembering which fleet was where. The fleet's posture couldn't be read in one place and nothing tested it.
So the flag now resolves the way
channelTagsalready does — explicit override wins, otherwise keyed on the resolvedCLIENT_ENV:prod stays off, deliberately. It runs the 0.7-line ingestor which still has the fallback. Flipping prod is a separate windowed decision (#1528 S0 drill) — and it must happen before prod's ingestor is repinned past 0.8.2, which is the constraint I flagged on client#490.
Resolution goes through
tracebloc.clientEnv, so the documented aliasstagingmaps tostginstead of silently missing its entry. That's backend#1723 — one env-name spelling away — and it has its own test.Safety of the flip
The Secret and the jobs-manager env are gated on the same resolver, so a flip is atomic in one upgrade: the Secret is created, jobs-manager restarts, validates the wiring (
_require_service_db_envfail-fasts if half-wired), mintstb_meta/tb_ingest, and spawned Jobs carry the credentials. A test asserts the Secret and the env move together.Evidence
helm lintclean.CLIENT_ENVlookup turns thestagingalias case red on its own.One of my own checks was vacuous mid-way and I want to flag it: my first render sweep reported "not wired" for every environment, and I nearly read that as a logic bug. The renders were erroring on
values.schema.json(got null, want boolean) and my grep counted zero either way. The corrected sweep asserts the render succeeded before interpreting the result.Note for review — pre-existing, not from this change
With the flag on,
secrets.yamlrenders two Secrets both named<release>-secrets. Identical ondevelopwithserviceDbAccounts=true, so out of scope here, but worth someone's eyes.🤖 Generated with Claude Code
Note
Medium Risk
Changes MySQL credential wiring and Secret emission for dev/stg fleets on upgrade; prod stays off but mistakes in env resolution or prod override could break ingestion or widen DB identity exposure.
Overview
Restores dev/staging ingestion by turning on dedicated MySQL identities (
tb_meta/tb_ingest) where the floating ingestor now requires per-jobDB_USER/DB_PASSWORD, while leaving prod off until a deliberate flip.The chart no longer treats
serviceDbAccountsas a single global boolean. A newtracebloc.serviceDbAccountshelper resolves explicitserviceDbAccountsoverride first, elseserviceDbAccountsByEnvkeyed on normalizedCLIENT_ENV(sostaging→stg). Defaults invalues.yamlare dev/stg: true, prod: false. jobs-manager, requests-proxy, and secrets now gateSERVICE_DB_ACCOUNTS/TB_*env and Secret keys on that helper instead of.Values.serviceDbAccountsalone.Adds
serviceDbAccountsByEnvto the values schema (nullableserviceDbAccounts), a Helm unittest suite for env/alias/override/Secret lockstep, bumps chart to 1.9.33, and updates SECURITY.md for per-env rollout and ingestor ordering.Reviewed by Cursor Bugbot for commit d7285f1. Bugbot is set up for automated code reviews on this repo. Configure here.