feat(capsule): short-circuit interceptor chain with veto semantics#587
feat(capsule): short-circuit interceptor chain with veto semantics#587joshuajbouw merged 2 commits intomainfrom
Conversation
Interceptors now return InterceptResult (Continue/Final/Deny) instead of raw bytes. The dispatcher runs matching interceptors sequentially in priority order and halts the chain on Final or Deny. - Continue: pass (possibly modified) payload to next interceptor - Final: short-circuit with response, no further interceptors fire - Deny: short-circuit with audit-logged reason, no further interceptors Wire format: discriminant byte (0x00/0x01/0x02) + payload. Empty bytes treated as Continue for backward compatibility with existing capsules. Single-interceptor events use the existing per-capsule queue fast path. Multi-interceptor events run as a sequential chain in a spawned task. Prior art: Bevy ECS (system ordering + run conditions), Express.js (next() middleware), Envoy (filter chain), Linux netfilter (NF_ACCEPT/ NF_DROP), DOM events (stopPropagation). Closes #585
Summary of ChangesHello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed! This pull request introduces a significant enhancement to the interceptor system by implementing a middleware chain with short-circuit capabilities. This change allows for more flexible and powerful control over event processing, enabling features like input guards and caching layers. The introduction of the Highlights
Using Gemini Code AssistThe full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips. Invoking Gemini You can request assistance from Gemini at any point by creating a comment using either
Customization To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a Limitations & Feedback Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here. A byte is sent with care, Through chains of filters there. Deny, or Final say, To change the flow today, And alter fate's affair. Footnotes
|
There was a problem hiding this comment.
Code Review
This pull request introduces a valuable short-circuiting mechanism for the interceptor chain, allowing interceptors to return Continue, Final, or Deny to control the execution flow. The implementation is well-structured, with a clear InterceptResult enum and backward-compatible wire format handling. The dispatcher logic is updated to manage the chain, including a fast-path for single-interceptor events, and the new functionality is thoroughly covered by tests.
I've found one issue in the single-interceptor dispatch logic where the interceptor's result was previously ignored. My review includes a suggestion to address this, ensuring proper handling of Result outcomes and preventing silent failures, consistent with repository guidelines.
Move has_valid_segments and topic_matches from dispatcher.rs into topic.rs. Pure extraction — no logic changes. Reduces dispatcher.rs from 1072 to 936 lines. Also addresses review: explicitly handle all InterceptResult variants in the single-interceptor dispatch path instead of Ok(_).
Linked Issue
Closes #585
Summary
Evolve the interceptor priority system from "ordered execution of all matching interceptors" to a middleware chain with short-circuit/veto capability. Interceptors return
Continue,Final, orDenyto control the chain. A guard at priority 10 can veto an event before the core handler at priority 100 ever sees it.Changes
InterceptResultenum (Continue/Final/Deny) tocapsule.rswith wire format decoderinvoke_interceptorreturn type fromCapsuleResult<Vec<u8>>toCapsuleResult<InterceptResult>across all trait implementations (Capsule, ExecutionEngine, WasmEngine, McpEngine)InterceptResult::from_guest_bytes()— backward compatible (empty bytes = Continue)sys.rs) to handle all three result variantsPrior Art
next()middleware chainTest Plan
Automated
cargo test --workspacepasses (24 dispatcher tests including 3 new chain tests)Manual
Checklist
[Unreleased]