Skip to content

fix: npx pre-flight, JSON parse safety, wave redirect reason#68

Merged
chitcommit merged 1 commit intomainfrom
fix/review-remediation-2
Mar 26, 2026
Merged

fix: npx pre-flight, JSON parse safety, wave redirect reason#68
chitcommit merged 1 commit intomainfrom
fix/review-remediation-2

Conversation

@chitcommit
Copy link
Copy Markdown
Contributor

@chitcommit chitcommit commented Mar 26, 2026

Summary

  • rotate-db-secret.py: Verify npx is on PATH before rotating the Neon password to prevent partial failure (password rotated but can't deploy to Workers = production outage)
  • rotate-db-secret.py: Catch json.JSONDecodeError on non-JSON responses from 1Password Connect and Neon API (e.g., HTML error pages with 200 status)
  • wave.ts: Add reason=callback_failed to catch block redirect, matching google.ts pattern

Context

Follow-up to PR #67 (review remediation). These three findings from the silent-failure-hunter review agent arrived after PR #67 auto-merged.

Test plan

  • python3 scripts/rotate-db-secret.py --help works without env vars
  • Script aborts cleanly if npx not on PATH
  • Wave OAuth callback error redirect includes reason parameter

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Bug Fixes
    • Database secret rotation now validates that required command-line tools are available before execution and includes improved error reporting when API responses fail to parse or are invalid
    • Wave OAuth callback error handling now includes specific failure context in redirect parameters, providing better diagnostic information when integration issues occur

- rotate-db-secret.py: verify npx is on PATH before rotating password
  to prevent partial failure (rotated password but can't deploy)
- rotate-db-secret.py: catch json.JSONDecodeError on non-JSON API
  responses from 1Password Connect and Neon
- wave.ts: add reason=callback_failed to catch block redirect
  (matching google.ts pattern)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Copilot AI review requested due to automatic review settings March 26, 2026 02:13
@chitcommit chitcommit enabled auto-merge (squash) March 26, 2026 02:13
@chatgpt-codex-connector
Copy link
Copy Markdown

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@github-actions
Copy link
Copy Markdown
Contributor

@coderabbitai review

Please evaluate:

  • Security implications
  • Credential exposure risk
  • Dependency supply chain concerns
  • Breaking API changes

@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai bot commented Mar 26, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: d0248279-3219-4e4f-9e2e-4e71731c5031

📥 Commits

Reviewing files that changed from the base of the PR and between 4288dc4 and b35a90b.

📒 Files selected for processing (2)
  • scripts/rotate-db-secret.py
  • server/routes/wave.ts

📝 Walkthrough

Walkthrough

Added defensive checks to the database secret rotation script—validating npx availability and improving JSON response error handling—and enhanced the Wave OAuth error callback redirect with a diagnostic reason parameter.

Changes

Cohort / File(s) Summary
Database Rotation Script Hardening
scripts/rotate-db-secret.py
Added preflight check for npx availability using shutil.which(), and improved error handling in op_get() and neon_post() with explicit JSON decode validation and truncated error reporting to stderr.
OAuth Error Reporting
server/routes/wave.ts
Enhanced Wave OAuth callback error redirect to include reason=callback_failed query parameter for better diagnostic context.

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~12 minutes

Possibly related PRs

Poem

🐰 A preflight check before we leap,
And JSON dreams no longer weep,
With npx found and errors clear,
The database secrets stay sincere! 🔐

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/review-remediation-2

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.

@cloudflare-workers-and-pages
Copy link
Copy Markdown

Deploying with  Cloudflare Workers  Cloudflare Workers

The latest updates on your project. Learn more about integrating Git with Workers.

Status Name Latest Commit Updated (UTC)
✅ Deployment successful!
View logs
chittyfinance b35a90b Mar 26 2026, 02:14 AM

@chitcommit chitcommit merged commit b97561b into main Mar 26, 2026
12 of 13 checks passed
@chitcommit chitcommit deleted the fix/review-remediation-2 branch March 26, 2026 02:15
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Hardens the DB secret rotation script against partial failures and malformed API responses, and aligns Wave OAuth error redirects with the existing Google callback pattern.

Changes:

  • Add an npx PATH pre-flight check to abort before rotating the Neon password if deployment tooling isn’t available.
  • Add JSONDecodeError handling for 1Password Connect and Neon API responses to fail fast on non-JSON bodies.
  • Add reason=callback_failed to Wave OAuth callback error redirects.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 3 comments.

File Description
scripts/rotate-db-secret.py Adds npx pre-flight and safer JSON parsing error handling for external API calls.
server/routes/wave.ts Adds a consistent reason query parameter on callback failure redirects.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment on lines +58 to +63
body = r.read()
try:
return json.loads(body)
except json.JSONDecodeError:
print(f"ERROR: 1Password Connect returned non-JSON: {body[:200]}", file=sys.stderr)
sys.exit(1)
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

In the JSONDecodeError path, body is bytes and the error message prints body[:200] directly, which ends up as a b'...' repr and may include non-printable characters. For consistency with the HTTPError branch (which decodes with errors="replace") and to keep logs readable/safe, decode/sanitize the snippet (and consider including response status/content-type instead of dumping raw bytes).

Copilot uses AI. Check for mistakes.
Comment on lines +85 to +90
body = r.read()
try:
return json.loads(body)
except json.JSONDecodeError:
print(f"ERROR: Neon API returned non-JSON: {body[:200]}", file=sys.stderr)
sys.exit(1)
Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

Same as op_get(): this JSONDecodeError branch prints a raw bytes slice in the error message. Decode/sanitize the snippet (e.g., utf-8 with errors="replace") to keep output readable and avoid logging arbitrary bytes.

Copilot uses AI. Check for mistakes.
Comment on lines +157 to +163
# Pre-flight: verify npx/wrangler available BEFORE rotating the password.
# If wrangler is missing, rotating would leave a new password that can't be deployed.
if not shutil.which("npx"):
print("ERROR: npx not found on PATH. Cannot deploy secrets to Cloudflare Workers.", file=sys.stderr)
print("ABORTING before password rotation to avoid partial failure.", file=sys.stderr)
sys.exit(1)

Copy link

Copilot AI Mar 26, 2026

Choose a reason for hiding this comment

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

The pre-flight comment says to verify "npx/wrangler" availability, but the code only checks npx is on PATH. Either adjust the comment to match what’s actually being validated, or extend the pre-flight to also validate that npx wrangler can run (e.g., npx wrangler --version with a short timeout) before rotating the password.

Suggested change
# Pre-flight: verify npx/wrangler available BEFORE rotating the password.
# If wrangler is missing, rotating would leave a new password that can't be deployed.
if not shutil.which("npx"):
print("ERROR: npx not found on PATH. Cannot deploy secrets to Cloudflare Workers.", file=sys.stderr)
print("ABORTING before password rotation to avoid partial failure.", file=sys.stderr)
sys.exit(1)
# Pre-flight: verify npx and wrangler are available BEFORE rotating the password.
# If wrangler is missing, rotating would leave a new password that can't be deployed.
if not shutil.which("npx"):
print("ERROR: npx not found on PATH. Cannot deploy secrets to Cloudflare Workers.", file=sys.stderr)
print("ABORTING before password rotation to avoid partial failure.", file=sys.stderr)
sys.exit(1)
try:
# Ensure that `npx wrangler` is runnable before proceeding.
subprocess.run(
["npx", "wrangler", "--version"],
stdout=subprocess.DEVNULL,
stderr=subprocess.DEVNULL,
check=True,
timeout=10,
)
except (subprocess.CalledProcessError, subprocess.TimeoutExpired, FileNotFoundError):
print("ERROR: 'npx wrangler' is not available or failed to run. Cannot deploy secrets to Cloudflare Workers.", file=sys.stderr)
print("ABORTING before password rotation to avoid partial failure.", file=sys.stderr)
sys.exit(1)

Copilot uses AI. Check for mistakes.
@claude
Copy link
Copy Markdown

claude bot commented Mar 26, 2026

Code Review — PR #68

Overall: LGTM with two minor notes. These are solid defensive hardening fixes. The partial-failure guard for npx is exactly the right approach — rotating the password without being able to deploy it is a scary outage scenario.


scripts/rotate-db-secret.py

npx pre-flight check

  • Correct placement: runs before password rotation, after arg parsing — matches the test plan assertion that --help still works.
  • Clear error messages explain why it is aborting.
  • Minor suggestion: shutil.which("npx") confirms npx is on PATH, but wrangler could still be missing (e.g., npx exists but the package is not installed). A stronger check would run npx wrangler --version and verify exit code 0. That said, it catches the most common CI failure mode and is acceptable as-is.

JSON parse safety

  • Consistent pattern applied to both op_get and neon_post — good symmetry.
  • Minor: body[:200] in the error print renders as Python bytes repr (b'...') rather than a readable string. The HTTPError handler below it already calls .decode("utf-8", errors="replace") — worth applying the same here for consistency. Not a bug, just cosmetic.

server/routes/wave.ts

reason=callback_failed in error redirect

  • Correct pattern match with google.ts.
  • Value is generic enough that it does not leak internal state to the client.
  • The actual error detail is already captured server-side by console.error.

No security concerns introduced. No breaking changes. Cloudflare deploy succeeded per CI.

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.

2 participants