Skip to content

Commit 760bf67

Browse files
Merge remote-tracking branch 'origin/staging' into fix/billing-lock-hold
2 parents f764497 + b86ebb3 commit 760bf67

382 files changed

Lines changed: 35021 additions & 2063 deletions

File tree

Some content is hidden

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

.claude/rules/sim-testing.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ vi.useFakeTimers()
144144
| `@/app/api/auth/oauth/utils` | `authOAuthUtilsMock`, `authOAuthUtilsMockFns` | `vi.mock('@/app/api/auth/oauth/utils', () => authOAuthUtilsMock)` |
145145
| `@/app/api/knowledge/utils` | `knowledgeApiUtilsMock`, `knowledgeApiUtilsMockFns` | `vi.mock('@/app/api/knowledge/utils', () => knowledgeApiUtilsMock)` |
146146
| `@/app/api/workflows/utils` | `workflowsApiUtilsMock`, `workflowsApiUtilsMockFns` | `vi.mock('@/app/api/workflows/utils', () => workflowsApiUtilsMock)` |
147-
| `@/lib/audit/log` | `auditMock`, `auditMockFns` | `vi.mock('@/lib/audit/log', () => auditMock)` |
147+
| `@sim/audit` | `auditMock`, `auditMockFns` | `vi.mock('@sim/audit', () => auditMock)` |
148148
| `@/lib/auth` | `authMock`, `authMockFns` | `vi.mock('@/lib/auth', () => authMock)` |
149149
| `@/lib/auth/hybrid` | `hybridAuthMock`, `hybridAuthMockFns` | `vi.mock('@/lib/auth/hybrid', () => hybridAuthMock)` |
150150
| `@/lib/copilot/request/http` | `copilotHttpMock`, `copilotHttpMockFns` | `vi.mock('@/lib/copilot/request/http', () => copilotHttpMock)` |

.cursor/rules/sim-testing.mdc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,7 +144,7 @@ vi.useFakeTimers()
144144
| `@/app/api/auth/oauth/utils` | `authOAuthUtilsMock`, `authOAuthUtilsMockFns` | `vi.mock('@/app/api/auth/oauth/utils', () => authOAuthUtilsMock)` |
145145
| `@/app/api/knowledge/utils` | `knowledgeApiUtilsMock`, `knowledgeApiUtilsMockFns` | `vi.mock('@/app/api/knowledge/utils', () => knowledgeApiUtilsMock)` |
146146
| `@/app/api/workflows/utils` | `workflowsApiUtilsMock`, `workflowsApiUtilsMockFns` | `vi.mock('@/app/api/workflows/utils', () => workflowsApiUtilsMock)` |
147-
| `@/lib/audit/log` | `auditMock`, `auditMockFns` | `vi.mock('@/lib/audit/log', () => auditMock)` |
147+
| `@sim/audit` | `auditMock`, `auditMockFns` | `vi.mock('@sim/audit', () => auditMock)` |
148148
| `@/lib/auth` | `authMock`, `authMockFns` | `vi.mock('@/lib/auth', () => authMock)` |
149149
| `@/lib/auth/hybrid` | `hybridAuthMock`, `hybridAuthMockFns` | `vi.mock('@/lib/auth/hybrid', () => hybridAuthMock)` |
150150
| `@/lib/copilot/request/http` | `copilotHttpMock`, `copilotHttpMockFns` | `vi.mock('@/lib/copilot/request/http', () => copilotHttpMock)` |

.devcontainer/post-create.sh

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,14 +71,26 @@ fi
7171

7272
# Set up environment variables if .env doesn't exist for the sim app
7373
if [ ! -f "apps/sim/.env" ]; then
74-
echo "📄 Creating .env file from template..."
74+
echo "📄 Creating apps/sim/.env from template..."
7575
if [ -f "apps/sim/.env.example" ]; then
7676
cp apps/sim/.env.example apps/sim/.env
7777
else
7878
echo "DATABASE_URL=postgresql://postgres:postgres@db:5432/simstudio" > apps/sim/.env
7979
fi
8080
fi
8181

