Skip to content

feat(a2a-nats-http): add HTTP/JSON-RPC + REST + SSE binding#365

Merged
yordis merged 5 commits into
mainfrom
yordis/feat-a2a-nats-http-bin
Jun 21, 2026
Merged

feat(a2a-nats-http): add HTTP/JSON-RPC + REST + SSE binding#365
yordis merged 5 commits into
mainfrom
yordis/feat-a2a-nats-http-bin

Conversation

@yordis

@yordis yordis commented Jun 21, 2026

Copy link
Copy Markdown
Member
  • the transports stack so far has only spoken NATS natively (a2a-nats-server, a2a-nats-stdio); HTTP-facing callers that can't dial NATS directly need a binding that funnels through the same A2aClient so the protocol contract stays single-sourced
  • coverage split mirrors the sibling binaries: env parsing + error types stay testable, the connect-and-serve half is gated behind cfg(not(coverage)) because trogon-nats::NatsJetStreamClient is excluded from coverage builds

The transports stack so far has been NATS-native (server/stdio); this
adds the HTTP-facing binary so callers that can't speak NATS directly
still hit the same A2aClient surface. JSON-RPC, REST and SSE bindings
all funnel through the existing message_send / tasks_* / push_* paths
so the protocol contract stays single-sourced. Coverage split mirrors
the other binaries: env parsing is testable, connect-and-serve gated
behind cfg(not(coverage)).

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@cursor

cursor Bot commented Jun 21, 2026

Copy link
Copy Markdown

PR Summary

Medium Risk
New network ingress with auth/policy marked future work; gateway JWT and shared error mapping affect how failures surface, but logic delegates to existing a2a-nats client with broad mock tests.

Overview
Adds a new a2a-nats-http crate and binary so HTTP clients can reach NATS-backed agents through the same A2aClient as a2a-nats-stdio / a2a-nats-server, instead of speaking NATS directly.

