Skip to content

Claude/cpu guard script dn d8u - #125

Merged
gamblecodezcom merged 12 commits into
mainfrom
claude/cpu-guard-script-DnD8u
Mar 3, 2026
Merged

Claude/cpu guard script dn d8u#125
gamblecodezcom merged 12 commits into
mainfrom
claude/cpu-guard-script-DnD8u

Conversation

@gamblecodezcom

@gamblecodezcom gamblecodezcom commented Mar 3, 2026

Copy link
Copy Markdown
Owner

User description

Summary by Sourcery

Improve robustness and safety of backend process management, logging, and webhook handling, plus adjust CPU guard whitelisting.

Bug Fixes:

  • Ensure autofix webhook fails fast with a clear error when rawBody is missing or misconfigured instead of proceeding with an invalid payload.
  • Prevent backend logging from failing when streams are destroyed or unwritable by falling back safely to console output.

Enhancements:

  • Fallback backend endpoint logs to /tmp when the configured log directory is not writable.
  • Tighten backend restart logic by targeting pkill to the project-specific backend.js path and re-checking/freeing the endpoint port before nohup fallback restarts.
  • Extend the CPU guard whitelist to protect the gcz_cpu_guard monitoring script from termination.

CodeAnt-AI Description

Improve backend reliability: safer logging, strict webhook validation, cleaner restart behavior, and CPU-guard protections

What Changed

  • Backend logging now avoids writing to destroyed or unwritable streams; log write errors are caught and messages fall back to console so the server doesn't crash when log files fail.
  • Autofix webhook now rejects requests if the original raw request body is missing or not a buffer, returns a 500 error, and logs a clear error instead of proceeding with an invalid payload.
  • Startup script falls back to /tmp for endpoint logs when the configured log directory is not writable, clears any process holding the endpoint port before restarting, and re-checks/frees the port before launching a nohup fallback; pkill now targets the project path to avoid killing unrelated Node processes.
  • Service unit pre-start runs with root escalation and attempts graceful termination (SIGTERM then SIGKILL) of any process holding the endpoint port to prevent immediate crash-restart loops.
  • CPU-guard whitelist extended to protect sibling monitoring scripts (gcz_cpu_guard) from being terminated.

Impact

✅ Clearer webhook failure errors
✅ Fewer endpoint crash-restart loops
✅ Fewer lost or fatal log-write failures

💡 Usage Guide

Checking Your Pull Request

Every time you make a pull request, our system automatically looks through it. We check for security issues, mistakes in how you're setting up your infrastructure, and common code problems. We do this to make sure your changes are solid and won't cause any trouble later.

Talking to CodeAnt AI

Got a question or need a hand with something in your pull request? You can easily get in touch with CodeAnt AI right here. Just type the following in a comment on your pull request, and replace "Your question here" with whatever you want to ask:

@codeant-ai ask: Your question here

This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.

Example

@codeant-ai ask: Can you suggest a safer alternative to storing this secret?

Preserve Org Learnings with CodeAnt

You can record team preferences so CodeAnt AI applies them in future reviews. Reply directly to the specific CodeAnt AI suggestion (in the same thread) and replace "Your feedback here" with your input:

@codeant-ai: Your feedback here

This helps CodeAnt AI learn and adapt to your team's coding style and standards.

Example

@codeant-ai: Do not flag unused imports.

Retrigger review

Ask CodeAnt AI to review the PR again, by typing:

@codeant-ai: review

Check Your Repository Health

To analyze the health of your code repository, visit our dashboard at https://app.codeant.ai. This tool helps you identify potential issues and areas for improvement in your codebase, ensuring your repository maintains high standards of code health.

claude added 9 commits March 3, 2026 20:23
… main

Combines all changes from this PR into a single clean commit:

- backend.js: store raw buffer on req.rawBody before express.json() runs
  so HMAC verification uses the original bytes (not JSON.stringify output);
  guard log stream creation in try-catch with .on('error') fallback to
  console so filesystem failures never crash the process
- package.json: broaden engine range from >=20 <22 to >=20 (Node v24 compat)
- package-lock.json: regenerate with express@4.x and all transitive deps
  (was missing, causing npm ci to fail on VPS)
- runewager-endpoint.service: User/Group → root (VPS runs as root)
- runewager.service: User/Group → root (VPS runs as root)

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
- Pin express to 4.22.1 (remove ^ semver range) to match the
  explicitly installed version and prevent future version drift
  that caused the missing-dependency failure on Node 21.

