@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.
- package/CHANGELOG.md +23 -0
- package/README.md +26 -5
- package/bin/debug-ledger.js +193 -0
- package/bin/gsd-t.js +259 -1
- package/commands/gsd-t-complete-milestone.md +2 -1
- package/commands/gsd-t-debug.md +48 -2
- package/commands/gsd-t-doc-ripple.md +148 -0
- package/commands/gsd-t-execute.md +102 -5
- package/commands/gsd-t-help.md +25 -2
- package/commands/gsd-t-integrate.md +41 -1
- package/commands/gsd-t-qa.md +26 -5
- package/commands/gsd-t-quick.md +39 -1
- package/commands/gsd-t-test-sync.md +26 -1
- package/commands/gsd-t-verify.md +8 -2
- package/commands/gsd-t-wave.md +57 -0
- package/docs/GSD-T-README.md +84 -1
- package/docs/architecture.md +9 -1
- package/docs/framework-comparison-scorecard.md +160 -0
- package/docs/requirements.md +33 -0
- package/examples/rules/desktop.ini +2 -0
- package/package.json +2 -2
- package/templates/CLAUDE-global.md +82 -4
- package/templates/stacks/_security.md +243 -0
- package/templates/stacks/desktop.ini +2 -0
- package/templates/stacks/docker.md +202 -0
- package/templates/stacks/firebase.md +166 -0
- package/templates/stacks/flutter.md +205 -0
- package/templates/stacks/github-actions.md +201 -0
- package/templates/stacks/graphql.md +216 -0
- package/templates/stacks/neo4j.md +218 -0
- package/templates/stacks/nextjs.md +184 -0
- package/templates/stacks/node-api.md +196 -0
- package/templates/stacks/playwright.md +528 -0
- package/templates/stacks/postgresql.md +225 -0
- package/templates/stacks/python.md +243 -0
- package/templates/stacks/react-native.md +216 -0
- package/templates/stacks/react.md +293 -0
- package/templates/stacks/redux.md +193 -0
- package/templates/stacks/rest-api.md +202 -0
- package/templates/stacks/supabase.md +188 -0
- package/templates/stacks/tailwind.md +169 -0
- package/templates/stacks/typescript.md +176 -0
- package/templates/stacks/vite.md +176 -0
- package/templates/stacks/vue.md +189 -0
- 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
|
-
|
|
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,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
|