@tekyzinc/gsd-t 2.45.11 → 2.50.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +26 -5
  3. package/bin/debug-ledger.js +193 -0
  4. package/bin/gsd-t.js +259 -1
  5. package/commands/gsd-t-complete-milestone.md +2 -1
  6. package/commands/gsd-t-debug.md +48 -2
  7. package/commands/gsd-t-doc-ripple.md +148 -0
  8. package/commands/gsd-t-execute.md +102 -5
  9. package/commands/gsd-t-help.md +25 -2
  10. package/commands/gsd-t-integrate.md +41 -1
  11. package/commands/gsd-t-qa.md +26 -5
  12. package/commands/gsd-t-quick.md +39 -1
  13. package/commands/gsd-t-test-sync.md +26 -1
  14. package/commands/gsd-t-verify.md +8 -2
  15. package/commands/gsd-t-wave.md +57 -0
  16. package/docs/GSD-T-README.md +84 -1
  17. package/docs/architecture.md +9 -1
  18. package/docs/framework-comparison-scorecard.md +160 -0
  19. package/docs/requirements.md +33 -0
  20. package/examples/rules/desktop.ini +2 -0
  21. package/package.json +2 -2
  22. package/templates/CLAUDE-global.md +82 -4
  23. package/templates/stacks/_security.md +243 -0
  24. package/templates/stacks/desktop.ini +2 -0
  25. package/templates/stacks/docker.md +202 -0
  26. package/templates/stacks/firebase.md +166 -0
  27. package/templates/stacks/flutter.md +205 -0
  28. package/templates/stacks/github-actions.md +201 -0
  29. package/templates/stacks/graphql.md +216 -0
  30. package/templates/stacks/neo4j.md +218 -0
  31. package/templates/stacks/nextjs.md +184 -0
  32. package/templates/stacks/node-api.md +196 -0
  33. package/templates/stacks/playwright.md +528 -0
  34. package/templates/stacks/postgresql.md +225 -0
  35. package/templates/stacks/python.md +243 -0
  36. package/templates/stacks/react-native.md +216 -0
  37. package/templates/stacks/react.md +293 -0
  38. package/templates/stacks/redux.md +193 -0
  39. package/templates/stacks/rest-api.md +202 -0
  40. package/templates/stacks/supabase.md +188 -0
  41. package/templates/stacks/tailwind.md +169 -0
  42. package/templates/stacks/typescript.md +176 -0
  43. package/templates/stacks/vite.md +176 -0
  44. package/templates/stacks/vue.md +189 -0
  45. package/templates/stacks/zustand.md +203 -0
@@ -49,6 +49,7 @@ PROJECT or FEATURE or SCAN
49
49
  | `/user:gsd-t-execute` | Run tasks — task-level fresh dispatch, worktree isolation, adaptive replanning, active rule injection |
50
50
  | `/user:gsd-t-test-sync` | Keep tests aligned with code changes |
51
51
  | `/user:gsd-t-qa` | QA agent — test generation, execution, gap reporting |
52
+ | `/user:gsd-t-doc-ripple` | Automated document ripple — update downstream docs after code changes |
52
53
  | `/user:gsd-t-integrate` | Wire domains together |
53
54
  | `/user:gsd-t-verify` | Run quality gates + goal-backward behavior verification |
54
55
  | `/user:gsd-t-complete-milestone` | Archive milestone + git tag (goal-backward gate, rule engine distillation) |
@@ -250,6 +251,32 @@ BEFORE reporting "tests pass" for ANY task:
250
251
 
251
252
  The conditional "if UI/routes/flows changed" in command files applies to **writing new E2E specs**, not to **running existing ones**. You always run existing E2E specs. Always.
252
253
 
