Skip to content

Commit 000e4f3

Browse files
authored
Merge pull request #1280 from mnfst/chore/review-security-module
Remove unused security module and endpoint
2 parents eb07868 + 51218ff commit 000e4f3

23 files changed

+79
-775
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"manifest": patch
3+
---
4+
5+
Remove unused security module, endpoint, entity, and seeder

packages/backend/src/app.module.ts

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,6 @@ import { AuthModule } from './auth/auth.module';
1717
import { HealthModule } from './health/health.module';
1818
import { TelemetryModule } from './telemetry/telemetry.module';
1919
import { AnalyticsModule } from './analytics/analytics.module';
20-
import { SecurityModule } from './security/security.module';
2120
import { OtlpModule } from './otlp/otlp.module';
2221
import { ModelPricesModule } from './model-prices/model-prices.module';
2322
import { NotificationsModule } from './notifications/notifications.module';
@@ -69,7 +68,6 @@ const serveStaticImports = frontendPath
6968
HealthModule,
7069
TelemetryModule,
7170
AnalyticsModule,
72-
SecurityModule,
7371
OtlpModule,
7472
ModelPricesModule,
7573
NotificationsModule,

packages/backend/src/database/database-seeder.service.spec.ts

Lines changed: 0 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ describe('DatabaseSeederService', () => {
2727
let mockAgentRepo: ReturnType<typeof makeMockRepo>;
2828
let mockAgentKeyRepo: ReturnType<typeof makeMockRepo>;
2929
let mockApiKeyRepo: ReturnType<typeof makeMockRepo>;
30-
let mockSecurityRepo: ReturnType<typeof makeMockRepo>;
3130
let mockMessageRepo: ReturnType<typeof makeMockRepo>;
3231
const originalSeedData = process.env['SEED_DATA'];
3332
const originalManifestMode = process.env['MANIFEST_MODE'];
@@ -41,7 +40,6 @@ describe('DatabaseSeederService', () => {
4140
mockAgentRepo = makeMockRepo();
4241
mockAgentKeyRepo = makeMockRepo();
4342
mockApiKeyRepo = makeMockRepo();
44-
mockSecurityRepo = makeMockRepo();
4543
mockMessageRepo = makeMockRepo();
4644

4745
service = new DatabaseSeederService(
@@ -51,7 +49,6 @@ describe('DatabaseSeederService', () => {
5149
mockAgentRepo as never,
5250
mockAgentKeyRepo as never,
5351
mockApiKeyRepo as never,
54-
mockSecurityRepo as never,
5552
mockMessageRepo as never,
5653
);
5754

@@ -345,48 +342,6 @@ describe('DatabaseSeederService', () => {
345342
});
346343
});
347344

348-
describe('seedSecurityEvents', () => {
349-
it('should skip seeding when events already exist', async () => {
350-
mockSecurityRepo.count.mockResolvedValue(5);
351-
352-
await service.onModuleInit();
353-
354-
expect(mockSecurityRepo.insert).not.toHaveBeenCalled();
355-
});
356-
357-
it('should insert 12 security events when table is empty', async () => {
358-
mockSecurityRepo.count.mockResolvedValue(0);
359-
360-
await service.onModuleInit();
361-
362-
expect(mockSecurityRepo.insert).toHaveBeenCalledTimes(12);
363-
});
364-
365-
it('should include events of all severity levels', async () => {
366-
mockSecurityRepo.count.mockResolvedValue(0);
367-
368-
await service.onModuleInit();
369-
370-
const insertedSeverities = mockSecurityRepo.insert.mock.calls.map(
371-
(call: unknown[]) => (call[0] as { severity: string }).severity,
372-
);
373-
expect(insertedSeverities).toContain('critical');
374-
expect(insertedSeverities).toContain('warning');
375-
expect(insertedSeverities).toContain('info');
376-
});
377-
378-
it('should attach admin user_id to security events', async () => {
379-
mockSecurityRepo.count.mockResolvedValue(0);
380-
mockDataSource.query.mockResolvedValue([{ id: 'admin-user-id' }]);
381-
382-
await service.onModuleInit();
383-
384-
for (const call of mockSecurityRepo.insert.mock.calls) {
385-
expect((call[0] as { user_id: string }).user_id).toBe('admin-user-id');
386-
}
387-
});
388-
});
389-
390345
describe('getAdminUserId edge cases', () => {
391346
it('should handle checkBetterAuthUser failure gracefully', async () => {
392347
// checkBetterAuthUser catches DB errors and returns false,

packages/backend/src/database/database-seeder.service.ts

Lines changed: 0 additions & 109 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import { Tenant } from '../entities/tenant.entity';
77
import { Agent } from '../entities/agent.entity';
88
import { AgentApiKey } from '../entities/agent-api-key.entity';
99
import { ApiKey } from '../entities/api-key.entity';
10-
import { SecurityEvent } from '../entities/security-event.entity';
1110
import { AgentMessage } from '../entities/agent-message.entity';
1211
import { hashKey, keyPrefix } from '../common/utils/hash.util';
1312
import { seedAgentMessages } from './seed-messages';
@@ -28,7 +27,6 @@ export class DatabaseSeederService implements OnModuleInit {
2827
@InjectRepository(Agent) private readonly agentRepo: Repository<Agent>,
2928
@InjectRepository(AgentApiKey) private readonly agentKeyRepo: Repository<AgentApiKey>,
3029
@InjectRepository(ApiKey) private readonly apiKeyRepo: Repository<ApiKey>,
31-
@InjectRepository(SecurityEvent) private readonly securityRepo: Repository<SecurityEvent>,
3230
@InjectRepository(AgentMessage) private readonly messageRepo: Repository<AgentMessage>,
3331
) {}
3432

@@ -45,7 +43,6 @@ export class DatabaseSeederService implements OnModuleInit {
4543
await this.seedAdminUser();
4644
await this.seedApiKey();
4745
await this.seedTenantAndAgent();
48-
await this.seedSecurityEvents();
4946
await this.seedAgentMessages();
5047
this.logger.log('Seeded demo data (dev/test only, SEED_DATA=true)');
5148
}
@@ -151,112 +148,6 @@ export class DatabaseSeederService implements OnModuleInit {
151148
this.logger.log(`Seeded tenant/agent with OTLP key: ${SEED_OTLP_KEY.substring(0, 8)}***`);
152149
}
153150

154-
private async seedSecurityEvents() {
155-
const count = await this.securityRepo.count();
156-
if (count > 0) return;
157-
158-
const userId = await this.getAdminUserId();
159-
160-
const now = Date.now();
161-
const events = [
162-
[
163-
'sec-001',
164-
'sess-001',
165-
-2,
166-
'critical',
167-
'unauthorized_access',
168-
'Unauthorized API key attempt from unknown IP',
169-
],
170-
[
171-
'sec-002',
172-
'sess-002',
173-
-3,
174-
'warning',
175-
'rate_limit',
176-
'Rate limit exceeded for agent — 150 req/min threshold',
177-
],
178-
[
179-
'sec-003',
180-
'sess-003',
181-
-5,
182-
'info',
183-
'config_change',
184-
'Alert rule "High cost threshold" updated by admin',
185-
],
186-
[
187-
'sec-004',
188-
'sess-004',
189-
-6,
190-
'warning',
191-
'sandbox_escape',
192-
'Sandbox escape attempt detected in agent session',
193-
],
194-
[
195-
'sec-005',
196-
'sess-005',
197-
-8,
198-
'critical',
199-
'data_exfiltration',
200-
'Suspicious outbound data transfer detected',
201-
],
202-
['sec-006', 'sess-006', -10, 'info', 'login', 'New login from device'],
203-
[
204-
'sec-007',
205-
'sess-007',
206-
-12,
207-
'warning',
208-
'permission_escalation',
209-
'Agent requested elevated permissions outside scope',
210-
],
211-
[
212-
'sec-008',
213-
'sess-008',
214-
-14,
215-
'info',
216-
'api_key_rotation',
217-
'API key rotated for production environment',
218-
],
219-
[
220-
'sec-009',
221-
'sess-009',
222-
-18,
223-
'critical',
224-
'injection_attempt',
225-
'Prompt injection attempt detected in agent input',
226-
],
227-
[
228-
'sec-010',
229-
'sess-010',
230-
-22,
231-
'warning',
232-
'token_anomaly',
233-
'Unusual token consumption spike: 340% above baseline',
234-
],
235-
[
236-
'sec-011',
237-
'sess-011',
238-
-24,
239-
'info',
240-
'audit',
241-
'Weekly security audit completed — 3 findings resolved',
242-
],
243-
['sec-012', 'sess-012', -48, 'warning', 'certificate', 'TLS certificate expiring in 14 days'],
244-
] as const;
245-
246-
for (const [id, sessionKey, hoursAgo, severity, category, description] of events) {
247-
const ts = new Date(now + hoursAgo * 3600000).toISOString();
248-
await this.securityRepo.insert({
249-
id,
250-
session_key: sessionKey,
251-
timestamp: ts,
252-
severity,
253-
category,
254-
description,
255-
user_id: userId,
256-
});
257-
}
258-
}
259-
260151
private async seedAgentMessages() {
261152
const userId = await this.getAdminUserId();
262153
if (!userId) return;

packages/backend/src/database/database.module.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { ConfigService } from '@nestjs/config';
55
import { AgentMessage } from '../entities/agent-message.entity';
66
import { LlmCall } from '../entities/llm-call.entity';
77
import { ToolExecution } from '../entities/tool-execution.entity';
8-
import { SecurityEvent } from '../entities/security-event.entity';
98
import { TokenUsageSnapshot } from '../entities/token-usage-snapshot.entity';
109
import { CostSnapshot } from '../entities/cost-snapshot.entity';
1110
import { AgentLog } from '../entities/agent-log.entity';
@@ -57,12 +56,12 @@ import { AddEmailProviderKeyPrefix1773300000000 } from './migrations/17733000000
5756
import { AddProviderModelCache1773400000000 } from './migrations/1773400000000-AddProviderModelCache';
5857
import { DropModelPricingTables1773500000000 } from './migrations/1773500000000-DropModelPricingTables';
5958
import { AddOverrideProvider1773600000000 } from './migrations/1773600000000-AddOverrideProvider';
59+
import { DropSecurityEventTable1773700000000 } from './migrations/1773700000000-DropSecurityEventTable';
6060

6161
const entities = [
6262
AgentMessage,
6363
LlmCall,
6464
ToolExecution,
65-
SecurityEvent,
6665
TokenUsageSnapshot,
6766
CostSnapshot,
6867
AgentLog,
@@ -114,6 +113,7 @@ const migrations = [
114113
AddProviderModelCache1773400000000,
115114
DropModelPricingTables1773500000000,
116115
AddOverrideProvider1773600000000,
116+
DropSecurityEventTable1773700000000,
117117
];
118118

119119
const isLocalMode = process.env['MANIFEST_MODE'] === 'local';
@@ -163,7 +163,6 @@ function buildModeServices() {
163163
AgentApiKey,
164164
AgentMessage,
165165
ApiKey,
166-
SecurityEvent,
167166
UserProvider,
168167
TierAssignment,
169168
CustomProvider,
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
import { QueryRunner } from 'typeorm';
2+
import { DropSecurityEventTable1773700000000 } from './1773700000000-DropSecurityEventTable';
3+
4+
describe('DropSecurityEventTable1773700000000', () => {
5+
let migration: DropSecurityEventTable1773700000000;
6+
let queryRunner: jest.Mocked<Pick<QueryRunner, 'query'>>;
7+
8+
beforeEach(() => {
9+
migration = new DropSecurityEventTable1773700000000();
10+
queryRunner = { query: jest.fn().mockResolvedValue(undefined) };
11+
});
12+
13+
describe('up', () => {
14+
it('should drop the security_event table', async () => {
15+
await migration.up(queryRunner as unknown as QueryRunner);
16+
17+
expect(queryRunner.query).toHaveBeenCalledTimes(1);
18+
expect(queryRunner.query).toHaveBeenCalledWith(
19+
expect.stringContaining('DROP TABLE IF EXISTS "security_event"'),
20+
);
21+
});
22+
});
23+
24+
describe('down', () => {
25+
it('should recreate the security_event table', async () => {
26+
await migration.down(queryRunner as unknown as QueryRunner);
27+
28+
expect(queryRunner.query).toHaveBeenCalledTimes(2);
29+
expect(queryRunner.query).toHaveBeenCalledWith(
30+
expect.stringContaining('CREATE TABLE "security_event"'),
31+
);
32+
});
33+
34+
it('should recreate the user_id/timestamp index', async () => {
35+
await migration.down(queryRunner as unknown as QueryRunner);
36+
37+
expect(queryRunner.query).toHaveBeenCalledWith(expect.stringContaining('CREATE INDEX'));
38+
});
39+
});
40+
});
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import { MigrationInterface, QueryRunner } from 'typeorm';
2+
3+
export class DropSecurityEventTable1773700000000 implements MigrationInterface {
4+
public async up(queryRunner: QueryRunner): Promise<void> {
5+
await queryRunner.query(`DROP TABLE IF EXISTS "security_event"`);
6+
}
7+
8+
public async down(queryRunner: QueryRunner): Promise<void> {
9+
await queryRunner.query(`
10+
CREATE TABLE "security_event" (
11+
"id" varchar PRIMARY KEY NOT NULL,
12+
"session_key" varchar,
13+
"timestamp" timestamp NOT NULL,
14+
"severity" varchar NOT NULL,
15+
"category" varchar NOT NULL,
16+
"description" varchar NOT NULL,
17+
"user_id" varchar
18+
)
19+
`);
20+
await queryRunner.query(
21+
`CREATE INDEX "IDX_security_event_user_id_timestamp" ON "security_event" ("user_id", "timestamp")`,
22+
);
23+
}
24+
}

packages/backend/src/entities/security-event.entity.ts

Lines changed: 0 additions & 27 deletions
This file was deleted.

0 commit comments

Comments
 (0)