Skip to content

Harden Railway deployment DB secrets#95

Open
willjy1 wants to merge 3 commits into
BAWES-Universe:masterfrom
willjy1:codex/harden-railway-deployment-db-secrets
Open

Harden Railway deployment DB secrets#95
willjy1 wants to merge 3 commits into
BAWES-Universe:masterfrom
willjy1:codex/harden-railway-deployment-db-secrets

Conversation

@willjy1
Copy link
Copy Markdown

@willjy1 willjy1 commented May 16, 2026

Related to #55

/claim #55

Scope

This is a narrow Railway deployment DB runtime-secret hardening slice. It does not touch S3/AWS keys, SQS/EventManager, MediaConvert, SES/mailers, Xero, Cloudinary, OneSignal, Civil ID upload/remove flows, live Railway/database access, candidate data, or real credential values.

Summary

  • Move dev-server Railway app DB, wallet DB, and Redis connection secrets to runtime environment variables.
  • Remove committed MySQL passwords from dev/prod Railway deployment scripts.
  • Require MYSQL_PASSWORD at runtime and pass it via MYSQL_PWD instead of the mysql command-line -p... argument.
  • Document the required Railway variables and add a static regression guard for this deployment-secret slice.

Verification

py -3 tests\check-railway-db-runtime-secrets.py
# Railway DB runtime secret check passed.

py -3 -m py_compile tests\check-railway-db-runtime-secrets.py

C:\Program Files\Git\bin\sh.exe -n environments/dev-server-railway/deployments/july_2025/3_july_2025_deployment.sh
C:\Program Files\Git\bin\sh.exe -n environments/dev-server-railway/deployments/july_2025/29_july_2025_deployment.sh
C:\Program Files\Git\bin\sh.exe -n environments/prod-railway/deployments/july_2025/3_july_2025_deployment.sh
C:\Program Files\Git\bin\sh.exe -n environments/prod-railway/deployments/july_2025/29_july_2025_deployment.sh

git diff --check

php -l could not be run here because PHP is not installed in this environment. The PHP change is limited to replacing literal config values with existing getenv(...)-style config expressions.

Safety boundary

No live Railway, database, Redis, AWS/IAM/S3, candidate data, private exports, screenshots, or credential values were accessed or included.

Transparency: automation-assisted; I reviewed the diff and verification before submitting.

Summary by CodeRabbit

  • Documentation

    • Added a guide for managing database and cache credentials via runtime environment variables.
  • Chores

    • Updated app and deployment configurations to read DB and Redis connection settings from environment variables and enforce supplying the DB password at deploy time.
  • Tests

    • Added an automated check that validates runtime secrets are sourced from environment variables and not embedded in configs or scripts.

Review Change Stack

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented May 16, 2026

Warning

Rate limit exceeded

@willjy1 has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 49 minutes and 18 seconds before requesting another review.

You’ve run out of usage credits. Purchase more in the billing tab.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: f0bbfea1-dd43-4f24-a5bd-39f79fdc6508

📥 Commits

Reviewing files that changed from the base of the PR and between 8a9b1cc and 8e25c38.

📒 Files selected for processing (1)
  • tests/check-railway-db-runtime-secrets.py
📝 Walkthrough

Walkthrough

Replaces hardcoded DB and Redis credentials with Railway environment variables in PHP config and deployment scripts, adds docs describing required runtime variables, centralizes MySQL calls via run_mysql (using MYSQL_PWD), and adds a Python test to enforce these rules.

Changes

Railway Database Runtime Secrets

Layer / File(s) Summary
Documentation and runtime secret requirements
docs/railway-db-runtime-secrets.md
New guide lists required Railway environment variables for primary DB, wallet DB, and Redis and prescribes supplying MYSQL_PASSWORD via Railway variables and using MYSQL_PWD rather than embedding passwords.
PHP application configuration for environment variables
environments/dev-server-railway/common/config/main-local.php
Dev config now sources dsn, username, and password for components.db and components.walletDb, and hostname, username, password, port, and database for components.redis, from environment variables.
Dev server deployment scripts refactoring
environments/dev-server-railway/deployments/july_2025/29_july_2025_deployment.sh, environments/dev-server-railway/deployments/july_2025/3_july_2025_deployment.sh
Both dev scripts read MySQL host/port/user/database from env vars with defaults, require MYSQL_PASSWORD, introduce run_mysql() that sets MYSQL_PWD and forwards args to mysql, and use run_mysql for readiness checks and SQL execution.
Production deployment scripts refactoring
environments/prod-railway/deployments/july_2025/29_july_2025_deployment.sh, environments/prod-railway/deployments/july_2025/3_july_2025_deployment.sh
Production scripts mirror dev changes: env-var-based MySQL parameters with defaults, required MYSQL_PASSWORD, run_mysql() helper, and using run_mysql for probes and SQL commands.
Runtime secret compliance validation test
tests/check-railway-db-runtime-secrets.py
New test enforces that docs and dev config reference required env vars, component passwords are sourced via getenv(), deployment scripts include required tokens and do not embed MYSQL_PASSWORD, and that no forbidden secret fragments are present.

