Skip to content

Add shared invite acceptance flow - #24

Merged
TraderSamwise merged 3 commits into
masterfrom
feat/multi-user-chat-acceptance
May 24, 2026
Merged

Add shared invite acceptance flow#24
TraderSamwise merged 3 commits into
masterfrom
feat/multi-user-chat-acceptance

Conversation

@TraderSamwise

@TraderSamwise TraderSamwise commented May 24, 2026

Copy link
Copy Markdown
Owner

Summary

  • include project service metadata in shared invite records and summaries
  • add app API/settings support for accepting share invites and persisting active shared sessions
  • add an invite accept route that preserves invite redirects through sign-in and routes accepted guests to the shared chat

Verification

  • yarn --cwd app lint
  • yarn --cwd app typecheck
  • yarn --cwd app test
  • yarn typecheck
  • yarn build

Summary by CodeRabbit

  • New Features

    • Accept shared chat invites and join collaborative sessions.
    • Active shared-session mode for seamless shared-project/session views and navigation.
    • Persisted "active share" setting and focused UI state for active shared sessions.
    • Sign-in now preserves and safely handles post-auth redirect targets.
  • Bug Fixes

    • Refined auth redirect behavior to avoid incorrect redirects on public routes.
    • Invite-sending now includes service endpoint details for more reliable connections.
  • Tests

    • Added and extended tests covering invite creation, acceptance, and shared-session persistence.

Review Change Stack

@coderabbitai

coderabbitai Bot commented May 24, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: e4d99eb6-f0a7-43f0-9295-8bf8505a1dfd

📥 Commits

Reviewing files that changed from the base of the PR and between 5565801 and d03f8c2.

📒 Files selected for processing (1)
  • relay/src/sharing.test.ts

📝 Walkthrough

Walkthrough

Adds invite acceptance with serviceEndpoint support, persists an active shared session in settings/Jotai, introduces acceptShareInvite API, updates relay to persist/sanitize endpoints, and adapts MainLayout/relay polling to operate in an active shared-session mode.

Changes

Shared Invite Acceptance & Active Session Mode

Layer / File(s) Summary
Shared session state & types
app/stores/settings.ts, app/stores/settings.test.ts
ActiveSharedSession type added; AppSettings.activeShare defaulted to null; normalizeActiveShare validates/normalizes serviceEndpoint and acceptedAt; activeSharedSessionAtom exposes activeShare; tests updated for defaults, normalization, and persistence.
API contracts for invite acceptance
app/lib/api.ts, app/lib/api.test.ts
SharedSessionSummary gains optional serviceEndpoint. createShareInvite accepts an optional serviceEndpoint and includes it in the relay POST body. New acceptShareInvite(ownerUserId, token, opts?) posts to relay accept endpoint and returns AcceptShareInviteResponse. Tests added/updated for create+accept flows over relay HTTP with auth.
Relay service: endpoint persistence & sanitization
relay/src/sharing.ts, relay/src/relay-object.ts, relay/src/sharing.test.ts
Add exported ShareServiceEndpoint { host, port }. Persist serviceEndpoint on created shares when sanitized, include it in summaries, sanitize/normalize persisted endpoint via sanitizeServiceEndpoint (trim host, integer port 1–65535), and update relay request parsing/tests to accept and assert endpoint handling and redaction.
Sign-in redirect & error handling
app/app/sign-in.tsx
Read optional redirect from local search params, sanitize to Href via sanitizeRedirect, use it after sign-in/2FA redirect, and add clerkErrorMessage helper to extract messages from unknown Clerk errors; update catch blocks accordingly.
Invite acceptance screen & routing
app/app/shares/invite/[ownerUserId]/[token]/accept.tsx, app/app/_layout.tsx
New AcceptShareInviteScreen that calls acceptShareInvite with auth token, validates returned serviceEndpoint/session metadata, writes activeSharedSessionAtom and selected project/session atoms, and navigates to the agent chat. Adds route entry for accept screen with header hidden.
Auth routing: public routes refactor
app/app/_layout.tsx
AuthGate splits public-route detection into onAuthScreen vs onPublicScreen so signed-in redirects occur only from auth screens; dependencies updated.
Active session mode: relay & polling
app/app/(main)/_layout.tsx, app/app/(main)/(tabs)/(dashboard)/agent/[sessionId]/chat.tsx
MainLayout observes activeSharedSessionAtom; when present, RelayTransport is created with owner/share scope, /projects polling is replaced by a synthetic shared project via projectFromActiveShare, selected project/session atoms set from the share, and /desktop-state/durable notifications polling short-circuit. Chat invite send now passes serviceEndpoint to createShareInvite.

Sequence Diagram

