@tekyzinc/gsd-t 2.46.11 → 2.50.11
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 +11 -0
- package/README.md +22 -2
- package/bin/debug-ledger.js +193 -0
- package/bin/gsd-t.js +259 -1
- package/commands/gsd-t-debug.md +64 -1
- package/commands/gsd-t-execute.md +79 -3
- package/commands/gsd-t-help.md +18 -2
- package/commands/gsd-t-init.md +7 -0
- package/commands/gsd-t-integrate.md +16 -0
- package/commands/gsd-t-quick.md +56 -1
- package/commands/gsd-t-test-sync.md +5 -1
- package/commands/gsd-t-verify.md +6 -1
- package/commands/gsd-t-wave.md +26 -0
- package/docs/GSD-T-README.md +83 -1
- package/docs/architecture.md +9 -1
- package/docs/requirements.md +30 -0
- package/package.json +1 -1
- package/templates/CLAUDE-global.md +19 -2
- 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
|
@@ -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
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
# Firebase Standards
|
|
2
|
+
|
|
3
|
+
These rules are MANDATORY. Violations fail the task. No exceptions.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## 1. Firestore Security Rules
|
|
8
|
+
|
|
9
|
+
```
|
|
10
|
+
MANDATORY:
|
|
11
|
+
├── Default-deny: rules start with allow read, write: if false;
|
|
12
|
+
├── Write granular rules per collection and operation (read, create, update, delete)
|
|
13
|
+
├── Use request.auth.uid for user-scoped access — NEVER trust client-sent IDs
|
|
14
|
+
├── Validate data shape in rules: request.resource.data.field is string
|
|
15
|
+
├── Test rules with the Firebase Emulator before deploying
|
|
16
|
+
└── NEVER use allow read, write: if true in production
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
**GOOD**
|
|
20
|
+
```
|
|
21
|
+
rules_version = '2';
|
|
22
|
+
service cloud.firestore {
|
|
23
|
+
match /databases/{database}/documents {
|
|
24
|
+
match /users/{userId} {
|
|
25
|
+
allow read: if request.auth != null && request.auth.uid == userId;
|
|
26
|
+
allow update: if request.auth != null && request.auth.uid == userId
|
|
27
|
+
&& request.resource.data.keys().hasOnly(['displayName', 'avatar', 'updatedAt'])
|
|
28
|
+
&& request.resource.data.displayName is string
|
|
29
|
+
&& request.resource.data.displayName.size() <= 100;
|
|
30
|
+
allow create, delete: if false;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
---
|
|
37
|
+
|
|
38
|
+
## 2. Firestore Data Modeling
|
|
39
|
+
|
|
40
|
+
```
|
|
41
|
+
MANDATORY:
|
|
42
|
+
├── Denormalize for read performance — Firestore charges per read, not per field
|
|
43
|
+
├── Subcollections for large or unbounded lists (messages, orders)
|
|
44
|
+
├── Embedded objects for small, bounded data that's always read together
|
|
45
|
+
├── Store document IDs as fields when needed for queries
|
|
46
|
+
├── Use server timestamps: serverTimestamp() — not client Date.now()
|
|
47
|
+
└── NEVER create deeply nested subcollection hierarchies (max 2-3 levels)
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**GOOD**
|
|
51
|
+
```typescript
|
|
52
|
+
// User document — embedded small data
|
|
53
|
+
{
|
|
54
|
+
id: "user-123",
|
|
55
|
+
displayName: "Jane Doe",
|
|
56
|
+
email: "jane@example.com",
|
|
57
|
+
settings: { theme: "dark", notifications: true }, // embedded — always read together
|
|
58
|
+
createdAt: serverTimestamp(),
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
// Orders — subcollection (unbounded, queried separately)
|
|
62
|
+
// /users/user-123/orders/{orderId}
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
---
|
|
66
|
+
|
|
67
|
+
## 3. Cloud Functions
|
|
68
|
+
|
|
69
|
+
```
|
|
70
|
+
MANDATORY:
|
|
71
|
+
├── Use v2 functions (onRequest, onCall, onDocumentWritten) — not v1
|
|
72
|
+
├── Validate ALL inputs in onCall functions — they're public endpoints
|
|
73
|
+
├── Set memory and timeout limits per function
|
|
74
|
+
├── Use secrets manager for API keys — not environment config
|
|
75
|
+
├── Idempotent design — functions may retry on failure
|
|
76
|
+
└── Keep functions focused — one responsibility per function
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
**GOOD**
|
|
80
|
+
```typescript
|
|
81
|
+
import { onCall, HttpsError } from 'firebase-functions/v2/https';
|
|
82
|
+
import { z } from 'zod';
|
|
83
|
+
|
|
84
|
+
const schema = z.object({ orderId: z.string().uuid() });
|
|
85
|
+
|
|
86
|
+
export const cancelOrder = onCall({ memory: '256MiB', timeoutSeconds: 30 }, async (request) => {
|
|
87
|
+
if (!request.auth) throw new HttpsError('unauthenticated', 'Must be logged in');
|
|
88
|
+
|
|
89
|
+
const parsed = schema.safeParse(request.data);
|
|
90
|
+
if (!parsed.success) throw new HttpsError('invalid-argument', 'Invalid input');
|
|
91
|
+
|
|
92
|
+
await db.collection('orders').doc(parsed.data.orderId).update({ status: 'cancelled' });
|
|
93
|
+
return { success: true };
|
|
94
|
+
});
|
|
95
|
+
```
|
|
96
|
+
|
|
97
|
+
---
|
|
98
|
+
|
|
99
|
+
## 4. Authentication
|
|
100
|
+
|
|
101
|
+
```
|
|
102
|
+
MANDATORY:
|
|
103
|
+
├── Use Firebase Auth — don't build custom auth alongside it
|
|
104
|
+
├── Store additional user data in Firestore — not in Auth custom claims (limited to 1KB)
|
|
105
|
+
├── Custom claims for roles/permissions only (admin, moderator)
|
|
106
|
+
├── Handle auth state with onAuthStateChanged listener
|
|
107
|
+
├── Sign out clears local state — don't leave stale data
|
|
108
|
+
└── NEVER store Firebase API keys as secrets — they're meant to be public (security rules protect data)
|
|
109
|
+
```
|
|
110
|
+
|
|
111
|
+
---
|
|
112
|
+
|
|
113
|
+
## 5. Storage Rules
|
|
114
|
+
|
|
115
|
+
```
|
|
116
|
+
MANDATORY:
|
|
117
|
+
├── Restrict uploads by file type and size in rules
|
|
118
|
+
├── User-scoped paths: /users/{userId}/avatar — match in rules
|
|
119
|
+
├── Validate content type: request.resource.contentType.matches('image/.*')
|
|
120
|
+
├── Set max file size in rules: request.resource.size < 5 * 1024 * 1024
|
|
121
|
+
└── NEVER allow public write access to storage
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
---
|
|
125
|
+
|
|
126
|
+
## 6. Emulator and Local Development
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
MANDATORY:
|
|
130
|
+
├── Use Firebase Emulator Suite for local development
|
|
131
|
+
├── Test security rules against the emulator before deploying
|
|
132
|
+
├── Seed data via emulator import — not manual dashboard entry
|
|
133
|
+
├── CI runs tests against emulators — not production
|
|
134
|
+
└── Never connect to production from local development
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
---
|
|
138
|
+
|
|
139
|
+
## 7. Anti-Patterns
|
|
140
|
+
|
|
141
|
+
```
|
|
142
|
+
NEVER:
|
|
143
|
+
├── allow read, write: if true in production rules
|
|
144
|
+
├── Trusting client-sent user IDs — use request.auth.uid
|
|
145
|
+
├── Deep subcollection nesting (4+ levels)
|
|
146
|
+
├── Large documents (> 1MB) — split into subcollections
|
|
147
|
+
├── Reading entire collections without query limits
|
|
148
|
+
├── v1 Cloud Functions for new code — use v2
|
|
149
|
+
├── Storing secrets in Firebase config — use Secret Manager
|
|
150
|
+
└── Testing against production — use emulators
|
|
151
|
+
```
|
|
152
|
+
|
|
153
|
+
---
|
|
154
|
+
|
|
155
|
+
## Firebase Verification Checklist
|
|
156
|
+
|
|
157
|
+
- [ ] Security rules default-deny with granular per-collection policies
|
|
158
|
+
- [ ] request.auth.uid used for access control — no client IDs trusted
|
|
159
|
+
- [ ] Data model optimized for reads (denormalized where appropriate)
|
|
160
|
+
- [ ] Subcollections for unbounded lists
|
|
161
|
+
- [ ] Cloud Functions v2 with input validation
|
|
162
|
+
- [ ] Functions are idempotent
|
|
163
|
+
- [ ] Storage rules restrict file type and size
|
|
164
|
+
- [ ] All rules tested against emulator
|
|
165
|
+
- [ ] serverTimestamp() used — not client timestamps
|
|
166
|
+
- [ ] No allow read, write: if true in production
|