Skip to content

Inbox integration#882

Merged
vdimarco merged 6 commits intomasterfrom
inbox-integration
Jan 23, 2026
Merged

Inbox integration#882
vdimarco merged 6 commits intomasterfrom
inbox-integration

Conversation

@vdimarco
Copy link
Contributor

@vdimarco vdimarco commented Jan 23, 2026

Greptile Overview

Greptile Summary

Integrated Terragon inbox feature with secure authentication bridge between Gatewayz and Terragon systems.

Key changes:

  • Added /inbox route with embedded Terragon iframe for AI coding agent capabilities
  • Implemented authentication bridge API (/api/terragon/auth) that generates encrypted tokens using AES-256-GCM with HMAC signatures
  • Used postMessage API to securely transfer auth tokens to iframe (avoiding URL exposure)
  • Added comprehensive test coverage (808 total test lines across 2 test files)
  • Updated footer component to hide on inbox pages for full-screen experience

Security approach:

  • API keys validated against backend before issuing tokens
  • Tokens encrypted with AES-256-GCM and signed with HMAC-SHA256
  • 1-hour token expiration
  • postMessage origin validation
  • Iframe sandbox restrictions

Architecture:
The auth bridge creates a secure token containing user metadata (userId, email, username, tier, keyHash) that Terragon can decrypt to authenticate users without exposing Gatewayz API keys.

Confidence Score: 3/5

  • Safe to merge with one critical cryptographic issue that should be addressed before production use
  • The implementation is well-tested and follows security best practices (encryption, HMAC signing, postMessage validation). However, the weak key derivation in the encryption function (padding with "0" characters) is a security concern that should be fixed. The extensive test coverage and thoughtful security design (postMessage over URL, origin validation, sandbox restrictions) are strong positives.
  • Pay close attention to src/app/api/terragon/auth/route.ts - fix the key derivation issue before deploying to production

Important Files Changed

Filename Overview
src/app/api/terragon/auth/tests/route.test.ts Comprehensive test suite for auth bridge API with 337 lines covering encryption, validation, error cases, and security scenarios
src/app/api/terragon/auth/route.ts Auth bridge API with AES-256-GCM encryption and HMAC signing - has weak key derivation issue that should be fixed
src/app/inbox/tests/page.test.tsx Extensive test suite covering authentication flows, iframe security, postMessage communication, and error states
src/app/inbox/page.tsx Inbox page with secure postMessage-based auth flow - has overly permissive sandbox attribute

Sequence Diagram

sequenceDiagram
    participant User
    participant InboxPage as Inbox Page<br/>(Frontend)
    participant AuthBridge as Auth Bridge API
    participant Backend as Gatewayz Backend
    participant Terragon as Terragon Inbox<br/>(iframe)

    User->>InboxPage: Visit /inbox
    InboxPage->>InboxPage: Check auth status
    
    alt User not authenticated
        InboxPage->>User: Show login prompt
        User->>InboxPage: Click Sign In
        InboxPage->>User: Redirect to Privy login
    else User authenticated
        InboxPage->>AuthBridge: POST request with user data
        AuthBridge->>Backend: Validate credentials
        Backend-->>AuthBridge: Return validation result
        
        alt Credentials valid
            AuthBridge->>AuthBridge: Generate encrypted token<br/>with HMAC signature
            AuthBridge-->>InboxPage: Return encrypted token
            InboxPage->>InboxPage: Build iframe URL<br/>(embed mode, awaitAuth flag)
            InboxPage->>Terragon: Load iframe
            Terragon-->>InboxPage: iframe loaded event
            InboxPage->>Terragon: postMessage with auth token
            Terragon->>Terragon: Decrypt and validate token
            Terragon-->>User: Show authenticated inbox
        else Credentials invalid
            AuthBridge-->>InboxPage: Return error
            InboxPage->>Terragon: Load iframe without auth
            Terragon-->>User: Show Terragon login
        end
    end
    
    Note over InboxPage,Terragon: Security: Token sent via postMessage<br/>not URL to avoid exposure
