@orchestrator-claude/definitions 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (73) hide show
  1. package/agents/api-extractor.md +687 -0
  2. package/agents/business-rule-miner.md +754 -0
  3. package/agents/code-archaeologist.md +720 -0
  4. package/agents/docs-guardian.md +524 -0
  5. package/agents/implementer.md +512 -0
  6. package/agents/legacy-discoverer.md +583 -0
  7. package/agents/legacy-synthesizer.md +1101 -0
  8. package/agents/orchestrator.md +165 -0
  9. package/agents/planner.md +365 -0
  10. package/agents/researcher.md +447 -0
  11. package/agents/reviewer.md +514 -0
  12. package/agents/schema-extractor.md +781 -0
  13. package/agents/specifier.md +360 -0
  14. package/agents/task-generator.md +390 -0
  15. package/bin/orch-defs.js +2 -0
  16. package/dist/cli.d.ts +3 -0
  17. package/dist/cli.d.ts.map +1 -0
  18. package/dist/cli.js +172 -0
  19. package/dist/cli.js.map +1 -0
  20. package/dist/commands/DiffCommand.d.ts +13 -0
  21. package/dist/commands/DiffCommand.d.ts.map +1 -0
  22. package/dist/commands/DiffCommand.js +74 -0
  23. package/dist/commands/DiffCommand.js.map +1 -0
  24. package/dist/commands/SeedCommand.d.ts +19 -0
  25. package/dist/commands/SeedCommand.d.ts.map +1 -0
  26. package/dist/commands/SeedCommand.js +56 -0
  27. package/dist/commands/SeedCommand.js.map +1 -0
  28. package/dist/http/ApiClient.d.ts +50 -0
  29. package/dist/http/ApiClient.d.ts.map +1 -0
  30. package/dist/http/ApiClient.js +58 -0
  31. package/dist/http/ApiClient.js.map +1 -0
  32. package/dist/index.d.ts +12 -0
  33. package/dist/index.d.ts.map +1 -0
  34. package/dist/index.js +11 -0
  35. package/dist/index.js.map +1 -0
  36. package/dist/manifest/ManifestLoader.d.ts +34 -0
  37. package/dist/manifest/ManifestLoader.d.ts.map +1 -0
  38. package/dist/manifest/ManifestLoader.js +110 -0
  39. package/dist/manifest/ManifestLoader.js.map +1 -0
  40. package/dist/manifest/types.d.ts +59 -0
  41. package/dist/manifest/types.d.ts.map +1 -0
  42. package/dist/manifest/types.js +5 -0
  43. package/dist/manifest/types.js.map +1 -0
  44. package/dist/scripts/generate-manifest.d.ts +10 -0
  45. package/dist/scripts/generate-manifest.d.ts.map +1 -0
  46. package/dist/scripts/generate-manifest.js +114 -0
  47. package/dist/scripts/generate-manifest.js.map +1 -0
  48. package/hooks/post-agent-artifact-relay.sh +157 -0
  49. package/hooks/post-artifact-generate.sh +39 -0
  50. package/hooks/post-implement-validate.sh +139 -0
  51. package/hooks/post-phase-checkpoint.sh +322 -0
  52. package/hooks/pre-agent-invoke.sh +34 -0
  53. package/hooks/pre-phase-advance.sh +40 -0
  54. package/hooks/track-agent-invocation.sh +241 -0
  55. package/kb/auth-strategies.md +742 -0
  56. package/kb/docs-constitution.md +310 -0
  57. package/kb/error-handling.md +555 -0
  58. package/kb/rest-conventions.md +458 -0
  59. package/kb/validation-patterns.md +589 -0
  60. package/manifest.json +314 -0
  61. package/package.json +65 -0
  62. package/skills/artifact-validator/SKILL.md +226 -0
  63. package/skills/docs-guardian/SKILL.md +230 -0
  64. package/skills/kb-lookup/SKILL.md +257 -0
  65. package/skills/phase-gate-evaluator/SKILL.md +274 -0
  66. package/skills/release/SKILL.md +239 -0
  67. package/skills/release/release.sh +491 -0
  68. package/skills/smoke-test/SKILL.md +195 -0
  69. package/skills/workflow-status/SKILL.md +322 -0
  70. package/workflows/bug-fix.json +74 -0
  71. package/workflows/feature-development.json +88 -0
  72. package/workflows/legacy-analysis.json +304 -0
  73. package/workflows/refactoring.json +74 -0
