Skip to content

fix(trogon-gateway): hardcode 1 MiB server limit to avoid async-nats race#119

Merged
yordis merged 1 commit intomainfrom
fix-linear
Apr 13, 2026
Merged

fix(trogon-gateway): hardcode 1 MiB server limit to avoid async-nats race#119
yordis merged 1 commit intomainfrom
fix-linear

Conversation

@yordis
Copy link
Copy Markdown
Member

@yordis yordis commented Apr 13, 2026

  • trogon_nats::connect always sets retry_on_initial_connect, which causes async-nats to return the Client before the background task that populates the ServerInfo watch channel has run — server_info().max_payload immediately after connect() therefore returns 0 (the Default value for usize)
  • MaxPayload::from_server_limit(0) saturates to a threshold of 0, routing every payload through the object-store claim-check path regardless of size; this was confirmed by inspecting the production OBJ_trogon-claims bucket, which contained all Linear webhook payloads (1.5–2.8 KiB) that should have been published inline
  • Hardcodes the NATS protocol default of 1 MiB as a safe stand-in until async-nats guarantees server_info() is populated before returning the Client, or trogon_nats::connect exposes a way to read server info post-connection accurately; the TODO in the code tracks what needs to be restored
  • Adds debug-level OTel instrumentation to ClaimCheckPublisher::publish_event recording messaging.message.body.size, trogon.claim_check.used, trogon.claim_check.threshold_bytes, and trogon.claim_check.key so the path decision is observable in traces going forward
  • Adds messaging.message.body.size to the linear.webhook span and logs server_max_payload_bytes / claim_check_threshold_bytes at gateway startup
  • Adds 20 real Linear webhook fixtures captured from production (Comment.create, Issue.create, Issue.update, IssueLabel.update) and a fixture-based test suite covering subject routing, payload preservation, and dedup header correctness

@cursor
Copy link
Copy Markdown

cursor bot commented Apr 13, 2026

PR Summary

Medium Risk
Changes how the gateway determines NATS max payload (now config-driven) which affects claim-check routing and message publishing behavior; misconfiguration could cause unexpected object-store usage or publish failures. Adds new telemetry and fixture-based tests, which are low risk but touch critical message-path observability.

Overview
The gateway no longer derives the claim-check threshold from nats.server_info().max_payload; it now uses a new config value TROGON_GATEWAY_NATS_MAX_PAYLOAD_BYTES (default 1 MiB) with validation to prevent 0, ensuring small payloads aren’t incorrectly routed through the object-store claim-check path.

Adds debug-level tracing in ClaimCheckPublisher::publish_event (payload size, threshold, whether claim-check was used, and key when applicable) and records messaging.message.body.size on the Linear webhook span, plus logs the resolved payload limit/threshold at startup.

Introduces fixture-based Linear webhook tests (with new JSON fixtures) to verify subject routing, payload preservation, and Nats-Msg-Id dedup header behavior.

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

@coderabbitai
Copy link
Copy Markdown

coderabbitai bot commented Apr 13, 2026

Warning

Rate limit exceeded

@yordis has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 7 minutes and 19 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 7 minutes and 19 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 219d3bcc-a499-4d36-9887-57871823bcce

📥 Commits

Reviewing files that changed from the base of the PR and between a8afecd and 1974b42.

📒 Files selected for processing (10)
  • rsworkspace/crates/trogon-gateway/src/config.rs
  • rsworkspace/crates/trogon-gateway/src/main.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/claim_check.rs
  • rsworkspace/crates/trogon-source-linear/src/server.rs
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Comment.create__comment_created_on_issue.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.create__issue_created_in_backlog.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__issue_moved_to_canceled.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__issue_reopened_to_todo.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.IssueLabel.update__label_applied.json
  • rsworkspace/crates/trogon-source-linear/tests/webhook_fixtures.rs

Walkthrough

Gateway now derives NATS max-payload from resolved config rather than server info; claim-check publishing adds detailed debug logs; Linear webhook handler records request body size in tracing spans; new Linear webhook fixtures and integration tests added.

Changes

Cohort / File(s) Summary
Gateway config & startup
rsworkspace/crates/trogon-gateway/src/config.rs, rsworkspace/crates/trogon-gateway/src/main.rs
Add nats_max_payload_bytes (validated NonZeroUsize) to config and use it to compute MaxPayload at startup; include server/threshold sizes in NATS-connected log; validate zero disallowed.
Claim-check publisher logging
rsworkspace/crates/trogon-nats/src/jetstream/claim_check.rs
Cache payload size and threshold, add structured tracing::debug! logs for both direct-publish and store-then-publish paths (include subject, sizes, threshold, used flag, and claim-check key).
Linear webhook instrumentation
rsworkspace/crates/trogon-source-linear/src/server.rs
Extend #[instrument] span to declare messaging.message.body.size and record actual request body length into the span during handling.
Linear webhook fixtures & tests
rsworkspace/crates/trogon-source-linear/tests/webhook_fixtures.rs, rsworkspace/crates/trogon-source-linear/tests/fixtures/*
Add new JSON fixtures for Comment.create, Issue.create (variants), Issue.update, IssueLabel.update and end-to-end tokio tests that sign requests, run the router with mock publishers/object store, assert 200 OK and expected NATS subject/payload fields.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested labels

rust:coverage-baseline-reset

Poem

🐰✨ I hopped through code with ears held high,
Config and payload taught me to fly.
Logs now whisper sizes true,
Fixtures bounce and tests pursue.
A little hop — the gateway’s new sky!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 70.00% 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 summarizes the main change: hardcoding a 1 MiB server limit to work around an async-nats race condition in the gateway initialization.
Description check ✅ Passed The description is directly related to the changeset, providing clear context about the problem, root cause, temporary fix, observability improvements, and test coverage added.

✏️ 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 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.

@github-actions
Copy link
Copy Markdown

github-actions bot commented Apr 13, 2026

badge

Code Coverage Summary

Details
Filename                                                                      Stmts    Miss  Cover    Missing
--------------------------------------------------------------------------  -------  ------  -------  ---------------------------------------------------------------------------------------------
crates/trogon-std/src/time/mock.rs                                              129       0  100.00%
crates/trogon-std/src/time/system.rs                                             35       0  100.00%
crates/acp-nats/src/agent/bridge.rs                                             123       4  96.75%   109-112
crates/acp-nats/src/agent/ext_method.rs                                          92       0  100.00%
crates/acp-nats/src/agent/js_request.rs                                         304       0  100.00%
crates/acp-nats/src/agent/list_sessions.rs                                       50       0  100.00%
crates/acp-nats/src/agent/set_session_model.rs                                   71       0  100.00%
crates/acp-nats/src/agent/cancel.rs                                             105       0  100.00%
crates/acp-nats/src/agent/test_support.rs                                       299       0  100.00%
crates/acp-nats/src/agent/new_session.rs                                         91       0  100.00%
crates/acp-nats/src/agent/fork_session.rs                                       106       0  100.00%
crates/acp-nats/src/agent/ext_notification.rs                                    88       0  100.00%
crates/acp-nats/src/agent/close_session.rs                                       67       0  100.00%
crates/acp-nats/src/agent/mod.rs                                                 65       0  100.00%
crates/acp-nats/src/agent/prompt.rs                                             633       0  100.00%
crates/acp-nats/src/agent/set_session_mode.rs                                    71       0  100.00%
crates/acp-nats/src/agent/load_session.rs                                       101       0  100.00%
crates/acp-nats/src/agent/resume_session.rs                                     102       0  100.00%
crates/acp-nats/src/agent/initialize.rs                                          83       0  100.00%
crates/acp-nats/src/agent/set_session_config_option.rs                           71       0  100.00%
crates/acp-nats/src/agent/authenticate.rs                                        52       0  100.00%
crates/acp-nats/src/agent/logout.rs                                              49       0  100.00%
crates/acp-nats-agent/src/connection.rs                                        1434       1  99.93%   686
crates/trogon-source-telegram/src/server.rs                                     387       0  100.00%
crates/trogon-source-telegram/src/signature.rs                                   38       0  100.00%
crates/trogon-source-telegram/src/config.rs                                      17       0  100.00%
crates/acp-nats/src/client/fs_read_text_file.rs                                 384       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/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/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/session_update.rs                                     55       0  100.00%
crates/acp-nats/src/client/mod.rs                                              2987       0  100.00%
crates/acp-nats/src/client/ext.rs                                               365       8  97.81%   193-204, 229-240
crates/acp-nats/src/client/fs_write_text_file.rs                                451       0  100.00%
crates/acp-nats/src/client/rpc_reply.rs                                          71       0  100.00%
crates/acp-nats/src/client/terminal_kill.rs                                     309       0  100.00%
crates/acp-nats/src/telemetry/metrics.rs                                         65       0  100.00%
crates/trogon-nats/src/jetstream/claim_check.rs                                 372       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/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/acp-nats/src/nats/subjects/subscriptions/all_agent_ext.rs                 11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/global_all.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_client.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/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/all_session.rs                   11       0  100.00%
crates/acp-nats/src/nats/subjects/subscriptions/one_agent.rs                     18       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-std/src/env/in_memory.rs                                           81       0  100.00%
crates/trogon-std/src/env/system.rs                                              17       0  100.00%
crates/acp-nats/src/ext_method_name.rs                                           70       0  100.00%
crates/acp-nats/src/acp_prefix.rs                                                51       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/acp-nats/src/error.rs                                                     84       0  100.00%
crates/acp-nats/src/config.rs                                                   204       0  100.00%
crates/acp-nats/src/client_proxy.rs                                             200       0  100.00%
crates/acp-nats/src/pending_prompt_waiters.rs                                   141       0  100.00%
crates/acp-nats/src/session_id.rs                                                72       0  100.00%
crates/acp-nats/src/jsonrpc.rs                                                    6       0  100.00%
crates/acp-nats/src/req_id.rs                                                    39       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-source-slack/src/server.rs                                        954       0  100.00%
crates/acp-nats-ws/src/config.rs                                                 83       0  100.00%
crates/acp-nats-ws/src/upgrade.rs                                                57       2  96.49%   59, 90
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/main.rs                                                  189      18  90.48%   89, 209-230, 308
crates/acp-nats/src/nats/subjects/stream.rs                                      58       0  100.00%
crates/acp-nats/src/nats/subjects/mod.rs                                        380       0  100.00%
crates/trogon-source-gitlab/src/signature.rs                                     30       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/acp-nats/src/nats/subjects/client_ops/terminal_wait_for_exit.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/session_update.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/fs_write_text_file.rs               15       0  100.00%
crates/acp-nats/src/nats/subjects/client_ops/session_request_permission.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_kill.rs                    15       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-incidentio/src/incidentio_signing_secret.rs                 67       0  100.00%
crates/trogon-source-incidentio/src/server.rs                                   365       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/signature.rs                                455       0  100.00%
crates/trogon-std/src/secret_string.rs                                           35       0  100.00%
crates/trogon-std/src/http.rs                                                    19       0  100.00%
crates/trogon-std/src/json.rs                                                    30       0  100.00%
crates/trogon-std/src/duration.rs                                                45       0  100.00%
crates/trogon-std/src/args.rs                                                    10       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/parsing.rs                                             285       1  99.65%   153
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/jetstream/streams.rs                                        194       4  97.94%   254-256, 266
crates/acp-nats/src/jetstream/ext_policy.rs                                      26       0  100.00%
crates/acp-nats/src/jetstream/provision.rs                                       61       0  100.00%
crates/acp-nats/src/jetstream/consumers.rs                                       99       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/notion_verification_token.rs                     17       0  100.00%
crates/trogon-source-notion/src/server.rs                                       351       8  97.72%   100-104, 137-138, 162-163
crates/acp-nats/src/nats/subjects/commands/cancel.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/close.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/commands/load.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/prompt.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/resume.rs                             18       0  100.00%
crates/trogon-source-linear/src/server.rs                                       392       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/acp-telemetry/src/log.rs                                                  71       1  98.59%   43
crates/acp-telemetry/src/metric.rs                                               35       3  91.43%   30-31, 39
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/trace.rs                                                32       3  90.62%   23-24, 32
crates/acp-telemetry/src/signal.rs                                                7       1  85.71%   43
crates/acp-telemetry/src/service_name.rs                                         49       0  100.00%
crates/trogon-gateway/src/http.rs                                               114       0  100.00%
crates/trogon-gateway/src/streams.rs                                            128       0  100.00%
crates/trogon-gateway/src/source_status.rs                                       32       0  100.00%
crates/trogon-gateway/src/main.rs                                                 4       0  100.00%
crates/trogon-gateway/src/config.rs                                            1371       0  100.00%
crates/trogon-std/src/dirs/system.rs                                             76       0  100.00%
crates/trogon-std/src/dirs/fixed.rs                                              84       0  100.00%
crates/acp-nats/src/nats/subjects/global/session_new.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/authenticate.rs                          8       0  100.00%
crates/acp-nats/src/nats/subjects/global/ext.rs                                  12       0  100.00%
crates/acp-nats/src/nats/subjects/global/initialize.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/logout.rs                                8       0  100.00%
crates/trogon-service-config/src/lib.rs                                          98       0  100.00%
crates/trogon-source-github/src/server.rs                                       351       0  100.00%
crates/trogon-source-github/src/signature.rs                                     64       0  100.00%
crates/trogon-source-github/src/config.rs                                        17       0  100.00%
crates/trogon-nats/src/client.rs                                                 25      25  0.00%    50-89
crates/trogon-nats/src/auth.rs                                                  119       0  100.00%
crates/trogon-nats/src/mocks.rs                                                 304       0  100.00%
crates/trogon-nats/src/token.rs                                                   8       0  100.00%
crates/trogon-nats/src/connect.rs                                               105      11  89.52%   22-24, 37, 49, 68-73
crates/trogon-nats/src/messaging.rs                                             552       2  99.64%   132, 142
crates/trogon-nats/src/nats_token.rs                                            161       0  100.00%
crates/trogon-nats/src/lease/mod.rs                                             603      13  97.84%   182-195
crates/trogon-nats/src/lease/renew_interval.rs                                   61       0  100.00%
crates/trogon-nats/src/lease/release.rs                                           5       5  0.00%    8-12
crates/trogon-nats/src/lease/lease_timing.rs                                     21       0  100.00%
crates/trogon-nats/src/lease/ttl.rs                                              76       0  100.00%
crates/trogon-nats/src/lease/provision.rs                                       210      10  95.24%   84-94
crates/trogon-nats/src/lease/lease_bucket.rs                                     19       0  100.00%
crates/trogon-nats/src/lease/lease_config_error.rs                               13       0  100.00%
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/renew.rs                                           263      19  92.78%   21-27, 46-57
crates/trogon-nats/src/lease/acquire.rs                                           8       8  0.00%    9-18
crates/acp-nats/src/nats/subjects/responses/cancelled.rs                         18       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/nats/subjects/responses/response.rs                          20       0  100.00%
crates/acp-nats/src/nats/subjects/responses/ext_ready.rs                         15       0  100.00%
TOTAL                                                                         25653     344  98.66%

Diff against main

Filename                                           Stmts    Miss  Cover
-----------------------------------------------  -------  ------  --------
crates/trogon-nats/src/jetstream/claim_check.rs       +4       0  +100.00%
crates/trogon-gateway/src/config.rs                  +21       0  +100.00%
TOTAL                                                +25       0  +0.00%

Results for commit: 1974b42

Minimum allowed coverage is 95%

♻️ This comment has been updated with latest results

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

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

75-77: Consider making the temporary payload fallback configurable.

A fixed 1 MiB stand-in can still misclassify messages on clusters configured with a lower server max_payload. An optional config/env override (defaulting to 1 MiB) would reduce that risk while the async-nats race is unresolved.

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

In `@rsworkspace/crates/trogon-gateway/src/main.rs` around lines 75 - 77, The
temporary hardcoded fallback of 1 MiB uses the local variable server_max_payload
and is passed to MaxPayload::from_server_limit, which should be configurable;
read an optional config/env override (e.g., SERVER_MAX_PAYLOAD_FALLBACK) and
parse it to set server_max_payload (defaulting to 1024 * 1024 if unset/invalid),
then pass that value into MaxPayload::from_server_limit where max_payload is
created so deployments can lower the temporary fallback without changing the
code.
🤖 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/crates/trogon-gateway/src/main.rs`:
- Line 74: Replace the placeholder tracking issue URL in the comment "//
Tracking issue: https://github.com/TrogonStack/trogonai/issues/TODO" with a
real, actionable issue link or remove the line; locate that exact comment string
in main.rs (top-level comment near the crate header) and update it to point to
the correct GitHub issue or a link to your project board so the tracking
reference is usable.

In
`@rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-1315-71e1-9e58-50f600aab7c8.json`:
- Line 1: The fixture contains real PII in JSON fields; replace any
human-identifying values under "actor", "assignee", "creatorId", "assigneeId",
and "subscriberIds" and any direct profile URLs with anonymized/synthetic values
(e.g., use fake names like "Test User", emails like "test+user@example.com", and
avatarUrl/url values pointing to a non-identifying placeholder), and ensure
fields "email", "name", "avatarUrl", "url", and any GUID-like IDs you cannot
regenerate are either anonymized or replaced with stable test IDs; update the
"actor" and "assignee" objects and any top-level URLs in the JSON (search for
keys "actor", "assignee", "creatorId", "subscriberIds", "avatarUrl", "email",
"url") and commit the sanitized fixture.

In
`@rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-2ab6-79f2-b417-b26f6ef51798.json`:
- Line 1: The fixture contains real PII in fields like actor.name, actor.email,
actor.avatarUrl, actor.url, assignee.name, assignee.email, avatarUrl, and any
subscriber/creator IDs embedded as contact info; replace those with
deterministic synthetic values while preserving IDs and payload shape (e.g., set
names to "Test User", emails to "user+<actor.id>@example.com", avatarUrl/profile
URLs to a non-production placeholder URL, and keep all UUIDs, numeric fields,
arrays, and keys unchanged); ensure description/descriptionData and all routing
fields (actor.id, assigneeId, creatorId, subscriberIds, teamId, stateId,
labelIds) remain intact so tests still exercise the same paths.

In
`@rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-3853-7f60-be17-e7e9e548acb7.json`:
- Line 1: The fixture contains real PII in fields under "actor", "assignee", and
creator/subscriber fields (e.g., actor.name, actor.email, actor.avatarUrl,
actor.url, assignee.name, assignee.email, assignee.avatarUrl, assignee.url,
creatorId, subscriberIds); update the JSON to redact/anonymize those values
(replace names with "Test User", emails with "user@example.com", avatarUrl/url
with a placeholder image/profile URL or remove them, and optionally replace real
GUIDs with synthetic IDs) so the fixture contains no production-identifiable
data while preserving schema and keys like "assignee", "actor", "creatorId", and
"subscriberIds".

---

Nitpick comments:
In `@rsworkspace/crates/trogon-gateway/src/main.rs`:
- Around line 75-77: The temporary hardcoded fallback of 1 MiB uses the local
variable server_max_payload and is passed to MaxPayload::from_server_limit,
which should be configurable; read an optional config/env override (e.g.,
SERVER_MAX_PAYLOAD_FALLBACK) and parse it to set server_max_payload (defaulting
to 1024 * 1024 if unset/invalid), then pass that value into
MaxPayload::from_server_limit where max_payload is created so deployments can
lower the temporary fallback without changing the code.
🪄 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: e43d46c1-f956-402c-a479-180f30469634

📥 Commits

Reviewing files that changed from the base of the PR and between fc3e8f0 and 9ba93bd.

📒 Files selected for processing (24)
  • rsworkspace/crates/trogon-gateway/src/main.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/claim_check.rs
  • rsworkspace/crates/trogon-source-linear/src/server.rs
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Comment.create__019d814d-a5a7-7e33-9b69-ee736af5afea.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Comment.create__019d814d-b505-71c2-ac44-06f7f78fffc4.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Comment.create__019d814d-f983-7152-b1ee-d910e7e77048.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Comment.create__019d8434-663b-7eb0-85ba-0b7b5b611645.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.create__019d814e-13ec-7911-bbcc-5dadd1d53273.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-b876-7e02-9c0c-3d39d4a0f77c.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-bb7a-78e2-aba2-527c675994c4.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-be7d-70c0-9578-5d6eb18fefdb.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-bf6a-7bb1-9420-c0768e1e8af8.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-bfad-7b60-8fc4-7773cfd2b133.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-ef1e-7db1-9a2a-cc152e45844d.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-f469-7470-9e01-6cd963190827.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-1164-75d2-a285-38e240ced9b2.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-12a9-7f53-b3f7-185229a046bd.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-1315-71e1-9e58-50f600aab7c8.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-145b-7f03-b904-f00a96e43a71.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-151a-7543-978b-ca61e2c4fa9f.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-2ab6-79f2-b417-b26f6ef51798.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814e-3853-7f60-be17-e7e9e548acb7.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.IssueLabel.update__019d814e-135e-7583-9a29-518b050d879c.json
  • rsworkspace/crates/trogon-source-linear/tests/webhook_fixtures.rs

Comment thread rsworkspace/crates/trogon-gateway/src/main.rs Outdated
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 3441ead. Configure here.

Comment thread rsworkspace/crates/trogon-nats/src/jetstream/claim_check.rs
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: 1

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

125-128: Add focused config tests for default/override and zero rejection.

This new env-backed control path should have regression tests for: default 1_048_576, explicit override, and invalid 0 handling.

🤖 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 125 - 128, Add
unit/integration tests that exercise the env-backed nats_max_payload_bytes
config: write tests that (1) do not set TROGON_GATEWAY_NATS_MAX_PAYLOAD_BYTES
and assert the loaded Config.nats_max_payload_bytes == 1_048_576, (2) set
TROGON_GATEWAY_NATS_MAX_PAYLOAD_BYTES to a nonzero value and assert the override
is picked up, and (3) set it to "0" and assert config loading fails (returns an
Err or validation error) rather than accepting zero. Use the same config loader
used in this crate (e.g. Config::from_env or the crate's config load function),
manipulate the environment only for the duration of each test, and clean
up/reset the env between cases.
🤖 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/crates/trogon-gateway/src/config.rs`:
- Around line 127-128: The nats_max_payload_bytes field currently allows zero;
make zero unrepresentable by changing the field to a constrained type (e.g.,
std::num::NonZeroUsize or a custom newtype like NatsMaxPayloadBytes) and update
the config resolution path (the resolve(...) code that constructs the config) to
validate and reject 0 explicitly if you cannot use NonZeroUsize; ensure any
parsing/Env deserialization of TROGON_GATEWAY_NATS_MAX_PAYLOAD_BYTES fails with
a clear error when value == 0 and propagate that error instead of storing 0 so
callers of nats_max_payload_bytes always see a non-zero value.

---

Nitpick comments:
In `@rsworkspace/crates/trogon-gateway/src/config.rs`:
- Around line 125-128: Add unit/integration tests that exercise the env-backed
nats_max_payload_bytes config: write tests that (1) do not set
TROGON_GATEWAY_NATS_MAX_PAYLOAD_BYTES and assert the loaded
Config.nats_max_payload_bytes == 1_048_576, (2) set
TROGON_GATEWAY_NATS_MAX_PAYLOAD_BYTES to a nonzero value and assert the override
is picked up, and (3) set it to "0" and assert config loading fails (returns an
Err or validation error) rather than accepting zero. Use the same config loader
used in this crate (e.g. Config::from_env or the crate's config load function),
manipulate the environment only for the duration of each test, and clean
up/reset the env between cases.
🪄 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: a083c97c-4481-4b8a-b1d9-ab64d1c870a4

📥 Commits

Reviewing files that changed from the base of the PR and between 9ba93bd and 5bd192b.

📒 Files selected for processing (2)
  • rsworkspace/crates/trogon-gateway/src/config.rs
  • rsworkspace/crates/trogon-gateway/src/main.rs
🚧 Files skipped from review as they are similar to previous changes (1)
  • rsworkspace/crates/trogon-gateway/src/main.rs

Comment thread rsworkspace/crates/trogon-gateway/src/config.rs
@yordis yordis force-pushed the fix-linear branch 7 times, most recently from fddac3d to a8afecd Compare April 13, 2026 15:13
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 (2)
rsworkspace/crates/trogon-source-linear/tests/webhook_fixtures.rs (2)

88-90: Assert message count before indexing messages[0].

Several tests index directly into the first publish result; if publish fails, that panics with a less-informative error. Add assert_eq!(messages.len(), 1) before first access in each case.

🧪 Representative change
     let messages = publisher.published_messages();
+    assert_eq!(messages.len(), 1);
     let published: serde_json::Value =
         serde_json::from_slice(&messages[0].payload).expect("valid JSON");

Also applies to: 110-113, 144-147, 182-184, 219-221

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

In `@rsworkspace/crates/trogon-source-linear/tests/webhook_fixtures.rs` around
lines 88 - 90, Add an explicit assertion that the publisher produced exactly one
message before indexing into messages[0]; after calling
publisher.published_messages() (the messages variable) insert
assert_eq!(messages.len(), 1) immediately prior to any use of messages[0] (e.g.,
before the serde_json::from_slice(&messages[0].payload) call and the other
occurrences in the file) so tests fail with a clear assertion message instead of
an out-of-bounds panic.

15-16: Use a realistic test constant for NATS claim check threshold instead of usize::MAX.

Tests using usize::MAX for MaxPayload::from_server_limit() don't exercise the actual boundary conditions. Align this with the 1 MiB fallback used elsewhere in the codebase (e.g., Slack source defaults to 1 MiB).

Suggested change
 const TEST_SECRET: &str = "test-secret";
+const TEST_SERVER_MAX_PAYLOAD_BYTES: usize = 1024 * 1024;
 ...
     let cc = ClaimCheckPublisher::new(
         publisher.clone(),
         MockObjectStore::new(),
         "test-bucket".to_string(),
-        MaxPayload::from_server_limit(usize::MAX),
+        MaxPayload::from_server_limit(TEST_SERVER_MAX_PAYLOAD_BYTES),
     );

Also applies to: 32-37

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

In `@rsworkspace/crates/trogon-source-linear/tests/webhook_fixtures.rs` around
lines 15 - 16, Replace the unrealistic usize::MAX used in webhook_fixtures.rs
for the NATS claim check threshold with a realistic 1 MiB value (1 * 1024 *
1024) so MaxPayload::from_server_limit() exercises real limits; update the test
constant(s) used around TEST_SECRET and any calls to
MaxPayload::from_server_limit() in that file (including the occurrences around
lines 32–37) to use the 1 MiB fallback consistent with the Slack source default.
🤖 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-source-linear/tests/webhook_fixtures.rs`:
- Around line 88-90: Add an explicit assertion that the publisher produced
exactly one message before indexing into messages[0]; after calling
publisher.published_messages() (the messages variable) insert
assert_eq!(messages.len(), 1) immediately prior to any use of messages[0] (e.g.,
before the serde_json::from_slice(&messages[0].payload) call and the other
occurrences in the file) so tests fail with a clear assertion message instead of
an out-of-bounds panic.
- Around line 15-16: Replace the unrealistic usize::MAX used in
webhook_fixtures.rs for the NATS claim check threshold with a realistic 1 MiB
value (1 * 1024 * 1024) so MaxPayload::from_server_limit() exercises real
limits; update the test constant(s) used around TEST_SECRET and any calls to
MaxPayload::from_server_limit() in that file (including the occurrences around
lines 32–37) to use the 1 MiB fallback consistent with the Slack source default.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 90b11344-ca8a-47cf-b8db-8aadcb525290

📥 Commits

Reviewing files that changed from the base of the PR and between fddac3d and a8afecd.

📒 Files selected for processing (10)
  • rsworkspace/crates/trogon-gateway/src/config.rs
  • rsworkspace/crates/trogon-gateway/src/main.rs
  • rsworkspace/crates/trogon-nats/src/jetstream/claim_check.rs
  • rsworkspace/crates/trogon-source-linear/src/server.rs
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Comment.create__019d8434-663b-7eb0-85ba-0b7b5b611645.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.create__019d814e-13ec-7911-bbcc-5dadd1d53273.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-b876-7e02-9c0c-3d39d4a0f77c.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-bf6a-7bb1-9420-c0768e1e8af8.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.IssueLabel.update__019d814e-135e-7583-9a29-518b050d879c.json
  • rsworkspace/crates/trogon-source-linear/tests/webhook_fixtures.rs
✅ Files skipped from review due to trivial changes (7)
  • rsworkspace/crates/trogon-source-linear/src/server.rs
  • rsworkspace/crates/trogon-gateway/src/main.rs
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.IssueLabel.update__019d814e-135e-7583-9a29-518b050d879c.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.create__019d814e-13ec-7911-bbcc-5dadd1d53273.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Comment.create__019d8434-663b-7eb0-85ba-0b7b5b611645.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-bf6a-7bb1-9420-c0768e1e8af8.json
  • rsworkspace/crates/trogon-source-linear/tests/fixtures/linear.Issue.update__019d814d-b876-7e02-9c0c-3d39d4a0f77c.json
🚧 Files skipped from review as they are similar to previous changes (1)
  • rsworkspace/crates/trogon-nats/src/jetstream/claim_check.rs

…ts race

When `retry_on_initial_connect` is set, async-nats returns the `Client`
before the background connection task populates the `ServerInfo` watch
channel, so `server_info().max_payload` is always 0 immediately after
connect — collapsing the claim-check threshold to 0 and routing every
payload through the object-store path.

`trogon_nats::connect` always sets `retry_on_initial_connect`, making
this race deterministic in production.

Workaround: read the limit from `TROGON_GATEWAY_NATS_MAX_PAYLOAD_BYTES`
(default 1 MiB) instead of querying the server. The original line is
kept as a comment pending resolution of the upstream race.

Tracking issue: #122

Also adds OTel instrumentation to `ClaimCheckPublisher::publish_event`
and the Linear webhook handler so the claim-check path decision is
observable in traces and structured logs, and adds 20 production fixture
payloads (PII-sanitised) with integration tests for the Linear source.

Signed-off-by: Yordis Prieto <yordis.prieto@gmail.com>
@yordis yordis merged commit 07f567e into main Apr 13, 2026
7 checks passed
@yordis yordis deleted the fix-linear branch April 13, 2026 17:32
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