Loading

root and others added 3 commits January 23, 2026 02:03
- Add /inbox page with iframe embedding and GatewayZ auth passthrough
- Add /api/terragon/auth endpoint for HMAC-signed token generation
- Update footer to hide on inbox pages
- Add comprehensive tests for inbox page and auth bridge API
- Update README with inbox page documentation

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add tests for body class manipulation on mount/unmount
- Add tests for overflow style handling
- Add tests for container classes
- Coverage improved to 93% statements

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Security improvements:
1. Validate API key against backend before issuing tokens
2. Encrypt token payload with AES-256-GCM instead of base64 encoding
3. Pass auth token via postMessage API instead of URL query params
4. Store keyHash in token instead of full API key

This addresses the 3 security concerns raised in the code review:
- API key validation now calls backend /api/user/me endpoint
- Payload is encrypted, not just encoded (prevents token interception)
- Token not exposed in URL (prevents leakage via logs/history/referer)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@chatgpt-codex-connector
Copy link

You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard.

@vercel
Copy link

vercel bot commented Jan 23, 2026

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Review Updated (UTC)
gatewayz-frontend Ready Ready Preview, Comment Jan 23, 2026 5:01am

@coderabbitai
Copy link

coderabbitai bot commented Jan 23, 2026

Warning

Rate limit exceeded

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

⌛ 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.

Note

Other AI code review bot(s) detected

CodeRabbit has detected other AI code review bot(s) in this pull request and will avoid duplicating their findings in the review comments. This may lead to a less comprehensive review.

✨ Finishing touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch inbox-integration

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Contributor

@greptile-apps greptile-apps bot left a comment

Choose a reason for hiding this comment

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

2 files reviewed, 2 comments

Edit Code Review Agent Settings | Greptile

title="Coding Inbox"
onLoad={handleIframeLoad}
allow="clipboard-read; clipboard-write"
sandbox="allow-scripts allow-same-origin allow-forms allow-popups allow-popups-to-escape-sandbox"
Copy link
Contributor

Choose a reason for hiding this comment

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

allow-popups-to-escape-sandbox allows the iframe to open windows that escape the sandbox, which could be a security risk if the embedded content is compromised.

Consider if this permission is necessary for your use case.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/app/inbox/page.tsx
Line: 366:366

Comment:
`allow-popups-to-escape-sandbox` allows the iframe to open windows that escape the sandbox, which could be a security risk if the embedded content is compromised.

Consider if this permission is necessary for your use case.

How can I resolve this? If you propose a fix, please make it concise.

