codecruise 0.1.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 (129) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +111 -0
  3. package/bin/codecruise.js +68 -0
  4. package/config/CLAUDE.md +107 -0
  5. package/config/agents/analyst.md +48 -0
  6. package/config/agents/architect-reviewer.md +161 -0
  7. package/config/agents/architect.md +119 -0
  8. package/config/agents/critic.md +63 -0
  9. package/config/agents/developer.md +96 -0
  10. package/config/agents/devops.md +81 -0
  11. package/config/agents/orchestrator.md +91 -0
  12. package/config/agents/planner.md +139 -0
  13. package/config/agents/retro.md +52 -0
  14. package/config/agents/reviewer.md +101 -0
  15. package/config/agents/security-reviewer.md +57 -0
  16. package/config/agents/stack/expo/AGENT.md +473 -0
  17. package/config/agents/stack/expo/rules/critical.md +427 -0
  18. package/config/agents/stack/expo/rules/native.md +455 -0
  19. package/config/agents/stack/expo/rules/navigation.md +445 -0
  20. package/config/agents/stack/expo/rules/performance.md +415 -0
  21. package/config/agents/stack/fastify/AGENT.md +397 -0
  22. package/config/agents/stack/fastify/rules/api-design.md +283 -0
  23. package/config/agents/stack/fastify/rules/critical.md +232 -0
  24. package/config/agents/stack/fastify/rules/queues.md +303 -0
  25. package/config/agents/stack/fastify/rules/security.md +384 -0
  26. package/config/agents/stack/index.yaml +48 -0
  27. package/config/agents/stack/nextjs/AGENT.md +421 -0
  28. package/config/agents/stack/nextjs/rules/components.md +413 -0
  29. package/config/agents/stack/nextjs/rules/critical.md +391 -0
  30. package/config/agents/stack/nextjs/rules/performance.md +403 -0
  31. package/config/agents/stack/nextjs/rules/styling.md +334 -0
  32. package/config/agents/stack/shared-ts/AGENT.md +384 -0
  33. package/config/agents/stack/shared-ts/rules/critical.md +315 -0
  34. package/config/agents/stack/shared-ts/rules/patterns.md +384 -0
  35. package/config/agents/stack/shared-ts/rules/zod.md +427 -0
  36. package/config/agents/tester.md +79 -0
  37. package/config/commands/architect-discuss.md +366 -0
  38. package/config/commands/architect-list.md +160 -0
  39. package/config/commands/architect-review.md +111 -0
  40. package/config/commands/architect.md +118 -0
  41. package/config/commands/compact.md +118 -0
  42. package/config/commands/companion.md +279 -0
  43. package/config/commands/dashboard.md +152 -0
  44. package/config/commands/doctor.md +227 -0
  45. package/config/commands/dogfood-report.md +101 -0
  46. package/config/commands/flags/run-autonomous.md +110 -0
  47. package/config/commands/flags/run-pause.md +80 -0
  48. package/config/commands/ingest.md +173 -0
  49. package/config/commands/init.md +128 -0
  50. package/config/commands/metrics.md +87 -0
  51. package/config/commands/parallel.md +320 -0
  52. package/config/commands/pause.md +55 -0
  53. package/config/commands/plan-review.md +130 -0
  54. package/config/commands/plan.md +216 -0
  55. package/config/commands/production-check.md +308 -0
  56. package/config/commands/refine.md +323 -0
  57. package/config/commands/resume.md +72 -0
  58. package/config/commands/retro.md +121 -0
  59. package/config/commands/retry.md +75 -0
  60. package/config/commands/role.md +310 -0
  61. package/config/commands/run.md +417 -0
  62. package/config/commands/scope.md +85 -0
  63. package/config/commands/setup-permissions.md +104 -0
  64. package/config/commands/skip.md +75 -0
  65. package/config/commands/spec-forge.md +213 -0
  66. package/config/commands/spec-help.md +194 -0
  67. package/config/commands/spec-patch.md +342 -0
  68. package/config/commands/spec-resolve.md +110 -0
  69. package/config/commands/spec-review.md +153 -0
  70. package/config/commands/status.md +114 -0
  71. package/config/commands/sync.md +131 -0
  72. package/config/commands/task.md +138 -0
  73. package/config/commands/verify.md +124 -0
  74. package/config/hooks/README.md +632 -0
  75. package/config/hooks/activity-log.sh +187 -0
  76. package/config/hooks/anti-rationalize.sh +52 -0
  77. package/config/hooks/capture-verification.sh +112 -0
  78. package/config/hooks/collect-metrics.sh +135 -0
  79. package/config/hooks/enforce-file-scope.sh +75 -0
  80. package/config/hooks/enforce-state-machine.sh +161 -0
  81. package/config/hooks/enforce-tdd.sh +180 -0
  82. package/config/hooks/format.sh +40 -0
  83. package/config/hooks/lib/activity-helpers.sh +162 -0
  84. package/config/hooks/lib/read-settings.sh +71 -0
  85. package/config/hooks/load-context-skills.sh +95 -0
  86. package/config/hooks/notify.sh +81 -0
  87. package/config/hooks/pre-commit.sample +35 -0
  88. package/config/hooks/protect-files.sh +63 -0
  89. package/config/hooks/track-agents.sh +41 -0
  90. package/config/hooks/track-commands.sh +37 -0
  91. package/config/hooks/track-enforcement.sh +44 -0
  92. package/config/hooks/track-ooda.sh +77 -0
  93. package/config/hooks/validate-commit-msg.sh +35 -0
  94. package/config/hooks/validate-plan.sh +213 -0
  95. package/config/hooks/verify-criteria.sh +46 -0
  96. package/config/hooks/verify-todo-completion.sh +140 -0
  97. package/config/rules/comments.md +25 -0
  98. package/config/rules/decision-rules.md +308 -0
  99. package/config/rules/hygiene.md +247 -0
  100. package/config/rules/pattern-detection.md +372 -0
  101. package/config/rules/profiles.md +193 -0
  102. package/config/rules/recovery.md +83 -0
  103. package/config/rules/scope-detection.md +213 -0
  104. package/config/rules/standards.md +127 -0
  105. package/config/rules/workflow.md +121 -0
  106. package/config/schemas.md +767 -0
  107. package/config/settings.json +195 -0
  108. package/config/skills/backend/SKILL.md +734 -0
  109. package/config/skills/database/SKILL.md +426 -0
  110. package/config/skills/frontend/SKILL.md +434 -0
  111. package/config/skills/git/SKILL.md +396 -0
  112. package/config/skills/index.yaml +36 -0
  113. package/config/skills/observability/SKILL.md +430 -0
  114. package/config/skills/package-dev/SKILL.md +498 -0
  115. package/config/skills/performance/SKILL.md +378 -0
  116. package/config/skills/resilience/SKILL.md +573 -0
  117. package/config/skills/testing/SKILL.md +398 -0
  118. package/config/skills/testing-patterns/SKILL.md +276 -0
  119. package/config/skills/typescript/SKILL.md +152 -0
  120. package/config/templates/CLAUDE.md +70 -0
  121. package/config/templates/README.md +117 -0
  122. package/config/templates/steering/adr-template.md +102 -0
  123. package/config/templates/steering/product.md +60 -0
  124. package/config/templates/steering/rfc-template.md +159 -0
  125. package/config/templates/steering/structure.md +146 -0
  126. package/config/templates/steering/tech.md +85 -0
  127. package/package.json +40 -0
  128. package/src/install.js +163 -0
  129. package/src/report.js +310 -0
