Description
What happened
External repository review at commit c7bebd1 found that the runtime database role is cluster-wide, which breaks when the role-creation script is run for a second environment on the same PostgreSQL cluster. Static reading of scripts/create_app_role.py L31–67 and api/db.py L209–241; not reproduced live.
Reconstructed scenario:
- First run: creates
te_app(cluster-wide), writes password to~/.te-migration/app-db.env. - Second run (same cluster, different env): rotates
te_apppassword (same role), overwrites credentials file. - The first environment's connections silently break on the next reconnect.
Password rotation is documented. The cross-environment invalidation consequence isn't.
Why this matters
Dev PCs commonly share one PostgreSQL cluster across environments. The product owner's dev setup runs PG 17 on 5432 and PG 18 on 5433; standing up Dev and Test on either shared cluster trips this.
Production is less affected (each env typically gets its own Azure PG), but the setup wizard runs on dev PCs where this is exactly the shape it fails on.
The te_app runtime role was introduced in M3d. There may be in-flight work assuming the current single-role model.
Decision taken 3 Nov 2026
Option (a) of 3 considered: per-environment role names and per-environment credential files.
te_app_dev,te_app_test,te_app_staging,te_app_prodas role names.~/.te-migration/app-db-dev.env,app-db-test.env, etc. as credential file names.- Role-creation script takes a mandatory
--envarg; refuses without it.
Option (b) rejected: per-database role via PostgreSQL's CREATE ROLE … IN DATABASE …. More idiomatic PostgreSQL but overkill for the scope and harder to reason about.
Option (c) rejected: documenting the limitation and warning users is a workaround that leaves the hazard in place. Correctness over simplicity.
Proposed
scripts/create_app_role.py— add mandatory--envarg; derive role name aste_app_<env>; write credential file as~/.te-migration/app-db-<env>.env.api/db.py— read role name and credential file based on current environment, not a hardcodedte_app.- Any scripts, docs or configs that currently reference
~/.te-migration/app-db.envas a bare name need updating. The PR should enumerate these in its description. - Migration path for existing dev PCs: if
~/.te-migration/app-db.envexists (from pre-fix usage), the new script offers to migrate it toapp-db-dev.envon first run with--env dev.
Done when
- Reproduction test added: shell test that provisions Dev, then Test, then verifies Dev's connection still works byte-identically.
- The test fails on
mainatc7bebd1without the fix. - The test passes with the fix.
- All existing references to
~/.te-migration/app-db.envenumerated in the PR description and updated in the change. - CI replica run quoted on the PR (counts in passed / failed / skipped form).
- Migration path exercised in a test (existing single-role dev PC upgraded cleanly).
Reference
Tracker row G36 (main tab). Repo review finding RV-S3. Related to M3d (which introduced te_app). Related: G34 (RV-S1 production DB config), G37 (RV-S4 image secrets) — all Standards P1 touching deployment and credential safety.
Activity
Merge main into #173 branch; move the new test into tests/system
Merge main into #173 branch again; regenerate the test catalogue
Merge pull request #208 from amar-python/fix/173-per-environment-runt…
amar-python commentedon Nov 10, 2026
Independent verification of the merged fix (#208), 10 Nov 2026
Checked against
mainat 942bc7e on PostgreSQL 16.15 withscram-sha-256(the PR notestrustauth hides the bug). This covers the gaps #208's own description listed: no literal red-then-green, andstart-api.ps1never run.The bug, red then green (same four steps, real
create_app_role.py, one cluster, Dev then Test)main(3006f12)main(942bc7e)te_appcreatedte_app_devcreatedte_app"new password set"te_app_testcreatedFATAL: password authentication failedte_app(one, shared)te_app_dev,te_app_testUpgrade of a pre-fix dev PC: provisioned with the old script, then ran
--env dev. The legacyapp-db.envwas moved aside untouched (same SHA),app-db-dev.envwas created mode0600, the new role connects, and the script printed theDROP OWNED BY te_app; DROP ROLE te_app;without running it. A second run is idempotent. No--env, or--env prdo, is refused.start-api.ps1, run in PowerShell 7.4.6: I ran the script's real credential-loading block (lines 1 to 56, byte-identical tomain) against files written by the real Python script, then connected to Postgres with what it loaded:API_ENVunset)app-db-dev.env, connects aste_app_devAPI_ENV=testapp-db-test.env, connects aste_app_test... create_app_role.py --env stagingAPP_DB_USERalready setTests:
test_runtime_role_per_env.pyandtest_runtime_role.pypass 16 of 16 onmain.Not covered: the rest of the script (the port-8000 check uses Windows-only
Get-NetTCPConnection, then it launches uvicorn); Windows PowerShell 5.1 (I used PowerShell 7 on Linux, withUSERPROFILEset by hand); a real Windows Git Bash session.Verified by Claude Code
Generated by Claude Code