@@ -0,0 +1,589 @@
1
+ ---
2
+ title: "Validation Patterns"
3
+ category: "patterns"
4
+ tier: "foundational"
5
+ tags: ["api", "validation", "zod", "security"]
6
+ template: "api"
7
+ ---
8
+
9
+ # Validation Patterns
10
+
11
+ ## Overview
12
+
13
+ This document defines validation patterns and best practices for ensuring data integrity and security in REST APIs using Zod for runtime type validation.
14
+
15
+ **Project**: my-project
16
+ **Template**: api
17
+
18
+ ---
19
+
20
+ ## 1. Why Validation Matters
21
+
22
+ ### Security
23
+
24
+ - **Prevent injection attacks**: SQL, NoSQL, XSS
25
+ - **Prevent buffer overflows**: Limit string/array sizes
26
+ - **Type safety at runtime**: TypeScript only validates at compile time
27
+
28
+ ### Data Integrity
29
+
30
+ - **Consistent data**: Enforce business rules at entry point
31
+ - **Clear error messages**: Help clients fix invalid requests
32
+ - **Fail fast**: Catch errors early in request lifecycle
33
+
34
+ ---
35
+
36
+ ## 2. Zod Schema Basics
37
+
38
+ ### Installation
39
+
40
+ ```bash
41
+ npm install zod
42
+ ```
43
+
44
+ ### Basic Types
45
+
46
+ ```typescript
47
+ import { z } from 'zod';
48
+
49
+ // Primitives
50
+ const stringSchema = z.string();
51
+ const numberSchema = z.number();
52
+ const booleanSchema = z.boolean();
53
+ const dateSchema = z.date();
54
+
55
+ // String validations
56
+ const emailSchema = z.string().email();
57
+ const urlSchema = z.string().url();
58
+ const uuidSchema = z.string().uuid();
59
+ const minMaxSchema = z.string().min(1).max(100);
60
+
61
+ // Number validations
62
+ const positiveSchema = z.number().positive();
63
+ const intSchema = z.number().int();
64
+ const rangeSchema = z.number().min(0).max(100);
65
+
66
+ // Optional and nullable
67
+ const optionalSchema = z.string().optional();
68
+ const nullableSchema = z.string().nullable();
69
+
70
+ // Arrays
71
+ const arraySchema = z.array(z.string());
72
+ const nonEmptyArraySchema = z.array(z.string()).nonempty();
73
+ const minLengthArraySchema = z.array(z.string()).min(1).max(10);
74
+ ```
75
+
76
+ ---
77
+
78
+ ## 3. Object Schemas
79
+
80
+ ### Basic Object
81
+
82
+ ```typescript
83
+ const UserSchema = z.object({
84
+ id: z.string().uuid(),
85
+ name: z.string().min(1).max(100),
86
+ email: z.string().email(),
87
+ age: z.number().int().positive().optional(),
88
+ role: z.enum(['user', 'admin', 'moderator']),
89
+ createdAt: z.date(),
90
+ });
91
+
92
+ // Infer TypeScript type from schema
93
+ type User = z.infer<typeof UserSchema>;
94
+ ```
95
+
96
+ ### Nested Objects
97
+
98
+ ```typescript
99
+ const AddressSchema = z.object({
100
+ street: z.string(),
101
+ city: z.string(),
102
+ state: z.string().length(2), // US state code
103
+ zipCode: z.string().regex(/^\d{5}$/),
104
+ });
105
+
106
+ const UserWithAddressSchema = z.object({
107
+ name: z.string(),
108
+ email: z.string().email(),
109
+ address: AddressSchema,
110
+ });
111
+ ```
112
+
113
+ ### Partial and Pick
114
+
115
+ ```typescript
116
+ // Make all fields optional
117
+ const PartialUserSchema = UserSchema.partial();
118
+
119
+ // Pick specific fields
120
+ const UserLoginSchema = UserSchema.pick({
121
+ email: true,
122
+ password: true,
123
+ });
124
+
125
+ // Omit specific fields
126
+ const UserWithoutPasswordSchema = UserSchema.omit({
127
+ password: true,
128
+ });
129
+ ```
130
+
131
+ ---
132
+
133
+ ## 4. Request Validation Schemas
134
+
135
+ ### Create Schemas
136
+
137
+ ```typescript
138
+ // POST /api/v1/users
139
+ const CreateUserSchema = z.object({
140
+ name: z.string().min(1, 'Name is required').max(100),
141
+ email: z.string().email('Invalid email format'),
142
+ password: z
143
+ .string()
144
+ .min(8, 'Password must be at least 8 characters')
145
+ .regex(
146
+ /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)/,
147
+ 'Password must contain uppercase, lowercase, and number'
148
+ ),
149
+ role: z.enum(['user', 'admin']).default('user'),
150
+ });
151
+
152
+ type CreateUserInput = z.infer<typeof CreateUserSchema>;
153
+ ```
154
+
155
+ ### Update Schemas
156
+
157
+ ```typescript
158
+ // PATCH /api/v1/users/:id
159
+ const UpdateUserSchema = z.object({
160
+ name: z.string().min(1).max(100).optional(),
161
+ email: z.string().email().optional(),
162
+ age: z.number().int().positive().optional(),
163
+ }).strict(); // Disallow unknown fields
164
+
165
+ type UpdateUserInput = z.infer<typeof UpdateUserSchema>;
166
+ ```
167
+
168
+ ### Query Parameter Schemas
169
+
170
+ ```typescript
171
+ // GET /api/v1/users?page=1&limit=20&role=admin
172
+ const ListUsersQuerySchema = z.object({
173
+ page: z.coerce.number().int().positive().default(1),
174
+ limit: z.coerce.number().int().positive().max(100).default(20),
175
+ role: z.enum(['user', 'admin', 'moderator']).optional(),
176
+ sort: z.enum(['name', 'email', 'createdAt']).default('createdAt'),
177
+ order: z.enum(['asc', 'desc']).default('desc'),
178
+ });
179
+
180
+ type ListUsersQuery = z.infer<typeof ListUsersQuerySchema>;
181
+ ```
182
+
183
+ ### Path Parameter Schemas
184
+
185
+ ```typescript
186
+ // GET /api/v1/users/:id
187
+ const UserIdParamSchema = z.object({
188
+ id: z.string().uuid('Invalid user ID format'),
189
+ });
190
+
191
+ type UserIdParam = z.infer<typeof UserIdParamSchema>;
192
+ ```
193
+
194
+ ---
195
+
196
+ ## 5. Validation Middleware
197
+
198
+ ### Generic Validation Middleware
199
+
200
+ ```typescript
201
+ // src/presentation/middleware/validate.ts
202
+ import type { Request, Response, NextFunction } from 'express';
203
+ import type { z } from 'zod';
204
+
205
+ export type ValidateTarget = 'body' | 'query' | 'params';
206
+
207
+ export function validate<T extends z.ZodSchema>(
208
+ schema: T,
209
+ target: ValidateTarget = 'body'
210
+ ) {
211
+ return (req: Request, res: Response, next: NextFunction) => {
212
+ const data = req[target];
213
+ const result = schema.safeParse(data);
214
+
215
+ if (!result.success) {
216
+ return res.status(400).json({
217
+ error: 'ValidationError',
218
+ message: 'Request validation failed',
219
+ details: result.error.issues.map(issue => ({
220
+ path: issue.path.join('.'),
221
+ message: issue.message,
222
+ code: issue.code,
223
+ })),
224
+ timestamp: new Date().toISOString(),
225
+ path: req.path,
226
+ });
227
+ }
228
+
229
+ // Replace with validated data (with defaults applied)
230
+ req[target] = result.data;
231
+ next();
232
+ };
233
+ }
234
+ ```
235
+
236
+ ### Usage in Routes
237
+
238
+ ```typescript
239
+ import { validate } from '../middleware/validate';
240
+ import { CreateUserSchema, UpdateUserSchema, ListUsersQuerySchema } from '../schemas/user';
241
+
242
+ // Create user
243
+ router.post(
244
+ '/api/v1/users',
245
+ validate(CreateUserSchema, 'body'),
246
+ async (req, res, next) => {
247
+ // req.body is now validated and typed
248
+ const result = await createUserUseCase.execute(req.body);
249
+ res.status(201).json(result);
250
+ }
251
+ );
252
+
253
+ // Update user
254
+ router.patch(
255
+ '/api/v1/users/:id',
256
+ validate(UserIdParamSchema, 'params'),
257
+ validate(UpdateUserSchema, 'body'),
258
+ async (req, res, next) => {
259
+ // req.params.id and req.body are validated
260
+ const result = await updateUserUseCase.execute({
261
+ userId: req.params.id,
262
+ ...req.body,
263
+ });
264
+ res.json(result);
265
+ }
266
+ );
267
+
268
+ // List users with query params
269
+ router.get(
270
+ '/api/v1/users',
271
+ validate(ListUsersQuerySchema, 'query'),
272
+ async (req, res, next) => {
273
+ // req.query is validated with defaults
274
+ const result = await listUsersUseCase.execute(req.query);
275
+ res.json(result);
276
+ }
277
+ );
278
+ ```
279
+
280
+ ---
281
+
282
+ ## 6. Custom Validations
283
+
284
+ ### Refine for Complex Rules
285
+
286
+ ```typescript
287
+ const PasswordChangeSchema = z
288
+ .object({
289
+ oldPassword: z.string(),
290
+ newPassword: z.string().min(8),
291
+ confirmPassword: z.string(),
292
+ })
293
+ .refine((data) => data.newPassword === data.confirmPassword, {
294
+ message: "Passwords don't match",
295
+ path: ['confirmPassword'], // Error will be on confirmPassword field
296
+ })
297
+ .refine((data) => data.oldPassword !== data.newPassword, {
298
+ message: 'New password must be different from old password',
299
+ path: ['newPassword'],
300
+ });
301
+ ```
302
+
303
+ ### Transform Values
304
+
305
+ ```typescript
306
+ const TrimmedStringSchema = z.string().transform((val) => val.trim());
307
+
308
+ const LowercaseEmailSchema = z
309
+ .string()
310
+ .email()
311
+ .transform((val) => val.toLowerCase());
312
+
313
+ const CreateUserSchema = z.object({
314
+ name: TrimmedStringSchema,
315
+ email: LowercaseEmailSchema,
316
+ });
317
+ ```
318
+
319
+ ### Custom Validators
320
+
321
+ ```typescript
322
+ function isValidCreditCard(value: string): boolean {
323
+ // Luhn algorithm implementation
324
+ return /^\d{16}$/.test(value); // Simplified
325
+ }
326
+
327
+ const PaymentSchema = z.object({
328
+ cardNumber: z.string().refine(isValidCreditCard, {
329
+ message: 'Invalid credit card number',
330
+ }),
331
+ cvv: z.string().regex(/^\d{3,4}$/),
332
+ expiry: z
333
+ .string()
334
+ .regex(/^\d{2}\/\d{2}$/)
335
+ .refine((val) => {
336
+ const [month, year] = val.split('/').map(Number);
337
+ const now = new Date();
338
+ const expiry = new Date(2000 + year, month - 1);
339
+ return expiry > now;
340
+ }, 'Card has expired'),
341
+ });
342
+ ```
343
+
344
+ ---
345
+
346
+ ## 7. Sanitization
347
+
348
+ ### Input Sanitization
349
+
350
+ ```typescript
351
+ import validator from 'validator';
352
+
353
+ const SanitizedStringSchema = z
354
+ .string()
355
+ .transform((val) => validator.escape(val)); // Escape HTML entities
356
+
357
+ const SafeUserInputSchema = z.object({
358
+ comment: z
359
+ .string()
360
+ .max(1000)
361
+ .transform((val) => validator.escape(val)),
362
+ username: z
363
+ .string()
364
+ .regex(/^[a-zA-Z0-9_-]+$/, 'Username can only contain alphanumeric characters, underscores, and hyphens'),
365
+ });
366
+ ```
367
+
368
+ ---
369
+
370
+ ## 8. File Upload Validation
371
+
372
+ ### Multer + Zod
373
+
374
+ ```typescript
375
+ import multer from 'multer';
376
+
377
+ const upload = multer({
378
+ limits: {
379
+ fileSize: 5 * 1024 * 1024, // 5MB
380
+ },
381
+ fileFilter: (req, file, cb) => {
382
+ const allowedMimes = ['image/jpeg', 'image/png', 'image/gif'];
383
+
384
+ if (!allowedMimes.includes(file.mimetype)) {
385
+ return cb(new Error('Invalid file type'));
386
+ }
387
+
388
+ cb(null, true);
389
+ },
390
+ });
391
+
392
+ const FileUploadSchema = z.object({
393
+ title: z.string().min(1).max(100),
394
+ description: z.string().max(500).optional(),
395
+ });
396
+
397
+ router.post(
398
+ '/api/v1/uploads',
399
+ upload.single('file'),
400
+ validate(FileUploadSchema, 'body'),
401
+ async (req, res) => {
402
+ if (!req.file) {
403
+ return res.status(400).json({ error: 'File is required' });
404
+ }
405
+
406
+ // Process file and validated body
407
+ const result = await uploadFileUseCase.execute({
408
+ file: req.file,
409
+ ...req.body,
410
+ });
411
+
412
+ res.status(201).json(result);
413
+ }
414
+ );
415
+ ```
416
+
417
+ ---
418
+
419
+ ## 9. Testing Validation
420
+
421
+ ### Test Valid Inputs
422
+
423
+ ```typescript
424
+ import request from 'supertest';
425
+ import { app } from '../src/server';
426
+
427
+ describe('POST /api/v1/users - Validation', () => {
428
+ it('should accept valid user data', async () => {
429
+ const validUser = {
430
+ name: 'John Doe',
431
+ email: 'john@example.com',
432
+ password: 'SecureP@ss123',
433
+ };
434
+
435
+ await request(app)
436
+ .post('/api/v1/users')
437
+ .send(validUser)
438
+ .expect(201);
439
+ });
440
+
441
+ it('should reject invalid email', async () => {
442
+ const invalidUser = {
443
+ name: 'John Doe',
444
+ email: 'not-an-email',
445
+ password: 'SecureP@ss123',
446
+ };
447
+
448
+ const response = await request(app)
449
+ .post('/api/v1/users')
450
+ .send(invalidUser)
451
+ .expect(400);
452
+
453
+ expect(response.body.error).toBe('ValidationError');
454
+ expect(response.body.details).toEqual(
455
+ expect.arrayContaining([
456
+ expect.objectContaining({
457
+ path: 'email',
458
+ message: expect.stringContaining('Invalid email'),
459
+ }),
460
+ ])
461
+ );
462
+ });
463
+
464
+ it('should reject weak password', async () => {
465
+ const invalidUser = {
466
+ name: 'John Doe',
467
+ email: 'john@example.com',
468
+ password: 'weak',
469
+ };
470
+
471
+ const response = await request(app)
472
+ .post('/api/v1/users')
473
+ .send(invalidUser)
474
+ .expect(400);
475
+
476
+ expect(response.body.details).toEqual(
477
+ expect.arrayContaining([
478
+ expect.objectContaining({
479
+ path: 'password',
480
+ message: expect.stringContaining('at least 8 characters'),
481
+ }),
482
+ ])
483
+ );
484
+ });
485
+
486
+ it('should reject unknown fields when strict', async () => {
487
+ const userWithExtra = {
488
+ name: 'John Doe',
489
+ email: 'john@example.com',
490
+ password: 'SecureP@ss123',
491
+ extraField: 'should-not-be-here',
492
+ };
493
+
494
+ await request(app)
495
+ .post('/api/v1/users')
496
+ .send(userWithExtra)
497
+ .expect(400);
498
+ });
499
+ });
500
+ ```
501
+
502
+ ---
503
+
504
+ ## 10. Best Practices
505
+
506
+ ### DO
507
+
508
+ 1. **Validate all inputs**: Body, query, params, headers
509
+ 2. **Use strict mode**: `.strict()` to reject unknown fields
510
+ 3. **Transform and sanitize**: Trim, lowercase, escape HTML
511
+ 4. **Provide clear error messages**: Help clients fix issues
512
+ 5. **Test edge cases**: Empty strings, negative numbers, large files
513
+ 6. **Set limits**: Max string length, array size, file size
514
+ 7. **Use enums**: For fixed sets of values
515
+
516
+ ### DON'T
517
+
518
+ 1. **Don't trust client input**: Always validate on server
519
+ 2. **Don't expose internal errors**: Sanitize error messages
520
+ 3. **Don't skip validation**: Even for "trusted" clients
521
+ 4. **Don't validate in use cases**: Validate at API boundary
522
+ 5. **Don't use regex for complex logic**: Use `.refine()`
523
+
524
+ ---
525
+
526
+ ## 11. Common Schemas
527
+
528
+ ### Email
529
+
530
+ ```typescript
531
+ const EmailSchema = z
532
+ .string()
533
+ .email()
534
+ .transform((val) => val.toLowerCase());
535
+ ```
536
+
537
+ ### Password
538
+
539
+ ```typescript
540
+ const PasswordSchema = z
541
+ .string()
542
+ .min(8, 'Password must be at least 8 characters')
543
+ .regex(
544
+ /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[@$!%*?&])/,
545
+ 'Password must contain uppercase, lowercase, number, and special character'
546
+ );
547
+ ```
548
+
549
+ ### Phone Number
550
+
551
+ ```typescript
552
+ const PhoneSchema = z
553
+ .string()
554
+ .regex(/^\+?[1-9]\d{1,14}$/, 'Invalid phone number format (E.164)');
555
+ ```
556
+
557
+ ### URL
558
+
559
+ ```typescript
560
+ const URLSchema = z.string().url();
561
+ ```
562
+
563
+ ### Date Range
564
+
565
+ ```typescript
566
+ const DateRangeSchema = z
567
+ .object({
568
+ startDate: z.coerce.date(),
569
+ endDate: z.coerce.date(),
570
+ })
571
+ .refine((data) => data.endDate > data.startDate, {
572
+ message: 'End date must be after start date',
573
+ path: ['endDate'],
574
+ });
575
+ ```
576
+
577
+ ---
578
+
579
+ ## References
580
+
581
+ - [Zod Documentation](https://zod.dev/)
582
+ - [OWASP Input Validation](https://cheatsheetseries.owasp.org/cheatsheets/Input_Validation_Cheat_Sheet.html)
583
+ - [validator.js](https://github.com/validatorjs/validator.js)
584
+
585
+ ---
586
+
587
+ **Generated for**: my-project
588
+ **Template**: api
589
+ **Constitution Preset**: orchestrator