Sequence Diagram

sequenceDiagram
  participant DevDeploymentScript
  participant Environment
  participant run_mysql
  participant MySQLClient

  DevDeploymentScript->>Environment: Read MYSQL_HOST/PORT/USER/DATABASE (with defaults)
  DevDeploymentScript->>Environment: Require MYSQL_PASSWORD (fail if missing)
  DevDeploymentScript->>run_mysql: Call run_mysql -e "SELECT 1"
  run_mysql->>run_mysql: Set MYSQL_PWD from environment
  run_mysql->>MySQLClient: Invoke mysql with host/port/user (uses MYSQL_PWD)
  MySQLClient-->>run_mysql: Return result
  run_mysql-->>DevDeploymentScript: Exit with status
  DevDeploymentScript->>run_mysql: Call run_mysql "$MYSQL_DATABASE" -e "ALTER TABLE..."
  run_mysql->>MySQLClient: Execute schema changes
  MySQLClient-->>run_mysql: Confirm
Loading

🎯 3 (Moderate) | ⏱️ ~20 minutes

🐰 A Bunny's Ode to Secrets
Once passwords hid inside the code,
Now Railway vars bear the load,
run_mysql hums a safer tune,
No more secrets baked by noon,
Hops of joy — secure and light, we hop.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.56% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Harden Railway deployment DB secrets' accurately summarizes the main objective: improving security of database credentials in Railway deployments through environment variables and removal of hardcoded passwords.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/check-railway-db-runtime-secrets.py`:
- Around line 18-23: Replace the hard-coded FORBIDDEN_SECRET_FRAGMENTS list with
a runtime-loaded source (e.g., read a CI-provided environment variable like
FORBIDDEN_SECRET_FRAGMENTS, split it, or load from a secure file) and update any
tests/logic that reference FORBIDDEN_SECRET_FRAGMENTS (including the occurrences
around lines 68-69) to use that runtime value; when reporting failures, never
log or assert the raw fragment strings — instead report counts or use a masked
representation (e.g., show only prefix/suffix or a fixed placeholder) so
secret-like values are not printed to logs or git history.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 201d38c9-e69d-420a-9644-192dc5bcb587

📥 Commits

Reviewing files that changed from the base of the PR and between 7b023ff and e2a3e4e.

📒 Files selected for processing (7)
  • docs/railway-db-runtime-secrets.md
  • environments/dev-server-railway/common/config/main-local.php
  • environments/dev-server-railway/deployments/july_2025/29_july_2025_deployment.sh
  • environments/dev-server-railway/deployments/july_2025/3_july_2025_deployment.sh
  • environments/prod-railway/deployments/july_2025/29_july_2025_deployment.sh
  • environments/prod-railway/deployments/july_2025/3_july_2025_deployment.sh
  • tests/check-railway-db-runtime-secrets.py

Comment thread tests/check-railway-db-runtime-secrets.py Outdated
@willjy1 willjy1 force-pushed the codex/harden-railway-deployment-db-secrets branch from e2a3e4e to b11f8db Compare May 16, 2026 08:34
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
tests/check-railway-db-runtime-secrets.py (1)

94-106: ⚡ Quick win

Make secret-source checks tolerant to equivalent PHP formatting.

These assertions depend on exact quoting/spacing (getenv('...'), 'password' => getenv('...')), so harmless formatting changes can fail CI even when behavior is correct.

Proposed fix
+import re
@@
     for name in DEV_CONFIG_ENV_VARS:
-        require(f"getenv('{name}')" in config, f"Dev Railway config must use getenv('{name}').")
+        require(
+            re.search(rf"getenv\(\s*['\"]{re.escape(name)}['\"]\s*\)", config) is not None,
+            f"Dev Railway config must use getenv('{name}').",
+        )
         require(f"`{name}`" in doc, f"Docs must mention `{name}`.")