254
+ ### E2E Test Quality Standard (MANDATORY)
255
+
256
+ **E2E tests must be FUNCTIONAL tests, not LAYOUT tests.** This is non-negotiable.
257
+
258
+ A layout test checks that elements exist (`isVisible`, `toBeAttached`, `toBeEnabled`, `toHaveCount`). A functional test checks that features work — actions produce correct outcomes.
259
+
260
+ ```
261
+ LAYOUT TEST (WRONG — passes even if every feature is broken):
262
+ await expect(page.locator('#tab-sessions')).toBeVisible();
263
+ await page.click('#tab-sessions');
264
+ // ← No assertion that the tab's content actually loaded
265
+
266
+ FUNCTIONAL TEST (RIGHT — fails if the feature is broken):
267
+ await page.click('#tab-sessions');
268
+ await expect(page.locator('.session-list')).toContainText('Session 1');
269
+ // ← Proves clicking the tab loaded the session data
270
+ ```
271
+
272
+ Every Playwright assertion must verify one of:
273
+ - **State changed**: After click/type/submit, the app state is different (new content, updated data, changed status)
274
+ - **Data flowed**: User input → API call → response rendered (use `page.waitForResponse` or assert on rendered data)
275
+ - **Content loaded**: Navigation/tab switch → destination content appeared (assert on text/data unique to destination)
276
+ - **Widget responded**: Terminal accepted keystrokes and produced output, editor saved changes, form submitted and data persisted
277
+
278
+ **If a test would pass on an empty HTML page with the correct element IDs and no JavaScript, it is not a functional test.** Rewrite it.
279
+
253
280
  ## QA Agent (Mandatory)
254
281
 
255
282
  Any GSD-T phase that produces or validates code **MUST run QA**. The QA agent's sole job is test generation, execution, and gap reporting. It never writes feature code.
@@ -269,10 +296,15 @@ a. Unit tests (vitest/jest/mocha): run the full suite
269
296
  b. E2E tests: check for playwright.config.* or cypress.config.* — if found, run the FULL E2E suite
270
297
  c. NEVER skip E2E when a config file exists. Running only unit tests is a QA FAILURE.
271
298
  d. Read .gsd-t/contracts/ for contract definitions. Check contract compliance.
272
- Report format: 'Unit: X/Y pass | E2E: X/Y pass (or N/A if no config) | Contract: compliant/violations'"
299
+ e. AUDIT E2E test quality: Review each Playwright spec if any test only checks element
300
+ existence (isVisible, toBeAttached, toBeEnabled) without verifying functional behavior
301
+ (state changes, data loaded, content updated after user actions), flag it as
302
+ 'SHALLOW TEST — needs functional assertions'. A passing test suite that doesn't catch
303
+ broken features is a QA FAILURE.
304
+ Report format: 'Unit: X/Y pass | E2E: X/Y pass (or N/A if no config) | Contract: compliant/violations | Shallow tests: N'"
273
305
  ```
274
306
 
275
- **QA failure blocks phase completion.** Lead cannot proceed until QA reports PASS or user explicitly overrides.
307
+ **QA failure OR shallow tests found blocks phase completion.** Lead cannot proceed until QA reports PASS with zero shallow tests, or user explicitly overrides.
276
308
 
277
309
  ## Model Display (MANDATORY)
278
310
 
@@ -307,7 +339,7 @@ This applies during: `gsd-t-execute`, `gsd-t-quick`, `gsd-t-integrate`, `gsd-t-w
307
339
 
308
340
  ## Prime Rule
309
341
  KEEP GOING. Only stop for:
310
- 1. Unrecoverable errors after 2 fix attempts
342
+ 1. Unrecoverable errors after 2 fix attempts (delegate to `gsd-t headless --debug-loop` first — only stop if exit code 4)
311
343
  2. Ambiguity that fundamentally changes project direction
312
344
  3. Milestone completion (checkpoint for user review)
313
345
  4. Destructive actions (see Destructive Action Guard above — ALWAYS stop)
@@ -361,6 +393,35 @@ BEFORE EVERY COMMIT:
361
393
 
362
394
  If ANY answer is YES and the doc is NOT updated, update it BEFORE committing. No exceptions.
363
395
 
