start-vibing 2.0.11 → 2.0.13
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 +177 -177
- package/dist/cli.js +19 -2
- package/package.json +42 -42
- package/template/.claude/CLAUDE.md +174 -174
- package/template/.claude/agents/01-orchestration/agent-selector.md +130 -130
- package/template/.claude/agents/01-orchestration/checkpoint-manager.md +142 -142
- package/template/.claude/agents/01-orchestration/context-manager.md +138 -138
- package/template/.claude/agents/01-orchestration/error-recovery.md +182 -182
- package/template/.claude/agents/01-orchestration/orchestrator.md +114 -114
- package/template/.claude/agents/01-orchestration/parallel-coordinator.md +141 -141
- package/template/.claude/agents/01-orchestration/task-decomposer.md +121 -121
- package/template/.claude/agents/01-orchestration/workflow-router.md +114 -114
- package/template/.claude/agents/02-typescript/bun-runtime-expert.md +197 -197
- package/template/.claude/agents/02-typescript/esm-resolver.md +193 -193
- package/template/.claude/agents/02-typescript/import-alias-enforcer.md +158 -158
- package/template/.claude/agents/02-typescript/ts-generics-helper.md +183 -183
- package/template/.claude/agents/02-typescript/ts-migration-helper.md +238 -238
- package/template/.claude/agents/02-typescript/ts-strict-checker.md +180 -180
- package/template/.claude/agents/02-typescript/ts-types-analyzer.md +199 -199
- package/template/.claude/agents/02-typescript/type-definition-writer.md +187 -187
- package/template/.claude/agents/02-typescript/zod-schema-designer.md +212 -212
- package/template/.claude/agents/02-typescript/zod-validator.md +158 -158
- package/template/.claude/agents/03-testing/playwright-assertions.md +265 -265
- package/template/.claude/agents/03-testing/playwright-e2e.md +247 -247
- package/template/.claude/agents/03-testing/playwright-fixtures.md +234 -234
- package/template/.claude/agents/03-testing/playwright-multi-viewport.md +256 -256
- package/template/.claude/agents/03-testing/playwright-page-objects.md +247 -247
- package/template/.claude/agents/03-testing/test-cleanup-manager.md +248 -248
- package/template/.claude/agents/03-testing/test-data-generator.md +254 -254
- package/template/.claude/agents/03-testing/tester-integration.md +278 -278
- package/template/.claude/agents/03-testing/tester-unit.md +207 -207
- package/template/.claude/agents/03-testing/vitest-config.md +287 -287
- package/template/.claude/agents/04-docker/container-health.md +255 -255
- package/template/.claude/agents/04-docker/deployment-validator.md +225 -225
- package/template/.claude/agents/04-docker/docker-compose-designer.md +281 -281
- package/template/.claude/agents/04-docker/docker-env-manager.md +235 -235
- package/template/.claude/agents/04-docker/docker-multi-stage.md +241 -241
- package/template/.claude/agents/04-docker/dockerfile-optimizer.md +208 -208
- package/template/.claude/agents/05-database/database-seeder.md +273 -273
- package/template/.claude/agents/05-database/mongodb-query-optimizer.md +230 -230
- package/template/.claude/agents/05-database/mongoose-aggregation.md +306 -306
- package/template/.claude/agents/05-database/mongoose-index-optimizer.md +182 -182
- package/template/.claude/agents/05-database/mongoose-schema-designer.md +267 -267
- package/template/.claude/agents/06-security/auth-session-validator.md +68 -68
- package/template/.claude/agents/06-security/input-sanitizer.md +80 -80
- package/template/.claude/agents/06-security/owasp-checker.md +97 -97
- package/template/.claude/agents/06-security/permission-auditor.md +100 -100
- package/template/.claude/agents/06-security/security-auditor.md +84 -84
- package/template/.claude/agents/06-security/sensitive-data-scanner.md +83 -83
- package/template/.claude/agents/07-documentation/api-documenter.md +136 -136
- package/template/.claude/agents/07-documentation/changelog-manager.md +105 -105
- package/template/.claude/agents/07-documentation/documenter.md +76 -76
- package/template/.claude/agents/07-documentation/domain-updater.md +81 -81
- package/template/.claude/agents/07-documentation/jsdoc-generator.md +114 -114
- package/template/.claude/agents/07-documentation/readme-generator.md +135 -135
- package/template/.claude/agents/08-git/branch-manager.md +58 -58
- package/template/.claude/agents/08-git/commit-manager.md +63 -63
- package/template/.claude/agents/08-git/pr-creator.md +76 -76
- package/template/.claude/agents/09-quality/code-reviewer.md +71 -71
- package/template/.claude/agents/09-quality/quality-checker.md +67 -67
- package/template/.claude/agents/10-research/best-practices-finder.md +89 -89
- package/template/.claude/agents/10-research/competitor-analyzer.md +106 -106
- package/template/.claude/agents/10-research/pattern-researcher.md +93 -93
- package/template/.claude/agents/10-research/research-cache-manager.md +76 -76
- package/template/.claude/agents/10-research/research-web.md +98 -98
- package/template/.claude/agents/10-research/tech-evaluator.md +101 -101
- package/template/.claude/agents/11-ui-ux/accessibility-auditor.md +136 -136
- package/template/.claude/agents/11-ui-ux/design-system-enforcer.md +125 -125
- package/template/.claude/agents/11-ui-ux/skeleton-generator.md +118 -118
- package/template/.claude/agents/11-ui-ux/ui-desktop.md +132 -132
- package/template/.claude/agents/11-ui-ux/ui-mobile.md +98 -98
- package/template/.claude/agents/11-ui-ux/ui-tablet.md +110 -110
- package/template/.claude/agents/12-performance/api-latency-analyzer.md +156 -156
- package/template/.claude/agents/12-performance/bundle-analyzer.md +113 -113
- package/template/.claude/agents/12-performance/memory-leak-detector.md +137 -137
- package/template/.claude/agents/12-performance/performance-profiler.md +115 -115
- package/template/.claude/agents/12-performance/query-optimizer.md +124 -124
- package/template/.claude/agents/12-performance/render-optimizer.md +154 -154
- package/template/.claude/agents/13-debugging/build-error-fixer.md +207 -207
- package/template/.claude/agents/13-debugging/debugger.md +149 -149
- package/template/.claude/agents/13-debugging/error-stack-analyzer.md +141 -141
- package/template/.claude/agents/13-debugging/network-debugger.md +208 -208
- package/template/.claude/agents/13-debugging/runtime-error-fixer.md +181 -181
- package/template/.claude/agents/13-debugging/type-error-resolver.md +185 -185
- package/template/.claude/agents/14-validation/final-validator.md +93 -93
- package/template/.claude/agents/_backup/analyzer.md +134 -134
- package/template/.claude/agents/_backup/code-reviewer.md +279 -279
- package/template/.claude/agents/_backup/commit-manager.md +219 -219
- package/template/.claude/agents/_backup/debugger.md +280 -280
- package/template/.claude/agents/_backup/documenter.md +237 -237
- package/template/.claude/agents/_backup/domain-updater.md +197 -197
- package/template/.claude/agents/_backup/final-validator.md +169 -169
- package/template/.claude/agents/_backup/orchestrator.md +149 -149
- package/template/.claude/agents/_backup/performance.md +232 -232
- package/template/.claude/agents/_backup/quality-checker.md +240 -240
- package/template/.claude/agents/_backup/research.md +315 -315
- package/template/.claude/agents/_backup/security-auditor.md +192 -192
- package/template/.claude/agents/_backup/tester.md +566 -566
- package/template/.claude/agents/_backup/ui-ux-reviewer.md +247 -247
- package/template/.claude/config/README.md +30 -30
- package/template/.claude/config/mcp-config.json +344 -344
- package/template/.claude/config/project-config.json +53 -53
- package/template/.claude/config/quality-gates.json +46 -46
- package/template/.claude/config/security-rules.json +45 -45
- package/template/.claude/config/testing-config.json +164 -164
- package/template/.claude/hooks/SETUP.md +126 -126
- package/template/.claude/hooks/run-hook.ts +176 -176
- package/template/.claude/hooks/stop-validator.ts +914 -824
- package/template/.claude/hooks/user-prompt-submit.ts +886 -886
- package/template/.claude/scripts/mcp-quick-install.ts +151 -151
- package/template/.claude/scripts/setup-mcps.ts +651 -651
- package/template/.claude/settings.json +275 -275
- package/template/.claude/skills/bun-runtime/SKILL.md +430 -430
- package/template/.claude/skills/codebase-knowledge/domains/claude-system.md +431 -431
- package/template/.claude/skills/codebase-knowledge/domains/mcp-integration.md +295 -295
- package/template/.claude/skills/debugging-patterns/SKILL.md +485 -485
- package/template/.claude/skills/docker-patterns/SKILL.md +555 -555
- package/template/.claude/skills/git-workflow/SKILL.md +454 -454
- package/template/.claude/skills/mongoose-patterns/SKILL.md +499 -499
- package/template/.claude/skills/nextjs-app-router/SKILL.md +327 -327
- package/template/.claude/skills/performance-patterns/SKILL.md +547 -547
- package/template/.claude/skills/playwright-automation/SKILL.md +438 -438
- package/template/.claude/skills/react-patterns/SKILL.md +389 -389
- package/template/.claude/skills/research-cache/SKILL.md +222 -222
- package/template/.claude/skills/shadcn-ui/SKILL.md +511 -511
- package/template/.claude/skills/tailwind-patterns/SKILL.md +465 -465
- package/template/.claude/skills/test-coverage/SKILL.md +467 -467
- package/template/.claude/skills/trpc-api/SKILL.md +434 -434
- package/template/.claude/skills/typescript-strict/SKILL.md +367 -367
- package/template/.claude/skills/zod-validation/SKILL.md +403 -403
- package/template/CLAUDE.md +117 -117
|
@@ -1,267 +1,267 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: mongoose-schema-designer
|
|
3
|
-
description: 'AUTOMATICALLY invoke BEFORE creating any database model. Triggers: new model, database design, schema needed. Designs properly typed Mongoose schemas with indexes. PROACTIVELY creates database models.'
|
|
4
|
-
model: sonnet
|
|
5
|
-
tools: Read, Write, Edit, Grep, Glob
|
|
6
|
-
skills: codebase-knowledge, mongoose-patterns
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Mongoose Schema Designer Agent
|
|
10
|
-
|
|
11
|
-
You design Mongoose schemas with proper typing and indexing.
|
|
12
|
-
|
|
13
|
-
## Schema Template
|
|
14
|
-
|
|
15
|
-
```typescript
|
|
16
|
-
// src/models/[entity].model.ts
|
|
17
|
-
import mongoose, { Schema, Document, Model } from 'mongoose';
|
|
18
|
-
|
|
19
|
-
// ============================================
|
|
20
|
-
// Types (in types/ folder)
|
|
21
|
-
// ============================================
|
|
22
|
-
// types/[entity].ts
|
|
23
|
-
export interface I[Entity] {
|
|
24
|
-
field1: string;
|
|
25
|
-
field2: number;
|
|
26
|
-
createdAt: Date;
|
|
27
|
-
updatedAt: Date;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
export interface I[Entity]Document extends I[Entity], Document {
|
|
31
|
-
// Instance methods
|
|
32
|
-
comparePassword(password: string): Promise<boolean>;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
export interface I[Entity]Model extends Model<I[Entity]Document> {
|
|
36
|
-
// Static methods
|
|
37
|
-
findByEmail(email: string): Promise<I[Entity]Document | null>;
|
|
38
|
-
}
|
|
39
|
-
|
|
40
|
-
// ============================================
|
|
41
|
-
// Schema (in models/ folder)
|
|
42
|
-
// ============================================
|
|
43
|
-
const [Entity]Schema = new Schema<I[Entity]Document, I[Entity]Model>(
|
|
44
|
-
{
|
|
45
|
-
field1: {
|
|
46
|
-
type: String,
|
|
47
|
-
required: [true, 'Field1 is required'],
|
|
48
|
-
trim: true,
|
|
49
|
-
maxlength: [100, 'Max 100 characters'],
|
|
50
|
-
},
|
|
51
|
-
field2: {
|
|
52
|
-
type: Number,
|
|
53
|
-
required: true,
|
|
54
|
-
min: [0, 'Must be positive'],
|
|
55
|
-
},
|
|
56
|
-
},
|
|
57
|
-
{
|
|
58
|
-
timestamps: true,
|
|
59
|
-
collection: '[entities]', // Explicit collection name
|
|
60
|
-
}
|
|
61
|
-
);
|
|
62
|
-
|
|
63
|
-
// ============================================
|
|
64
|
-
// Indexes
|
|
65
|
-
// ============================================
|
|
66
|
-
[Entity]Schema.index({ field1: 1 }, { unique: true });
|
|
67
|
-
[Entity]Schema.index({ createdAt: -1 });
|
|
68
|
-
[Entity]Schema.index({ field1: 'text', field2: 'text' }); // Text search
|
|
69
|
-
|
|
70
|
-
// ============================================
|
|
71
|
-
// Instance Methods
|
|
72
|
-
// ============================================
|
|
73
|
-
[Entity]Schema.methods.comparePassword = async function(
|
|
74
|
-
password: string
|
|
75
|
-
): Promise<boolean> {
|
|
76
|
-
return Bun.password.verify(password, this.password);
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
// ============================================
|
|
80
|
-
// Static Methods
|
|
81
|
-
// ============================================
|
|
82
|
-
[Entity]Schema.statics.findByEmail = async function(
|
|
83
|
-
email: string
|
|
84
|
-
): Promise<I[Entity]Document | null> {
|
|
85
|
-
return this.findOne({ email: email.toLowerCase() });
|
|
86
|
-
};
|
|
87
|
-
|
|
88
|
-
// ============================================
|
|
89
|
-
// Hooks
|
|
90
|
-
// ============================================
|
|
91
|
-
[Entity]Schema.pre('save', async function(next) {
|
|
92
|
-
if (this.isModified('password')) {
|
|
93
|
-
this.password = await Bun.password.hash(this.password);
|
|
94
|
-
}
|
|
95
|
-
next();
|
|
96
|
-
});
|
|
97
|
-
|
|
98
|
-
// ============================================
|
|
99
|
-
// Export Model
|
|
100
|
-
// ============================================
|
|
101
|
-
export const [Entity]Model = mongoose.model<I[Entity]Document, I[Entity]Model>(
|
|
102
|
-
'[Entity]',
|
|
103
|
-
[Entity]Schema
|
|
104
|
-
);
|
|
105
|
-
```
|
|
106
|
-
|
|
107
|
-
## User Model Example
|
|
108
|
-
|
|
109
|
-
```typescript
|
|
110
|
-
// src/models/user.model.ts
|
|
111
|
-
import mongoose, { Schema, Document, Model } from 'mongoose';
|
|
112
|
-
import type { IUser, IUserDocument, IUserModel } from '$types/user';
|
|
113
|
-
|
|
114
|
-
const UserSchema = new Schema<IUserDocument, IUserModel>(
|
|
115
|
-
{
|
|
116
|
-
email: {
|
|
117
|
-
type: String,
|
|
118
|
-
required: [true, 'Email is required'],
|
|
119
|
-
unique: true,
|
|
120
|
-
lowercase: true,
|
|
121
|
-
trim: true,
|
|
122
|
-
match: [/^\S+@\S+\.\S+$/, 'Invalid email format'],
|
|
123
|
-
},
|
|
124
|
-
password: {
|
|
125
|
-
type: String,
|
|
126
|
-
required: [true, 'Password is required'],
|
|
127
|
-
minlength: [8, 'Password must be at least 8 characters'],
|
|
128
|
-
select: false, // Don't include in queries by default
|
|
129
|
-
},
|
|
130
|
-
name: {
|
|
131
|
-
type: String,
|
|
132
|
-
required: [true, 'Name is required'],
|
|
133
|
-
trim: true,
|
|
134
|
-
maxlength: [100, 'Name cannot exceed 100 characters'],
|
|
135
|
-
},
|
|
136
|
-
role: {
|
|
137
|
-
type: String,
|
|
138
|
-
enum: ['admin', 'user', 'viewer'],
|
|
139
|
-
default: 'user',
|
|
140
|
-
},
|
|
141
|
-
isActive: {
|
|
142
|
-
type: Boolean,
|
|
143
|
-
default: true,
|
|
144
|
-
},
|
|
145
|
-
lastLoginAt: Date,
|
|
146
|
-
},
|
|
147
|
-
{
|
|
148
|
-
timestamps: true,
|
|
149
|
-
toJSON: {
|
|
150
|
-
transform: (_, ret) => {
|
|
151
|
-
delete ret.password;
|
|
152
|
-
delete ret.__v;
|
|
153
|
-
return ret;
|
|
154
|
-
},
|
|
155
|
-
},
|
|
156
|
-
}
|
|
157
|
-
);
|
|
158
|
-
|
|
159
|
-
// Indexes
|
|
160
|
-
UserSchema.index({ email: 1 }, { unique: true });
|
|
161
|
-
UserSchema.index({ role: 1, isActive: 1 });
|
|
162
|
-
UserSchema.index({ createdAt: -1 });
|
|
163
|
-
|
|
164
|
-
// Methods
|
|
165
|
-
UserSchema.methods.comparePassword = async function (password: string) {
|
|
166
|
-
return Bun.password.verify(password, this.password);
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// Statics
|
|
170
|
-
UserSchema.statics.findByEmail = function (email: string) {
|
|
171
|
-
return this.findOne({ email: email.toLowerCase() }).select('+password');
|
|
172
|
-
};
|
|
173
|
-
|
|
174
|
-
// Hooks
|
|
175
|
-
UserSchema.pre('save', async function (next) {
|
|
176
|
-
if (this.isModified('password')) {
|
|
177
|
-
this.password = await Bun.password.hash(this.password);
|
|
178
|
-
}
|
|
179
|
-
next();
|
|
180
|
-
});
|
|
181
|
-
|
|
182
|
-
export const UserModel = mongoose.model<IUserDocument, IUserModel>('User', UserSchema);
|
|
183
|
-
```
|
|
184
|
-
|
|
185
|
-
## Index Strategies
|
|
186
|
-
|
|
187
|
-
| Type | Syntax | Use Case |
|
|
188
|
-
| ------------ | ------------------------------ | ------------------------- |
|
|
189
|
-
| Single field | `{ field: 1 }` | Frequent queries on field |
|
|
190
|
-
| Compound | `{ field1: 1, field2: -1 }` | Multi-field queries |
|
|
191
|
-
| Unique | `{ unique: true }` | No duplicates |
|
|
192
|
-
| Text | `{ field: 'text' }` | Full-text search |
|
|
193
|
-
| TTL | `{ expireAfterSeconds: 3600 }` | Auto-expire documents |
|
|
194
|
-
| Sparse | `{ sparse: true }` | Only index non-null |
|
|
195
|
-
|
|
196
|
-
## Validation Patterns
|
|
197
|
-
|
|
198
|
-
```typescript
|
|
199
|
-
const schema = new Schema({
|
|
200
|
-
// Required with custom message
|
|
201
|
-
field: {
|
|
202
|
-
type: String,
|
|
203
|
-
required: [true, 'Field is required'],
|
|
204
|
-
},
|
|
205
|
-
|
|
206
|
-
// Enum validation
|
|
207
|
-
status: {
|
|
208
|
-
type: String,
|
|
209
|
-
enum: {
|
|
210
|
-
values: ['active', 'inactive'],
|
|
211
|
-
message: '{VALUE} is not a valid status',
|
|
212
|
-
},
|
|
213
|
-
},
|
|
214
|
-
|
|
215
|
-
// Custom validator
|
|
216
|
-
phone: {
|
|
217
|
-
type: String,
|
|
218
|
-
validate: {
|
|
219
|
-
validator: (v: string) => /^\+\d{10,15}$/.test(v),
|
|
220
|
-
message: 'Invalid phone format',
|
|
221
|
-
},
|
|
222
|
-
},
|
|
223
|
-
|
|
224
|
-
// Min/max
|
|
225
|
-
age: {
|
|
226
|
-
type: Number,
|
|
227
|
-
min: [0, 'Age must be positive'],
|
|
228
|
-
max: [150, 'Invalid age'],
|
|
229
|
-
},
|
|
230
|
-
});
|
|
231
|
-
```
|
|
232
|
-
|
|
233
|
-
## Output Format
|
|
234
|
-
|
|
235
|
-
```markdown
|
|
236
|
-
## Mongoose Schema Design
|
|
237
|
-
|
|
238
|
-
### Entity: [Name]
|
|
239
|
-
|
|
240
|
-
### Schema
|
|
241
|
-
|
|
242
|
-
\`\`\`typescript
|
|
243
|
-
[Full schema code]
|
|
244
|
-
\`\`\`
|
|
245
|
-
|
|
246
|
-
### Indexes
|
|
247
|
-
|
|
248
|
-
| Index | Fields | Type | Purpose |
|
|
249
|
-
| ------------- | --------- | ------ | ------------ |
|
|
250
|
-
| email_1 | email | unique | Fast lookup |
|
|
251
|
-
| createdAt\_-1 | createdAt | desc | Recent first |
|
|
252
|
-
|
|
253
|
-
### Methods
|
|
254
|
-
|
|
255
|
-
| Method | Type | Purpose |
|
|
256
|
-
| --------------- | -------- | --------------- |
|
|
257
|
-
| comparePassword | instance | Verify password |
|
|
258
|
-
| findByEmail | static | Find by email |
|
|
259
|
-
```
|
|
260
|
-
|
|
261
|
-
## Critical Rules
|
|
262
|
-
|
|
263
|
-
1. **TYPES IN types/** - Interfaces separate from schema
|
|
264
|
-
2. **EXPLICIT INDEXES** - Define for query patterns
|
|
265
|
-
3. **VALIDATION MESSAGES** - User-friendly errors
|
|
266
|
-
4. **HIDE SENSITIVE** - select: false for passwords
|
|
267
|
-
5. **HOOKS FOR LOGIC** - Pre/post save for transforms
|
|
1
|
+
---
|
|
2
|
+
name: mongoose-schema-designer
|
|
3
|
+
description: 'AUTOMATICALLY invoke BEFORE creating any database model. Triggers: new model, database design, schema needed. Designs properly typed Mongoose schemas with indexes. PROACTIVELY creates database models.'
|
|
4
|
+
model: sonnet
|
|
5
|
+
tools: Read, Write, Edit, Grep, Glob
|
|
6
|
+
skills: codebase-knowledge, mongoose-patterns
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Mongoose Schema Designer Agent
|
|
10
|
+
|
|
11
|
+
You design Mongoose schemas with proper typing and indexing.
|
|
12
|
+
|
|
13
|
+
## Schema Template
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
// src/models/[entity].model.ts
|
|
17
|
+
import mongoose, { Schema, Document, Model } from 'mongoose';
|
|
18
|
+
|
|
19
|
+
// ============================================
|
|
20
|
+
// Types (in types/ folder)
|
|
21
|
+
// ============================================
|
|
22
|
+
// types/[entity].ts
|
|
23
|
+
export interface I[Entity] {
|
|
24
|
+
field1: string;
|
|
25
|
+
field2: number;
|
|
26
|
+
createdAt: Date;
|
|
27
|
+
updatedAt: Date;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export interface I[Entity]Document extends I[Entity], Document {
|
|
31
|
+
// Instance methods
|
|
32
|
+
comparePassword(password: string): Promise<boolean>;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
export interface I[Entity]Model extends Model<I[Entity]Document> {
|
|
36
|
+
// Static methods
|
|
37
|
+
findByEmail(email: string): Promise<I[Entity]Document | null>;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
// ============================================
|
|
41
|
+
// Schema (in models/ folder)
|
|
42
|
+
// ============================================
|
|
43
|
+
const [Entity]Schema = new Schema<I[Entity]Document, I[Entity]Model>(
|
|
44
|
+
{
|
|
45
|
+
field1: {
|
|
46
|
+
type: String,
|
|
47
|
+
required: [true, 'Field1 is required'],
|
|
48
|
+
trim: true,
|
|
49
|
+
maxlength: [100, 'Max 100 characters'],
|
|
50
|
+
},
|
|
51
|
+
field2: {
|
|
52
|
+
type: Number,
|
|
53
|
+
required: true,
|
|
54
|
+
min: [0, 'Must be positive'],
|
|
55
|
+
},
|
|
56
|
+
},
|
|
57
|
+
{
|
|
58
|
+
timestamps: true,
|
|
59
|
+
collection: '[entities]', // Explicit collection name
|
|
60
|
+
}
|
|
61
|
+
);
|
|
62
|
+
|
|
63
|
+
// ============================================
|
|
64
|
+
// Indexes
|
|
65
|
+
// ============================================
|
|
66
|
+
[Entity]Schema.index({ field1: 1 }, { unique: true });
|
|
67
|
+
[Entity]Schema.index({ createdAt: -1 });
|
|
68
|
+
[Entity]Schema.index({ field1: 'text', field2: 'text' }); // Text search
|
|
69
|
+
|
|
70
|
+
// ============================================
|
|
71
|
+
// Instance Methods
|
|
72
|
+
// ============================================
|
|
73
|
+
[Entity]Schema.methods.comparePassword = async function(
|
|
74
|
+
password: string
|
|
75
|
+
): Promise<boolean> {
|
|
76
|
+
return Bun.password.verify(password, this.password);
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
// ============================================
|
|
80
|
+
// Static Methods
|
|
81
|
+
// ============================================
|
|
82
|
+
[Entity]Schema.statics.findByEmail = async function(
|
|
83
|
+
email: string
|
|
84
|
+
): Promise<I[Entity]Document | null> {
|
|
85
|
+
return this.findOne({ email: email.toLowerCase() });
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
// ============================================
|
|
89
|
+
// Hooks
|
|
90
|
+
// ============================================
|
|
91
|
+
[Entity]Schema.pre('save', async function(next) {
|
|
92
|
+
if (this.isModified('password')) {
|
|
93
|
+
this.password = await Bun.password.hash(this.password);
|
|
94
|
+
}
|
|
95
|
+
next();
|
|
96
|
+
});
|
|
97
|
+
|
|
98
|
+
// ============================================
|
|
99
|
+
// Export Model
|
|
100
|
+
// ============================================
|
|
101
|
+
export const [Entity]Model = mongoose.model<I[Entity]Document, I[Entity]Model>(
|
|
102
|
+
'[Entity]',
|
|
103
|
+
[Entity]Schema
|
|
104
|
+
);
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
## User Model Example
|
|
108
|
+
|
|
109
|
+
```typescript
|
|
110
|
+
// src/models/user.model.ts
|
|
111
|
+
import mongoose, { Schema, Document, Model } from 'mongoose';
|
|
112
|
+
import type { IUser, IUserDocument, IUserModel } from '$types/user';
|
|
113
|
+
|
|
114
|
+
const UserSchema = new Schema<IUserDocument, IUserModel>(
|
|
115
|
+
{
|
|
116
|
+
email: {
|
|
117
|
+
type: String,
|
|
118
|
+
required: [true, 'Email is required'],
|
|
119
|
+
unique: true,
|
|
120
|
+
lowercase: true,
|
|
121
|
+
trim: true,
|
|
122
|
+
match: [/^\S+@\S+\.\S+$/, 'Invalid email format'],
|
|
123
|
+
},
|
|
124
|
+
password: {
|
|
125
|
+
type: String,
|
|
126
|
+
required: [true, 'Password is required'],
|
|
127
|
+
minlength: [8, 'Password must be at least 8 characters'],
|
|
128
|
+
select: false, // Don't include in queries by default
|
|
129
|
+
},
|
|
130
|
+
name: {
|
|
131
|
+
type: String,
|
|
132
|
+
required: [true, 'Name is required'],
|
|
133
|
+
trim: true,
|
|
134
|
+
maxlength: [100, 'Name cannot exceed 100 characters'],
|
|
135
|
+
},
|
|
136
|
+
role: {
|
|
137
|
+
type: String,
|
|
138
|
+
enum: ['admin', 'user', 'viewer'],
|
|
139
|
+
default: 'user',
|
|
140
|
+
},
|
|
141
|
+
isActive: {
|
|
142
|
+
type: Boolean,
|
|
143
|
+
default: true,
|
|
144
|
+
},
|
|
145
|
+
lastLoginAt: Date,
|
|
146
|
+
},
|
|
147
|
+
{
|
|
148
|
+
timestamps: true,
|
|
149
|
+
toJSON: {
|
|
150
|
+
transform: (_, ret) => {
|
|
151
|
+
delete ret.password;
|
|
152
|
+
delete ret.__v;
|
|
153
|
+
return ret;
|
|
154
|
+
},
|
|
155
|
+
},
|
|
156
|
+
}
|
|
157
|
+
);
|
|
158
|
+
|
|
159
|
+
// Indexes
|
|
160
|
+
UserSchema.index({ email: 1 }, { unique: true });
|
|
161
|
+
UserSchema.index({ role: 1, isActive: 1 });
|
|
162
|
+
UserSchema.index({ createdAt: -1 });
|
|
163
|
+
|
|
164
|
+
// Methods
|
|
165
|
+
UserSchema.methods.comparePassword = async function (password: string) {
|
|
166
|
+
return Bun.password.verify(password, this.password);
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Statics
|
|
170
|
+
UserSchema.statics.findByEmail = function (email: string) {
|
|
171
|
+
return this.findOne({ email: email.toLowerCase() }).select('+password');
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
// Hooks
|
|
175
|
+
UserSchema.pre('save', async function (next) {
|
|
176
|
+
if (this.isModified('password')) {
|
|
177
|
+
this.password = await Bun.password.hash(this.password);
|
|
178
|
+
}
|
|
179
|
+
next();
|
|
180
|
+
});
|
|
181
|
+
|
|
182
|
+
export const UserModel = mongoose.model<IUserDocument, IUserModel>('User', UserSchema);
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
## Index Strategies
|
|
186
|
+
|
|
187
|
+
| Type | Syntax | Use Case |
|
|
188
|
+
| ------------ | ------------------------------ | ------------------------- |
|
|
189
|
+
| Single field | `{ field: 1 }` | Frequent queries on field |
|
|
190
|
+
| Compound | `{ field1: 1, field2: -1 }` | Multi-field queries |
|
|
191
|
+
| Unique | `{ unique: true }` | No duplicates |
|
|
192
|
+
| Text | `{ field: 'text' }` | Full-text search |
|
|
193
|
+
| TTL | `{ expireAfterSeconds: 3600 }` | Auto-expire documents |
|
|
194
|
+
| Sparse | `{ sparse: true }` | Only index non-null |
|
|
195
|
+
|
|
196
|
+
## Validation Patterns
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
const schema = new Schema({
|
|
200
|
+
// Required with custom message
|
|
201
|
+
field: {
|
|
202
|
+
type: String,
|
|
203
|
+
required: [true, 'Field is required'],
|
|
204
|
+
},
|
|
205
|
+
|
|
206
|
+
// Enum validation
|
|
207
|
+
status: {
|
|
208
|
+
type: String,
|
|
209
|
+
enum: {
|
|
210
|
+
values: ['active', 'inactive'],
|
|
211
|
+
message: '{VALUE} is not a valid status',
|
|
212
|
+
},
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
// Custom validator
|
|
216
|
+
phone: {
|
|
217
|
+
type: String,
|
|
218
|
+
validate: {
|
|
219
|
+
validator: (v: string) => /^\+\d{10,15}$/.test(v),
|
|
220
|
+
message: 'Invalid phone format',
|
|
221
|
+
},
|
|
222
|
+
},
|
|
223
|
+
|
|
224
|
+
// Min/max
|
|
225
|
+
age: {
|
|
226
|
+
type: Number,
|
|
227
|
+
min: [0, 'Age must be positive'],
|
|
228
|
+
max: [150, 'Invalid age'],
|
|
229
|
+
},
|
|
230
|
+
});
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Output Format
|
|
234
|
+
|
|
235
|
+
```markdown
|
|
236
|
+
## Mongoose Schema Design
|
|
237
|
+
|
|
238
|
+
### Entity: [Name]
|
|
239
|
+
|
|
240
|
+
### Schema
|
|
241
|
+
|
|
242
|
+
\`\`\`typescript
|
|
243
|
+
[Full schema code]
|
|
244
|
+
\`\`\`
|
|
245
|
+
|
|
246
|
+
### Indexes
|
|
247
|
+
|
|
248
|
+
| Index | Fields | Type | Purpose |
|
|
249
|
+
| ------------- | --------- | ------ | ------------ |
|
|
250
|
+
| email_1 | email | unique | Fast lookup |
|
|
251
|
+
| createdAt\_-1 | createdAt | desc | Recent first |
|
|
252
|
+
|
|
253
|
+
### Methods
|
|
254
|
+
|
|
255
|
+
| Method | Type | Purpose |
|
|
256
|
+
| --------------- | -------- | --------------- |
|
|
257
|
+
| comparePassword | instance | Verify password |
|
|
258
|
+
| findByEmail | static | Find by email |
|
|
259
|
+
```
|
|
260
|
+
|
|
261
|
+
## Critical Rules
|
|
262
|
+
|
|
263
|
+
1. **TYPES IN types/** - Interfaces separate from schema
|
|
264
|
+
2. **EXPLICIT INDEXES** - Define for query patterns
|
|
265
|
+
3. **VALIDATION MESSAGES** - User-friendly errors
|
|
266
|
+
4. **HIDE SENSITIVE** - select: false for passwords
|
|
267
|
+
5. **HOOKS FOR LOGIC** - Pre/post save for transforms
|
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
---
|
|
2
|
-
name: auth-session-validator
|
|
3
|
-
description: 'AUTOMATICALLY invoke when implementing auth or session code. Triggers: auth code, login, session, token, JWT. Validates authentication and session handling. PROACTIVELY ensures secure auth implementation.'
|
|
4
|
-
model: sonnet
|
|
5
|
-
tools: Read, Grep, Glob
|
|
6
|
-
skills: security-scan
|
|
7
|
-
---
|
|
8
|
-
|
|
9
|
-
# Auth Session Validator Agent
|
|
10
|
-
|
|
11
|
-
You validate authentication and session handling security.
|
|
12
|
-
|
|
13
|
-
## Auth Patterns to Verify
|
|
14
|
-
|
|
15
|
-
### Password Hashing
|
|
16
|
-
|
|
17
|
-
```typescript
|
|
18
|
-
// CORRECT - Use Bun.password
|
|
19
|
-
const hash = await Bun.password.hash(password);
|
|
20
|
-
const valid = await Bun.password.verify(password, hash);
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
### Session Token Generation
|
|
24
|
-
|
|
25
|
-
```typescript
|
|
26
|
-
// CORRECT - Cryptographically secure
|
|
27
|
-
import { randomBytes } from 'crypto';
|
|
28
|
-
const token = randomBytes(32).toString('hex');
|
|
29
|
-
```
|
|
30
|
-
|
|
31
|
-
### JWT Configuration
|
|
32
|
-
|
|
33
|
-
```typescript
|
|
34
|
-
// CORRECT - Short expiry, refresh tokens
|
|
35
|
-
const token = jwt.sign(payload, secret, { expiresIn: '15m' });
|
|
36
|
-
const refreshToken = jwt.sign({ userId }, refreshSecret, { expiresIn: '7d' });
|
|
37
|
-
```
|
|
38
|
-
|
|
39
|
-
## Checklist
|
|
40
|
-
|
|
41
|
-
- [ ] Passwords hashed with bcrypt/argon2/Bun.password
|
|
42
|
-
- [ ] Tokens cryptographically random
|
|
43
|
-
- [ ] JWT short expiry (< 1 hour)
|
|
44
|
-
- [ ] Refresh token rotation
|
|
45
|
-
- [ ] Session invalidation on logout
|
|
46
|
-
- [ ] HTTP-only cookies
|
|
47
|
-
- [ ] Secure flag on cookies
|
|
48
|
-
- [ ] SameSite cookie attribute
|
|
49
|
-
- [ ] Rate limiting on auth endpoints
|
|
50
|
-
- [ ] Account lockout after failures
|
|
51
|
-
|
|
52
|
-
## Cookie Security
|
|
53
|
-
|
|
54
|
-
```typescript
|
|
55
|
-
res.cookie('session', token, {
|
|
56
|
-
httpOnly: true, // No JS access
|
|
57
|
-
secure: true, // HTTPS only
|
|
58
|
-
sameSite: 'strict', // CSRF protection
|
|
59
|
-
maxAge: 3600000, // 1 hour
|
|
60
|
-
});
|
|
61
|
-
```
|
|
62
|
-
|
|
63
|
-
## Detection Commands
|
|
64
|
-
|
|
65
|
-
```bash
|
|
66
|
-
# Find auth-related code
|
|
67
|
-
grep -rn "login\|logout\|session\|token\|password" server/ --include="*.ts"
|
|
68
|
-
```
|
|
1
|
+
---
|
|
2
|
+
name: auth-session-validator
|
|
3
|
+
description: 'AUTOMATICALLY invoke when implementing auth or session code. Triggers: auth code, login, session, token, JWT. Validates authentication and session handling. PROACTIVELY ensures secure auth implementation.'
|
|
4
|
+
model: sonnet
|
|
5
|
+
tools: Read, Grep, Glob
|
|
6
|
+
skills: security-scan
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# Auth Session Validator Agent
|
|
10
|
+
|
|
11
|
+
You validate authentication and session handling security.
|
|
12
|
+
|
|
13
|
+
## Auth Patterns to Verify
|
|
14
|
+
|
|
15
|
+
### Password Hashing
|
|
16
|
+
|
|
17
|
+
```typescript
|
|
18
|
+
// CORRECT - Use Bun.password
|
|
19
|
+
const hash = await Bun.password.hash(password);
|
|
20
|
+
const valid = await Bun.password.verify(password, hash);
|
|
21
|
+
```
|
|
22
|
+
|
|
23
|
+
### Session Token Generation
|
|
24
|
+
|
|
25
|
+
```typescript
|
|
26
|
+
// CORRECT - Cryptographically secure
|
|
27
|
+
import { randomBytes } from 'crypto';
|
|
28
|
+
const token = randomBytes(32).toString('hex');
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
### JWT Configuration
|
|
32
|
+
|
|
33
|
+
```typescript
|
|
34
|
+
// CORRECT - Short expiry, refresh tokens
|
|
35
|
+
const token = jwt.sign(payload, secret, { expiresIn: '15m' });
|
|
36
|
+
const refreshToken = jwt.sign({ userId }, refreshSecret, { expiresIn: '7d' });
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## Checklist
|
|
40
|
+
|
|
41
|
+
- [ ] Passwords hashed with bcrypt/argon2/Bun.password
|
|
42
|
+
- [ ] Tokens cryptographically random
|
|
43
|
+
- [ ] JWT short expiry (< 1 hour)
|
|
44
|
+
- [ ] Refresh token rotation
|
|
45
|
+
- [ ] Session invalidation on logout
|
|
46
|
+
- [ ] HTTP-only cookies
|
|
47
|
+
- [ ] Secure flag on cookies
|
|
48
|
+
- [ ] SameSite cookie attribute
|
|
49
|
+
- [ ] Rate limiting on auth endpoints
|
|
50
|
+
- [ ] Account lockout after failures
|
|
51
|
+
|
|
52
|
+
## Cookie Security
|
|
53
|
+
|
|
54
|
+
```typescript
|
|
55
|
+
res.cookie('session', token, {
|
|
56
|
+
httpOnly: true, // No JS access
|
|
57
|
+
secure: true, // HTTPS only
|
|
58
|
+
sameSite: 'strict', // CSRF protection
|
|
59
|
+
maxAge: 3600000, // 1 hour
|
|
60
|
+
});
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
## Detection Commands
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
# Find auth-related code
|
|
67
|
+
grep -rn "login\|logout\|session\|token\|password" server/ --include="*.ts"
|
|
68
|
+
```
|