Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
19 commits
Select commit Hold shift + click to select a range
febc36f
fix(security): enforce URL validation across connectors, providers, a…
waleedlatif1 Apr 20, 2026
2ae1ad2
feat(ui): Add slack manifest generator (#4237)
TheodoreSpeaks Apr 20, 2026
d9209f9
improvement(governance): workspace-org invitation system consolidatio…
icecrasher321 Apr 20, 2026
0cd14f4
improvement(sso): fix provider lookup, migrate UI to emcn, add enterp…
waleedlatif1 Apr 20, 2026
ac4ccfc
fix(billing): close TOCTOU race in subscription transfer, centralize …
waleedlatif1 Apr 20, 2026
802f4cf
feat(jobs): Add data retention jobs (#4128)
TheodoreSpeaks Apr 21, 2026
94202ed
improvement(knowledge): show selector with saved option in connector …
waleedlatif1 Apr 21, 2026
0e1ff0a
improvement(enterprise): slack wizard UI, enterprise docs, data reten…
waleedlatif1 Apr 21, 2026
699bbfd
feat(log): Add wrapper function for standardized logging (#4061)
TheodoreSpeaks Apr 21, 2026
2456128
feat(contact): add contact page, migrate help/demo forms to useMutati…
waleedlatif1 Apr 21, 2026
42ef2b1
fix(landing): resolve error-page crash on invalid /models and /integr…
waleedlatif1 Apr 21, 2026
d185953
improvement(landing): scope navbar/footer to (shell) route group, ali…
waleedlatif1 Apr 21, 2026
3a0e7b8
seo(robots): disallow tag-filtered blog URLs from crawlers (#4247)
emir-karabeg Apr 21, 2026
aee6189
improvement(access-control): migrate to workspace scope (#4244)
icecrasher321 Apr 21, 2026
2d94b37
feat(integrations): AWS SES, IAM Identity Center, and enhanced IAM/ST…
waleedlatif1 Apr 21, 2026
34cfc26
improvement(contact): add Turnstile CAPTCHA, honeypot, and robustness…
waleedlatif1 Apr 22, 2026
193f06f
fix(aws): add validateAwsRegion to all AWS route schemas to prevent S…
waleedlatif1 Apr 22, 2026
45bf396
fix(deps): bump drizzle-orm 0.45.2 + adopt MCP SDK 1.25.3 native type…
waleedlatif1 Apr 22, 2026
c2529c3
fix(settings): hide data-retention nav item when user lacks enterpris…
waleedlatif1 Apr 22, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
5 changes: 4 additions & 1 deletion .claude/rules/global.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
# Global Standards

## Logging
Import `createLogger` from `sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log`.
Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log`. Inside API routes wrapped with `withRouteHandler`, loggers automatically include the request ID.

## API Route Handlers
All API route handlers must be wrapped with `withRouteHandler` from `@/lib/core/utils/with-route-handler`. Never export a bare `async function GET/POST/...` — always use `export const METHOD = withRouteHandler(...)`.

## Comments
Use TSDoc for documentation. No `====` separators. No non-TSDoc comments.
Expand Down
13 changes: 10 additions & 3 deletions .claude/rules/sim-testing.md
Original file line number Diff line number Diff line change
Expand Up @@ -217,13 +217,20 @@ it('reads a row', async () => {
```

**Default chains supported:**
- `select()/selectDistinct()/selectDistinctOn() → from() → where()/innerJoin()/leftJoin() → where() → limit()/orderBy()/returning()/groupBy()`
- `select()/selectDistinct()/selectDistinctOn() → from() → where()/innerJoin()/leftJoin() → where() → limit()/orderBy()/returning()/groupBy()/for()`
- `insert() → values() → returning()/onConflictDoUpdate()/onConflictDoNothing()`
- `update() → set() → where() → limit()/orderBy()/returning()`
- `delete() → where() → limit()/orderBy()/returning()`
- `update() → set() → where() → limit()/orderBy()/returning()/for()`
- `delete() → where() → limit()/orderBy()/returning()/for()`
- `db.execute()` resolves `[]`
- `db.transaction(cb)` calls cb with `dbChainMock.db`

`.for('update')` (Postgres row-level locking) is supported on `where`
builders. It returns a thenable with `.limit` / `.orderBy` / `.returning` /
`.groupBy` attached, so both `await .where().for('update')` (terminal) and
`await .where().for('update').limit(1)` (chained) work. Override the terminal
result with `dbChainMockFns.for.mockResolvedValueOnce([...])`; for the chained
form, mock the downstream terminal (e.g. `dbChainMockFns.limit.mockResolvedValueOnce([...])`).

All terminals default to `Promise.resolve([])`. Override per-test with `dbChainMockFns.<terminal>.mockResolvedValueOnce(...)`.

Use `resetDbChainMock()` in `beforeEach` only when tests replace wiring with `.mockReturnValue` / `.mockResolvedValue` (permanent). Tests using only `...Once` variants don't need it.
Expand Down
38 changes: 37 additions & 1 deletion CLAUDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ You are a professional software engineer. All code must follow best practices: a

## Global Standards

- **Logging**: Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log`
- **Logging**: Import `createLogger` from `@sim/logger`. Use `logger.info`, `logger.warn`, `logger.error` instead of `console.log`. Inside API routes wrapped with `withRouteHandler`, loggers automatically include the request ID — no manual `withMetadata({ requestId })` needed
- **API Route Handlers**: All API route handlers (`GET`, `POST`, `PUT`, `DELETE`, `PATCH`) must be wrapped with `withRouteHandler` from `@/lib/core/utils/with-route-handler`. This provides request ID tracking, automatic error logging for 4xx/5xx responses, and unhandled error catching. See "API Route Pattern" section below
- **Comments**: Use TSDoc for documentation. No `====` separators. No non-TSDoc comments
- **Styling**: Never update global styles. Keep all styling local to components
- **ID Generation**: Never use `crypto.randomUUID()`, `nanoid`, or `uuid` package. Use `generateId()` (UUID v4) or `generateShortId()` (compact) from `@sim/utils/id`
Expand Down Expand Up @@ -93,6 +94,41 @@ export function Component({ requiredProp, optionalProp = false }: ComponentProps

Extract when: 50+ lines, used in 2+ files, or has own state/logic. Keep inline when: < 10 lines, single use, purely presentational.

## API Route Pattern

Every API route handler must be wrapped with `withRouteHandler`. This sets up `AsyncLocalStorage`-based request context so all loggers in the request lifecycle automatically include the request ID.

```typescript
import { createLogger } from '@sim/logger'
import type { NextRequest } from 'next/server'
import { NextResponse } from 'next/server'
import { withRouteHandler } from '@/lib/core/utils/with-route-handler'

const logger = createLogger('MyAPI')

// Simple route
export const GET = withRouteHandler(async (request: NextRequest) => {
logger.info('Handling request') // automatically includes {requestId=...}
return NextResponse.json({ ok: true })
})

// Route with params
export const DELETE = withRouteHandler(async (
request: NextRequest,
{ params }: { params: Promise<{ id: string }> }
) => {
const { id } = await params
return NextResponse.json({ deleted: id })
})

// Composing with other middleware (withRouteHandler wraps the outermost layer)
export const POST = withRouteHandler(withAdminAuth(async (request) => {
return NextResponse.json({ ok: true })
}))
```

Never export a bare `async function GET/POST/...` — always use `export const METHOD = withRouteHandler(...)`.

## Hooks

```typescript
Expand Down
29 changes: 29 additions & 0 deletions apps/docs/components/icons.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -4681,6 +4681,17 @@ export function IAMIcon(props: SVGProps<SVGSVGElement>) {
)
}

export function IdentityCenterIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 24 24' xmlns='http://www.w3.org/2000/svg'>
<path
d='M13.694,14.8194562 C14.376,14.1374562 14.376,13.0294562 13.694,12.3474562 C13.353,12.0074562 12.906,11.8374562 12.459,11.8374562 C12.01,11.8374562 11.563,12.0074562 11.222,12.3474562 C10.542,13.0284562 10.542,14.1384562 11.222,14.8194562 C11.905,15.5014562 13.013,15.4994562 13.694,14.8194562 M14.718,15.1374562 L18.703,19.1204562 L17.996,19.8274562 L16.868,18.6994562 L15.793,19.7754562 L15.086,19.0684562 L16.161,17.9924562 L14.011,15.8444562 C13.545,16.1654562 13.003,16.3294562 12.458,16.3294562 C11.755,16.3294562 11.051,16.0624562 10.515,15.5264562 C9.445,14.4554562 9.445,12.7124562 10.515,11.6404562 C11.586,10.5714562 13.329,10.5694562 14.401,11.6404562 C15.351,12.5904562 15.455,14.0674562 14.718,15.1374562 M20,12.1014562 C20,14.1684562 18.505,15.0934562 17.023,15.0934562 L17.023,14.0934562 C17.487,14.0934562 19,13.9494562 19,12.1014562 C19,11.0044562 18.353,10.3894562 16.905,10.1084562 C16.68,10.0654562 16.514,9.87545615 16.501,9.64845615 C16.446,8.74445615 15.987,8.11245615 15.384,8.11245615 C15.084,8.11245615 14.854,8.24245615 14.616,8.54645615 C14.506,8.68845615 14.324,8.75945615 14.147,8.73245615 C13.968,8.70545615 13.818,8.58445615 13.755,8.41445615 C13.577,7.94345615 13.211,7.43345615 12.723,6.97745615 C12.231,6.50945615 10.883,5.50745615 8.972,6.27345615 C7.885,6.70545615 7.034,7.94945615 7.034,9.10745615 C7.034,9.23545615 7.043,9.36245615 7.058,9.48845615 C7.061,9.50945615 7.062,9.53045615 7.062,9.55145615 C7.062,9.79945615 6.882,10.0064562 6.645,10.0464562 C5.886,10.2394562 5,10.7454562 5,12.0554562 L5.005,12.2104562 C5.069,13.3254562 6.252,13.9954562 7.358,13.9984562 L8,13.9984562 L8,14.9984562 L7.357,14.9984562 C5.536,14.9944562 4.095,13.8194562 4.006,12.2644562 C4.003,12.1944562 4,12.1244562 4,12.0554562 C4,10.6944562 4.752,9.64845615 6.035,9.18845615 C6.034,9.16145615 6.034,9.13445615 6.034,9.10745615 C6.034,7.54345615 7.138,5.92545615 8.602,5.34345615 C10.298,4.66545615 12.095,5.00345615 13.409,6.24945615 C13.706,6.52745615 14.076,6.92645615 14.372,7.41345615 C14.673,7.21245615 15.008,7.11245615 15.384,7.11245615 C16.257,7.11245615 17.231,7.77145615 17.458,9.20745615 C19.145,9.63245615 20,10.6054562 20,12.1014562'
fill='#FFFFFF'
/>
</svg>
)
}

export function STSIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'>
Expand All @@ -4699,6 +4710,24 @@ export function STSIcon(props: SVGProps<SVGSVGElement>) {
)
}

export function SESIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'>
<defs>
<linearGradient x1='0%' y1='100%' x2='100%' y2='0%' id='sesGradient'>
<stop stopColor='#BD0816' offset='0%' />
<stop stopColor='#FF5252' offset='100%' />
</linearGradient>
</defs>
<rect fill='url(#sesGradient)' width='80' height='80' />
<path
d='M57,60.999875 C57,59.373846 55.626,57.9998214 54,57.9998214 C52.374,57.9998214 51,59.373846 51,60.999875 C51,62.625904 52.374,63.9999286 54,63.9999286 C55.626,63.9999286 57,62.625904 57,60.999875 L57,60.999875 Z M40,59.9998571 C38.374,59.9998571 37,61.3738817 37,62.9999107 C37,64.6259397 38.374,65.9999643 40,65.9999643 C41.626,65.9999643 43,64.6259397 43,62.9999107 C43,61.3738817 41.626,59.9998571 40,59.9998571 L40,59.9998571 Z M26,57.9998214 C24.374,57.9998214 23,59.373846 23,60.999875 C23,62.625904 24.374,63.9999286 26,63.9999286 C27.626,63.9999286 29,62.625904 29,60.999875 C29,59.373846 27.626,57.9998214 26,57.9998214 L26,57.9998214 Z M28.605,42.9995536 L51.395,42.9995536 L43.739,36.1104305 L40.649,38.7584778 C40.463,38.9194807 40.23,38.9994821 39.999,38.9994821 C39.768,38.9994821 39.535,38.9194807 39.349,38.7584778 L36.26,36.1104305 L28.605,42.9995536 Z M27,28.1732888 L27,41.7545313 L34.729,34.7984071 L27,28.1732888 Z M51.297,26.9992678 L28.703,26.9992678 L39.999,36.6824408 L51.297,26.9992678 Z M53,41.7545313 L53,28.1732888 L45.271,34.7974071 L53,41.7545313 Z M59,60.999875 C59,63.7099234 56.71,65.9999643 54,65.9999643 C51.29,65.9999643 49,63.7099234 49,60.999875 C49,58.6308327 50.75,56.5837961 53,56.1057876 L53,52.9997321 L41,52.9997321 L41,58.1058233 C43.25,58.5838319 45,60.6308684 45,62.9999107 C45,65.7099591 42.71,68 40,68 C37.29,68 35,65.7099591 35,62.9999107 C35,60.6308684 36.75,58.5838319 39,58.1058233 L39,52.9997321 L27,52.9997321 L27,56.1057876 C29.25,56.5837961 31,58.6308327 31,60.999875 C31,63.7099234 28.71,65.9999643 26,65.9999643 C23.29,65.9999643 21,63.7099234 21,60.999875 C21,58.6308327 22.75,56.5837961 25,56.1057876 L25,51.9997143 C25,51.4477044 25.447,50.9996964 26,50.9996964 L39,50.9996964 L39,44.9995893 L26,44.9995893 C25.447,44.9995893 25,44.5515813 25,43.9995714 L25,25.99925 C25,25.4472401 25.447,24.9992321 26,24.9992321 L54,24.9992321 C54.553,24.9992321 55,25.4472401 55,25.99925 L55,43.9995714 C55,44.5515813 54.553,44.9995893 54,44.9995893 L41,44.9995893 L41,50.9996964 L54,50.9996964 C54.553,50.9996964 55,51.4477044 55,51.9997143 L55,56.1057876 C57.25,56.5837961 59,58.6308327 59,60.999875 L59,60.999875 Z M68,39.9995 C68,45.9066055 66.177,51.5597064 62.727,56.3447919 L61.104,55.174771 C64.307,50.7316916 66,45.4845979 66,39.9995 C66,25.664244 54.337,14.0000357 40.001,14.0000357 C25.664,14.0000357 14,25.664244 14,39.9995 C14,45.4845979 15.693,50.7316916 18.896,55.174771 L17.273,56.3447919 C13.823,51.5597064 12,45.9066055 12,39.9995 C12,24.5612243 24.561,12 39.999,12 C55.438,12 68,24.5612243 68,39.9995 L68,39.9995 Z'
fill='#FFFFFF'
/>
</svg>
)
}

