Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
70 changes: 68 additions & 2 deletions .cursor/rules/design-system.mdc
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
---
description:
globs: *.tsx
description: Any time we are going to write react components and / or layouts
alwaysApply: false
---

Expand Down Expand Up @@ -28,10 +27,77 @@ Design System & Component Guidelines

## Layout & Spacing

- **Flexbox-First**: ALWAYS prefer flexbox with `gap` over hardcoded margins (`mt-`, `mb-`, `ml-`, `mr-`)
- **Use Gaps, Not Margins**: Use `gap-2`, `gap-4`, `space-y-4` for spacing between elements
- **Consistent Spacing**: Use standard Tailwind spacing scale (`space-y-4`, `gap-6`, etc.)
- **Card-Based Layouts**: Prefer Card components for content organization
- **Minimal Padding**: Use conservative padding - `p-3`, `p-4` rather than larger values
- **Clean Separators**: Use subtle borders (`border-t`, `border-muted`) instead of heavy dividers
- **NEVER Hardcode Margins**: Avoid `mt-4`, `mb-2`, `ml-3` unless absolutely necessary for exceptions

## Color & Visual Elements

- **Status Colors**:
- Green for completed/success states
- Blue for in-progress/info states
- Yellow for warnings
- Red for errors/destructive actions
- **Subtle Indicators**: Use small colored dots (`w-2 h-2 rounded-full`) instead of large icons for status
- **Minimal Shadows**: Prefer `hover:shadow-sm` over heavy shadow effects
- **Progress Bars**: Keep thin (`h-1`, `h-2`) for minimal visual weight

## Interactive Elements

- **Subtle Hover States**: Use gentle transitions (`transition-shadow`, `hover:shadow-sm`)
- **Consistent Button Sizing**: Prefer `size="sm"` for most buttons, `size="icon"` for icon-only
- **Badge Usage**: Keep badges minimal with essential info only (percentages, short status)

## Data Display

- **Shared Design Language**: Ensure related components (cards, overviews, details) use consistent patterns
- **Minimal Stats**: Present data cleanly without excessive decoration
- **Contextual Icons**: Use small, relevant icons (`h-3 w-3`, `h-4 w-4`) sparingly for context

## Anti-Patterns to Avoid

- Large text sizes (`text-2xl+` except for main headings)
- Heavy shadows or borders
- Excessive use of colored backgrounds
- Redundant badges or status indicators
- Complex custom styling overrides
- Non-semantic color usage (hardcoded hex values)
- Cluttered layouts with too many visual elements
Rule Name: design-system
Description:
Design System & Component Guidelines

## Design Philosophy

- **B2B, Modern, Flat, Minimal, Elegant**: All UI should follow a clean, professional aesthetic suitable for business applications
- **Sleek & Minimal**: Avoid visual clutter, use whitespace effectively, keep interfaces clean
- **Dark Mode First**: Always ensure components work seamlessly in both light and dark modes

## Component Usage

- **Adhere to Base Components**: Minimize custom overrides and stick to shadcn/ui base components whenever possible
- **Semantic Color Classes**: Use semantic classes like `text-muted-foreground`, `bg-muted/50` instead of hardcoded colors
- **Dark Mode Support**: Always use dark mode variants like `bg-green-50 dark:bg-green-950/20`, `text-green-600 dark:text-green-400`

## Typography & Sizing

- **Moderate Text Sizes**: Avoid overly large text - prefer `text-base`, `text-sm`, `text-xs` over `text-xl+`
- **Consistent Hierarchy**: Use `font-medium`, `font-semibold` sparingly, prefer `font-normal` with size differentiation
- **Tabular Numbers**: Use `tabular-nums` class for numeric data to ensure proper alignment

## Layout & Spacing

- **Flexbox-First**: ALWAYS prefer flexbox with `gap` over hardcoded margins (`mt-`, `mb-`, `ml-`, `mr-`)
- **Use Gaps, Not Margins**: Use `gap-2`, `gap-4`, `space-y-4` for spacing between elements
- **Consistent Spacing**: Use standard Tailwind spacing scale (`space-y-4`, `gap-6`, etc.)
- **Card-Based Layouts**: Prefer Card components for content organization
- **Minimal Padding**: Use conservative padding - `p-3`, `p-4` rather than larger values
- **Clean Separators**: Use subtle borders (`border-t`, `border-muted`) instead of heavy dividers
- **NEVER Hardcode Margins**: Avoid `mt-4`, `mb-2`, `ml-3` unless absolutely necessary for exceptions

## Color & Visual Elements

Expand Down
184 changes: 184 additions & 0 deletions ENTERPRISE_API_AUTOMATION_VERSIONING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# Enterprise API - Automation Versioning Endpoints

## Overview

Implement versioning for automation scripts. The Next.js app handles database operations (storing version metadata), while the Enterprise API handles S3 operations (copying/managing script files) and Redis operations (chat history).

## Context

### Current S3 Structure

- **Draft script**: `{orgId}/{taskId}/{automationId}.automation.js`
- Scripts are stored in S3 via the enterprise API

### New S3 Structure for Versions

- **Draft script**: `{orgId}/{taskId}/{automationId}.draft.js`
- **Published versions**: `{orgId}/{taskId}/{automationId}.v{version}.js`

**Migration Note**: Existing scripts at `{automationId}.automation.js` should be moved to `{automationId}.draft.js`

### Database (handled by Next.js app)

- `EvidenceAutomationVersion` table stores version metadata
- Next.js app creates version records after enterprise API copies files

## Endpoints to Implement

### 1. Publish Draft Script

**Endpoint**: `POST /api/tasks-automations/publish`

**Purpose**: Create a new version by copying current draft script to a versioned S3 key.

**Request Body**:

```typescript
{
orgId: string;
taskId: string;
automationId: string;
}
```

**Process**:

1. Construct draft S3 key: `{orgId}/{taskId}/{automationId}.draft.js`
2. Check if draft script exists in S3
3. If not found, return error: `{ success: false, error: 'No draft script found to publish' }`
4. Query database to get the next version number:
- Find highest existing version for this `automationId`
- Increment by 1 (or start at 1 if no versions exist)
5. Construct version S3 key: `{orgId}/{taskId}/{automationId}.v{nextVersion}.js`
6. Copy draft script to version key in S3
7. Return success with the version number and scriptKey

**Response**:

```typescript
{
success: boolean;
version?: number; // e.g., 1, 2, 3
scriptKey?: string; // e.g., "org_xxx/tsk_xxx/aut_xxx.v1.js"
error?: string;
}
```

**Note**: Enterprise API determines the version number server-side by querying the database, not from client input. This prevents version conflicts.

**Error Cases**:

- Draft script not found in S3
- S3 copy operation fails
- Invalid orgId/taskId/automationId

---

### 2. Restore Version to Draft

**Endpoint**: `POST /api/tasks-automations/restore-version`

**Purpose**: Replace current draft script with a published version's script. Chat history is preserved.

**Request Body**:

```typescript
{
orgId: string;
taskId: string;
automationId: string;
version: number; // Which version to restore (e.g., 1, 2, 3)
}
```

**Process**:

1. Construct version S3 key: `{orgId}/{taskId}/{automationId}.v{version}.js`
2. Check if version script exists in S3
3. If not found, return error: `{ success: false, error: 'Version not found' }`
4. Construct draft S3 key: `{orgId}/{taskId}/{automationId}.draft.js`
5. Copy version script to draft key in S3 (overwrites current draft)
6. Do NOT touch Redis chat history - it should persist
7. Return success

**Response**:

```typescript
{
success: boolean;
error?: string;
}
```

**Error Cases**:

- Version script not found in S3
- S3 copy operation fails
- Invalid version number

---

## Implementation Notes

### S3 Operations

- Use AWS S3 SDK's `copyObject` method to copy between keys
- Bucket name should come from environment variables
- Ensure proper error handling for S3 operations

### Authentication

- These endpoints should require authentication (API key or session)
- Validate that the user has access to the organization/task/automation

### Redis Chat History

- **Important**: Do NOT clear or modify chat history when restoring versions
- Chat history key format: `automation:{automationId}:chat`
- Chat history persists regardless of which version is in the draft

### Example S3 Keys

For automation `aut_68e6a70803cf925eac17896a` in task `tsk_68e6a5c1e0b762e741c2e020`:

- **Draft**: `org_68e6a5c1d30338b3981c2104/tsk_68e6a5c1e0b762e741c2e020/aut_68e6a70803cf925eac17896a.draft.js`
- **Version 1**: `org_68e6a5c1d30338b3981c2104/tsk_68e6a5c1e0b762e741c2e020/aut_68e6a70803cf925eac17896a.v1.js`
- **Version 2**: `org_68e6a5c1d30338b3981c2104/tsk_68e6a5c1e0b762e741c2e020/aut_68e6a70803cf925eac17896a.v2.js`

### Integration Flow

#### Publishing a Version

1. User clicks "Publish" in Next.js UI with optional changelog
2. Next.js calls `POST /api/tasks-automations/publish` (no version number in request)
3. Enterprise API:
- Queries database to get next version number
- Copies draft → versioned S3 key
- Returns version number and scriptKey
4. Next.js saves version record to database with returned version number, scriptKey, and changelog

#### Restoring a Version

1. User clicks "Restore Version X" in Next.js UI
2. Shows confirmation dialog warning current draft will be lost
3. Next.js calls `POST /api/tasks-automations/restore-version`
4. Enterprise API copies version script → draft S3 key
5. Enterprise API returns success
6. Next.js shows success message
7. User can continue editing in builder with restored script

