Skip to content

fix(chart): resolve serviceDbAccounts per environment — unbreak dev + staging ingestion (backend#1752) - #676

Merged
LukasWodka merged 2 commits into
developfrom
fix/1752-service-db-accounts-per-env
Aug 12, 2026
Merged

fix(chart): resolve serviceDbAccounts per environment — unbreak dev + staging ingestion (backend#1752)#676
LukasWodka merged 2 commits into
developfrom
fix/1752-service-db-accounts-per-env

Conversation

@LukasWodka

@LukasWodkaLukasWodka commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

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:

imageversionDB_USER with the flag off
ghcr.io/tracebloc/ingestor:dev0.8.5ValueError
ghcr.io/tracebloc/ingestor:stg0.8.5ValueError
prodDigest sha256:9098b3c9…0.7.7'edgeuser' — works

data-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/: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 (#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 channelTags already does — explicit override wins, otherwise keyed on the resolvedCLIENT_ENV:

serviceDbAccounts: # operator override, normally unsetserviceDbAccountsByEnv:
dev: true # already running the ingestor that needs the credsstg: true # ← this is what unbreaks stagingprod: false # explicitly unchanged

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 alias staging maps to stg instead 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_env fail-fasts if half-wired), mints tb_meta/tb_ingest, and spawned Jobs carry the credentials. A test asserts the Secret and the env move together.

Evidence

  • 384 chart tests (was 375), helm lint clean.
  • Rendered across every env name and both override directions.
  • Mutation-checked: reverting the templates turns the dev/stg cases red; swapping the resolver for a raw CLIENT_ENV lookup turns the staging alias 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.yaml renders two Secrets both named <release>-secrets. Identical on develop with serviceDbAccounts=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-job DB_USER/DB_PASSWORD, while leaving prod off until a deliberate flip.

The chart no longer treats serviceDbAccounts as a single global boolean. A new tracebloc.serviceDbAccounts helper resolves explicit serviceDbAccounts override first, else serviceDbAccountsByEnv keyed on normalized CLIENT_ENV (so stagingstg). Defaults in values.yaml are dev/stg: true, prod: false. jobs-manager, requests-proxy, and secrets now gate SERVICE_DB_ACCOUNTS / TB_* env and Secret keys on that helper instead of .Values.serviceDbAccounts alone.

Adds serviceDbAccountsByEnv to the values schema (nullable serviceDbAccounts), 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.

… 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>
@LukasWodkaLukasWodka self-assigned this Aug 11, 2026
…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

Copy link
Copy Markdown
ContributorAuthor

Added docs/SECURITY.md — the org rule is that a statement this change falsifies travels with it, and §4.1.1 / §8.10 had four:

  • tb_meta / tb_ingest listed as "not yet consumed" — S2 shipped (client-runtime#305/fix(installer): make the training size configurable at install (TRACEBLOC_TRAINING_RESOURCES) #308, client#664); they are consumed wherever the flag is on
  • edgeuser 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 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:

Turn this flag on for a fleet before its ingestor moves to 0.8.x, never after. For prod that means before images.ingestor.prodDigest moves past 0.8.2 (client#490).

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.

@LukasWodka
LukasWodka merged commit 760bb43 into developAug 12, 2026
22 checks passed
@LukasWodka
LukasWodka deleted the fix/1752-service-db-accounts-per-env branch August 12, 2026 06:04
Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@LukasWodka@saadqbal