@dzhechkov/skills-idea2prd 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.
- package/LICENSE +21 -0
- package/README.md +71 -0
- package/bin/cli.js +5 -0
- package/package.json +49 -0
- package/sources.json +25 -0
- package/src/cli.js +108 -0
- package/src/commands/doctor.js +340 -0
- package/src/commands/init.js +168 -0
- package/src/commands/list.js +146 -0
- package/src/commands/remove.js +182 -0
- package/src/commands/update.js +170 -0
- package/src/utils.js +154 -0
- package/templates/.claude/commands/idea2prd-manual.md +35 -0
- package/templates/.claude/skills/explore/SKILL.md +218 -0
- package/templates/.claude/skills/explore/references/questioning-techniques.md +151 -0
- package/templates/.claude/skills/explore/references/task-brief-templates.md +355 -0
- package/templates/.claude/skills/goap-research-ed25519/SKILL.md +418 -0
- package/templates/.claude/skills/goap-research-ed25519/references/ed25519-verification.md +658 -0
- package/templates/.claude/skills/goap-research-ed25519/references/research-actions.md +544 -0
- package/templates/.claude/skills/goap-research-ed25519/references/source-evaluation.md +560 -0
- package/templates/.claude/skills/goap-research-ed25519/scripts/ed25519_verifier.py +662 -0
- package/templates/.claude/skills/goap-research-ed25519/scripts/goap_planner.py +720 -0
- package/templates/.claude/skills/idea2prd-manual/SKILL.md +695 -0
- package/templates/.claude/skills/idea2prd-manual/references/adr-catalog.md +288 -0
- package/templates/.claude/skills/idea2prd-manual/references/c4-model.md +277 -0
- package/templates/.claude/skills/idea2prd-manual/references/completion-checklist-template.md +446 -0
- package/templates/.claude/skills/idea2prd-manual/references/ddd-patterns.md +261 -0
- package/templates/.claude/skills/idea2prd-manual/references/fitness-functions-catalog.md +414 -0
- package/templates/.claude/skills/idea2prd-manual/references/pseudocode-style.md +404 -0
- package/templates/.claude/skills/idea2prd-manual/scripts/ai_context_builder.py +491 -0
- package/templates/.claude/skills/idea2prd-manual/scripts/c4_generator.py +311 -0
- package/templates/.claude/skills/idea2prd-manual/scripts/fitness_validator.py +451 -0
- package/templates/.claude/skills/idea2prd-manual/scripts/pseudocode_generator.py +430 -0
- package/templates/.claude/skills/problem-solver-enhanced/SKILL.md +565 -0
|
@@ -0,0 +1,446 @@
|
|
|
1
|
+
# Completion Checklist Template
|
|
2
|
+
|
|
3
|
+
Reference файл для Phase 6: Completion Checklist.
|
|
4
|
+
Используется для генерации deployment-ready документации.
|
|
5
|
+
|
|
6
|
+
---
|
|
7
|
+
|
|
8
|
+
## Template Structure
|
|
9
|
+
|
|
10
|
+
```markdown
|
|
11
|
+
# Completion Checklist: {ProductName}
|
|
12
|
+
|
|
13
|
+
## 1. Development Environment Setup
|
|
14
|
+
|
|
15
|
+
### Required Tools
|
|
16
|
+
- [ ] Runtime: {runtime} (e.g., Node.js v20+, Python 3.11+)
|
|
17
|
+
- [ ] Container: Docker & Docker Compose
|
|
18
|
+
- [ ] Database: {database} (or Docker container)
|
|
19
|
+
- [ ] Cache: {cache} (if applicable)
|
|
20
|
+
- [ ] Message Queue: {queue} (if applicable)
|
|
21
|
+
|
|
22
|
+
### Local Setup Commands
|
|
23
|
+
\`\`\`bash
|
|
24
|
+
# Clone and install
|
|
25
|
+
git clone {repo-url}
|
|
26
|
+
cd {project-name}
|
|
27
|
+
{install-command}
|
|
28
|
+
|
|
29
|
+
# Environment setup
|
|
30
|
+
cp .env.example .env
|
|
31
|
+
# Edit .env with local credentials
|
|
32
|
+
|
|
33
|
+
# Database setup
|
|
34
|
+
{db-setup-commands}
|
|
35
|
+
|
|
36
|
+
# Run locally
|
|
37
|
+
{run-command}
|
|
38
|
+
\`\`\`
|
|
39
|
+
|
|
40
|
+
### Environment Variables
|
|
41
|
+
| Variable | Description | Example |
|
|
42
|
+
|----------|-------------|---------|
|
|
43
|
+
| DATABASE_URL | Database connection | postgresql://... |
|
|
44
|
+
| JWT_SECRET | JWT signing key | random-string |
|
|
45
|
+
| ... | ... | ... |
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
## 2. CI/CD Pipeline
|
|
50
|
+
|
|
51
|
+
### GitHub Actions Template
|
|
52
|
+
\`\`\`yaml
|
|
53
|
+
name: CI/CD Pipeline
|
|
54
|
+
|
|
55
|
+
on:
|
|
56
|
+
push:
|
|
57
|
+
branches: [main, develop]
|
|
58
|
+
pull_request:
|
|
59
|
+
branches: [main]
|
|
60
|
+
|
|
61
|
+
env:
|
|
62
|
+
REGISTRY: {registry}
|
|
63
|
+
IMAGE_NAME: {image-name}
|
|
64
|
+
|
|
65
|
+
jobs:
|
|
66
|
+
lint:
|
|
67
|
+
runs-on: ubuntu-latest
|
|
68
|
+
steps:
|
|
69
|
+
- uses: actions/checkout@v4
|
|
70
|
+
- name: Setup {runtime}
|
|
71
|
+
uses: {setup-action}
|
|
72
|
+
- run: {lint-command}
|
|
73
|
+
|
|
74
|
+
test:
|
|
75
|
+
runs-on: ubuntu-latest
|
|
76
|
+
services:
|
|
77
|
+
postgres:
|
|
78
|
+
image: postgres:15
|
|
79
|
+
env:
|
|
80
|
+
POSTGRES_PASSWORD: test
|
|
81
|
+
options: >-
|
|
82
|
+
--health-cmd pg_isready
|
|
83
|
+
--health-interval 10s
|
|
84
|
+
steps:
|
|
85
|
+
- uses: actions/checkout@v4
|
|
86
|
+
- name: Setup {runtime}
|
|
87
|
+
uses: {setup-action}
|
|
88
|
+
- run: {install-command}
|
|
89
|
+
- run: {test-command}
|
|
90
|
+
env:
|
|
91
|
+
DATABASE_URL: postgresql://postgres:test@localhost:5432/test
|
|
92
|
+
|
|
93
|
+
build:
|
|
94
|
+
needs: [lint, test]
|
|
95
|
+
runs-on: ubuntu-latest
|
|
96
|
+
steps:
|
|
97
|
+
- uses: actions/checkout@v4
|
|
98
|
+
- name: Build Docker image
|
|
99
|
+
run: |
|
|
100
|
+
docker build -t $REGISTRY/$IMAGE_NAME:${{ github.sha }} .
|
|
101
|
+
docker tag $REGISTRY/$IMAGE_NAME:${{ github.sha }} $REGISTRY/$IMAGE_NAME:latest
|
|
102
|
+
|
|
103
|
+
deploy-staging:
|
|
104
|
+
needs: build
|
|
105
|
+
if: github.ref == 'refs/heads/develop'
|
|
106
|
+
runs-on: ubuntu-latest
|
|
107
|
+
environment: staging
|
|
108
|
+
steps:
|
|
109
|
+
- name: Deploy to staging
|
|
110
|
+
run: |
|
|
111
|
+
# Platform-specific deploy command
|
|
112
|
+
|
|
113
|
+
deploy-production:
|
|
114
|
+
needs: build
|
|
115
|
+
if: github.ref == 'refs/heads/main'
|
|
116
|
+
runs-on: ubuntu-latest
|
|
117
|
+
environment: production
|
|
118
|
+
steps:
|
|
119
|
+
- name: Deploy to production
|
|
120
|
+
run: |
|
|
121
|
+
# Platform-specific deploy command
|
|
122
|
+
\`\`\`
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 3. Infrastructure
|
|
127
|
+
|
|
128
|
+
### Docker Compose (Development)
|
|
129
|
+
\`\`\`yaml
|
|
130
|
+
version: '3.8'
|
|
131
|
+
|
|
132
|
+
services:
|
|
133
|
+
app:
|
|
134
|
+
build: .
|
|
135
|
+
ports:
|
|
136
|
+
- "{port}:{port}"
|
|
137
|
+
environment:
|
|
138
|
+
- NODE_ENV=development
|
|
139
|
+
- DATABASE_URL=postgresql://user:pass@postgres:5432/db
|
|
140
|
+
depends_on:
|
|
141
|
+
- postgres
|
|
142
|
+
volumes:
|
|
143
|
+
- .:/app
|
|
144
|
+
- /app/node_modules
|
|
145
|
+
|
|
146
|
+
postgres:
|
|
147
|
+
image: postgres:15
|
|
148
|
+
environment:
|
|
149
|
+
POSTGRES_USER: user
|
|
150
|
+
POSTGRES_PASSWORD: pass
|
|
151
|
+
POSTGRES_DB: db
|
|
152
|
+
volumes:
|
|
153
|
+
- postgres_data:/var/lib/postgresql/data
|
|
154
|
+
ports:
|
|
155
|
+
- "5432:5432"
|
|
156
|
+
|
|
157
|
+
# Add if needed: redis, rabbitmq, etc.
|
|
158
|
+
|
|
159
|
+
volumes:
|
|
160
|
+
postgres_data:
|
|
161
|
+
\`\`\`
|
|
162
|
+
|
|
163
|
+
### Dockerfile
|
|
164
|
+
\`\`\`dockerfile
|
|
165
|
+
# Build stage
|
|
166
|
+
FROM {base-image} AS builder
|
|
167
|
+
WORKDIR /app
|
|
168
|
+
COPY {dependency-files} .
|
|
169
|
+
RUN {install-command}
|
|
170
|
+
COPY . .
|
|
171
|
+
RUN {build-command}
|
|
172
|
+
|
|
173
|
+
# Production stage
|
|
174
|
+
FROM {prod-image}
|
|
175
|
+
WORKDIR /app
|
|
176
|
+
COPY --from=builder /app/{build-output} .
|
|
177
|
+
EXPOSE {port}
|
|
178
|
+
CMD [{start-command}]
|
|
179
|
+
\`\`\`
|
|
180
|
+
|
|
181
|
+
### Kubernetes Manifests (Production)
|
|
182
|
+
|
|
183
|
+
#### deployment.yaml
|
|
184
|
+
\`\`\`yaml
|
|
185
|
+
apiVersion: apps/v1
|
|
186
|
+
kind: Deployment
|
|
187
|
+
metadata:
|
|
188
|
+
name: {app-name}
|
|
189
|
+
spec:
|
|
190
|
+
replicas: 3
|
|
191
|
+
selector:
|
|
192
|
+
matchLabels:
|
|
193
|
+
app: {app-name}
|
|
194
|
+
template:
|
|
195
|
+
metadata:
|
|
196
|
+
labels:
|
|
197
|
+
app: {app-name}
|
|
198
|
+
spec:
|
|
199
|
+
containers:
|
|
200
|
+
- name: {app-name}
|
|
201
|
+
image: {registry}/{image}:latest
|
|
202
|
+
ports:
|
|
203
|
+
- containerPort: {port}
|
|
204
|
+
env:
|
|
205
|
+
- name: DATABASE_URL
|
|
206
|
+
valueFrom:
|
|
207
|
+
secretKeyRef:
|
|
208
|
+
name: {app-name}-secrets
|
|
209
|
+
key: database-url
|
|
210
|
+
resources:
|
|
211
|
+
requests:
|
|
212
|
+
memory: "256Mi"
|
|
213
|
+
cpu: "250m"
|
|
214
|
+
limits:
|
|
215
|
+
memory: "512Mi"
|
|
216
|
+
cpu: "500m"
|
|
217
|
+
livenessProbe:
|
|
218
|
+
httpGet:
|
|
219
|
+
path: /health
|
|
220
|
+
port: {port}
|
|
221
|
+
initialDelaySeconds: 30
|
|
222
|
+
periodSeconds: 10
|
|
223
|
+
readinessProbe:
|
|
224
|
+
httpGet:
|
|
225
|
+
path: /ready
|
|
226
|
+
port: {port}
|
|
227
|
+
initialDelaySeconds: 5
|
|
228
|
+
periodSeconds: 5
|
|
229
|
+
\`\`\`
|
|
230
|
+
|
|
231
|
+
#### service.yaml
|
|
232
|
+
\`\`\`yaml
|
|
233
|
+
apiVersion: v1
|
|
234
|
+
kind: Service
|
|
235
|
+
metadata:
|
|
236
|
+
name: {app-name}
|
|
237
|
+
spec:
|
|
238
|
+
selector:
|
|
239
|
+
app: {app-name}
|
|
240
|
+
ports:
|
|
241
|
+
- port: 80
|
|
242
|
+
targetPort: {port}
|
|
243
|
+
type: ClusterIP
|
|
244
|
+
\`\`\`
|
|
245
|
+
|
|
246
|
+
#### hpa.yaml
|
|
247
|
+
\`\`\`yaml
|
|
248
|
+
apiVersion: autoscaling/v2
|
|
249
|
+
kind: HorizontalPodAutoscaler
|
|
250
|
+
metadata:
|
|
251
|
+
name: {app-name}
|
|
252
|
+
spec:
|
|
253
|
+
scaleTargetRef:
|
|
254
|
+
apiVersion: apps/v1
|
|
255
|
+
kind: Deployment
|
|
256
|
+
name: {app-name}
|
|
257
|
+
minReplicas: 2
|
|
258
|
+
maxReplicas: 10
|
|
259
|
+
metrics:
|
|
260
|
+
- type: Resource
|
|
261
|
+
resource:
|
|
262
|
+
name: cpu
|
|
263
|
+
target:
|
|
264
|
+
type: Utilization
|
|
265
|
+
averageUtilization: 70
|
|
266
|
+
\`\`\`
|
|
267
|
+
|
|
268
|
+
---
|
|
269
|
+
|
|
270
|
+
## 4. Monitoring & Observability
|
|
271
|
+
|
|
272
|
+
### Logging Configuration
|
|
273
|
+
\`\`\`json
|
|
274
|
+
{
|
|
275
|
+
"level": "info",
|
|
276
|
+
"format": "json",
|
|
277
|
+
"fields": {
|
|
278
|
+
"service": "{app-name}",
|
|
279
|
+
"version": "{version}",
|
|
280
|
+
"environment": "{env}"
|
|
281
|
+
},
|
|
282
|
+
"redact": ["password", "token", "secret", "authorization"]
|
|
283
|
+
}
|
|
284
|
+
\`\`\`
|
|
285
|
+
|
|
286
|
+
### Prometheus Metrics
|
|
287
|
+
\`\`\`
|
|
288
|
+
# Application metrics to expose:
|
|
289
|
+
|
|
290
|
+
# HTTP
|
|
291
|
+
http_requests_total{method, path, status}
|
|
292
|
+
http_request_duration_seconds{method, path}
|
|
293
|
+
http_request_size_bytes{method, path}
|
|
294
|
+
http_response_size_bytes{method, path}
|
|
295
|
+
|
|
296
|
+
# Database
|
|
297
|
+
db_query_duration_seconds{query_type, table}
|
|
298
|
+
db_connections_active
|
|
299
|
+
db_connections_idle
|
|
300
|
+
|
|
301
|
+
# Business
|
|
302
|
+
{domain}_events_total{event_type}
|
|
303
|
+
{domain}_operations_total{operation, status}
|
|
304
|
+
{domain}_processing_duration_seconds{operation}
|
|
305
|
+
\`\`\`
|
|
306
|
+
|
|
307
|
+
### OpenTelemetry Setup
|
|
308
|
+
\`\`\`javascript
|
|
309
|
+
// Example: Node.js OTEL setup
|
|
310
|
+
const { NodeSDK } = require('@opentelemetry/sdk-node');
|
|
311
|
+
const { getNodeAutoInstrumentations } = require('@opentelemetry/auto-instrumentations-node');
|
|
312
|
+
|
|
313
|
+
const sdk = new NodeSDK({
|
|
314
|
+
serviceName: '{app-name}',
|
|
315
|
+
instrumentations: [getNodeAutoInstrumentations()],
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
sdk.start();
|
|
319
|
+
\`\`\`
|
|
320
|
+
|
|
321
|
+
### Alerting Rules
|
|
322
|
+
| Alert | Condition | Severity | Action |
|
|
323
|
+
|-------|-----------|----------|--------|
|
|
324
|
+
| HighErrorRate | error_rate > 1% for 5m | Critical | Page on-call |
|
|
325
|
+
| HighLatency | p95 > 500ms for 5m | Warning | Slack notification |
|
|
326
|
+
| DatabaseDown | db_up == 0 for 1m | Critical | Page on-call |
|
|
327
|
+
| HighCPU | cpu_usage > 80% for 10m | Warning | Slack notification |
|
|
328
|
+
| HighMemory | memory_usage > 80% for 10m | Warning | Slack notification |
|
|
329
|
+
| QueueBacklog | queue_size > 1000 for 5m | Warning | Slack notification |
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## 5. Security Checklist
|
|
334
|
+
|
|
335
|
+
### Authentication & Authorization
|
|
336
|
+
- [ ] OAuth 2.0 / JWT implemented
|
|
337
|
+
- [ ] Token expiration: Access (15min), Refresh (7d)
|
|
338
|
+
- [ ] RBAC roles defined and enforced
|
|
339
|
+
- [ ] Rate limiting on auth endpoints (10 req/min)
|
|
340
|
+
- [ ] Account lockout after 5 failed attempts
|
|
341
|
+
|
|
342
|
+
### Data Protection
|
|
343
|
+
- [ ] Passwords: bcrypt with cost factor 12+
|
|
344
|
+
- [ ] PII: Encrypted at rest (AES-256)
|
|
345
|
+
- [ ] Transit: TLS 1.3 required
|
|
346
|
+
- [ ] Secrets: In vault/secret manager, not in code
|
|
347
|
+
- [ ] Logs: PII redacted
|
|
348
|
+
|
|
349
|
+
### OWASP Top 10 Mitigations
|
|
350
|
+
| Vulnerability | Mitigation | Status |
|
|
351
|
+
|---------------|------------|--------|
|
|
352
|
+
| Injection | Parameterized queries, input validation | [ ] |
|
|
353
|
+
| Broken Auth | Session management, MFA option | [ ] |
|
|
354
|
+
| Sensitive Data | Encryption, minimal data retention | [ ] |
|
|
355
|
+
| XXE | Disable external entities | [ ] |
|
|
356
|
+
| Broken Access | RBAC, resource ownership checks | [ ] |
|
|
357
|
+
| Misconfig | Security headers, defaults review | [ ] |
|
|
358
|
+
| XSS | Output encoding, CSP | [ ] |
|
|
359
|
+
| Insecure Deser | Type checking, signature validation | [ ] |
|
|
360
|
+
| Vulnerable Deps | Automated scanning, updates | [ ] |
|
|
361
|
+
| Logging | Structured logs, audit trail | [ ] |
|
|
362
|
+
|
|
363
|
+
### Security Headers
|
|
364
|
+
\`\`\`
|
|
365
|
+
Strict-Transport-Security: max-age=31536000; includeSubDomains
|
|
366
|
+
Content-Security-Policy: default-src 'self'
|
|
367
|
+
X-Content-Type-Options: nosniff
|
|
368
|
+
X-Frame-Options: DENY
|
|
369
|
+
X-XSS-Protection: 1; mode=block
|
|
370
|
+
Referrer-Policy: strict-origin-when-cross-origin
|
|
371
|
+
\`\`\`
|
|
372
|
+
|
|
373
|
+
---
|
|
374
|
+
|
|
375
|
+
## 6. Documentation Checklist
|
|
376
|
+
|
|
377
|
+
### Generated (from idea2prd)
|
|
378
|
+
- [x] PRD.md - Product requirements
|
|
379
|
+
- [x] DDD Strategic - Bounded contexts, domain events
|
|
380
|
+
- [x] DDD Tactical - Aggregates, entities, value objects
|
|
381
|
+
- [x] ADRs - Architecture decisions
|
|
382
|
+
- [x] C4 Diagrams - System architecture
|
|
383
|
+
- [x] Pseudocode - Algorithm specifications
|
|
384
|
+
- [x] Test Scenarios - Gherkin specs
|
|
385
|
+
|
|
386
|
+
### Additional Required
|
|
387
|
+
- [ ] API Documentation (OpenAPI/Swagger)
|
|
388
|
+
- [ ] README.md with quick start
|
|
389
|
+
- [ ] CONTRIBUTING.md for contributors
|
|
390
|
+
- [ ] CHANGELOG.md for version history
|
|
391
|
+
- [ ] Runbook for operations
|
|
392
|
+
- [ ] Incident response playbook
|
|
393
|
+
|
|
394
|
+
---
|
|
395
|
+
|
|
396
|
+
## 7. Pre-Launch Checklist
|
|
397
|
+
|
|
398
|
+
### Performance
|
|
399
|
+
- [ ] Load testing completed (target: {X} req/s)
|
|
400
|
+
- [ ] P95 latency < {target}ms verified
|
|
401
|
+
- [ ] Database queries optimized (no N+1)
|
|
402
|
+
- [ ] Indexes created for common queries
|
|
403
|
+
- [ ] Caching strategy implemented
|
|
404
|
+
- [ ] CDN configured for static assets
|
|
405
|
+
|
|
406
|
+
### Reliability
|
|
407
|
+
- [ ] Health check endpoint: GET /health
|
|
408
|
+
- [ ] Readiness endpoint: GET /ready
|
|
409
|
+
- [ ] Graceful shutdown implemented
|
|
410
|
+
- [ ] Circuit breakers for external calls
|
|
411
|
+
- [ ] Retry policies with exponential backoff
|
|
412
|
+
- [ ] Dead letter queue for failed messages
|
|
413
|
+
|
|
414
|
+
### Observability
|
|
415
|
+
- [ ] Structured logging enabled
|
|
416
|
+
- [ ] Metrics endpoint exposed
|
|
417
|
+
- [ ] Tracing configured
|
|
418
|
+
- [ ] Dashboards created
|
|
419
|
+
- [ ] Alerts configured
|
|
420
|
+
|
|
421
|
+
### Operations
|
|
422
|
+
- [ ] Runbook documented
|
|
423
|
+
- [ ] On-call rotation scheduled
|
|
424
|
+
- [ ] Rollback procedure tested
|
|
425
|
+
- [ ] Backup/restore verified
|
|
426
|
+
- [ ] Disaster recovery plan
|
|
427
|
+
|
|
428
|
+
### Launch
|
|
429
|
+
- [ ] Staging environment validated
|
|
430
|
+
- [ ] Production environment prepared
|
|
431
|
+
- [ ] Feature flags configured
|
|
432
|
+
- [ ] Gradual rollout plan (1% → 10% → 50% → 100%)
|
|
433
|
+
- [ ] Communication plan ready
|
|
434
|
+
- [ ] Support team briefed
|
|
435
|
+
|
|
436
|
+
---
|
|
437
|
+
|
|
438
|
+
## Generation Instructions
|
|
439
|
+
|
|
440
|
+
When generating COMPLETION_CHECKLIST.md:
|
|
441
|
+
|
|
442
|
+
1. Replace all `{placeholders}` with actual values from PRD/ADRs
|
|
443
|
+
2. Remove sections not applicable to the project
|
|
444
|
+
3. Add project-specific items as needed
|
|
445
|
+
4. Ensure all commands are valid for chosen tech stack
|
|
446
|
+
5. Verify all file paths match project structure
|
|
@@ -0,0 +1,261 @@
|
|
|
1
|
+
# DDD Patterns Reference
|
|
2
|
+
|
|
3
|
+
Справочник по Domain-Driven Design для idea2prd skills.
|
|
4
|
+
|
|
5
|
+
## Strategic DDD
|
|
6
|
+
|
|
7
|
+
### Bounded Context
|
|
8
|
+
|
|
9
|
+
**Определение:** Логическая граница, внутри которой domain model консистентна.
|
|
10
|
+
|
|
11
|
+
**Как идентифицировать:**
|
|
12
|
+
- Разные команды → разные contexts
|
|
13
|
+
- Разный Ubiquitous Language → разные contexts
|
|
14
|
+
- Разная скорость изменений → разные contexts
|
|
15
|
+
- Разный data ownership → разные contexts
|
|
16
|
+
|
|
17
|
+
**Template:**
|
|
18
|
+
```markdown
|
|
19
|
+
### [Context Name]
|
|
20
|
+
**Responsibility:** [What this context owns]
|
|
21
|
+
**Type:** Core | Supporting | Generic
|
|
22
|
+
**Key Concepts:** [Aggregates, main entities]
|
|
23
|
+
**Team:** [Ownership]
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
### Context Map Patterns
|
|
29
|
+
|
|
30
|
+
| Pattern | Description | When to Use |
|
|
31
|
+
|---------|-------------|-------------|
|
|
32
|
+
| **Partnership** | Совместная эволюция | Одна команда, тесная связь |
|
|
33
|
+
| **Shared Kernel** | Общая часть модели | Очень тесная связь |
|
|
34
|
+
| **Customer-Supplier** | U поставляет, D потребляет | Ясная зависимость |
|
|
35
|
+
| **Conformist** | D принимает модель U как есть | Нет влияния на U |
|
|
36
|
+
| **Anticorruption Layer** | D защищается от U | Legacy, внешние API |
|
|
37
|
+
| **Open Host Service** | U публикует API для всех | Public API |
|
|
38
|
+
| **Published Language** | Стандартный формат обмена | Интеграции |
|
|
39
|
+
|
|
40
|
+
**Mermaid Template:**
|
|
41
|
+
```mermaid
|
|
42
|
+
graph LR
|
|
43
|
+
A[Context A] -->|"U/D: Published Language"| B[Context B]
|
|
44
|
+
B -.->|"ACL"| C[External API]
|
|
45
|
+
```
|
|
46
|
+
|
|
47
|
+
---
|
|
48
|
+
|
|
49
|
+
### Subdomain Classification
|
|
50
|
+
|
|
51
|
+
| Type | Characteristics | Strategy |
|
|
52
|
+
|------|-----------------|----------|
|
|
53
|
+
| **Core** | Конкурентное преимущество | Build in-house, best devs |
|
|
54
|
+
| **Supporting** | Нужно для Core, не уникально | Build or buy |
|
|
55
|
+
| **Generic** | Commodity | Buy/SaaS |
|
|
56
|
+
|
|
57
|
+
---
|
|
58
|
+
|
|
59
|
+
## Tactical DDD
|
|
60
|
+
|
|
61
|
+
### Aggregate
|
|
62
|
+
|
|
63
|
+
**Определение:** Кластер объектов с единой границей консистентности.
|
|
64
|
+
|
|
65
|
+
**Rules:**
|
|
66
|
+
- Транзакция = один aggregate
|
|
67
|
+
- Внешние ссылки только по ID
|
|
68
|
+
- Aggregate Root обеспечивает инварианты
|
|
69
|
+
|
|
70
|
+
**Template:**
|
|
71
|
+
```typescript
|
|
72
|
+
class Order { // Aggregate Root
|
|
73
|
+
private id: OrderId;
|
|
74
|
+
private items: OrderItem[]; // Entity внутри
|
|
75
|
+
private status: OrderStatus; // Value Object
|
|
76
|
+
|
|
77
|
+
addItem(product: ProductId, qty: Quantity): void {
|
|
78
|
+
if (this.status !== OrderStatus.DRAFT) {
|
|
79
|
+
throw new Error("Cannot modify");
|
|
80
|
+
}
|
|
81
|
+
// ...
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
**Size:** Max 5-7 entities per aggregate.
|
|
87
|
+
|
|
88
|
+
---
|
|
89
|
+
|
|
90
|
+
### Entity
|
|
91
|
+
|
|
92
|
+
**Определение:** Объект с уникальной идентичностью.
|
|
93
|
+
|
|
94
|
+
**Characteristics:**
|
|
95
|
+
- Has ID
|
|
96
|
+
- Mutable
|
|
97
|
+
- Equality by ID
|
|
98
|
+
|
|
99
|
+
```typescript
|
|
100
|
+
class User {
|
|
101
|
+
readonly id: UserId;
|
|
102
|
+
private email: Email;
|
|
103
|
+
|
|
104
|
+
equals(other: User): boolean {
|
|
105
|
+
return this.id.equals(other.id);
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
### Value Object
|
|
113
|
+
|
|
114
|
+
**Определение:** Объект без идентичности, определяется атрибутами.
|
|
115
|
+
|
|
116
|
+
**Characteristics:**
|
|
117
|
+
- Immutable
|
|
118
|
+
- Equality by attributes
|
|
119
|
+
- Self-validating
|
|
120
|
+
|
|
121
|
+
**Common Value Objects:**
|
|
122
|
+
```typescript
|
|
123
|
+
// Money
|
|
124
|
+
class Money {
|
|
125
|
+
constructor(readonly amount: number, readonly currency: Currency) {
|
|
126
|
+
if (amount < 0) throw new Error("Negative");
|
|
127
|
+
}
|
|
128
|
+
add(other: Money): Money { /* returns new */ }
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Email
|
|
132
|
+
class Email {
|
|
133
|
+
constructor(readonly value: string) {
|
|
134
|
+
if (!isValid(value)) throw new Error("Invalid");
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// DateRange
|
|
139
|
+
class DateRange {
|
|
140
|
+
constructor(readonly start: Date, readonly end: Date) {
|
|
141
|
+
if (end < start) throw new Error("Invalid range");
|
|
142
|
+
}
|
|
143
|
+
}
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
---
|
|
147
|
+
|
|
148
|
+
### Domain Event
|
|
149
|
+
|
|
150
|
+
**Определение:** Сигнал о значимом событии в домене.
|
|
151
|
+
|
|
152
|
+
**Naming:** Past tense (OrderPlaced, UserRegistered)
|
|
153
|
+
|
|
154
|
+
**Template:**
|
|
155
|
+
```typescript
|
|
156
|
+
interface DomainEvent {
|
|
157
|
+
occurredAt: Date;
|
|
158
|
+
aggregateId: string;
|
|
159
|
+
aggregateType: string;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
class OrderPlaced implements DomainEvent {
|
|
163
|
+
constructor(
|
|
164
|
+
readonly orderId: OrderId,
|
|
165
|
+
readonly customerId: CustomerId,
|
|
166
|
+
readonly items: OrderItemDto[],
|
|
167
|
+
readonly totalAmount: Money,
|
|
168
|
+
readonly occurredAt: Date = new Date()
|
|
169
|
+
) {}
|
|
170
|
+
}
|
|
171
|
+
```
|
|
172
|
+
|
|
173
|
+
---
|
|
174
|
+
|
|
175
|
+
### Repository
|
|
176
|
+
|
|
177
|
+
**Определение:** Абстракция для persistence агрегатов.
|
|
178
|
+
|
|
179
|
+
**Rules:**
|
|
180
|
+
- One per Aggregate Root
|
|
181
|
+
- Returns Aggregate, not raw data
|
|
182
|
+
|
|
183
|
+
**Template:**
|
|
184
|
+
```typescript
|
|
185
|
+
interface OrderRepository {
|
|
186
|
+
findById(id: OrderId): Promise<Order | null>;
|
|
187
|
+
findByCustomer(id: CustomerId): Promise<Order[]>;
|
|
188
|
+
save(order: Order): Promise<void>;
|
|
189
|
+
delete(id: OrderId): Promise<void>;
|
|
190
|
+
}
|
|
191
|
+
```
|
|
192
|
+
|
|
193
|
+
---
|
|
194
|
+
|
|
195
|
+
### Domain Service
|
|
196
|
+
|
|
197
|
+
**Определение:** Логика, не принадлежащая конкретному Aggregate.
|
|
198
|
+
|
|
199
|
+
**When to use:**
|
|
200
|
+
- Операция с несколькими Aggregates
|
|
201
|
+
- Stateless operations
|
|
202
|
+
|
|
203
|
+
```typescript
|
|
204
|
+
class PricingService {
|
|
205
|
+
calculateDiscount(customer: Customer, order: Order): Money {
|
|
206
|
+
// Cross-aggregate logic
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
---
|
|
212
|
+
|
|
213
|
+
### Application Service
|
|
214
|
+
|
|
215
|
+
**Определение:** Orchestration layer (use cases).
|
|
216
|
+
|
|
217
|
+
**Responsibilities:**
|
|
218
|
+
- Use case coordination
|
|
219
|
+
- Transaction management
|
|
220
|
+
- Authorization
|
|
221
|
+
- DTO transformation
|
|
222
|
+
|
|
223
|
+
```typescript
|
|
224
|
+
class OrderService {
|
|
225
|
+
async placeOrder(cmd: PlaceOrderCmd): Promise<OrderId> {
|
|
226
|
+
const customer = await this.customerRepo.findById(cmd.customerId);
|
|
227
|
+
const order = Order.create(customer, cmd.items);
|
|
228
|
+
await this.orderRepo.save(order);
|
|
229
|
+
await this.eventBus.publish(order.domainEvents);
|
|
230
|
+
return order.id;
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
```
|
|
234
|
+
|
|
235
|
+
---
|
|
236
|
+
|
|
237
|
+
## Quick Reference
|
|
238
|
+
|
|
239
|
+
### Aggregate Design Checklist
|
|
240
|
+
|
|
241
|
+
- [ ] Clear invariants identified
|
|
242
|
+
- [ ] Single Aggregate Root
|
|
243
|
+
- [ ] ≤7 entities
|
|
244
|
+
- [ ] External refs by ID only
|
|
245
|
+
- [ ] One aggregate per transaction
|
|
246
|
+
|
|
247
|
+
### Bounded Context Checklist
|
|
248
|
+
|
|
249
|
+
- [ ] Clear responsibility defined
|
|
250
|
+
- [ ] Ubiquitous Language documented
|
|
251
|
+
- [ ] Type classified (Core/Supporting/Generic)
|
|
252
|
+
- [ ] Relationships mapped
|
|
253
|
+
- [ ] Team ownership assigned
|
|
254
|
+
|
|
255
|
+
### Event Design Checklist
|
|
256
|
+
|
|
257
|
+
- [ ] Past tense naming
|
|
258
|
+
- [ ] Includes aggregate ID
|
|
259
|
+
- [ ] Immutable payload
|
|
260
|
+
- [ ] Contains all needed data
|
|
261
|
+
- [ ] Timestamp included
|