### Error Handling

- Return proper HTTP status codes (404 for not found, 400 for bad request, 500 for S3 errors)
- Include descriptive error messages in response body
- Log errors for debugging

### Testing Checklist

- [ ] Can publish a draft script as version 1
- [ ] Can publish multiple versions (1, 2, 3...)
- [ ] Cannot publish if no draft exists
- [ ] Can restore version 1 to draft
- [ ] Restoring doesn't affect chat history
- [ ] S3 keys follow correct naming convention
- [ ] Proper error messages when scripts don't exist
23 changes: 16 additions & 7 deletions apps/api/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,23 +1,32 @@
# Use Node.js runtime for production
FROM node:20-alpine

# Install wget for health check
RUN apk add --no-cache wget
# Install required packages (wget for healthcheck, curl/bash for bun install, libc compat for prisma)
RUN apk add --no-cache wget curl bash libc6-compat openssl

WORKDIR /app

# Copy the entire pre-built bundle (no dependencies needed)
# Copy manifests first and install production deps inside the image (avoid broken bun symlinks)
COPY package.json ./

# Install bun and deps
RUN curl -fsSL https://bun.sh/install | bash \
&& export PATH="/root/.bun/bin:$PATH" \
&& bun install --production --ignore-scripts

# Now copy the pre-built app contents (dist/, prisma/, etc.)
COPY . .

# Generate Prisma client inside the image (ensures runtime client matches installed deps)
RUN npx prisma generate

# Set environment variables
ENV NODE_ENV=production
ENV PORT=3333

# Create a non-root user for security
RUN addgroup --system nestjs && adduser --system --ingroup nestjs nestjs

# Change ownership to nestjs user
RUN chown -R nestjs:nestjs /app
RUN addgroup --system nestjs && adduser --system --ingroup nestjs nestjs \
&& chown -R nestjs:nestjs /app

USER nestjs

Expand Down
8 changes: 5 additions & 3 deletions apps/api/buildspec.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ phases:

# Install only API workspace dependencies
- echo "Installing API dependencies only..."
- bun install --filter=@comp/api --frozen-lockfile
- bun install --filter=@comp/api --frozen-lockfile || bun install --filter=@comp/api --ignore-scripts || bun install --ignore-scripts

# Build NestJS application (prebuild automatically handles Prisma)
- echo "Building NestJS application..."
Expand Down Expand Up @@ -66,12 +66,14 @@ phases:
- '[ -f "../docker-build/src/main.js" ] || { echo "❌ main.js not found in docker-build/src"; exit 1; }'

# Copy entire node_modules for runtime (includes @trycompai/db from npm)
- echo "Bundling all runtime dependencies..."
- cp -r ../../node_modules ../docker-build/
- echo "Skipping host node_modules copy; Dockerfile installs prod deps inside image"

# Copy Dockerfile
- echo "Copying Dockerfile..."
- cp Dockerfile ../docker-build/
- echo "Copying package manifests for image install..."
- cp package.json ../docker-build/
- cp ../../bun.lock ../docker-build/ || true

# Build Docker image
- echo "Building Docker image..."
Expand Down
7 changes: 5 additions & 2 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
"version": "0.0.1",
"author": "",
"dependencies": {
"@prisma/client": "^6.13.0",
"prisma": "^6.13.0",
"@aws-sdk/client-s3": "^3.859.0",
"@aws-sdk/s3-request-presigner": "^3.859.0",
"@nestjs/common": "^11.0.1",
Expand All @@ -14,6 +16,7 @@
"@trycompai/db": "^1.3.7",
"archiver": "^7.0.1",
"axios": "^1.12.2",
"better-auth": "^1.3.27",
"class-transformer": "^0.5.1",
"class-validator": "^0.14.2",
"jose": "^6.0.12",
Expand Down Expand Up @@ -70,8 +73,8 @@
"private": true,
"scripts": {
"build": "nest build",
"build:docker": "prisma generate && nest build",
"db:generate": "bun run db:getschema && prisma generate",
"build:docker": "bunx prisma generate && nest build",
"db:generate": "bun run db:getschema && bunx prisma generate",
"db:getschema": "node ../../packages/db/scripts/combine-schemas.js && cp ../../packages/db/dist/schema.prisma prisma/schema.prisma",
"db:migrate": "cd ../../packages/db && bunx prisma migrate dev && cd ../../apps/api",
"dev": "nest start --watch",
Expand Down
1 change: 0 additions & 1 deletion apps/api/src/app.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@ import { TasksModule } from './tasks/tasks.module';
import { VendorsModule } from './vendors/vendors.module';
import { ContextModule } from './context/context.module';


@Module({
imports: [
ConfigModule.forRoot({
Expand Down
Loading
Loading