Claude/cpu guard script dn d8u - #122
Conversation
|
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 · |
Reviewer's GuideAdds a new companion HTTP service (runewager-endpoint) with its own systemd unit, introduces a centralized Telegram rate limiter and safe wrapper, tightens CPU guard forensics file creation, and updates the redeploy script to properly manage companion services and improve health output formatting. Sequence diagram for Autofix webhook handling and admin broadcastsequenceDiagram
participant AF as Autofix_webhook_sender
participant EP as Express_endpoint_backend
participant RL as rateLimiter
participant TG as Telegram_API
participant ADM as Admin_chat
AF->>EP: POST /autofix/webhook (raw body + HMAC)
EP->>EP: verifySignature(rawBody, signature)
alt invalid_or_missing_secret
EP->>EP: log error (autofix.webhook)
EP-->>AF: 401 Invalid signature
else valid_signature
EP->>EP: parse JSON payload, extract event
EP->>EP: logger.event(autofix.webhook)
EP->>RL: globalThrottle(sendAdmin_request)
activate RL
RL->>TG: HTTPS sendMessage(botToken, adminChatId[], text)
deactivate RL
TG-->>ADM: deliver admin notification
EP-->>AF: 200 { ok: true, requestId }
end
Class diagram for rateLimiter and telegramSafe modulesclassDiagram
class rateLimiter {
<<module>>
-GLOBAL_GAP_MS : number
-CHAT_GAP_MS : number
-API_CALL_TIMEOUT_MS : number
-_chatQueues : Map
-_globalTail : Promise
-_globalLast : number
-_delay(ms : number) Promise
-_globalSlot(fn : function) Promise
+enqueue(chatId : string|number|null, fn : function) Promise
+globalThrottle(fn : function) Promise
+stats() Object
}
class telegramSafe {
<<module>>
-_bot : Telegraf
-_inited : boolean
-_withRetry(fn : function, maxRetries : number) Promise
-_assertInited() void
+init(bot : Telegraf) void
+sendMessage(chatId : string|number, text : string, options : Object) Promise
+editMessageText(chatId : string|number, messageId : number, text : string, options : Object) Promise
+answerCallbackQuery(callbackId : string, options : Object) Promise
+sendPhoto(chatId : string|number, photo : any, options : Object) Promise
+sendDocument(chatId : string|number, document : any, options : Object) Promise
}
class Telegraf {
<<from telegraf>>
+telegram : Telegram
}
class Telegram {
+sendMessage(chatId : string|number, text : string, extra : Object) Promise
+editMessageText(chatId : string|number, messageId : number, inlineMessageId : string, text : string, extra : Object) Promise
+answerCbQuery(callbackQueryId : string, text : string, showAlert : boolean, extra : Object) Promise
+answerCallbackQuery(callbackQueryId : string, text : string, showAlert : boolean, extra : Object) Promise
+sendPhoto(chatId : string|number, photo : any, extra : Object) Promise
+sendDocument(chatId : string|number, document : any, extra : Object) Promise
+sendAnimation(chatId : string|number, animation : any, extra : Object) Promise
+sendSticker(chatId : string|number, sticker : any, extra : Object) Promise
+forwardMessage(chatId : string|number, fromChatId : string|number, messageId : number, extra : Object) Promise
+callApi(method : string, data : Object, signal : any) Promise
}
Telegraf --> Telegram : has
telegramSafe ..> rateLimiter : uses
telegramSafe ..> Telegraf : patches bot.telegram
Class diagram for backend companion HTTP serviceclassDiagram
class BackendService {
<<module backend.js>>
-PORT : number
-AUTOFIX_SECRET : string
-TG_TOKEN : string
-ADMIN_CHAT_IDS : string[]
-LOG_DIR : string
-LOG_FILE : string
-ERR_FILE : string
-_logStream : WriteStream
-_errStream : WriteStream
+sendAdmin(msg : string) Promise
+verifySignature(rawBody : Buffer, signature : string) boolean
+shutdown(signal : string) void
}
class Logger {
<<object>>
+info(eventType : string, msg : string, extra : Object) void
+error(eventType : string, msg : string, extra : Object) void
+event(eventType : string, msg : string, extra : Object) void
-_entry(level : string, eventType : string, msg : string, extra : Object) Object
-_write(streams : WriteStream[], obj : Object) void
}
class ExpressApp {
<<from express>>
+use(middleware : function) void
+get(path : string, handler : function) void
+post(path : string, handler : function) void
+listen(port : number, host : string, callback : function) Server
}
class RateLimiterModule {
<<module rateLimiter.js>>
+globalThrottle(fn : function) Promise
+enqueue(chatId : string|number|null, fn : function) Promise
+stats() Object
}
BackendService ..> Logger : uses
BackendService ..> ExpressApp : configures
BackendService ..> RateLimiterModule : uses
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
|
Warning Rate limit exceeded
⌛ How to resolve this issue?After the wait time has elapsed, a review can be triggered using the 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. ⛔ Files ignored due to path filters (1)
📒 Files selected for processing (4)
📝 WalkthroughWalkthroughAdds an Express-based HTTP endpoint service with HMAC-SHA256 webhook validation, structured JSON logging, graceful shutdown handling, Telegram admin notifications, and implements both global and per-chat rate limiting for Telegram API calls with automatic retry logic. Changes
Sequence Diagram(s)sequenceDiagram
actor Client
participant Express as backend.js<br/>(Express Service)
participant Limiter as rateLimiter.js<br/>(Rate Limiter)
participant TgSafe as telegramSafe.js<br/>(Telegram Wrapper)
participant TgAPI as Telegram Bot API
participant Logger as Logger<br/>(Structured Log)
participant Admin as Admin Channel<br/>(Telegram)
Client->>Express: POST /autofix/webhook<br/>(with HMAC signature)
Express->>Express: Validate HMAC-SHA256<br/>signature
alt Signature Invalid
Express->>Logger: Log 401 failure
Express->>Client: 401 Unauthorized
else Signature Valid
Express->>Logger: Log request<br/>(with requestId)
Express->>Limiter: enqueue(adminChatId,<br/>sendMessage fn)
Limiter->>Limiter: Wait for per-chat<br/>& global slots
Limiter->>TgSafe: Call patched<br/>sendMessage
TgSafe->>TgSafe: Apply retry logic<br/>(exponential backoff)
loop Retry on 429 or transient
TgSafe->>TgAPI: Send message
TgAPI-->>TgSafe: 429 / error
end
TgAPI-->>TgSafe: Success
TgSafe-->>Limiter: Result
Limiter-->>Express: Resolve
Express->>Logger: Log success
Express->>Client: 200 OK
end
opt On Error
Express->>Logger: Log error
Express->>Admin: Notify admin<br/>of failure
end
Estimated code review effort🎯 4 (Complex) | ⏱️ ~45 minutes Possibly related PRs
Suggested labels
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 inconclusive)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
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 |
Sequence DiagramShows the new companion HTTP endpoint validating Autofix HMAC-signed webhooks and notifying admins via a centralized, rate-limited Telegram wrapper. Also shows bot initialization where telegramSafe is applied to route all Telegram calls through the global rate limiter. sequenceDiagram
participant AutofixSender
participant Endpoint
participant RateLimiter
participant TelegramAPI
Note over Endpoint: index.js calls telegramSafe.init(bot) at startup
Endpoint->>RateLimiter: Patch bot.telegram methods (init)
RateLimiter-->>Endpoint: Methods wrapped (sendMessage, callApi, globalThrottle)
AutofixSender->>Endpoint: POST /autofix/webhook (HMAC-signed payload)
Endpoint->>Endpoint: verifySignature(rawBody, header)
alt signature valid
Endpoint->>RateLimiter: sendAdmin() -> globalThrottle(sendMessage to each ADMIN_CHAT_ID)
RateLimiter->>TelegramAPI: schedule/send API calls (global + per-chat limits)
TelegramAPI-->>RateLimiter: 200 OK / responses
RateLimiter-->>Endpoint: all notifications scheduled/completed
Endpoint-->>AutofixSender: 200 OK (received)
else invalid
Endpoint-->>AutofixSender: 401 Invalid signature
end
Generated by CodeAnt AI |
There was a problem hiding this comment.
Hey - I've found 1 issue, and left some high level feedback:
- In backend.js the combination of
app.use('/autofix', express.raw(...))followed by a globalexpress.json()meansreq.bodywill no longer be the original raw buffer when the/autofix/webhookhandler runs, so reconstructingrawBodywithJSON.stringify(req.body)can change whitespace/key order and break HMAC verification; consider storing the raw buffer on a separate property (e.g.req.rawBody) in the raw middleware and using that directly for signature checks. - The logging setup in backend.js assumes the
createWriteStreamcalls succeed even if themkdirSyncfails; you may want to guard writes when_logStreamor_errStreamare undefined or fall back toconsolelogging to avoid potential runtime errors on startup in constrained environments.
Prompt for AI Agents
Please address the comments from this code review:
## Overall Comments
- In backend.js the combination of `app.use('/autofix', express.raw(...))` followed by a global `express.json()` means `req.body` will no longer be the original raw buffer when the `/autofix/webhook` handler runs, so reconstructing `rawBody` with `JSON.stringify(req.body)` can change whitespace/key order and break HMAC verification; consider storing the raw buffer on a separate property (e.g. `req.rawBody`) in the raw middleware and using that directly for signature checks.
- The logging setup in backend.js assumes the `createWriteStream` calls succeed even if the `mkdirSync` fails; you may want to guard writes when `_logStream` or `_errStream` are undefined or fall back to `console` logging to avoid potential runtime errors on startup in constrained environments.
## Individual Comments
### Comment 1
<location path="backend.js" line_range="47-48" />
<code_context>
+ console.error(`[backend] Cannot create log directory ${LOG_DIR}: ${e.message}`);
+}
+
+const _logStream = fs.createWriteStream(LOG_FILE, { flags: 'a' });
+const _errStream = fs.createWriteStream(ERR_FILE, { flags: 'a' });
+
+const logger = {
</code_context>
<issue_to_address>
**issue (bug_risk):** Guard against write-stream errors so logging failures don't crash the process
`createWriteStream` can emit `'error'` if the directory becomes unwritable or the filesystem fails. Without `error` handlers, subsequent `write()` calls can cause unhandled exceptions and crash the service. Please attach `error` listeners and either fall back to `console` logging or a no-op logger when the streams fail, so logging issues can't terminate `runewager-endpoint`.
</issue_to_address>Help me be more useful! Please click 👍 or 👎 on each comment and I'll use the feedback to improve your reviews.
Nitpicks 🔍
|
… 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
4f08923 to
c1ad46c
Compare
|
CodeAnt AI finished reviewing your PR. |
User description
Summary by Sourcery
Introduce a companion HTTP endpoint service and centralized Telegram rate-limiting, and wire them into deployment and runtime tooling.
New Features:
Bug Fixes:
CodeAnt-AI Description
Add a companion HTTP endpoint, centralized Telegram rate-limiter, and deploy fixes
What Changed
Impact
✅ Clearer autofix webhook diagnostics✅ Fewer Telegram rate-limit failures and automated retries✅ Safer redeploys that avoid port conflicts and show companion service status💡 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:
This lets you have a chat with CodeAnt AI about your pull request, making it easier to understand and improve your code.
Example
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:
This helps CodeAnt AI learn and adapt to your team's coding style and standards.
Example
Retrigger review
Ask CodeAnt AI to review the PR again, by typing:
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.
Summary by CodeRabbit
New Features
Chores