* Returns: iv.ciphertext.authTag (all base64url encoded)
*/
function encryptPayload(payload: string, secret: string): string {
const key = Buffer.from(secret.padEnd(32, "0").slice(0, 32)); // Ensure 32 bytes
Copy link
Contributor

Choose a reason for hiding this comment

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

Weak key derivation - padding with "0" characters is predictable and weakens the encryption key strength. Use a proper key derivation function like PBKDF2, HKDF, or scrypt instead of simple padding.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/app/api/terragon/auth/route.ts
Line: 39:39

Comment:
Weak key derivation - padding with "0" characters is predictable and weakens the encryption key strength. Use a proper key derivation function like PBKDF2, HKDF, or scrypt instead of simple padding.

How can I resolve this? If you propose a fix, please make it concise.

…-escape-sandbox

- Replace weak key padding with HKDF (SHA-256) for AES-256-GCM encryption key derivation
- Remove allow-popups-to-escape-sandbox from iframe sandbox attribute for improved security
- Update tests to match new key derivation method

Addresses code review security concerns:
- Weak key derivation using padEnd("0") was predictable and weakened encryption
- allow-popups-to-escape-sandbox allowed iframe popups to escape sandbox restrictions

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Comment on lines 194 to 202
const handleRetry = useCallback(() => {
setConnectionError(false);
setIsLoading(true);
iframeLoadedRef.current = false;
authSentRef.current = false;
setIframeKey((prev) => prev + 1);

if (loadTimeoutRef.current) {
clearTimeout(loadTimeoutRef.current);

This comment was marked as outdated.

Copy link
Contributor Author

Auto-Fix Status Update

Trigger

PR synchronize event - checking for CI failures and review comments.

Review Comments Addressed

The following Greptile review comments were identified and have already been fixed in commit 44a6af21:

  1. Weak key derivation (src/app/api/terragon/auth/route.ts:39)

    • Issue: Padding secret with "0" characters was predictable and weakened encryption key strength
    • Fix: Replaced with HKDF (SHA-256) for proper cryptographic key derivation using hkdfSync()
  2. allow-popups-to-escape-sandbox (src/app/inbox/page.tsx:366)

    • Issue: This sandbox permission allowed iframe popups to escape sandbox restrictions, posing a security risk
    • Fix: Removed allow-popups-to-escape-sandbox from iframe sandbox attribute

Local Verification

  • ✅ All 39 tests pass for inbox and terragon auth modules
  • ✅ TypeScript type check passes
  • ✅ All CI checks now passing (Vercel, CodeRabbit, GitGuardian)

Status

No additional changes required - the security fixes from the Greptile review have already been implemented and pushed. The PR is ready for review and merge.


Automated by Terragon Agent

Resolved conflicts by keeping security fixes:
- Use HKDF for key derivation instead of weak padding
- Remove allow-popups-to-escape-sandbox from iframe sandbox

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@sentry
Copy link

sentry bot commented Jan 23, 2026

Codecov Report

✅ All modified and coverable lines are covered by tests.

📢 Thoughts on this report? Let us know!

@blacksmith-sh

This comment has been minimized.

@openhands-ai
Copy link

openhands-ai bot commented Jan 23, 2026

Looks like there are a few issues preventing this PR from being merged!

  • GitHub Actions are failing:
    • CI

If you'd like me to help, just leave a comment, like

@OpenHands please fix the failing actions on PR #882 at branch `inbox-integration`

Feel free to include any additional details that might help me get this PR into a better state.

You can manage your notification settings

The handleRetry function was not clearing the authToken and terragonUrl
state, which meant the useEffect would not re-fetch a fresh token when
the user clicked retry. This could cause persistent authentication
failures if the original 1-hour token had expired.

Changes:
- Clear authToken and terragonUrl in handleRetry
- Add iframeKey to useEffect dependencies to trigger fresh fetch
- Remove redundant timeout from handleRetry (useEffect handles it)
- Add test case verifying fresh token fetch on retry

Fixes: Sentry bug report about handleRetry not re-fetching auth token

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@vdimarco vdimarco merged commit 2b9d6e5 into master Jan 23, 2026
17 checks passed
Copy link
Contributor Author

Auto-Fix Status Update

Trigger

PR synchronize event - E2E test failures detected from Blacksmith CI report.

Issues Identified

The following E2E tests were failing in chat-streaming-live.spec.ts:

  • should stream response and display incrementally (timeout after 60s)
  • should handle streaming with reasoning content (flaky - passed on retry)
  • should display error for 500 server error (flaky - passed on retry)

Root Cause: All failures were due to page.waitForLoadState('networkidle') timing out. The chat page has continuous background network requests (analytics, auth polling, websockets) that prevent the network from ever becoming "idle" within the 60 second test timeout.

Fix Applied

Replaced waitForLoadState('networkidle') with waitForLoadState('domcontentloaded') in all 14 occurrences within e2e/chat-streaming-live.spec.ts. The domcontentloaded state is more appropriate for pages with persistent background connections, as it allows tests to proceed as soon as the DOM is ready without waiting for all network activity to cease.

Local Verification

  • ✅ TypeScript type check passes
  • ✅ ESLint passes (no new warnings)
  • ✅ Changes are syntactically valid

Commit

fix(e2e): replace networkidle with domcontentloaded in streaming tests

Status

The fix has been pushed. CI should now run and pass the E2E tests. If the tests still fail, it may indicate additional issues that require human investigation.


Automated by Terragon Agent

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