Files
sentryagent-idp/openspec/vv_audit/VV_ISSUE_003.md
SentryAgent.ai Developer 7441c9f298 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>
2026-04-07 04:52:47 +00:00

3.4 KiB
Raw Permalink Blame History

VV_ISSUE_003 — any type usage in src/db/pool.ts

Status: RESOLVED Severity: MAJOR Category: TYPE_VIOLATION Logged by: LeadValidator Date: 2026-04-07 Audit phase: Phase C — TypeScript Standards Audit

Finding

The PRD (Sections 6.4 and 4.5) states: "No any types — ever." and "TypeScript strict mode: zero any types." The tsconfig.json correctly enables noImplicitAny: true and all strict flags.

Despite this, src/db/pool.ts contains explicit any type casts on two lines (lines 89 and 91), with ESLint suppression comments (eslint-disable-next-line @typescript-eslint/no-explicit-any) added to bypass the linting rule. While the developer included a comment explaining the technical reason (wrapping the pg query method in a shim that is difficult to type precisely), the PRD standard is absolute: zero any types, with no exceptions granted.

The intent of the standard is to eliminate unsafe escape hatches that weaken TypeScript's type safety guarantees. Using any in the database pool layer — a critical path component — is particularly concerning since this wraps every database query in the application.

Evidence

File: src/db/pool.ts, lines 8891:

// eslint-disable-next-line @typescript-eslint/no-explicit-any
const originalQuery = pool.query.bind(pool) as (...args: any[]) => Promise<any>;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
(pool as any).query = async (...args: any[]): Promise<any> => {

There are 5 any occurrences on these two lines:

  • (...args: any[]) => Promise<any> — line 89
  • (pool as any) — line 91
  • (...args: any[]): Promise<any> — line 91

The surrounding comment (lines 8487) acknowledges the issue and explains the rationale, but does not resolve it per PRD standards.

Required Action

Replace the any types in src/db/pool.ts with properly typed alternatives. Options:

  1. Use the pg library's exported QueryConfig, QueryResultRow, and overload signatures to type the query wrapper correctly without resorting to any.
  2. Use generic types: <T extends QueryResultRow>(...args: Parameters<Pool['query']>) => Promise<QueryResult<T>>
  3. If the shim cannot be typed without any due to pg's type definitions, document the specific technical constraint and seek CEO approval for a formal exemption. An exemption does NOT mean leaving it as-is — it means a tracked, acknowledged deviation.

Remove the eslint-disable-next-line suppression comments once the any types are resolved.

CTO Response

Agreed. The any types in pool.ts were a sanctioned workaround for pg's overloaded Pool.query signature. The correct solution is to use unknown[] rest parameters and Object.defineProperty to replace the method without widening the pool reference to any. The pool's typed interface is preserved at the type level for all callers; only the internal shim uses unknown as the safe alternative to any.

Resolution

Fixed in: src/db/pool.ts

Replaced the two any-typed lines and two eslint-disable-next-line suppressions with a clean Object.defineProperty shim:

  • originalQuery is typed via pool.query.bind(pool) — no cast needed
  • The replacement function uses unknown[] rest params and Promise<unknown> — zero any types
  • TypeScript compiles clean (npx tsc --noEmit — 0 errors)
  • Pool's typed interface (Pool['query']) unchanged for all callers