Skip to content

Commit ce78343

Browse files
aledlieclaude
andcommitted
docs: sync date stamps with git commit history
Update 'Last Updated' and 'Updated:' fields in 30 documentation files to reflect their actual last git commit dates. Files updated across: - docs/architecture/ (3 files) - docs/archive/ (3 files) - docs/dashboard_ui/ (5 files) - docs/deployment/ (5 files) - docs/runbooks/ (4 files) - docs/setup/ (2 files) - docs/testing/ (1 file) - Other locations (7 files) 🤖 Generated with Claude Code Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 8c6382d commit ce78343

28 files changed

Lines changed: 990 additions & 28 deletions

‎.ast-grep/README.md‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -270,5 +270,5 @@ pattern: |
270270
---
271271

272272
**Created:** 2025-11-11
273-
**Last Updated:** 2025-11-11
273+
**Last Updated:** 2025-11-23
274274
**Version:** 1.0.0
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
/**
2+
* Request Validation Middleware
3+
*
4+
* Validates request bodies using Zod schemas and returns detailed error messages.
5+
*/
6+
7+
import { ZodError } from 'zod';
8+
import { createComponentLogger } from '../../../sidequest/utils/logger.js';
9+
10+
const logger = createComponentLogger('ValidationMiddleware');
11+
12+
/**
13+
* Format Zod validation errors into user-friendly messages
14+
*/
15+
function formatZodErrors(error) {
16+
return error.errors.map(err => ({
17+
field: err.path.join('.'),
18+
message: err.message,
19+
code: err.code
20+
}));
21+
}
22+
23+
/**
24+
* Create validation middleware for a Zod schema
25+
*/
26+
export function validateRequest(schema) {
27+
return (req, res, next) => {
28+
try {
29+
// Validate request body against schema
30+
const validated = schema.parse(req.body);
31+
32+
// Replace request body with validated data (type-safe)
33+
req.body = validated;
34+
35+
next();
36+
} catch (error) {
37+
if (error instanceof ZodError) {
38+
const errors = formatZodErrors(error);
39+
40+
logger.warn({
41+
path: req.path,
42+
method: req.method,
43+
errors
44+
}, 'Request validation failed');
45+
46+
// Return detailed validation error
47+
return res.status(400).json({
48+
error: 'Bad Request',
49+
message: 'Request validation failed',
50+
timestamp: new Date().toISOString(),
51+
errors
52+
});
53+
}
54+
55+
// Unknown error - pass to error handler
56+
logger.error({ error }, 'Unknown validation error');
57+
next(error);
58+
}
59+
};
60+
}
61+
62+
/**
63+
* Validate query parameters
64+
* Stores validated data in req.validatedQuery to avoid read-only req.query
65+
*/
66+
export function validateQuery(schema) {
67+
return (req, res, next) => {
68+
try {
69+
const validated = schema.parse(req.query);
70+
// Store in custom property since req.query is read-only
71+
req.validatedQuery = validated;
72+
next();
73+
} catch (error) {
74+
if (error instanceof ZodError) {
75+
const errors = formatZodErrors(error);
76+
77+
logger.warn({
78+
path: req.path,
79+
method: req.method,
80+
errors
81+
}, 'Query validation failed');
82+
83+
return res.status(400).json({
84+
error: 'Bad Request',
85+
message: 'Query parameter validation failed',
86+
timestamp: new Date().toISOString(),
87+
errors
88+
});
89+
}
90+
91+
next(error);
92+
}
93+
};
94+
}
95+
96+
/**
97+
* Validate path parameters
98+
*/
99+
export function validateParams(schema) {
100+
return (req, res, next) => {
101+
try {
102+
const validated = schema.parse(req.params);
103+
req.params = validated;
104+
next();
105+
} catch (error) {
106+
if (error instanceof ZodError) {
107+
const errors = formatZodErrors(error);
108+
109+
logger.warn({
110+
path: req.path,
111+
method: req.method,
112+
errors
113+
}, 'Path parameter validation failed');
114+
115+
return res.status(400).json({
116+
error: 'Bad Request',
117+
message: 'Path parameter validation failed',
118+
timestamp: new Date().toISOString(),
119+
errors
120+
});
121+
}
122+
123+
next(error);
124+
}
125+
};
126+
}

0 commit comments

Comments
 (0)