82+
# Set up env for the realtime server (must match the shared values in apps/sim/.env)
83+
if [ ! -f "apps/realtime/.env" ] && [ -f "apps/realtime/.env.example" ]; then
84+
echo "📄 Creating apps/realtime/.env from template..."
85+
cp apps/realtime/.env.example apps/realtime/.env
86+
fi
87+
88+
# Set up packages/db/.env for drizzle-kit and migration scripts
89+
if [ ! -f "packages/db/.env" ] && [ -f "packages/db/.env.example" ]; then
90+
echo "📄 Creating packages/db/.env from template..."
91+
cp packages/db/.env.example packages/db/.env
92+
fi
93+
8294
# Generate schema and run database migrations
8395
echo "🗃️ Running database schema generation and migrations..."
8496
echo "Generating schema..."

.github/workflows/test-build.yml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,15 @@ jobs:
103103
- name: Lint code
104104
run: bun run lint:check
105105

106+
- name: Enforce monorepo boundaries
107+
run: bun run check:boundaries
108+
109+
- name: Verify realtime prune graph
110+
run: bun run check:realtime-prune
111+
112+
- name: Type-check realtime server
113+
run: bunx turbo run type-check --filter=@sim/realtime
114+
106115
- name: Run tests with coverage
107116
env:
108117
NODE_OPTIONS: '--no-warnings --max-old-space-size=8192'

AGENTS.md

Lines changed: 34 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,42 @@ You are a professional software engineer. All code must follow best practices: a
2020

2121
### Root Structure
2222
```
23-
apps/sim/
24-
├── app/ # Next.js app router (pages, API routes)
25-
├── blocks/ # Block definitions and registry
26-
├── components/ # Shared UI (emcn/, ui/)
27-
├── executor/ # Workflow execution engine
28-
├── hooks/ # Shared hooks (queries/, selectors/)
29-
├── lib/ # App-wide utilities
30-
├── providers/ # LLM provider integrations
31-
├── stores/ # Zustand stores
32-
├── tools/ # Tool definitions
33-
└── triggers/ # Trigger definitions
23+
apps/
24+
├── sim/ # Next.js app (UI + API routes + workflow editor)
25+
│ ├── app/ # Next.js app router (pages, API routes)
26+
│ ├── blocks/ # Block definitions and registry
27+
│ ├── components/ # Shared UI (emcn/, ui/)
28+
│ ├── executor/ # Workflow execution engine
29+
│ ├── hooks/ # Shared hooks (queries/, selectors/)
30+
│ ├── lib/ # App-wide utilities
31+
│ ├── providers/ # LLM provider integrations
32+
│ ├── stores/ # Zustand stores
33+
│ ├── tools/ # Tool definitions
34+
│ └── triggers/ # Trigger definitions
35+
└── realtime/ # Bun Socket.IO server (collaborative canvas)
36+
└── src/ # auth, config, database, handlers, middleware,
37+
# rooms, routes, internal/webhook-cleanup.ts
38+
39+
packages/
40+
├── audit/ # @sim/audit — recordAudit + AuditAction + AuditResourceType
41+
├── auth/ # @sim/auth — @sim/auth/verify (shared Better Auth verifier)
42+
├── db/ # @sim/db — drizzle schema + client
43+
├── logger/ # @sim/logger
44+
├── realtime-protocol/ # @sim/realtime-protocol — socket operation constants + zod schemas
45+
├── security/ # @sim/security — safeCompare
46+
├── tsconfig/ # shared tsconfig presets
47+
├── utils/ # @sim/utils
48+
├── workflow-authz/ # @sim/workflow-authz — authorizeWorkflowByWorkspacePermission
49+
├── workflow-persistence/ # @sim/workflow-persistence — raw load/save + subflow helpers
50+
└── workflow-types/ # @sim/workflow-types — pure BlockState/Loop/Parallel/... types
3451
```
3552

53+
### Package boundaries
54+
- `apps/* → packages/*` only. Packages never import from `apps/*`.
55+
- Each package has explicit subpath `exports` maps; no barrels that accidentally pull in heavy halves.
56+
- `apps/realtime` intentionally avoids Next.js, React, the block/tool registry, provider SDKs, and the executor. CI enforces this via `scripts/check-monorepo-boundaries.ts` and `scripts/check-realtime-prune-graph.ts`.
57+
- Auth is shared across services via the Better Auth "Shared Database Session" pattern: both apps read the same `BETTER_AUTH_SECRET` and point at the same DB via `@sim/db`.
58+
3659
### Naming Conventions
3760
- Components: PascalCase (`WorkflowList`)
3861
- Hooks: `use` prefix (`useWorkflowOperations`)

apps/docs/content/docs/en/enterprise/data-retention.mdx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ description: Control how long execution logs, deleted resources, and copilot dat
66
import { FAQ } from '@/components/ui/faq'
77
import { Image } from '@/components/ui/image'
88

9-
Data Retention lets workspace admins on Enterprise plans configure how long three categories of data are kept before they are permanently deleted. Each workspace in your organization can have its own independent configuration.
9+
Data Retention lets organization owners and admins on Enterprise plans configure how long three categories of data are kept before they are permanently deleted. The configuration applies to every workspace in the organization.
1010

1111
---
1212

@@ -58,9 +58,9 @@ Each setting is independent. You can configure a short log retention period alon
5858

5959
---
6060

61-
## Per-workspace configuration
61+
## Organization-wide configuration
6262

63-
Retention is configured at the **workspace level**, not organization-wide. Each workspace in your organization can have a different configuration. Changes to one workspace's settings do not affect other workspaces.
63+
Retention is configured at the **organization level**. A single configuration applies to every workspace in the organization — there are no per-workspace overrides.
6464

6565
---
6666

