diff --git a/.veritas-kanban/telemetry/events-2026-01-28.ndjson b/.veritas-kanban/telemetry/events-2026-01-28.ndjson index 2d72811b..e01daa2a 100644 --- a/.veritas-kanban/telemetry/events-2026-01-28.ndjson +++ b/.veritas-kanban/telemetry/events-2026-01-28.ndjson @@ -1728,3 +1728,4 @@ {"type":"task.status_changed","taskId":"task_20260128_u73mT3","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_EjShEPw7YS3u","timestamp":"2026-01-28T18:04:06.746Z"} {"type":"task.status_changed","taskId":"task_20260128_VVqEG1","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_X4p02S1uaswP","timestamp":"2026-01-28T18:04:06.932Z"} {"type":"task.status_changed","taskId":"task_20260128_xu0DY5","project":"veritas-kanban","status":"in-progress","previousStatus":"todo","id":"evt_j4vRMJuwSzya","timestamp":"2026-01-28T18:04:07.737Z"} +{"type":"task.status_changed","taskId":"task_20260128_u73mT3","project":"veritas-kanban","status":"done","previousStatus":"in-progress","id":"evt_SBwP5sBSKJW7","timestamp":"2026-01-28T18:05:24.388Z"} diff --git a/server/.veritas-kanban/activity.json b/server/.veritas-kanban/activity.json index 3d1018ab..70f027d5 100644 --- a/server/.veritas-kanban/activity.json +++ b/server/.veritas-kanban/activity.json @@ -1,4 +1,26 @@ [ + { + "id": "activity_1769623529304_9xemufqe7", + "type": "comment_added", + "taskId": "task_20260128_u73mT3", + "taskTitle": "SECURITY: Remove .env from git and create .env.example", + "details": { + "author": "Veritas", + "preview": "Updated .gitignore with explicit .env.example allo..." + }, + "timestamp": "2026-01-28T18:05:29.304Z" + }, + { + "id": "activity_1769623524389_x9eyqk318", + "type": "status_changed", + "taskId": "task_20260128_u73mT3", + "taskTitle": "SECURITY: Remove .env from git and create .env.example", + "details": { + "from": "in-progress", + "status": "done" + }, + "timestamp": "2026-01-28T18:05:24.389Z" + }, { "id": "activity_1769623447737_ioe02qo88", "type": "status_changed", diff --git a/server/src/index.ts b/server/src/index.ts index 6409cca8..0b5eef12 100644 --- a/server/src/index.ts +++ b/server/src/index.ts @@ -88,7 +88,7 @@ app.use( frameSrc: ["'none'"], baseUri: ["'self'"], formAction: ["'self'"], - ...(isDev ? {} : { upgradeInsecureRequests: [] }), + upgradeInsecureRequests: isDev ? null : [], }, }, // Cross-Origin-Embedder-Policy can break loading of cross-origin resources; @@ -391,6 +391,7 @@ server.listen(PORT, () => { ║ Health: http://localhost:${PORT}/health ║ ║ ${authLine.padEnd(42)}║ ║ ${corsLine.padEnd(42)}║ +║ Helmet: ON (CSP + security headers) ║ ║ Rate Limit: 100 req/min ║ ║ Body Limit: 1MB ║ ╚═══════════════════════════════════════════════╝ diff --git a/server/src/middleware/auth.ts b/server/src/middleware/auth.ts index c9f88bfa..e24097ef 100644 --- a/server/src/middleware/auth.ts +++ b/server/src/middleware/auth.ts @@ -154,13 +154,6 @@ function validateApiKey(apiKey: string, config: AuthConfig): { valid: boolean; r // === JWT Verification === function verifyJwtCookie(req: Request): { valid: boolean; error?: string } { - const securityConfig = getSecurityConfig(); - - // No JWT secret means no password auth configured - if (!securityConfig.jwtSecret) { - return { valid: false }; - } - // Get cookie from request const token = req.cookies?.veritas_session; if (!token) { @@ -168,7 +161,7 @@ function verifyJwtCookie(req: Request): { valid: boolean; error?: string } { } try { - jwt.verify(token, securityConfig.jwtSecret); + jwt.verify(token, getJwtSecret()); return { valid: true }; } catch (err) { if (err instanceof jwt.TokenExpiredError) { @@ -342,11 +335,11 @@ export function authenticateWebSocket(req: IncomingMessage): WebSocketAuthResult } // 1. Check JWT cookie - if (passwordAuthEnabled && securityConfig.jwtSecret) { + if (passwordAuthEnabled) { const token = extractJwtFromWebSocket(req); if (token) { try { - jwt.verify(token, securityConfig.jwtSecret); + jwt.verify(token, getJwtSecret()); return { authenticated: true, role: 'admin', keyName: 'session', isLocalhost }; } catch { // Token invalid or expired, continue to other auth methods