agentic-team-templates 0.3.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.
- package/README.md +280 -0
- package/bin/cli.js +5 -0
- package/package.json +47 -0
- package/src/index.js +521 -0
- package/templates/_shared/code-quality.md +162 -0
- package/templates/_shared/communication.md +114 -0
- package/templates/_shared/core-principles.md +62 -0
- package/templates/_shared/git-workflow.md +165 -0
- package/templates/_shared/security-fundamentals.md +173 -0
- package/templates/blockchain/.cursorrules/defi-patterns.md +520 -0
- package/templates/blockchain/.cursorrules/gas-optimization.md +339 -0
- package/templates/blockchain/.cursorrules/overview.md +130 -0
- package/templates/blockchain/.cursorrules/security.md +318 -0
- package/templates/blockchain/.cursorrules/smart-contracts.md +364 -0
- package/templates/blockchain/.cursorrules/testing.md +415 -0
- package/templates/blockchain/.cursorrules/web3-integration.md +538 -0
- package/templates/blockchain/CLAUDE.md +389 -0
- package/templates/cli-tools/.cursorrules/architecture.md +412 -0
- package/templates/cli-tools/.cursorrules/arguments.md +406 -0
- package/templates/cli-tools/.cursorrules/distribution.md +546 -0
- package/templates/cli-tools/.cursorrules/error-handling.md +455 -0
- package/templates/cli-tools/.cursorrules/overview.md +136 -0
- package/templates/cli-tools/.cursorrules/testing.md +537 -0
- package/templates/cli-tools/.cursorrules/user-experience.md +545 -0
- package/templates/cli-tools/CLAUDE.md +356 -0
- package/templates/data-engineering/.cursorrules/data-modeling.md +367 -0
- package/templates/data-engineering/.cursorrules/data-quality.md +455 -0
- package/templates/data-engineering/.cursorrules/overview.md +85 -0
- package/templates/data-engineering/.cursorrules/performance.md +339 -0
- package/templates/data-engineering/.cursorrules/pipeline-design.md +280 -0
- package/templates/data-engineering/.cursorrules/security.md +460 -0
- package/templates/data-engineering/.cursorrules/testing.md +452 -0
- package/templates/data-engineering/CLAUDE.md +974 -0
- package/templates/devops-sre/.cursorrules/capacity-planning.md +653 -0
- package/templates/devops-sre/.cursorrules/change-management.md +584 -0
- package/templates/devops-sre/.cursorrules/chaos-engineering.md +651 -0
- package/templates/devops-sre/.cursorrules/disaster-recovery.md +641 -0
- package/templates/devops-sre/.cursorrules/incident-management.md +565 -0
- package/templates/devops-sre/.cursorrules/observability.md +714 -0
- package/templates/devops-sre/.cursorrules/overview.md +230 -0
- package/templates/devops-sre/.cursorrules/postmortems.md +588 -0
- package/templates/devops-sre/.cursorrules/runbooks.md +760 -0
- package/templates/devops-sre/.cursorrules/slo-sli.md +617 -0
- package/templates/devops-sre/.cursorrules/toil-reduction.md +567 -0
- package/templates/devops-sre/CLAUDE.md +1007 -0
- package/templates/documentation/.cursorrules/adr.md +277 -0
- package/templates/documentation/.cursorrules/api-documentation.md +411 -0
- package/templates/documentation/.cursorrules/code-comments.md +253 -0
- package/templates/documentation/.cursorrules/maintenance.md +260 -0
- package/templates/documentation/.cursorrules/overview.md +82 -0
- package/templates/documentation/.cursorrules/readme-standards.md +306 -0
- package/templates/documentation/CLAUDE.md +120 -0
- package/templates/fullstack/.cursorrules/api-contracts.md +331 -0
- package/templates/fullstack/.cursorrules/architecture.md +298 -0
- package/templates/fullstack/.cursorrules/overview.md +109 -0
- package/templates/fullstack/.cursorrules/shared-types.md +348 -0
- package/templates/fullstack/.cursorrules/testing.md +386 -0
- package/templates/fullstack/CLAUDE.md +349 -0
- package/templates/ml-ai/.cursorrules/data-engineering.md +483 -0
- package/templates/ml-ai/.cursorrules/deployment.md +601 -0
- package/templates/ml-ai/.cursorrules/model-development.md +538 -0
- package/templates/ml-ai/.cursorrules/monitoring.md +658 -0
- package/templates/ml-ai/.cursorrules/overview.md +131 -0
- package/templates/ml-ai/.cursorrules/security.md +637 -0
- package/templates/ml-ai/.cursorrules/testing.md +678 -0
- package/templates/ml-ai/CLAUDE.md +1136 -0
- package/templates/mobile/.cursorrules/navigation.md +246 -0
- package/templates/mobile/.cursorrules/offline-first.md +302 -0
- package/templates/mobile/.cursorrules/overview.md +71 -0
- package/templates/mobile/.cursorrules/performance.md +345 -0
- package/templates/mobile/.cursorrules/testing.md +339 -0
- package/templates/mobile/CLAUDE.md +233 -0
- package/templates/platform-engineering/.cursorrules/ci-cd.md +778 -0
- package/templates/platform-engineering/.cursorrules/developer-experience.md +632 -0
- package/templates/platform-engineering/.cursorrules/infrastructure-as-code.md +600 -0
- package/templates/platform-engineering/.cursorrules/kubernetes.md +710 -0
- package/templates/platform-engineering/.cursorrules/observability.md +747 -0
- package/templates/platform-engineering/.cursorrules/overview.md +215 -0
- package/templates/platform-engineering/.cursorrules/security.md +855 -0
- package/templates/platform-engineering/.cursorrules/testing.md +878 -0
- package/templates/platform-engineering/CLAUDE.md +850 -0
- package/templates/utility-agent/.cursorrules/action-control.md +284 -0
- package/templates/utility-agent/.cursorrules/context-management.md +186 -0
- package/templates/utility-agent/.cursorrules/hallucination-prevention.md +253 -0
- package/templates/utility-agent/.cursorrules/overview.md +78 -0
- package/templates/utility-agent/.cursorrules/token-optimization.md +369 -0
- package/templates/utility-agent/CLAUDE.md +513 -0
- package/templates/web-backend/.cursorrules/api-design.md +255 -0
- package/templates/web-backend/.cursorrules/authentication.md +309 -0
- package/templates/web-backend/.cursorrules/database-patterns.md +298 -0
- package/templates/web-backend/.cursorrules/error-handling.md +366 -0
- package/templates/web-backend/.cursorrules/overview.md +69 -0
- package/templates/web-backend/.cursorrules/security.md +358 -0
- package/templates/web-backend/.cursorrules/testing.md +395 -0
- package/templates/web-backend/CLAUDE.md +366 -0
- package/templates/web-frontend/.cursorrules/accessibility.md +296 -0
- package/templates/web-frontend/.cursorrules/component-patterns.md +204 -0
- package/templates/web-frontend/.cursorrules/overview.md +72 -0
- package/templates/web-frontend/.cursorrules/performance.md +325 -0
- package/templates/web-frontend/.cursorrules/state-management.md +227 -0
- package/templates/web-frontend/.cursorrules/styling.md +271 -0
- package/templates/web-frontend/.cursorrules/testing.md +311 -0
- package/templates/web-frontend/CLAUDE.md +399 -0
|
@@ -0,0 +1,358 @@
|
|
|
1
|
+
# Backend Security
|
|
2
|
+
|
|
3
|
+
Security best practices specific to backend API development.
|
|
4
|
+
|
|
5
|
+
## Input Validation
|
|
6
|
+
|
|
7
|
+
### Validate at the Boundary
|
|
8
|
+
|
|
9
|
+
All external input must be validated before processing.
|
|
10
|
+
|
|
11
|
+
```ts
|
|
12
|
+
import { z } from 'zod';
|
|
13
|
+
|
|
14
|
+
// Define schema
|
|
15
|
+
const CreateUserSchema = z.object({
|
|
16
|
+
email: z.string().email().max(255),
|
|
17
|
+
name: z.string().min(1).max(100),
|
|
18
|
+
age: z.number().int().positive().max(150).optional(),
|
|
19
|
+
role: z.enum(['user', 'admin']).default('user'),
|
|
20
|
+
});
|
|
21
|
+
|
|
22
|
+
// Validate in route handler
|
|
23
|
+
app.post('/users', async (req, res, next) => {
|
|
24
|
+
const result = CreateUserSchema.safeParse(req.body);
|
|
25
|
+
|
|
26
|
+
if (!result.success) {
|
|
27
|
+
return res.status(422).json({
|
|
28
|
+
error: {
|
|
29
|
+
code: 'VALIDATION_ERROR',
|
|
30
|
+
message: 'Validation failed',
|
|
31
|
+
details: result.error.errors,
|
|
32
|
+
},
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
const user = await createUser(result.data);
|
|
37
|
+
res.status(201).json({ data: user });
|
|
38
|
+
});
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
### Sanitize Output
|
|
42
|
+
|
|
43
|
+
```ts
|
|
44
|
+
// Sanitize HTML content before storage
|
|
45
|
+
import DOMPurify from 'isomorphic-dompurify';
|
|
46
|
+
|
|
47
|
+
const sanitizeHtml = (html: string): string => {
|
|
48
|
+
return DOMPurify.sanitize(html, {
|
|
49
|
+
ALLOWED_TAGS: ['p', 'b', 'i', 'em', 'strong', 'a', 'ul', 'ol', 'li'],
|
|
50
|
+
ALLOWED_ATTR: ['href'],
|
|
51
|
+
});
|
|
52
|
+
};
|
|
53
|
+
|
|
54
|
+
// Remove sensitive fields before returning
|
|
55
|
+
const sanitizeUser = (user: User): PublicUser => {
|
|
56
|
+
const { passwordHash, resetToken, ...publicFields } = user;
|
|
57
|
+
return publicFields;
|
|
58
|
+
};
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Injection Prevention
|
|
62
|
+
|
|
63
|
+
### SQL Injection
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// ALWAYS use parameterized queries
|
|
67
|
+
|
|
68
|
+
// Good: Parameterized query
|
|
69
|
+
const users = await db.query(
|
|
70
|
+
'SELECT * FROM users WHERE email = $1 AND status = $2',
|
|
71
|
+
[email, status]
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
// Good: ORM with built-in protection
|
|
75
|
+
const users = await db.user.findMany({
|
|
76
|
+
where: { email, status },
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
// Bad: String interpolation
|
|
80
|
+
const users = await db.query(
|
|
81
|
+
`SELECT * FROM users WHERE email = '${email}'` // SQL INJECTION!
|
|
82
|
+
);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
### Command Injection
|
|
86
|
+
|
|
87
|
+
```ts
|
|
88
|
+
import { execFile } from 'child_process';
|
|
89
|
+
|
|
90
|
+
// Good: Use execFile with array arguments
|
|
91
|
+
execFile('convert', [inputPath, '-resize', '800x600', outputPath]);
|
|
92
|
+
|
|
93
|
+
// Bad: String concatenation
|
|
94
|
+
exec(`convert ${inputPath} -resize 800x600 ${outputPath}`); // INJECTION!
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
### NoSQL Injection
|
|
98
|
+
|
|
99
|
+
```ts
|
|
100
|
+
// Good: Validate input types
|
|
101
|
+
const findUser = async (query: unknown) => {
|
|
102
|
+
const { id } = z.object({ id: z.string().uuid() }).parse(query);
|
|
103
|
+
return db.collection('users').findOne({ _id: id });
|
|
104
|
+
};
|
|
105
|
+
|
|
106
|
+
// Bad: Accepting arbitrary objects
|
|
107
|
+
const findUser = async (query: any) => {
|
|
108
|
+
return db.collection('users').findOne(query); // Can inject $gt, $ne, etc.
|
|
109
|
+
};
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
## Rate Limiting
|
|
113
|
+
|
|
114
|
+
### Endpoint-Level Rate Limiting
|
|
115
|
+
|
|
116
|
+
```ts
|
|
117
|
+
import rateLimit from 'express-rate-limit';
|
|
118
|
+
|
|
119
|
+
// General API rate limit
|
|
120
|
+
const apiLimiter = rateLimit({
|
|
121
|
+
windowMs: 60 * 1000, // 1 minute
|
|
122
|
+
max: 100, // 100 requests per minute
|
|
123
|
+
standardHeaders: true,
|
|
124
|
+
legacyHeaders: false,
|
|
125
|
+
});
|
|
126
|
+
|
|
127
|
+
// Strict rate limit for auth endpoints
|
|
128
|
+
const authLimiter = rateLimit({
|
|
129
|
+
windowMs: 15 * 60 * 1000, // 15 minutes
|
|
130
|
+
max: 5, // 5 attempts
|
|
131
|
+
skipSuccessfulRequests: true,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Apply to routes
|
|
135
|
+
app.use('/api', apiLimiter);
|
|
136
|
+
app.post('/auth/login', authLimiter, loginHandler);
|
|
137
|
+
app.post('/auth/reset-password', authLimiter, resetPasswordHandler);
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
### User-Level Rate Limiting
|
|
141
|
+
|
|
142
|
+
```ts
|
|
143
|
+
// Track per-user limits for expensive operations
|
|
144
|
+
const userLimiter = async (userId: string, action: string, limit: number) => {
|
|
145
|
+
const key = `ratelimit:${userId}:${action}`;
|
|
146
|
+
const current = await redis.incr(key);
|
|
147
|
+
|
|
148
|
+
if (current === 1) {
|
|
149
|
+
await redis.expire(key, 3600); // 1 hour window
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
if (current > limit) {
|
|
153
|
+
throw new RateLimitError(`Too many ${action} requests`);
|
|
154
|
+
}
|
|
155
|
+
};
|
|
156
|
+
```
|
|
157
|
+
|
|
158
|
+
## Security Headers
|
|
159
|
+
|
|
160
|
+
```ts
|
|
161
|
+
import helmet from 'helmet';
|
|
162
|
+
|
|
163
|
+
app.use(helmet({
|
|
164
|
+
contentSecurityPolicy: {
|
|
165
|
+
directives: {
|
|
166
|
+
defaultSrc: ["'self'"],
|
|
167
|
+
scriptSrc: ["'self'"],
|
|
168
|
+
styleSrc: ["'self'", "'unsafe-inline'"],
|
|
169
|
+
imgSrc: ["'self'", 'data:', 'https:'],
|
|
170
|
+
connectSrc: ["'self'"],
|
|
171
|
+
frameSrc: ["'none'"],
|
|
172
|
+
objectSrc: ["'none'"],
|
|
173
|
+
},
|
|
174
|
+
},
|
|
175
|
+
hsts: {
|
|
176
|
+
maxAge: 31536000,
|
|
177
|
+
includeSubDomains: true,
|
|
178
|
+
preload: true,
|
|
179
|
+
},
|
|
180
|
+
referrerPolicy: { policy: 'strict-origin-when-cross-origin' },
|
|
181
|
+
}));
|
|
182
|
+
|
|
183
|
+
// CORS configuration
|
|
184
|
+
import cors from 'cors';
|
|
185
|
+
|
|
186
|
+
app.use(cors({
|
|
187
|
+
origin: process.env.ALLOWED_ORIGINS?.split(',') || false,
|
|
188
|
+
credentials: true,
|
|
189
|
+
methods: ['GET', 'POST', 'PUT', 'PATCH', 'DELETE'],
|
|
190
|
+
allowedHeaders: ['Content-Type', 'Authorization'],
|
|
191
|
+
}));
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
## Secrets Management
|
|
195
|
+
|
|
196
|
+
### Environment Variables
|
|
197
|
+
|
|
198
|
+
```ts
|
|
199
|
+
// config/env.ts
|
|
200
|
+
import { z } from 'zod';
|
|
201
|
+
|
|
202
|
+
const envSchema = z.object({
|
|
203
|
+
NODE_ENV: z.enum(['development', 'test', 'production']),
|
|
204
|
+
DATABASE_URL: z.string().url(),
|
|
205
|
+
JWT_SECRET: z.string().min(32),
|
|
206
|
+
API_KEY: z.string().min(16),
|
|
207
|
+
});
|
|
208
|
+
|
|
209
|
+
// Validate at startup
|
|
210
|
+
const env = envSchema.parse(process.env);
|
|
211
|
+
export { env };
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
### Never Log Secrets
|
|
215
|
+
|
|
216
|
+
```ts
|
|
217
|
+
// Bad
|
|
218
|
+
logger.info('Config loaded', { dbUrl: process.env.DATABASE_URL });
|
|
219
|
+
|
|
220
|
+
// Good
|
|
221
|
+
logger.info('Config loaded', {
|
|
222
|
+
database: process.env.DATABASE_URL?.split('@')[1], // Host only
|
|
223
|
+
environment: process.env.NODE_ENV,
|
|
224
|
+
});
|
|
225
|
+
```
|
|
226
|
+
|
|
227
|
+
### Rotate Secrets
|
|
228
|
+
|
|
229
|
+
Support secret rotation without downtime:
|
|
230
|
+
|
|
231
|
+
```ts
|
|
232
|
+
// Accept both old and new secrets during rotation
|
|
233
|
+
const verifyToken = (token: string): Payload => {
|
|
234
|
+
const secrets = [process.env.JWT_SECRET, process.env.JWT_SECRET_OLD].filter(Boolean);
|
|
235
|
+
|
|
236
|
+
for (const secret of secrets) {
|
|
237
|
+
try {
|
|
238
|
+
return jwt.verify(token, secret);
|
|
239
|
+
} catch {
|
|
240
|
+
continue;
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
throw new UnauthorizedError('Invalid token');
|
|
245
|
+
};
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
## Request Validation
|
|
249
|
+
|
|
250
|
+
### Validate Content-Type
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
app.use(express.json({
|
|
254
|
+
type: ['application/json'],
|
|
255
|
+
limit: '1mb',
|
|
256
|
+
}));
|
|
257
|
+
|
|
258
|
+
// Reject unexpected content types
|
|
259
|
+
app.use((req, res, next) => {
|
|
260
|
+
if (req.method !== 'GET' && !req.is('application/json')) {
|
|
261
|
+
return res.status(415).json({
|
|
262
|
+
error: { code: 'UNSUPPORTED_MEDIA_TYPE', message: 'Expected application/json' },
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
next();
|
|
266
|
+
});
|
|
267
|
+
```
|
|
268
|
+
|
|
269
|
+
### Limit Request Size
|
|
270
|
+
|
|
271
|
+
```ts
|
|
272
|
+
app.use(express.json({ limit: '1mb' }));
|
|
273
|
+
|
|
274
|
+
// Per-route limits for file uploads
|
|
275
|
+
app.post('/upload', express.raw({ limit: '10mb' }), uploadHandler);
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Logging for Security
|
|
279
|
+
|
|
280
|
+
### Audit Logging
|
|
281
|
+
|
|
282
|
+
```ts
|
|
283
|
+
// Log security-relevant events
|
|
284
|
+
const auditLog = async (event: AuditEvent) => {
|
|
285
|
+
await db.auditLog.create({
|
|
286
|
+
data: {
|
|
287
|
+
action: event.action,
|
|
288
|
+
userId: event.userId,
|
|
289
|
+
ip: event.ip,
|
|
290
|
+
userAgent: event.userAgent,
|
|
291
|
+
resource: event.resource,
|
|
292
|
+
resourceId: event.resourceId,
|
|
293
|
+
timestamp: new Date(),
|
|
294
|
+
metadata: event.metadata,
|
|
295
|
+
},
|
|
296
|
+
});
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// Usage
|
|
300
|
+
await auditLog({
|
|
301
|
+
action: 'USER_LOGIN',
|
|
302
|
+
userId: user.id,
|
|
303
|
+
ip: req.ip,
|
|
304
|
+
userAgent: req.headers['user-agent'],
|
|
305
|
+
});
|
|
306
|
+
|
|
307
|
+
await auditLog({
|
|
308
|
+
action: 'PERMISSION_CHANGED',
|
|
309
|
+
userId: admin.id,
|
|
310
|
+
ip: req.ip,
|
|
311
|
+
resource: 'user',
|
|
312
|
+
resourceId: targetUser.id,
|
|
313
|
+
metadata: { oldRole: 'user', newRole: 'admin' },
|
|
314
|
+
});
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
### Security Monitoring
|
|
318
|
+
|
|
319
|
+
Log patterns that might indicate attacks:
|
|
320
|
+
|
|
321
|
+
```ts
|
|
322
|
+
// Track failed login attempts
|
|
323
|
+
if (loginFailed) {
|
|
324
|
+
logger.warn({
|
|
325
|
+
event: 'LOGIN_FAILED',
|
|
326
|
+
email,
|
|
327
|
+
ip: req.ip,
|
|
328
|
+
userAgent: req.headers['user-agent'],
|
|
329
|
+
});
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
// Track suspicious patterns
|
|
333
|
+
if (validationErrors.length > 10) {
|
|
334
|
+
logger.warn({
|
|
335
|
+
event: 'SUSPICIOUS_INPUT',
|
|
336
|
+
ip: req.ip,
|
|
337
|
+
path: req.path,
|
|
338
|
+
errorCount: validationErrors.length,
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
```
|
|
342
|
+
|
|
343
|
+
## Security Checklist
|
|
344
|
+
|
|
345
|
+
Before deployment:
|
|
346
|
+
|
|
347
|
+
- [ ] All inputs validated with strict schemas
|
|
348
|
+
- [ ] Parameterized queries for all database operations
|
|
349
|
+
- [ ] Rate limiting on all endpoints
|
|
350
|
+
- [ ] Authentication required on protected routes
|
|
351
|
+
- [ ] Authorization checked for resource access
|
|
352
|
+
- [ ] Security headers configured (HSTS, CSP, etc.)
|
|
353
|
+
- [ ] CORS properly configured
|
|
354
|
+
- [ ] Secrets not in code or logs
|
|
355
|
+
- [ ] HTTPS enforced
|
|
356
|
+
- [ ] Error messages don't leak sensitive info
|
|
357
|
+
- [ ] Audit logging for security events
|
|
358
|
+
- [ ] Dependencies audited for vulnerabilities
|