@@ -73,7 +73,7 @@ By default, all three settings are unconfigured — no data is automatically del
7373
<FAQ items={[
7474
{
7575
question: "Who can configure data retention settings?",
76-
answer: "Only workspace admins can configure data retention settings. On Sim Cloud, the workspace must be on an Enterprise plan."
76+
answer: "Only organization owners and admins can configure data retention settings. On Sim Cloud, the organization must be on an Enterprise plan."
7777
},
7878
{
7979
question: "Is deletion immediate once the retention period expires?",
@@ -85,7 +85,7 @@ By default, all three settings are unconfigured — no data is automatically del
8585
},
8686
{
8787
question: "Does the retention period apply to all workspaces in my organization?",
88-
answer: "No. Retention is configured per workspace. Each workspace in your organization can have a different configuration."
88+
answer: "Yes. Retention is configured once per organization and applies to every workspace in the organization."
8989
},
9090
{
9191
question: "What happens if I shorten the retention period?",

apps/realtime/.env.example

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# Environment variables required by the @sim/realtime (Socket.IO) server.
2+
# These MUST match the corresponding values in apps/sim/.env for auth to work.
3+
# See apps/realtime/src/env.ts for the full zod schema.
4+
5+
# Core
6+
NODE_ENV=development
7+
PORT=3002
8+
9+
# Database — must point at the same Postgres as the main app
10+
DATABASE_URL=postgresql://postgres:postgres@localhost:5432/simstudio
11+
12+
# Auth — shared with apps/sim (Better Auth "Shared Database Session" pattern)
13+
BETTER_AUTH_URL=http://localhost:3000
14+
BETTER_AUTH_SECRET=your_better_auth_secret_min_32_chars
15+
16+
# Internal RPC — shared with apps/sim
17+
INTERNAL_API_SECRET=your_internal_api_secret_min_32_chars
18+
19+
# Public app URL — used for CORS allow-list and base URL resolution
20+
NEXT_PUBLIC_APP_URL=http://localhost:3000
21+
22+
# Optional: Redis for cross-pod room management
23+
# Leave unset for single-pod / in-memory rooms
24+
# REDIS_URL=redis://localhost:6379
25+
26+
# Optional: extra Socket.IO CORS allow-list (comma-separated)
27+
# ALLOWED_ORIGINS=https://embed.example.com,https://admin.example.com
28+
29+
# Optional: disable auth entirely for trusted private networks
30+
# DISABLE_AUTH=true

apps/realtime/package.json

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
{
2+
"name": "@sim/realtime",
3+
"version": "0.1.0",
4+
"private": true,
5+
"license": "Apache-2.0",
6+
"type": "module",
7+
"engines": {
8+
"bun": ">=1.2.13",
9+
"node": ">=20.0.0"
10+
},
11+
"scripts": {
12+
"dev": "bun --watch src/index.ts",
13+
"start": "bun src/index.ts",
14+
"type-check": "tsc --noEmit",
15+
"lint": "biome check --write --unsafe .",
16+
"lint:check": "biome check .",
17+
"format": "biome format --write .",
18+
"format:check": "biome format .",
19+
"test": "vitest run",
20+
"test:watch": "vitest"
21+
},
22+
"dependencies": {
23+
"@sim/audit": "workspace:*",
24+
"@sim/auth": "workspace:*",
25+
"@sim/db": "workspace:*",
26+
"@sim/logger": "workspace:*",
27+
"@sim/realtime-protocol": "workspace:*",
28+
"@sim/security": "workspace:*",
29+
"@sim/utils": "workspace:*",
30+
"@sim/workflow-authz": "workspace:*",
31+
"@sim/workflow-persistence": "workspace:*",
32+
"@sim/workflow-types": "workspace:*",
33+
"@socket.io/redis-adapter": "8.3.0",
34+
"drizzle-orm": "^0.45.2",
35+
"postgres": "^3.4.5",
36+
"redis": "5.10.0",
37+
"socket.io": "^4.8.1",
38+
"zod": "^3.24.2"
39+
},
40+
"devDependencies": {
41+
"@sim/testing": "workspace:*",
42+
"@sim/tsconfig": "workspace:*",
43+
"@types/node": "24.2.1",
44+
"socket.io-client": "4.8.1",
45+
"typescript": "^5.7.3",
46+
"vitest": "^3.0.8"
47+
}
48+
}

apps/realtime/src/auth.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { createVerifyAuth } from '@sim/auth/verify'
2+
import { env } from '@/env'
3+
4+
export const ANONYMOUS_USER_ID = '00000000-0000-0000-0000-000000000000'
5+
6+
export const ANONYMOUS_USER = {
7+
id: ANONYMOUS_USER_ID,
8+
name: 'Anonymous',
9+
email: 'anonymous@localhost',
10+
emailVerified: true,
11+
image: null,
12+
} as const
13+
14+
export const auth = createVerifyAuth({
15+
secret: env.BETTER_AUTH_SECRET,
16+
baseURL: env.BETTER_AUTH_URL,
17+
})
Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,7 @@ import { createLogger } from '@sim/logger'
33
import { createAdapter } from '@socket.io/redis-adapter'
44
import { createClient, type RedisClientType } from 'redis'
55
import { Server } from 'socket.io'
6-
import { env } from '@/lib/core/config/env'
7-
import { isProd } from '@/lib/core/config/feature-flags'
8-
import { getBaseUrl } from '@/lib/core/utils/urls'
6+
import { env, getBaseUrl, isProd } from '@/env'
97

108
const logger = createLogger('SocketIOConfig')
119

0 commit comments

Comments
 (0)