JSON-RPC is served on POST / (full A2A method surface, including message/stream and tasks/resubscribe as SSE with bootstrap frames aligned to the stdio bridge). REST equivalents live under /v1/*, plus /.well-known/agent-card.json. Middleware negotiates A2A-Version, A2A-Extensions, and application/a2a+json, with optional path rewrite for /v1/tasks/{id}:cancel-style URLs.

Runtime wires NATS + JetStream, env-driven timeouts, and optional A2A_USE_GATEWAY routing with a caller JWT. Connect/serve is cfg(not(coverage)) like the other A2A binaries; integration tests use mock NATS/JetStream.

Reviewed by Cursor Bugbot for commit cbdabe0. Bugbot is set up for automated code reviews on this repo. Configure here.

@coderabbitai

coderabbitai Bot commented Jun 21, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@yordis, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 21 minutes and 1 second. Learn how PR review limits work.

Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file).

⌛ How to resolve this issue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits.

🚦 How do rate limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly.

Please see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 4c08895a-0560-4798-8e0d-4820ffbf43b2

📥 Commits

Reviewing files that changed from the base of the PR and between 2ae3c49 and cbdabe0.

📒 Files selected for processing (6)
  • rsworkspace/crates/a2a-nats-http/README.md
  • rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs
  • rsworkspace/crates/a2a-nats-http/src/headers.rs
  • rsworkspace/crates/a2a-nats-http/src/rest.rs
  • rsworkspace/crates/a2a-nats-http/src/runtime.rs
  • rsworkspace/crates/a2a-nats-http/src/sse.rs

Walkthrough

A new a2a-nats-http crate is introduced, providing an Axum HTTP server that exposes the A2A protocol over JSON-RPC (POST /), a REST API (/v1/...), and SSE streaming, all backed by a2a_nats::A2aClient. The crate includes A2A spec negotiation middleware, a URI-rewriting middleware for A2A custom method syntax, a runtime bootstrap with gateway support, and a comprehensive test suite.

Changes

a2a-nats-http: Axum HTTP adapter for A2A over NATS

Layer / File(s) Summary
Crate manifest, entry point, and runtime bootstrap
rsworkspace/crates/a2a-nats-http/Cargo.toml, rsworkspace/crates/a2a-nats-http/README.md, rsworkspace/crates/a2a-nats-http/src/lib.rs, rsworkspace/crates/a2a-nats-http/src/main.rs, rsworkspace/crates/a2a-nats-http/src/runtime.rs
Cargo.toml and README.md define the crate metadata and documentation. lib.rs declares all submodules and re-exports run/RuntimeError. main.rs wires tracing and calls run() with error exit. runtime.rs defines RuntimeError, reads env config, connects to NATS (with optional gateway JWT validation), builds the Axum app, and serves with graceful shutdown; a coverage stub variant returns immediately.
A2A spec negotiation middleware
rsworkspace/crates/a2a-nats-http/src/headers.rs
Adds public header name constants (a2a-version, a2a-extensions), A2A_MEDIA_TYPE, SpecNegotiationConfig with a fluent builder, RequestedExtension/parse_extensions for comma-delimited extension header parsing (supporting ? prefix and ;q=0 optionality), the negotiate Axum middleware that validates version/extensions and echoes negotiated values to the response, default_config(), and unit tests.
SSE stream conversion and error mapping
rsworkspace/crates/a2a-nats-http/src/sse.rs
typed_event_stream_to_sse converts a TypedEventStream<Result<_, ClientError>> into an infallible Axum SSE Event stream, wrapping each item in a JSON-RPC 2.0 envelope with "result" or "error". client_error_to_jsonrpc_code maps ClientError variants to (code, message) tuples, falling back to -32603.
JSON-RPC handlers
rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs
JsonRpcEnvelope deserializes incoming JSON-RPC requests. handle_jsonrpc dispatches on envelope.method to all A2aClient operations, returning SSE streams for message/stream and tasks/resubscribe (with an initial snapshot event), and JSON-RPC payloads for all other methods. agent_card selects HTTP status based on the mapped error code. Helper builders produce jsonrpc_ok, jsonrpc_error_response, jsonrpc_parse_error, and sse_response values.
REST handler router and per-endpoint implementations
rsworkspace/crates/a2a-nats-http/src/rest.rs
Generic router() builder wires all /v1/... REST routes. Handlers cover agent card, message send/stream (SSE), tasks list/get/cancel/subscribe (SSE with snapshot), and push notification config CRUD. rest_error_response and http_status_for_jsonrpc_code convert ClientError to HTTP status and JSON error bodies.
Router assembly and URI-rewriting middleware
rsworkspace/crates/a2a-nats-http/src/router.rs
build/build_with_negotiation mount JSON-RPC, agent-card, and REST routes with A2aClient state, apply the spec negotiation middleware, apply rewrite_a2a_custom_method (which rewrites /v1/tasks/{id}:{action} to /v1/tasks/{id}/{action} for cancel/subscribe), and add Tower HTTP tracing and compression layers.
Integration and unit test suite
rsworkspace/crates/a2a-nats-http/src/tests.rs
Test helpers construct mock NATS clients and Axum apps. Tests cover all JSON-RPC methods, agent card (success and 503 mapping), SSE content-type, string id forwarding, gateway routing, RuntimeError display, client_error_to_jsonrpc_code mapping, and spec negotiation header behavior.

Sequence Diagram(s)

sequenceDiagram
    participant Client as HTTP Client
    participant Router as Axum Router
    participant Negotiate as negotiate middleware
    participant Handler as handle_jsonrpc / REST handler
    participant A2aClient as A2aClient<N,J>
    participant NATS

    Client->>Router: POST / (JSON-RPC) or GET/POST /v1/...
    Router->>Router: rewrite_a2a_custom_method (path rewrite if needed)
    Router->>Negotiate: negotiate middleware
    Negotiate->>Negotiate: parse + validate a2a-version / a2a-extensions
    alt version or required extension invalid
        Negotiate-->>Client: HTTP 400 JSON-RPC error
    else negotiation ok
        Negotiate->>Handler: next.run(request) with NegotiatedSpec in extensions
        Handler->>A2aClient: method call (e.g. message_send, task_get, message_stream)
        A2aClient->>NATS: publish/subscribe
        NATS-->>A2aClient: response or event stream
        A2aClient-->>Handler: Result<T, ClientError>
        alt streaming (SSE)
            Handler-->>Client: SSE stream (typed_event_stream_to_sse → JSON-RPC envelopes)
        else one-shot
            Handler-->>Client: JSON-RPC result or error (HTTP 200)
        end
        Negotiate->>Negotiate: echo a2a-version + a2a-extensions to response headers
        Negotiate-->>Client: final response with A2A headers
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • TrogonStack/trogonai#300: The ClientError→JSON-RPC code mapping in sse.rs and handlers/mod.rs directly consumes JSON-RPC error-code constants and codec primitives introduced in this PR for a2a-nats.
  • TrogonStack/trogonai#330: The message/stream and tasks/resubscribe SSE endpoints consume TypedEventStream from a2a-nats::client::event_stream introduced in this PR.
  • TrogonStack/trogonai#357: This PR adds the server-side message_stream handler on the NATS server that produces the event stream consumed by the HTTP layer's message/stream endpoint in the current PR.

Poem

🐇 A new HTTP bridge hops into place,
JSON-RPC and REST at a NATS-powered pace.
SSE streams flow like a river of events,
Spec headers negotiated, no version dissents.
The router rewrites paths with a cunning rewrite,
And tests keep the warren both sturdy and tight! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 46.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title directly and specifically describes the main change: adding HTTP/JSON-RPC + REST + SSE binding to the a2a-nats-http crate, which is the primary objective of this PR.
Description check ✅ Passed The description clearly explains the rationale and implementation approach: providing an HTTP binding for non-NATS callers through a shared A2aClient interface, with specific coverage strategy details matching the PR's scope.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch yordis/feat-a2a-nats-http-bin

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.

Comment thread rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs Outdated
Comment thread rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs Outdated
Comment thread rsworkspace/crates/a2a-nats-http/src/rest.rs
Comment thread rsworkspace/crates/a2a-nats-http/src/rest.rs Outdated
@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown

badge

Code Coverage Summary

Details
Filename                                                                                  Stmts    Miss  Cover    Missing
--------------------------------------------------------------------------------------  -------  ------  -------  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
crates/acp-nats/src/jetstream/provision.rs                                                   52       0  100.00%
crates/acp-nats/src/jetstream/ext_policy.rs                                                  26       0  100.00%
crates/acp-nats/src/jetstream/consumers.rs                                                   91       0  100.00%
crates/acp-nats/src/jetstream/streams.rs                                                    163       4  97.55%   206-208, 218
crates/a2a-nats/src/nats/subjects/agents/card.rs                                             20       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/message_stream.rs                                   23       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/message_send.rs                                     23       0  100.00%
crates/trogon-decider-runtime/src/event/stream_event.rs                                       8       0  100.00%
crates/trogon-decider-runtime/src/event/mod.rs                                              170       0  100.00%
crates/trogon-decider-runtime/src/event/event_identity.rs                                     3       0  100.00%
crates/trogon-decider-runtime/src/event/event_id.rs                                          32       0  100.00%
crates/trogon-std/src/args.rs                                                                19       9  52.63%   11-28
crates/trogon-std/src/duration.rs                                                            42       0  100.00%
crates/trogon-std/src/json.rs                                                                30       0  100.00%
crates/trogon-std/src/secret_string.rs                                                       32       0  100.00%
crates/trogon-std/src/signal.rs                                                              26      12  53.85%   6-11, 18-25, 34
crates/trogon-std/src/uuid.rs                                                                 7       0  100.00%
crates/trogon-std/src/http.rs                                                                19       0  100.00%
crates/trogon-service-config/src/lib.rs                                                      92       0  100.00%
crates/a2a-nats/src/catalog/import_gate/principal.rs                                         14       0  100.00%
crates/a2a-nats/src/catalog/import_gate/allow_all.rs                                          2       0  100.00%
crates/a2a-nats/src/catalog/import_gate/error.rs                                              9       0  100.00%
crates/trogon-decider-runtime/src/snapshot/snapshot_type.rs                                  73       0  100.00%
crates/trogon-decider-runtime/src/snapshot/mod.rs                                             3       0  100.00%
crates/trogon-decider-runtime/src/snapshot/read_snapshot.rs                                  11       0  100.00%
crates/a2a-nats/src/push/dlq_dedup.rs                                                       120       0  100.00%
crates/a2a-nats/src/push/push_payload.rs                                                     88       0  100.00%
crates/a2a-nats/src/push/dlq.rs                                                             283       0  100.00%
crates/a2a-nats/src/push/idempotency_key_header.rs                                           43       0  100.00%
crates/a2a-nats/src/push/target.rs                                                           54       0  100.00%
crates/a2a-nats/src/push/push_notification_config.rs                                         20       0  100.00%
crates/a2a-nats/src/push/nats_push_subject.rs                                                34       0  100.00%
crates/a2a-nats/src/push/delivery_semantics.rs                                              274       0  100.00%
crates/a2a-nats/src/push/dispatch_error.rs                                                  111       0  100.00%
crates/a2a-nats/src/push/push_notification_config_id.rs                                      41       0  100.00%
crates/a2a-nats/src/push/status_transition_id.rs                                             30       0  100.00%
crates/a2a-nats/src/push/terminal_push_task_state.rs                                         64       0  100.00%
crates/a2a-nats/src/push/authentication_header.rs                                           104       0  100.00%
crates/a2a-nats/src/push/caller_id.rs                                                        91       0  100.00%
crates/a2a-nats/src/push/push_delivery_semantics_registry.rs                                 57       0  100.00%
crates/a2a-nats/src/push/push_idempotency_key.rs                                             84       0  100.00%
crates/a2a-nats/src/push/push_notification_target.rs                                        108       0  100.00%
crates/acp-nats/src/nats/subjects/stream.rs                                                  56       0  100.00%
crates/acp-nats/src/nats/subjects/mod.rs                                                    362       0  100.00%
crates/trogon-scheduler/src/processor/execution/execution_schedules/mod.rs                  270       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_config_option.rs                              15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/load.rs                                           15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_model.rs                                      15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/prompt.rs                                         15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/fork.rs                                           15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/cancel.rs                                         15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/resume.rs                                         15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/close.rs                                          15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_mode.rs                                       15       0  100.00%
crates/trogon-telemetry/src/lib.rs                                                          208      24  88.46%   56, 120, 125, 130, 140-141, 147-165, 201, 204, 207, 213
crates/trogon-telemetry/src/service_name.rs                                                  44       0  100.00%
crates/trogon-telemetry/src/trace.rs                                                         23       1  95.65%   24
crates/trogon-telemetry/src/resource_attribute.rs                                            23       0  100.00%
crates/trogon-telemetry/src/log.rs                                                           70       1  98.57%   35
crates/trogon-telemetry/src/metric.rs                                                        26       1  96.15%   30
crates/trogon-std/src/fs/mem.rs                                                             216      10  95.37%   61-63, 77-79, 132-134, 157
crates/trogon-std/src/fs/system.rs                                                           92       0  100.00%
crates/mcp-nats/src/nats/subjects/mod.rs                                                     89       0  100.00%
crates/trogon-gateway/src/source/slack/signature.rs                                          66       0  100.00%
crates/trogon-gateway/src/source/slack/server.rs                                            853       0  100.00%
crates/trogon-gateway/src/source/slack/config.rs                                             58       0  100.00%
crates/trogon-gateway/src/source/slack/socket_mode.rs                                       716       0  100.00%
crates/trogon-std/src/telemetry/http.rs                                                     217       0  100.00%
crates/a2a-nats-stdio/src/dispatch.rs                                                       839      11  98.69%   116, 119-121, 229, 232-234, 668, 1058, 1068
crates/a2a-nats-stdio/src/wire.rs                                                            57       0  100.00%
crates/a2a-nats-stdio/src/main.rs                                                             4       0  100.00%
crates/a2a-nats-stdio/src/runtime.rs                                                        102       0  100.00%
crates/a2a-nats-stdio/src/io_loop.rs                                                         84       0  100.00%
crates/a2a-nats/src/nats/subjects/subscriptions/agent_all.rs                                 20       0  100.00%
crates/a2a-nats/src/nats/subjects/subscriptions/task_one_events.rs                           20       0  100.00%
crates/a2a-nats/src/nats/subjects/subscriptions/task_all_events.rs                           17       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/fs_write_text_file.rs                           12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/session_request_permission.rs                   12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_output.rs                              12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/fs_read_text_file.rs                            12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/session_update.rs                               12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_release.rs                             12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_wait_for_exit.rs                       12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_create.rs                              12       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_kill.rs                                12       0  100.00%
crates/acp-nats/src/nats/subjects/responses/prompt_response.rs                               27       0  100.00%
crates/acp-nats/src/nats/subjects/responses/cancelled.rs                                     15       0  100.00%
crates/acp-nats/src/nats/subjects/responses/ext_ready.rs                                     12       0  100.00%
crates/acp-nats/src/nats/subjects/responses/response.rs                                      20       0  100.00%
crates/acp-nats/src/nats/subjects/responses/update.rs                                        27       0  100.00%
crates/trogon-scheduler/src/processor/execution/checkpoints/store.rs                        407      17  95.82%   102, 120, 124, 132, 224-230, 236, 279-283
crates/trogon-scheduler/src/processor/execution/checkpoints/failure.rs                       38       0  100.00%
crates/trogon-scheduler/src/processor/execution/checkpoints/codec.rs                        641      68  89.39%   134, 140, 149, 192, 208-210, 227, 244-246, 415, 417-419, 453-464, 480-481, 486-487, 493-494, 507-508, 513-514, 519-523, 529-530, 545-546, 551-552, 558-559, 566-567, 572-573, 585-589, 595-597, 612-618, 626, 631-633, 643, 648
crates/trogon-scheduler/src/processor/execution/checkpoints/record.rs                         6       0  100.00%
crates/trogonai-proto/src/codec.rs                                                           16       0  100.00%
crates/trogonai-proto/src/convert.rs                                                        120       0  100.00%
crates/acp-nats/src/nats/subjects/global/initialize.rs                                        6       0  100.00%
crates/acp-nats/src/nats/subjects/global/ext_notify.rs                                        9       0  100.00%
crates/acp-nats/src/nats/subjects/global/authenticate.rs                                      6       0  100.00%
crates/acp-nats/src/nats/subjects/global/session_list.rs                                      6       0  100.00%
crates/acp-nats/src/nats/subjects/global/session_new.rs                                       6       0  100.00%
crates/acp-nats/src/nats/subjects/global/ext.rs                                               9       0  100.00%
crates/acp-nats/src/nats/subjects/global/logout.rs                                            6       0  100.00%
crates/trogon-gateway/src/source/telegram/server.rs                                         339       0  100.00%
crates/trogon-gateway/src/source/telegram/registration.rs                                   313       0  100.00%
crates/trogon-gateway/src/source/telegram/config.rs                                          89       0  100.00%
crates/trogon-gateway/src/source/telegram/signature.rs                                       27       0  100.00%
crates/acp-nats/src/telemetry/metrics.rs                                                     53       0  100.00%
crates/a2a-nats/src/jsonrpc.rs                                                               49       0  100.00%
crates/a2a-nats/src/context_id.rs                                                            51       1  98.04%   26
crates/a2a-nats/src/config.rs                                                               318       0  100.00%
crates/a2a-nats/src/a2a_prefix.rs                                                            44       0  100.00%
crates/a2a-nats/src/req_id.rs                                                                41       0  100.00%
crates/a2a-nats/src/task_id.rs                                                               54       1  98.15%   25
crates/a2a-nats/src/constants.rs                                                             36       0  100.00%
crates/a2a-nats/src/error.rs                                                                 32       0  100.00%
crates/a2a-nats/src/gateway_ingress.rs                                                      243       0  100.00%
crates/a2a-nats/src/agent_id.rs                                                              58       0  100.00%
crates/mcp-nats/src/nats/subjects/server/call_tool.rs                                        12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/resource_list_changed.rs                            12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/resource_updated.rs                                 12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/subscribe_resource.rs                               12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/list_resources.rs                                   12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/set_logging_level.rs                                12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/tool_list_changed.rs                                12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/unsubscribe_resource.rs                             12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/get_task_result.rs                                  12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/elicitation_completed.rs                            12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/get_task.rs                                         12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/initialize.rs                                       12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/list_resource_templates.rs                          12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/complete.rs                                         12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/prompt_list_changed.rs                              12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/list_tasks.rs                                       12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/ping.rs                                              9       0  100.00%
crates/mcp-nats/src/nats/subjects/server/list_prompts.rs                                     12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/get_prompt.rs                                       12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/list_tools.rs                                       12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/cancelled.rs                                        12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/cancel_task.rs                                      12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/logging_message.rs                                  12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/progress.rs                                         12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/read_resource.rs                                    12       0  100.00%
crates/trogon-nats/src/telemetry/messaging.rs                                                82       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/prompt_wildcard.rs                            9       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_client.rs                                 9       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_agent.rs                                  9       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_agent_ext.rs                              9       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_session.rs                                9       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_session.rs                               12       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_client.rs                                15       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/global_all.rs                                 9       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_agent.rs                                 15       0  100.00%
crates/trogon-gateway/src/main.rs                                                           111       0  100.00%
crates/trogon-gateway/src/config.rs                                                        2588      42  98.38%   81, 665, 668, 828, 885, 968, 971, 974, 978, 1062-1069, 1146, 1149, 1152, 1157, 1215, 1218, 1221, 1300, 1303, 1306, 1310, 1374, 1377, 1380, 1443, 1446, 1449, 1454, 1529, 1532, 1535, 1540, 1598, 1601, 1604, 1817-1819
crates/trogon-gateway/src/source_status.rs                                                   24       0  100.00%
crates/trogon-gateway/src/http.rs                                                           145       0  100.00%
crates/trogon-gateway/src/source_plugin.rs                                                  268       3  98.88%   82, 139-140
crates/trogon-gateway/src/streams.rs                                                        129       0  100.00%
crates/trogon-gateway/src/source_integration_id.rs                                           55       2  96.36%   58, 60
crates/a2a-nats-server/src/noop_handler.rs                                                  183       0  100.00%
crates/a2a-nats-server/src/runtime.rs                                                        98       0  100.00%
crates/a2a-nats-server/src/main.rs                                                            4       0  100.00%
crates/a2a-nats/src/nats/subjects/stream.rs                                                  54       0  100.00%
crates/a2a-nats/src/push/dispatcher/composite.rs                                            154       0  100.00%
crates/a2a-nats/src/push/dispatcher/http.rs                                                 141       0  100.00%
crates/a2a-nats/src/push/dispatcher/mod.rs                                                   88       0  100.00%
crates/a2a-nats/src/push/dispatcher/nats.rs                                                 183       0  100.00%
crates/a2a-nats/src/push/dispatcher/jetstream.rs                                            226       0  100.00%
crates/a2a-nats-http/src/headers.rs                                                         167       6  96.41%   94, 103, 159, 220-222
crates/a2a-nats-http/src/rest.rs                                                            316     287  9.18%    63-415, 420-425, 427-428, 432-437
crates/a2a-nats-http/src/router.rs                                                           55      14  74.55%   59-63, 69-79
crates/a2a-nats-http/src/sse.rs                                                              44      28  36.36%   15-51, 61-68
crates/a2a-nats-http/src/main.rs                                                              4       0  100.00%
crates/a2a-nats-http/src/runtime.rs                                                          30      26  13.33%   36-45, 51-147
crates/mcp-nats/src/jsonrpc.rs                                                               22       0  100.00%
crates/mcp-nats/src/client.rs                                                                31       0  100.00%
crates/mcp-nats/src/mcp_prefix.rs                                                            34       0  100.00%
crates/mcp-nats/src/server.rs                                                                31       0  100.00%
crates/mcp-nats/src/transport.rs                                                            698       0  100.00%
crates/mcp-nats/src/mcp_peer_id.rs                                                           31       0  100.00%
crates/mcp-nats/src/config.rs                                                               110       0  100.00%
crates/mcp-nats/src/nats/subjects/client/cancelled.rs                                        12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/progress.rs                                         12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/ping.rs                                              9       0  100.00%
crates/mcp-nats/src/nats/subjects/client/list_roots.rs                                       12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/create_message.rs                                   12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/roots_list_changed.rs                               12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/create_elicitation.rs                               12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/initialized.rs                                      12       0  100.00%
crates/trogon-decider-runtime/src/headers/header_name.rs                                     28       0  100.00%
crates/trogon-decider-runtime/src/headers/header_value.rs                                    34       0  100.00%
crates/trogon-decider-runtime/src/headers/mod.rs                                             74       0  100.00%
crates/trogon-decider-runtime/src/headers/header_map.rs                                      54       3  94.44%   20-22
crates/a2a-nats/src/catalog/watch.rs                                                         99       0  100.00%
crates/a2a-nats/src/catalog/store.rs                                                        382       0  100.00%
crates/a2a-nats/src/catalog/nats_kv.rs                                                       19       0  100.00%
crates/a2a-nats/src/catalog/registrar.rs                                                    211       0  100.00%
crates/trogon-gateway/src/source/github/config.rs                                            17       0  100.00%
crates/trogon-gateway/src/source/github/signature.rs                                         50       0  100.00%
crates/trogon-gateway/src/source/github/server.rs                                           328       0  100.00%
crates/trogon-nats/src/connect.rs                                                            82       6  92.68%   41-46
crates/trogon-nats/src/nats_token.rs                                                        157       0  100.00%
crates/trogon-nats/src/client.rs                                                             22      22  0.00%    50-86
crates/trogon-nats/src/server_info.rs                                                        76       3  96.05%   19-21
crates/trogon-nats/src/auth.rs                                                              114       0  100.00%
crates/trogon-nats/src/messaging.rs                                                         534       2  99.63%   144, 154
crates/trogon-nats/src/mocks.rs                                                             314       0  100.00%
crates/trogon-nats/src/subject_token_violation.rs                                            11       0  100.00%
crates/trogon-nats/src/token.rs                                                               6       0  100.00%
crates/trogon-scheduler/src/commands/record_schedule_occurrence.rs                          348       1  99.71%   182
crates/trogon-scheduler/src/commands/pause_schedule.rs                                      174       0  100.00%
crates/trogon-scheduler/src/commands/create_schedule.rs                                     199       0  100.00%
crates/trogon-scheduler/src/commands/state.rs                                               472       0  100.00%
crates/trogon-scheduler/src/commands/snapshot.rs                                              4       0  100.00%
crates/trogon-scheduler/src/commands/resume_schedule.rs                                     207       0  100.00%
crates/trogon-scheduler/src/commands/schedule_next_occurrence.rs                            355       0  100.00%
crates/trogon-scheduler/src/commands/remove_schedule.rs                                     171       0  100.00%
crates/trogon-gateway/src/source/microsoft_graph/client_state.rs                             30       0  100.00%
crates/trogon-gateway/src/source/microsoft_graph/server.rs                                  325       0  100.00%
crates/a2a-nats/src/client/unary.rs                                                         187       0  100.00%
crates/a2a-nats/src/client/event_stream.rs                                                  247       0  100.00%
crates/a2a-nats/src/client/error.rs                                                         161       2  98.76%   135, 144
crates/a2a-nats/src/client/resubscribe.rs                                                    69       0  100.00%
crates/a2a-nats/src/client/handle.rs                                                        934       0  100.00%
crates/a2a-nats/src/client/streaming.rs                                                     236       0  100.00%
crates/a2a-nats/src/client/gateway_headers.rs                                                68       0  100.00%
crates/a2a-nats/src/client/wire.rs                                                           38       0  100.00%
crates/trogonai-proto/src/scheduler/schedules/codec.rs                                      377       0  100.00%
crates/a2a-nats-http/src/handlers/mod.rs                                                    185      68  63.24%   52-57, 64, 68, 74, 88-91, 95, 111, 115, 121, 125, 143-176, 182, 185, 190-196, 200-206, 210-216, 220-221
crates/mcp-nats/src/nats/subjects/subscriptions/one_client.rs                                 9       0  100.00%
crates/mcp-nats/src/nats/subjects/subscriptions/one_server.rs                                 9       0  100.00%
crates/mcp-nats/src/nats/subjects/subscriptions/all_client.rs                                 6       0  100.00%
crates/mcp-nats/src/nats/subjects/subscriptions/all_server.rs                                 6       0  100.00%
crates/trogon-gateway/src/source/discord/gateway.rs                                         426       1  99.77%   137
crates/trogon-gateway/src/source/discord/config.rs                                          105       0  100.00%
crates/acp-nats-server/src/main.rs                                                          900      10  98.89%   109, 243-250, 450
crates/acp-nats-server/src/connection.rs                                                    182      36  80.22%   95-102, 107-122, 138, 140-141, 146, 155-156, 161, 165, 169, 172, 180, 184, 187, 190-194, 232
crates/acp-nats-server/src/acp_connection_id.rs                                              37       0  100.00%
crates/acp-nats-server/src/config.rs                                                        126       3  97.62%   41-43
crates/acp-nats-server/src/transport.rs                                                    1915     106  94.46%   253, 512, 530, 557, 611, 616, 636, 648, 767, 790-792, 844, 861-864, 960-963, 1038, 1041, 1044, 1053, 1057, 1060, 1063-1066, 1085, 1118-1121, 1129-1134, 1146-1150, 1154-1163, 1175-1176, 1194-1195, 1205, 1221-1225, 1253-1259, 1279-1281, 1286-1290, 1293-1298, 1315, 1317-1318, 1400-1401, 1413-1414, 1434-1435, 1487-1503, 2208, 2252, 2305, 2361, 2374
crates/trogon-gateway/src/source/incidentio/signature.rs                                    206       0  100.00%
crates/trogon-gateway/src/source/incidentio/server.rs                                       343       0  100.00%
crates/trogon-gateway/src/source/incidentio/incidentio_event_type.rs                         62       0  100.00%
crates/trogon-gateway/src/source/incidentio/config.rs                                        16       0  100.00%
crates/trogon-gateway/src/source/incidentio/incidentio_signing_secret.rs                     56       0  100.00%
crates/a2a-nats/src/audit/emitter.rs                                                        160       0  100.00%
crates/a2a-nats/src/audit/envelope.rs                                                       204       0  100.00%
crates/a2a-nats/src/audit/task_lifecycle.rs                                                  17       0  100.00%
crates/mcp-nats/src/telemetry/transport.rs                                                    6       0  100.00%
crates/a2a-pack/src/agent_card_schema.rs                                                     81       0  100.00%
crates/a2a-pack/src/agent_card_read.rs                                                       66       0  100.00%
crates/trogon-decider-runtime/src/event/codec/event_decode.rs                                29       0  100.00%
crates/trogon-decider-runtime/src/event/codec/event_payload_error.rs                         25       0  100.00%
crates/trogon-decider/src/act.rs                                                             62       0  100.00%
crates/trogon-decider/src/decision.rs                                                        27       0  100.00%
crates/trogon-decider/src/events.rs                                                          49       0  100.00%
crates/trogon-decider/src/lib.rs                                                            138       0  100.00%
crates/trogon-decider/src/testing.rs                                                        675       0  100.00%
crates/trogon-scheduler/src/processor/execution/reconciliation/go_duration.rs                59       0  100.00%
crates/trogon-scheduler/src/processor/execution/reconciliation/request.rs                   542       2  99.63%   285, 290
crates/trogon-scheduler/src/processor/execution/reconciliation/reconcile.rs                 808      13  98.39%   251-260, 325-327
crates/trogon-scheduler/src/processor/execution/reconciliation/recorded_events.rs           690      16  97.68%   200-205, 242, 250, 271, 291, 297, 303, 336, 346, 364, 448, 533, 541, 818, 1034
crates/trogon-scheduler/src/processor/execution/reconciliation/rrule_wakeup_payload.rs       35       0  100.00%
crates/trogon-scheduler/src/processor/execution/reconciliation/schedule_subject.rs           59       3  94.92%   60-62
crates/trogon-scheduler/src/processor/execution/reconciliation/schedule_key.rs               67       0  100.00%
crates/trogon-std/src/dirs/fixed.rs                                                          80       0  100.00%
crates/trogon-std/src/dirs/system.rs                                                         71       0  100.00%
crates/a2a-nats/src/jetstream/provision.rs                                                   62       0  100.00%
crates/a2a-nats/src/jetstream/streams.rs                                                     73       0  100.00%
crates/a2a-nats/src/jetstream/consumers.rs                                                  112       0  100.00%
crates/a2a-nats/src/jetstream/stream_options.rs                                             114       0  100.00%
crates/a2a-nats/src/nats/subjects/tasks/events.rs                                            31       0  100.00%
crates/trogon-decider-runtime/src/execution.rs                                             1432       0  100.00%
crates/mcp-nats/src/nats/mod.rs                                                              99       0  100.00%
crates/mcp-nats/src/nats/parsing.rs                                                         191       0  100.00%
crates/trogon-std/src/time/system.rs                                                         31       0  100.00%
crates/trogon-std/src/time/mock.rs                                                          125       0  100.00%
crates/acp-nats-stdio/src/main.rs                                                           135      25  81.48%   67, 115-122, 128-130, 147, 176-195
crates/acp-nats-stdio/src/config.rs                                                          66       0  100.00%
crates/trogon-gateway/src/source/linear/server.rs                                           386       0  100.00%
crates/trogon-gateway/src/source/linear/signature.rs                                         54       1  98.15%   16
crates/trogon-gateway/src/source/linear/config.rs                                            17       0  100.00%
crates/a2a-nats/src/catalog/import_gate/spicedb/mod.rs                                      107       0  100.00%
crates/a2a-nats/src/catalog/import_gate/spicedb/cache.rs                                     36       0  100.00%
crates/a2a-nats/src/catalog/import_gate/spicedb/config.rs                                    70       0  100.00%
crates/trogon-scheduler/src/processor/execution/wakeup.rs                                   353       7  98.02%   83-85, 127, 400, 416, 585
crates/acp-nats-agent/src/connection.rs                                                    1252       1  99.92%   583
crates/trogon-decider-runtime/src/snapshot/codec/snapshot_payload_decode.rs                   3       0  100.00%
crates/trogon-decider-runtime/src/snapshot/codec/encoded_snapshot.rs                        117       0  100.00%
crates/trogon-decider-runtime/src/snapshot/codec/snapshot_decode_error.rs                    49       0  100.00%
crates/trogon-decider-runtime/src/snapshot/codec/snapshot_encode_error.rs                    36       0  100.00%
crates/trogon-decider-runtime/src/snapshot/codec/snapshot_envelope_decode_error.rs           28       0  100.00%
crates/trogon-decider-runtime/src/snapshot/codec/snapshot_envelope_encode_error.rs           14       0  100.00%
crates/trogon-decider-runtime/src/stream/append_stream.rs                                     5       0  100.00%
crates/trogon-decider-runtime/src/stream/mod.rs                                              38       0  100.00%
crates/trogon-decider-runtime/src/stream/read_stream.rs                                       7       0  100.00%
crates/trogon-decider-runtime/src/stream/stream_position.rs                                  26       0  100.00%
crates/trogon-gateway/src/source/twitter/config.rs                                           17       0  100.00%
crates/trogon-gateway/src/source/twitter/signature.rs                                        58       0  100.00%
crates/trogon-gateway/src/source/twitter/server.rs                                          524       0  100.00%
crates/trogon-nats/src/lease/ttl.rs                                                          68       0  100.00%
crates/trogon-nats/src/lease/acquire.rs                                                       5       5  0.00%    9-14
crates/trogon-nats/src/lease/lease_bucket.rs                                                 19       0  100.00%
crates/trogon-nats/src/lease/lease_timing.rs                                                 15       0  100.00%
crates/trogon-nats/src/lease/mod.rs                                                         523      13  97.51%   113-126
crates/trogon-nats/src/lease/nats_kv_lease_config.rs                                         26       0  100.00%
crates/trogon-nats/src/lease/lease_key.rs                                                    19       0  100.00%
crates/trogon-nats/src/lease/release.rs                                                       5       5  0.00%    8-12
crates/trogon-nats/src/lease/renew.rs                                                       246      19  92.28%   23-29, 48-59
crates/trogon-nats/src/lease/renew_interval.rs                                               57       0  100.00%
crates/trogon-nats/src/lease/provision.rs                                                   187      10  94.65%   82-92
crates/trogon-scheduler/src/commands/domain/schedule_id.rs                                   81       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule_event_delivery.rs                       25       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule.rs                                     638       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule_event_sampling_source.rs                20       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule_event_schedule.rs                       83       0  100.00%
crates/trogon-scheduler/src/commands/domain/recurrence.rs                                   179       1  99.44%   99
crates/trogon-scheduler/src/commands/domain/message.rs                                      219       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule_occurrence_sequence.rs                  30       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule_event_status.rs                         10       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/tasks/cancel.rs                                     23       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/tasks/get.rs                                        23       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/tasks/list.rs                                       23       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/tasks/resubscribe.rs                                23       0  100.00%
crates/acp-nats/src/client/ext.rs                                                           296       8  97.30%   146-155, 172-181
crates/acp-nats/src/client/mod.rs                                                          2851       0  100.00%
crates/acp-nats/src/client/ext_session_prompt_response.rs                                   135       0  100.00%
crates/acp-nats/src/client/terminal_kill.rs                                                 278       0  100.00%
crates/acp-nats/src/client/request_permission.rs                                            298       0  100.00%
crates/acp-nats/src/client/fs_write_text_file.rs                                            408       0  100.00%
crates/acp-nats/src/client/fs_read_text_file.rs                                             346       0  100.00%
crates/acp-nats/src/client/rpc_reply.rs                                                      64       0  100.00%
crates/acp-nats/src/client/terminal_release.rs                                              335       0  100.00%
crates/acp-nats/src/client/terminal_create.rs                                               264       0  100.00%
crates/acp-nats/src/client/session_update.rs                                                 55       0  100.00%
crates/acp-nats/src/client/terminal_output.rs                                               206       0  100.00%
crates/acp-nats/src/client/terminal_wait_for_exit.rs                                        364       0  100.00%
crates/trogon-gateway/src/source/notion/verification_token.rs                               220       0  100.00%
crates/trogon-gateway/src/source/notion/notion_event_type.rs                                 46       3  93.48%   50-52
crates/trogon-gateway/src/source/notion/notion_verification_token.rs                         17       0  100.00%
crates/trogon-gateway/src/source/notion/server.rs                                           310       4  98.71%   115-116, 135-136
crates/trogon-gateway/src/source/notion/signature.rs                                         45       0  100.00%
crates/trogon-gateway/src/source/standard_webhooks.rs                                       138       0  100.00%
crates/trogon-nats/src/jetstream/mocks.rs                                                  1686       1  99.94%   505
crates/trogon-nats/src/jetstream/publish.rs                                                  64       0  100.00%
crates/trogon-nats/src/jetstream/claim_check.rs                                             393      10  97.46%   45-47, 99-105
crates/trogon-nats/src/jetstream/create_conflicts.rs                                         24       0  100.00%
crates/trogon-nats/src/jetstream/traits.rs                                                   46      40  13.04%   181-251
crates/trogon-nats/src/jetstream/stream_max_age.rs                                           18       0  100.00%
crates/trogon-scheduler/src/telemetry/metrics.rs                                             52       0  100.00%
crates/trogon-scheduler/src/telemetry/trace.rs                                               41       0  100.00%
crates/a2a-identity-types/src/principal.rs                                                   40       0  100.00%
crates/a2a-identity-types/src/error.rs                                                       20       0  100.00%
crates/a2a-identity-types/src/caller.rs                                                      61       0  100.00%
crates/a2a-identity-types/src/jwt.rs                                                        156       0  100.00%
crates/acp-nats/src/nats/extensions.rs                                                        3       0  100.00%
crates/acp-nats/src/nats/parsing.rs                                                         278       1  99.64%   151
crates/acp-nats/src/nats/mod.rs                                                              23       0  100.00%
crates/trogon-scheduler/src/processor/execution/worker/testkit.rs                           330       4  98.79%   459, 490-491, 496
crates/trogon-scheduler/src/processor/execution/worker/processor.rs                        1356      12  99.12%   279, 339, 437-438, 444, 499-501, 533-536
crates/trogon-scheduler/src/processor/execution/worker/dispatcher.rs                       1095       1  99.91%   200
crates/trogon-scheduler/src/processor/execution/worker/consumer.rs                          203       0  100.00%
crates/acp-nats/src/agent/resume_session.rs                                                  90       0  100.00%
crates/acp-nats/src/agent/ext_notification.rs                                                82       0  100.00%
crates/acp-nats/src/agent/new_session.rs                                                     82       0  100.00%
crates/acp-nats/src/agent/set_session_model.rs                                               67       0  100.00%
crates/acp-nats/src/agent/authenticate.rs                                                    49       0  100.00%
crates/acp-nats/src/agent/set_session_config_option.rs                                       67       0  100.00%
crates/acp-nats/src/agent/close_session.rs                                                   63       0  100.00%
crates/acp-nats/src/agent/logout.rs                                                          49       0  100.00%
crates/acp-nats/src/agent/fork_session.rs                                                    94       0  100.00%
crates/acp-nats/src/agent/test_support.rs                                                   267       0  100.00%
crates/acp-nats/src/agent/load_session.rs                                                    89       0  100.00%
crates/acp-nats/src/agent/set_session_mode.rs                                                67       0  100.00%
crates/acp-nats/src/agent/bridge.rs                                                         123       4  96.75%   108-111
crates/acp-nats/src/agent/initialize.rs                                                      79       0  100.00%
crates/acp-nats/src/agent/js_request.rs                                                     283       0  100.00%
crates/acp-nats/src/agent/cancel.rs                                                         101       0  100.00%
crates/acp-nats/src/agent/ext_method.rs                                                      82       0  100.00%
crates/acp-nats/src/agent/list_sessions.rs                                                   47       0  100.00%
crates/acp-nats/src/agent/mod.rs                                                             65       0  100.00%
crates/acp-nats/src/agent/prompt.rs                                                         471       0  100.00%
crates/trogon-decider-nats/src/stream_store.rs                                              659      18  97.27%   70-72, 245, 273-274, 277, 293-297, 464-465, 506, 519-523
crates/trogon-decider-nats/src/snapshot_store.rs                                            861      27  96.86%   208-210, 248-250, 361-367, 449, 585, 590, 686-688, 694-696, 730-731, 741-742, 761, 789-790
crates/trogon-decider-nats/src/store.rs                                                     128      45  64.84%   50-54, 101-167
crates/mcp-nats-stdio/src/config.rs                                                         149       0  100.00%
crates/mcp-nats-stdio/src/main.rs                                                           204       0  100.00%
crates/trogon-std/src/env/in_memory.rs                                                       73       0  100.00%
crates/trogon-std/src/env/system.rs                                                          17       0  100.00%
crates/mcp-nats-server/src/main.rs                                                          357     127  64.43%   151-168, 204-206, 216, 222-223, 230-233, 257-259, 263-272, 294-307, 312-360, 491, 494, 502-544
crates/mcp-nats-server/src/allowed_host.rs                                                   88       0  100.00%
crates/mcp-nats-server/src/config.rs                                                        257       0  100.00%
crates/acp-nats/src/session_id.rs                                                            68       0  100.00%
crates/acp-nats/src/acp_prefix.rs                                                            46       0  100.00%
crates/acp-nats/src/client_proxy.rs                                                         181       0  100.00%
crates/acp-nats/src/config.rs                                                               203       0  100.00%
crates/acp-nats/src/jsonrpc.rs                                                                6       0  100.00%
crates/acp-nats/src/ext_method_name.rs                                                       65       0  100.00%
crates/acp-nats/src/pending_prompt_waiters.rs                                               131       0  100.00%
crates/acp-nats/src/lib.rs                                                                   69       0  100.00%
crates/acp-nats/src/in_flight_slot_guard.rs                                                  32       0  100.00%
crates/acp-nats/src/error.rs                                                                 82       0  100.00%
crates/acp-nats/src/req_id.rs                                                                39       0  100.00%
crates/trogon-gateway/src/source/gitlab/gitlab_signing_token.rs                              62       0  100.00%
crates/trogon-gateway/src/source/gitlab/signature.rs                                        165       0  100.00%
crates/trogon-gateway/src/source/gitlab/server.rs                                           460       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/push/set.rs                                         20       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/push/delete.rs                                      23       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/push/get.rs                                         20       0  100.00%
crates/a2a-nats/src/nats/subjects/agents/push/list.rs                                        23       0  100.00%
crates/a2a-nats/src/server/tasks_resubscribe.rs                                             103       0  100.00%
crates/a2a-nats/src/server/push_get.rs                                                      106       0  100.00%
crates/a2a-nats/src/server/tasks_list.rs                                                     97       0  100.00%
crates/a2a-nats/src/server/dispatch.rs                                                      113       0  100.00%
crates/a2a-nats/src/server/message_stream.rs                                                265       0  100.00%
crates/a2a-nats/src/server/push_delete.rs                                                    97       0  100.00%
crates/a2a-nats/src/server/push_list.rs                                                     104       0  100.00%
crates/a2a-nats/src/server/tasks_cancel.rs                                                  103       0  100.00%
crates/a2a-nats/src/server/bridge.rs                                                        282       0  100.00%
crates/a2a-nats/src/server/message_send.rs                                                  114       0  100.00%
crates/a2a-nats/src/server/test_support.rs                                                   41       0  100.00%
crates/a2a-nats/src/server/agent_card.rs                                                    191       0  100.00%
crates/a2a-nats/src/server/tasks_get.rs                                                     103       0  100.00%
crates/a2a-nats/src/server/wire.rs                                                          120       0  100.00%
crates/a2a-nats/src/server/push_set.rs                                                       99       0  100.00%
crates/a2a-nats/src/server/handler.rs                                                        70       0  100.00%
crates/trogon-gateway/src/source/sentry/server.rs                                           308       0  100.00%
crates/trogon-gateway/src/source/sentry/signature.rs                                         42       0  100.00%
crates/trogon-gateway/src/source/sentry/sentry_client_secret.rs                              17       0  100.00%
TOTAL                                                                                     62800    1257  98.00%

Diff against main

Filename                                    Stmts    Miss  Cover
----------------------------------------  -------  ------  --------
crates/a2a-nats-http/src/headers.rs          +167      +6  +96.41%
crates/a2a-nats-http/src/rest.rs             +316    +287  +9.18%
crates/a2a-nats-http/src/router.rs            +55     +14  +74.55%
crates/a2a-nats-http/src/sse.rs               +44     +28  +36.36%
crates/a2a-nats-http/src/main.rs               +4       0  +100.00%
crates/a2a-nats-http/src/runtime.rs           +30     +26  +13.33%
crates/a2a-nats-http/src/handlers/mod.rs     +185     +68  +63.24%
TOTAL                                        +801    +429  -0.67%

Results for commit: cbdabe0

Minimum allowed coverage is 95%

♻️ This comment has been updated with latest results

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 6

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@rsworkspace/crates/a2a-nats-http/README.md`:
- Around line 1-3: The README heading uses the incorrect crate name
"a2a-nats-server" when it should be "a2a-nats-http" to match the actual binary
name. Update the heading from "a2a-nats-server" to "a2a-nats-http" on the first
line, and also review lines 10-12 for any other references to "a2a-nats-server"
that need to be corrected to the proper crate/binary name "a2a-nats-http" to
ensure the documented startup path and examples are accurate.

In `@rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs`:
- Around line 45-48: Add validation for the jsonrpc version field before
dispatching the method. After extracting id and params from the envelope but
before the match statement that dispatches on envelope.method, check that
envelope.jsonrpc exists and equals "2.0". If the jsonrpc field is missing or
does not match "2.0", return a JSON-RPC invalid-request error response with the
appropriate error code and message instead of proceeding to the method dispatch.

In `@rsworkspace/crates/a2a-nats-http/src/headers.rs`:
- Around line 88-100: The code does not validate that extracted URIs are
non-empty after parsing, which allows malformed headers like "?" or ";q=0" to
create invalid extension entries. In both branches of the condition (the
strip_prefix('?') case and the split_once(';') case), after trimming the URI
value, add a check to ensure the resulting string is not empty. If the URI is
empty, skip the parse and return None instead of creating the Self struct. This
validation should occur before constructing the Self object in both the first
branch (around line 90) and second branch (around line 99).

In `@rsworkspace/crates/a2a-nats-http/src/rest.rs`:
- Around line 270-287: The post_push_set function extracts the path id parameter
but discards it with the underscore prefix, allowing the untrusted JSON request
body to entirely control the write target. Remove the underscore from the _id
parameter in the Path(Path(_id)) binding, then validate that the task id from
the path matches the task id in the TaskPushNotificationConfig request body (or
overwrite the request body's task id with the path id) before calling
client.push_set to ensure the path constraint is enforced according to the
untrusted input boundary type guidelines.

In `@rsworkspace/crates/a2a-nats-http/src/runtime.rs`:
- Line 23: Replace the `InvalidGatewayCallerJwt(String)` error variant with a
typed variant that wraps the original JWT error directly (e.g., a struct field
containing the actual error type returned by JWT parsing/validation operations).
Update all locations where this variant is constructed (including lines 39-40
and 113-120) to pass the original error object instead of converting it to a
String. This preserves error context and enables proper source chaining for
debugging.

In `@rsworkspace/crates/a2a-nats-http/src/sse.rs`:
- Around line 21-27: The error handling in the unwrap_or_else closure returns
JSON-RPC error code -32700 (Parse error) with id set to null, but since this is
a server-side serialization failure (not a client parse error), it should return
error code -32603 (Internal error) instead. Additionally, preserve the original
request id from the envelope for proper request correlation. Modify the
serde_json::json! block to change the error code from -32700 to -32603 and set
the id field to the actual id from the envelope instead of null.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 3ca234df-968a-41e1-a429-2430b5433424

📥 Commits

Reviewing files that changed from the base of the PR and between 883d110 and 2ae3c49.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (11)
  • rsworkspace/crates/a2a-nats-http/Cargo.toml
  • rsworkspace/crates/a2a-nats-http/README.md
  • rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs
  • rsworkspace/crates/a2a-nats-http/src/headers.rs
  • rsworkspace/crates/a2a-nats-http/src/lib.rs
  • rsworkspace/crates/a2a-nats-http/src/main.rs
  • rsworkspace/crates/a2a-nats-http/src/rest.rs
  • rsworkspace/crates/a2a-nats-http/src/router.rs
  • rsworkspace/crates/a2a-nats-http/src/runtime.rs
  • rsworkspace/crates/a2a-nats-http/src/sse.rs
  • rsworkspace/crates/a2a-nats-http/src/tests.rs

Comment thread rsworkspace/crates/a2a-nats-http/README.md Outdated
Comment thread rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs
Comment thread rsworkspace/crates/a2a-nats-http/src/headers.rs
Comment thread rsworkspace/crates/a2a-nats-http/src/rest.rs
Comment thread rsworkspace/crates/a2a-nats-http/src/runtime.rs Outdated
Comment thread rsworkspace/crates/a2a-nats-http/src/sse.rs
… headers, runtime, sse

- handlers: read top-level lastSeq for tasks/resubscribe so the http and
  stdio binaries stay wire-compatible on the resume cursor
- handlers: reject envelopes without jsonrpc='2.0' before dispatch so the
  bridge can't front another protocol's calls
- handlers: agent-card failures now return a JSON error envelope so JSON
  clients can parse them, matching REST get_card and the success path
- rest: post_push_set now binds writes to the path task id, rejecting a
  mismatched body taskId instead of letting untrusted JSON pick the target
- rest: drop the spurious _keep_delete_chain noop route — it was router
  scaffolding, not an A2A operation
- headers: skip extension tokens whose uri ends up empty after optional
  marker stripping (a bare '?' or ';q=0' must not negotiate implicitly)
- runtime: replace InvalidGatewayCallerJwt(String) with InvalidGatewayCallerJwt(JwtError)
  so source chaining works and structured context isn't lost to format!
- sse: server-side envelope serialization failure is -32603 Internal, not
  -32700 Parse error, and echoes the original id for stream correlation
- README: crate/binary name reads a2a-nats-http, not a2a-nats-server

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Comment thread rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs Outdated
The handler was discarding the unary SendMessageResponse and only
forwarding JetStream events, so HTTP callers never received the task
handle that anchors subsequent notifications — out of sync with
tasks/resubscribe and the stdio bridge, which both emit a bootstrap
result before the stream.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Comment thread rsworkspace/crates/a2a-nats-http/src/rest.rs Outdated
Comment thread rsworkspace/crates/a2a-nats-http/src/sse.rs
Two follow-on streaming inconsistencies:

- REST subscribe was emitting the snapshot as a bare {result} frame
  while later JetStream frames carried the full jsonrpc envelope, so a
  single response stream mixed two wire formats.
- JetStream updates on message/stream and tasks/resubscribe rode as
  repeated 'result' messages tagged with the request id. The stdio
  bridge sends JSON-RPC notifications with method set to the originating
  stream method so callers can route incremental events without
  matching on id; HTTP now does the same.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>

@cursor cursor Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cursor Bugbot has reviewed your changes using default effort and found 2 potential issues.

Fix All in Cursor

❌ Bugbot Autofix is OFF. To automatically fix reported issues with cloud agents, have a team admin enable autofix in the Cursor dashboard.

Reviewed by Cursor Bugbot for commit d8890b2. Configure here.

Comment thread rsworkspace/crates/a2a-nats-http/src/handlers/mod.rs Outdated
Comment thread rsworkspace/crates/a2a-nats-http/src/rest.rs Outdated
…to REST JSON shape

The well-known agent-card route was special-casing AGENT_UNAVAILABLE
and bucketing every other ClientError as HTTP 500 while /v1/card
mapped extended-card-not-configured to 404, invalid-agent-response to
502, etc. — the same protocol failure returned different HTTP status
codes depending on which route the client hit. Both now share the REST
status table so the response contract is route-independent.

The /v1/tasks/{id}/subscribe route also returned a bare text body when
A2aTaskId::new rejected the path id; sibling REST routes return the
{"error":{code,message}} JSON shape, so clients couldn't parse this
one failure uniformly. Subscribe now matches the rest.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis yordis added the rust:coverage-baseline-reset Relax Rust coverage gate to establish a new baseline label Jun 21, 2026
@yordis yordis merged commit e2d0ce3 into main Jun 21, 2026
9 of 10 checks passed
@yordis yordis deleted the yordis/feat-a2a-nats-http-bin branch June 21, 2026 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

rust:coverage-baseline-reset Relax Rust coverage gate to establish a new baseline

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant