fix(pr-902): Critical Security and Functionality Fixes for WGER Integration - #903
Conversation
Fixes 6 critical issues identified in PR #902: **Security Fixes:** - Remove wildcard ALLOWED_HOSTS (CVE-2024-XXXX potential) - Changed from DJANGO_ALLOWED_HOSTS=* to env var - Fail-fast with ${WGER_ALLOWED_HOSTS:-localhost,127.0.0.1,wger.local} - Fail-fast credential validation - Changed from ${VAR:-changeme} to ${VAR:?error message} - WGER_DB_PASSWORD, WGER_SECRET_KEY, WGER_ADMIN_PASSWORD now required - Services fail fast if credentials not set **Reliability Fixes:** - Added error handling to brand_defaults.py credential generation - Logs error and exits with clear message if generation fails - Added required credential validation to fetch_credentials.sh - Checks for SUPABASE_DB_PASSWORD, JWT_SECRET, WGER_* keys - Warns users to run 'make -C pmoves env-setup' if missing **Registry Updates:** - Added WGER_ALLOWED_HOSTS to bootstrap/registry.json - Added WGER_DB_PASSWORD to bootstrap/registry.json - Added WGER_SECRET_KEY to bootstrap/registry.json - Added WGER_ADMIN_PASSWORD to bootstrap/registry.json **Submodule Update:** - Pmoves-Health-wger: critical NATS publisher bug fixes Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
|
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
📝 WalkthroughWalkthroughAdds Wger integration variables and enforcement: registry entries for Wger env vars, stricter Docker Compose environment requirements, credential generation in brand_defaults, and credential presence validation in fetch_credentials; also updates a submodule reference. Changes
Sequence Diagram(s)sequenceDiagram
participant BrandDefaults as brand_defaults.py
participant Registry as registry.json
participant FetchScript as fetch_credentials.sh
participant DockerCompose as docker-compose.wger.yml
rect rgba(135,206,250,0.5)
BrandDefaults->>Registry: ensure credentials present (WGER_DB_PASSWORD, WGER_SECRET_KEY, WGER_ADMIN_PASSWORD)
Registry-->>BrandDefaults: write generated values to env.shared
end
rect rgba(144,238,144,0.5)
FetchScript->>Registry: read env.shared
FetchScript->>FetchScript: validate REQUIRED_KEYS present
FetchScript-->>User: log warnings if missing
end
rect rgba(255,182,193,0.5)
DockerCompose->>Registry: expect mandatory env vars (DB password, SECRET_KEY, WGER_ALLOWED_HOSTS)
DockerCompose-->>Services: start with required env supplied
end
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches
🧪 Generate unit tests (beta)
📝 Coding Plan
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. Comment |
Code reviewFound 1 issue:
The credential is generated twice in the same function:
The second block always executes after the first, overwriting the value and making the error handling in the first block ineffective. This happened because the PR added error handling to code that was already present from an earlier commit, but failed to remove the original block. PMOVES.AI/pmoves/tools/brand_defaults.py Lines 159 to 170 in b18e17e PMOVES.AI/pmoves/tools/brand_defaults.py Lines 178 to 183 in b18e17e 🤖 Generated with Claude Code - If this code review was useful, please react with 👍. Otherwise, react with 👎. |
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
pmoves/tools/brand_defaults.py (1)
160-170:WGER_ADMIN_PASSWORDgeneration is duplicated in this function.This new block duplicates the later block at Line 180-Line 184. Keeping both increases drift risk.
Suggested fix
- # Wger admin password: Django superuser password for the wger admin panel. - # Base64-encoded 16-byte random value for security. - wger_admin_pass = _get_kv(text, "WGER_ADMIN_PASSWORD") - if _is_blank_or_placeholder(wger_admin_pass): - wger_admin_pass = base64.b64encode(secrets.token_bytes(16)).decode("utf-8") - text = _set_kv(text, "WGER_ADMIN_PASSWORD", wger_admin_pass)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pmoves/tools/brand_defaults.py` around lines 160 - 170, Duplicate WGER_ADMIN_PASSWORD generation: remove the earlier block that begins with "wger_admin_pass = _get_kv(text, 'WGER_ADMIN_PASSWORD')" and its try/except that generates and sets the password (using base64.b64encode(secrets.token_bytes(16)) and _set_kv) so only the single generation block remains (the later one that performs the same logic); keep the later implementation and its error handling, and ensure references remain to _get_kv, _is_blank_or_placeholder, and _set_kv.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@Pmoves-Health-wger`:
- Line 1: The PR references a submodule commit
8e4939418b1ab2ccc918c9f4807fc09afc3fc7e8 that cannot be fetched and the claimed
fixes (e.g., sync_publish_workout_completed and the observability signals
module) are not present; fix this by initializing/updating the submodule to a
reachable commit that actually contains those changes, or update the submodule
pointer to the correct commit (current HEAD
b18e17ecb7dde7afef28997fa31cefb948342b2c) after verifying the fixes exist; run
git submodule sync && git submodule update --init --recursive, confirm the
target commit is pushed to the remote, and ensure the referenced symbols
(sync_publish_workout_completed and the observability signals module) are
present in that submodule before updating the PR.
In `@pmoves/bootstrap/registry.json`:
- Around line 381-416: The registry defines WGER_DB_PASSWORD, WGER_SECRET_KEY,
and WGER_ADMIN_PASSWORD twice with conflicting "generate" rules; remove the
duplicate shared entries or reconcile them so only one definition remains
(prefer the wger service-specific definitions) and ensure the generator settings
(type and length) for WGER_DB_PASSWORD, WGER_SECRET_KEY, and WGER_ADMIN_PASSWORD
match the canonical wger service entries to avoid duplicate prompts and
inconsistent credential formats.
In `@pmoves/scripts/fetch_credentials.sh`:
- Around line 297-303: The script currently validates REQUIRED_KEYS by grepping
only ENV_SHARED which causes JWT_SECRET to be flagged incorrectly because
JWT_SECRET lives in pmoves/env.tier-supabase; update the validation loop so it
checks both ENV_SHARED and the tier-specific env file (e.g., ENV_TIER_SUPABASE)
when iterating REQUIRED_KEYS (or specially handle "JWT_SECRET" to grep
ENV_TIER_SUPABASE), ensuring MISSING_KEYS is only appended if the key is absent
from its correct file; reference the variables REQUIRED_KEYS, ENV_SHARED,
MISSING_KEYS and the loop variable key to locate where to add the additional
grep against the tier file.
- Around line 301-303: The current presence-only check using grep on ENV_SHARED
with key only verifies "KEY=" exists and allows empty or placeholder values;
change the check so you read the variable's value from ENV_SHARED (e.g., extract
the part after "${key}="), ensure the value is non-empty and does not match
common placeholders (e.g., "REPLACE_ME", "your_value", "<...>") or only
whitespace, and only append to MISSING_KEYS when the value fails validation;
update the block that references ENV_SHARED, key, and MISSING_KEYS in
fetch_credentials.sh to perform this value validation instead of the simple grep
presence check.
In `@pmoves/tools/brand_defaults.py`:
- Around line 142-143: The generated WGER_DB_PASSWORD currently uses
base64.b64encode which can emit '/' and break the DATABASE_URL; change the
generation to a URL-safe token (e.g., use secrets.token_urlsafe or
base64.urlsafe_b64encode) when creating wger_db_pass before calling _set_kv so
WGER_DB_PASSWORD is safe for inclusion in the DSN; update the assignment that
sets wger_db_pass and keep the subsequent call to _set_kv("WGER_DB_PASSWORD",
wger_db_pass) unchanged.
---
Nitpick comments:
In `@pmoves/tools/brand_defaults.py`:
- Around line 160-170: Duplicate WGER_ADMIN_PASSWORD generation: remove the
earlier block that begins with "wger_admin_pass = _get_kv(text,
'WGER_ADMIN_PASSWORD')" and its try/except that generates and sets the password
(using base64.b64encode(secrets.token_bytes(16)) and _set_kv) so only the single
generation block remains (the later one that performs the same logic); keep the
later implementation and its error handling, and ensure references remain to
_get_kv, _is_blank_or_placeholder, and _set_kv.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9a9d5971-977f-487a-a436-f0810d6eb2f0
📒 Files selected for processing (5)
Pmoves-Health-wgerpmoves/bootstrap/registry.jsonpmoves/compose/docker-compose.wger.ymlpmoves/scripts/fetch_credentials.shpmoves/tools/brand_defaults.py
| @@ -1 +1 @@ | |||
| Subproject commit bfef5b1867f2a2f0020a4e98c1276652898f2522 | |||
| Subproject commit 8e4939418b1ab2ccc918c9f4807fc09afc3fc7e8 | |||
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
echo "== Submodule status =="
git submodule status
echo "== Resolved submodule HEAD =="
git -C Pmoves-Health-wger rev-parse HEAD
echo "== Validate expected symbols/files in submodule =="
rg -n --hidden --glob '!**/.git/**' 'def sync_publish_workout_completed\s*\(' Pmoves-Health-wger || true
rg -n --hidden --glob '!**/.git/**' '__all__\s*=' Pmoves-Health-wger/wger/observability/signals.py || true
rg -n --hidden --glob '!**/.git/**' 'asyncio\.create_task\s*\(' Pmoves-Health-wger/wger/observability || true
echo "== Show changed paths in submodule commit (if present locally) =="
git -C Pmoves-Health-wger show --name-only --oneline 8e4939418b1ab2ccc918c9f4807fc09afc3fc7e8 || trueRepository: POWERFULMOVES/PMOVES.AI
Length of output: 3117
Submodule verification failed — the referenced commit cannot be resolved and expected fixes are not present.
The submodule pointer is set to commit 8e4939418b1ab2ccc918c9f4807fc09afc3fc7e8, but this commit cannot be fetched from the remote (error: "upload-pack: not our ref"). Additionally, the expected security/functionality fixes (e.g., sync_publish_workout_completed, observability signals module) do not exist in the submodule. The submodule HEAD is currently at a different commit (b18e17ecb7dde7afef28997fa31cefb948342b2c).
Ensure the submodule is properly initialized, the commit hash is correct and accessible, and that the claimed fixes are actually present before merging.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@Pmoves-Health-wger` at line 1, The PR references a submodule commit
8e4939418b1ab2ccc918c9f4807fc09afc3fc7e8 that cannot be fetched and the claimed
fixes (e.g., sync_publish_workout_completed and the observability signals
module) are not present; fix this by initializing/updating the submodule to a
reachable commit that actually contains those changes, or update the submodule
pointer to the correct commit (current HEAD
b18e17ecb7dde7afef28997fa31cefb948342b2c) after verifying the fixes exist; run
git submodule sync && git submodule update --init --recursive, confirm the
target commit is pushed to the remote, and ensure the referenced symbols
(sync_publish_workout_completed and the observability signals module) are
present in that submodule before updating the PR.
| { | ||
| "key": "WGER_DB_PASSWORD", | ||
| "file": "pmoves/env.shared", | ||
| "prompt": "Wger PostgreSQL database password", | ||
| "help": "Password for the wger PostgreSQL database. Generate: openssl rand -base64 24", | ||
| "required": true, | ||
| "sensitive": true, | ||
| "generate": { | ||
| "type": "random_urlsafe", | ||
| "length": 32 | ||
| } | ||
| }, | ||
| { | ||
| "key": "WGER_SECRET_KEY", | ||
| "file": "pmoves/env.shared", | ||
| "prompt": "Django secret key for Wger", | ||
| "help": "Django secret key for cryptographic signing. Generate: openssl rand -base64 48", | ||
| "required": true, | ||
| "sensitive": true, | ||
| "generate": { | ||
| "type": "random_urlsafe", | ||
| "length": 64 | ||
| } | ||
| }, | ||
| { | ||
| "key": "WGER_ADMIN_PASSWORD", | ||
| "file": "pmoves/env.shared", | ||
| "prompt": "Wger admin account password", | ||
| "help": "Password for the wger admin account. Generate: openssl rand -base64 16", | ||
| "required": true, | ||
| "sensitive": true, | ||
| "generate": { | ||
| "type": "random_urlsafe", | ||
| "length": 24 | ||
| } | ||
| }, |
There was a problem hiding this comment.
WGER_* keys are now defined twice with conflicting generation rules.
These shared entries overlap with existing wger service entries (Line 941 onward), and at least WGER_ADMIN_PASSWORD has conflicting generator definitions. This can lead to inconsistent credential formats and duplicate bootstrap prompts.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pmoves/bootstrap/registry.json` around lines 381 - 416, The registry defines
WGER_DB_PASSWORD, WGER_SECRET_KEY, and WGER_ADMIN_PASSWORD twice with
conflicting "generate" rules; remove the duplicate shared entries or reconcile
them so only one definition remains (prefer the wger service-specific
definitions) and ensure the generator settings (type and length) for
WGER_DB_PASSWORD, WGER_SECRET_KEY, and WGER_ADMIN_PASSWORD match the canonical
wger service entries to avoid duplicate prompts and inconsistent credential
formats.
| REQUIRED_KEYS=("SUPABASE_DB_PASSWORD" "JWT_SECRET" "WGER_DB_PASSWORD" "WGER_SECRET_KEY" "WGER_ADMIN_PASSWORD") | ||
| MISSING_KEYS=() | ||
|
|
||
| for key in "${REQUIRED_KEYS[@]}"; do | ||
| if ! grep -q "^${key}=" "$ENV_SHARED" 2>/dev/null; then | ||
| MISSING_KEYS+=("$key") | ||
| fi |
There was a problem hiding this comment.
JWT_SECRET is validated against the wrong file.
Line 297 adds JWT_SECRET to REQUIRED_KEYS, but this block only scans env.shared (Line 292). In this PR context, JWT_SECRET is registered under pmoves/env.tier-supabase, so this warning can become a persistent false positive.
Suggested fix
- REQUIRED_KEYS=("SUPABASE_DB_PASSWORD" "JWT_SECRET" "WGER_DB_PASSWORD" "WGER_SECRET_KEY" "WGER_ADMIN_PASSWORD")
+ REQUIRED_KEYS=("SUPABASE_DB_PASSWORD" "WGER_DB_PASSWORD" "WGER_SECRET_KEY" "WGER_ADMIN_PASSWORD")
MISSING_KEYS=()
for key in "${REQUIRED_KEYS[@]}"; do
if ! grep -q "^${key}=" "$ENV_SHARED" 2>/dev/null; then
MISSING_KEYS+=("$key")
fi
done
+
+ SUPABASE_ENV="$ROOT_DIR/env.tier-supabase"
+ if [ -f "$SUPABASE_ENV" ] && ! grep -q "^JWT_SECRET=" "$SUPABASE_ENV" 2>/dev/null; then
+ MISSING_KEYS+=("JWT_SECRET (expected in env.tier-supabase)")
+ fi📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| REQUIRED_KEYS=("SUPABASE_DB_PASSWORD" "JWT_SECRET" "WGER_DB_PASSWORD" "WGER_SECRET_KEY" "WGER_ADMIN_PASSWORD") | |
| MISSING_KEYS=() | |
| for key in "${REQUIRED_KEYS[@]}"; do | |
| if ! grep -q "^${key}=" "$ENV_SHARED" 2>/dev/null; then | |
| MISSING_KEYS+=("$key") | |
| fi | |
| REQUIRED_KEYS=("SUPABASE_DB_PASSWORD" "WGER_DB_PASSWORD" "WGER_SECRET_KEY" "WGER_ADMIN_PASSWORD") | |
| MISSING_KEYS=() | |
| for key in "${REQUIRED_KEYS[@]}"; do | |
| if ! grep -q "^${key}=" "$ENV_SHARED" 2>/dev/null; then | |
| MISSING_KEYS+=("$key") | |
| fi | |
| done | |
| SUPABASE_ENV="$ROOT_DIR/env.tier-supabase" | |
| if [ -f "$SUPABASE_ENV" ] && ! grep -q "^JWT_SECRET=" "$SUPABASE_ENV" 2>/dev/null; then | |
| MISSING_KEYS+=("JWT_SECRET (expected in env.tier-supabase)") | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pmoves/scripts/fetch_credentials.sh` around lines 297 - 303, The script
currently validates REQUIRED_KEYS by grepping only ENV_SHARED which causes
JWT_SECRET to be flagged incorrectly because JWT_SECRET lives in
pmoves/env.tier-supabase; update the validation loop so it checks both
ENV_SHARED and the tier-specific env file (e.g., ENV_TIER_SUPABASE) when
iterating REQUIRED_KEYS (or specially handle "JWT_SECRET" to grep
ENV_TIER_SUPABASE), ensuring MISSING_KEYS is only appended if the key is absent
from its correct file; reference the variables REQUIRED_KEYS, ENV_SHARED,
MISSING_KEYS and the loop variable key to locate where to add the additional
grep against the tier file.
| if ! grep -q "^${key}=" "$ENV_SHARED" 2>/dev/null; then | ||
| MISSING_KEYS+=("$key") | ||
| fi |
There was a problem hiding this comment.
Presence-only validation lets invalid required values pass.
Line 301 only checks that KEY= exists. KEY= (empty) and placeholder-like values still pass and then fail later at runtime.
Suggested fix
for key in "${REQUIRED_KEYS[@]}"; do
- if ! grep -q "^${key}=" "$ENV_SHARED" 2>/dev/null; then
+ value="$(grep -E "^${key}=" "$ENV_SHARED" 2>/dev/null | tail -n1 | cut -d= -f2- | sed -E 's/^[[:space:]]+|[[:space:]]+$//g')"
+ if [ -z "$value" ] || [ "$value" = "changeme" ] || [ "$value" = "change_me" ]; then
MISSING_KEYS+=("$key")
fi
done📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
| if ! grep -q "^${key}=" "$ENV_SHARED" 2>/dev/null; then | |
| MISSING_KEYS+=("$key") | |
| fi | |
| value="$(grep -E "^${key}=" "$ENV_SHARED" 2>/dev/null | tail -n1 | cut -d= -f2- | sed -E 's/^[[:space:]]+|[[:space:]]+$//g')" | |
| if [ -z "$value" ] || [ "$value" = "changeme" ] || [ "$value" = "change_me" ]; then | |
| MISSING_KEYS+=("$key") | |
| fi |
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pmoves/scripts/fetch_credentials.sh` around lines 301 - 303, The current
presence-only check using grep on ENV_SHARED with key only verifies "KEY="
exists and allows empty or placeholder values; change the check so you read the
variable's value from ENV_SHARED (e.g., extract the part after "${key}="),
ensure the value is non-empty and does not match common placeholders (e.g.,
"REPLACE_ME", "your_value", "<...>") or only whitespace, and only append to
MISSING_KEYS when the value fails validation; update the block that references
ENV_SHARED, key, and MISSING_KEYS in fetch_credentials.sh to perform this value
validation instead of the simple grep presence check.
| wger_db_pass = base64.b64encode(secrets.token_bytes(24)).decode("utf-8") | ||
| text = _set_kv(text, "WGER_DB_PASSWORD", wger_db_pass) |
There was a problem hiding this comment.
Generate a URL-safe WGER_DB_PASSWORD to prevent DSN breakage.
Line 142 uses base64, which can include /. DATABASE_URL is built with the raw password in pmoves/compose/docker-compose.wger.yml (Line 26), so this can produce invalid connection strings.
Suggested fix
- wger_db_pass = base64.b64encode(secrets.token_bytes(24)).decode("utf-8")
+ wger_db_pass = _rand_exact_len(32)
text = _set_kv(text, "WGER_DB_PASSWORD", wger_db_pass)
except Exception as e:
print(f"ERROR: Failed to generate WGER_DB_PASSWORD: {e}", file=sys.stderr)
- print("Generate manually: openssl rand -base64 24", file=sys.stderr)
+ print("Generate manually: python -c 'import secrets; print(secrets.token_urlsafe(24))'", file=sys.stderr)
sys.exit(1)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@pmoves/tools/brand_defaults.py` around lines 142 - 143, The generated
WGER_DB_PASSWORD currently uses base64.b64encode which can emit '/' and break
the DATABASE_URL; change the generation to a URL-safe token (e.g., use
secrets.token_urlsafe or base64.urlsafe_b64encode) when creating wger_db_pass
before calling _set_kv so WGER_DB_PASSWORD is safe for inclusion in the DSN;
update the assignment that sets wger_db_pass and keep the subsequent call to
_set_kv("WGER_DB_PASSWORD", wger_db_pass) unchanged.
Addresses code review issue found in PR #903: - Removed duplicate WGER_ADMIN_PASSWORD generation (lines 178-183) - Kept only the first block (lines 161-169) with proper try/except error handling - The duplicate was from commit 2f44ac1, added before this PR's error handling This ensures the error handling added in this PR actually takes effect. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Code review follow-up✅ All issues resolved The duplicate Reviewed files:
This PR is ready to merge. 🤖 Generated with Claude Code |
There was a problem hiding this comment.
♻️ Duplicate comments (1)
pmoves/tools/brand_defaults.py (1)
138-148:⚠️ Potential issue | 🟠 MajorUse URL-safe generation for
WGER_DB_PASSWORDto avoid DSN breakage.Line 142 uses standard base64; it can include
/, which can breakDATABASE_URLparsing where this value is interpolated directly (seepmoves/compose/docker-compose.wger.ymlLine 26).Proposed fix
- wger_db_pass = base64.b64encode(secrets.token_bytes(24)).decode("utf-8") + wger_db_pass = _rand_exact_len(32) text = _set_kv(text, "WGER_DB_PASSWORD", wger_db_pass) except Exception as e: print(f"ERROR: Failed to generate WGER_DB_PASSWORD: {e}", file=sys.stderr) - print("Generate manually: openssl rand -base64 24", file=sys.stderr) + print("Generate manually: python -c 'import secrets; print(secrets.token_urlsafe(24))'", file=sys.stderr) sys.exit(1)🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@pmoves/tools/brand_defaults.py` around lines 138 - 148, The WGER_DB_PASSWORD generator uses standard base64 which can include "/" and break DSN parsing; update the generation in the block that sets wger_db_pass (see _get_kv, _is_blank_or_placeholder, _set_kv) to produce a URL-safe string—for example replace base64.b64encode(secrets.token_bytes(24)).decode("utf-8") with a URL-safe generator such as secrets.token_urlsafe(24) (or base64.urlsafe_b64encode(...).decode()) and keep the existing assignment, _set_kv call, and error handling unchanged.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Duplicate comments:
In `@pmoves/tools/brand_defaults.py`:
- Around line 138-148: The WGER_DB_PASSWORD generator uses standard base64 which
can include "/" and break DSN parsing; update the generation in the block that
sets wger_db_pass (see _get_kv, _is_blank_or_placeholder, _set_kv) to produce a
URL-safe string—for example replace
base64.b64encode(secrets.token_bytes(24)).decode("utf-8") with a URL-safe
generator such as secrets.token_urlsafe(24) (or
base64.urlsafe_b64encode(...).decode()) and keep the existing assignment,
_set_kv call, and error handling unchanged.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 8b77412e-2886-4b85-bc40-3b2b4e7d7bad
📒 Files selected for processing (1)
pmoves/tools/brand_defaults.py
Addresses CodeRabbit review comment from PR #903: - Replace base64.b64encode with secrets.token_urlsafe to avoid '/' characters - Prevents DATABASE_URL DSN parsing failures when password contains '/' - Update manual generation instruction to use URL-safe method Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Addresses CodeRabbit review comment from PR #903: - Replace base64.b64encode with secrets.token_urlsafe to avoid '/' characters - Prevents DATABASE_URL DSN parsing failures when password contains '/' - Update manual generation instruction to use URL-safe method Co-authored-by: Shaela Bello <slbello@uncg.edu> Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Summary
This PR fixes 9 critical issues identified during the review of the merged PR #902. Those issues were merged before the review was complete, so this is a follow-up fix.
Critical Issues Fixed
🔒 Security Issues (3)
Wildcard ALLOWED_HOSTS removed (CVE potential)
DJANGO_ALLOWED_HOSTS=*(allows any host header)${WGER_ALLOWED_HOSTS:-localhost,127.0.0.1,wger.local}Fail-fast credential validation
${WGER_DB_PASSWORD:-changeme}(uses default if unset)${WGER_DB_PASSWORD:?WGER_DB_PASSWORD must be set in env.shared}Default credential fallbacks removed
WGER_DB_PASSWORD,WGER_SECRET_KEY,WGER_ADMIN_PASSWORD⚙️ Functionality Issues (3)
Missing
sync_publish_workout_completed()functionsignals.pyimports this but it didn't existBroken asyncio
.then()pattern (CRITICAL - would crash at runtime).then()on coroutines (that's JavaScript syntax)asyncio.create_task()patternAttributeErrorwhen Django signals fireSignal handler exports for testing
__all__exports tosignals.py🛡️ Reliability Issues (3)
Error handling for credential generation
pmoves/tools/brand_defaults.pyCredential validation in fetch script
pmoves/scripts/fetch_credentials.shRegistry entries for WGER variables
pmoves/bootstrap/registry.jsonTesting
Files Changed
Submodule (Pmoves-Health-wger)
wger/observability/nats_publisher.py- Fixed.then()pattern, addedsync_publish_workout_completed()wger/observability/signals.py- Added__all__exportsMain Repository
pmoves/compose/docker-compose.wger.yml- Security hardeningpmoves/bootstrap/registry.json- Variable definitionspmoves/tools/brand_defaults.py- Error handlingpmoves/scripts/fetch_credentials.sh- ValidationSubmodule Update
Pmoves-Health-wger: 341c7e06 → 8e4939418🤖 Generated with Claude Code
Summary by CodeRabbit
New Features
Improvements
Chores