- Add ExecStartPre to runewager-endpoint.service: kills any stale
  process holding port 3001 before each systemd start, eliminating
  the EADDRINUSE → instant-crash → restart loop.  Also tightened
  StartLimitBurst=4 / RestartSec=10 / StartLimitIntervalSec=120
  to reduce CPU spike if the service still fails repeatedly.

- Add section 9d to prod-run.sh: installs/refreshes the endpoint
  service unit from the repo copy, clears port 3001 before restart,
  restarts via systemd with a nohup fallback — so a full prod-run
  now brings both services up cleanly without manual intervention.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
Monitoring-only companion to rw_cpu_guard.sh. Generates timestamped
Markdown reports under /root/CPU_LOGS for /var/www/html/gcz and
/var/www/html/Runewager stacks, rotates to keep last 10 reports,
and symlinks the latest as CPU_report.md.

Never kills, renice-s, or restarts any process — purely observational.
Coexists safely with rw_cpu_guard.sh (separate log path, no shared state).

Features:
  - System-wide CPU summary via top
  - High-CPU process table (>85% threshold)
  - GCZ stack process listing with ⚠️ flag on hot processes
  - Best-effort dpkg package attribution for flagged pids
  - --status, --install-cron, --dry-run modes
  - Self-exclusion and kernel-thread exclusion from reports

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
…de processes

`pkill -f "node .*backend.js"` was too broad — on a shared host it
could kill any Node process whose cmdline contains "backend.js".
Narrowed both pkill calls (systemd fallback + no-systemd path) to
`node .*<PROJECT_DIR>/backend.js` so only the Runewager endpoint
process is targeted.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
gcz_cpu_guard.sh lives on the VPS directly, not in this repo.
Added "gcz_cpu_guard" to WHITELIST_PATTERNS in rw_cpu_guard.sh so
the Runewager CPU governor never renice/kills/stops the GCZ monitoring
script regardless of its CPU usage.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
Both static service files were hardcoding User=root/Group=root,
meaning any RCE in index.js or backend.js yielded full system control
and made ProtectSystem/NoNewPrivileges sandboxing meaningless.

Changes:
- runewager.service: User/Group → runewager (prod-run.sh already
  creates this system user and chowns logs/ + data/ to it)
- runewager-endpoint.service: User/Group → runewager; ExecStartPre
  prefixed with '+' so systemd runs only that port-clear step as root
  (needed to kill stale root-owned processes), while backend.js itself
  runs unprivileged

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
prod-run.sh: kept scoped pkill pattern (node .*PROJECT_DIR/backend.js)
  over the broad main version (node .*backend.js) — prevents killing
  unrelated node processes on shared hosts.

runewager-endpoint.service: kept our version with ExecStartPre '+' prefix
  (root-exec for port-clear step) and User/Group=runewager over main's
  root user with unprefixed ExecStartPre.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
backend.js — _write double-logging:
  Filter to writable streams first; fall back to a single console.log
  only when none are available. Previously logger.error() with two null
  streams would print the same line twice to stdout.

backend.js — rawBody guard on webhook:
  Treat missing/non-Buffer req.rawBody as a 500 (middleware
  misconfiguration) rather than silently falling back to Buffer.alloc(0),
  which was indistinguishable from a genuine signature mismatch.

prod-run.sh — port race in nohup fallback:
  After a failed systemctl restart, re-check and free ENDPOINT_PORT
  before launching the nohup fallback. The original cleanup ran before
  the systemd attempt, leaving a race window where another process
  could bind the port.

Note: log paths are NOT a conflict — prod-run.sh LOG_DIR resolves to
$PROJECT_DIR/logs, same as backend.js path.join(__dirname, 'logs').

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
…rds, log fallback)

runewager-endpoint.service — aggressive prestart kill:
  Replace direct SIGKILL with SIGTERM → 3s wait → SIGKILL escalation.
  Gives the port holder a chance to shut down gracefully before forcing.

backend.js — stream write guards:
  Filter streams by !destroyed && writable before writing, and wrap
  each write in try/catch so a mid-flight stream error is logged to
  stderr rather than crashing or silently corrupting output.

