contextos-agents 2.1.0 → 2.2.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/.agents/adapters/aider/export.js +2 -2
- package/.agents/adapters/claude/export.js +53 -2
- package/.agents/adapters/drift-detector.js +6 -3
- package/.agents/adapters/pure-compiler.js +18 -6
- package/.agents/ctx.js +13 -8
- package/.agents/plugins.js +347 -26
- package/.agents/profiles.js +32 -11
- package/README.md +38 -3
- package/bin/commands/hook.js +50 -12
- package/bin/commands/scan.js +10 -3
- package/bin/index.js +165 -53
- package/bin/lib/git-snapshot.js +70 -43
- package/bin/lib/scan.js +108 -27
- package/bin/lib/ui.js +140 -0
- package/catalog/skills/adapters/EXAMPLES.md +19 -0
- package/catalog/skills/adapters/SKILL.md +101 -0
- package/catalog/skills/adapters/TROUBLESHOOTING.md +7 -0
- package/catalog/skills/adapters/VALIDATION.json +12 -0
- package/catalog/skills/adapters/skill.yaml +13 -0
- package/catalog/skills/api-design/EXAMPLES.md +91 -0
- package/catalog/skills/api-design/SKILL.md +63 -0
- package/catalog/skills/api-design/TROUBLESHOOTING.md +54 -0
- package/catalog/skills/api-design/VALIDATION.json +11 -0
- package/catalog/skills/api-design/skill.yaml +14 -0
- package/catalog/skills/architecture-diagrams/SKILL.md +108 -0
- package/catalog/skills/architecture-diagrams/VALIDATION.json +12 -0
- package/catalog/skills/architecture-diagrams/skill.yaml +9 -0
- package/catalog/skills/brutalist-design/EXAMPLES.md +59 -0
- package/catalog/skills/brutalist-design/SKILL.md +150 -0
- package/catalog/skills/brutalist-design/VALIDATION.json +12 -0
- package/catalog/skills/brutalist-design/skill.yaml +10 -0
- package/catalog/skills/ci-cd/EXAMPLES.md +79 -0
- package/catalog/skills/ci-cd/SKILL.md +69 -0
- package/catalog/skills/ci-cd/TROUBLESHOOTING.md +52 -0
- package/catalog/skills/ci-cd/VALIDATION.json +11 -0
- package/catalog/skills/ci-cd/skill.yaml +13 -0
- package/catalog/skills/database/EXAMPLES.md +74 -0
- package/catalog/skills/database/SKILL.md +101 -0
- package/catalog/skills/database/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/database/VALIDATION.json +11 -0
- package/catalog/skills/database/skill.yaml +14 -0
- package/catalog/skills/ddd/EXAMPLES.md +42 -0
- package/catalog/skills/ddd/SKILL.md +247 -0
- package/catalog/skills/ddd/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ddd/VALIDATION.json +12 -0
- package/catalog/skills/ddd/skill.yaml +14 -0
- package/catalog/skills/decisions/EXAMPLES.md +35 -0
- package/catalog/skills/decisions/SKILL.md +90 -0
- package/catalog/skills/decisions/TROUBLESHOOTING.md +13 -0
- package/catalog/skills/decisions/VALIDATION.json +12 -0
- package/catalog/skills/decisions/skill.yaml +13 -0
- package/catalog/skills/docker/EXAMPLES.md +56 -0
- package/catalog/skills/docker/SKILL.md +169 -0
- package/catalog/skills/docker/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/docker/VALIDATION.json +11 -0
- package/catalog/skills/docker/skill.yaml +13 -0
- package/catalog/skills/fastapi/EXAMPLES.md +36 -0
- package/catalog/skills/fastapi/SKILL.md +171 -0
- package/catalog/skills/fastapi/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/fastapi/VALIDATION.json +12 -0
- package/catalog/skills/fastapi/skill.yaml +14 -0
- package/catalog/skills/generators/EXAMPLES.md +19 -0
- package/catalog/skills/generators/SKILL.md +110 -0
- package/catalog/skills/generators/TROUBLESHOOTING.md +7 -0
- package/catalog/skills/generators/VALIDATION.json +12 -0
- package/catalog/skills/generators/skill.yaml +22 -0
- package/catalog/skills/generators/templates/API.md +77 -0
- package/catalog/skills/generators/templates/ARCHITECTURE.md +70 -0
- package/catalog/skills/generators/templates/DATABASE.md +42 -0
- package/catalog/skills/generators/templates/DECISION.md +46 -0
- package/catalog/skills/generators/templates/PRD.md +67 -0
- package/catalog/skills/generators/templates/PROJECT_GRAPH.md +56 -0
- package/catalog/skills/generators/templates/ROADMAP.md +51 -0
- package/catalog/skills/generators/templates/TASKS.md +43 -0
- package/catalog/skills/generators/templates/UI.md +73 -0
- package/catalog/skills/graphify/EXAMPLES.md +73 -0
- package/catalog/skills/graphify/SKILL.md +130 -0
- package/catalog/skills/graphify/VALIDATION.json +12 -0
- package/catalog/skills/graphify/skill.yaml +13 -0
- package/catalog/skills/impeccable-design/EXAMPLES.md +26 -0
- package/catalog/skills/impeccable-design/SKILL.md +201 -0
- package/catalog/skills/impeccable-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/impeccable-design/VALIDATION.json +12 -0
- package/catalog/skills/impeccable-design/skill.yaml +15 -0
- package/catalog/skills/interview-me/SKILL.md +97 -0
- package/catalog/skills/interview-me/VALIDATION.json +12 -0
- package/catalog/skills/interview-me/skill.yaml +9 -0
- package/catalog/skills/microservices/EXAMPLES.md +38 -0
- package/catalog/skills/microservices/SKILL.md +164 -0
- package/catalog/skills/microservices/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/microservices/VALIDATION.json +12 -0
- package/catalog/skills/microservices/skill.yaml +14 -0
- package/catalog/skills/minimalist-design/EXAMPLES.md +58 -0
- package/catalog/skills/minimalist-design/SKILL.md +113 -0
- package/catalog/skills/minimalist-design/VALIDATION.json +12 -0
- package/catalog/skills/minimalist-design/skill.yaml +10 -0
- package/catalog/skills/nestjs/EXAMPLES.md +40 -0
- package/catalog/skills/nestjs/SKILL.md +139 -0
- package/catalog/skills/nestjs/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/nestjs/VALIDATION.json +12 -0
- package/catalog/skills/nestjs/skill.yaml +14 -0
- package/catalog/skills/nextjs/EXAMPLES.md +40 -0
- package/catalog/skills/nextjs/SKILL.md +163 -0
- package/catalog/skills/nextjs/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/nextjs/VALIDATION.json +12 -0
- package/catalog/skills/nextjs/skill.yaml +14 -0
- package/catalog/skills/node/EXAMPLES.md +80 -0
- package/catalog/skills/node/SKILL.md +128 -0
- package/catalog/skills/node/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/node/VALIDATION.json +12 -0
- package/catalog/skills/node/skill.yaml +14 -0
- package/catalog/skills/performance/EXAMPLES.md +30 -0
- package/catalog/skills/performance/SKILL.md +75 -0
- package/catalog/skills/performance/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/performance/VALIDATION.json +12 -0
- package/catalog/skills/performance/skill.yaml +14 -0
- package/catalog/skills/react/EXAMPLES.md +79 -0
- package/catalog/skills/react/SKILL.md +132 -0
- package/catalog/skills/react/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/react/VALIDATION.json +12 -0
- package/catalog/skills/react/skill.yaml +14 -0
- package/catalog/skills/react-best-practices/SKILL.md +158 -0
- package/catalog/skills/react-best-practices/VALIDATION.json +12 -0
- package/catalog/skills/react-best-practices/skill.yaml +13 -0
- package/catalog/skills/redesign-audit/SKILL.md +117 -0
- package/catalog/skills/redesign-audit/VALIDATION.json +12 -0
- package/catalog/skills/redesign-audit/skill.yaml +9 -0
- package/catalog/skills/security-audit/EXAMPLES.md +79 -0
- package/catalog/skills/security-audit/SKILL.md +91 -0
- package/catalog/skills/security-audit/TROUBLESHOOTING.md +46 -0
- package/catalog/skills/security-audit/VALIDATION.json +11 -0
- package/catalog/skills/security-audit/skill.yaml +14 -0
- package/catalog/skills/soft-design/EXAMPLES.md +51 -0
- package/catalog/skills/soft-design/SKILL.md +108 -0
- package/catalog/skills/soft-design/VALIDATION.json +12 -0
- package/catalog/skills/soft-design/skill.yaml +10 -0
- package/catalog/skills/state-management/EXAMPLES.md +56 -0
- package/catalog/skills/state-management/SKILL.md +168 -0
- package/catalog/skills/state-management/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/state-management/VALIDATION.json +11 -0
- package/catalog/skills/state-management/skill.yaml +14 -0
- package/catalog/skills/subagent-orchestrator/SKILL.md +117 -0
- package/catalog/skills/subagent-orchestrator/VALIDATION.json +12 -0
- package/catalog/skills/subagent-orchestrator/skill.yaml +9 -0
- package/catalog/skills/system-design/EXAMPLES.md +75 -0
- package/catalog/skills/system-design/SKILL.md +419 -0
- package/catalog/skills/system-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/system-design/VALIDATION.json +12 -0
- package/catalog/skills/system-design/skill.yaml +14 -0
- package/catalog/skills/terraform/EXAMPLES.md +74 -0
- package/catalog/skills/terraform/SKILL.md +55 -0
- package/catalog/skills/terraform/TROUBLESHOOTING.md +53 -0
- package/catalog/skills/terraform/VALIDATION.json +11 -0
- package/catalog/skills/terraform/skill.yaml +14 -0
- package/catalog/skills/testing/EXAMPLES.md +122 -0
- package/catalog/skills/testing/SKILL.md +70 -0
- package/catalog/skills/testing/TROUBLESHOOTING.md +18 -0
- package/catalog/skills/testing/VALIDATION.json +11 -0
- package/catalog/skills/testing/skill.yaml +14 -0
- package/catalog/skills/typescript/EXAMPLES.md +64 -0
- package/catalog/skills/typescript/SKILL.md +112 -0
- package/catalog/skills/typescript/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/typescript/VALIDATION.json +12 -0
- package/catalog/skills/typescript/skill.yaml +14 -0
- package/catalog/skills/ui-design/EXAMPLES.md +21 -0
- package/catalog/skills/ui-design/SKILL.md +124 -0
- package/catalog/skills/ui-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ui-design/VALIDATION.json +12 -0
- package/catalog/skills/ui-design/skill.yaml +16 -0
- package/catalog/skills/ui-ux-pro/EXAMPLES.md +62 -0
- package/catalog/skills/ui-ux-pro/SKILL.md +418 -0
- package/catalog/skills/ui-ux-pro/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ui-ux-pro/VALIDATION.json +12 -0
- package/catalog/skills/ui-ux-pro/skill.yaml +14 -0
- package/catalog/skills/ux-design/EXAMPLES.md +36 -0
- package/catalog/skills/ux-design/SKILL.md +116 -0
- package/catalog/skills/ux-design/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/ux-design/VALIDATION.json +12 -0
- package/catalog/skills/ux-design/skill.yaml +16 -0
- package/catalog/skills/vercel-optimize/SKILL.md +83 -0
- package/catalog/skills/vercel-optimize/VALIDATION.json +12 -0
- package/catalog/skills/vercel-optimize/scripts/collect-signals.mjs +131 -0
- package/catalog/skills/vercel-optimize/scripts/gate-investigations.mjs +142 -0
- package/catalog/skills/vercel-optimize/scripts/merge-signals.mjs +143 -0
- package/catalog/skills/vercel-optimize/scripts/scan-codebase.mjs +174 -0
- package/catalog/skills/vercel-optimize/skill.yaml +15 -0
- package/catalog/skills/web-accessibility/EXAMPLES.md +39 -0
- package/catalog/skills/web-accessibility/SKILL.md +151 -0
- package/catalog/skills/web-accessibility/TROUBLESHOOTING.md +19 -0
- package/catalog/skills/web-accessibility/VALIDATION.json +12 -0
- package/catalog/skills/web-accessibility/skill.yaml +14 -0
- package/package.json +3 -2
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: system-design
|
|
3
|
+
description: >
|
|
4
|
+
Scalable architecture skill based on the System Design Primer.
|
|
5
|
+
Before designing any backend, reason about load balancers, caching,
|
|
6
|
+
DB partitioning, CAP theorem, and microservices trade-offs.
|
|
7
|
+
Adapted for Serverless/Edge, Next.js App Router, BFF, and DDD patterns.
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# system-design
|
|
11
|
+
|
|
12
|
+
## Overview
|
|
13
|
+
|
|
14
|
+
Scalable system architecture blueprint based on the System Design Primer and DDIA. Enforces load balancing, multi-tier caching (Redis, CDN), database partitioning, CAP theorem tradeoffs, and rate limiting before code is written.
|
|
15
|
+
|
|
16
|
+
## When to Use
|
|
17
|
+
|
|
18
|
+
Activate during the PLAN phase of any backend service, API design, database schema creation, or scalability optimization.
|
|
19
|
+
|
|
20
|
+
## Rules & Patterns
|
|
21
|
+
|
|
22
|
+
Based on [donnemartin/system-design-primer](https://github.com/donnemartin/system-design-primer) - the most starred system design resource on GitHub.
|
|
23
|
+
|
|
24
|
+
## Core Principle
|
|
25
|
+
|
|
26
|
+
> **Everything is a trade-off.** Before writing a single line of backend code, reason through the system at scale. A flat monolith that works now fails at 10× load.
|
|
27
|
+
|
|
28
|
+
---
|
|
29
|
+
|
|
30
|
+
## Mandatory Pre-Design Checklist
|
|
31
|
+
|
|
32
|
+
Before architecting any backend system, answer these questions:
|
|
33
|
+
|
|
34
|
+
1. **Scale**: What is the expected QPS (queries per second)? Peak vs average?
|
|
35
|
+
2. **Data volume**: How much data? Growth rate? 1GB? 1TB? 1PB?
|
|
36
|
+
3. **Consistency vs Availability**: Can we tolerate eventual consistency? (CAP theorem)
|
|
37
|
+
4. **Read/Write ratio**: Is it read-heavy (cache it!) or write-heavy (shard it!)?
|
|
38
|
+
5. **Latency requirements**: Real-time (<100ms)? Near-real-time (<1s)? Batch?
|
|
39
|
+
6. **Global distribution**: Single region or multi-region?
|
|
40
|
+
7. **Deployment model**: Traditional servers, Serverless, or Edge functions?
|
|
41
|
+
|
|
42
|
+
---
|
|
43
|
+
|
|
44
|
+
## Core Architecture Patterns
|
|
45
|
+
|
|
46
|
+
### Load Balancing
|
|
47
|
+
|
|
48
|
+
```
|
|
49
|
+
Clients → Load Balancer → [App Server 1, App Server 2, App Server N]
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
- Use **Round Robin** for stateless services
|
|
53
|
+
- Use **Least Connections** for varying request times
|
|
54
|
+
- Use **IP Hash** for session affinity (or move sessions to Redis)
|
|
55
|
+
- Always add **health checks** - remove unhealthy nodes automatically
|
|
56
|
+
|
|
57
|
+
**Rule**: Any service expecting > 1000 RPS needs a load balancer. No exceptions.
|
|
58
|
+
|
|
59
|
+
### Caching Strategy
|
|
60
|
+
|
|
61
|
+
```
|
|
62
|
+
App → [Cache Layer: Redis/Memcached] → Database
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Cache decision ladder (check in order):
|
|
66
|
+
|
|
67
|
+
1. Is it read > write? → Cache it
|
|
68
|
+
2. Is it expensive to compute? → Cache it
|
|
69
|
+
3. Is it user-specific? → Cache with user key
|
|
70
|
+
4. Is it global? → Shared cache, shorter TTL
|
|
71
|
+
|
|
72
|
+
**Cache patterns**:
|
|
73
|
+
|
|
74
|
+
- **Cache-aside** (lazy loading): check cache → miss → load DB → write cache
|
|
75
|
+
- **Write-through**: write to DB AND cache simultaneously (consistency > performance)
|
|
76
|
+
- **Write-behind**: write to cache → async flush to DB (performance > consistency)
|
|
77
|
+
|
|
78
|
+
**Invalidation**: Use TTL + event-driven invalidation. Never stale-forever.
|
|
79
|
+
|
|
80
|
+
**Modern framework-native caching (Next.js App Router)**:
|
|
81
|
+
Before spinning up a dedicated Redis instance for caching API responses, check if Next.js built-in mechanisms are sufficient:
|
|
82
|
+
|
|
83
|
+
- `revalidatePath('/dashboard')` - invalidate all cache for a route
|
|
84
|
+
- `revalidateTag('user-profile')` - fine-grained tagged cache invalidation
|
|
85
|
+
- `unstable_cache()` - server-side data caching with TTL
|
|
86
|
+
|
|
87
|
+
```typescript
|
|
88
|
+
// [GOOD] Use Next.js native caching first
|
|
89
|
+
import { revalidateTag } from 'next/cache'
|
|
90
|
+
|
|
91
|
+
const getUser = unstable_cache(
|
|
92
|
+
async (id: string) => db.users.findById(id),
|
|
93
|
+
['user'],
|
|
94
|
+
{ tags: ['user-profile'], revalidate: 3600 }
|
|
95
|
+
)
|
|
96
|
+
|
|
97
|
+
// Invalidate on mutation:
|
|
98
|
+
await db.users.update(id, data)
|
|
99
|
+
revalidateTag('user-profile')
|
|
100
|
+
|
|
101
|
+
// [BAD] Don't add Redis for simple SSR caching when Next.js handles it
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### Database Architecture
|
|
105
|
+
|
|
106
|
+
#### When to use SQL vs NoSQL
|
|
107
|
+
|
|
108
|
+
| Scenario | Use SQL | Use NoSQL |
|
|
109
|
+
| ---------- | --------- | ----------- |
|
|
110
|
+
| Complex joins, ACID transactions | [PASS] | [FAIL] |
|
|
111
|
+
| Flexible/evolving schema | [FAIL] | [PASS] |
|
|
112
|
+
| Horizontal scaling needed | Careful | [PASS] |
|
|
113
|
+
| Simple key-value lookup | Overkill | [PASS] |
|
|
114
|
+
| Full-text search | Use Elasticsearch | Use Elasticsearch |
|
|
115
|
+
| Time-series data | TimescaleDB | InfluxDB |
|
|
116
|
+
|
|
117
|
+
#### Scaling Databases
|
|
118
|
+
|
|
119
|
+
**Vertical scaling**: Bigger machine. Easy but has ceiling.
|
|
120
|
+
**Read replicas**: Route SELECT to replicas, writes to primary.
|
|
121
|
+
**Sharding (horizontal partitioning)**:
|
|
122
|
+
|
|
123
|
+
- Hash sharding: `user_id % N` - even distribution, hard to rebalance
|
|
124
|
+
- Range sharding: user_id 1-1M on shard 1 - easy range queries, hotspots risk
|
|
125
|
+
- Directory-based: lookup table maps key → shard - flexible, but lookup is overhead
|
|
126
|
+
|
|
127
|
+
**Denormalization**: For read-heavy systems, duplicate data to avoid joins.
|
|
128
|
+
**Rule**: Don't shard until you've maxed out read replicas.
|
|
129
|
+
|
|
130
|
+
### Message Queues & Async Processing
|
|
131
|
+
|
|
132
|
+
```
|
|
133
|
+
Producer → [Queue: Redis/RabbitMQ/Kafka] → Consumer Workers
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Use queues when:
|
|
137
|
+
|
|
138
|
+
- Operation takes > 200ms (email, PDF generation, ML inference)
|
|
139
|
+
- You need retry logic on failure
|
|
140
|
+
- You need to decouple services
|
|
141
|
+
- Traffic spikes need to be absorbed
|
|
142
|
+
|
|
143
|
+
**Kafka** = durability + replay + high throughput (events/analytics)
|
|
144
|
+
**Redis Queue** = simplicity + low latency (jobs/tasks)
|
|
145
|
+
**RabbitMQ** = complex routing + acknowledgements
|
|
146
|
+
|
|
147
|
+
### Microservices vs Monolith
|
|
148
|
+
|
|
149
|
+
**Start with a monolith** unless you have > 10 engineers or proven scale need.
|
|
150
|
+
|
|
151
|
+
When to split into microservices:
|
|
152
|
+
|
|
153
|
+
- Independent deployment cycles needed
|
|
154
|
+
- Different scaling requirements per service
|
|
155
|
+
- Team autonomy (Conway's Law)
|
|
156
|
+
- Clear service boundaries (DDD bounded contexts)
|
|
157
|
+
|
|
158
|
+
**Rule**: A microservice should be able to be rewritten in 2 weeks by 2 engineers.
|
|
159
|
+
|
|
160
|
+
Service communication:
|
|
161
|
+
|
|
162
|
+
- **Sync (REST/gRPC)**: when caller needs immediate response
|
|
163
|
+
- **Async (events/queue)**: when caller can tolerate delay, or decoupling is needed
|
|
164
|
+
- **BFF / Server Actions**: for web apps, prefer typed client-server contracts (see below)
|
|
165
|
+
|
|
166
|
+
---
|
|
167
|
+
|
|
168
|
+
## Modern Stack Patterns (Serverless, Edge, Next.js)
|
|
169
|
+
|
|
170
|
+
### Serverless & Edge Architecture
|
|
171
|
+
|
|
172
|
+
When deploying to serverless (Vercel Functions, AWS Lambda) or edge (Vercel Edge, Cloudflare Workers), the classical "App Server + Load Balancer" model changes:
|
|
173
|
+
|
|
174
|
+
**Cold Start Problem**:
|
|
175
|
+
|
|
176
|
+
- Serverless functions spin up from zero on first request - this can add 100-1000ms
|
|
177
|
+
- **Never** do heavy initialization at module level (DB connections, config loading, crypto keys)
|
|
178
|
+
- **Always** initialize lazily inside the handler, or use a connection pooling service
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
// [BAD] Wrong: Module-level initialization (runs on cold start, hangs the function)
|
|
182
|
+
const db = new DatabaseClient({ ... }) // top of file
|
|
183
|
+
|
|
184
|
+
// [GOOD] Correct: Lazy initialization with caching
|
|
185
|
+
let db: DatabaseClient | null = null
|
|
186
|
+
function getDb() {
|
|
187
|
+
if (!db) db = new DatabaseClient({ ... })
|
|
188
|
+
return db
|
|
189
|
+
}
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
**DB Connection Pooling in Serverless**:
|
|
193
|
+
|
|
194
|
+
- Traditional in-process pools (pg-pool, knex) do NOT work in serverless - each invocation is ephemeral
|
|
195
|
+
- Use **Prisma Accelerate**, **PlanetScale**, **Neon** pooling, or **Supabase** - they handle pooling at the infrastructure level
|
|
196
|
+
- Rule: If deploying to Vercel/serverless, NEVER assume `max_connections` is managed by your app process
|
|
197
|
+
|
|
198
|
+
**Edge Functions limitations**:
|
|
199
|
+
|
|
200
|
+
- No Node.js APIs (no `fs`, no `crypto.randomBytes`, limited DNS)
|
|
201
|
+
- Latency must be < 50ms - no heavy DB queries
|
|
202
|
+
- Use edge for: auth token verification, A/B testing, geo-routing, lightweight transformations
|
|
203
|
+
|
|
204
|
+
### BFF Pattern & Server Actions (Type-Safe Client-Server)
|
|
205
|
+
|
|
206
|
+
When building web apps, prefer typed client-server communication over generic REST endpoints:
|
|
207
|
+
|
|
208
|
+
**Option 1: Server Actions (Next.js App Router)**
|
|
209
|
+
For mutations that touch the database directly, skip the API route entirely:
|
|
210
|
+
|
|
211
|
+
```typescript
|
|
212
|
+
// [GOOD] Server Action: No API route needed, fully type-safe
|
|
213
|
+
"use server"
|
|
214
|
+
export async function updateUser(id: string, data: UpdateUserInput) {
|
|
215
|
+
// Input validation (always!)
|
|
216
|
+
const validated = UpdateUserSchema.parse(data)
|
|
217
|
+
|
|
218
|
+
// Auth check (always before data access!)
|
|
219
|
+
const session = await getSession()
|
|
220
|
+
if (session.userId !== id && !session.isAdmin) {
|
|
221
|
+
throw new Error("Forbidden")
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return db.users.update(id, validated)
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// [BAD] Over-engineering: Don't create /api/users/[id] + fetch wrapper for simple mutations
|
|
228
|
+
```
|
|
229
|
+
|
|
230
|
+
**Option 2: tRPC (Full-stack type safety)**
|
|
231
|
+
For complex APIs with many routes, use tRPC to get end-to-end type safety from DB to UI without code generation.
|
|
232
|
+
|
|
233
|
+
**Option 3: REST (When appropriate)**
|
|
234
|
+
When building a public API consumed by external clients or mobile apps - use REST with OpenAPI spec.
|
|
235
|
+
|
|
236
|
+
**Decision rule**:
|
|
237
|
+
|
|
238
|
+
- Internal web-to-DB mutation → **Server Action**
|
|
239
|
+
- Internal complex API → **tRPC**
|
|
240
|
+
- Public/mobile API → **REST + OpenAPI**
|
|
241
|
+
|
|
242
|
+
### Domain-Driven Design (DDD) - Business Logic Isolation
|
|
243
|
+
|
|
244
|
+
**Rule**: NEVER write business logic inside API route handlers, Server Actions, or controllers. Always extract to dedicated services/use-cases.
|
|
245
|
+
|
|
246
|
+
```
|
|
247
|
+
[FAIL] Wrong structure:
|
|
248
|
+
app/api/orders/route.ts ← contains: validation + auth + business logic + DB query
|
|
249
|
+
|
|
250
|
+
[PASS] Correct structure:
|
|
251
|
+
app/api/orders/route.ts ← only: parse request, call service, return response
|
|
252
|
+
src/services/order.service.ts ← all business logic, testable without HTTP context
|
|
253
|
+
src/repositories/order.repo.ts ← all DB queries
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
Example:
|
|
257
|
+
|
|
258
|
+
```typescript
|
|
259
|
+
// [BAD] Business logic in route (untestable, bloated)
|
|
260
|
+
export async function POST(req: Request) {
|
|
261
|
+
const data = await req.json()
|
|
262
|
+
if (data.quantity <= 0) return new Response("Invalid", { status: 400 })
|
|
263
|
+
const inventory = await db.inventory.findById(data.productId)
|
|
264
|
+
if (inventory.stock < data.quantity) return new Response("Out of stock", { status: 400 })
|
|
265
|
+
const total = inventory.price * data.quantity
|
|
266
|
+
// ... 40 more lines
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
// [GOOD] Thin route, fat service
|
|
270
|
+
export async function POST(req: Request) {
|
|
271
|
+
const data = await req.json()
|
|
272
|
+
const result = await orderService.createOrder(data)
|
|
273
|
+
return Response.json(result)
|
|
274
|
+
}
|
|
275
|
+
|
|
276
|
+
// orderService.createOrder() - pure function, fully unit-testable without HTTP
|
|
277
|
+
```
|
|
278
|
+
|
|
279
|
+
---
|
|
280
|
+
|
|
281
|
+
## Scalability Design Patterns
|
|
282
|
+
|
|
283
|
+
### CDN (Content Delivery Network)
|
|
284
|
+
|
|
285
|
+
- Serve static assets (JS, CSS, images) from CDN edge nodes
|
|
286
|
+
- Cache API responses that don't change per-user
|
|
287
|
+
- Reduce origin server load by 80%+
|
|
288
|
+
|
|
289
|
+
### Rate Limiting
|
|
290
|
+
|
|
291
|
+
Always implement for public APIs:
|
|
292
|
+
|
|
293
|
+
```
|
|
294
|
+
- Token bucket: smooth bursts, allows brief spikes
|
|
295
|
+
- Leaky bucket: strict rate, no bursts
|
|
296
|
+
- Fixed window: simple, vulnerable to boundary spikes
|
|
297
|
+
- Sliding window: most accurate, slightly more complex
|
|
298
|
+
```
|
|
299
|
+
|
|
300
|
+
Store rate limit state in Redis (not in-process - it doesn't survive restarts).
|
|
301
|
+
|
|
302
|
+
### Circuit Breaker
|
|
303
|
+
|
|
304
|
+
Prevent cascade failures:
|
|
305
|
+
|
|
306
|
+
```
|
|
307
|
+
CLOSED (normal) → [failures > threshold] → OPEN (fail fast)
|
|
308
|
+
↑ ↓
|
|
309
|
+
└────── [timeout] ← HALF-OPEN (test request) ──┘
|
|
310
|
+
```
|
|
311
|
+
|
|
312
|
+
### Database Connection Pooling
|
|
313
|
+
|
|
314
|
+
- **Traditional servers**: Use pg-pool, knex, Prisma connection pool
|
|
315
|
+
- **Serverless**: Use Prisma Accelerate, PlanetScale, Neon, or Supabase pooling - NOT in-process pools
|
|
316
|
+
|
|
317
|
+
---
|
|
318
|
+
|
|
319
|
+
## CAP Theorem in Practice
|
|
320
|
+
|
|
321
|
+
**You can only guarantee 2 of 3**: Consistency, Availability, Partition Tolerance
|
|
322
|
+
|
|
323
|
+
| System | Chooses | Example |
|
|
324
|
+
| -------- | --------- | --------- |
|
|
325
|
+
| Traditional SQL | CP | PostgreSQL |
|
|
326
|
+
| Distributed NoSQL | AP | DynamoDB, Cassandra |
|
|
327
|
+
| Cache | AP (tunable) | Redis with replication |
|
|
328
|
+
|
|
329
|
+
**For most apps**: Choose AP. Accept eventual consistency. Use optimistic locking for critical writes.
|
|
330
|
+
|
|
331
|
+
---
|
|
332
|
+
|
|
333
|
+
## Designing Data-Intensive Applications (DDIA) Patterns
|
|
334
|
+
|
|
335
|
+
Based on _Designing Data-Intensive Applications_ (Martin Kleppmann) and [ciembor/agent-rules-books](https://github.com/ciembor/agent-rules-books).
|
|
336
|
+
|
|
337
|
+
### 1. The Dual-Write Problem & Transactional Outbox
|
|
338
|
+
|
|
339
|
+
**The Anti-Pattern**: Updating the database and sending a message to a broker (Kafka, RabbitMQ, SQS) in two separate operations. If one fails, the system enters an inconsistent state.
|
|
340
|
+
|
|
341
|
+
**The Solution**: Write the business entity AND an event record to an `outbox` table in the SAME database transaction:
|
|
342
|
+
|
|
343
|
+
```sql
|
|
344
|
+
BEGIN TRANSACTION;
|
|
345
|
+
UPDATE orders SET status = 'PAID' WHERE id = 'ord_123';
|
|
346
|
+
INSERT INTO outbox_events (id, aggregate_type, aggregate_id, event_type, payload, created_at)
|
|
347
|
+
VALUES ('evt_456', 'Order', 'ord_123', 'OrderPaid', '{"amount": 99.00}', NOW());
|
|
348
|
+
COMMIT;
|
|
349
|
+
```
|
|
350
|
+
|
|
351
|
+
A background process (polling worker or Debezium CDC) reads `outbox_events`, delivers them to the message broker, and marks them as published.
|
|
352
|
+
|
|
353
|
+
### 2. Idempotency Invariant for Mutations
|
|
354
|
+
|
|
355
|
+
All write operations exposed over HTTP or queues MUST support deduplication:
|
|
356
|
+
|
|
357
|
+
- Accept an `Idempotency-Key` header (UUID or client-generated hash).
|
|
358
|
+
- Store key with status in Redis or DB with a TTL (e.g., 24 hours).
|
|
359
|
+
- If the key is already `COMPLETED`, return the cached response immediately without re-executing.
|
|
360
|
+
- If `IN_PROGRESS`, return HTTP `409 Conflict` or queue retry.
|
|
361
|
+
|
|
362
|
+
### 3. Read-Your-Own-Writes Consistency
|
|
363
|
+
|
|
364
|
+
When using read replicas, replication lag (even 50ms) causes users to not see their own changes immediately after saving:
|
|
365
|
+
|
|
366
|
+
- **Rule**: Route user reads to the primary database for `N` seconds (e.g., 5s) following any mutation by that user.
|
|
367
|
+
- Route all other queries and background jobs to read replicas.
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Architecture Decision Template
|
|
372
|
+
|
|
373
|
+
When proposing any backend architecture, include:
|
|
374
|
+
|
|
375
|
+
```markdown
|
|
376
|
+
## System Design Decision
|
|
377
|
+
|
|
378
|
+
**Scale Target**: [X RPS, Y GB data, Z users]
|
|
379
|
+
**Deployment Model**: [Traditional servers | Serverless | Edge]
|
|
380
|
+
**CAP Choice**: [CP/AP] because [reason]
|
|
381
|
+
**Read/Write Ratio**: [X:Y]
|
|
382
|
+
|
|
383
|
+
### Components
|
|
384
|
+
- **API Layer**: [REST/tRPC/Server Actions] - [why this choice]
|
|
385
|
+
- **Cache**: [Next.js native | Redis] for [what] with [TTL/tags strategy]
|
|
386
|
+
- **Database**: [SQL/NoSQL] - [pooling solution for serverless if applicable]
|
|
387
|
+
- **Async**: [Queue tech] for [what operations]
|
|
388
|
+
|
|
389
|
+
### Business Logic Isolation
|
|
390
|
+
- Services: [list key service files]
|
|
391
|
+
- Repositories: [list key repo files]
|
|
392
|
+
- Routes/Actions: [thin handlers only]
|
|
393
|
+
|
|
394
|
+
### Trade-offs Accepted
|
|
395
|
+
- [Trade-off 1]: [Why acceptable]
|
|
396
|
+
- [Trade-off 2]: [Why acceptable]
|
|
397
|
+
|
|
398
|
+
### Scaling Path
|
|
399
|
+
1. Now (MVP): [simple setup]
|
|
400
|
+
2. At 10× load: [first scaling step]
|
|
401
|
+
3. At 100× load: [next scaling step]
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
|
|
405
|
+
## Code Examples
|
|
406
|
+
|
|
407
|
+
See `EXAMPLES.md` for detailed code examples.
|
|
408
|
+
|
|
409
|
+
## Validation Checklist
|
|
410
|
+
|
|
411
|
+
What to verify during the review phase before completing the task.
|
|
412
|
+
|
|
413
|
+
## Common Mistakes
|
|
414
|
+
|
|
415
|
+
Anti-patterns and things to explicitly avoid. See `TROUBLESHOOTING.md`.
|
|
416
|
+
|
|
417
|
+
## Integration Notes
|
|
418
|
+
|
|
419
|
+
How this skill interacts with other skills.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# system-design Troubleshooting & Common Mistakes
|
|
2
|
+
|
|
3
|
+
## 1. Serverless Connection Exhaustion
|
|
4
|
+
|
|
5
|
+
- **Symptom**: "FATAL: remaining connection slots are reserved for non-replication superuser connections" under modest traffic.
|
|
6
|
+
- **Root Cause**: Serverless/Edge functions opening new DB connection pools per invoked instance.
|
|
7
|
+
- **Fix**: Use a connection pooler like PgBouncer or managed pooling (Supabase connection pool, AWS RDS Proxy, Prisma Accelerate).
|
|
8
|
+
|
|
9
|
+
## 2. Cache Invalidation Drift
|
|
10
|
+
|
|
11
|
+
- **Symptom**: Users see stale, outdated data after making updates.
|
|
12
|
+
- **Root Cause**: Updates to database do not invalidate related cache keys, or TTLs are set to infinite.
|
|
13
|
+
- **Fix**: Invalidate cache keys explicitly on write in the same transactional flow, and always set defensive TTLs.
|
|
14
|
+
|
|
15
|
+
## 3. Lack of Rate Limiting and Backpressure
|
|
16
|
+
|
|
17
|
+
- **Symptom**: Backend crashes or slows to a crawl during traffic spikes or bot scraping.
|
|
18
|
+
- **Root Cause**: Unthrottled public endpoints without token-bucket or sliding-window rate limiting.
|
|
19
|
+
- **Fix**: Add rate-limiting middleware (Redis-backed sliding window) at the API gateway / Edge layer.
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
schemaVersion: 2
|
|
2
|
+
name: system-design
|
|
3
|
+
category: architecture
|
|
4
|
+
type: instruction-only
|
|
5
|
+
description: >
|
|
6
|
+
Architecture and system design skill based on donnemartin's System Design Primer.
|
|
7
|
+
Teaches scalable architecture thinking: load balancers, caching, DB partitioning,
|
|
8
|
+
microservices, CAP theorem, and trade-off analysis before writing backend code.
|
|
9
|
+
version: 1.0.0
|
|
10
|
+
resources:
|
|
11
|
+
- EXAMPLES.md
|
|
12
|
+
- SKILL.md
|
|
13
|
+
- TROUBLESHOOTING.md
|
|
14
|
+
- VALIDATION.json
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
# Terraform - Examples & Refactoring Scenarios
|
|
2
|
+
|
|
3
|
+
## Example 1: Zero-Downtime Address Refactoring with `moved` Blocks
|
|
4
|
+
|
|
5
|
+
When moving an inline resource into a dedicated child module, never allow Terraform to destroy and recreate it:
|
|
6
|
+
|
|
7
|
+
```hcl
|
|
8
|
+
# Before refactor (in root main.tf):
|
|
9
|
+
# resource "aws_s3_bucket" "assets" {
|
|
10
|
+
# bucket = "company-production-assets"
|
|
11
|
+
# }
|
|
12
|
+
|
|
13
|
+
# After refactor:
|
|
14
|
+
module "storage" {
|
|
15
|
+
source = "../../modules/storage"
|
|
16
|
+
bucket_name = "company-production-assets"
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
# Refactor migration declaration (prevents destructive delete/recreate):
|
|
20
|
+
moved {
|
|
21
|
+
from = aws_s3_bucket.assets
|
|
22
|
+
to = module.storage.aws_s3_bucket.this
|
|
23
|
+
}
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Example 2: Safe Environment Module Pattern
|
|
29
|
+
|
|
30
|
+
```hcl
|
|
31
|
+
# environments/prod/versions.tf
|
|
32
|
+
terraform {
|
|
33
|
+
required_version = ">= 1.9.0"
|
|
34
|
+
|
|
35
|
+
required_providers {
|
|
36
|
+
aws = {
|
|
37
|
+
source = "hashicorp/aws"
|
|
38
|
+
version = "~> 5.50.0"
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
backend "s3" {
|
|
43
|
+
bucket = "tf-state-prod-lock"
|
|
44
|
+
key = "core/terraform.tfstate"
|
|
45
|
+
region = "us-east-1"
|
|
46
|
+
dynamodb_table = "tf-state-locks"
|
|
47
|
+
encrypt = true
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
---
|
|
53
|
+
|
|
54
|
+
## Example 3: Safe Destroy Verification Script
|
|
55
|
+
|
|
56
|
+
```bash
|
|
57
|
+
#!/usr/bin/env bash
|
|
58
|
+
set -euo pipefail
|
|
59
|
+
|
|
60
|
+
TARGET_RESOURCE="${1:-}"
|
|
61
|
+
|
|
62
|
+
if [[ -z "$TARGET_RESOURCE" ]]; then
|
|
63
|
+
echo "Error: Target resource address must be specified."
|
|
64
|
+
exit 1
|
|
65
|
+
fi
|
|
66
|
+
|
|
67
|
+
echo "Running safe destroy inspection for: $TARGET_RESOURCE"
|
|
68
|
+
terraform plan -destroy -target="$TARGET_RESOURCE" -out="destroy.tfplan"
|
|
69
|
+
|
|
70
|
+
# Display affected resources
|
|
71
|
+
terraform show -json destroy.tfplan | jq -r '.resource_changes[] | select(.change.actions[] == "delete") | .address'
|
|
72
|
+
|
|
73
|
+
echo "Carefully inspect the resources above. Run terraform apply destroy.tfplan only after manual confirmation."
|
|
74
|
+
```
|
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: terraform
|
|
3
|
+
description: Production-grade Terraform and OpenTofu IaC guidance. Enforces diagnose-first failure mode analysis, Safe Destroy Protocol, state management, and modular architecture.
|
|
4
|
+
---
|
|
5
|
+
|
|
6
|
+
# Terraform and OpenTofu
|
|
7
|
+
|
|
8
|
+
Diagnose-first guidance for Terraform and OpenTofu infrastructure as code, inspired by Anton Babenko's engineering standards.
|
|
9
|
+
|
|
10
|
+
## Response Contract
|
|
11
|
+
|
|
12
|
+
Every Terraform or OpenTofu modification must declare:
|
|
13
|
+
1. **Assumptions & Version Floor**: Runtime (`terraform` or `tofu`), exact version, providers, backend type, and environment criticality.
|
|
14
|
+
2. **Risk Category Addressed**: Identify whether the change impacts identity churn, secret exposure, blast radius, destroy cascades, or CI drift.
|
|
15
|
+
3. **Chosen Remediation & Trade-offs**: Why this approach was selected over alternatives.
|
|
16
|
+
4. **Validation Plan**: Exact commands (`terraform fmt -check`, `validate`, `plan -out=tfplan`) tailored to the change.
|
|
17
|
+
5. **Rollback Notes**: Clear procedure for reverting any state or resource mutation.
|
|
18
|
+
|
|
19
|
+
## Safe Destroy Protocol
|
|
20
|
+
|
|
21
|
+
Never run `terraform destroy` or remove state without strict guards:
|
|
22
|
+
- **Mandatory Plan-Destroy**: Never execute a destroy operation without first running `terraform plan -destroy` and displaying every single resource marked for deletion.
|
|
23
|
+
- **Check Implicit Dependents**: Review `locals` and `for_each` consumers referencing targeted resources to ensure no unexpected cascading deletions occur.
|
|
24
|
+
- **Zero Auto-Approve on Destroy**: The `-auto-approve` flag is strictly forbidden on destroy operations.
|
|
25
|
+
|
|
26
|
+
## Diagnose Before Generating
|
|
27
|
+
|
|
28
|
+
| Failure Category | Symptoms | Prevention Strategy |
|
|
29
|
+
|------------------|----------|---------------------|
|
|
30
|
+
| **Identity Churn** | Resource addresses shift after refactoring, recreation of stateful resources | Use `for_each` instead of numeric `count`; apply `moved` blocks for refactored addresses |
|
|
31
|
+
| **Secret Exposure** | Sensitive tokens in variables, plan outputs, or unencrypted state | Mark outputs/variables with `sensitive = true`; use KMS-encrypted remote backends |
|
|
32
|
+
| **Blast Radius** | Oversized monolithic state files, shared dev/prod configurations | Isolate state per environment and bounded context; keep modules focused |
|
|
33
|
+
| **Destroy Cascade** | Targeted destruction deletes dependent databases or networks | Run `plan -destroy` first; inspect dependency DAG |
|
|
34
|
+
| **CI Drift** | Local plan differs from CI runner; unpinned providers | Pin exact provider and module versions; run plans strictly against reviewed commit SHA |
|
|
35
|
+
|
|
36
|
+
## Module Hierarchy & Directory Layout
|
|
37
|
+
|
|
38
|
+
Structure infrastructure into three distinct layers:
|
|
39
|
+
1. **Resource Module**: Single logical grouping of closely connected resources (e.g. VPC + subnets, or S3 bucket + bucket policy).
|
|
40
|
+
2. **Infrastructure Module**: Collection of resource modules fulfilling a sub-system (e.g. multi-region compute cluster with monitoring).
|
|
41
|
+
3. **Composition**: Environment-level assembly tying modules together for a specific environment (`dev`, `staging`, `prod`).
|
|
42
|
+
|
|
43
|
+
```
|
|
44
|
+
environments/
|
|
45
|
+
prod/
|
|
46
|
+
main.tf # Calls reusable modules
|
|
47
|
+
variables.tf
|
|
48
|
+
outputs.tf
|
|
49
|
+
versions.tf # Exact provider pins & backend configuration
|
|
50
|
+
modules/
|
|
51
|
+
networking/
|
|
52
|
+
main.tf
|
|
53
|
+
variables.tf
|
|
54
|
+
outputs.tf
|
|
55
|
+
```
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
# Terraform - Troubleshooting & Common Edge Cases
|
|
2
|
+
|
|
3
|
+
## Common Diagnostic Scenarios
|
|
4
|
+
|
|
5
|
+
### 1. Stuck Remote State Lock (`Error acquiring the state lock`)
|
|
6
|
+
|
|
7
|
+
- **Symptom**: Terraform commands abort with `Error message: ConditionalCheckFailedException: The conditional request failed` or `Lock Info: ID: <lock-id>`.
|
|
8
|
+
- **Root Cause**: A previous CI runner or local process crashed, timed out, or was killed before releasing the DynamoDB or backend lock.
|
|
9
|
+
- **Fix Protocol**:
|
|
10
|
+
1. Inspect the Lock Info: verify the lock owner and creation timestamp.
|
|
11
|
+
2. Confirm that no active pipeline or engineer is running an apply on this workspace.
|
|
12
|
+
3. Force-unlock using the exact Lock ID:
|
|
13
|
+
```bash
|
|
14
|
+
terraform force-unlock <lock-id>
|
|
15
|
+
```
|
|
16
|
+
4. Never disable locks by setting `-lock=false`.
|
|
17
|
+
|
|
18
|
+
---
|
|
19
|
+
|
|
20
|
+
### 2. Cascading Destruction of Dependent Resources via `for_each` / `locals`
|
|
21
|
+
|
|
22
|
+
- **Symptom**: Destroying a single resource triggers planned deletion of dozens of downstream resources.
|
|
23
|
+
- **Root Cause**: Downstream resources reference the targeted resource in a `for_each` map or local projection. Removing the upstream resource causes keys in `for_each` to disappear, queueing destruction of all instances.
|
|
24
|
+
- **Fix Protocol**:
|
|
25
|
+
1. Always run `terraform plan -destroy -target=<resource>` first.
|
|
26
|
+
2. Inspect the resource changes list for unexpected deletions.
|
|
27
|
+
3. Decouple downstream configurations or provide static placeholder values in `locals` before attempting targeted deletion.
|
|
28
|
+
|
|
29
|
+
---
|
|
30
|
+
|
|
31
|
+
### 3. Identity Churn on Refactoring Module Paths
|
|
32
|
+
|
|
33
|
+
- **Symptom**: After restructuring modules, `terraform plan` reports: `Plan: 5 to add, 0 to change, 5 to destroy` for existing stateful resources.
|
|
34
|
+
- **Root Cause**: Changing module names or nesting paths changes the resource addresses in the Terraform state file.
|
|
35
|
+
- **Fix Protocol**:
|
|
36
|
+
- Use `moved` blocks to cleanly inform Terraform of the address change:
|
|
37
|
+
```hcl
|
|
38
|
+
moved {
|
|
39
|
+
from = module.old_network.aws_vpc.main
|
|
40
|
+
to = module.vpc.aws_vpc.this
|
|
41
|
+
}
|
|
42
|
+
```
|
|
43
|
+
- Re-run `terraform plan`. It should now report `Plan: 0 to add, 0 to change, 0 to destroy` with a clear notice of moved resource addresses.
|
|
44
|
+
|
|
45
|
+
---
|
|
46
|
+
|
|
47
|
+
### 4. Cyclic Dependency Errors (`Cycle: module.a, module.b`)
|
|
48
|
+
|
|
49
|
+
- **Symptom**: Terraform graph computation aborts with a cyclic dependency error.
|
|
50
|
+
- **Root Cause**: Module A references outputs from Module B, while Module B references outputs from Module A.
|
|
51
|
+
- **Fix Protocol**:
|
|
52
|
+
1. Break bidirectional coupling by extracting the shared configuration or data resource into a dedicated upstream module (e.g. `module.shared_networking`).
|
|
53
|
+
2. Pass IDs downward; never allow lower-tier modules to depend on upper-tier compositions.
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
{
|
|
2
|
+
"skill": "terraform",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"checks": [
|
|
5
|
+
"Response contract declared with assumptions, risk category, and rollback plan",
|
|
6
|
+
"Safe destroy protocol strictly enforced without -auto-approve",
|
|
7
|
+
"Module hierarchy maintained (resource -> infrastructure -> composition)",
|
|
8
|
+
"Remote backend configured with state locking and encryption at rest",
|
|
9
|
+
"Resource refactoring uses moved blocks to prevent identity churn"
|
|
10
|
+
]
|
|
11
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
schemaVersion: 2
|
|
2
|
+
name: terraform
|
|
3
|
+
description: Production-grade Terraform and OpenTofu IaC guidance inspired by Anton Babenko. Enforces diagnose-first failure mode analysis, Safe Destroy Protocol, and modular composition.
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
category: devops
|
|
6
|
+
type: instruction-only
|
|
7
|
+
requires:
|
|
8
|
+
- engineering-workflow
|
|
9
|
+
- decisions
|
|
10
|
+
resources:
|
|
11
|
+
- EXAMPLES.md
|
|
12
|
+
- SKILL.md
|
|
13
|
+
- TROUBLESHOOTING.md
|
|
14
|
+
- VALIDATION.json
|