-
Notifications
You must be signed in to change notification settings - Fork 0
Add missing API features and accessibility improvements #16
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -0,0 +1,194 @@ | ||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * Health Check Lambda Handler | ||||||||||||||||||||||||||||||||
| * Provides system health status for monitoring | ||||||||||||||||||||||||||||||||
| * Requirements: Monitoring and observability | ||||||||||||||||||||||||||||||||
| * Following SOLID principles: Single Responsibility | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| import { APIGatewayEvent, APIGatewayResponse } from '../../types/api'; | ||||||||||||||||||||||||||||||||
| import { createDatabaseConnection } from '../../utils/database-connection'; | ||||||||||||||||||||||||||||||||
| import { createLogger } from '../../middleware/logging'; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * Health status type | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| export type HealthStatus = 'healthy' | 'degraded' | 'unhealthy'; | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * Component health info | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| interface ComponentHealth { | ||||||||||||||||||||||||||||||||
| status: HealthStatus; | ||||||||||||||||||||||||||||||||
| message?: string; | ||||||||||||||||||||||||||||||||
| responseTime?: number; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * Health check response | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| interface HealthCheckResponse { | ||||||||||||||||||||||||||||||||
| status: HealthStatus; | ||||||||||||||||||||||||||||||||
| timestamp: string; | ||||||||||||||||||||||||||||||||
| uptime: number; | ||||||||||||||||||||||||||||||||
| version: string; | ||||||||||||||||||||||||||||||||
| components: { | ||||||||||||||||||||||||||||||||
| database: ComponentHealth; | ||||||||||||||||||||||||||||||||
| memory: ComponentHealth; | ||||||||||||||||||||||||||||||||
| }; | ||||||||||||||||||||||||||||||||
| } | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| /** | ||||||||||||||||||||||||||||||||
| * Check database health | ||||||||||||||||||||||||||||||||
| */ | ||||||||||||||||||||||||||||||||
| async function checkDatabaseHealth(): Promise<ComponentHealth> { | ||||||||||||||||||||||||||||||||
| const startTime = Date.now(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| try { | ||||||||||||||||||||||||||||||||
| const db = await createDatabaseConnection(); | ||||||||||||||||||||||||||||||||
|
|
||||||||||||||||||||||||||||||||
| // Simple query to check connectivity | ||||||||||||||||||||||||||||||||
| await db.query('SELECT 1'); | ||||||||||||||||||||||||||||||||
| await db.disconnect(); | ||||||||||||||||||||||||||||||||
|
Comment on lines
+43
to
+51
|
||||||||||||||||||||||||||||||||
| async function checkDatabaseHealth(): Promise<ComponentHealth> { | |
| const startTime = Date.now(); | |
| try { | |
| const db = await createDatabaseConnection(); | |
| // Simple query to check connectivity | |
| await db.query('SELECT 1'); | |
| await db.disconnect(); | |
| async function checkDatabaseHealth(db: { query: (sql: string) => Promise<any> }): Promise<ComponentHealth> { | |
| const startTime = Date.now(); | |
| try { | |
| // Simple query to check connectivity | |
| await db.query('SELECT 1'); |
Copilot
AI
Nov 18, 2025
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exposing version information in health check responses could aid attackers in identifying known vulnerabilities. Consider making version exposure configurable or removing it from public health endpoints.
| const response: HealthCheckResponse = { | |
| status: overallStatus, | |
| timestamp: new Date().toISOString(), | |
| uptime: process.uptime(), | |
| version: process.env.APP_VERSION || '1.0.0', | |
| components, | |
| // Conditionally include version information based on environment variable | |
| const exposeVersion = process.env.EXPOSE_VERSION_IN_HEALTHCHECK === 'true'; | |
| const response: Omit<HealthCheckResponse, 'version'> & Partial<Pick<HealthCheckResponse, 'version'>> = { | |
| status: overallStatus, | |
| timestamp: new Date().toISOString(), | |
| uptime: process.uptime(), | |
| components, | |
| ...(exposeVersion && { version: process.env.APP_VERSION || '1.0.0' }), |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This nested ternary operator for determining the statusCode can be simplified for better readability. A single ternary check against 'unhealthy' is sufficient and more direct.
| const statusCode = overallStatus === 'healthy' ? 200 : overallStatus === 'degraded' ? 200 : 503; | |
| const statusCode = overallStatus === 'unhealthy' ? 503 : 200; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Parsing arbitrary JSON from multipart fields without validation could allow injection of malicious data structures. Consider validating the parsed metadata against a schema or whitelist of allowed fields before accepting it.