@@
     for component, env_var in COMPONENT_PASSWORD_ENV.items():
         block = component_block(config, component)
         require(
-            f"'password' => getenv('{env_var}')" in block,
+            re.search(
+                rf"'password'\s*=>\s*getenv\(\s*['\"]{re.escape(env_var)}['\"]\s*\)",
+                block,
+            ) is not None,
             f"{component} password must come from getenv('{env_var}').",
         )
-        require("'password' => '" not in block, f"{component} password must not be an inline literal.")
-        require("'password' => \"" not in block, f"{component} password must not be an inline literal.")
+        require(
+            re.search(r"'password'\s*=>\s*['\"]", block) is None,
+            f"{component} password must not be an inline literal.",
+        )
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@tests/check-railway-db-runtime-secrets.py` around lines 94 - 106, The current
tests iterate DEV_CONFIG_ENV_VARS and COMPONENT_PASSWORD_ENV and use exact
string checks (e.g. require(f"getenv('{name}')" in config) and
require(f"'password' => getenv('{env_var}')" in block)) which break on harmless
PHP formatting differences; update the assertions in the loop that references
DEV_CONFIG_ENV_VARS, COMPONENT_PASSWORD_ENV and component_block() to use
case-sensitive regex matching that tolerates single or double quotes, optional
whitespace around => and parentheses, and optional spaces after getenv (e.g.
pattern like r"getenv\(\s*['\"]{name}['\"]\s*\)" and
r"['\"]password['\"]\s*=>\s*getenv\(\s*['\"]{env_var}['\"]\s*\)"), and replace
the existing literal "in" checks with a regex search that preserves the same
failure messages.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@tests/check-railway-db-runtime-secrets.py`:
- Around line 54-56: When FORBIDDEN_SECRET_FRAGMENTS_FILE is set but unreadable,
the current Path(fragment_file).read_text call will raise a raw traceback; wrap
the read in a controlled check: verify Path(fragment_file).exists() and
is_file() (or wrap read_text in try/except), and on any failure call pytest.fail
with a clear regression-check message that includes the fragment_file path;
update the fragment_file/fragments handling so fragments.extend(...) only runs
after the existence/read succeeds and any exceptions are caught and converted to
pytest.fail.

---

Nitpick comments:
In `@tests/check-railway-db-runtime-secrets.py`:
- Around line 94-106: The current tests iterate DEV_CONFIG_ENV_VARS and
COMPONENT_PASSWORD_ENV and use exact string checks (e.g.
require(f"getenv('{name}')" in config) and require(f"'password' =>
getenv('{env_var}')" in block)) which break on harmless PHP formatting
differences; update the assertions in the loop that references
DEV_CONFIG_ENV_VARS, COMPONENT_PASSWORD_ENV and component_block() to use
case-sensitive regex matching that tolerates single or double quotes, optional
whitespace around => and parentheses, and optional spaces after getenv (e.g.
pattern like r"getenv\(\s*['\"]{name}['\"]\s*\)" and
r"['\"]password['\"]\s*=>\s*getenv\(\s*['\"]{env_var}['\"]\s*\)"), and replace
the existing literal "in" checks with a regex search that preserves the same
failure messages.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 2450e02f-c82b-4deb-8d11-5b75e059dde0

📥 Commits

Reviewing files that changed from the base of the PR and between e2a3e4e and 8a9b1cc.

📒 Files selected for processing (7)
  • docs/railway-db-runtime-secrets.md
  • environments/dev-server-railway/common/config/main-local.php
  • environments/dev-server-railway/deployments/july_2025/29_july_2025_deployment.sh
  • environments/dev-server-railway/deployments/july_2025/3_july_2025_deployment.sh
  • environments/prod-railway/deployments/july_2025/29_july_2025_deployment.sh
  • environments/prod-railway/deployments/july_2025/3_july_2025_deployment.sh
  • tests/check-railway-db-runtime-secrets.py
✅ Files skipped from review due to trivial changes (1)
  • docs/railway-db-runtime-secrets.md
🚧 Files skipped from review as they are similar to previous changes (5)
  • environments/prod-railway/deployments/july_2025/3_july_2025_deployment.sh
  • environments/dev-server-railway/common/config/main-local.php
  • environments/dev-server-railway/deployments/july_2025/3_july_2025_deployment.sh
  • environments/dev-server-railway/deployments/july_2025/29_july_2025_deployment.sh
  • environments/prod-railway/deployments/july_2025/29_july_2025_deployment.sh

Comment thread tests/check-railway-db-runtime-secrets.py Outdated
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant