Skip to content

fix(web): send the Railway token as a RailwayConnectRequest instance - #1221

Merged
Makisuo merged 2 commits into
mainfrom
fix/railway-connect-payload
Oct 3, 2026
Merged

Makisuo merged 2 commits into
mainfrom
fix/railway-connect-payload

Conversation

@Makisuo

@Makisuo Makisuo commented Oct 3, 2026 •

Copy link
Copy Markdown
Collaborator

What

The Railway connect form now sends new RailwayConnectRequest({ token }) instead of a plain { token } object. It's a one-line change in railway-integration-card.tsx.

Why

Connecting Railway in production always failed with "Failed to connect Railway", whatever token was used.

railwayConnect is a v1 endpoint, and its payload is a Schema.Class. The HttpApi client rejects a plain object when it encodes the payload, so the request is never sent. TypeScript accepts the plain object because it has the same shape. The Cloudflare, Hazel and GitHub connect flows already construct their request classes; the Railway form didn't.

Evidence

  • Production traces: maple-web has http.client GET /api/integrations/railway/status spans, but no http.client PUT for the connect. maple-api has no PUT /api/integrations/railway and no RailwayMetricsService.connect span. The request never left the browser.
  • Schema check: Schema.encodeUnknownExit(RailwayConnectRequest) returns Failure for { token } and Success for new RailwayConnectRequest({ token }).

Testing

  • Web typecheck and oxlint pass.
  • The connect flow has not been re-run in a browser. After deploy, connecting a Railway token should produce a RailwayMetricsService.connect span.

View with [code]smith Autofix with [code]smith
Need help on this PR? Tag @codesmith-bot with what you need. Autofix is disabled.

Summary by CodeRabbit

  • Bug Fixes
    • Railway connection requests now use the format expected by the service, helping token submissions work correctly.

The v1 integrations payloads are Schema.Class, so the client rejects a
plain `{ token }` object while encoding and never sends the PUT. Every
connect attempt showed "Failed to connect Railway" with no request
reaching the API. Construct the class, as the other connect flows do.
@maple-review-bot

maple-review-bot Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 3/5 · needs attention
The fix is correct and matches the other connect flows; the only soft spot is the unguarded class constructor on the submit path.
quality 90/100 · 1 warning · tests missing · risk low

The Railway connect form now sends new RailwayConnectRequest({ token }) instead of a plain object, matching what the Cloudflare, Hazel and GitHub forms already do; the HttpApi client encodes v1 payloads from Schema.Class instances, so the plain object was rejected before the request was sent. The fix is right and contained.

  • railwayConnect payload is now a RailwayConnectRequest instance

Findings

🟠 Warning · F1 · Over-long token throws in the RailwayConnectRequest constructor, leaving the form stuck

correctness · apps/web/src/components/integrations/railway-integration-card.tsx:57

RailwayConnectRequest validates in its constructor (Schema.isMinLength(8), Schema.isMaxLength(512), packages/domain/src/http/integrations.ts:904), so a pasted token longer than 512 characters throws a ParseError while the argument is evaluated. The throw happens before await connect(...) completes, so setSubmitting(false) on line 58 never runs: the form keeps its spinner and shows no error, and the user has to reload the page. The button's token.trim().length < 8 guard only covers the minimum.

Wrap the submit body in `try { ... } finally { setSubmitting(false) }` so a construction throw still clears the spinner and surfaces a message, or extend the button's disabled condition to `token.trim().length > 512`.
🤖 Prompt to fix this finding with an AI agent
Findings from an automated review of commit 12d893443544e7c1874672e081cb10ba1508573b. Verify each one against the current code before changing anything, fix only those that still apply, and keep each fix to the lines it names.

---

F1 · Warning · correctness · apps/web/src/components/integrations/railway-integration-card.tsx:57
Over-long token throws in the `RailwayConnectRequest` constructor, leaving the form stuck
`RailwayConnectRequest` validates in its constructor (`Schema.isMinLength(8)`, `Schema.isMaxLength(512)`, packages/domain/src/http/integrations.ts:904), so a pasted token longer than 512 characters throws a `ParseError` while the argument is evaluated. The throw happens before `await connect(...)` completes, so `setSubmitting(false)` on line 58 never runs: the form keeps its spinner and shows no error, and the user has to reload the page. The button's `token.trim().length < 8` guard only covers the minimum.
Suggested fix: Wrap the submit body in `try { ... } finally { setSubmitting(false) }` so a construction throw still clears the spinner and surfaces a message, or extend the button's disabled condition to `token.trim().length > 512`.
What was checked
  • RailwayConnectRequest and the v1 railwayConnect endpoint exist at the imported path (packages/domain/src/http/integrations.ts:904, :1184)
  • Other connect flows already construct request classes (integration-connect.tsx:266, github-integration-card.tsx:185, destination-dialog.tsx:384)
  • Server route trims and validates the token too (apps/api/src/routes/v1/integrations.http.ts:531), so the trimmed payload stays compatible

12d8934 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@coderabbitai

coderabbitai Bot commented Oct 3, 2026

Copy link
Copy Markdown

Review in Change Stack →

Navigate logical layers of code changes, visualize relationships, and explore their blast radius.

Note

Currently processing new changes in this PR. This may take a few minutes, please wait...

⚙️ Run configuration
  • Configuration used: defaults
  • Review profile: CHILL
  • Plan: Advanced
  • Run ID: 0dab5f8e-c192-46e3-b3bd-c2b742ea8639
📥 Commits

Reviewing files that changed from the base of the PR and between 063904d and 12d8934.

📒 Files selected for processing (1)
  • apps/web/src/components/integrations/railway-integration-card.tsx
 ________________________________________________________________
< Your exception handling needs a therapist and a boundary plan. >
 ----------------------------------------------------------------
  \
   \   \
        \ /\
        ( )
      .( o ).
✨ Finishing Touches
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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.

@maple-review-bot maple-review-bot 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.

1 inline note from Maple's review. The score and summary are in the review comment above.

Comment thread apps/web/src/components/integrations/railway-integration-card.tsx Outdated
@maple-review-bot

maple-review-bot Bot commented Oct 3, 2026 •

Copy link
Copy Markdown

Maple review

🟡 Confidence 3/5 · needs attention
Contained frontend change; the decode path mirrors existing decodeUnknownOption usage, but no test covers the new disabled/validation states.
quality 90/100 · 1 warning · tests missing · risk low

Warning

This review ended early; what follows is what it established.

The Railway token form now validates the pasted token by decoding it into a RailwayConnectRequest instance and submits that instance, replacing the constructor call that threw on out-of-range tokens. Safe to merge.

  • RailwayTokenForm decodes { token: token.trim() } with decodeUnknownOption instead of constructing the request class
  • Submit is disabled while the decode fails, and a length hint is shown

Still open from earlier reviews

What was checked
  • RailwayConnectRequest field rules (packages/domain/src/http/integrations.ts:904-906): trimmed, 8-512, and the decode input is pre-trimmed
  • Length is the only rule the decode can fail, so the hint text matches the failure
  • new ...Request(...) for mutations is the existing convention (integration-connect.tsx:266,312,347)

26ac2b4 · Updated on every push. Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.

@Makisuo
Makisuo merged commit a23b446 into main Oct 3, 2026
40 checks passed
@Makisuo
Makisuo deleted the fix/railway-connect-payload branch October 3, 2026 22: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