prod-run.sh — silent log creation:
  Replace `touch ... 2>/dev/null || true` with an explicit failure
  check; when the log directory is not writable, warn and fall back
  to /tmp so the nohup backend process always has somewhere to log.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
@codeant-ai

codeant-ai Bot commented Mar 3, 2026

Copy link
Copy Markdown

CodeAnt AI is reviewing your PR.


Thanks for using CodeAnt! 🎉

We're free for open-source projects. if you're enjoying it, help us grow by sharing.

Share on X ·
Reddit ·
LinkedIn

@sourcery-ai

sourcery-ai Bot commented Mar 3, 2026

Copy link
Copy Markdown

Reviewer's Guide

Adjusts endpoint startup robustness, backend logging resilience, webhook signature validation safety, and CPU guard whitelisting to improve reliability and avoid killing monitoring scripts.

Sequence diagram for autofix webhook signature validation

sequenceDiagram
    actor Client
    participant ExpressApp
    participant WebhookHandler
    participant Logger
    participant SignatureVerifier

    Client->>ExpressApp: POST /autofix/webhook (body)
    ExpressApp->>ExpressApp: Middleware parses body
    ExpressApp->>ExpressApp: Set req.rawBody (Buffer)
    ExpressApp->>WebhookHandler: Invoke handler with req, res

    WebhookHandler->>WebhookHandler: Read headers x-autofix-signature or x-hub-signature-256
    WebhookHandler->>WebhookHandler: Read req.rawBody as rawBody

    WebhookHandler->>WebhookHandler: Check rawBody exists and is Buffer
    alt rawBody missing or not Buffer
        WebhookHandler->>Logger: error(autofix.webhook, Missing rawBody, { requestId })
        Logger-->>WebhookHandler: Logged error
        WebhookHandler-->>Client: 500 JSON { ok: false, error: Internal server error, requestId }
    else rawBody valid
        WebhookHandler->>SignatureVerifier: verifySignature(rawBody, signature)
        SignatureVerifier-->>WebhookHandler: result
        alt AUTOFIX_SECRET missing or signature invalid
            WebhookHandler-->>Client: Error response (unauthorized or misconfigured)
        else Signature valid
            WebhookHandler-->>Client: 200 JSON { ok: true, ... }
        end
    end
Loading

Class diagram for backend logger utility

classDiagram
    class Logger {
        +info(eventType, msg, extra)
        +error(eventType, msg, extra)
        +debug(eventType, msg, extra)
        +_write(streams, obj)
    }

    class Stream {
        +destroyed : boolean
        +writable : boolean
        +write(line)
    }

    Logger "1" --> "*" Stream : writes to

    class AutofixWebhookHandler {
        +handle(req, res)
    }

    class ExpressRequest {
        +id
        +headers
        +rawBody
    }

    class ExpressResponse {
        +status(code)
        +json(body)
    }

    class SignatureVerifier {
        +verifySignature(rawBody, signature)
    }

    AutofixWebhookHandler --> Logger : uses
    AutofixWebhookHandler --> ExpressRequest : receives
    AutofixWebhookHandler --> ExpressResponse : responds via
    AutofixWebhookHandler --> SignatureVerifier : calls
Loading

File-Level Changes

Change Details Files
Make endpoint log file initialization robust to unwritable log directories by falling back to /tmp.
  • Replace unconditional touch of endpoint log files with a guarded touch that checks for failure
  • On failure, log a warning and redirect endpoint logs to /tmp paths
  • Ensure new /tmp log files are created if possible
prod-run.sh
Harden nohup fallback restart logic for the backend service, including more precise process killing and port conflict handling.
  • Tighten pkill patterns to only match node processes running the backend.js in the current PROJECT_DIR
  • Before nohup fallback, re-check the endpoint port and free it if another process is listening
  • Apply the more specific pkill pattern both for systemd restart fallback and no-systemd path
prod-run.sh
Improve backend logger stream handling to avoid writing to invalid streams and fall back cleanly to stdout.
  • Filter logger streams to only those that are non-null, not destroyed, and writable before writing log lines
  • Wrap individual stream writes in try/catch and log write errors to console.error
  • Fallback to console.log when no writable streams are available
backend.js
Make the Autofix webhook handler robust to missing or invalid rawBody, avoiding signature verification on undefined data.
  • Read rawBody directly from req.rawBody without defaulting to an empty buffer
  • Validate that rawBody is present and is a Buffer before proceeding
  • Log an explicit error and return a 500 response if rawBody is missing or misconfigured
