Uh oh!
There was an error while loading. Please reload this page.
feat(ocap-kernel): add resource limits for remote communications - #714
Conversation
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
a40d3eb to
96f26e2CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
b6c23e0 to
25e81acCompareUh oh!
There was an error while loading. Please reload this page.
8e04986 to
ce1e774CompareUh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
rekmarks
commented
Jan 5, 2026
@cursor review |
Uh oh!
There was an error while loading. Please reload this page.
ce1e774 to
8323837CompareUh oh!
There was an error while loading. Please reload this page.
FUDCo
left a comment
There was a problem hiding this comment.
This looks fine for what it is.
One lingering question I have is that as we get more careful about detecting error conditions (or proclaiming them, in the case of configurable resource limits), are we potentially setting ourselves up for situations where an error bubbles up to user code at some location other than the location that is actually responsible for causing it? In other words, will a message transmission error always find its way back to the actual send operation that triggered it?
More generally, could user code find itself in an unrecoverable error state (by that I don't mean a state where there's an error that you can't get rid of -- things can always break unfixably, e.g., a remote host dies forever -- but rather a state where you don't actually know you're stuck). It's entirely plausible to me that everything is fine, but I can't tell from reading the tests whether our tests give us reason to believe we are ok on this score.
@FUDCo Two parts to your question: Error attribution: Yeah transmission errors are always caught within the specific Stuck without knowing: Currently |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
71fe98b to
b9f908bCompareUh oh!
There was an error while loading. Please reload this page.
PR Review: Resource Limits for Remote CommunicationsI've completed a comprehensive review of this PR. Overall, this is high-quality work with excellent attention to detail on resource management and edge cases. The implementation addresses critical DoS vulnerabilities and includes thorough test coverage. Below are my findings: ✅ Strengths1. Excellent Error Design
2. Robust Resource Limit EnforcementThe implementation is thorough and handles numerous edge cases:
3. Channel Lifecycle Management
4. Comprehensive Test Coverage
5. Security Considerations
🔍 Issues & RecommendationsCriticalNone - No critical issues found. High Priority1. Error Propagation Concern (addresses @FUDCo's comment) The current implementation has a potential issue where resource limit errors may not always propagate back to the caller: Location: try{checkConnectionLimit();}catch{// Connection limit reached - close the dialed channel and queue the messagelogger.log(`${targetPeerId}:: connection limit reached after dial, queueing message`,);awaitconnectionFactory.closeChannel(channel,targetPeerId);currentQueue.enqueue(message);handleConnectionLoss(targetPeerId,channel);return;// ⚠️ Returns silently, caller doesn't know message was queued}Problem: When the connection limit is reached after dial, the message is silently queued and reconnection is triggered. The caller receives a successful Promise resolution but the message wasn't actually sent. Similar issue at: Recommendation: Consider one of these approaches:
This ensures user code knows when messages are delayed vs. successfully sent, avoiding the "unrecoverable error state" concern. 2. TextEncoder Creation Efficiency Location: functionvalidateMessageSize(message: string): void{constmessageSizeBytes=newTextEncoder().encode(message).length;// ...}Issue: Creates a new Recommendation: constmessageEncoder=newTextEncoder();// Create once at module levelfunctionvalidateMessageSize(message: string): void{constmessageSizeBytes=messageEncoder.encode(message).length;// ...}Medium Priority3. Race Condition in Cleanup Location: The for(constpeerIdofstalePeers){lastConnectionTime.delete(peerId);messageQueues.delete(peerId);// ...}Issue: If a connection is established between when Recommendation: Add a final check before deletion: for(constpeerIdofstalePeers){// Re-check that peer is still stale (not reconnected since we checked)if(channels.has(peerId)||reconnectionManager.isReconnecting(peerId)){continue;// Skip cleanup, peer is active again}lastConnectionTime.delete(peerId);// ...}4. Missing TypeDoc Documentation Location: The new maxConcurrentConnections?: number|undefined;// Missing: what happens when reached?
maxMessageSizeBytes?: number|undefined;// Missing: exact behavior on exceed
stalePeerTimeoutMs?: number|undefined;// Missing: what data is cleaned up?Recommendation: Add detailed TypeDoc comments per CLAUDE.md conventions: /** * Maximum message size in bytes (default: 1MB). * Messages exceeding this limit will be immediately rejected with ResourceLimitError. */
maxMessageSizeBytes?: number|undefined;5. Potential Integer Overflow in Test Location: When testing message size limits with values like Recommendation: Add a test comment documenting the max safe value or add explicit validation in the options. Low Priority6. Code Style: Error Handling Pattern Location: Multiple locations use empty Per CLAUDE.md, prefer explicit error handling. Several places catch and ignore errors: }catch{logger.log(`${targetPeerId}:: connection limit reached...`);// ...}Recommendation: Make error variable explicit: }catch(limitError){logger.log(`${targetPeerId}:: connection limit reached...`);// Could log limitError.message for better diagnostics}7. Magic Number for SCTP Code Location: constSCTP_USER_INITIATED_ABORT=12;// RFC 4960Note: Good use of a constant! Consider extracting to a shared constants file if used elsewhere, but current location is fine for now. 📊 Performance & ScaleGood:
Consider:
🔒 Security Assessment✅ Well Protected:
|
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
b9c906e to
982f9b8Compare- Add connection limit (default 100 concurrent connections) - Add message size limit (default 1MB per message) - Add stale peer cleanup (removes data for peers disconnected >1 hour) - Make all limits configurable via RemoteCommsOptions - Add ResourceLimitError for limit violations - Add comprehensive tests for all resource limits This prevents memory exhaustion and manages system resources by: - Rejecting new connections when limit is reached - Rejecting messages exceeding size limit - Periodically cleaning up stale peer data
When an inbound connection replaces a channel during reconnection flush, the old flush fails but messages would get stuck. Now we detect the channel replacement and automatically flush on the new channel. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
b03fba3 to
645b251Compare
FUDCo
left a comment
There was a problem hiding this comment.
Looks goodish. I'm still concerned about lost messages getting lost, but I don't think that's a reason to hold up the train. We should add an issue to make sure we don't let that one fall through the cracks, though.
Closes#660
This prevents memory exhaustion and manages system resources by:
Note
Implements configurable resource limits and lifecycle hardening for remote communications, and adds a dedicated error type for violations.
maxConcurrentConnections(default 100): rejects inbound when full, checks again post-dial for outbound; introducescloseChannelto release streamsmaxMessageSizeBytes(default 1MB) before dialing/queuingcleanupIntervalMs,stalePeerTimeoutMs): prunes queues/hints/intentional-close/retry state; cleaned up onstop()RemoteCommsOptionswith new limits/cleanup options; tracks last-activity timestampsErrorCode.ResourceLimitErrorandResourceLimitError(marshal/unmarshal) with comprehensive tests and exportsWritten by Cursor Bugbot for commit 2704782. This will update automatically on new commits. Configure here.