Skip to content

feat(a2a-auth-callout): wire production main and add docker-gated integration test - #377

Merged
yordis merged 4 commits into
mainfrom
yordis/feat-a2a-auth-callout-bin
Jun 21, 2026
Merged

feat(a2a-auth-callout): wire production main and add docker-gated integration test#377
yordis merged 4 commits into
mainfrom
yordis/feat-a2a-auth-callout-bin

Conversation

@yordis

@yordis yordis commented Jun 21, 2026

Copy link
Copy Markdown
Member
  • Library has been complete since the dispatcher/subscriber slices landed, but the binary was still a stub — operators had no production entrypoint that loaded credential verifiers from the documented environment contract.
  • The NATS-server-in-Docker contract was unverified end-to-end against a real auth callout flow; the gated integration test pins it so regressions surface locally where Docker is available without blocking CI.

…egration test

The library has been complete since the dispatcher/subscriber slices
landed but the binary was still a stub, so operators had no production
entrypoint that loaded credential verifiers from the documented
environment contract and the NATS-server-in-Docker contract was
unverified end-to-end against a real auth callout flow.

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

cursor Bot commented Jun 21, 2026

Copy link
Copy Markdown

PR Summary

High Risk
Introduces the live NATS auth-callout process that mints user JWTs and ACLs from OIDC/mTLS; misconfiguration or verifier gaps would deny or incorrectly admit connections.

Overview
Replaces the stub binary with a production a2a-auth-callout entrypoint that boots from the documented env contract: signing keys, tenant allowlist, NKey/XKey wire codec, optional OIDC (JWKS discovery) and mTLS trust anchors, NATS connect (optional user/password), then runs Subscriber on $SYS.REQ.USER.AUTH. It fails fast if no credential verifiers are configured and exits non-zero when the subscription ends so orchestrators restart the pod. tracing-subscriber is added for structured logs.

The crate re-exports Subscriber, DenialPublisherConfig, and AuthCalloutWireCodec for operators and tests.

Adds Docker-gated (#[ignore]) integration tests against nats-server 2.14 via testcontainers, exercising OIDC bearer, mTLS, and API-key callout paths: minted NATS user JWT shape, tenant ACL, stable caller_id, and successful client connect via with_auth_callback. The harness documents a TODO to pin the server request-signing NKey (vs auth_callout.issuer in config).

Reviewed by Cursor Bugbot for commit b6920df. 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 31 minutes and 37 seconds. 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: c473cbf4-23e9-41ba-9e65-b21a36e3ca88

📥 Commits

Reviewing files that changed from the base of the PR and between 6be34be and b6920df.

📒 Files selected for processing (2)
  • rsworkspace/crates/a2a-auth-callout/src/main.rs
  • rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs

Walkthrough

Replaces stub main.rs with a production Tokio entrypoint that reads environment configuration, builds optional OIDC and mTLS verifiers, constructs AuthCalloutWireCodec, connects to NATS, and runs a Subscriber/CalloutDispatcher. Adds DenialPublisherConfig, Subscriber, and AuthCalloutWireCodec as public re-exports. Adds tracing-subscriber and testcontainers dependencies. Adds a 721-line integration test suite covering OIDC, mTLS, and API key callout flows against a real nats-server container.

Changes

Auth Callout Production Wiring and Integration Tests

Layer / File(s) Summary
Dependencies and public re-exports
rsworkspace/crates/a2a-auth-callout/Cargo.toml, rsworkspace/crates/a2a-auth-callout/src/lib.rs
Pins tracing-subscriber (=0.3.23, fmt/env-filter) and testcontainers (=0.27.0, dev) in Cargo.toml; publicly re-exports DenialPublisherConfig, Subscriber, and AuthCalloutWireCodec from lib.rs.
Production main entrypoint
rsworkspace/crates/a2a-auth-callout/src/main.rs
Removes coverage stubs; adds #[tokio::main] async fn main() that reads env vars (NATS_URL, signing key source, allowed accounts, JWT TTL, NKey/Xkey), constructs optional OIDC and mTLS verifiers, builds AuthCalloutWireCodec and account resolver, connects to NATS, and runs Subscriber with CalloutDispatcher. Process exits on config or runtime errors.
Integration test scaffolding and NatsCalloutStack
rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs (lines 1–265, 426–471)
Defines CapturingDispatcher adapter with in-memory JWT/error capture, NatsCalloutStack that writes temp nats.conf, starts nats-server container via testcontainers, wires the auth-callout subscriber loop, and provides async retry helpers for repeated connection attempts.
OIDC key material, NATS config, mTLS fixtures, and JWT helpers
rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs (lines 267–424, 548–619)
Builds nats.conf strings with optional TLS blocks; generates RSA JWK pairs and mocked OIDC/JWKS HTTP endpoints via wiremock; mints RS256 bearer tokens; verifies minted NATS user JWT structure, tenant ACL contents, and caller identity stability; generates CA/server/client TLS certs using rcgen.
Per-mode dispatcher construction helpers
rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs (lines 473–546)
Helper functions build CalloutDispatcher instances for static-JWKS OIDC, X509 mTLS (trust anchor PEM), and HMAC API key modes, each paired with static signing keys.
OIDC, mTLS, and API key integration test cases
rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs (lines 621–721)
Three #[tokio::test] cases (all #[ignore = "requires Docker (task #8)"]) drive callout attempts until two JWTs are captured, then assert stable caller ID and ACLs and that a final NATS client connection succeeds for each auth mode.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • TrogonStack/trogonai#371: The OIDC and mTLS verifier implementations exercised by the new main.rs wiring and nats_server_callout_integration.rs dispatcher tests were introduced in this PR.
  • TrogonStack/trogonai#375: The Subscriber and DenialPublisherConfig types now re-exported from lib.rs and driven in the new integration tests were implemented in this PR.

Suggested labels

rust:coverage-baseline-reset

🐇 Hoppity hop, the stubs are gone,
A real main wakes at NATS's dawn,
OIDC keys and mTLS certs,
API keys and container alerts —
Three tests now guard the callout gate,
This rabbit ships, and ships it great! 🎉

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.51% 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 PR title clearly summarizes the two main changes: wiring the production main entrypoint and adding a Docker-gated integration test for the a2a-auth-callout feature.
Description check ✅ Passed The PR description directly relates to the changeset, explaining why the production main was needed and detailing the Docker-gated integration test approach without blocking CI.
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-auth-callout-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-auth-callout/src/main.rs
@github-actions

github-actions Bot commented Jun 21, 2026

Copy link
Copy Markdown

badge

Code Coverage Summary

Details
Filename                                                                                  Stmts    Miss  Cover    Missing
--------------------------------------------------------------------------------------  -------  ------  -------  ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
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/a2a-nats/src/nats/subjects/subscriptions/agent_all.rs                                 20       0  100.00%
crates/trogon-std/src/duration.rs                                                            42       0  100.00%
crates/trogon-std/src/args.rs                                                                19       9  52.63%   11-28
crates/trogon-std/src/http.rs                                                                19       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/json.rs                                                                30       0  100.00%
crates/trogon-std/src/uuid.rs                                                                 7       0  100.00%
crates/trogon-std/src/dirs/system.rs                                                         71       0  100.00%
crates/trogon-std/src/dirs/fixed.rs                                                          80       0  100.00%
crates/a2a-nats/src/server/handler.rs                                                        70       0  100.00%
crates/a2a-nats/src/server/agent_card.rs                                                    191       0  100.00%
crates/a2a-nats/src/server/tasks_resubscribe.rs                                             103       0  100.00%
crates/a2a-nats/src/server/push_list.rs                                                     104       0  100.00%
crates/a2a-nats/src/server/bridge.rs                                                        282       0  100.00%
crates/a2a-nats/src/server/tasks_cancel.rs                                                  103       0  100.00%
crates/a2a-nats/src/server/push_get.rs                                                      106       0  100.00%
crates/a2a-nats/src/server/tasks_get.rs                                                     103       0  100.00%
crates/a2a-nats/src/server/dispatch.rs                                                      113       0  100.00%
crates/a2a-nats/src/server/test_support.rs                                                   41       0  100.00%
crates/a2a-nats/src/server/push_set.rs                                                       99       0  100.00%
crates/a2a-nats/src/server/message_send.rs                                                  114       0  100.00%
crates/a2a-nats/src/server/push_delete.rs                                                    97       0  100.00%
crates/a2a-nats/src/server/message_stream.rs                                                265       0  100.00%
crates/a2a-nats/src/server/tasks_list.rs                                                     97       0  100.00%
crates/a2a-nats/src/server/wire.rs                                                          120       0  100.00%
crates/a2a-pack/src/agent_card_read.rs                                                       66       0  100.00%
crates/a2a-pack/src/agent_card_schema.rs                                                     81       0  100.00%
crates/trogon-decider-runtime/src/stream/mod.rs                                              38       0  100.00%
crates/trogon-decider-runtime/src/stream/stream_position.rs                                  26       0  100.00%
crates/trogon-decider-runtime/src/stream/append_stream.rs                                     5       0  100.00%
crates/trogon-decider-runtime/src/stream/read_stream.rs                                       7       0  100.00%
crates/mcp-nats-server/src/config.rs                                                        257       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/src/nats/mod.rs                                                              99       0  100.00%
crates/mcp-nats/src/nats/parsing.rs                                                         191       0  100.00%
crates/a2a-nats-http/src/headers.rs                                                         167       6  96.41%   94, 103, 159, 220-222
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/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/rest.rs                                                            316     287  9.18%    63-415, 420-425, 427-428, 432-437
crates/a2a-nats/src/nats/subjects/agents/message_send.rs                                     23       0  100.00%
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/trogon-decider-runtime/src/snapshot/codec/snapshot_payload_decode.rs                   3       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_encode_error.rs                    36       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_envelope_encode_error.rs           14       0  100.00%
crates/trogon-decider-runtime/src/snapshot/codec/snapshot_decode_error.rs                    49       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/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/source_integration_id.rs                                           55       2  96.36%   58, 60
crates/trogon-gateway/src/source_status.rs                                                   24       0  100.00%
crates/trogon-gateway/src/streams.rs                                                        129       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/sentry/sentry_client_secret.rs                              17       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/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/logout.rs                                            6       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/ext.rs                                               9       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/record.rs                         6       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/failure.rs                       38       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/fs_write_text_file.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/terminal_kill.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_request_permission.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/session_update.rs                               12       0  100.00%
crates/a2a-auth-callout/src/wire/test_encode.rs                                              59       0  100.00%
crates/a2a-auth-callout/src/wire/xkey_public.rs                                              51       0  100.00%
crates/a2a-auth-callout/src/wire/bridge_adapter.rs                                           73      20  72.60%   30-55, 58
crates/a2a-auth-callout/src/wire/server_auth_request_envelope.rs                            108      29  73.15%   16-18, 29-33, 38-39, 41-44, 64, 77-94
crates/a2a-auth-callout/src/wire/nkey_seed.rs                                                61       0  100.00%
crates/a2a-auth-callout/src/wire/server_auth_request_claims.rs                              100      17  83.00%   24-26, 36-38, 120, 123-127, 141-146
crates/a2a-auth-callout/src/wire/wire_codec.rs                                               58      58  0.00%    19-92
crates/a2a-auth-callout/src/wire/callout_auth_response_claims.rs                             94      23  75.53%   49-74
crates/a2a-auth-callout/src/wire/nkey_public.rs                                             106      11  89.62%   47, 71-73, 87-90, 102, 118-119
crates/trogon-scheduler/src/telemetry/metrics.rs                                             52       0  100.00%
crates/trogon-scheduler/src/telemetry/trace.rs                                               41       0  100.00%
crates/acp-nats/src/nats/subjects/responses/prompt_response.rs                               27       0  100.00%
crates/acp-nats/src/nats/subjects/responses/ext_ready.rs                                     12       0  100.00%
crates/acp-nats/src/nats/subjects/responses/cancelled.rs                                     15       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-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/acp-nats/src/nats/parsing.rs                                                         278       1  99.64%   151
crates/acp-nats/src/nats/extensions.rs                                                        3       0  100.00%
crates/acp-nats/src/nats/mod.rs                                                              23       0  100.00%
crates/mcp-nats-stdio/src/config.rs                                                         149       0  100.00%
crates/mcp-nats-stdio/src/main.rs                                                           204       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-server/src/noop_handler.rs                                                  183       0  100.00%
crates/trogon-scheduler/src/processor/execution/execution_schedules/mod.rs                  270       0  100.00%
crates/a2a-nats-stdio/src/io_loop.rs                                                         84       0  100.00%
crates/a2a-nats-stdio/src/runtime.rs                                                        102       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/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/initialized.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/create_elicitation.rs                               12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/cancelled.rs                                        12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/list_roots.rs                                       12       0  100.00%
crates/mcp-nats/src/nats/subjects/client/ping.rs                                              9       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/call_tool.rs                                        12       0  100.00%
crates/mcp-nats/src/nats/subjects/server/list_prompts.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/get_prompt.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/cancel_task.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/mcp-nats/src/nats/subjects/server/prompt_list_changed.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/resource_list_changed.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/initialize.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/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/cancelled.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/subscribe_resource.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/list_resources.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/list_tools.rs                                       12       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-telemetry/src/log.rs                                                           70       1  98.57%   35
crates/trogon-telemetry/src/trace.rs                                                         23       1  95.65%   24
crates/trogon-telemetry/src/metric.rs                                                        26       1  96.15%   30
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/resource_attribute.rs                                            23       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/trogon-gateway/src/source/gitlab/gitlab_signing_token.rs                              62       0  100.00%
crates/trogon-decider-runtime/src/execution.rs                                             1432       0  100.00%
crates/acp-nats-stdio/src/config.rs                                                          66       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/src/telemetry/metrics.rs                                                     53       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-gateway/src/source/slack/server.rs                                            853       0  100.00%
crates/trogon-gateway/src/source/slack/signature.rs                                          66       0  100.00%
crates/trogonai-proto/src/codec.rs                                                           16       0  100.00%
crates/trogonai-proto/src/convert.rs                                                        120       0  100.00%
crates/trogonai-proto/src/scheduler/schedules/codec.rs                                      377       0  100.00%
crates/acp-nats-agent/src/connection.rs                                                    1252       1  99.92%   583
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/trogon-gateway/src/source/twitter/server.rs                                          524       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-std/src/telemetry/http.rs                                                     217       0  100.00%
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/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/main.rs                                                          900      10  98.89%   109, 243-250, 450
crates/acp-nats-server/src/config.rs                                                        126       3  97.62%   41-43
crates/trogon-nats/src/telemetry/messaging.rs                                                82       0  100.00%
crates/mcp-nats/src/telemetry/transport.rs                                                    6       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/nats/subjects/agents/push/set.rs                                         20       0  100.00%
crates/acp-nats/src/in_flight_slot_guard.rs                                                  32       0  100.00%
crates/acp-nats/src/ext_method_name.rs                                                       65       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/pending_prompt_waiters.rs                                               131       0  100.00%
crates/acp-nats/src/error.rs                                                                 82       0  100.00%
crates/acp-nats/src/lib.rs                                                                   69       0  100.00%
crates/acp-nats/src/client_proxy.rs                                                         181       0  100.00%
crates/acp-nats/src/acp_prefix.rs                                                            46       0  100.00%
crates/acp-nats/src/req_id.rs                                                                39       0  100.00%
crates/acp-nats/src/session_id.rs                                                            68       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-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/stream_event.rs                                       8       0  100.00%
crates/trogon-decider-runtime/src/event/event_id.rs                                          32       0  100.00%
crates/mcp-nats/src/nats/subjects/mod.rs                                                     89       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/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/trogon-decider-runtime/src/event/codec/event_payload_error.rs                         25       0  100.00%
crates/trogon-decider-runtime/src/event/codec/event_decode.rs                                29       0  100.00%
crates/trogon-scheduler/src/processor/execution/worker/consumer.rs                          203       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/dispatcher.rs                       1095       1  99.91%   200
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/wakeup.rs                                   353       7  98.02%   83-85, 127, 400, 416, 585
crates/trogon-gateway/src/source/linear/config.rs                                            17       0  100.00%
crates/trogon-gateway/src/source/linear/signature.rs                                         54       1  98.15%   16
crates/trogon-gateway/src/source/linear/server.rs                                           386       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/a2a-nats/src/catalog/import_gate/principal.rs                                         14       0  100.00%
crates/a2a-nats/src/task_id.rs                                                               54       1  98.15%   25
crates/a2a-nats/src/a2a_prefix.rs                                                            44       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/req_id.rs                                                                41       0  100.00%
crates/a2a-nats/src/config.rs                                                               318       0  100.00%
crates/a2a-nats/src/constants.rs                                                             36       0  100.00%
crates/a2a-nats/src/context_id.rs                                                            51       1  98.04%   26
crates/a2a-nats/src/agent_id.rs                                                              58       0  100.00%
crates/a2a-nats/src/jsonrpc.rs                                                               49       0  100.00%
crates/a2a-nats/src/push/delivery_semantics.rs                                              274       0  100.00%
crates/a2a-nats/src/push/dlq.rs                                                             283       0  100.00%
crates/a2a-nats/src/push/caller_id.rs                                                        91       0  100.00%
crates/a2a-nats/src/push/dispatch_error.rs                                                  111       0  100.00%
crates/a2a-nats/src/push/push_payload.rs                                                     88       0  100.00%
crates/a2a-nats/src/push/push_notification_config_id.rs                                      41       0  100.00%
crates/a2a-nats/src/push/target.rs                                                           54       0  100.00%
crates/a2a-nats/src/push/authentication_header.rs                                           104       0  100.00%
crates/a2a-nats/src/push/terminal_push_task_state.rs                                         64       0  100.00%
crates/a2a-nats/src/push/push_notification_target.rs                                        108       0  100.00%
crates/a2a-nats/src/push/push_notification_config.rs                                         20       0  100.00%
crates/a2a-nats/src/push/push_delivery_semantics_registry.rs                                 57       0  100.00%
crates/a2a-nats/src/push/status_transition_id.rs                                             30       0  100.00%
crates/a2a-nats/src/push/dlq_dedup.rs                                                       120       0  100.00%
crates/a2a-nats/src/push/push_idempotency_key.rs                                             84       0  100.00%
crates/a2a-nats/src/push/idempotency_key_header.rs                                           43       0  100.00%
crates/a2a-nats/src/push/nats_push_subject.rs                                                34       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/mod.rs                                      107       0  100.00%
crates/a2a-nats/src/catalog/import_gate/spicedb/config.rs                                    70       0  100.00%
crates/a2a-auth-callout/src/signing_key_source/file.rs                                       38       6  84.21%   40-42, 61-63
crates/a2a-auth-callout/src/signing_key_source/env.rs                                        38       4  89.47%   58, 75-77
crates/a2a-auth-callout/src/signing_key_source/key_version.rs                                20       8  60.00%   15-19, 28, 39-41
crates/a2a-auth-callout/src/signing_key_source/vault.rs                                       3       0  100.00%
crates/a2a-auth-callout/src/signing_key_source/loader.rs                                     18      18  0.00%    7-35
crates/a2a-auth-callout/src/signing_key_source/minting_material.rs                           18       6  66.67%   31-36
crates/a2a-auth-callout/src/signing_key_source/signing_key_handle.rs                         15       6  60.00%   15-20
crates/a2a-auth-callout/src/signing_key_source/static_source.rs                              25       0  100.00%
crates/a2a-nats/src/client/wire.rs                                                           38       0  100.00%
crates/a2a-nats/src/client/unary.rs                                                         187       0  100.00%
crates/a2a-nats/src/client/resubscribe.rs                                                    69       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/error.rs                                                         161       2  98.76%   135, 144
crates/a2a-nats/src/client/handle.rs                                                        934       0  100.00%
crates/a2a-nats/src/client/event_stream.rs                                                  247       0  100.00%
crates/mcp-nats/src/nats/subjects/subscriptions/one_client.rs                                 9       0  100.00%
crates/mcp-nats/src/nats/subjects/subscriptions/all_server.rs                                 6       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/trogon-std/src/time/mock.rs                                                          125       0  100.00%
crates/trogon-std/src/time/system.rs                                                         31       0  100.00%
crates/trogon-std/src/fs/system.rs                                                           92       0  100.00%
crates/trogon-std/src/fs/mem.rs                                                             216      10  95.37%   61-63, 77-79, 132-134, 157
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/signature.rs                                       27       0  100.00%
crates/trogon-gateway/src/source/telegram/config.rs                                          89       0  100.00%
crates/a2a-nats/src/nats/subjects/stream.rs                                                  54       0  100.00%
crates/acp-nats/src/client/session_update.rs                                                 55       0  100.00%
crates/acp-nats/src/client/request_permission.rs                                            298       0  100.00%
crates/acp-nats/src/client/mod.rs                                                          2851       0  100.00%
crates/acp-nats/src/client/fs_write_text_file.rs                                            408       0  100.00%
crates/acp-nats/src/client/terminal_release.rs                                              335       0  100.00%
crates/acp-nats/src/client/rpc_reply.rs                                                      64       0  100.00%
crates/acp-nats/src/client/fs_read_text_file.rs                                             346       0  100.00%
crates/acp-nats/src/client/terminal_create.rs                                               264       0  100.00%
crates/acp-nats/src/client/terminal_output.rs                                               206       0  100.00%
crates/acp-nats/src/client/terminal_kill.rs                                                 278       0  100.00%
crates/acp-nats/src/client/terminal_wait_for_exit.rs                                        364       0  100.00%
crates/acp-nats/src/client/ext.rs                                                           296       8  97.30%   146-155, 172-181
crates/acp-nats/src/client/ext_session_prompt_response.rs                                   135       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_delivery.rs                       25       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule_event_schedule.rs                       83       0  100.00%
crates/trogon-scheduler/src/commands/domain/schedule_id.rs                                   81       0  100.00%
crates/trogon-scheduler/src/commands/domain/recurrence.rs                                   179       1  99.44%   99
crates/trogon-scheduler/src/commands/domain/schedule_event_status.rs                         10       0  100.00%
crates/trogon-scheduler/src/commands/domain/message.rs                                      219       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.rs                                     638       0  100.00%
crates/a2a-nats/src/jetstream/consumers.rs                                                  112       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/stream_options.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/nats_token.rs                                                        157       0  100.00%
crates/trogon-nats/src/server_info.rs                                                        76       3  96.05%   19-21
crates/trogon-nats/src/connect.rs                                                            82       6  92.68%   41-46
crates/trogon-nats/src/subject_token_violation.rs                                            11       0  100.00%
crates/trogon-nats/src/client.rs                                                             22      22  0.00%    50-86
crates/trogon-nats/src/token.rs                                                               6       0  100.00%
crates/trogon-nats/src/auth.rs                                                              114       0  100.00%
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/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-std/src/env/in_memory.rs                                                       73       0  100.00%
crates/trogon-std/src/env/system.rs                                                          17       0  100.00%
crates/a2a-auth-callout/src/jwt/nats_permission_claims.rs                                    10       0  100.00%
crates/a2a-auth-callout/src/jwt/nats_user_jwt.rs                                            232      21  90.95%   131, 178, 187-196, 209, 214, 228, 237-242, 284, 288, 313
crates/a2a-auth-callout/src/jwt/mod.rs                                                      328     116  64.63%   28-31, 45-51, 59-78, 115-118, 123, 181, 185-187, 196-220, 243, 252-254, 273, 280-283, 306-308, 311-313, 319-330, 362-392, 413-420, 444, 449-453
crates/a2a-auth-callout/src/jwt/user_jwt_subject.rs                                          12       6  50.00%   18-26
crates/trogon-scheduler/src/commands/state.rs                                               472       0  100.00%
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/schedule_next_occurrence.rs                            355       0  100.00%
crates/trogon-scheduler/src/commands/resume_schedule.rs                                     207       0  100.00%
crates/trogon-scheduler/src/commands/remove_schedule.rs                                     171       0  100.00%
crates/trogon-scheduler/src/commands/snapshot.rs                                              4       0  100.00%
crates/trogon-scheduler/src/commands/record_schedule_occurrence.rs                          348       1  99.71%   182
crates/trogon-service-config/src/lib.rs                                                      92       0  100.00%
crates/trogon-decider-runtime/src/headers/header_value.rs                                    34       0  100.00%
crates/trogon-decider-runtime/src/headers/header_map.rs                                      54       3  94.44%   20-22
crates/trogon-decider-runtime/src/headers/header_name.rs                                     28       0  100.00%
crates/trogon-decider-runtime/src/headers/mod.rs                                             74       0  100.00%
crates/trogon-nats/src/jetstream/claim_check.rs                                             393      10  97.46%   45-47, 99-105
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/stream_max_age.rs                                           18       0  100.00%
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/a2a-auth-callout/src/credentials/oidc.rs                                             405      24  94.07%   18-19, 21-23, 48-50, 160, 164, 178, 212-218, 278-280, 306, 450, 509, 528
crates/a2a-auth-callout/src/credentials/mtls.rs                                             212      29  86.32%   60-62, 71-72, 81, 118-122, 131-135, 151, 153-154, 168-169, 209-213, 216-219
crates/a2a-auth-callout/src/credentials/api_key.rs                                          130      13  90.00%   30-33, 41-46, 56, 61-63
crates/a2a-identity-types/src/caller.rs                                                      61       0  100.00%
crates/a2a-identity-types/src/jwt.rs                                                        156       0  100.00%
crates/a2a-identity-types/src/error.rs                                                       20       0  100.00%
crates/a2a-identity-types/src/principal.rs                                                   40       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_session.rs                                9       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_client.rs                                15       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_session.rs                               12       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/prompt_wildcard.rs                            9       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_agent.rs                                 15       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_agent.rs                                  9       0  100.00%
crates/a2a-nats/src/nats/subjects/tasks/events.rs                                            31       0  100.00%
crates/trogon-gateway/src/source/discord/config.rs                                          105       0  100.00%
crates/trogon-gateway/src/source/discord/gateway.rs                                         426       1  99.77%   137
crates/a2a-nats/src/catalog/watch.rs                                                         99       0  100.00%
crates/a2a-nats/src/catalog/registrar.rs                                                    211       0  100.00%
crates/a2a-nats/src/catalog/nats_kv.rs                                                       19       0  100.00%
crates/a2a-nats/src/catalog/store.rs                                                        382       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/a2a-nats/src/push/dispatcher/nats.rs                                                 183       0  100.00%
crates/a2a-nats/src/push/dispatcher/composite.rs                                            154       0  100.00%
crates/a2a-nats/src/push/dispatcher/jetstream.rs                                            226       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-auth-callout/src/main.rs                                                         143     143  0.00%    21-217
crates/a2a-auth-callout/src/error.rs                                                        117       2  98.29%   28, 104
crates/a2a-auth-callout/src/permissions.rs                                                  179      19  89.39%   16-34, 126-139
crates/a2a-auth-callout/src/test_support.rs                                                  20      20  0.00%    16-36
crates/a2a-auth-callout/src/denial_reason.rs                                                 35       0  100.00%
crates/a2a-auth-callout/src/dispatcher.rs                                                   167      19  88.62%   58-62, 82-112
crates/a2a-auth-callout/src/account_resolver.rs                                              58       6  89.66%   32-37, 48
crates/a2a-auth-callout/src/subscriber.rs                                                    96      96  0.00%    26-177
crates/a2a-auth-callout/src/denial_category.rs                                               90       1  98.89%   40
crates/a2a-auth-callout/src/caller_jwt_header.rs                                             20      20  0.00%    11-39
crates/a2a-auth-callout/src/denial_claims.rs                                                135      30  77.78%   21-25, 34, 53-57, 66, 85-89, 98, 125-150
crates/trogon-gateway/src/source/microsoft_graph/server.rs                                  325       0  100.00%
crates/trogon-gateway/src/source/microsoft_graph/client_state.rs                             30       0  100.00%
crates/acp-nats/src/agent/authenticate.rs                                                    49       0  100.00%
crates/acp-nats/src/agent/set_session_mode.rs                                                67       0  100.00%
crates/acp-nats/src/agent/set_session_config_option.rs                                       67       0  100.00%
crates/acp-nats/src/agent/set_session_model.rs                                               67       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/mod.rs                                                             65       0  100.00%
crates/acp-nats/src/agent/test_support.rs                                                   267       0  100.00%
crates/acp-nats/src/agent/ext_notification.rs                                                82       0  100.00%
crates/acp-nats/src/agent/js_request.rs                                                     283       0  100.00%
crates/acp-nats/src/agent/prompt.rs                                                         471       0  100.00%
crates/acp-nats/src/agent/fork_session.rs                                                    94       0  100.00%
crates/acp-nats/src/agent/bridge.rs                                                         123       4  96.75%   108-111
crates/acp-nats/src/agent/close_session.rs                                                   63       0  100.00%
crates/acp-nats/src/agent/initialize.rs                                                      79       0  100.00%
crates/acp-nats/src/agent/new_session.rs                                                     82       0  100.00%
crates/acp-nats/src/agent/resume_session.rs                                                  90       0  100.00%
crates/acp-nats/src/agent/list_sessions.rs                                                   47       0  100.00%
crates/acp-nats/src/agent/logout.rs                                                          49       0  100.00%
crates/acp-nats/src/agent/load_session.rs                                                    89       0  100.00%
crates/mcp-nats/src/client.rs                                                                31       0  100.00%
crates/mcp-nats/src/config.rs                                                               110       0  100.00%
crates/mcp-nats/src/jsonrpc.rs                                                               22       0  100.00%
crates/mcp-nats/src/mcp_peer_id.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/trogon-gateway/src/source/incidentio/incidentio_signing_secret.rs                     56       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/server.rs                                       343       0  100.00%
crates/trogon-gateway/src/source/incidentio/signature.rs                                    206       0  100.00%
crates/trogon-gateway/src/source/standard_webhooks.rs                                       138       0  100.00%
crates/trogon-nats/src/lease/mod.rs                                                         523      13  97.51%   113-126
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_interval.rs                                               57       0  100.00%
crates/trogon-nats/src/lease/lease_bucket.rs                                                 19       0  100.00%
crates/trogon-nats/src/lease/acquire.rs                                                       5       5  0.00%    9-14
crates/trogon-nats/src/lease/renew.rs                                                       246      19  92.28%   23-29, 48-59
crates/trogon-nats/src/lease/ttl.rs                                                          68       0  100.00%
crates/trogon-nats/src/lease/nats_kv_lease_config.rs                                         26       0  100.00%
crates/trogon-nats/src/lease/provision.rs                                                   187      10  94.65%   82-92
crates/trogon-nats/src/lease/lease_timing.rs                                                 15       0  100.00%
crates/trogon-scheduler/src/processor/execution/reconciliation/schedule_key.rs               67       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/schedule_subject.rs           59       3  94.92%   60-62
crates/trogon-scheduler/src/processor/execution/reconciliation/rrule_wakeup_payload.rs       35       0  100.00%
crates/trogon-scheduler/src/processor/execution/reconciliation/go_duration.rs                59       0  100.00%
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/acp-nats/src/jetstream/consumers.rs                                                   91       0  100.00%
crates/acp-nats/src/jetstream/ext_policy.rs                                                  26       0  100.00%
crates/acp-nats/src/jetstream/streams.rs                                                    163       4  97.55%   206-208, 218
crates/acp-nats/src/jetstream/provision.rs                                                   52       0  100.00%
crates/acp-nats/src/nats/subjects/commands/cancel.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/set_config_option.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/fork.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/set_model.rs                                      15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_mode.rs                                       15       0  100.00%
crates/acp-nats/src/nats/subjects/commands/load.rs                                           15       0  100.00%
TOTAL                                                                                     66074    2028  96.93%

Diff against main

Filename                               Stmts    Miss  Cover
-----------------------------------  -------  ------  --------
crates/a2a-auth-callout/src/main.rs     +139    +143  -100.00%
TOTAL                                   +139    +143  -0.21%

Results for commit: b6920df

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: 5

🧹 Nitpick comments (1)
rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs (1)

202-238: ⚡ Quick win

Use the production Subscriber in this live integration path.

This custom loop reimplements the subscriber contract, so the Docker-backed test can pass while production Subscriber::run regresses around queue subscription, decode-failure fallback replies, publish-failure fallback replies, or denial-reason construction. Wiring Subscriber::new(callout_client, capturing, wire).run() here would keep the test aligned with the production path described by the PR objective.

♻️ Proposed direction
-use a2a_auth_callout::{
-    AccountResolver, AuthCalloutWireCodec, DenialCategory, MintedUserJwt, NkeyPublic, NkeySeed, StaticAccountResolver,
-};
+use a2a_auth_callout::{
+    AccountResolver, AuthCalloutWireCodec, MintedUserJwt, NkeyPublic, NkeySeed, StaticAccountResolver, Subscriber,
+};

-        let wire = Arc::new(AuthCalloutWireCodec::new(server_issuer, callout_seed, None, None).expect("wire codec"));
+        let wire = AuthCalloutWireCodec::new(server_issuer, callout_seed, None, None).expect("wire codec");

         let capture = MintedJwtCapture::new();
         let dispatch_errors = DispatchErrorCapture::default();
         let capturing = CapturingDispatcher {
             inner: dispatcher,
             capture: capture.clone(),
             errors: dispatch_errors.clone(),
         };

         let callout_client = connect_callout_service(&nats_url, client_tls).await;
-        let mut auth_sub = callout_client
-            .subscribe("$SYS.REQ.USER.AUTH")
-            .await
-            .expect("subscribe auth callout subject");
-        let reply_client = callout_client.clone();
-        let wire_task = Arc::clone(&wire);
-        let callout_errors = dispatch_errors.clone();
         let subscriber_task = tokio::spawn(async move {
-            while let Some(msg) = auth_sub.next().await {
-                ...
-            }
-            Ok(())
+            Subscriber::new(callout_client, capturing, wire).run().await
         });
🤖 Prompt for 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.

In `@rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs`
around lines 202 - 238, The subscriber_task contains a custom reimplementation
of the subscription handling logic that diverges from the production Subscriber
implementation, which risks masking regressions in queue subscriptions,
decode-failure handling, publish-failure handling, or denial-reason
construction. Replace the manual while loop that subscribes to
"$SYS.REQ.USER.AUTH", handles auth_sub.next().await, and manually
encodes/publishes responses with a direct call to the production Subscriber
struct by instantiating Subscriber::new(callout_client, capturing, wire) and
calling its run() method to keep the test aligned with the actual production
code path.
🤖 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-auth-callout/src/main.rs`:
- Around line 33-45: Create a typed error enum for startup errors instead of
using String-based errors. Update the three functions env_required,
load_nkey_seed_env, and load_nkey_public_env to return this typed error enum
instead of Result<_, String>. Replace the stringly-typed error conversions
(format! and to_string() calls) with enum variants that wrap the source errors
as fields, preserving error context and type information rather than discarding
it through string conversion.
- Around line 92-96: The error message logged when
signing_key_source_from_process_env() fails is misleading because it only
mentions AUTH_CALLOUT_ISSUER being invalid, but the function can fail for
multiple reasons including missing key source mode, vault configuration errors,
or key file access issues. Change the tracing::error message to be more generic
and accurately describe the operation that failed, such as indicating the
failure is in loading or configuring the signing key source, rather than blaming
a specific environment variable.
- Around line 104-108: The current implementation of parsing
AUTH_CALLOUT_USER_JWT_TTL_SECS silently falls back to the default duration when
the value cannot be parsed, which masks configuration errors. Modify the parsing
logic to distinguish between the environment variable being unset (OK to use
default) versus being set but invalid (should fail). Check if the environment
variable exists using std::env::var, and if it returns Ok, attempt to parse the
string value as u64 and Duration; if parsing fails, panic or return an error
rather than defaulting. Only use Duration::from_secs(DEFAULT_USER_JWT_TTL_SECS)
as the default when the environment variable is not set at all (Err case from
std::env::var).

In
`@rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs`:
- Line 19: Add a documentation comment near the async_nats import (line 19) and
at the test harness that uses ConnectOptions with auth callback methods (around
lines 149-159 and 436-454) to explain why async_nats is used directly instead of
the trogon-nats abstraction layer. The comment should clarify that trogon-nats
currently lacks support for dynamic auth callbacks (which are needed for this
test), and this represents an exception to the repo guidelines. Additionally,
consider noting that trogon-nats could be extended in the future to support
callback-based authentication mechanisms for improved testability and
consistency.
- Around line 316-319: The JWKS fixture defines a public key with key_operations
marked as KeyOperations::Sign, but public keys are used for verification, not
signing. In the CommonParameters struct initialization, change the
key_operations field from Some(vec![KeyOperations::Sign]) to
Some(vec![KeyOperations::Verify]) to correctly reflect that this public key is
intended for JWT verification according to RFC 7517 specifications.

---

Nitpick comments:
In
`@rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs`:
- Around line 202-238: The subscriber_task contains a custom reimplementation of
the subscription handling logic that diverges from the production Subscriber
implementation, which risks masking regressions in queue subscriptions,
decode-failure handling, publish-failure handling, or denial-reason
construction. Replace the manual while loop that subscribes to
"$SYS.REQ.USER.AUTH", handles auth_sub.next().await, and manually
encodes/publishes responses with a direct call to the production Subscriber
struct by instantiating Subscriber::new(callout_client, capturing, wire) and
calling its run() method to keep the test aligned with the actual production
code path.
🪄 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: 55ae7457-3f4c-4a4d-a303-d87c6574356d

📥 Commits

Reviewing files that changed from the base of the PR and between a4475c7 and 6be34be.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (4)
  • rsworkspace/crates/a2a-auth-callout/Cargo.toml
  • rsworkspace/crates/a2a-auth-callout/src/lib.rs
  • rsworkspace/crates/a2a-auth-callout/src/main.rs
  • rsworkspace/crates/a2a-auth-callout/tests/nats_server_callout_integration.rs

Comment thread rsworkspace/crates/a2a-auth-callout/src/main.rs Outdated
Comment thread rsworkspace/crates/a2a-auth-callout/src/main.rs
Comment thread rsworkspace/crates/a2a-auth-callout/src/main.rs Outdated
…in tests

A binary that boots with zero credential verifiers, with a misleading
signing-key error message, with a silently defaulted TTL on parse
failure, or with String-typed startup errors hides misconfiguration
behind a process that looks healthy yet denies every callout.

The test JWKS fixture also advertised the public key as 'sign' which is
backwards under RFC 7517 and trips verifier libraries that honor key_ops.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
…server-nkey TODO

The harness mints user JWTs whose audience is the tenant account, but
nats.conf only declared AUTH/APP/SYS — without the tenant declared at
the server level, even a successful callout cannot land the connect
against the intended account. The other Cursor finding is real but
requires reading the NATS server's per-boot identity NKey before
constructing the wire codec; tracking it inline so the docker-gated
flow is honest about its current limitation rather than silently broken.

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 1 potential issue.

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 f40334f. Configure here.

Comment thread rsworkspace/crates/a2a-auth-callout/src/main.rs Outdated
An Ok(()) return from Subscriber::run means the NATS subscription
closed (connection drop or shutdown), which is never a healthy steady
state — falling through to a zero exit lets orchestrators treat the
silent stop as a clean shutdown and skip the restart, leaving auth
callouts down while NATS clients can no longer authenticate.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis
yordis merged commit 7daf7c4 into main Jun 21, 2026
6 of 7 checks passed
@yordis
yordis deleted the yordis/feat-a2a-auth-callout-bin branch June 21, 2026 18:14
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