Skip to content

Commit cbff0f9

Browse files
[dev] [Marfuen] mariano/more-10 (#1610)
* chore(automation): set default title and handle empty integrations in workflow visualizer * chore: add ability to support multiple automations per task * chore(automation): add update and delete functionality for task automations * refactor(tasks): simplify task fetching and remove unused members logic * chore(automation): implement automated evidence collection and related schema * chore(docs): add fraud to risk category enum in openapi schema * refactor(automation): remove organizationId from automation methods * chore: cleanup and add automations * feat(automation): enhance automation overview with latest runs and details * chore: cleanup chat * feat: added chat history * refactor(chat): use ref for automationId to improve state management * chore(automation): implement versioning for automation scripts with API endpoints * chore: update bun lock * chore: update UI * chore(automation): update integrationsUsed type in UnifiedWorkflowCard * chore(deps): add better-auth package and update TypeScript target --------- Co-authored-by: Mariano Fuentes <[email protected]>
1 parent 1dd9e16 commit cbff0f9

File tree

159 files changed

+5225
-1332
lines changed

Some content is hidden

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

159 files changed

+5225
-1332
lines changed

.cursor/rules/design-system.mdc

Lines changed: 68 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
---
2-
description:
3-
globs: *.tsx
2+
description: Any time we are going to write react components and / or layouts
43
alwaysApply: false
54
---
65

@@ -28,10 +27,77 @@ Design System & Component Guidelines
2827

2928
## Layout & Spacing
3029

30+
- **Flexbox-First**: ALWAYS prefer flexbox with `gap` over hardcoded margins (`mt-`, `mb-`, `ml-`, `mr-`)
31+
- **Use Gaps, Not Margins**: Use `gap-2`, `gap-4`, `space-y-4` for spacing between elements
3132
- **Consistent Spacing**: Use standard Tailwind spacing scale (`space-y-4`, `gap-6`, etc.)
3233
- **Card-Based Layouts**: Prefer Card components for content organization
3334
- **Minimal Padding**: Use conservative padding - `p-3`, `p-4` rather than larger values
3435
- **Clean Separators**: Use subtle borders (`border-t`, `border-muted`) instead of heavy dividers
36+
- **NEVER Hardcode Margins**: Avoid `mt-4`, `mb-2`, `ml-3` unless absolutely necessary for exceptions
37+
38+
## Color & Visual Elements
39+
40+
- **Status Colors**:
41+
- Green for completed/success states
42+
- Blue for in-progress/info states
43+
- Yellow for warnings
44+
- Red for errors/destructive actions
45+
- **Subtle Indicators**: Use small colored dots (`w-2 h-2 rounded-full`) instead of large icons for status
46+
- **Minimal Shadows**: Prefer `hover:shadow-sm` over heavy shadow effects
47+
- **Progress Bars**: Keep thin (`h-1`, `h-2`) for minimal visual weight
48+
49+
## Interactive Elements
50+
51+
- **Subtle Hover States**: Use gentle transitions (`transition-shadow`, `hover:shadow-sm`)
52+
- **Consistent Button Sizing**: Prefer `size="sm"` for most buttons, `size="icon"` for icon-only
53+
- **Badge Usage**: Keep badges minimal with essential info only (percentages, short status)
54+
55+
## Data Display
56+
57+
- **Shared Design Language**: Ensure related components (cards, overviews, details) use consistent patterns
58+
- **Minimal Stats**: Present data cleanly without excessive decoration
59+
- **Contextual Icons**: Use small, relevant icons (`h-3 w-3`, `h-4 w-4`) sparingly for context
60+
61+
## Anti-Patterns to Avoid
62+
63+
- Large text sizes (`text-2xl+` except for main headings)
64+
- Heavy shadows or borders
65+
- Excessive use of colored backgrounds
66+
- Redundant badges or status indicators
67+
- Complex custom styling overrides
68+
- Non-semantic color usage (hardcoded hex values)
69+
- Cluttered layouts with too many visual elements
70+
Rule Name: design-system
71+
Description:
72+
Design System & Component Guidelines
73+
74+
## Design Philosophy
75+
76+
- **B2B, Modern, Flat, Minimal, Elegant**: All UI should follow a clean, professional aesthetic suitable for business applications
77+
- **Sleek & Minimal**: Avoid visual clutter, use whitespace effectively, keep interfaces clean
78+
- **Dark Mode First**: Always ensure components work seamlessly in both light and dark modes
79+
80+
## Component Usage
81+
82+
- **Adhere to Base Components**: Minimize custom overrides and stick to shadcn/ui base components whenever possible
83+
- **Semantic Color Classes**: Use semantic classes like `text-muted-foreground`, `bg-muted/50` instead of hardcoded colors
84+
- **Dark Mode Support**: Always use dark mode variants like `bg-green-50 dark:bg-green-950/20`, `text-green-600 dark:text-green-400`
85+
86+
## Typography & Sizing
87+
88+
- **Moderate Text Sizes**: Avoid overly large text - prefer `text-base`, `text-sm`, `text-xs` over `text-xl+`
89+
- **Consistent Hierarchy**: Use `font-medium`, `font-semibold` sparingly, prefer `font-normal` with size differentiation
90+
- **Tabular Numbers**: Use `tabular-nums` class for numeric data to ensure proper alignment
91+
92+
## Layout & Spacing
93+
94+
- **Flexbox-First**: ALWAYS prefer flexbox with `gap` over hardcoded margins (`mt-`, `mb-`, `ml-`, `mr-`)
95+
- **Use Gaps, Not Margins**: Use `gap-2`, `gap-4`, `space-y-4` for spacing between elements
96+
- **Consistent Spacing**: Use standard Tailwind spacing scale (`space-y-4`, `gap-6`, etc.)
97+
- **Card-Based Layouts**: Prefer Card components for content organization
98+
- **Minimal Padding**: Use conservative padding - `p-3`, `p-4` rather than larger values
99+
- **Clean Separators**: Use subtle borders (`border-t`, `border-muted`) instead of heavy dividers
100+
- **NEVER Hardcode Margins**: Avoid `mt-4`, `mb-2`, `ml-3` unless absolutely necessary for exceptions
35101

36102
## Color & Visual Elements
37103

Lines changed: 184 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Enterprise API - Automation Versioning Endpoints
2+
3+
## Overview
4+
5+
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).
6+
7+
## Context
8+
9+
### Current S3 Structure
10+
11+
- **Draft script**: `{orgId}/{taskId}/{automationId}.automation.js`
12+
- Scripts are stored in S3 via the enterprise API
13+
14+
### New S3 Structure for Versions
15+
16+
- **Draft script**: `{orgId}/{taskId}/{automationId}.draft.js`
17+
- **Published versions**: `{orgId}/{taskId}/{automationId}.v{version}.js`
18+
19+
**Migration Note**: Existing scripts at `{automationId}.automation.js` should be moved to `{automationId}.draft.js`
20+
21+
### Database (handled by Next.js app)
22+
23+
- `EvidenceAutomationVersion` table stores version metadata
24+
- Next.js app creates version records after enterprise API copies files
25+
26+
## Endpoints to Implement
27+
28+
### 1. Publish Draft Script
29+
30+
**Endpoint**: `POST /api/tasks-automations/publish`
31+
32+
**Purpose**: Create a new version by copying current draft script to a versioned S3 key.
33+
34+
**Request Body**:
35+
36+
```typescript
37+
{
38+
orgId: string;
39+
taskId: string;
40+
automationId: string;
41+
}
42+
```
43+
44+
**Process**:
45+
46+
1. Construct draft S3 key: `{orgId}/{taskId}/{automationId}.draft.js`
47+
2. Check if draft script exists in S3
48+
3. If not found, return error: `{ success: false, error: 'No draft script found to publish' }`
49+
4. Query database to get the next version number:
50+
- Find highest existing version for this `automationId`
51+
- Increment by 1 (or start at 1 if no versions exist)
52+
5. Construct version S3 key: `{orgId}/{taskId}/{automationId}.v{nextVersion}.js`
53+
6. Copy draft script to version key in S3
54+
7. Return success with the version number and scriptKey
55+
56+
**Response**:
57+
58+
```typescript
59+
{
60+
success: boolean;
61+
version?: number; // e.g., 1, 2, 3
62+
scriptKey?: string; // e.g., "org_xxx/tsk_xxx/aut_xxx.v1.js"
63+
error?: string;
64+
}
65+
```
66+
67+
**Note**: Enterprise API determines the version number server-side by querying the database, not from client input. This prevents version conflicts.
68+
69+
**Error Cases**:
70+
71+
- Draft script not found in S3
72+
- S3 copy operation fails
73+
- Invalid orgId/taskId/automationId
74+
75+
---
76+
77+
### 2. Restore Version to Draft
78+
79+
**Endpoint**: `POST /api/tasks-automations/restore-version`
80+
81+
**Purpose**: Replace current draft script with a published version's script. Chat history is preserved.
82+
83+
**Request Body**:
84+
85+
```typescript
86+
{
87+
orgId: string;
88+
taskId: string;
89+
automationId: string;
90+
version: number; // Which version to restore (e.g., 1, 2, 3)
91+
}
92+
```
93+
94+
**Process**:
95+
96+
1. Construct version S3 key: `{orgId}/{taskId}/{automationId}.v{version}.js`
97+
2. Check if version script exists in S3
98+
3. If not found, return error: `{ success: false, error: 'Version not found' }`
99+
4. Construct draft S3 key: `{orgId}/{taskId}/{automationId}.draft.js`
100+
5. Copy version script to draft key in S3 (overwrites current draft)
101+
6. Do NOT touch Redis chat history - it should persist
102+
7. Return success
103+
104+
**Response**:
105+
106+
```typescript
107+
{
108+
success: boolean;
109+
error?: string;
110+
}
111+
```
112+
113+
**Error Cases**:
114+
115+
- Version script not found in S3
116+
- S3 copy operation fails
117+
- Invalid version number
118+
119+
---
120+
121+
## Implementation Notes
122+
123+
### S3 Operations
124+
125+
- Use AWS S3 SDK's `copyObject` method to copy between keys
126+
- Bucket name should come from environment variables
127+
- Ensure proper error handling for S3 operations
128+
129+
### Authentication
130+
131+
- These endpoints should require authentication (API key or session)
132+
- Validate that the user has access to the organization/task/automation
133+
134+
### Redis Chat History
135+
136+
- **Important**: Do NOT clear or modify chat history when restoring versions
137+
- Chat history key format: `automation:{automationId}:chat`
138+
- Chat history persists regardless of which version is in the draft
139+
140+
### Example S3 Keys
141+
142+
For automation `aut_68e6a70803cf925eac17896a` in task `tsk_68e6a5c1e0b762e741c2e020`:
143+
144+
- **Draft**: `org_68e6a5c1d30338b3981c2104/tsk_68e6a5c1e0b762e741c2e020/aut_68e6a70803cf925eac17896a.draft.js`
145+
- **Version 1**: `org_68e6a5c1d30338b3981c2104/tsk_68e6a5c1e0b762e741c2e020/aut_68e6a70803cf925eac17896a.v1.js`
146+
- **Version 2**: `org_68e6a5c1d30338b3981c2104/tsk_68e6a5c1e0b762e741c2e020/aut_68e6a70803cf925eac17896a.v2.js`
147+
148+
### Integration Flow
149+
150+
#### Publishing a Version
151+
152+
1. User clicks "Publish" in Next.js UI with optional changelog
153+
2. Next.js calls `POST /api/tasks-automations/publish` (no version number in request)
154+
3. Enterprise API:
155+
- Queries database to get next version number
156+
- Copies draft → versioned S3 key
157+
- Returns version number and scriptKey
158+
4. Next.js saves version record to database with returned version number, scriptKey, and changelog
159+
160+
#### Restoring a Version
161+
162+
1. User clicks "Restore Version X" in Next.js UI
163+
2. Shows confirmation dialog warning current draft will be lost
164+
3. Next.js calls `POST /api/tasks-automations/restore-version`
165+
4. Enterprise API copies version script → draft S3 key
166+
5. Enterprise API returns success
167+
6. Next.js shows success message
168+
7. User can continue editing in builder with restored script
169+
170+
### Error Handling
171+
172+
- Return proper HTTP status codes (404 for not found, 400 for bad request, 500 for S3 errors)
173+
- Include descriptive error messages in response body
174+
- Log errors for debugging
175+
176+
### Testing Checklist
177+
178+
- [ ] Can publish a draft script as version 1
179+
- [ ] Can publish multiple versions (1, 2, 3...)
180+
- [ ] Cannot publish if no draft exists
181+
- [ ] Can restore version 1 to draft
182+
- [ ] Restoring doesn't affect chat history
183+
- [ ] S3 keys follow correct naming convention
184+
- [ ] Proper error messages when scripts don't exist

