Skip to content

bridge: add broker long-poll v2 pull signing#123

Merged
benvinegar merged 3 commits into
mainfrom
bentlegen/broker-long-poll-v2-client
Feb 22, 2026
Merged

bridge: add broker long-poll v2 pull signing#123
benvinegar merged 3 commits into
mainfrom
bentlegen/broker-long-poll-v2-client

Conversation

@benvinegar
Copy link
Copy Markdown
Member

@benvinegar benvinegar commented Feb 22, 2026

Summary

  • add broker pull long-poll support in slack-bridge/broker-bridge.mjs using wait_seconds (default 20s, clamped to 25s max)
  • sign long-poll pulls with inbox.pull.v2 stable JSON canonicalization; keep legacy inbox.pull signing when SLACK_BROKER_WAIT_SECONDS=0
  • clamp broker pull inputs before signing (SLACK_BROKER_MAX_MESSAGES to 1..100, SLACK_BROKER_WAIT_SECONDS to 0..25) so signatures match broker-side clamped verification
  • skip extra idle sleep after successful long-poll cycles so timeout loops can immediately re-pull
  • add canonicalizeOutboundV2 helper and unit coverage in slack-bridge/crypto.test.mjs
  • add semi-integration coverage in test/broker-bridge.integration.test.mjs for:
    • default v2 long-poll request signing
    • legacy fallback mode when wait is disabled
    • max_messages clamping before signature generation
  • document/tune new env var SLACK_BROKER_WAIT_SECONDS in CONFIGURATION.md, README.md, and AGENTS.md

Testing

  • node --test slack-bridge/crypto.test.mjs
  • node --check slack-bridge/broker-bridge.mjs
  • node --check test/broker-bridge.integration.test.mjs

@greptile-apps
Copy link
Copy Markdown

greptile-apps Bot commented Feb 22, 2026

Greptile Summary

This PR adds broker long-poll v2 support with cryptographic request signing using stable JSON canonicalization. The implementation introduces SLACK_BROKER_WAIT_SECONDS (default 20s, max 25s) for long-polling, while maintaining backward compatibility with legacy short-poll mode when set to 0.

Key changes:

  • Added canonicalizeOutboundV2 helper using deterministic JSON serialization to match broker-side verification
  • Implemented signPullRequest function that uses v2 signing for long-poll requests and falls back to legacy signing for short-poll
  • Added clampInt helper to ensure all broker pull inputs are clamped before signing (max_messages: 1-100, wait_seconds: 0-25) to match broker-side validation
  • Skip idle sleep after successful long-poll cycles to enable immediate re-polling when broker timeout completes
  • Comprehensive test coverage: unit tests for canonicalization and 3 integration tests covering v2 signing, legacy fallback, and input clamping
  • Documentation updated across README.md, CONFIGURATION.md, AGENTS.md, and bin/config.sh

The implementation is well-structured with proper separation of concerns, thorough testing, and clear documentation. Input validation through clamping prevents signature mismatches between client and broker.

Confidence Score: 5/5

  • This PR is safe to merge with minimal risk
  • The implementation is production-ready with excellent code quality: proper input validation through clamping, cryptographically sound signing logic, backward compatibility preservation, comprehensive test coverage (unit + integration), and thorough documentation updates. The changes are well-isolated to broker bridge functionality with no breaking changes to existing behavior.
  • No files require special attention

Important Files Changed

Filename Overview
slack-bridge/broker-bridge.mjs Added long-poll v2 signing with clamped inputs, conditional sleep logic, and proper backward compatibility
slack-bridge/crypto.mjs Added canonicalizeOutboundV2 helper using stable JSON serialization for v2 request signing
slack-bridge/crypto.test.mjs Added unit tests covering canonicalizeOutboundV2 output format and type validation
test/broker-bridge.integration.test.mjs Added three integration tests for v2 signing, legacy fallback mode, and max_messages clamping

Sequence Diagram

sequenceDiagram
    participant Bridge as broker-bridge.mjs
    participant Crypto as crypto.mjs
    participant Broker as Broker API
    
    Note over Bridge: Poll Loop Start
    Bridge->>Bridge: Check BROKER_WAIT_SECONDS
    
    alt Long-poll mode (wait_seconds > 0)
        Bridge->>Crypto: canonicalizeOutboundV2(workspace, "inbox.pull.v2", timestamp, payload)
        Crypto->>Crypto: stableStringify({workspace_id, action, timestamp, payload})
        Crypto-->>Bridge: Uint8Array (canonical bytes)
        Bridge->>Bridge: crypto_sign_detached(canonical, privateKey)
    else Legacy short-poll (wait_seconds = 0)
        Bridge->>Crypto: canonicalizeOutbound(workspace, "inbox.pull", timestamp, max_messages)
        Crypto->>Crypto: utf8Bytes("workspace|action|timestamp|max_messages")
        Crypto-->>Bridge: Uint8Array (canonical bytes)
        Bridge->>Bridge: crypto_sign_detached(canonical, privateKey)
    end
    
    Bridge->>Broker: POST /api/inbox/pull<br/>{workspace_id, max_messages, wait_seconds?, timestamp, signature}
    Broker-->>Bridge: {ok: true, messages: [...]}
    
    Bridge->>Bridge: Process messages
    
    alt Long-poll mode
        Bridge->>Bridge: Skip sleep, immediately re-poll
    else Short-poll mode
        Bridge->>Bridge: Sleep POLL_INTERVAL_MS
    end
    
    Note over Bridge: Repeat Poll Loop
Loading

Last reviewed commit: 7665c30

@benvinegar benvinegar force-pushed the bentlegen/broker-long-poll-v2-client branch from 7b3e8f2 to f19b29a Compare February 22, 2026 20:33
@benvinegar benvinegar merged commit 2c88a83 into main Feb 22, 2026
9 checks passed
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.

1 participant