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:
54
src/types.ts
54
src/types.ts
@@ -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 */
|
||||
|
||||
Reference in New Issue
Block a user