diff --git a/.agents/skills/audit-design-system/SKILL.md b/.agents/skills/audit-design-system/SKILL.md
new file mode 100644
index 0000000000..a0c7d0dc22
--- /dev/null
+++ b/.agents/skills/audit-design-system/SKILL.md
@@ -0,0 +1,23 @@
+---
+name: audit-design-system
+description: Audit & fix design system usage — migrate @trycompai/ui and lucide-react to @trycompai/design-system
+---
+
+Audit the specified files for design system compliance. **Fix every issue found immediately.**
+
+## Rules
+
+1. **`@trycompai/design-system`** is the primary component library. `@trycompai/ui` is legacy — only use as last resort when no DS equivalent exists.
+2. **Always check DS exports first** before reaching for `@trycompai/ui`. Run `node -e "console.log(Object.keys(require('@trycompai/design-system')))"` to check.
+3. **Icons**: Use `@trycompai/design-system/icons` (Carbon icons), NOT `lucide-react`. Check with `node -e "const i = require('@trycompai/design-system/icons'); console.log(Object.keys(i).filter(k => k.match(/YourSearch/i)))"`.
+4. **DS components that do NOT accept `className`**: `Text`, `Stack`, `HStack`, `Badge`, `Button` — wrap in `
` for custom styling.
+5. **Button**: Use DS `Button` with `loading`, `iconLeft`, `iconRight` props instead of manually rendering spinners/icons.
+6. **Layout**: Use `PageLayout`, `PageHeader`, `Stack`, `HStack`, `Section`, `SettingGroup`.
+7. **Patterns**: Sheet (`Sheet > SheetContent > SheetHeader + SheetBody`), Drawer, Collapsible.
+
+## Process
+1. Read files specified in `$ARGUMENTS`
+2. Find `@trycompai/ui` imports — check if DS equivalent exists
+3. Find `lucide-react` imports — find matching Carbon icons
+4. Migrate components and icons
+5. Run build to verify: `bunx turbo run typecheck --filter=@trycompai/app`
diff --git a/.agents/skills/audit-hooks/SKILL.md b/.agents/skills/audit-hooks/SKILL.md
new file mode 100644
index 0000000000..7c14d1a240
--- /dev/null
+++ b/.agents/skills/audit-hooks/SKILL.md
@@ -0,0 +1,34 @@
+---
+name: audit-hooks
+description: Audit & fix hooks and API usage patterns — eliminate server actions, raw fetch, and stale patterns
+---
+
+Audit the specified files for hook and API usage compliance. **Fix every issue found immediately.**
+
+## Forbidden Patterns (fix immediately)
+
+1. **`useAction` from `next-safe-action`** → replace with SWR hook or custom mutation hook
+2. **Server actions mutating via `@db`** → delete and use API hook instead
+3. **Direct `@db` in client components** → replace with `apiClient` via hook
+4. **Direct `@db` in Next.js pages for mutations** → replace with `serverApi`
+5. **Raw `fetch()` without `credentials: 'include'`** → use `apiClient`
+6. **`window.location.reload()` after mutations** → use SWR `mutate()`
+7. **`router.refresh()` after mutations** → use SWR `mutate()`
+8. **`useEffect` + `apiClient.get` for data fetching** → replace with `useSWR`
+9. **Callback props for data refresh** (`onXxxAdded`, `onSuccess`) → remove, rely on SWR cache sharing
+
+## Required Patterns
+
+- **Client data fetching**: `useSWR` with `apiClient` or custom hook
+- **Client mutations**: custom hooks wrapping `apiClient` with `mutate()` for cache invalidation
+- **Server components**: `serverApi` from `apps/app/src/lib/api-server.ts`
+- **SWR**: `fallbackData` for SSR data, `revalidateOnMount: !initialData`
+- **API response**: lists = `response.data.data`, single = `response.data`
+- **`mutate()` safety**: guard against `undefined` in optimistic update functions
+- **`Array.isArray()` checks**: when consuming SWR data that could be stale
+
+## Process
+1. Read files specified in `$ARGUMENTS`
+2. Find forbidden patterns and fix them
+3. Ensure all data fetching uses SWR hooks
+4. Run typecheck to verify: `bunx turbo run typecheck --filter=@trycompai/app`
diff --git a/.agents/skills/audit-rbac/SKILL.md b/.agents/skills/audit-rbac/SKILL.md
new file mode 100644
index 0000000000..df0786bcb0
--- /dev/null
+++ b/.agents/skills/audit-rbac/SKILL.md
@@ -0,0 +1,42 @@
+---
+name: audit-rbac
+description: Audit & fix RBAC and audit log compliance in API endpoints and frontend components
+---
+
+Audit the specified files or directories for RBAC and audit log compliance. **Fix every issue found immediately.**
+
+## Rules
+
+### API Endpoints (NestJS — `apps/api/src/`)
+1. **Every mutation endpoint** (POST, PATCH, PUT, DELETE) MUST have `@RequirePermission('resource', 'action')`. If missing, **add it**.
+2. **Read endpoints** (GET) should have `@RequirePermission('resource', 'read')`. If missing, **add it**.
+3. **Self-endpoints** (e.g., `/me/preferences`) may skip `@RequirePermission` — authentication via `HybridAuthGuard` is sufficient.
+4. **Controller format**: Must use `@Controller({ path: 'name', version: '1' })`, NOT `@Controller('v1/name')`. If wrong, **fix it**.
+5. **Guards**: Use `@UseGuards(HybridAuthGuard, PermissionGuard)` at controller or endpoint level. Never skip PermissionGuard.
+6. **Webhooks**: External webhook endpoints use `@Public()` — no auth required.
+
+### Frontend Components (`apps/app/src/`)
+1. **Every mutation element** (button, form submit, toggle, switch, file upload) MUST be gated with `usePermissions` from `@/hooks/use-permissions`. If not:
+ - **Create/Add buttons**: Wrap with `{hasPermission('resource', 'create') &&
...`
+ - **Edit/Delete in dropdown menus**: Wrap the menu item
+ - **Inline form fields on detail pages**: Add `disabled={!canUpdate}`
+ - **Status/property selectors**: Add `disabled={!canUpdate}`
+2. **Actions columns** in tables: hide entire column when user lacks write permission.
+3. **No manual role string parsing** (`role.includes('admin')`) — use `hasPermission()`.
+4. **Nav items**: gate with `canAccessRoute(permissions, 'routeSegment')`.
+5. **Page-level**: call `requireRoutePermission('segment', orgId)` server-side.
+
+### Permission Resources
+`organization`, `member`, `control`, `evidence`, `policy`, `risk`, `vendor`, `task`, `framework`, `audit`, `finding`, `questionnaire`, `integration`, `apiKey`, `trust`, `pentest`, `app`, `compliance`
+
+### Multi-Product RBAC
+- Products (compliance, pen testing) are org-level feature flags — NOT RBAC
+- `app:read` gates compliance dashboard; `pentest:read` gates security product
+- Custom roles can grant access to any combination of resources
+- Portal-only resources (`policy`, `compliance`) do NOT grant app access
+
+## Process
+1. Read files specified in `$ARGUMENTS` (or scan the directory)
+2. Check each rule above
+3. **Fix every violation immediately** — don't just report
+4. Run typecheck to verify: `bunx turbo run typecheck --filter=@trycompai/api --filter=@trycompai/app`
diff --git a/.agents/skills/audit-tests/SKILL.md b/.agents/skills/audit-tests/SKILL.md
new file mode 100644
index 0000000000..ae7a3b1459
--- /dev/null
+++ b/.agents/skills/audit-tests/SKILL.md
@@ -0,0 +1,30 @@
+---
+name: audit-tests
+description: Audit & fix unit tests for permission-gated components
+---
+
+Check that unit tests exist and pass for permission-gated components. **Write missing tests immediately.**
+
+## Infrastructure
+- **Framework**: Vitest with jsdom
+- **Component testing**: `@testing-library/react` + `@testing-library/jest-dom`
+- **Setup**: `apps/app/src/test-utils/setup.ts`
+- **Permission mocks**: `apps/app/src/test-utils/mocks/permissions.ts`
+- **Run**: `cd apps/app && bunx vitest run`
+
+## Required Test Pattern
+
+Every component importing `usePermissions` MUST have tests covering:
+
+1. **Admin (write) user**: mutation elements visible/enabled
+2. **Auditor (read-only)**: mutation elements hidden/disabled
+3. **Data always visible**: read-only content renders regardless of permissions
+
+Use `setMockPermissions`, `ADMIN_PERMISSIONS`, `AUDITOR_PERMISSIONS` from test utils.
+
+## Process
+1. Find components with `usePermissions` in `$ARGUMENTS`
+2. Check for corresponding `.test.tsx` files
+3. Write missing tests following the pattern above
+4. Fix any failing tests
+5. Run: `cd apps/app && bunx vitest run`
diff --git a/.agents/skills/better-auth-best-practices/SKILL.md b/.agents/skills/better-auth-best-practices/SKILL.md
index 3e6a4e1972..5e4b8d9edc 100644
--- a/.agents/skills/better-auth-best-practices/SKILL.md
+++ b/.agents/skills/better-auth-best-practices/SKILL.md
@@ -11,11 +11,11 @@ description: Configure Better Auth server and client, set up database adapters,
## Setup Workflow
-1. Install: `npm install better-auth`
+1. Install: `bun add better-auth`
2. Set env vars: `BETTER_AUTH_SECRET` and `BETTER_AUTH_URL`
3. Create `auth.ts` with database + config
4. Create route handler for your framework
-5. Run `npx @better-auth/cli@latest migrate`
+5. Run `bunx @better-auth/cli@latest migrate`
6. Verify: call `GET /api/auth/ok` — should return `{ status: "ok" }`
---
@@ -32,9 +32,9 @@ Only define `baseURL`/`secret` in config if env vars are NOT set.
CLI looks for `auth.ts` in: `./`, `./lib`, `./utils`, or under `./src`. Use `--config` for custom path.
### CLI Commands
-- `npx @better-auth/cli@latest migrate` - Apply schema (built-in adapter)
-- `npx @better-auth/cli@latest generate` - Generate schema for Prisma/Drizzle
-- `npx @better-auth/cli mcp --cursor` - Add MCP to AI tools
+- `bunx @better-auth/cli@latest migrate` - Apply schema (built-in adapter)
+- `bunx @better-auth/cli@latest generate` - Generate schema for Prisma/Drizzle
+- `bunx @better-auth/cli@latest mcp --cursor` - Add MCP to AI tools
**Re-run after adding/changing plugins.**
@@ -172,4 +172,4 @@ For separate client/server projects: `createAuthClient()`.
- [Options Reference](https://better-auth.com/docs/reference/options)
- [LLMs.txt](https://better-auth.com/llms.txt)
- [GitHub](https://github.com/better-auth/better-auth)
-- [Init Options Source](https://github.com/better-auth/better-auth/blob/main/packages/core/src/types/init-options.ts)
\ No newline at end of file
+- [Init Options Source](https://github.com/better-auth/better-auth/blob/main/packages/core/src/types/init-options.ts)
diff --git a/.agents/skills/code/SKILL.md b/.agents/skills/code/SKILL.md
new file mode 100644
index 0000000000..d6028d192f
--- /dev/null
+++ b/.agents/skills/code/SKILL.md
@@ -0,0 +1,185 @@
+---
+name: code
+description: "Use when writing TypeScript/React code - covers type safety, component patterns, and file organization"
+---
+
+Source Cursor rule: `.cursor/rules/code.mdc`.
+Original Cursor alwaysApply: `false`.
+
+# Code Standards
+
+## TypeScript
+
+### No `any`, No Unsafe Casts
+
+```tsx
+// ✅ Validate with zod
+const TaskSchema = z.object({ id: z.string(), title: z.string() });
+const task = TaskSchema.parse(response.data);
+
+// ✅ Use unknown and narrow
+const parseResponse = (data: unknown): Task => {
+ if (!isTask(data)) throw new Error('Invalid');
+ return data;
+};
+
+// ❌ Never
+const data: any = fetchData();
+const task = response as Task;
+const name = user!.name;
+// @ts-ignore
+```
+
+### Generics Over Any
+
+```tsx
+// ✅ Generic
+const first = (items: T[]): T | undefined => items[0];
+
+// ❌ Any
+const first = (items: any[]): any => items[0];
+```
+
+## React Patterns
+
+### Named Exports, PascalCase
+
+```tsx
+// ✅ Named export, PascalCase file
+// TaskCard.tsx
+export function TaskCard({ task }: TaskCardProps) { ... }
+
+// ❌ Default export, lowercase
+export default function taskCard() { ... }
+```
+
+### Derive State, Avoid useEffect
+
+```tsx
+// ✅ Derived
+const completedCount = tasks.filter(t => t.completed).length;
+
+// ❌ Synced state
+const [count, setCount] = useState(0);
+useEffect(() => {
+ setCount(tasks.filter(t => t.completed).length);
+}, [tasks]);
+```
+
+### When useEffect IS Appropriate
+
+```tsx
+// External subscriptions
+useEffect(() => {
+ const sub = eventSource.subscribe(handler);
+ return () => sub.unsubscribe();
+}, []);
+
+// DOM measurements
+useEffect(() => {
+ setHeight(ref.current?.getBoundingClientRect().height);
+}, []);
+```
+
+### Toasts with Sonner
+
+```tsx
+import { toast } from 'sonner';
+
+toast.success('Task created');
+toast.error('Failed to save');
+toast.promise(saveTask(), {
+ loading: 'Saving...',
+ success: 'Saved!',
+ error: 'Failed',
+});
+```
+
+## File Structure
+
+### Colocate at Route Level
+
+```
+app/(app)/[orgId]/tasks/
+├── page.tsx # Server component
+├── components/
+│ └── TaskList.tsx # Client component
+├── hooks/
+│ └── useTasks.ts # SWR hook
+└── data/
+ └── queries.ts # Server queries
+```
+
+### Share Only When Reused 3+ Times
+
+```
+src/components/shared/ # Cross-page components
+src/hooks/ # Shared hooks (useApiSWR, useDebounce)
+```
+
+## Code Quality
+
+### File Size Limit: 300 Lines
+
+Split large files into focused components.
+
+### Named Parameters for 2+ Args
+
+```tsx
+// ✅ Named
+const createTask = ({ title, assigneeId }: CreateTaskParams) => { ... };
+createTask({ title: 'Review PR', assigneeId: user.id });
+
+// ❌ Positional
+const createTask = (title: string, assigneeId: string) => { ... };
+createTask('Review PR', user.id); // What's the 2nd param?
+```
+
+### Early Returns
+
+```tsx
+// ✅ Early return
+function processTask(task: Task | null) {
+ if (!task) return null;
+ if (task.deleted) return null;
+ return ;
+}
+
+// ❌ Nested
+function processTask(task) {
+ if (task) {
+ if (!task.deleted) {
+ return ;
+ }
+ }
+ return null;
+}
+```
+
+### Event Handler Naming
+
+```tsx
+// ✅ Prefix with "handle"
+const handleClick = () => { ... };
+const handleSubmit = (e: FormEvent) => { ... };
+const handleTaskCreate = (task: Task) => { ... };
+```
+
+## Accessibility
+
+```tsx
+// Interactive elements need keyboard support
+ e.key === 'Enter' && handleClick()}
+ aria-label="Delete task"
+>
+
+
+
+// Form inputs need labels
+Task Name
+
+```
diff --git a/.agents/skills/cursor-usage/SKILL.md b/.agents/skills/cursor-usage/SKILL.md
new file mode 100644
index 0000000000..b2b96b6c5c
--- /dev/null
+++ b/.agents/skills/cursor-usage/SKILL.md
@@ -0,0 +1,269 @@
+---
+name: cursor-usage
+description: "How to write and manage Cursor rules - invoke with @cursor-usage"
+---
+
+Source Cursor rule: `.cursor/rules/cursor-usage.mdc`.
+Original file scope: `.cursor/rules/*.mdc`.
+Original Cursor alwaysApply: `false`.
+
+# Using Cursor Rules
+
+## Overview
+
+Cursor rules provide system-level instructions to the AI to maintain code consistency, quality, and adherence to project standards. They are stored in the `.cursor/rules/` directory as `.mdc` (Markdown with frontmatter) files.
+
+## Rule File Structure
+
+Each `.mdc` rule file consists of two parts:
+
+### 1. Frontmatter (YAML metadata)
+
+```yaml
+---
+description: Brief overview of what this rule enforces
+globs: **/*.{ts,tsx}
+alwaysApply: true
+---
+```
+
+**Frontmatter Fields:**
+
+- `description`: A clear, concise explanation of the rule's purpose
+- `globs`: Glob pattern to match files where this rule should apply (plain string, no quotes or arrays)
+ - Examples:
+ - `**/*.tsx` - All TSX files
+ - `**/*.{ts,tsx}` - All TS and TSX files
+ - `apps/*/components/**/*.tsx` - All TSX files in any app's components directory
+ - `**/trigger/**/*.ts` - All TS files in trigger directories
+- `alwaysApply`: Boolean indicating if the rule should always be active
+ - `true`: Rule is always active when working on matching files
+ - `false`: Rule can be selectively invoked with `@rule-name`
+
+### 2. Content (Markdown)
+
+The body of the rule file contains the actual guidelines, examples, and instructions written in Markdown format.
+
+## How Rules Are Applied
+
+### Automatic Application
+
+Rules with `alwaysApply: true` are automatically loaded when:
+
+- You open a file matching the `globs` pattern
+- You're working on code that matches the pattern
+- Cursor AI generates or suggests code for matching files
+
+### Manual Invocation
+
+You can reference specific rules in your prompts:
+
+```
+@design-system create a new button component
+```
+
+This explicitly tells Cursor to apply the design-system rule.
+
+## Best Practices for Writing Rules
+
+### 1. Keep Rules Focused
+
+- Each rule file should cover a specific domain (e.g., design system, API patterns, testing)
+- Avoid mixing unrelated concerns in a single rule file
+- Aim for rules under 500 lines for better AI comprehension
+
+### 2. Provide Concrete Examples
+
+Always include:
+
+- ✅ Good examples (what TO do)
+- ❌ Bad examples (what NOT to do)
+- Real code snippets from your project
+
+```tsx
+// ✅ Good: Use semantic tokens
+Content
+
+// ❌ Bad: Hardcoded colors
+Content
+```
+
+### 3. Use Clear Section Headers
+
+Organize content with descriptive headers:
+
+```markdown
+## Core Principles
+
+## Rules
+
+## Examples
+
+## Exceptions
+
+## Common Mistakes
+```
+
+### 4. Define Exceptions Explicitly
+
+If there are cases where rules don't apply, state them clearly:
+
+```markdown
+## Exceptions
+
+The ONLY time you can pass className to a design system component is for:
+
+1. Width utilities: `w-full`, `max-w-md`
+2. Responsive display: `hidden`, `md:block`
+```
+
+### 5. Include Checklists
+
+Provide actionable checklists for validation:
+
+```markdown
+## Code Review Checklist
+
+Before committing:
+
+- [ ] Uses semantic color tokens
+- [ ] Works in both light and dark mode
+- [ ] Fully responsive
+```
+
+## Managing Rules
+
+### Creating a New Rule
+
+1. Create a new `.mdc` file in `.cursor/rules/`
+2. Add appropriate frontmatter
+3. Write clear guidelines with examples
+4. Test by working on matching files
+
+### Updating Existing Rules
+
+1. Edit the `.mdc` file
+2. Rules are automatically reloaded
+3. Test changes with relevant files
+
+### Organizing Rules
+
+Recommended structure:
+
+```
+.cursor/rules/
+├── design-system.mdc # Component usage, variants, composition
+├── code-standards.mdc # General code quality rules
+├── typescript-rules.mdc # TypeScript type safety
+├── react-code.mdc # React patterns and conventions
+├── data-fetching.mdc # Server/client data patterns
+└── cursor-usage.mdc # This file - how to use rules
+```
+
+## Rule Scope with Globs
+
+### Common Glob Patterns
+
+```yaml
+# All TypeScript/TSX files
+globs: **/*.{ts,tsx}
+
+# Only TSX files (React components)
+globs: **/*.tsx
+
+# Only trigger task files
+globs: **/trigger/**/*.ts
+
+# Prisma schema files
+globs: **/*.prisma
+
+# All JSON and TypeScript files
+globs: **/*.{ts,tsx,json}
+```
+
+### Glob Pattern Tips
+
+- Use `**` for recursive directory matching
+- Use `*` for single-level wildcard
+- Use `{ts,tsx}` for multiple extensions
+- No quotes or array brackets needed
+- Be specific to avoid over-applying rules
+
+## Debugging Rules
+
+### Rule Not Applying?
+
+1. Check the `globs` pattern matches your file
+2. Verify frontmatter YAML syntax is correct
+3. Ensure `alwaysApply` is set appropriately
+4. Try manually invoking with `@ruleName`
+
+### Rule Conflicting?
+
+1. Check if multiple rules apply to the same files
+2. Make rules more specific with tighter `globs`
+3. Consolidate related rules into one file
+
+## Advanced Features
+
+### Conditional Rules
+
+Use `alwaysApply: false` for rules that should only apply in specific contexts:
+
+```yaml
+---
+description: Performance optimization guidelines
+globs: **/*.ts
+alwaysApply: false
+---
+```
+
+Invoke with: `@performance-optimization refactor this component`
+
+### Hierarchical Rules
+
+More specific globs take precedence:
+
+- `design-system.mdc` with `globs: **/*.tsx` (broad)
+- `trigger.basic.mdc` with `globs: **/trigger/**/*.ts` (specific)
+
+The specific rule will have more weight for trigger files.
+
+## Quick Reference
+
+### Create a New Rule
+
+```bash
+touch .cursor/rules/my-new-rule.mdc
+```
+
+```yaml
+---
+description: What this rule enforces
+globs: **/*.{ts,tsx}
+alwaysApply: true
+---
+
+# Rule Title
+
+## Guidelines
+
+- Point 1
+- Point 2
+```
+
+### Apply a Rule
+
+- Automatic: Save a file matching the `globs` pattern
+- Manual: Use `@my-new-rule` in your prompt
+
+### Debug a Rule
+
+1. Check file matches `globs` pattern
+2. Verify YAML frontmatter syntax
+3. Look for conflicting rules
+4. Try manual invocation
+
+---
+
+**Remember**: Rules are here to help, not hinder. If a rule doesn't make sense for a specific case, discuss with the team and update the rule accordingly.
diff --git a/.agents/skills/data/SKILL.md b/.agents/skills/data/SKILL.md
new file mode 100644
index 0000000000..9acffa3874
--- /dev/null
+++ b/.agents/skills/data/SKILL.md
@@ -0,0 +1,146 @@
+---
+name: data
+description: "Use when implementing data fetching, API calls, server/client components, or SWR hooks"
+---
+
+Source Cursor rule: `.cursor/rules/data.mdc`.
+Original Cursor alwaysApply: `false`.
+
+# Data Fetching
+
+## Core Pattern: Server → Client → SWR
+
+### 1. Server Page Fetches Data
+
+```tsx
+// app/(app)/[orgId]/tasks/page.tsx
+export default async function TasksPage({ params }: { params: Promise<{ orgId: string }> }) {
+ const { orgId } = await params; // From URL, NOT session
+ const tasks = await getTasks(orgId);
+ return ;
+}
+```
+
+### 2. Client Component Receives Initial Data
+
+```tsx
+// components/TaskListClient.tsx
+'use client';
+
+export function TaskListClient({ organizationId, initialTasks }: Props) {
+ const { tasks, createTask, updateTask } = useTasks({
+ organizationId,
+ initialData: initialTasks,
+ });
+ // Initial render is instant - no loading state
+}
+```
+
+### 3. SWR Hook with fallbackData
+
+```tsx
+// hooks/useTasks.ts
+export function useTasks({ organizationId, initialData }: UseTasksOptions) {
+ const { data, mutate } = useSWR(
+ ['/v1/tasks', organizationId], // Include orgId for cache isolation
+ async ([endpoint, orgId]) => {
+ const response = await apiClient.get(endpoint, orgId);
+ return response.data?.tasks ?? [];
+ },
+ { fallbackData: initialData }
+ );
+
+ const createTask = async (input: CreateTaskInput) => {
+ await apiClient.post('/v1/tasks', input, organizationId);
+ mutate(); // Revalidate
+ };
+
+ const updateTask = async ({ taskId, input }: { taskId: string; input: UpdateTaskInput }) => {
+ await apiClient.put(`/v1/tasks/${taskId}`, input, organizationId);
+ mutate(); // Revalidate
+ };
+
+ return { tasks: data ?? [], createTask, updateTask, mutate };
+}
+```
+
+## API Client
+
+Use `apiClient` from `@/lib/api-client`:
+
+```tsx
+import { apiClient } from '@/lib/api-client';
+
+await apiClient.get('/v1/endpoint', organizationId);
+await apiClient.post('/v1/endpoint', body, organizationId);
+await apiClient.put('/v1/endpoint', body, organizationId);
+await apiClient.delete('/v1/endpoint', organizationId);
+```
+
+## Server vs Client Components
+
+**Layouts = server.** Interactive logic in separate client components.
+
+```tsx
+// layout.tsx (server)
+export default function Layout({ children }) {
+ return (
+
+
+ {/* Client component */}
+ {children}
+
+ );
+}
+
+// components/ClientTabs.tsx
+'use client';
+export function ClientTabs() {
+ const router = useRouter();
+ // Interactive logic here
+}
+```
+
+## State Management
+
+**No `nuqs`** - use React state or Next.js patterns:
+
+```tsx
+// ✅ React state for UI
+const [isOpen, setIsOpen] = useState(false);
+
+// ✅ Next.js for URL state
+const router = useRouter();
+const searchParams = useSearchParams();
+
+// ❌ No nuqs
+import { useQueryState } from 'nuqs';
+```
+
+## Rules
+
+```tsx
+// ✅ Always
+const { orgId } = await params; // From URL params
+const { data } = useSWR(key, f, { fallbackData }); // With initial data
+await apiClient.get('/v1/endpoint', orgId); // Use apiClient
+useSWR(['/v1/tasks', orgId], fetcher); // Include orgId in key
+
+// ❌ Never
+const orgId = session?.activeOrganizationId; // From session
+const { data } = useSWR('/api/data'); // No initial data
+await fetch('/api/endpoint'); // Direct fetch
+```
+
+## File Structure
+
+```
+app/(app)/[orgId]/tasks/
+├── page.tsx # Server - fetches data
+├── components/
+│ └── TaskListClient.tsx # Client - receives initialData
+├── hooks/
+│ └── useTasks.ts # SWR hook with mutations
+└── data/
+ └── queries.ts # Server-side queries
+```
diff --git a/.agents/skills/essentials/SKILL.md b/.agents/skills/essentials/SKILL.md
new file mode 100644
index 0000000000..21711433da
--- /dev/null
+++ b/.agents/skills/essentials/SKILL.md
@@ -0,0 +1,108 @@
+---
+name: essentials
+description: "Critical rules that must always be followed"
+---
+
+Source Cursor rule: `.cursor/rules/essentials.mdc`.
+Original file scope: `**/*.{ts,tsx}`.
+Original Cursor alwaysApply: `true`.
+
+# Essentials
+
+## Package Manager
+
+Use `bun`, never npm/yarn/pnpm.
+
+```bash
+bun install # Install deps
+bun add # Add package
+bun run