Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
23 commits
Select commit Hold shift + click to select a range
93ede07
chore(automation): set default title and handle empty integrations in…
Marfuen Oct 6, 2025
897fd6e
Merge branch 'main' of https://github.com/trycompai/comp into mariano…
Marfuen Oct 6, 2025
735e281
chore: add ability to support multiple automations per task
Marfuen Oct 6, 2025
1c1e9e6
chore(automation): add update and delete functionality for task autom…
Marfuen Oct 6, 2025
c9b1f56
refactor(tasks): simplify task fetching and remove unused members logic
Marfuen Oct 6, 2025
0e30323
Merge branch 'main' of https://github.com/trycompai/comp into mariano…
Marfuen Oct 7, 2025
679b382
chore(automation): implement automated evidence collection and relate…
Marfuen Oct 7, 2025
14a890d
chore(docs): add fraud to risk category enum in openapi schema
Marfuen Oct 8, 2025
7ed986e
Merge branch 'main' of https://github.com/trycompai/comp into mariano…
Marfuen Oct 8, 2025
47389be
refactor(automation): remove organizationId from automation methods
Marfuen Oct 8, 2025
217eecb
Merge branch 'main' of https://github.com/trycompai/comp into mariano…
Marfuen Oct 8, 2025
4ad255a
chore: cleanup and add automations
Marfuen Oct 8, 2025
a8dd3a7
feat(automation): enhance automation overview with latest runs and de…
Marfuen Oct 9, 2025
0d1e59a
chore: cleanup chat
Marfuen Oct 9, 2025
4cd8fac
feat: added chat history
Marfuen Oct 9, 2025
ebb4588
refactor(chat): use ref for automationId to improve state management
Marfuen Oct 9, 2025
03df4e1
chore(automation): implement versioning for automation scripts with A…
Marfuen Oct 12, 2025
1ed7e60
Merge branch 'main' of https://github.com/trycompai/comp into mariano…
Marfuen Oct 13, 2025
e69c5f3
chore: update bun lock
Marfuen Oct 13, 2025
99f4d4f
chore: update UI
Marfuen Oct 13, 2025
8a91278
Merge branch 'main' of https://github.com/trycompai/comp into mariano…
Marfuen Oct 14, 2025
d75a8a0
chore(automation): update integrationsUsed type in UnifiedWorkflowCard
Marfuen Oct 14, 2025
3da67d3
chore(deps): add better-auth package and update TypeScript target
Marfuen Oct 14, 2025
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
1 change: 1 addition & 0 deletions apps/api/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,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
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
59 changes: 59 additions & 0 deletions apps/api/src/automation/automation.controller.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
import {
Body,
Controller,
Param,
Patch,
Post,
UseGuards,
} from '@nestjs/common';
import {
ApiHeader,
ApiOperation,
ApiResponse,
ApiSecurity,
ApiTags,
} from '@nestjs/swagger';
import { HybridAuthGuard } from '../auth/hybrid-auth.guard';
import { AutomationService } from './automation.service';
import { CreateAutomationDto } from './dto/create-automation.dto';
import { UpdateAutomationDto } from './dto/update-automation.dto';
import { AUTOMATION_OPERATIONS } from './schemas/automation-operations';
import { CREATE_AUTOMATION_RESPONSES } from './schemas/create-automation.responses';
import { UPDATE_AUTOMATION_RESPONSES } from './schemas/update-automation.responses';

@ApiTags('Automations')
@Controller({ path: 'automations', version: '1' })
@UseGuards(HybridAuthGuard)
@ApiSecurity('apikey')
@ApiHeader({
name: 'X-Organization-Id',
description:
'Organization ID (required for session auth, optional for API key auth)',
required: false,
})
export class AutomationController {
constructor(private readonly automationService: AutomationService) {}

@Post()
@ApiOperation(AUTOMATION_OPERATIONS.createAutomation)
@ApiResponse(CREATE_AUTOMATION_RESPONSES[201])
@ApiResponse(CREATE_AUTOMATION_RESPONSES[400])
@ApiResponse(CREATE_AUTOMATION_RESPONSES[401])
@ApiResponse(CREATE_AUTOMATION_RESPONSES[404])
async createAutomation(@Body() createAutomationDto: CreateAutomationDto) {
return this.automationService.create(createAutomationDto);
}

@Patch(':automationId')
@ApiOperation(AUTOMATION_OPERATIONS.updateAutomation)
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[200])
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[400])
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[401])
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[404])
async updateAutomation(
@Param('automationId') automationId: string,
@Body() updateAutomationDto: UpdateAutomationDto,
) {
return this.automationService.update(automationId, updateAutomationDto);
}
}
11 changes: 11 additions & 0 deletions apps/api/src/automation/automation.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { Module } from '@nestjs/common';
import { AuthModule } from '../auth/auth.module';
import { AutomationController } from './automation.controller';
import { AutomationService } from './automation.service';

@Module({
imports: [AuthModule],
controllers: [AutomationController],
providers: [AutomationService],
})
export class AutomationModule {}
Loading
Loading