backend.js
Extend CPU guard whitelist to ensure sibling monitoring scripts are never killed.
  • Add gcz_cpu_guard to the whitelist patterns alongside rw_cpu_guard
  • Clarify comment that both the guard and sibling monitoring scripts are untouchable
scripts/rw_cpu_guard.sh

Tips and commands

Interacting with Sourcery

  • Trigger a new review: Comment @sourcery-ai review on the pull request.
  • Continue discussions: Reply directly to Sourcery's review comments.
  • Generate a GitHub issue from a review comment: Ask Sourcery to create an
    issue from a review comment by replying to it. You can also reply to a
    review comment with @sourcery-ai issue to create an issue from it.
  • Generate a pull request title: Write @sourcery-ai anywhere in the pull
    request title to generate a title at any time. You can also comment
    @sourcery-ai title on the pull request to (re-)generate the title at any time.
  • Generate a pull request summary: Write @sourcery-ai summary anywhere in
    the pull request body to generate a PR summary at any time exactly where you
    want it. You can also comment @sourcery-ai summary on the pull request to
    (re-)generate the summary at any time.
  • Generate reviewer's guide: Comment @sourcery-ai guide on the pull
    request to (re-)generate the reviewer's guide at any time.
  • Resolve all Sourcery comments: Comment @sourcery-ai resolve on the
    pull request to resolve all Sourcery comments. Useful if you've already
    addressed all the comments and don't want to see them anymore.
  • Dismiss all Sourcery reviews: Comment @sourcery-ai dismiss on the pull
    request to dismiss all existing Sourcery reviews. Especially useful if you
    want to start fresh with a new review - don't forget to comment
    @sourcery-ai review to trigger a new review!

Customizing Your Experience

Access your dashboard to:

  • Enable or disable review features such as the Sourcery-generated pull request
    summary, the reviewer's guide, and others.
  • Change the review language.
  • Add, remove or edit custom review instructions.
  • Adjust other review settings.

Getting Help

@coderabbitai

coderabbitai Bot commented Mar 3, 2026

Copy link
Copy Markdown

Warning

Rate limit exceeded

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

⌛ 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.

📥 Commits

Reviewing files that changed from the base of the PR and between b090755 and 63bfc3b.

📒 Files selected for processing (3)
  • backend.js
  • prod-run.sh
  • runewager-endpoint.service
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch claude/cpu-guard-script-DnD8u

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.

sourcery-ai[bot]

This comment was marked as resolved.

@codeant-ai codeant-ai Bot added the size:M This PR changes 30-99 lines, ignoring generated files label Mar 3, 2026
…scalation

backend.js: kept writable/destroyed stream guard + try/catch over bare filter(Boolean)
runewager-endpoint.service: kept SIGTERM→3s→SIGKILL escalation over direct kill -9

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
Comment thread runewager-endpoint.service Outdated
@codeant-ai

This comment was marked as resolved.

@codeant-ai

codeant-ai Bot commented Mar 3, 2026

Copy link
Copy Markdown

CodeAnt AI finished reviewing your PR.

claude added 2 commits March 3, 2026 21:43
prod-run.sh — pkill regex safety:
  Escape PROJECT_DIR with sed before interpolating into the pkill -f
  pattern. Spaces or regex metacharacters in the path (e.g. dots in
  /var/www) can cause unexpected matches or silent pattern failure.

backend.js — rawBody missing response code:
  Change 500 → 400 when req.rawBody is absent. 500 caused webhook
  senders to treat the rejection as transient and retry; 400 signals
  a permanent bad-request so retries stop. The server-side
  misconfiguration is still logged as an error for visibility.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
fuser without -t outputs "3001/tcp: 1234" — the full string was
being passed to kill, causing it to fail silently and leaving the
port holder alive (EADDRINUSE crash loop when lsof is unavailable).
fuser -t outputs only the bare PID, matching lsof -t behaviour.

https://claude.ai/code/session_01WpEqAiDbpqnBywMjYXJHf4
@gamblecodezcom
gamblecodezcom merged commit 7c6debe into main Mar 3, 2026
6 checks passed
@gamblecodezcom
gamblecodezcom deleted the claude/cpu-guard-script-DnD8u branch March 3, 2026 21:44
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

size:M This PR changes 30-99 lines, ignoring generated files

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants