Skip to content

fix(gateway): preserve inbound event fidelity for Sentry and Linear sources#124

Merged
yordis merged 3 commits intomainfrom
fix-linear
Apr 15, 2026
Merged

fix(gateway): preserve inbound event fidelity for Sentry and Linear sources#124
yordis merged 3 commits intomainfrom
fix-linear

Conversation

@yordis
Copy link
Copy Markdown
Member

@yordis yordis commented Apr 15, 2026

Summary

  • Ensure the gateway can accept Sentry as an inbound source so Sentry-driven workflows can enter the platform without custom side paths.
  • Preserve higher-fidelity event intake for Linear so downstream consumers can rely on the original webhook semantics.
  • Keep local gateway configuration and documentation aligned so operators can enable the source set without guesswork.

Testing

  • mise exec -- cargo fmt --all --manifest-path rsworkspace/Cargo.toml
  • mise exec -- cargo test -p trogon-source-sentry -p trogon-gateway --manifest-path rsworkspace/Cargo.toml

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 15, 2026

PR Summary

Medium Risk
Introduces a new externally-facing webhook endpoint with custom signature validation and NATS publishing, which can affect ingress reliability and message routing if misconfigured. Changes are mostly additive and covered by unit tests, but involve security-sensitive verification logic.

Overview
Adds Sentry as a new inbound source end-to-end: a new trogon-source-sentry crate verifies Sentry integration webhooks (HMAC SHA-256 over raw JSON), enforces a 2MiB body limit, and publishes the raw payload to NATS using subjects like {subject_prefix}.{resource}.{action} with relevant headers (incl. request-id as NATS_MESSAGE_ID).

trogon-gateway now loads Sentry source config, mounts /sentry/webhook, and provisions a SENTRY JetStream stream; config validation adds a MissingField error type and enforces TROGON_SOURCE_SENTRY_NATS_ACK_TIMEOUT_SECS <= 1.

Docs and local compose env examples are updated for Sentry.

Reviewer note: new env vars were introduced—please confirm each exists in every environment: TROGON_SOURCE_SENTRY_STATUS, TROGON_SOURCE_SENTRY_CLIENT_SECRET, TROGON_SOURCE_SENTRY_SUBJECT_PREFIX, TROGON_SOURCE_SENTRY_STREAM_NAME, TROGON_SOURCE_SENTRY_STREAM_MAX_AGE_SECS, TROGON_SOURCE_SENTRY_NATS_ACK_TIMEOUT_SECS.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 15, 2026

Walkthrough

Adds a new Sentry webhook source: introduces the trogon-source-sentry crate, integrates it into trogon-gateway (config resolution, router mounting, and JetStream provisioning), implements HMAC-SHA256 signature verification and webhook handling (/sentry/webhook), and updates documentation and environment examples.

Changes

Cohort / File(s) Summary
Env & Docs
devops/docker/compose/.env.example, devops/docker/compose/services/trogon-gateway/README.md
Added commented Sentry env vars and documented the /sentry/webhook path, required TROGON_SOURCE_SENTRY_CLIENT_SECRET, signature behavior, and NATS subject format.
Workspace & Gateway Cargo
rsworkspace/Cargo.toml, rsworkspace/crates/trogon-gateway/Cargo.toml
Added trogon-source-sentry as a workspace dependency and added it to trogon-gateway crate dependencies.
Gateway config & composition
rsworkspace/crates/trogon-gateway/src/config.rs, rsworkspace/crates/trogon-gateway/src/http.rs, rsworkspace/crates/trogon-gateway/src/streams.rs
Added sources.sentry config resolution (with validation and new error variant), wired ResolvedConfig.sentry, conditionally mounted /sentry router, and invoked provisioning for Sentry streams; updated tests/fixtures and stream counts.
New crate manifest & surface
rsworkspace/crates/trogon-source-sentry/Cargo.toml, rsworkspace/crates/trogon-source-sentry/src/lib.rs
Added new trogon-source-sentry crate manifest and public module/re-exports (config, constants, sentry_client_secret, server, signature).
Sentry config & constants
rsworkspace/crates/trogon-source-sentry/src/config.rs, rsworkspace/crates/trogon-source-sentry/src/constants.rs
Introduced public SentryConfig type and HTTP/NATS header and body-size constants.
Secrets & signature
rsworkspace/crates/trogon-source-sentry/src/sentry_client_secret.rs, rsworkspace/crates/trogon-source-sentry/src/signature.rs
Added SentryClientSecret wrapper (redacted Debug) and HMAC-SHA256 verify with SignatureError variants and tests.
Server / router / handler
rsworkspace/crates/trogon-source-sentry/src/server.rs
Implemented provision (JetStream stream creation) and router with POST /webhook handler: header checks, signature verification, JSON parsing, subject construction, header propagation, claim-check publish to JetStream, error mappings, and a comprehensive test suite.

Sequence Diagram(s)

sequenceDiagram
    participant Sentry as "External Sentry"
    participant Gateway as "Gateway / Handler"
    participant Verifier as "Signature Verifier"
    participant Parser as "Payload Parser"
    participant JetStream as "NATS / JetStream"

    Sentry->>Gateway: POST /sentry/webhook (body + sig header)
    Gateway->>Verifier: verify(client_secret, body, sig_header)
    alt signature valid
        Verifier-->>Gateway: OK
        Gateway->>Parser: parse body -> {resource, action, ...}
        alt payload valid
            Parser-->>Gateway: parsed payload
            Gateway->>JetStream: publish(subject = prefix.resource.action, body, headers)
            JetStream-->>Gateway: published
            Gateway-->>Sentry: 200 OK
        else payload invalid
            Parser-->>Gateway: error
            Gateway-->>Sentry: 400 Bad Request
        end
    else signature invalid
        Verifier-->>Gateway: mismatch/error
        Gateway-->>Sentry: 401 Unauthorized
    end
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 I guard the hook with secret key held tight,
HMAC whiskers twitching through the night,
I hop the bytes to NATS on cue,
Subject stitched: resource.action.true,
The rabbit claps — webhooks leap in light! 🥕

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 55.68% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding Sentry as a new inbound source and preserving event fidelity, which aligns with the comprehensive changeset.
Description check ✅ Passed The description relates to the changeset by explaining the motivation for adding Sentry support and maintaining configuration/documentation clarity.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix-linear

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/trogon-gateway/src/config.rs
@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 15, 2026

badge

Code Coverage Summary

Details
Filename                                                                      Stmts    Miss  Cover    Missing
--------------------------------------------------------------------------  -------  ------  -------  ---------------------------------------------------------------------------------------------
crates/trogon-source-telegram/src/config.rs                                      17       0  100.00%
crates/trogon-source-telegram/src/signature.rs                                   38       0  100.00%
crates/trogon-source-telegram/src/server.rs                                     387       0  100.00%
crates/trogon-std/src/env/system.rs                                              17       0  100.00%
crates/trogon-std/src/env/in_memory.rs                                           81       0  100.00%
crates/trogon-std/src/time/system.rs                                             35       0  100.00%
crates/trogon-std/src/time/mock.rs                                              129       0  100.00%
crates/acp-nats/src/nats/subjects/commands/load.rs                               18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/fork.rs                               18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/close.rs                              18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_config_option.rs                  18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/cancel.rs                             18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/prompt.rs                             18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/resume.rs                             18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_mode.rs                           18       0  100.00%
crates/acp-nats/src/nats/subjects/commands/set_model.rs                          18       0  100.00%
crates/acp-nats/src/nats/subjects/global/logout.rs                                8       0  100.00%
crates/acp-nats/src/nats/subjects/global/authenticate.rs                          8       0  100.00%
crates/acp-nats/src/nats/subjects/global/initialize.rs                            8       0  100.00%
crates/acp-nats/src/nats/subjects/global/session_list.rs                          8       0  100.00%
crates/acp-nats/src/nats/subjects/global/session_new.rs                           8       0  100.00%
crates/acp-nats/src/nats/subjects/global/ext_notify.rs                           12       0  100.00%
crates/acp-nats/src/nats/subjects/global/ext.rs                                  12       0  100.00%
crates/trogon-nats/src/lease/lease_timing.rs                                     21       0  100.00%
crates/trogon-nats/src/lease/lease_config_error.rs                               13       0  100.00%
crates/trogon-nats/src/lease/renew.rs                                           263      19  92.78%   21-27, 46-57
crates/trogon-nats/src/lease/renew_interval.rs                                   61       0  100.00%
crates/trogon-nats/src/lease/acquire.rs                                           8       8  0.00%    9-18
crates/trogon-nats/src/lease/lease_bucket.rs                                     19       0  100.00%
crates/trogon-nats/src/lease/release.rs                                           5       5  0.00%    8-12
crates/trogon-nats/src/lease/mod.rs                                             603      13  97.84%   182-195
crates/trogon-nats/src/lease/provision.rs                                       210      10  95.24%   84-94
crates/trogon-nats/src/lease/lease_key.rs                                        19       0  100.00%
crates/trogon-nats/src/lease/nats_kv_lease_config.rs                             30       0  100.00%
crates/trogon-nats/src/lease/ttl.rs                                              76       0  100.00%
crates/acp-nats-agent/src/connection.rs                                        1434       1  99.93%   686
crates/acp-nats/src/agent/list_sessions.rs                                       50       0  100.00%
crates/acp-nats/src/agent/cancel.rs                                             105       0  100.00%
crates/acp-nats/src/agent/resume_session.rs                                     102       0  100.00%
crates/acp-nats/src/agent/authenticate.rs                                        52       0  100.00%
crates/acp-nats/src/agent/set_session_model.rs                                   71       0  100.00%
crates/acp-nats/src/agent/fork_session.rs                                       106       0  100.00%
crates/acp-nats/src/agent/initialize.rs                                          83       0  100.00%
crates/acp-nats/src/agent/ext_method.rs                                          92       0  100.00%
crates/acp-nats/src/agent/mod.rs                                                 65       0  100.00%
crates/acp-nats/src/agent/ext_notification.rs                                    88       0  100.00%
crates/acp-nats/src/agent/load_session.rs                                       101       0  100.00%
crates/acp-nats/src/agent/logout.rs                                              49       0  100.00%
crates/acp-nats/src/agent/close_session.rs                                       67       0  100.00%
crates/acp-nats/src/agent/prompt.rs                                             633       0  100.00%
crates/acp-nats/src/agent/new_session.rs                                         91       0  100.00%
crates/acp-nats/src/agent/js_request.rs                                         304       0  100.00%
crates/acp-nats/src/agent/set_session_config_option.rs                           71       0  100.00%
crates/acp-nats/src/agent/test_support.rs                                       299       0  100.00%
crates/acp-nats/src/agent/bridge.rs                                             123       4  96.75%   109-112
crates/acp-nats/src/agent/set_session_mode.rs                                    71       0  100.00%
crates/trogon-source-notion/src/notion_event_type.rs                             48       3  93.75%   49-51
crates/trogon-source-notion/src/signature.rs                                     63       1  98.41%   32
crates/trogon-source-notion/src/server.rs                                       351       8  97.72%   100-104, 137-138, 162-163
crates/trogon-source-notion/src/notion_verification_token.rs                     17       0  100.00%
crates/acp-nats/src/nats/subjects/mod.rs                                        380       0  100.00%
crates/acp-nats/src/nats/subjects/stream.rs                                      58       0  100.00%
crates/acp-nats/src/req_id.rs                                                    39       0  100.00%
crates/acp-nats/src/pending_prompt_waiters.rs                                   141       0  100.00%
crates/acp-nats/src/error.rs                                                     84       0  100.00%
crates/acp-nats/src/jsonrpc.rs                                                    6       0  100.00%
crates/acp-nats/src/client_proxy.rs                                             200       0  100.00%
crates/acp-nats/src/config.rs                                                   204       0  100.00%
crates/acp-nats/src/session_id.rs                                                72       0  100.00%
crates/acp-nats/src/acp_prefix.rs                                                51       0  100.00%
crates/acp-nats/src/ext_method_name.rs                                           70       0  100.00%
crates/acp-nats/src/in_flight_slot_guard.rs                                      32       0  100.00%
crates/acp-nats/src/lib.rs                                                       73       0  100.00%
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/claim_check.rs                                 372       0  100.00%
crates/trogon-nats/src/jetstream/mocks.rs                                       740      44  94.05%   368-382, 388-396, 411-422, 436-446, 514-516
crates/trogon-nats/src/jetstream/traits.rs                                       43      43  0.00%    140-208
crates/trogon-source-incidentio/src/signature.rs                                455       0  100.00%
crates/trogon-source-incidentio/src/config.rs                                    16       0  100.00%
crates/trogon-source-incidentio/src/incidentio_event_type.rs                     67       0  100.00%
crates/trogon-source-incidentio/src/incidentio_signing_secret.rs                 67       0  100.00%
crates/trogon-source-incidentio/src/server.rs                                   365       0  100.00%
crates/acp-nats/src/jetstream/consumers.rs                                       99       0  100.00%
crates/acp-nats/src/jetstream/provision.rs                                       61       0  100.00%
crates/acp-nats/src/jetstream/ext_policy.rs                                      26       0  100.00%
crates/acp-nats/src/jetstream/streams.rs                                        194       4  97.94%   254-256, 266
crates/acp-nats/src/telemetry/metrics.rs                                         65       0  100.00%
crates/trogon-source-gitlab/src/server.rs                                       431       0  100.00%
crates/trogon-source-gitlab/src/config.rs                                        17       0  100.00%
crates/trogon-source-gitlab/src/signature.rs                                     30       0  100.00%
crates/trogon-std/src/secret_string.rs                                           35       0  100.00%
crates/trogon-std/src/duration.rs                                                45       0  100.00%
crates/trogon-std/src/http.rs                                                    19       0  100.00%
crates/trogon-std/src/args.rs                                                    10       0  100.00%
crates/trogon-std/src/json.rs                                                    30       0  100.00%
crates/trogon-nats/src/telemetry/messaging.rs                                   102       0  100.00%
crates/trogon-gateway/src/config.rs                                            1561       0  100.00%
crates/trogon-gateway/src/http.rs                                               123       0  100.00%
crates/trogon-gateway/src/main.rs                                                 4       0  100.00%
crates/trogon-gateway/src/source_status.rs                                       32       0  100.00%
crates/trogon-gateway/src/streams.rs                                            138       0  100.00%
crates/trogon-nats/src/token.rs                                                   8       0  100.00%
crates/trogon-nats/src/client.rs                                                 25      25  0.00%    50-89
crates/trogon-nats/src/mocks.rs                                                 304       0  100.00%
crates/trogon-nats/src/connect.rs                                               105      11  89.52%   22-24, 37, 49, 68-73
crates/trogon-nats/src/auth.rs                                                  119       0  100.00%
crates/trogon-nats/src/messaging.rs                                             598       2  99.67%   153, 163
crates/trogon-nats/src/nats_token.rs                                            161       0  100.00%
crates/acp-telemetry/src/metric.rs                                               35       3  91.43%   30-31, 39
crates/acp-telemetry/src/trace.rs                                                32       3  90.62%   23-24, 32
crates/acp-telemetry/src/lib.rs                                                 169      32  81.07%   28-34, 56-63, 98, 103, 108, 122-137, 174, 177, 180, 186
crates/acp-telemetry/src/service_name.rs                                         49       0  100.00%
crates/acp-telemetry/src/signal.rs                                                7       1  85.71%   43
crates/acp-telemetry/src/log.rs                                                  71       1  98.59%   43
crates/acp-nats/src/nats/mod.rs                                                  23       0  100.00%
crates/acp-nats/src/nats/extensions.rs                                            3       0  100.00%
crates/acp-nats/src/nats/parsing.rs                                             285       1  99.65%   153
crates/acp-nats/src/nats/subjects/subscriptions/one_client.rs                    18       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_session.rs                   18       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/global_all.rs                    11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_agent.rs                     18       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_client.rs                    11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_session.rs                   11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/prompt_wildcard.rs               11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_agent.rs                     11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/all_agent_ext.rs                 11       0  100.00%
crates/trogon-std/src/dirs/fixed.rs                                              84       0  100.00%
crates/trogon-std/src/dirs/system.rs                                             76       0  100.00%
crates/trogon-source-github/src/config.rs                                        17       0  100.00%
crates/trogon-source-github/src/signature.rs                                     64       0  100.00%
crates/trogon-source-github/src/server.rs                                       351       0  100.00%
crates/trogon-source-linear/src/signature.rs                                     54       1  98.15%   16
crates/trogon-source-linear/src/config.rs                                        17       0  100.00%
crates/trogon-source-linear/src/server.rs                                       392       0  100.00%
crates/trogon-std/src/telemetry/http.rs                                         239       0  100.00%
crates/trogon-source-discord/src/config.rs                                      109       0  100.00%
crates/trogon-source-discord/src/gateway.rs                                     491       1  99.80%   157
crates/trogon-source-sentry/src/sentry_client_secret.rs                          17       0  100.00%
crates/trogon-source-sentry/src/signature.rs                                     56       0  100.00%
crates/trogon-source-sentry/src/server.rs                                       359       0  100.00%
crates/trogon-service-config/src/lib.rs                                          98       0  100.00%
crates/acp-nats-stdio/src/main.rs                                               141      27  80.85%   64, 116-123, 129-131, 148, 179-200
crates/acp-nats-stdio/src/config.rs                                              72       0  100.00%
crates/trogon-source-slack/src/server.rs                                        954       0  100.00%
crates/trogon-source-slack/src/signature.rs                                      80       0  100.00%
crates/trogon-source-slack/src/config.rs                                         17       0  100.00%
crates/trogon-std/src/fs/system.rs                                              102       0  100.00%
crates/trogon-std/src/fs/mem.rs                                                 220      10  95.45%   61-63, 77-79, 133-135, 158
crates/acp-nats/src/nats/subjects/client_ops/session_request_permission.rs       15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/fs_read_text_file.rs                15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/fs_write_text_file.rs               15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_create.rs                  15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_wait_for_exit.rs           15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_kill.rs                    15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_release.rs                 15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/terminal_output.rs                  15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/session_update.rs                   15       0  100.00%
crates/acp-nats/src/nats/subjects/responses/cancelled.rs                         18       0  100.00%
crates/acp-nats/src/nats/subjects/responses/ext_ready.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/acp-nats/src/nats/subjects/responses/prompt_response.rs                   27       0  100.00%
crates/acp-nats/src/client/terminal_kill.rs                                     309       0  100.00%
crates/acp-nats/src/client/session_update.rs                                     55       0  100.00%
crates/acp-nats/src/client/rpc_reply.rs                                          71       0  100.00%
crates/acp-nats/src/client/ext_session_prompt_response.rs                       157       0  100.00%
crates/acp-nats/src/client/terminal_create.rs                                   294       0  100.00%
crates/acp-nats/src/client/mod.rs                                              2987       0  100.00%
crates/acp-nats/src/client/fs_read_text_file.rs                                 384       0  100.00%
crates/acp-nats/src/client/ext.rs                                               365       8  97.81%   193-204, 229-240
crates/acp-nats/src/client/terminal_wait_for_exit.rs                            396       0  100.00%
crates/acp-nats/src/client/request_permission.rs                                338       0  100.00%
crates/acp-nats/src/client/fs_write_text_file.rs                                451       0  100.00%
crates/acp-nats/src/client/terminal_output.rs                                   223       0  100.00%
crates/acp-nats/src/client/terminal_release.rs                                  357       0  100.00%
crates/acp-nats-ws/src/connection.rs                                            166      35  78.92%   75-82, 87-98, 114, 116-117, 122, 133-135, 142, 146, 150, 153-161, 172, 176, 179, 182-186, 220
crates/acp-nats-ws/src/upgrade.rs                                                57       2  96.49%   59, 90
crates/acp-nats-ws/src/main.rs                                                  189      18  90.48%   89, 209-230, 308
crates/acp-nats-ws/src/config.rs                                                 83       0  100.00%
TOTAL                                                                         26681     344  98.71%

Diff against main

Filename                                                   Stmts    Miss  Cover
-------------------------------------------------------  -------  ------  --------
crates/trogon-gateway/src/config.rs                         +190       0  +100.00%
crates/trogon-gateway/src/http.rs                             +9       0  +100.00%
crates/trogon-gateway/src/streams.rs                         +10       0  +100.00%
crates/trogon-source-sentry/src/sentry_client_secret.rs      +17       0  +100.00%
crates/trogon-source-sentry/src/signature.rs                 +56       0  +100.00%
crates/trogon-source-sentry/src/server.rs                   +359       0  +100.00%
TOTAL                                                       +641       0  +0.03%

Results for commit: 151b6dd

Minimum allowed coverage is 95%

♻️ This comment has been updated with latest results

@yordis yordis marked this pull request as ready for review April 15, 2026 04:41
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🧹 Nitpick comments (1)
rsworkspace/crates/trogon-gateway/src/config.rs (1)

1293-1300: Round out the Sentry config test matrix with token-validation failures.

resolve_sentry now validates both subject_prefix and stream_name, but the new tests only cover the secret and zero-duration branches. Adding the two invalid-token cases would keep Sentry at parity with the existing source coverage and protect those new validation paths from regressions.

Also applies to: 1567-1584, 2128-2135, 2419-2445

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-gateway/src/config.rs` around lines 1293 - 1300,
The test matrix for resolve_sentry is missing cases for token-validation
failures of subject_prefix and stream_name; update the tests that use
sentry_toml and resolve_sentry to add two new cases that provide invalid tokens
for subject_prefix and for stream_name (e.g., malformed or empty values) and
assert that resolve_sentry returns the expected validation error for each.
Locate the tests that call sentry_toml(...) and resolve_sentry(...) and add
assertions for the two failure paths so the suite covers secret, zero-duration,
subject_prefix, and stream_name validation.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@rsworkspace/Cargo.toml`:
- Around line 11-13: The new workspace-level clippy denies for expect_used,
panic, and unwrap_used will break CI because existing codebases contain many
violations; revert these global "deny" rules and instead set them to "warn" or
remove them from the top-level Cargo.toml so clippy doesn't fail immediately, or
apply the denies gradually by adding them only to specific crates that have been
remediated; specifically update the Cargo.toml entries for expect_used, panic,
and unwrap_used (the three keys shown) to a non-failing level or move them to
per-crate Cargo.toml files and stage fixes across trogon-std, trogon-gateway,
trogon-source-linear, etc., before enabling "deny" workspace-wide.

In `@rsworkspace/crates/trogon-gateway/src/config.rs`:
- Around line 1098-1120: In resolve_sentry, don’t treat a missing client_secret
as an implicit disable: if resolve_source_status("sentry", ...) indicates the
source is enabled but section.client_secret is None, push a typed
ConfigValidationError (e.g. a dedicated missing-field variant/struct such as
ConfigValidationError::missing("sentry","client_secret") or a new MissingField
error type) to errors and return None; update or add the error type to be a
proper struct/enum that implements Display and std::error::Error, and keep the
existing handling for invalid secrets (the match on SentryClientSecret::new)
unchanged.

In `@rsworkspace/crates/trogon-source-sentry/src/signature.rs`:
- Around line 33-39: The verify function uses expect() when constructing
HmacSha256 which violates the lint; add a new SignatureError variant (e.g.,
InvalidKey or HmacKeyError wrapping the underlying error type) and change
HmacSha256::new_from_slice(secret.as_bytes()).expect(...) to use
new_from_slice(...).map_err(SignatureError::InvalidKey)? (or wrap the
digest::InvalidLength) so the error is propagated instead of panicking; keep the
rest of verify (mac.update, mac.verify_slice) unchanged and return the mapped
SignatureError on failure.

---

Nitpick comments:
In `@rsworkspace/crates/trogon-gateway/src/config.rs`:
- Around line 1293-1300: The test matrix for resolve_sentry is missing cases for
token-validation failures of subject_prefix and stream_name; update the tests
that use sentry_toml and resolve_sentry to add two new cases that provide
invalid tokens for subject_prefix and for stream_name (e.g., malformed or empty
values) and assert that resolve_sentry returns the expected validation error for
each. Locate the tests that call sentry_toml(...) and resolve_sentry(...) and
add assertions for the two failure paths so the suite covers secret,
zero-duration, subject_prefix, and stream_name validation.
🪄 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: b5cf5b00-b223-48d9-a93b-c43087287647

📥 Commits

Reviewing files that changed from the base of the PR and between 85f57e0 and 553bbbd.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • devops/docker/compose/.env.example
  • devops/docker/compose/services/trogon-gateway/README.md
  • rsworkspace/Cargo.toml
  • rsworkspace/crates/trogon-gateway/Cargo.toml
  • rsworkspace/crates/trogon-gateway/src/config.rs
  • rsworkspace/crates/trogon-gateway/src/http.rs
  • rsworkspace/crates/trogon-gateway/src/streams.rs
  • rsworkspace/crates/trogon-source-sentry/Cargo.toml
  • rsworkspace/crates/trogon-source-sentry/src/config.rs
  • rsworkspace/crates/trogon-source-sentry/src/constants.rs
  • rsworkspace/crates/trogon-source-sentry/src/lib.rs
  • rsworkspace/crates/trogon-source-sentry/src/sentry_client_secret.rs
  • rsworkspace/crates/trogon-source-sentry/src/server.rs
  • rsworkspace/crates/trogon-source-sentry/src/signature.rs

Comment thread rsworkspace/Cargo.toml Outdated
Comment thread rsworkspace/crates/trogon-gateway/src/config.rs
Comment thread rsworkspace/crates/trogon-source-sentry/src/signature.rs
Comment thread devops/docker/compose/.env.example Outdated
Comment thread rsworkspace/crates/trogon-gateway/src/config.rs
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
yordis added 2 commits April 15, 2026 01:36
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
Copy link
Copy Markdown

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
rsworkspace/crates/trogon-gateway/src/config.rs (1)

1190-1208: Consider validating the upper bound before constructing the duration.

The current order creates NonZeroDuration first, then checks the max bound. This means a value like 2 will allocate a duration object only to fail the subsequent check. Reversing the order would be slightly more efficient:

♻️ Optional: check bound first
+    if section.nats_ack_timeout_secs > SENTRY_MAX_ACK_TIMEOUT_SECS {
+        errors.push(ConfigValidationError::invalid(
+            "sentry",
+            "nats_ack_timeout_secs",
+            DurationTooLong::new(SENTRY_MAX_ACK_TIMEOUT_SECS),
+        ));
+        return None;
+    }
+
     let nats_ack_timeout = match NonZeroDuration::from_secs(section.nats_ack_timeout_secs) {
         Ok(duration) => duration,
         Err(error) => {
             errors.push(ConfigValidationError::invalid(
                 "sentry",
                 "nats_ack_timeout_secs",
                 error,
             ));
             return None;
         }
     };
-    if section.nats_ack_timeout_secs > SENTRY_MAX_ACK_TIMEOUT_SECS {
-        errors.push(ConfigValidationError::invalid(
-            "sentry",
-            "nats_ack_timeout_secs",
-            DurationTooLong::new(SENTRY_MAX_ACK_TIMEOUT_SECS),
-        ));
-        return None;
-    }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@rsworkspace/crates/trogon-gateway/src/config.rs` around lines 1190 - 1208,
Move the SENTRY_MAX_ACK_TIMEOUT_SECS upper-bound check to run before calling
NonZeroDuration::from_secs: first if section.nats_ack_timeout_secs >
SENTRY_MAX_ACK_TIMEOUT_SECS {
errors.push(ConfigValidationError::invalid("sentry", "nats_ack_timeout_secs",
DurationTooLong::new(SENTRY_MAX_ACK_TIMEOUT_SECS))); return None; } and then
construct NonZeroDuration::from_secs(section.nats_ack_timeout_secs) handling its
Err case as before (pushing ConfigValidationError::invalid with the same
"sentry"/"nats_ack_timeout_secs" context), so you avoid allocating a duration
for values that will be rejected by the max check.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Nitpick comments:
In `@rsworkspace/crates/trogon-gateway/src/config.rs`:
- Around line 1190-1208: Move the SENTRY_MAX_ACK_TIMEOUT_SECS upper-bound check
to run before calling NonZeroDuration::from_secs: first if
section.nats_ack_timeout_secs > SENTRY_MAX_ACK_TIMEOUT_SECS {
errors.push(ConfigValidationError::invalid("sentry", "nats_ack_timeout_secs",
DurationTooLong::new(SENTRY_MAX_ACK_TIMEOUT_SECS))); return None; } and then
construct NonZeroDuration::from_secs(section.nats_ack_timeout_secs) handling its
Err case as before (pushing ConfigValidationError::invalid with the same
"sentry"/"nats_ack_timeout_secs" context), so you avoid allocating a duration
for values that will be rejected by the max check.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: c082ff32-53c2-46f8-9818-5b836238f936

📥 Commits

Reviewing files that changed from the base of the PR and between 553bbbd and 151b6dd.

⛔ Files ignored due to path filters (1)
  • rsworkspace/Cargo.lock is excluded by !**/*.lock
📒 Files selected for processing (14)
  • devops/docker/compose/.env.example
  • devops/docker/compose/services/trogon-gateway/README.md
  • rsworkspace/Cargo.toml
  • rsworkspace/crates/trogon-gateway/Cargo.toml
  • rsworkspace/crates/trogon-gateway/src/config.rs
  • rsworkspace/crates/trogon-gateway/src/http.rs
  • rsworkspace/crates/trogon-gateway/src/streams.rs
  • rsworkspace/crates/trogon-source-sentry/Cargo.toml
  • rsworkspace/crates/trogon-source-sentry/src/config.rs
  • rsworkspace/crates/trogon-source-sentry/src/constants.rs
  • rsworkspace/crates/trogon-source-sentry/src/lib.rs
  • rsworkspace/crates/trogon-source-sentry/src/sentry_client_secret.rs
  • rsworkspace/crates/trogon-source-sentry/src/server.rs
  • rsworkspace/crates/trogon-source-sentry/src/signature.rs
✅ Files skipped from review due to trivial changes (10)
  • rsworkspace/Cargo.toml
  • rsworkspace/crates/trogon-gateway/src/http.rs
  • devops/docker/compose/.env.example
  • rsworkspace/crates/trogon-gateway/Cargo.toml
  • devops/docker/compose/services/trogon-gateway/README.md
  • rsworkspace/crates/trogon-source-sentry/src/config.rs
  • rsworkspace/crates/trogon-source-sentry/Cargo.toml
  • rsworkspace/crates/trogon-source-sentry/src/lib.rs
  • rsworkspace/crates/trogon-source-sentry/src/sentry_client_secret.rs
  • rsworkspace/crates/trogon-source-sentry/src/constants.rs
🚧 Files skipped from review as they are similar to previous changes (2)
  • rsworkspace/crates/trogon-gateway/src/streams.rs
  • rsworkspace/crates/trogon-source-sentry/src/signature.rs

Copy link
Copy Markdown

@cursor cursor bot left a comment

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 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 151b6dd. Configure here.

Comment thread rsworkspace/crates/trogon-source-sentry/src/server.rs
@yordis yordis merged commit 38090c0 into main Apr 15, 2026
7 checks passed
@yordis yordis deleted the fix-linear branch April 15, 2026 15:26
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