@@ -0,0 +1,384 @@
1
+ # Security Rules - Fastify
2
+
3
+ Authentication, authorization, and protection patterns.
4
+
5
+ ---
6
+
7
+ ## Authentication
8
+
9
+ ### SEC-001: Use secure token generation
10
+
11
+ ```typescript
12
+ import { randomBytes, createHash } from 'crypto';
13
+
14
+ // For refresh tokens, API keys
15
+ function generateSecureToken(): string {
16
+ return randomBytes(32).toString('hex'); // 64 chars
17
+ }
18
+
19
+ // For password reset tokens (shorter-lived)
20
+ function generateResetToken(): string {
21
+ return randomBytes(16).toString('hex'); // 32 chars
22
+ }
23
+
24
+ // Hash tokens before storing
25
+ function hashToken(token: string): string {
26
+ return createHash('sha256').update(token).digest('hex');
27
+ }
28
+ ```
29
+
30
+ ### SEC-002: Implement JWT correctly
31
+
32
+ ```typescript
33
+ import jwt from 'jsonwebtoken';
34
+
35
+ const ACCESS_TOKEN_EXPIRY = '15m';
36
+ const REFRESH_TOKEN_EXPIRY = '7d';
37
+
38
+ interface TokenPayload {
39
+ sub: string; // User ID
40
+ role: string;
41
+ type: 'access' | 'refresh';
42
+ }
43
+
44
+ function signAccessToken(userId: string, role: string): string {
45
+ return jwt.sign(
46
+ { sub: userId, role, type: 'access' },
47
+ process.env.JWT_SECRET!,
48
+ { expiresIn: ACCESS_TOKEN_EXPIRY }
49
+ );
50
+ }
51
+
52
+ function signRefreshToken(userId: string): string {
53
+ return jwt.sign(
54
+ { sub: userId, type: 'refresh' },
55
+ process.env.JWT_REFRESH_SECRET!, // Different secret!
56
+ { expiresIn: REFRESH_TOKEN_EXPIRY }
57
+ );
58
+ }
59
+ ```
60
+
61
+ ### SEC-003: Store passwords securely
62
+
63
+ ```typescript
64
+ import bcrypt from 'bcrypt';
65
+
66
+ const SALT_ROUNDS = 12;
67
+
68
+ async function hashPassword(password: string): Promise<string> {
69
+ return bcrypt.hash(password, SALT_ROUNDS);
70
+ }
71
+
72
+ async function verifyPassword(password: string, hash: string): Promise<boolean> {
73
+ return bcrypt.compare(password, hash);
74
+ }
75
+
76
+ // Never store plaintext passwords
77
+ // Never log passwords
78
+ // Never return password hash in API responses
79
+ ```
80
+
81
+ ### SEC-004: Implement account lockout
82
+
83
+ ```typescript
84
+ const MAX_FAILED_ATTEMPTS = 5;
85
+ const LOCKOUT_DURATION = 15 * 60 * 1000; // 15 minutes
86
+
87
+ async function handleLogin(email: string, password: string) {
88
+ const user = await db.user.findUnique({ where: { email } });
89
+
90
+ if (!user) {
91
+ // Don't reveal if user exists
92
+ throw new AuthError('Invalid credentials');
93
+ }
94
+
95
+ if (user.lockedUntil && user.lockedUntil > new Date()) {
96
+ throw new AuthError('Account locked. Try again later.');
97
+ }
98
+
99
+ const valid = await verifyPassword(password, user.password);
100
+
101
+ if (!valid) {
102
+ const attempts = user.failedAttempts + 1;
103
+ const updates: any = { failedAttempts: attempts };
104
+
105
+ if (attempts >= MAX_FAILED_ATTEMPTS) {
106
+ updates.lockedUntil = new Date(Date.now() + LOCKOUT_DURATION);
107
+ }
108
+
109
+ await db.user.update({ where: { id: user.id }, data: updates });
110
+ throw new AuthError('Invalid credentials');
111
+ }
112
+
113
+ // Reset on success
114
+ await db.user.update({
115
+ where: { id: user.id },
116
+ data: { failedAttempts: 0, lockedUntil: null },
117
+ });
118
+
119
+ return user;
120
+ }
121
+ ```
122
+
123
+ ---
124
+
125
+ ## Authorization
126
+
127
+ ### SEC-005: Implement RBAC
128
+
129
+ ```typescript
130
+ type Role = 'USER' | 'ADMIN' | 'SUPER_ADMIN';
131
+
132
+ const permissions: Record<Role, string[]> = {
133
+ USER: ['read:own', 'write:own'],
134
+ ADMIN: ['read:own', 'write:own', 'read:all', 'write:all'],
135
+ SUPER_ADMIN: ['read:own', 'write:own', 'read:all', 'write:all', 'manage:users'],
136
+ };
137
+
138
+ function hasPermission(role: Role, permission: string): boolean {
139
+ return permissions[role]?.includes(permission) ?? false;
140
+ }
141
+
142
+ // Middleware
143
+ function requirePermission(permission: string) {
144
+ return async (request: FastifyRequest, reply: FastifyReply) => {
145
+ if (!hasPermission(request.user.role, permission)) {
146
+ return reply.status(403).send({
147
+ error: { code: 'FORBIDDEN', message: 'Insufficient permissions' }
148
+ });
149
+ }
150
+ };
151
+ }
152
+ ```
153
+
154
+ ### SEC-006: Validate resource ownership
155
+
156
+ ```typescript
157
+ async function getOrder(request: FastifyRequest<{ Params: { id: string } }>) {
158
+ const order = await db.order.findUnique({
159
+ where: { id: request.params.id },
160
+ });
161
+
162
+ if (!order) {
163
+ throw new NotFoundError('Order');
164
+ }
165
+
166
+ // Validate ownership (unless admin)
167
+ if (order.userId !== request.user.id && request.user.role !== 'ADMIN') {
168
+ throw new ForbiddenError('Not your order');
169
+ }
170
+
171
+ return { data: order };
172
+ }
173
+ ```
174
+
175
+ ### SEC-007: Use scoped tokens for specific actions
176
+
177
+ ```typescript
178
+ // Email verification token
179
+ function generateVerificationToken(userId: string): string {
180
+ return jwt.sign(
181
+ { sub: userId, action: 'verify-email' },
182
+ process.env.JWT_SECRET!,
183
+ { expiresIn: '24h' }
184
+ );
185
+ }
186
+
187
+ // Password reset token
188
+ function generatePasswordResetToken(userId: string): string {
189
+ return jwt.sign(
190
+ { sub: userId, action: 'reset-password' },
191
+ process.env.JWT_SECRET!,
192
+ { expiresIn: '1h' }
193
+ );
194
+ }
195
+
196
+ // Verify with action check
197
+ function verifyActionToken(token: string, expectedAction: string) {
198
+ const payload = jwt.verify(token, process.env.JWT_SECRET!);
199
+
200
+ if (payload.action !== expectedAction) {
201
+ throw new AuthError('Invalid token');
202
+ }
203
+
204
+ return payload;
205
+ }
206
+ ```
207
+
208
+ ---
209
+
210
+ ## Input Protection
211
+
212
+ ### SEC-008: Sanitize user input
213
+
214
+ ```typescript
215
+ import DOMPurify from 'isomorphic-dompurify';
216
+
217
+ // For HTML content (if allowed)
218
+ function sanitizeHtml(input: string): string {
219
+ return DOMPurify.sanitize(input, {
220
+ ALLOWED_TAGS: ['b', 'i', 'em', 'strong', 'a', 'p'],
221
+ ALLOWED_ATTR: ['href'],
222
+ });
223
+ }
224
+
225
+ // For plain text - strip all HTML
226
+ function sanitizePlainText(input: string): string {
227
+ return DOMPurify.sanitize(input, { ALLOWED_TAGS: [] });
228
+ }
229
+ ```
230
+
231
+ ### SEC-009: Prevent NoSQL injection (if using MongoDB)
232
+
233
+ ```typescript
234
+ // BAD - user can inject operators
235
+ const user = await db.collection('users').findOne({
236
+ email: request.body.email, // { "$ne": null } would match all
237
+ });
238
+
239
+ // GOOD - validate type
240
+ const emailSchema = z.string().email();
241
+ const email = emailSchema.parse(request.body.email);
242
+
243
+ // Or sanitize
244
+ function sanitizeMongoInput(input: unknown): unknown {
245
+ if (typeof input === 'object' && input !== null) {
246
+ const keys = Object.keys(input);
247
+ if (keys.some(k => k.startsWith('$'))) {
248
+ throw new ValidationError('Invalid input');
249
+ }
250
+ }
251
+ return input;
252
+ }
253
+ ```
254
+
255
+ ### SEC-010: Rate limit sensitive endpoints
256
+
257
+ ```typescript
258
+ import rateLimit from '@fastify/rate-limit';
259
+
260
+ // Global rate limit
261
+ await fastify.register(rateLimit, {
262
+ max: 100,
263
+ timeWindow: '1 minute',
264
+ });
265
+
266
+ // Stricter for auth
267
+ fastify.register(async (instance) => {
268
+ await instance.register(rateLimit, {
269
+ max: 5,
270
+ timeWindow: '15 minutes',
271
+ keyGenerator: (request) => request.ip,
272
+ });
273
+
274
+ instance.post('/auth/login', loginHandler);
275
+ instance.post('/auth/register', registerHandler);
276
+ instance.post('/auth/forgot-password', forgotPasswordHandler);
277
+ });
278
+
279
+ // Even stricter for password reset
280
+ fastify.post('/auth/reset-password', {
281
+ config: {
282
+ rateLimit: {
283
+ max: 3,
284
+ timeWindow: '1 hour',
285
+ },
286
+ },
287
+ }, resetPasswordHandler);
288
+ ```
289
+
290
+ ---
291
+
292
+ ## Headers & CORS
293
+
294
+ ### SEC-011: Set security headers
295
+
296
+ ```typescript
297
+ import helmet from '@fastify/helmet';
298
+
299
+ await fastify.register(helmet, {
300
+ contentSecurityPolicy: {
301
+ directives: {
302
+ defaultSrc: ["'self'"],
303
+ scriptSrc: ["'self'"],
304
+ styleSrc: ["'self'", "'unsafe-inline'"],
305
+ imgSrc: ["'self'", 'data:', 'https:'],
306
+ },
307
+ },
308
+ hsts: {
309
+ maxAge: 31536000,
310
+ includeSubDomains: true,
311
+ },
312
+ });
313
+ ```
314
+
315
+ ### SEC-012: Configure CORS properly
316
+
317
+ ```typescript
318
+ import cors from '@fastify/cors';
319
+
320
+ await fastify.register(cors, {
321
+ origin: (origin, cb) => {
322
+ const allowedOrigins = [
323
+ 'https://app.example.com',
324
+ 'https://admin.example.com',
325
+ ];
326
+
327
+ if (process.env.NODE_ENV === 'development') {
328
+ allowedOrigins.push('http://localhost:3000');
329
+ }
330
+
331
+ if (!origin || allowedOrigins.includes(origin)) {
332
+ cb(null, true);
333
+ } else {
334
+ cb(new Error('Not allowed by CORS'), false);
335
+ }
336
+ },
337
+ credentials: true,
338
+ methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
339
+ });
340
+ ```
341
+
342
+ ---
343
+
344
+ ## Audit & Logging
345
+
346
+ ### SEC-013: Log security events
347
+
348
+ ```typescript
349
+ // Log authentication events
350
+ logger.info('Login successful', { userId, ip: request.ip });
351
+ logger.warn('Login failed', { email, ip: request.ip, reason: 'invalid_password' });
352
+ logger.warn('Account locked', { userId, ip: request.ip });
353
+
354
+ // Log authorization failures
355
+ logger.warn('Access denied', {
356
+ userId: request.user?.id,
357
+ resource: request.url,
358
+ permission: 'write:all',
359
+ });
360
+
361
+ // Log sensitive operations
362
+ logger.info('Password changed', { userId });
363
+ logger.info('User deleted', { deletedUserId, deletedBy: request.user.id });
364
+ ```
365
+
366
+ ### SEC-014: Never log sensitive data
367
+
368
+ ```typescript
369
+ // BAD
370
+ logger.info('Login', { email, password });
371
+ logger.info('Payment', { cardNumber, cvv });
372
+
373
+ // GOOD
374
+ logger.info('Login', { email });
375
+ logger.info('Payment', { cardLast4: card.slice(-4), amount });
376
+
377
+ // Redact in error serialization
378
+ function serializeError(error: Error) {
379
+ return {
380
+ message: error.message,
381
+ // Never include: stack (in prod), request body, headers
382
+ };
383
+ }
384
+ ```
@@ -0,0 +1,48 @@
1
+ # Stack Agents Registry
2
+ # Loaded at startup (~80 tokens)
3
+ # Full agents loaded on-demand when workspace matches
4
+
5
+ version: '1.0.0'
6
+
7
+ agents:
8
+ shared-ts:
9
+ description: TypeScript foundation - strict mode, patterns, zod schemas
10
+ triggers: ['*.ts', '*.tsx', 'typescript', 'types', 'zod', 'schema']
11
+ dependencies: []
12
+ priority: 1 # Load first (foundation)
13
+ token_budget: 800
14
+
15
+ nextjs:
16
+ description: Next.js App Router, Tailwind, shadcn/ui patterns
17
+ triggers: ['next.config', 'app/', 'pages/', 'tailwind', 'shadcn', '@/components']
18
+ dependencies: [shared-ts]
19
+ priority: 2
20
+ token_budget: 800
21
+
22
+ expo:
23
+ description: React Native + Expo SDK, navigation, native modules
24
+ triggers: ['app.json', 'expo', 'react-native', 'navigation', 'native']
25
+ dependencies: [shared-ts]
26
+ priority: 2
27
+ token_budget: 800
28
+
29
+ fastify:
30
+ description: Fastify APIs, BullMQ queues, RabbitMQ messaging
31
+ triggers: ['fastify', 'bullmq', 'rabbitmq', 'api/', 'routes/', 'queue']
32
+ dependencies: [shared-ts]
33
+ priority: 2
34
+ token_budget: 800
35
+
36
+ # Loading strategy:
37
+ # 1. This index always loaded (~80 tokens)
38
+ # 2. Orchestrator detects workspace agents from CLAUDE.md or package.json
39
+ # 3. Load shared-ts first if any TypeScript workspace
40
+ # 4. Load stack agents based on workspace triggers
41
+ # 5. Load rules on-demand when applying patterns (~200 tokens each)
42
+
43
+ # Token budget strategy:
44
+ # - Orchestrator: 500 tokens (always)
45
+ # - Per agent: 800 tokens (AGENT.md summary)
46
+ # - Per rule: 200 tokens (on-demand)
47
+ # - Max concurrent: 3 agents
48
+ # - Total max: 500 + (3 x 800) + (5 x 200) = 3,900 tokens