Skip to content

Commit 85e2107

Browse files
feat(web): Ask share links (#888)
1 parent dd98025 commit 85e2107

File tree

51 files changed

+2602
-263
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+2602
-263
lines changed

CHANGELOG.md

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
77

88
## [Unreleased]
99

10+
### Added
11+
- Added chat duplication to create copies of existing chats. [#888](https://github.com/sourcebot-dev/sourcebot/pull/888)
12+
- Added Open Graph metadata and image generation for shared chat links. [#888](https://github.com/sourcebot-dev/sourcebot/pull/888)
13+
- [EE] Added chat sharing with specific users, allowing chat owners to invite org members to view private chats. [#888](https://github.com/sourcebot-dev/sourcebot/pull/888)
14+
15+
### Changed
16+
- Changed chat permissions model from read-only flag to ownership-based access control. [#888](https://github.com/sourcebot-dev/sourcebot/pull/888)
17+
- Improved anonymous chat experience: anonymous users can now create chats and claim them upon signing in. [#888](https://github.com/sourcebot-dev/sourcebot/pull/888)
18+
1019
### Fixed
1120
- Fixed issue where local repos with URL-encoded spaces in remote URLs would fail to load tree preview and index correctly. [#899](https://github.com/sourcebot-dev/sourcebot/pull/899)
1221

CLAUDE.md

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,26 @@ To build a specific package:
1818
yarn workspace @sourcebot/<package-name> build
1919
```
2020

21+
## File Naming
22+
23+
Files should use camelCase starting with a lowercase letter:
24+
25+
```
26+
// Correct
27+
shareChatPopover.tsx
28+
userAvatar.tsx
29+
apiClient.ts
30+
31+
// Incorrect
32+
ShareChatPopover.tsx
33+
UserAvatar.tsx
34+
share-chat-popover.tsx
35+
```
36+
37+
Exceptions:
38+
- Special files like `README.md`, `CHANGELOG.md`, `LICENSE`
39+
- Next.js conventions: `page.tsx`, `layout.tsx`, `loading.tsx`, etc.
40+
2141
## Tailwind CSS
2242

2343
Use Tailwind color classes directly instead of CSS variable syntax:
@@ -30,6 +50,138 @@ className="border-border bg-card text-foreground text-muted-foreground bg-muted
3050
className="border-[var(--border)] bg-[var(--card)] text-[var(--foreground)]"
3151
```
3252

53+
## API Route Handlers
54+
55+
Route handlers should validate inputs using Zod schemas.
56+
57+
**Query parameters** (GET requests):
58+
59+
```ts
60+
import { queryParamsSchemaValidationError, serviceErrorResponse } from "@/lib/serviceError";
61+
import { z } from "zod";
62+
63+
const myQueryParamsSchema = z.object({
64+
q: z.string().default(''),
65+
page: z.coerce.number().int().positive().default(1),
66+
});
67+
68+
export const GET = apiHandler(async (request: NextRequest) => {
69+
const rawParams = Object.fromEntries(
70+
Object.keys(myQueryParamsSchema.shape).map(key => [
71+
key,
72+
request.nextUrl.searchParams.get(key) ?? undefined
73+
])
74+
);
75+
const parsed = myQueryParamsSchema.safeParse(rawParams);
76+
77+
if (!parsed.success) {
78+
return serviceErrorResponse(
79+
queryParamsSchemaValidationError(parsed.error)
80+
);
81+
}
82+
83+
const { q, page } = parsed.data;
84+
// ... rest of handler
85+
});
86+
```
87+
88+
**Request body** (POST/PUT/PATCH requests):
89+
90+
```ts
91+
import { requestBodySchemaValidationError, serviceErrorResponse } from "@/lib/serviceError";
92+
import { z } from "zod";
93+
94+
const myRequestBodySchema = z.object({
95+
name: z.string(),
96+
count: z.number().optional(),
97+
});
98+
99+
export const POST = apiHandler(async (request: NextRequest) => {
100+
const body = await request.json();
101+
const parsed = myRequestBodySchema.safeParse(body);
102+
103+
if (!parsed.success) {
104+
return serviceErrorResponse(
105+
requestBodySchemaValidationError(parsed.error)
106+
);
107+
}
108+
109+
const { name, count } = parsed.data;
110+
// ... rest of handler
111+
});
112+
```
113+
114+
## Data Fetching
115+
116+
For GET requests, prefer using API routes with react-query over server actions. This provides caching benefits and better control over data refetching.
117+
118+
```tsx
119+
// Preferred: API route + react-query
120+
import { useQuery } from "@tanstack/react-query";
121+
122+
const { data, isLoading } = useQuery({
123+
queryKey: ["items", id],
124+
queryFn: () => fetch(`/api/items/${id}`).then(res => res.json()),
125+
});
126+
```
127+
128+
Server actions should be used for mutations (POST/PUT/DELETE operations), not for data fetching.
129+
130+
## Authentication
131+
132+
Use `withAuthV2` or `withOptionalAuthV2` from `@/withAuthV2` to protect server actions and API routes.
133+
134+
- **`withAuthV2`** - Requires authentication. Returns `notAuthenticated()` if user is not logged in.
135+
- **`withOptionalAuthV2`** - Allows anonymous access if the org has anonymous access enabled. `user` may be `undefined`.
136+
- **`withMinimumOrgRole`** - Wrap inside auth context to require a minimum role (e.g., `OrgRole.OWNER`).
137+
138+
**Important:** Always use the `prisma` instance provided by the auth context. This instance has `userScopedPrismaClientExtension` applied, which enforces repository visibility rules (e.g., filtering repos based on user permissions). Do NOT import `prisma` directly from `@/prisma` in actions or routes that return data to the client.
139+
140+
**Server actions** - Wrap with `sew()` for error handling:
141+
142+
```ts
143+
'use server';
144+
145+
import { sew } from "@/actions";
146+
import { withAuthV2 } from "@/withAuthV2";
147+
148+
export const myProtectedAction = async ({ id }: { id: string }) => sew(() =>
149+
withAuthV2(async ({ org, user, prisma }) => {
150+
// user is guaranteed to be defined
151+
// prisma is scoped to the user
152+
return { success: true };
153+
})
154+
);
155+
156+
export const myPublicAction = async ({ id }: { id: string }) => sew(() =>
157+
withOptionalAuthV2(async ({ org, user, prisma }) => {
158+
// user may be undefined for anonymous access
159+
return { success: true };
160+
})
161+
);
162+
```
163+
164+
**API routes** - Check `isServiceError` and return `serviceErrorResponse`:
165+
166+
```ts
167+
import { serviceErrorResponse } from "@/lib/serviceError";
168+
import { isServiceError } from "@/lib/utils";
169+
import { withAuthV2 } from "@/withAuthV2";
170+
171+
export const GET = apiHandler(async (request: NextRequest) => {
172+
const result = await withAuthV2(async ({ org, user, prisma }) => {
173+
// ... your logic
174+
return data;
175+
});
176+
177+
if (isServiceError(result)) {
178+
return serviceErrorResponse(result);
179+
}
180+
181+
return Response.json(result);
182+
});
183+
```
184+
33185
## Branches and Pull Requests
34186

35187
When creating a branch or opening a PR, ask the user for:

docs/docs.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
"group": "Ask Sourcebot",
4747
"pages": [
4848
"docs/features/ask/overview",
49+
"docs/features/ask/chat-sharing",
4950
"docs/features/ask/add-model-providers"
5051
]
5152
},

docs/docs/configuration/auth/faq.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ This page covers a range of frequently asked questions about Sourcebot's built-i
3030
Sourcebot supports connecting your identity proxy directly into the built-in auth system using an IAP bridge. This allows Sourcebot to
3131
register and authenticate automatically on a successful identity proxy log in.
3232

33-
Sourcebot currently supports [GCP IAP](/docs/configuration/auth/providers#gcp-iap). If you're using a different IAP
33+
Sourcebot currently supports [GCP IAP](/docs/configuration/idp). If you're using a different IAP
3434
and require support, please [reach out](https://www.sourcebot.dev/contact)
3535
</Accordion>
3636

docs/docs/configuration/transactional-emails.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ To enable transactional emails in your deployment, set the following environment
77

88
- Send emails when new members are invited
99
- Send emails when organization join requests are created/accepted
10-
- Log into the Sourcebot deployment using [email codes](/docs/configuration/auth/overview#email-codes)
10+
- Log into the Sourcebot deployment using [email codes](/docs/configuration/auth/providers#email-codes)
1111

1212
| Variable | Description |
1313
| :------- | :---------- |

docs/docs/connections/generic-git-host.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ icon: git-alt
55

66
import GenericGitHost from '/snippets/schemas/v3/genericGitHost.schema.mdx'
77

8-
Sourcebot can sync code from any Git host (by clone url). This is helpful when you want to search code that not in a [supported code host](/docs/connections/overview#supported-code-hosts).
8+
Sourcebot can sync code from any Git host (by clone url). This is helpful when you want to search code that not in a [supported code host](/docs/connections/overview#platform-connection-guides).
99

1010
If you're not familiar with Sourcebot [connections](/docs/connections/overview), please read that overview first.
1111

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
---
2+
title: Chat Sharing
3+
---
4+
5+
Chat sharing allows you to share Ask Sourcebot conversations with others. Whether you want to share insights with your team or make a conversation publicly accessible, Sourcebot provides flexible sharing options.
6+
7+
<Frame>
8+
<img src="/images/chat-sharing-dialog.png" alt="Chat sharing dialog" />
9+
</Frame>
10+
11+
## Visibility Options
12+
13+
Every chat has a visibility setting that controls who can access it:
14+
15+
<Frame>
16+
<img src="/images/chat-visibility-dropdown.png" alt="Chat visibility dropdown" />
17+
</Frame>
18+
19+
### Private (Default)
20+
- Only the chat owner can view the conversation
21+
- Other users cannot access the chat, even with the link
22+
- You can explicitly invite specific org members to view the chat (requires [Enterprise license](/docs/license-key))
23+
24+
### Public
25+
- Anyone with the link can view the conversation
26+
- If [anonymous access](/docs/configuration/auth/access-settings) is enabled, no authentication is required to view
27+
- Useful for sharing insights with your team or creating reference documentation
28+
- Public chats can be duplicated by others
29+
30+
## Sharing with Specific Users
31+
32+
<Note>Sharing with specific users requires an [Enterprise license](/docs/license-key).</Note>
33+
34+
<Frame>
35+
<img src="/images/chat-invite-users.png" alt="Invite users dialog" />
36+
</Frame>
37+
38+
Chat owners can invite specific organization members to view their private chats:
39+
40+
1. Open the chat you want to share
41+
2. Click the **Share** button in the top-right corner
42+
3. Search for users by name or email
43+
4. Select the users you want to invite
44+
5. Click **Invite** to grant them access
45+
46+
Invited users will be able to:
47+
- View the full conversation
48+
- See all messages and code citations
49+
- Navigate through referenced code snippets
50+
51+
Invited users **cannot**:
52+
- Edit or delete the chat
53+
- Send new messages
54+
- Invite other users
55+
56+
### Removing Access
57+
58+
<Frame>
59+
<img src="/images/chat-remove-user.png" alt="Remove user from chat" />
60+
</Frame>
61+
62+
To remove a user's access to your chat:
63+
64+
1. Open the Share dialog
65+
2. Find the user in the "People with access" list
66+
3. Click the **X** button next to their name

docs/docs/license-key.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ docker run \
3333
| [Agents](/docs/features/agents/overview) |||
3434
| [Login with credentials](/docs/configuration/auth/overview) |||
3535
| [Login with email codes](/docs/configuration/auth/overview) |||
36-
| [Login with SSO](/docs/configuration/auth/overview#enterprise-authentication-providers) | 🛑 ||
36+
| [Login with SSO](/docs/configuration/auth/providers#enterprise-authentication-providers) | 🛑 ||
3737
| [Permission syncing](/docs/features/permission-syncing) | 🛑 ||
3838
| [Code navigation](/docs/features/code-navigation) | 🛑 ||
3939
| [Search contexts](/docs/features/search/search-contexts) | 🛑 ||

docs/docs/overview.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -124,7 +124,7 @@ Connect your code from multiple code-host platforms and search across all of the
124124

125125
### Authentication
126126

127-
Sourcebot comes with built-in support for authentication via [email/password](/docs/configuration/auth/overview#email-%2F-password), [email codes](/docs/configuration/auth/overview#email-codes), and various [SSO providers](/docs/configuration/auth/overview#enterprise-authentication-providers).
127+
Sourcebot comes with built-in support for authentication via [email/password](/docs/configuration/auth/providers#email-%2F-password), [email codes](/docs/configuration/auth/providers#email-codes), and various [SSO providers](/docs/configuration/auth/providers#enterprise-authentication-providers).
128128

129129
<Accordion title="Key benefits">
130130
- **Configurable auth providers:** Configure the auth providers that are available to your team.

docs/docs/upgrade/v3-to-v4-guide.mdx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ Please note that the following features are no longer supported in v4:
3636

3737
![Pending Approval Page](/images/pending_approval.png)
3838

39-
The owner can view and approve join requests by navigating to **Settings -> Members**. Automatic provisioning of accounts is supported when using SSO/Oauth providers, check out the [auth docs](/docs/configuration/auth/overview#enterprise-authentication-providers) for more info
39+
The owner can view and approve join requests by navigating to **Settings -> Members**. Automatic provisioning of accounts is supported when using SSO/Oauth providers, check out the [auth docs](/docs/configuration/auth/providers#enterprise-authentication-providers) for more info
4040

4141
</Step>
4242
<Step title="You're done!">

0 commit comments

Comments
 (0)