sequenceDiagram
  participant User
  participant AcceptScreen as AcceptShareInviteScreen
  participant SignIn as SignInScreen
  participant API as api.acceptShareInvite
  participant Relay as Relay Service
  participant State as Jotai Settings
  participant MainLayout
  participant ChatScreen

  User->>AcceptScreen: Visit /shares/invite/[ownerUserId]/[token]/accept
  AcceptScreen->>SignIn: Not signed in → redirect
  User->>SignIn: Sign in with redirect param
  SignIn->>API: POST /auth/sign-in
  SignIn->>User: Redirect back to /shares/invite/...
  AcceptScreen->>AcceptScreen: Auth loaded & signed in
  AcceptScreen->>API: acceptShareInvite(ownerUserId, token, {token})
  API->>Relay: POST /shares/invite/{ownerUserId}/{token}/accept
  Relay->>API: Return serviceEndpoint, sessionId, shareId
  AcceptScreen->>State: Write activeSharedSessionAtom
  AcceptScreen->>State: Write selectedSessionIdAtom
  AcceptScreen->>MainLayout: Navigate to /agent/[sessionId]/chat
  MainLayout->>MainLayout: Detect activeShare set
  MainLayout->>Relay: Create RelayTransport with owner/share scope
  MainLayout->>MainLayout: Poll with shared-only project
  ChatScreen->>ChatScreen: Load in active shared session mode
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related PRs

  • TraderSamwise/aimux#18: Related relay sharing foundation changes; this PR extends SharedSession types and invite/accept paths with serviceEndpoint support.
  • TraderSamwise/aimux#23: Earlier changes to invite-sending in chat.tsx; this PR updates the call to include serviceEndpoint.
  • TraderSamwise/aimux#20: RelayTransport constructor / options changes that the MainLayout active-share relay scoping relies on.

Poem

A rabbit hops through invite links so fine,
Signs in, accepts, and scopes the relay line,
Active shares sparkle with endpoints set true,
MainLayout listens, polls only what's due—
Hooray, shared chats bloom! 🐇✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'Add shared invite acceptance flow' accurately describes the main objective of the PR, which adds the complete flow for accepting shared chat invites across multiple files.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

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

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/multi-user-chat-acceptance

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 3

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@app/app/sign-in.tsx`:
- Around line 32-34: The sign-in flow currently only navigates when a `redirect`
exists, so after `setActive({ session: result.createdSessionId })` successful
sign-in with no `redirect` leaves the user on the sign-in page; update the logic
in the block handling `result.status === "complete"` to call
`router.replace(redirect)` when `redirect` is provided and otherwise perform a
fallback navigation (e.g., `router.replace("/")` or the app's default post-login
route) so the user is immediately routed; modify the code around `if
(result.status === "complete") { ... }` where `setActive` is called to add this
fallback behavior and ensure it integrates with the existing `AuthGate` flow.
- Around line 63-65: When handling the verification flow where result.status ===
"complete" (same block that calls setActive({ session: result.createdSessionId
})), ensure you apply the same redirect fallback as the sign-in flow: replace
the router.replace(redirect) call with a fallback-aware call (e.g.,
router.replace(redirect ?? '/')) so a default path is used when redirect is
undefined; update the verification flow's block that checks result.status ===
"complete" to use this fallback behavior.

In `@relay/src/sharing.ts`:
- Around line 165-172: normalizeShare currently returns persisted share records
without sanitizing the stored serviceEndpoint, so legacy data can bypass the
host/port normalization done for new input; update normalizeShare (used by
normalizeSharingState and findShareForSession) to run sanitizeServiceEndpoint on
share.serviceEndpoint (and replace the field only if sanitizeServiceEndpoint
returns a value) so downstream consumers always receive a normalized host/port
shape consistent with the input-side call to sanitizeServiceEndpoint.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8b7052a7-9b22-472c-a4df-66295965cad0

📥 Commits

Reviewing files that changed from the base of the PR and between 75a6efc and 6e8e080.

📒 Files selected for processing (12)
  • app/app/(main)/(tabs)/(dashboard)/agent/[sessionId]/chat.tsx
  • app/app/(main)/_layout.tsx
  • app/app/_layout.tsx
  • app/app/shares/invite/[ownerUserId]/[token]/accept.tsx
  • app/app/sign-in.tsx
  • app/lib/api.test.ts
  • app/lib/api.ts
  • app/stores/settings.test.ts
  • app/stores/settings.ts
  • relay/src/relay-object.ts
  • relay/src/sharing.test.ts
  • relay/src/sharing.ts

Comment thread app/app/sign-in.tsx Outdated
Comment thread app/app/sign-in.tsx Outdated
Comment thread relay/src/sharing.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@relay/src/sharing.test.ts`:
- Around line 220-237: The persisted-share fixture passed into createShareInvite
is missing the top-level SharingState version and has an invalid participants
shape: add version: 1 at the top of the persisted state and change the
participants entry for "share_existing" so each participant value conforms to
ShareParticipantRecord (include required fields such as status and joinedAt
alongside the existing owner fields) so that the participants map contains
objects with status and joinedAt rather than the raw owner object.
🪄 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: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 8fae821c-d7f5-4c30-adb2-89035597b3bb

📥 Commits

Reviewing files that changed from the base of the PR and between 6e8e080 and 5565801.

📒 Files selected for processing (3)
  • app/app/sign-in.tsx
  • relay/src/sharing.test.ts
  • relay/src/sharing.ts

Comment thread relay/src/sharing.test.ts
@TraderSamwise
TraderSamwise merged commit 79d120c into master May 24, 2026
1 check passed
@TraderSamwise
TraderSamwise deleted the feat/multi-user-chat-acceptance branch May 24, 2026 10:44
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