396
+ ## Document Ripple Completion Gate (MANDATORY)
397
+
398
+ **NEVER report a task as "done" or present a summary until ALL downstream documents are updated.** This is not optional.
399
+
400
+ When a change affects multiple files (e.g., a new standard that applies across command files, a renamed API, a new convention), you MUST:
401
+
402
+ 1. **Identify the full blast radius BEFORE starting**: List every file that needs the change
403
+ 2. **Complete ALL updates in one pass**: Do not update 3 of 8 files and then present a summary
404
+ 3. **Run the Pre-Commit Gate on the COMPLETE changeset**: Not on a partial subset
405
+ 4. **Only THEN report completion**
406
+
407
+ ```
408
+ BEFORE reporting "done" or presenting a summary:
409
+ ├── Did this change establish a new standard, rule, or convention?
410
+ │ YES → Grep for every file that should enforce it. Update ALL of them.
411
+ ├── Did this change modify a pattern used in multiple command files?
412
+ │ YES → Find and update EVERY command file that uses that pattern.
413
+ ├── Did this change affect a template (CLAUDE-global, CLAUDE-project, etc.)?
414
+ │ YES → The template AND the live equivalent (~/.claude/CLAUDE.md) must match.
415
+ ├── Did this change add a new requirement?
416
+ │ YES → Add to docs/requirements.md in the same pass.
417
+ ├── Have I checked EVERY file in the blast radius?
418
+ │ NO → Keep going. Do not present partial work.
419
+ └── Am I about to say "want me to also update X?" or "should I check Y?"
420
+ YES → STOP. Just update X and check Y. Then report done.
421
+ ```
422
+
423
+ **The test for this gate**: If the user asks "did you update all the documents?" and the answer would be "no, I missed some" — you failed this gate. The user should never need to ask.
424
+
364
425
  ## Execution Behavior
365
426
  - ALWAYS check docs/architecture.md before adding or modifying components.
366
427
  - ALWAYS check docs/workflows.md before changing any multi-step process.
@@ -370,7 +431,7 @@ If ANY answer is YES and the doc is NOT updated, update it BEFORE committing. No
370
431
  - NEVER pause to show verification steps — execute them.
371
432
  - NEVER ask "should I continue?" — just continue.
372
433
  - NEVER summarize what you're "about to do" — just do it.
373
- - IF a test fails, fix it immediately (up to 2 attempts) before reporting.
434
+ - IF a test fails, fix it immediately (up to 2 attempts) before reporting. If both attempts fail, delegate to `gsd-t headless --debug-loop` before stopping.
374
435
 
375
436
  ## Autonomy Levels
376
437
 