export function SecretsManagerIcon(props: SVGProps<SVGSVGElement>) {
return (
<svg {...props} viewBox='0 0 80 80' xmlns='http://www.w3.org/2000/svg'>
Expand Down
4 changes: 4 additions & 0 deletions apps/docs/components/ui/icon-mapping.ts
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,7 @@ import {
HuggingFaceIcon,
HunterIOIcon,
IAMIcon,
IdentityCenterIcon,
ImageIcon,
IncidentioIcon,
InfisicalIcon,
Expand Down Expand Up @@ -152,6 +153,7 @@ import {
RootlyIcon,
S3Icon,
SalesforceIcon,
SESIcon,
SearchIcon,
SecretsManagerIcon,
SendgridIcon,
Expand Down Expand Up @@ -294,6 +296,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
huggingface: HuggingFaceIcon,
hunter: HunterIOIcon,
iam: IAMIcon,
identity_center: IdentityCenterIcon,
image_generator: ImageIcon,
imap: MailServerIcon,
incidentio: IncidentioIcon,
Expand Down Expand Up @@ -370,6 +373,7 @@ export const blockTypeToIconMap: Record<string, IconComponent> = {
sentry: SentryIcon,
serper: SerperIcon,
servicenow: ServiceNowIcon,
ses: SESIcon,
sftp: SftpIcon,
sharepoint: MicrosoftSharepointIcon,
shopify: ShopifyIcon,
Expand Down
Loading
Loading