Skip to content

[settings-naming] Normalize ingestor DB/path env vars to TRACEBLOC_ prefix - #587

Open
aptracebloc wants to merge 2 commits into
developfrom
settings-naming/env-normalize
Open

[settings-naming] Normalize ingestor DB/path env vars to TRACEBLOC_ prefix#587
aptracebloc wants to merge 2 commits into
developfrom
settings-naming/env-normalize

Conversation

@aptracebloc

@aptracebloc aptracebloc commented Sep 11, 2026

Copy link
Copy Markdown
Contributor

What

RFC-0076 settings-naming for the data-ingestors env surface (data-ingestors#585, part of the backend#3391 epic). The ingestor now reads its own DB and path env vars alias-first: the canonical TRACEBLOC_-prefixed name wins, the bare name keeps working as a deprecated read-side alias (remove_by: 2026-12-31).

Old → new (canonical is read first; the bare name is a deprecated alias)

Old (deprecated alias) New (canonical) Kind
DB_USER TRACEBLOC_DB_USER required credential
DB_PASSWORD TRACEBLOC_DB_PASSWORD required credential
DB_NAME TRACEBLOC_DB_NAME optional (default training_test_datasets)
SRC_PATH TRACEBLOC_SRC_PATH optional (default "")
LABEL_FILE TRACEBLOC_LABEL_FILE optional (default "")

Not renamed here: MYSQL_HOST/MYSQL_PORT (the stock MySQL-image / docker-entrypoint contract, not ours) and TABLE_NAME (cross-repo ingest wire contract; its rename is a B4 decision — deferred).

Blank-handling

_read_env_alias resolves on is not None, not truthiness: an explicitly-set-empty canonical (TRACEBLOC_DB_NAME="") is a present value that wins over a stale legacy name or the default — restoring the pre-PR os.environ.get behaviour and preserving an explicit blank for the caller's own guard. An optional field returns the blank as-is; a required credential's _require_env still fails fast on the blank, so a blank required credential fails loudly rather than silently authenticating with a stale legacy secret. (Matches what backend/client-runtime settled on: "preserve present-but-blank for the caller's guard".)

runtime_env contract stays legacy-required until the phase-2 spawner flip

runtime_env.v1.json's required[].name stays DB_USER / DB_PASSWORDthe name jobs-manager actually injects today. The added aliases: ["TRACEBLOC_DB_USER"] / ["TRACEBLOC_DB_PASSWORD"] documents the canonical the reader also accepts. Declaring the canonical name required before the spawner injects it would be a reader-before-writer violation and would falsely fail the backend spawner-contract check. Flipping the required name to the canonical is a coordinated phase-2 step (when the spawner injects the canonical); accordingly _require_env takes the injected name as arg 0 (what the AST contract test pins) and reads the canonical alias ahead of it. Contract version is unchanged.

Docs swept to the canonical spelling (+ deprecated-alias note)

  • Readme.md, ingestor-job.yaml — the stale "bare DB_USER/DB_PASSWORD below still work" comment is reworded: the env block now sets TRACEBLOC_DB_*, and the bare names remain read-side aliases (not set in this file).
  • template READMEs: tabular_classification, tabular_regression, time_series_classification, time_series_forecasting, time_to_event_prediction (plus the previously-updated causal_language_modeling / embeddings / masked_language_modeling / seq2seq).
  • e2e/README.md.

Deferred follow-ups (not in this PR)

  • e2e legacy-name reads (phase-2 setter side). The 6 e2e contract tests (test_image_lookup_contract_e2e.py, test_semseg_client_contract_e2e.py, test_content_compare_e2e.py, test_characterization.py, test_database_e2e.py, test_ingest_e2e.py) connect to MySQL via os.environ["DB_USER"] directly, and e2e/conftest.py still injects the legacy DB_* names. Latent — breaks only when the alias is dropped; the conftest is the phase-2 setter side and moves with the spawner flip.
  • TABLE_NAME rename — cross-repo ingest wire contract; its eventual name is a B4 decision (already deferred).

Verification

  • Full unit suite green (2386 passed, 1 xfailed). New/flattened tests cover alias-first reads, "canonical-blank wins" for DB_NAME and (fail-fast) for DB_USER/DB_PASSWORD, and the reconciled runtime_env contract.
  • black --check and ruff check (repo ruff.toml, pinned ruff 0.15.20) clean.
  • Version-bump gate: mid-cycle (__version__ 0.8.21 pending vs v0.8.20 released), no bump required.

Closes #585
Part of tracebloc/backend#3391

🤖 Generated with Claude Code


Note

Medium Risk
Changes how MySQL credentials and ingest paths are read from the environment, including edge cases when both old and new names are set; backward-compatible aliases limit breakage, but mis-set blank canonical vars can fail startup where legacy secrets used to work.

Overview
Implements RFC-0076 settings-naming (data-ingestors#585): the ingestor now resolves DB and path settings alias-first, preferring TRACEBLOC_DB_USER, TRACEBLOC_DB_PASSWORD, TRACEBLOC_DB_NAME, TRACEBLOC_SRC_PATH, and TRACEBLOC_LABEL_FILE. Legacy names (DB_*, SRC_PATH, LABEL_FILE) still work until 2026-12-31.

Config gains _read_env_alias and extends _require_env(required_name, canonical) so canonical values win when both are set; a present-but-empty canonical overrides a legacy value (optional fields keep ""; required creds still fail fast instead of falling back to a stale secret).

runtime_env.v1.json documents aliases for the two required credentials while required.name stays DB_USER / DB_PASSWORD until jobs-manager emits the prefixed names (phase 2). Contract tests now pin alias sets against config.py via AST.

Docs and samples (Readme.md, ingestor-job.yaml, template READMEs, e2e/README.md) switch to the TRACEBLOC_* spellings with deprecation notes. Unit tests cover alias precedence, blank-canonical behavior, and updated clean_env var lists.

Reviewed by Cursor Bugbot for commit 2cc6360. Bugbot is set up for automated code reviews on this repo. Configure here.

…refix

Read DB_USER/DB_PASSWORD/DB_NAME and SRC_PATH/LABEL_FILE alias-first via a new
_read_env_alias/_require_env: the canonical TRACEBLOC_-prefixed names win, the
bare names stay a deprecated read-side alias (remove_by 2026-12-31). A present-
but-empty value resolves as present (is-not-None), so a blank canonical wins
over a stale legacy value -- an optional field returns the blank as-is, while a
required credential fails fast instead of silently authenticating with the
legacy secret.

The runtime_env contract keeps DB_USER/DB_PASSWORD as the required names the
spawner (jobs-manager) injects; the required-name flip to the canonical is a
coordinated phase-2 step, so _require_env takes the injected name as arg 0
(what the contract test pins) and reads the canonical alias ahead of it.

Docs (ingestor-job.yaml, Readme, e2e + template READMEs) moved to the canonical
spelling with the deprecated-alias note. data-ingestors#585.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

Comment thread tracebloc_ingestor/schema/runtime_env.v1.json
…g.py (Bugbot)

The schema's `aliases` and _require_env's `canonical` argument were two
hand-kept copies of the same alias-first names, with only arg 0 (the
required `name`) pinned. Extend the AST reader to also capture the
canonical alias per call, and assert the schema `aliases` set equals the
set the reader actually accepts — in both directions. Over-claiming
(contract lists a name the reader ignores) and under-claiming (reader
accepts a name the contract omits) now both fail the contract test, so a
spawner trusting `aliases` can never drift from the reader.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@aptracebloc

Copy link
Copy Markdown
Contributor Author

bugbot run

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stale Bugbot comment from a previous run.

@aptracebloc

Copy link
Copy Markdown
Contributor Author

bugbot run

@aptracebloc

Copy link
Copy Markdown
Contributor Author

Addressed the Bugbot finding ("Aliases lack bidirectional contract pins"): extended tests/test_runtime_env_contract.py so the schema's aliases and _require_env's canonical argument can no longer drift.

The AST reader now captures both args per _require_env call (the required name and the alias-first canonical), and a new test asserts the schema's aliases set equals the set the reader actually accepts — in both directions. Over-claiming (schema lists a name the reader ignores) and under-claiming (reader accepts a name the schema omits) now both fail the contract test, so a spawner trusting aliases can never accept a name the reader no longer honors. Verified both drift directions fail; full make check green (2387 passed).

— drafted with Claude Code

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

✅ Bugbot reviewed your changes and found no new issues!

Comment @cursor review or bugbot run to trigger another review on this PR

Reviewed by Cursor Bugbot for commit 2cc6360. Configure here.

@LukasWodka
LukasWodka requested review from saqlainsyed007 and removed request for shujaatTracebloc September 11, 2026 14:20
Comment thread e2e/README.md

> The ingestor reads its DB env alias-first (RFC-0076 settings-naming), so the
> canonical `TRACEBLOC_DB_*` spellings above work. The direct-connect contract
> tests (`test_*_e2e.py`) still read the legacy `DB_USER`/`DB_PASSWORD`/`DB_NAME`

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The note says conftest backfills to the same root defaults, but conftest.py backfills via os.environ.get("DB_USER", "root") (lines 81-83) — that only lands on root when DB_USER/DB_PASSWORD are unset. A user who follows the new guidance and sets non-root creds via the canonical names (TRACEBLOC_DB_USER=myuser TRACEBLOC_DB_PASSWORD=...) leaves the bare DB_USER/DB_PASSWORD unset, so the ingestor-path connects as myuser while the direct-connect test_*_e2e.py tests connect as root — a silent split that didn't exist before this PR (both sides used the same DB_* names). Consider having conftest read TRACEBLOC_DB_* alias-first too (matching the ingestor), or noting the example only holds for the root container defaults.

@saqlainsyed007 saqlainsyed007 left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approving. Clean, tightly-scoped RFC-0076 settings-naming migration for the ingestor's DB/path env surface — and correctly a shim, not a hard-cut: _read_env_alias reads the canonical TRACEBLOC_* name first and falls back to the bare deprecated name (remove_by: 2026-12-31), so no reader or deployment breaks in lockstep.

What I verified:

  • Migration is alias-first (is not None, not truthiness): a present-but-blank canonical wins over a stale legacy value — returned as-is for optional fields, and correctly fail-fast in _require_env for the required credentials so a blank never silently authenticates with a legacy secret. Well-covered by the new parametrized tests.
  • Var-SETTING side moves in this same PR: ingestor-job.yaml sets the TRACEBLOC_* names, docs/templates swept, deprecation notes added. No deploy mismatch.
  • No old-name reader left behind in a breaking way. The e2e test_*_e2e.py / conftest.py still use the bare DB_* names — explicitly deferred as phase-2 (setter side moves with the spawner flip), and safe meanwhile because the alias resolves both.
  • runtime_env.v1.json keeps DB_USER/DB_PASSWORD as the required contract names (reader-before-writer) and documents the canonical as aliases; the new AST↔schema test_declared_aliases_match_what_the_reader_accepts pins the two copies bidirectionally.

CI fully green (pytest 3.11/3.12, e2e real MySQL, Bugbot, quality suite). One low-severity docs nit posted inline on e2e/README.md (the "same root defaults" note only holds for the root example) — non-blocking, overlaps the phase-2 deferral already named in the PR body.

Sign up for free to 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.

[settings-naming] data-ingestors: TRACEBLOC_DB_* + prefix owned config env vars (alias-first)

2 participants