Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
import { BatchUpdateRequirementsDto } from './batch-update-requirements.dto';

/**
* Mirrors the global ValidationPipe config from main.ts:
* whitelist: true, transform: true, enableImplicitConversion: true
*/
function toDto(plain: Record<string, unknown>): BatchUpdateRequirementsDto {
return plainToInstance(BatchUpdateRequirementsDto, plain, {
enableImplicitConversion: true,
});
}

describe('BatchUpdateRequirementsDto', () => {
it('accepts a valid batch payload', async () => {
const dto = toDto({
updates: [{ id: 'frq_1', description: 'Updated description' }],
});
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors).toHaveLength(0);
});

// ── nested description length (FRAME-2: limit raised 5,000 → 10,000) ─
it('accepts a nested description at the 10,000-char limit', async () => {
const dto = toDto({
updates: [{ id: 'frq_1', description: 'x'.repeat(10_000) }],
});
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors).toHaveLength(0);
});

it('rejects a nested description longer than 10,000 chars', async () => {
const dto = toDto({
updates: [{ id: 'frq_1', description: 'x'.repeat(10_001) }],
});
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors.length).toBeGreaterThan(0);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ class BatchUpdateRequirementItem {
@ApiProperty()
@IsString()
@IsOptional()
@MaxLength(5000)
@MaxLength(10000)
description?: string;

@ApiProperty()
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
import { CreateRequirementDto } from './create-requirement.dto';

/**
* Mirrors the global ValidationPipe config from main.ts:
* whitelist: true, transform: true, enableImplicitConversion: true
*/
function toDto(plain: Record<string, unknown>): CreateRequirementDto {
return plainToInstance(CreateRequirementDto, plain, {
enableImplicitConversion: true,
});
}

const VALID_BASE = {
frameworkId: 'frk_abc123',
name: 'AC-1',
description: 'Access control policy and procedures',
};

describe('CreateRequirementDto', () => {
it('accepts a valid payload', async () => {
const dto = toDto(VALID_BASE);
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors).toHaveLength(0);
});

// ── description length (FRAME-2: limit raised 5,000 → 10,000) ──────
it('accepts a description at the 10,000-char limit', async () => {
const dto = toDto({ ...VALID_BASE, description: 'x'.repeat(10_000) });
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors).toHaveLength(0);
});

it('rejects a description longer than 10,000 chars', async () => {
const dto = toDto({ ...VALID_BASE, description: 'x'.repeat(10_001) });
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors.length).toBeGreaterThan(0);
expect(errors[0].property).toBe('description');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ export class CreateRequirementDto {

@ApiProperty({ example: 'Control environment requirements' })
@IsString()
@MaxLength(5000)
@MaxLength(10000)
description: string;

@ApiPropertyOptional({ example: 'Access Control' })
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import { plainToInstance } from 'class-transformer';
import { validate } from 'class-validator';
import { UpdateRequirementDto } from './update-requirement.dto';

/**
* Mirrors the global ValidationPipe config from main.ts:
* whitelist: true, transform: true, enableImplicitConversion: true
*/
function toDto(plain: Record<string, unknown>): UpdateRequirementDto {
return plainToInstance(UpdateRequirementDto, plain, {
enableImplicitConversion: true,
});
}

describe('UpdateRequirementDto', () => {
it('accepts a partial update (single field)', async () => {
const dto = toDto({ name: 'AC-2' });
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors).toHaveLength(0);
});

// ── description length (FRAME-2: limit raised 5,000 → 10,000) ──────
it('accepts a description at the 10,000-char limit', async () => {
const dto = toDto({ description: 'x'.repeat(10_000) });
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors).toHaveLength(0);
});

it('rejects a description longer than 10,000 chars', async () => {
const dto = toDto({ description: 'x'.repeat(10_001) });
const errors = await validate(dto, {
whitelist: true,
forbidNonWhitelisted: true,
});
expect(errors.length).toBeGreaterThan(0);
expect(errors[0].property).toBe('description');
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class UpdateRequirementDto {
@ApiPropertyOptional()
@IsString()
@IsOptional()
@MaxLength(5000)
@MaxLength(10000)
description?: string;

@ApiPropertyOptional()
Expand Down
8 changes: 6 additions & 2 deletions packages/docs/mcp-server.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -45,8 +45,12 @@ The `npx -y @trycompai/mcp-server` command you'll see throughout is what handles

**Easiest path — drag-and-drop install:**

1. Download the latest [`mcp-server.mcpb`](https://github.com/trycompai/comp/releases) bundle from our GitHub Releases page.
2. Drag the `.mcpb` file directly onto the Claude Desktop window.
<Card title="Download for Claude Desktop" icon="download" href="https://api.trycomp.ai/mcp/download/claude-desktop">
Always serves the latest Comp AI MCP bundle (`.mcpb`) — no version hunting.
</Card>

1. Click **Download for Claude Desktop** above to get the latest `mcp-server.mcpb` bundle.
2. Drag the downloaded `.mcpb` file directly onto the Claude Desktop window.
3. Claude Desktop shows an install prompt — confirm, then paste your Comp AI API key in the extension settings.
4. Restart any open chats. Comp AI tools are now available.

Expand Down
Loading