## 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>
196 lines
5.1 KiB
TypeScript
196 lines
5.1 KiB
TypeScript
/**
|
|
* Regions Repository
|
|
* Handles CRUD operations for provider regions
|
|
*/
|
|
|
|
import { BaseRepository } from './base';
|
|
import { Region, RegionInput, RepositoryError, ErrorCodes } from '../types';
|
|
|
|
export class RegionsRepository extends BaseRepository<Region> {
|
|
protected tableName = 'regions';
|
|
protected allowedColumns = [
|
|
'provider_id',
|
|
'region_code',
|
|
'region_name',
|
|
'country_code',
|
|
'latitude',
|
|
'longitude',
|
|
'available',
|
|
];
|
|
|
|
/**
|
|
* Find all regions for a specific provider
|
|
*/
|
|
async findByProvider(providerId: number): Promise<Region[]> {
|
|
try {
|
|
const result = await this.db
|
|
.prepare('SELECT * FROM regions WHERE provider_id = ?')
|
|
.bind(providerId)
|
|
.all<Region>();
|
|
|
|
return result.results;
|
|
} catch (error) {
|
|
this.logger.error('findByProvider failed', {
|
|
providerId,
|
|
error: error instanceof Error ? error.message : 'Unknown error'
|
|
});
|
|
throw new RepositoryError(
|
|
`Failed to find regions for provider: ${providerId}`,
|
|
ErrorCodes.DATABASE_ERROR,
|
|
error
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Find a region by provider ID and region code
|
|
*/
|
|
async findByCode(providerId: number, code: string): Promise<Region | null> {
|
|
try {
|
|
const result = await this.db
|
|
.prepare('SELECT * FROM regions WHERE provider_id = ? AND region_code = ?')
|
|
.bind(providerId, code)
|
|
.first<Region>();
|
|
|
|
return result || null;
|
|
} catch (error) {
|
|
this.logger.error('findByCode failed', {
|
|
providerId,
|
|
code,
|
|
error: error instanceof Error ? error.message : 'Unknown error'
|
|
});
|
|
throw new RepositoryError(
|
|
`Failed to find region by code: ${code}`,
|
|
ErrorCodes.DATABASE_ERROR,
|
|
error
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Bulk upsert regions for a provider
|
|
* Uses batch operations for efficiency
|
|
*/
|
|
async upsertMany(providerId: number, regions: RegionInput[]): Promise<number> {
|
|
if (regions.length === 0) {
|
|
return 0;
|
|
}
|
|
|
|
try {
|
|
// Build upsert statements for each region
|
|
const statements = regions.map((region) => {
|
|
return this.db.prepare(
|
|
`INSERT INTO regions (
|
|
provider_id, region_code, region_name, country_code,
|
|
latitude, longitude, available
|
|
) VALUES (?, ?, ?, ?, ?, ?, ?)
|
|
ON CONFLICT(provider_id, region_code)
|
|
DO UPDATE SET
|
|
region_name = excluded.region_name,
|
|
country_code = excluded.country_code,
|
|
latitude = excluded.latitude,
|
|
longitude = excluded.longitude,
|
|
available = excluded.available`
|
|
).bind(
|
|
providerId,
|
|
region.region_code,
|
|
region.region_name,
|
|
region.country_code || null,
|
|
region.latitude || null,
|
|
region.longitude || null,
|
|
region.available
|
|
);
|
|
});
|
|
|
|
// Count successful operations
|
|
const successCount = await this.executeBatchCount(statements);
|
|
|
|
this.logger.info('Upserted regions', {
|
|
providerId,
|
|
count: successCount
|
|
});
|
|
return successCount;
|
|
} catch (error) {
|
|
this.logger.error('upsertMany failed', {
|
|
providerId,
|
|
count: regions.length,
|
|
error: error instanceof Error ? error.message : 'Unknown error'
|
|
});
|
|
throw new RepositoryError(
|
|
`Failed to upsert regions for provider: ${providerId}`,
|
|
ErrorCodes.TRANSACTION_FAILED,
|
|
error
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Get available regions only
|
|
*/
|
|
async findAvailable(providerId?: number): Promise<Region[]> {
|
|
try {
|
|
let query = 'SELECT * FROM regions WHERE available = 1';
|
|
const params: (string | number | boolean | null)[] = [];
|
|
|
|
if (providerId !== undefined) {
|
|
query += ' AND provider_id = ?';
|
|
params.push(providerId);
|
|
}
|
|
|
|
const result = await this.db
|
|
.prepare(query)
|
|
.bind(...params)
|
|
.all<Region>();
|
|
|
|
return result.results;
|
|
} catch (error) {
|
|
this.logger.error('findAvailable failed', {
|
|
providerId,
|
|
error: error instanceof Error ? error.message : 'Unknown error'
|
|
});
|
|
throw new RepositoryError(
|
|
'Failed to find available regions',
|
|
ErrorCodes.DATABASE_ERROR,
|
|
error
|
|
);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Update region availability status
|
|
*/
|
|
async updateAvailability(id: number, available: boolean): Promise<Region> {
|
|
try {
|
|
const result = await this.db
|
|
.prepare('UPDATE regions SET available = ? WHERE id = ? RETURNING *')
|
|
.bind(available ? 1 : 0, id)
|
|
.first<Region>();
|
|
|
|
if (!result) {
|
|
throw new RepositoryError(
|
|
`Region not found: ${id}`,
|
|
ErrorCodes.NOT_FOUND
|
|
);
|
|
}
|
|
|
|
return result;
|
|
} catch (error) {
|
|
this.logger.error('updateAvailability failed', {
|
|
id,
|
|
available,
|
|
error: error instanceof Error ? error.message : 'Unknown error'
|
|
});
|
|
|
|
if (error instanceof RepositoryError) {
|
|
throw error;
|
|
}
|
|
|
|
throw new RepositoryError(
|
|
`Failed to update region availability: ${id}`,
|
|
ErrorCodes.DATABASE_ERROR,
|
|
error
|
|
);
|
|
}
|
|
}
|
|
}
|