refactor: comprehensive code review fixes (security, performance, QA)

## Security Improvements
- Fix timing attack in verifyApiKey with fixed 256-byte buffer
- Fix sortOrder SQL injection with whitelist validation
- Fix rate limiting bypass for non-Cloudflare traffic (fail-closed)
- Remove stack trace exposure in error responses
- Add request_id for audit trail (X-Request-ID header)
- Sanitize origin header to prevent log injection
- Add content-length validation for /sync endpoint (10KB limit)
- Replace Math.random() with crypto.randomUUID() for sync IDs
- Expand sensitive data masking patterns (8 → 18)

## Performance Improvements
- Reduce rate limiter KV reads from 3 to 1 per request (66% reduction)
- Increase sync batch size from 100 to 500 (80% fewer batches)
- Fix health check N+1 query with efficient JOINs
- Fix COUNT(*) Cartesian product with COUNT(DISTINCT)
- Implement shared logger cache pattern across repositories
- Add CacheService singleton pattern in recommend.ts
- Add composite index for recommendation queries
- Implement Anvil pricing query batching (100 per chunk)

## QA Improvements
- Add BATCH_SIZE bounds validation (1-1000)
- Add pagination bounds (page >= 1, MAX_OFFSET = 100000)
- Add min/max range consistency validation
- Add DB reference validation for singleton services
- Add type guards for database result validation
- Add timeout mechanism for external API calls (10-60s)
- Use SUPPORTED_PROVIDERS constant instead of hardcoded list

## Removed
- Remove Vault integration (using Wrangler secrets)
- Remove 6-hour pricing cron (daily sync only)

## Configuration
- Add idx_instance_types_specs_filter composite index
- Add CORS Access-Control-Expose-Headers

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
kappa
2026-01-25 23:50:37 +09:00
parent 9f3d3a245a
commit 3a8dd705e6
47 changed files with 2031 additions and 2459 deletions

View File

@@ -1,38 +1,3 @@
/**
* Vault Credentials Types - supports different providers
*/
export interface VaultCredentials {
provider: string;
api_token?: string; // Linode
api_key?: string; // Vultr
aws_access_key_id?: string; // AWS
aws_secret_access_key?: string; // AWS
}
/**
* Vault API Response Structure - flexible for different providers
*/
export interface VaultSecretResponse {
data: {
data: Record<string, string>; // Flexible key-value pairs
metadata: {
created_time: string;
custom_metadata: null;
deletion_time: string;
destroyed: boolean;
version: number;
};
};
}
/**
* Cache Entry Structure
*/
export interface CacheEntry<T> {
data: T;
expiresAt: number;
}
// ============================================================
// Database Entity Types
// ============================================================
@@ -283,6 +248,8 @@ export interface InstanceQueryParams {
page?: number;
/** Number of results per page */
limit?: number;
/** Force total count calculation (performance optimization: only runs on first page by default) */
include_count?: boolean;
}
/**
@@ -430,20 +397,23 @@ export interface Env {
DB: D1Database;
/** KV namespace for rate limiting */
RATE_LIMIT_KV: KVNamespace;
/** Vault server URL for credentials management */
VAULT_URL: string;
/** Vault authentication token */
VAULT_TOKEN: string;
/** API key for request authentication */
API_KEY: string;
/** Provider API credentials (from Wrangler secrets) */
LINODE_API_TOKEN?: string;
VULTR_API_KEY?: string;
AWS_ACCESS_KEY_ID?: string;
AWS_SECRET_ACCESS_KEY?: string;
/** Batch size for synchronization operations */
SYNC_BATCH_SIZE?: string;
/** Cache TTL in seconds */
CACHE_TTL_SECONDS?: string;
/** Log level (debug, info, warn, error, none) - Controls logging verbosity */
LOG_LEVEL?: string;
/** CORS origin for Access-Control-Allow-Origin header (default: '*') */
/** CORS origin for Access-Control-Allow-Origin header */
CORS_ORIGIN?: string;
/** Environment (development|production) - Controls development-specific features */
ENVIRONMENT?: string;
}
// ============================================================
@@ -458,8 +428,6 @@ export enum SyncStage {
IDLE = 'idle',
/** Initialization stage */
INIT = 'init',
/** Fetching provider credentials from Vault */
FETCH_CREDENTIALS = 'fetch_credentials',
/** Fetching regions from provider API */
FETCH_REGIONS = 'fetch_regions',
/** Fetching instance types from provider API */
@@ -476,6 +444,8 @@ export enum SyncStage {
STORE_DATA = 'store_data',
/** Validation stage */
VALIDATE = 'validate',
/** Synchronizing Anvil pricing from source provider */
SYNC_ANVIL_PRICING = 'sync_anvil_pricing',
/** Sync completed successfully */
COMPLETE = 'complete',
/** Legacy alias for COMPLETE */