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:
@@ -5,19 +5,14 @@
|
||||
|
||||
import { BaseRepository } from './base';
|
||||
import { G8Pricing, G8PricingInput, RepositoryError, ErrorCodes } from '../types';
|
||||
import { createLogger } from '../utils/logger';
|
||||
import { calculateRetailHourly, calculateRetailMonthly } from '../constants';
|
||||
|
||||
export class G8PricingRepository extends BaseRepository<G8Pricing> {
|
||||
protected tableName = 'g8_pricing';
|
||||
protected logger = createLogger('[G8PricingRepository]');
|
||||
protected allowedColumns = [
|
||||
'g8_instance_id',
|
||||
'region_id',
|
||||
'hourly_price',
|
||||
'monthly_price',
|
||||
'hourly_price_retail',
|
||||
'monthly_price_retail',
|
||||
'currency',
|
||||
'available',
|
||||
];
|
||||
@@ -85,42 +80,28 @@ export class G8PricingRepository extends BaseRepository<G8Pricing> {
|
||||
|
||||
try {
|
||||
const statements = pricingData.map((pricing) => {
|
||||
const hourlyRetail = calculateRetailHourly(pricing.hourly_price);
|
||||
const monthlyRetail = calculateRetailMonthly(pricing.monthly_price);
|
||||
|
||||
return this.db.prepare(
|
||||
`INSERT INTO g8_pricing (
|
||||
g8_instance_id, region_id, hourly_price, monthly_price,
|
||||
hourly_price_retail, monthly_price_retail,
|
||||
currency, available
|
||||
) VALUES (?, ?, ?, ?, ?, ?, ?, ?)
|
||||
) VALUES (?, ?, ?, ?, ?, ?)
|
||||
ON CONFLICT(g8_instance_id, region_id)
|
||||
DO UPDATE SET
|
||||
hourly_price = excluded.hourly_price,
|
||||
monthly_price = excluded.monthly_price,
|
||||
hourly_price_retail = excluded.hourly_price_retail,
|
||||
monthly_price_retail = excluded.monthly_price_retail,
|
||||
currency = excluded.currency,
|
||||
available = excluded.available,
|
||||
updated_at = datetime('now')`
|
||||
available = excluded.available`
|
||||
).bind(
|
||||
pricing.g8_instance_id,
|
||||
pricing.region_id,
|
||||
pricing.hourly_price,
|
||||
pricing.monthly_price,
|
||||
hourlyRetail,
|
||||
monthlyRetail,
|
||||
pricing.currency,
|
||||
pricing.available
|
||||
);
|
||||
});
|
||||
|
||||
const results = await this.executeBatch(statements);
|
||||
|
||||
const successCount = results.reduce(
|
||||
(sum, result) => sum + (result.meta.changes ?? 0),
|
||||
0
|
||||
);
|
||||
const successCount = await this.executeBatchCount(statements);
|
||||
|
||||
this.logger.info('Upserted G8 pricing records', { count: successCount });
|
||||
return successCount;
|
||||
|
||||
Reference in New Issue
Block a user