@@ -522,6 +583,23 @@ Also pad all cell values in a column to the width of the widest value:
522
583
  ```
523
584
 
524
585
 
586
+ ## Stack Rules Engine
587
+
588
+ GSD-T auto-detects project tech stack at subagent spawn time and injects mandatory best-practice rules into the subagent prompt.
589
+
590
+ **Detection sources**: `package.json` (React, TypeScript, Node API), `requirements.txt`/`pyproject.toml` (Python), `go.mod` (Go), `Cargo.toml` (Rust).
591
+
592
+ **Universal rules**: Templates prefixed with `_` (e.g., `_security.md`) are **always** injected, regardless of stack.
593
+
594
+ **Stack-specific rules**: Injected only when the matching stack is detected (e.g., `react.md` when `"react"` is in `package.json`).
595
+
596
+ **Enforcement**: Stack rule violations have the same weight as contract violations — they are task failures, not warnings.
597
+
598
+ **Extensible**: Drop a `.md` file into `templates/stacks/` in the GSD-T package to add rules for a new stack. If the directory is missing, detection skips silently.
599
+
600
+ **Commands that inject stack rules**: `gsd-t-execute`, `gsd-t-quick`, `gsd-t-integrate`, `gsd-t-wave`, `gsd-t-debug`.
601
+
602
+
525
603
  # Recovery After Interruption
526
604
 
527
605
  When resuming work (new session or after /clear):
@@ -0,0 +1,243 @@
1
+ # Security Standards (Universal — All Projects)
2
+
3
+ These rules are MANDATORY. Violations fail the task. No exceptions.
4
+
5
+ ---
6
+
7
+ ## 1. Input Validation & Sanitization
8
+
9
+ ### All User Input
10
+ - **Validate at system boundaries** — every value from users, external APIs, URL params, form fields, file uploads
11
+ - **Whitelist, don't blacklist** — define what IS allowed, reject everything else
12
+ - **Validate type, length, format, and range** before processing
13
+ - **Trim and normalize** strings before validation (Unicode normalization, whitespace)
14
+
15
+ ### SQL Injection Prevention
16
+ ```
17
+ MANDATORY:
18
+ ├── Use parameterized queries / prepared statements — ALWAYS
19
+ ├── Never concatenate user input into SQL strings
20
+ ├── ORM query builders are preferred over raw SQL
21
+ └── If raw SQL is unavoidable, use the ORM's parameterized escape
22
+ ```
23
+
24
+ ### Command Injection Prevention
25
+ ```
26
+ MANDATORY:
27
+ ├── Never pass user input to shell commands (exec, spawn, system)
28
+ ├── If shell execution is unavoidable, use allowlisted commands only
29
+ ├── Use execFile (not exec) with explicit argument arrays
30
+ └── Never construct commands with string interpolation from user data
31
+ ```
32
+
33
+ ---
34
+
35
+ ## 2. Cross-Site Scripting (XSS)
36
+
37
+ ### Output Encoding
38
+ - **Encode all dynamic output** before rendering in HTML, JavaScript, CSS, or URLs
39
+ - **Context-aware encoding** — HTML entities in HTML, JS escaping in script tags, URL encoding in URLs
40
+ - **Never trust data from any source** — even your own database (it may contain previously-injected content)
41
+
42
+ ### DOM Manipulation
43
+ ```
44
+ MANDATORY:
45
+ ├── Never use innerHTML, outerHTML, or document.write with user data
46
+ ├── Use textContent or innerText for text insertion
47
+ ├── If HTML rendering is required, sanitize with DOMPurify first
48
+ │ ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'ul', 'ol', 'li', 'a', 'b', 'i', 'u']
49
+ │ ALLOWED_ATTR: ['href'] (on <a> only, with URL validation)
50
+ ├── React: never use dangerouslySetInnerHTML without DOMPurify
51
+ └── Vue: never use v-html without DOMPurify
52
+ ```
53
+
54
+ ### Content Security Policy
55
+ - Set `Content-Security-Policy` headers on all responses
56
+ - Minimum: `default-src 'self'; script-src 'self'; style-src 'self' 'unsafe-inline'`
57
+ - Never allow `'unsafe-eval'` in production
58
+
59
+ ---
60
+
61
+ ## 3. Authentication & Session Management
62
+
63
+ ### Token Handling
64
+ ```
65
+ MANDATORY:
66
+ ├── Never store auth tokens in localStorage or sessionStorage
67
+ │ (accessible to any XSS attack — game over)
68
+ ├── Use httpOnly, Secure, SameSite cookies for session tokens
69
+ ├── For SPAs: store tokens in memory (React Context, closure)
70
+ │ Accept that page refresh = re-authenticate
71
+ ├── Access tokens: short-lived (15 min max)
72
+ ├── Refresh tokens: httpOnly cookie only, rotate on use
73
+ └── Never include tokens in URLs or query parameters
74
+ ```
75
+
76
+ ### Password Handling
77
+ - **Never store plaintext passwords** — use bcrypt, scrypt, or Argon2
78
+ - **Minimum 12 character requirement** — no maximum length restriction
79
+ - **Never log passwords** — not even hashed ones
80
+ - **Rate limit login attempts** — 5 failures → progressive delay or lockout
81
+
82
+ ### Session Security
83
+ - Regenerate session ID after authentication
84
+ - Set session timeout (idle: 30 min, absolute: 8 hours)
85
+ - Invalidate all sessions on password change
86
+
87
+ ---
88
+
89
+ ## 4. API Security
90
+
91
+ ### Request Validation
92
+ ```
93
+ MANDATORY:
94
+ ├── Validate Content-Type header matches expected format
95
+ ├── Validate request body against a schema (Zod, Joi, JSON Schema)
96
+ ├── Reject requests with unexpected fields (additionalProperties: false)
97
+ ├── Set maximum request body size (default: 1MB)
98
+ └── Rate limit all endpoints (default: 100 req/min per IP for APIs)
99
+ ```
100
+
101
+ ### Response Security
102
+ - Never include stack traces or internal error details in production responses
103
+ - Use generic error messages for auth failures ("Invalid credentials" — don't reveal which field failed)
104
+ - Set security headers on all responses:
105
+ - `X-Content-Type-Options: nosniff`
106
+ - `X-Frame-Options: DENY`
107
+ - `Strict-Transport-Security: max-age=31536000; includeSubDomains`
108
+ - `X-XSS-Protection: 0` (rely on CSP instead)
109
+
110
+ ### CORS
111
+ - Never use `Access-Control-Allow-Origin: *` on authenticated endpoints
112
+ - Whitelist specific origins
113
+ - Never reflect the Origin header as the CORS origin without validation
114
+
115
+ ---
116
+
117
+ ## 5. Secrets Management
118
+
119
+ ```
120
+ MANDATORY:
121
+ ├── Never hardcode secrets in source code (API keys, passwords, tokens)
122
+ ├── Never commit .env files with real secrets
123
+ ├── Use environment variables for all secrets
124
+ ├── Never log secrets — redact in all log outputs
125
+ ├── Never include secrets in frontend/client-side code
126
+ │ (all client code is visible to users)
127
+ ├── Never include secrets in error messages or stack traces
128
+ └── Rotate secrets regularly and on any suspected compromise
129
+ ```
130
+
131
+ ### .gitignore Requirements
132
+ These files must ALWAYS be in `.gitignore`:
133
+ - `.env`, `.env.local`, `.env.*.local`
134
+ - `*.pem`, `*.key`, `*.cert`
135
+ - `credentials.json`, `service-account.json`
136
+ - `*.sqlite`, `*.db` (local databases)
137
+
138
+ ---
139
+
140
+ ## 6. AI-Specific Security (LLM / Prompt Injection)
141
+
142
+ ### Prompt Injection Prevention
143
+ ```
144
+ MANDATORY when user input feeds into LLM calls:
145
+ ├── Never concatenate user input directly into system prompts
146
+ ├── Use structured message format: system message (trusted) + user message (untrusted)
147
+ ├── Validate and sanitize user input before including in any prompt
148
+ ├── Strip or escape control sequences (markdown, XML tags, instruction-like text)
149
+ ├── Set output length limits to prevent extraction attacks
150
+ ├── Log and monitor prompt inputs for injection attempts
151
+ └── Never allow user input to modify system instructions or tool definitions
152
+ ```
153
+
154
+ ### LLM Output Handling
155
+ - **Never trust LLM output** — treat it as untrusted input
156
+ - Validate LLM-generated code before execution
157
+ - Sanitize LLM-generated HTML/markdown before rendering
158
+ - Never execute LLM-suggested shell commands without validation
159
+ - If LLM output feeds into database queries, use parameterized queries
160
+
161
+ ### Sensitive Data in Prompts
162
+ - Never include PII, passwords, or API keys in LLM prompts
163
+ - Redact sensitive fields before sending to external LLM APIs
164
+ - Be aware that LLM API providers may log prompts — treat all prompt content as potentially logged
165
+
166
+ ---
167
+
168
+ ## 7. File Upload Security
169
+
170
+ ```
171
+ MANDATORY when handling file uploads:
172
+ ├── Validate file type by content (magic bytes), not just extension
173
+ ├── Set maximum file size limits
174
+ ├── Generate random filenames — never use the original filename in storage
175
+ ├── Store uploads outside the web root
176
+ ├── Scan for malware before processing
177
+ ├── Never execute or interpret uploaded files
178
+ └── Set Content-Disposition: attachment on file downloads
179
+ ```
180
+
181
+ ---
182
+
183
+ ## 8. Dependency Security
184
+
185
+ - **Audit dependencies regularly** — `npm audit`, `pip audit`, `go mod verify`
186
+ - **Pin dependency versions** — use lockfiles (package-lock.json, poetry.lock)
187
+ - **Never install packages from untrusted sources**
188
+ - **Review dependency licenses** for compatibility
189
+ - **Monitor for CVEs** in production dependencies
190
+
191
+ ---
192
+
193
+ ## 9. Logging & Error Handling
194
+
195
+ ### What to Log
196
+ - Authentication events (login, logout, failed attempts)
197
+ - Authorization failures (access denied)
198
+ - Input validation failures
199
+ - Application errors and exceptions
200
+ - Security-relevant events (rate limiting, CORS rejections)
201
+
202
+ ### What NEVER to Log
203
+ - Passwords (even hashed)
204
+ - Session tokens or API keys
205
+ - Full credit card numbers
206
+ - Social security numbers or government IDs
207
+ - Personal health information
208
+ - Any data subject to PII regulations
209
+
210
+ ### Error Handling
211
+ - Never expose stack traces to users in production
212
+ - Use structured error responses with error codes
213
+ - Log the full error server-side, return a sanitized version to the client
214
+ - Never catch and swallow errors silently — log them at minimum
215
+
216
+ ---
217
+
218
+ ## 10. External Links
219
+
220
+ ```
221
+ MANDATORY:
222
+ ├── All external links: target="_blank" rel="noopener noreferrer"
223
+ ├── Validate URLs before redirecting (prevent open redirect attacks)
224
+ ├── Never redirect to user-supplied URLs without validation
225
+ └── Whitelist allowed redirect domains
226
+ ```
227
+
228
+ ---
229
+
230
+ ## Pre-Commit Security Checklist
231
+
232
+ Before committing code that handles user input, authentication, or external data:
233
+
234
+ - [ ] No hardcoded secrets in source code
235
+ - [ ] User input validated and sanitized at system boundaries
236
+ - [ ] SQL queries use parameterized statements
237
+ - [ ] No `innerHTML` / `dangerouslySetInnerHTML` without sanitization
238
+ - [ ] Auth tokens not stored in localStorage
239
+ - [ ] Error responses don't expose internal details
240
+ - [ ] External links use `rel="noopener noreferrer"`
241
+ - [ ] File uploads validated by content type and size
242
+ - [ ] Sensitive data not logged
243
+ - [ ] If LLM-integrated: prompt injection prevention in place
@@ -0,0 +1,2 @@
1
+ [.ShellClassInfo]
2
+ IconResource=C:\Program Files\Google\Drive File Stream\122.0.1.0\GoogleDriveFS.exe,27
@@ -0,0 +1,202 @@
1
+ # Docker Standards
2
+
3
+ These rules are MANDATORY. Violations fail the task. No exceptions.
4
+
5
+ ---
6
+
7
+ ## 1. Dockerfile — Multi-Stage Builds
8
+
9
+ ```
10
+ MANDATORY:
11
+ ├── Use multi-stage builds — separate build and runtime stages
12
+ ├── Final stage uses a minimal base image (alpine, distroless, slim)
13
+ ├── NEVER install dev dependencies in the runtime stage
14
+ ├── Pin base image versions — NEVER use :latest
15
+ └── One service per container — not multiple processes
16
+ ```
17
+
18
+ **BAD**
19
+ ```dockerfile
20
+ FROM node:20
21
+ COPY . .
22
+ RUN npm install
23
+ CMD ["node", "server.js"]
24
+ ```
25
+
26
+ **GOOD**
27
+ ```dockerfile
28
+ # Build stage
29
+ FROM node:20-alpine AS builder
30
+ WORKDIR /app
31
+ COPY package*.json ./
32
+ RUN npm ci --production=false
33
+ COPY . .
34
+ RUN npm run build
35
+
36
+ # Runtime stage
37
+ FROM node:20-alpine
38
+ WORKDIR /app
39
+ COPY --from=builder /app/dist ./dist
40
+ COPY --from=builder /app/node_modules ./node_modules
41
+ COPY package*.json ./
42
+ USER node
43
+ EXPOSE 3000
44
+ CMD ["node", "dist/server.js"]
45
+ ```
46
+
47
+ ---
48
+
49
+ ## 2. Layer Optimization
50
+
51
+ ```
52
+ MANDATORY:
53
+ ├── Copy package.json/lock files BEFORE source code — leverage layer cache
54
+ ├── Use .dockerignore to exclude node_modules, .git, .env, build artifacts
55
+ ├── Combine RUN commands where logical — each RUN creates a layer
56
+ ├── Clean up caches in the same RUN that creates them
57
+ └── Order instructions from least-changing to most-changing
58
+ ```
59
+
60
+ **GOOD** `.dockerignore`:
61
+ ```
62
+ node_modules
63
+ .git
64
+ .env*
65
+ dist
66
+ *.md
67
+ .gsd-t
68
+ ```
69
+
70
+ ---
71
+
72
+ ## 3. Security
73
+
74
+ ```
75
+ MANDATORY:
76
+ ├── Run as non-root user (USER node, USER nobody, or create a dedicated user)
77
+ ├── NEVER copy .env files into the image — use runtime env vars or secrets
78
+ ├── NEVER hardcode secrets, tokens, or passwords in Dockerfile
79
+ ├── Use COPY not ADD (ADD can auto-extract archives and fetch URLs — too implicit)
80
+ ├── Scan images for vulnerabilities (docker scout, trivy, snyk)
81
+ └── Set HEALTHCHECK instruction for production images
82
+ ```
83
+
84
+ ---
85
+
86
+ ## 4. Docker Compose
87
+
88
+ ```
89
+ MANDATORY:
90
+ ├── Use compose.yaml (not docker-compose.yml — modern naming)
91
+ ├── Always specify depends_on with condition: service_healthy where possible
92
+ ├── Use named volumes for persistent data — NEVER bind-mount data directories in production
93
+ ├── Define networks explicitly — don't rely on the default bridge
94
+ ├── Environment variables via env_file — not inline in compose.yaml
95
+ └── Pin image versions in compose — no :latest
96
+ ```
97
+
98
+ **GOOD**
99
+ ```yaml
100
+ services:
101
+ api:
102
+ build:
103
+ context: .
104
+ dockerfile: Dockerfile
105
+ ports:
106
+ - "3000:3000"
107
+ env_file: .env
108
+ depends_on:
109
+ db:
110
+ condition: service_healthy
111
+ networks:
112
+ - app-network
113
+
114
+ db:
115
+ image: postgres:16-alpine
116
+ volumes:
117
+ - pgdata:/var/lib/postgresql/data
118
+ healthcheck:
119
+ test: ["CMD-SHELL", "pg_isready -U postgres"]
120
+ interval: 10s
121
+ timeout: 5s
122
+ retries: 5
123
+ networks:
124
+ - app-network
125
+
126
+ volumes:
127
+ pgdata:
128
+
129
+ networks:
130
+ app-network:
131
+ ```
132
+
133
+ ---
134
+
135
+ ## 5. Image Tagging
136
+
137
+ ```
138
+ MANDATORY:
139
+ ├── Tag with semantic version: myapp:1.2.3
140
+ ├── Also tag with git SHA for traceability: myapp:abc1234
141
+ ├── Tag :latest only on the main/production branch
142
+ ├── NEVER push untagged images to a registry
143
+ └── Use consistent naming: {registry}/{org}/{app}:{tag}
144
+ ```
145
+
146
+ ---
147
+
148
+ ## 6. Development vs Production
149
+
150
+ ```
151
+ MANDATORY:
152
+ ├── Use compose.override.yaml for dev-specific config (hot reload, debug ports)
153
+ ├── Dev: bind-mount source code for hot reload
154
+ ├── Prod: COPY built artifacts — no bind mounts
155
+ ├── Dev: include dev dependencies and debug tools
156
+ ├── Prod: production dependencies only, no source maps
157
+ └── NEVER use the dev image in production
158
+ ```
159
+
160
+ ---
161
+
162
+ ## 7. Health Checks
163
+
164
+ ```
165
+ MANDATORY for production:
166
+ ├── HEALTHCHECK in Dockerfile for standalone containers
167
+ ├── healthcheck in compose for orchestrated services
168
+ ├── Check actual readiness (HTTP endpoint, DB connection) — not just process alive
169
+ ├── Reasonable intervals: 10-30s interval, 3-5 retries
170
+ └── Lightweight check — don't hit expensive endpoints
171
+ ```
172
+
173
+ ---
174
+
175
+ ## 8. Anti-Patterns
176
+
177
+ ```
178
+ NEVER:
179
+ ├── :latest in production — pin versions
180
+ ├── Root user in containers — always USER non-root
181
+ ├── Secrets in build args or ENV — use runtime secrets
182
+ ├── ADD when COPY suffices
183
+ ├── Multiple services in one container — one process per container
184
+ ├── Ignoring .dockerignore — bloated images and leaked files
185
+ ├── apt-get install without cleanup in the same RUN
186
+ └── Bind-mounting host paths in production compose
187
+ ```
188
+
189
+ ---
190
+
191
+ ## Docker Verification Checklist
192
+
193
+ - [ ] Multi-stage build with minimal runtime image
194
+ - [ ] Base images pinned to specific versions
195
+ - [ ] .dockerignore excludes node_modules, .git, .env
196
+ - [ ] Runs as non-root user
197
+ - [ ] No secrets in Dockerfile or build args
198
+ - [ ] Layer cache optimized (package files before source)
199
+ - [ ] HEALTHCHECK defined
200
+ - [ ] Compose uses named volumes and explicit networks
201
+ - [ ] Images tagged with version and git SHA
202
+ - [ ] Dev and prod configs separated