apps/api/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
"@trycompai/db": "^1.3.7",
1515
"archiver": "^7.0.1",
1616
"axios": "^1.12.2",
17+
"better-auth": "^1.3.27",
1718
"class-transformer": "^0.5.1",
1819
"class-validator": "^0.14.2",
1920
"jose": "^6.0.12",

apps/api/src/app.module.ts

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { TasksModule } from './tasks/tasks.module';
1717
import { VendorsModule } from './vendors/vendors.module';
1818
import { ContextModule } from './context/context.module';
1919

20-
2120
@Module({
2221
imports: [
2322
ConfigModule.forRoot({
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
import {
2+
Body,
3+
Controller,
4+
Param,
5+
Patch,
6+
Post,
7+
UseGuards,
8+
} from '@nestjs/common';
9+
import {
10+
ApiHeader,
11+
ApiOperation,
12+
ApiResponse,
13+
ApiSecurity,
14+
ApiTags,
15+
} from '@nestjs/swagger';
16+
import { HybridAuthGuard } from '../auth/hybrid-auth.guard';
17+
import { AutomationService } from './automation.service';
18+
import { CreateAutomationDto } from './dto/create-automation.dto';
19+
import { UpdateAutomationDto } from './dto/update-automation.dto';
20+
import { AUTOMATION_OPERATIONS } from './schemas/automation-operations';
21+
import { CREATE_AUTOMATION_RESPONSES } from './schemas/create-automation.responses';
22+
import { UPDATE_AUTOMATION_RESPONSES } from './schemas/update-automation.responses';
23+
24+
@ApiTags('Automations')
25+
@Controller({ path: 'automations', version: '1' })
26+
@UseGuards(HybridAuthGuard)
27+
@ApiSecurity('apikey')
28+
@ApiHeader({
29+
name: 'X-Organization-Id',
30+
description:
31+
'Organization ID (required for session auth, optional for API key auth)',
32+
required: false,
33+
})
34+
export class AutomationController {
35+
constructor(private readonly automationService: AutomationService) {}
36+
37+
@Post()
38+
@ApiOperation(AUTOMATION_OPERATIONS.createAutomation)
39+
@ApiResponse(CREATE_AUTOMATION_RESPONSES[201])
40+
@ApiResponse(CREATE_AUTOMATION_RESPONSES[400])
41+
@ApiResponse(CREATE_AUTOMATION_RESPONSES[401])
42+
@ApiResponse(CREATE_AUTOMATION_RESPONSES[404])
43+
async createAutomation(@Body() createAutomationDto: CreateAutomationDto) {
44+
return this.automationService.create(createAutomationDto);
45+
}
46+
47+
@Patch(':automationId')
48+
@ApiOperation(AUTOMATION_OPERATIONS.updateAutomation)
49+
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[200])
50+
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[400])
51+
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[401])
52+
@ApiResponse(UPDATE_AUTOMATION_RESPONSES[404])
53+
async updateAutomation(
54+
@Param('automationId') automationId: string,
55+
@Body() updateAutomationDto: UpdateAutomationDto,
56+
) {
57+
return this.automationService.update(automationId, updateAutomationDto);
58+
}
59+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
import { Module } from '@nestjs/common';
2+
import { AuthModule } from '../auth/auth.module';
3+
import { AutomationController } from './automation.controller';
4+
import { AutomationService } from './automation.service';
5+
6+
@Module({
7+
imports: [AuthModule],
8+
controllers: [AutomationController],
9+
providers: [AutomationService],
10+
})
11+
export class AutomationModule {}

0 commit comments

Comments
 (0)