fix(vv): resolve all 6 V&V issues — field trial unblocked
All findings from the inaugural LeadValidator audit resolved and confirmed. Release gate: PASS. VV_ISSUE_002 (BLOCKER): 15 OpenAPI specs verified present covering all 20 route groups (46 endpoints documented in docs/openapi/) VV_ISSUE_003 (MAJOR): Remove any types from src/db/pool.ts — replaced pool.query shim with unknown[] + Object.defineProperty, zero any types, eslint-disable suppressions removed VV_ISSUE_004 (MAJOR): Remove raw Pool from ScaffoldController and HealthDetailedController — injected AgentRepository/CredentialRepository and DbProbe interface respectively; added CredentialRepository.findActiveClientId() VV_ISSUE_005 (MAJOR): Add unit tests for 5 untested services — ComplianceStatusStore, EventPublisher, MarketplaceService, OIDCTrustPolicyService, UsageService VV_ISSUE_006 (MAJOR): Add integration tests for 7 missing route groups — analytics, billing, tiers, webhooks, marketplace, oidc-trust-policies, oidc-token-exchange VV_ISSUE_001 (MINOR): Create missing design.md and tasks.md in 4 OpenSpec archives — all archives now complete Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -4,7 +4,8 @@
|
||||
*/
|
||||
|
||||
import { Request, Response, NextFunction } from 'express';
|
||||
import { Pool } from 'pg';
|
||||
import { AgentRepository } from '../repositories/AgentRepository.js';
|
||||
import { CredentialRepository } from '../repositories/CredentialRepository.js';
|
||||
import { AuditService } from '../services/AuditService.js';
|
||||
import { ScaffoldService, SCAFFOLD_LANGUAGES } from '../services/ScaffoldService.js';
|
||||
import { ScaffoldLanguage } from '../types/scaffold.js';
|
||||
@@ -17,12 +18,14 @@ import { AgentNotFoundError, AuthorizationError, ValidationError } from '../util
|
||||
export class ScaffoldController {
|
||||
/**
|
||||
* @param scaffoldService - The scaffold generation service.
|
||||
* @param pool - PostgreSQL connection pool for agent credential lookup.
|
||||
* @param agentRepo - Agent repository for agent lookup.
|
||||
* @param credentialRepo - Credential repository for active credential lookup.
|
||||
* @param auditService - Audit log service.
|
||||
*/
|
||||
constructor(
|
||||
private readonly scaffoldService: ScaffoldService,
|
||||
private readonly pool: Pool,
|
||||
private readonly agentRepo: AgentRepository,
|
||||
private readonly credentialRepo: CredentialRepository,
|
||||
private readonly auditService: AuditService,
|
||||
) {}
|
||||
|
||||
@@ -53,38 +56,25 @@ export class ScaffoldController {
|
||||
const tenantId = req.user.organization_id ?? 'org_system';
|
||||
|
||||
// Fetch agent and verify it belongs to the authenticated tenant
|
||||
const agentResult = await this.pool.query<{
|
||||
agent_id: string;
|
||||
email: string;
|
||||
organization_id: string;
|
||||
}>(
|
||||
`SELECT agent_id, email, organization_id FROM agents WHERE agent_id = $1`,
|
||||
[agentId],
|
||||
);
|
||||
const agent = await this.agentRepo.findById(agentId);
|
||||
|
||||
if (agentResult.rows.length === 0) {
|
||||
if (agent === null) {
|
||||
throw new AgentNotFoundError(agentId);
|
||||
}
|
||||
|
||||
const agentRow = agentResult.rows[0];
|
||||
if (agentRow.organization_id !== tenantId) {
|
||||
if (agent.organizationId !== tenantId) {
|
||||
throw new AuthorizationError('You do not own this agent.');
|
||||
}
|
||||
|
||||
// Fetch the agent's active credential client_id
|
||||
const credResult = await this.pool.query<{ client_id: string }>(
|
||||
`SELECT client_id FROM credentials WHERE agent_id = $1 AND status = 'active' ORDER BY created_at DESC LIMIT 1`,
|
||||
[agentId],
|
||||
);
|
||||
|
||||
const clientId =
|
||||
credResult.rows.length > 0 ? credResult.rows[0].client_id : agentRow.agent_id;
|
||||
const activeClientId = await this.credentialRepo.findActiveClientId(agentId);
|
||||
const clientId = activeClientId ?? agentId;
|
||||
|
||||
const apiUrl = process.env['API_URL'] ?? process.env['NEXT_PUBLIC_API_URL'] ?? 'https://api.sentryagent.ai';
|
||||
|
||||
const { stream, filename } = await this.scaffoldService.generateScaffold({
|
||||
agentId,
|
||||
agentName: agentRow.email.split('@')[0] ?? agentId,
|
||||
agentName: agent.email.split('@')[0] ?? agentId,
|
||||
clientId,
|
||||
language,
|
||||
apiUrl,
|
||||
|
||||
Reference in New Issue
Block a user