start-vibing-stacks 2.6.0 → 2.7.3

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 (80) hide show
  1. package/README.md +83 -135
  2. package/dist/index.js +16 -2
  3. package/dist/migrate.d.ts +27 -0
  4. package/dist/migrate.js +217 -0
  5. package/dist/setup.js +10 -0
  6. package/package.json +1 -1
  7. package/stacks/_shared/agents/claude-md-compactor.md +1 -0
  8. package/stacks/_shared/agents/commit-manager.md +1 -0
  9. package/stacks/_shared/agents/documenter.md +1 -0
  10. package/stacks/_shared/agents/domain-updater.md +1 -0
  11. package/stacks/_shared/agents/research-web.md +1 -0
  12. package/stacks/_shared/agents/security-auditor.md +168 -0
  13. package/stacks/_shared/agents/tester.md +1 -0
  14. package/stacks/_shared/hooks/final-check.ts +205 -0
  15. package/stacks/_shared/hooks/stop-validator.ts +77 -1
  16. package/stacks/_shared/skills/accessibility-wcag22/SKILL.md +284 -0
  17. package/stacks/_shared/skills/ci-pipelines/SKILL.md +166 -0
  18. package/stacks/_shared/skills/codebase-knowledge/SKILL.md +5 -0
  19. package/stacks/_shared/skills/database-migrations/SKILL.md +256 -0
  20. package/stacks/_shared/skills/debugging-patterns/SKILL.md +5 -0
  21. package/stacks/_shared/skills/docker-patterns/SKILL.md +5 -0
  22. package/stacks/_shared/skills/docs-tracker/SKILL.md +5 -0
  23. package/stacks/_shared/skills/error-handling/SKILL.md +335 -0
  24. package/stacks/_shared/skills/final-check/SKILL.md +74 -37
  25. package/stacks/_shared/skills/git-workflow/SKILL.md +5 -0
  26. package/stacks/_shared/skills/hook-development/SKILL.md +5 -0
  27. package/stacks/_shared/skills/observability/SKILL.md +351 -0
  28. package/stacks/_shared/skills/performance-patterns/SKILL.md +5 -0
  29. package/stacks/_shared/skills/playwright-automation/SKILL.md +5 -0
  30. package/stacks/_shared/skills/quality-gate/SKILL.md +5 -0
  31. package/stacks/_shared/skills/research-cache/SKILL.md +5 -0
  32. package/stacks/_shared/skills/secrets-management/SKILL.md +245 -0
  33. package/stacks/_shared/skills/security-baseline/SKILL.md +202 -0
  34. package/stacks/_shared/skills/test-coverage/SKILL.md +5 -0
  35. package/stacks/_shared/skills/ui-ux-audit/SKILL.md +5 -0
  36. package/stacks/frontend/react/skills/preline-ui/SKILL.md +5 -0
  37. package/stacks/frontend/react/skills/react-patterns/SKILL.md +5 -0
  38. package/stacks/frontend/react/skills/react-standards/SKILL.md +5 -0
  39. package/stacks/frontend/react/skills/react-ui-patterns/SKILL.md +5 -0
  40. package/stacks/frontend/react/skills/shadcn-ui/SKILL.md +5 -0
  41. package/stacks/frontend/react/skills/tailwind-patterns/SKILL.md +5 -0
  42. package/stacks/frontend/react/skills/zod-validation/SKILL.md +5 -0
  43. package/stacks/frontend/react-inertia/skills/inertia-react/SKILL.md +5 -0
  44. package/stacks/frontend/react-inertia/skills/react-standards/SKILL.md +5 -0
  45. package/stacks/nodejs/skills/api-security-node/SKILL.md +275 -0
  46. package/stacks/nodejs/skills/bun-runtime/SKILL.md +5 -0
  47. package/stacks/nodejs/skills/mongoose-patterns/SKILL.md +5 -0
  48. package/stacks/nodejs/skills/nextjs-app-router/SKILL.md +5 -0
  49. package/stacks/nodejs/skills/trpc-api/SKILL.md +5 -0
  50. package/stacks/nodejs/skills/typescript-strict/SKILL.md +5 -0
  51. package/stacks/nodejs/stack.json +2 -1
  52. package/stacks/nodejs/workflows/ci.yml +90 -0
  53. package/stacks/nodejs/workflows/security.yml +45 -0
  54. package/stacks/php/skills/api-design/SKILL.md +5 -0
  55. package/stacks/php/skills/api-security/SKILL.md +5 -0
  56. package/stacks/php/skills/composer-workflow/SKILL.md +5 -0
  57. package/stacks/php/skills/external-api-patterns/SKILL.md +5 -0
  58. package/stacks/php/skills/inertia-react/SKILL.md +5 -0
  59. package/stacks/php/skills/laravel-inertia-i18n/SKILL.md +5 -0
  60. package/stacks/php/skills/laravel-octane/SKILL.md +5 -0
  61. package/stacks/php/skills/laravel-patterns/SKILL.md +5 -0
  62. package/stacks/php/skills/mariadb-octane/SKILL.md +5 -0
  63. package/stacks/php/skills/php-patterns/SKILL.md +5 -0
  64. package/stacks/php/skills/phpstan-analysis/SKILL.md +5 -0
  65. package/stacks/php/skills/phpunit-testing/SKILL.md +5 -0
  66. package/stacks/php/skills/security-scan-php/SKILL.md +5 -0
  67. package/stacks/php/workflows/ci.yml +106 -0
  68. package/stacks/php/workflows/security.yml +36 -0
  69. package/stacks/python/skills/api-security-python/SKILL.md +312 -0
  70. package/stacks/python/skills/async-patterns/SKILL.md +5 -0
  71. package/stacks/python/skills/django-patterns/SKILL.md +5 -0
  72. package/stacks/python/skills/fastapi-patterns/SKILL.md +5 -0
  73. package/stacks/python/skills/pydantic-validation/SKILL.md +5 -0
  74. package/stacks/python/skills/pytest-testing/SKILL.md +5 -0
  75. package/stacks/python/skills/python-patterns/SKILL.md +5 -0
  76. package/stacks/python/skills/python-performance/SKILL.md +5 -0
  77. package/stacks/python/skills/scripting-automation/SKILL.md +5 -0
  78. package/stacks/python/stack.json +2 -1
  79. package/stacks/python/workflows/ci.yml +76 -0
  80. package/stacks/python/workflows/security.yml +56 -0
@@ -1,56 +1,93 @@
1
- # Final Check — Task Completion Validator
1
+ ---
2
+ name: final-check
3
+ version: 2.0.0
4
+ description: Final validator with VETO power. Now executable — runs `npx tsx .claude/hooks/final-check.ts` to scan for debug statements, secrets, .skip, any, RCE risks, SQL concat. Blocks completion on CRITICAL/HIGH findings.
5
+ ---
2
6
 
3
- **ALWAYS invoke BEFORE completing ANY task. HAS VETO POWER.**
7
+ # Final Check Executable Validator
4
8
 
5
- > ⚠️ **VETO POWER:** If any rule is violated STOP, list violations, require fix, re-validate.
9
+ **ALWAYS run BEFORE completing ANY task. HAS VETO POWER.**
6
10
 
7
- ## Purpose
11
+ > v2.0+ promotes this from a manual checklist to an executable script. The script never trusts memory.
8
12
 
9
- Last check before task completion. Ensures nothing was forgotten.
13
+ ## How to Run
10
14
 
11
- ## Checklist
15
+ ```bash
16
+ npx tsx .claude/hooks/final-check.ts
17
+ ```
12
18
 
13
- ### 1. Code Quality
14
- - [ ] Quality gates passed (PHPStan/TypeCheck, Tests, Lint)
15
- - [ ] No `console.log` / `var_dump` left in code
16
- - [ ] No TODO/FIXME left unresolved
17
- - [ ] No hardcoded secrets or credentials
19
+ Exit codes:
20
+ - `0` clean (or only LOW/MEDIUM warnings)
21
+ - `1` at least one CRITICAL or HIGH finding → **task blocked**
18
22
 
19
- ### 2. Documentation
20
- - [ ] CLAUDE.md "Last Change" updated
21
- - [ ] Affected domain files updated
22
- - [ ] New patterns documented
23
+ ## What It Scans
23
24
 
24
- ### 3. Testing
25
- - [ ] New code has tests
26
- - [ ] Existing tests still pass
27
- - [ ] Edge cases covered
25
+ For every file in the diff (staged + unstaged + untracked) matching the active stack's source extensions, every line is checked against:
28
26
 
29
- ### 4. Git
30
- - [ ] On correct branch
31
- - [ ] All files committed
32
- - [ ] Conventional commit message
33
- - [ ] Merged to main (if complete)
27
+ | Severity | Rule | Why blocking |
28
+ |---|---|---|
29
+ | CRITICAL | Hardcoded secret pattern (api key / token / password) | Leak risk |
30
+ | CRITICAL | Public env var with `*SECRET\|*TOKEN\|*PRIVATE\|*PASSWORD\|*CREDENTIAL` | Bundles into client |
31
+ | HIGH | Arbitrary code-execution function (`eval`, Python `exec`) | RCE |
32
+ | HIGH | `subprocess` with `shell=True` (Python) | Command injection |
33
+ | HIGH | SQL string concatenation / f-string SQL | SQL injection |
34
+ | HIGH | `it.only` / `test.only` / `describe.only` / `it.skip` in committed test | False green CI |
35
+ | MEDIUM | `console.log/debug/trace` outside tests | Debug leftover, log noise |
36
+ | MEDIUM | PHP `var_dump/dd/dump/print_r` | Debug leftover |
37
+ | MEDIUM | TypeScript `any` (without `/* ok */` escape) | Erodes strict mode |
38
+ | MEDIUM | `@ts-ignore` (use `@ts-expect-error` with comment) | Silently outdated |
39
+ | MEDIUM | `@pytest.mark.skip` | Hidden test gaps |
40
+ | LOW | `print()` outside tests (Python) | Use logger |
41
+ | LOW | TODO / FIXME / XXX / HACK | Track or remove |
34
42
 
35
- ### 5. Skills Consulted
36
- - [ ] Codebase knowledge checked before implementing
37
- - [ ] Research cache checked before web search
38
- - [ ] Security patterns applied
43
+ Lines containing recognised placeholders (`<your...>`, `YOUR_X`, `placeholder`, `example.com`, `sk_test_`) are skipped to avoid false positives in `.env.example` and docs.
39
44
 
40
- ## Violation Response
45
+ ## Workflow
41
46
 
42
47
  ```
43
- BLOCKED: [Violation description]
48
+ 1. Implementation done
49
+ 2. Run npx tsx .claude/hooks/final-check.ts
50
+ 3. If exit 1 → fix, re-run
51
+ 4. If exit 0 → proceed to quality-gate → commit
52
+ ```
53
+
54
+ ## Suppressing False Positives
44
55
 
45
- Required fixes:
46
- 1. [Fix needed]
47
- 2. [Fix needed]
56
+ When a finding is intentional (e.g. an `any` in well-justified glue code):
48
57
 
49
- Re-run final-check after fixing.
58
+ ```ts
59
+ const result = (json as any) /* ok: external lib without types */;
50
60
  ```
51
61
 
62
+ Only `/* ok */` immediately after `: any` is recognised. For other rules, refactor — there is no general-purpose suppression by design.
63
+
64
+ ## Hook Wiring (Optional)
65
+
66
+ To run automatically on Stop, add to `.claude/settings.json`:
67
+
68
+ ```json
69
+ {
70
+ "hooks": {
71
+ "Stop": [{
72
+ "matcher": "*",
73
+ "hooks": [{ "type": "command", "command": "npx tsx ${CLAUDE_PROJECT_DIR}/.claude/hooks/final-check.ts" }]
74
+ }]
75
+ }
76
+ }
77
+ ```
78
+
79
+ The default Stop is `stop-validator.ts` (git/branch/CLAUDE.md/secret scan). `final-check.ts` is complementary — runs before it as a code-quality gate.
80
+
52
81
  ## Rules
53
82
 
54
- 1. **VETO POWER** — can block task completion
55
- 2. **ALL CHECKS MUST PASS** — no partial approvals
56
- 3. **RE-VALIDATE AFTER FIXES** — don't trust "I fixed it"
83
+ 1. **VETO POWER** — exit 1 blocks task completion
84
+ 2. **NEVER skip** — `--no-verify` style bypasses are forbidden
85
+ 3. **RE-RUN after fixes** — don't trust memory
86
+ 4. **One finding at a time** — fix CRITICAL first, then HIGH
87
+ 5. **Refactor over suppress** — `/* ok */` is for extraordinary cases
88
+
89
+ ## See Also
90
+
91
+ - `quality-gate` — typecheck/lint/test/build (different scope)
92
+ - `security-baseline` — what the secret/RCE rules enforce
93
+ - `stop-validator.ts` — git/branch/docs gate (sibling, complementary)
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: git-workflow
3
+ version: 1.0.0
4
+ ---
5
+
1
6
  # Git Workflow
2
7
 
3
8
  ## Branch Naming
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: hook-development
3
+ version: 1.0.0
4
+ ---
5
+
1
6
  # Hook Development — Claude Code Hooks
2
7
 
3
8
  **ALWAYS invoke when creating or modifying Claude Code hooks.**
@@ -0,0 +1,351 @@
1
+ ---
2
+ name: observability
3
+ version: 1.0.0
4
+ description: Structured logging, correlation IDs, OpenTelemetry tracing, error tracking (Sentry), metrics, and PII redaction. Invoke when adding logging, instrumentation, or debugging production issues.
5
+ ---
6
+
7
+ # Observability — Logs, Traces, Metrics
8
+
9
+ **ALWAYS invoke when adding logging, instrumentation, error tracking, or analyzing production issues.**
10
+
11
+ > Three pillars: **Logs** (what happened) + **Traces** (where time was spent) + **Metrics** (how much / how often).
12
+ > One signal: **correlation/trace IDs** that thread through all three.
13
+
14
+ ---
15
+
16
+ ## 1. Structured Logging — Mandatory
17
+
18
+ Logs are JSON, not text. Free-form strings can't be queried, aggregated, or alerted on.
19
+
20
+ ### Required fields per log line
21
+
22
+ | Field | Source |
23
+ |---|---|
24
+ | `timestamp` | ISO-8601, UTC |
25
+ | `level` | `trace` / `debug` / `info` / `warn` / `error` / `fatal` |
26
+ | `msg` | Short human description |
27
+ | `service` | Service name |
28
+ | `env` | `production` / `staging` / `development` |
29
+ | `trace_id` | OpenTelemetry trace id (W3C `traceparent`) |
30
+ | `span_id` | Current span |
31
+ | `request_id` | Inbound HTTP request id (mirror to `x-request-id` header) |
32
+ | `user_id` | Authenticated user (hash if PII concerns) — **never** email/full name |
33
+
34
+ ### Node.js — pino
35
+ ```ts
36
+ // lib/logger.ts
37
+ import pino from 'pino';
38
+ import { randomUUID } from 'crypto';
39
+
40
+ export const logger = pino({
41
+ level: process.env['LOG_LEVEL'] ?? 'info',
42
+ base: {
43
+ service: 'api',
44
+ env: process.env['NODE_ENV'],
45
+ pid: process.pid,
46
+ },
47
+ timestamp: pino.stdTimeFunctions.isoTime,
48
+ redact: {
49
+ paths: [
50
+ 'req.headers.authorization',
51
+ 'req.headers.cookie',
52
+ 'req.body.password',
53
+ 'req.body.token',
54
+ '*.password',
55
+ '*.creditCard',
56
+ '*.ssn',
57
+ ],
58
+ censor: '[REDACTED]',
59
+ },
60
+ });
61
+
62
+ // HTTP middleware: attach request_id + child logger to req
63
+ export function requestLogger(req, res, next) {
64
+ const requestId = req.headers['x-request-id'] ?? randomUUID();
65
+ res.setHeader('x-request-id', requestId);
66
+ req.log = logger.child({ request_id: requestId, method: req.method, path: req.path });
67
+ req.log.info({ event: 'request.start' });
68
+ res.on('finish', () => {
69
+ req.log.info({ event: 'request.end', status: res.statusCode, duration_ms: Date.now() - req.startTime });
70
+ });
71
+ next();
72
+ }
73
+ ```
74
+
75
+ ### Python — structlog
76
+ ```python
77
+ import structlog, logging, sys, uuid
78
+
79
+ structlog.configure(
80
+ processors=[
81
+ structlog.contextvars.merge_contextvars,
82
+ structlog.processors.add_log_level,
83
+ structlog.processors.TimeStamper(fmt="iso", utc=True),
84
+ structlog.processors.StackInfoRenderer(),
85
+ structlog.processors.format_exc_info,
86
+ structlog.processors.JSONRenderer(),
87
+ ],
88
+ wrapper_class=structlog.make_filtering_bound_logger(logging.INFO),
89
+ logger_factory=structlog.PrintLoggerFactory(file=sys.stdout),
90
+ )
91
+
92
+ log = structlog.get_logger()
93
+
94
+ # FastAPI middleware
95
+ @app.middleware("http")
96
+ async def request_logger(request, call_next):
97
+ request_id = request.headers.get("x-request-id", str(uuid.uuid4()))
98
+ structlog.contextvars.bind_contextvars(
99
+ request_id=request_id, method=request.method, path=request.url.path
100
+ )
101
+ log.info("request.start")
102
+ response = await call_next(request)
103
+ response.headers["x-request-id"] = request_id
104
+ log.info("request.end", status=response.status_code)
105
+ structlog.contextvars.clear_contextvars()
106
+ return response
107
+ ```
108
+
109
+ ### PHP — Monolog
110
+ ```php
111
+ // config/logging.php
112
+ 'channels' => [
113
+ 'json' => [
114
+ 'driver' => 'monolog',
115
+ 'handler' => Monolog\Handler\StreamHandler::class,
116
+ 'with' => ['stream' => 'php://stdout'],
117
+ 'formatter' => Monolog\Formatter\JsonFormatter::class,
118
+ 'processors' => [
119
+ Monolog\Processor\WebProcessor::class,
120
+ Monolog\Processor\UidProcessor::class,
121
+ ],
122
+ ],
123
+ ],
124
+ ```
125
+
126
+ ---
127
+
128
+ ## 2. Log Levels — Use Them Right
129
+
130
+ | Level | When |
131
+ |---|---|
132
+ | `trace` | Verbose diagnostics, off in prod |
133
+ | `debug` | Development helper, off in prod by default |
134
+ | `info` | Business events: signup, payment, login, job completed |
135
+ | `warn` | Recoverable anomaly: retry, deprecated path, fallback used |
136
+ | `error` | Operation failed for one user/request, system continues |
137
+ | `fatal` | Cannot continue, process exits |
138
+
139
+ Default prod level: `info`. Errors should always page or alert. `debug` flooding logs is a cost issue.
140
+
141
+ ---
142
+
143
+ ## 3. PII Redaction — Mandatory
144
+
145
+ Never log:
146
+ - Passwords, hashes, tokens, cookies, `Authorization` headers
147
+ - Full credit card / IBAN / SSN / passport
148
+ - Plaintext email if your jurisdiction (GDPR/LGPD) treats it as PII without legitimate basis
149
+ - Full request body or full response body without filtering
150
+
151
+ Redact at the logger level (so it can't be bypassed by a forgetful caller):
152
+
153
+ ```ts
154
+ // pino redact paths (above)
155
+ // or wrap manually:
156
+ function safeBody(body: any) {
157
+ const out = { ...body };
158
+ for (const k of ['password', 'token', 'cookie', 'authorization']) {
159
+ if (k in out) out[k] = '[REDACTED]';
160
+ }
161
+ return out;
162
+ }
163
+ ```
164
+
165
+ For email: log a hash of the email or the first 2 chars + domain (`jo***@example.com`). Document the policy.
166
+
167
+ ---
168
+
169
+ ## 4. Distributed Tracing — OpenTelemetry
170
+
171
+ Tracing answers "where did the request spend time" across services.
172
+
173
+ ### Node.js (auto-instrumentation)
174
+ ```ts
175
+ // instrumentation.ts — load BEFORE any other import
176
+ import { NodeSDK } from '@opentelemetry/sdk-node';
177
+ import { getNodeAutoInstrumentations } from '@opentelemetry/auto-instrumentations-node';
178
+ import { OTLPTraceExporter } from '@opentelemetry/exporter-trace-otlp-http';
179
+ import { Resource } from '@opentelemetry/resources';
180
+ import { ATTR_SERVICE_NAME } from '@opentelemetry/semantic-conventions';
181
+
182
+ new NodeSDK({
183
+ resource: new Resource({ [ATTR_SERVICE_NAME]: 'api' }),
184
+ traceExporter: new OTLPTraceExporter({ url: process.env['OTEL_EXPORTER_OTLP_ENDPOINT'] }),
185
+ instrumentations: [getNodeAutoInstrumentations()],
186
+ }).start();
187
+ ```
188
+
189
+ Run: `node --import ./instrumentation.js dist/index.js`
190
+
191
+ ### Python (FastAPI)
192
+ ```python
193
+ from opentelemetry.instrumentation.fastapi import FastAPIInstrumentor
194
+ from opentelemetry.instrumentation.sqlalchemy import SQLAlchemyInstrumentor
195
+ from opentelemetry.instrumentation.httpx import HTTPXClientInstrumentor
196
+
197
+ FastAPIInstrumentor.instrument_app(app)
198
+ SQLAlchemyInstrumentor().instrument(engine=engine)
199
+ HTTPXClientInstrumentor().instrument()
200
+ ```
201
+
202
+ ### Manual span — when you want to time business logic
203
+ ```ts
204
+ import { trace } from '@opentelemetry/api';
205
+ const tracer = trace.getTracer('billing');
206
+
207
+ await tracer.startActiveSpan('charge_customer', async (span) => {
208
+ try {
209
+ span.setAttribute('customer.id', customerId);
210
+ const charge = await stripe.charges.create({ amount, customer: customerId });
211
+ span.setAttribute('charge.id', charge.id);
212
+ return charge;
213
+ } catch (err) {
214
+ span.recordException(err);
215
+ span.setStatus({ code: 2 /* ERROR */ });
216
+ throw err;
217
+ } finally {
218
+ span.end();
219
+ }
220
+ });
221
+ ```
222
+
223
+ ---
224
+
225
+ ## 5. Error Tracking — Sentry
226
+
227
+ Pair with structured logging. Sentry is for **alertable** errors with full stack + breadcrumbs; logs are for **everything**.
228
+
229
+ ### Node.js
230
+ ```ts
231
+ import * as Sentry from '@sentry/node';
232
+
233
+ Sentry.init({
234
+ dsn: process.env['SENTRY_DSN'],
235
+ environment: process.env['NODE_ENV'],
236
+ tracesSampleRate: 0.1,
237
+ profilesSampleRate: 0.1,
238
+ beforeSend(event) {
239
+ // Defense in depth — strip if logger redaction missed it
240
+ if (event.request?.cookies) delete event.request.cookies;
241
+ if (event.request?.headers?.['authorization']) {
242
+ event.request.headers['authorization'] = '[REDACTED]';
243
+ }
244
+ return event;
245
+ },
246
+ });
247
+ ```
248
+
249
+ ### Python
250
+ ```python
251
+ import sentry_sdk
252
+ from sentry_sdk.integrations.fastapi import FastApiIntegration
253
+ from sentry_sdk.scrubber import EventScrubber, DEFAULT_DENYLIST
254
+
255
+ sentry_sdk.init(
256
+ dsn=os.environ["SENTRY_DSN"],
257
+ environment=os.environ["APP_ENV"],
258
+ traces_sample_rate=0.1,
259
+ integrations=[FastApiIntegration()],
260
+ event_scrubber=EventScrubber(denylist=DEFAULT_DENYLIST + ["jwt", "session"]),
261
+ send_default_pii=False,
262
+ )
263
+ ```
264
+
265
+ ---
266
+
267
+ ## 6. Metrics
268
+
269
+ Track **RED** (Rate / Errors / Duration) on every endpoint and **USE** (Utilization / Saturation / Errors) on every resource.
270
+
271
+ OpenTelemetry metrics + Prometheus exporter, or vendor SDK (Datadog, New Relic).
272
+
273
+ ```ts
274
+ import { metrics } from '@opentelemetry/api';
275
+ const meter = metrics.getMeter('api');
276
+
277
+ const httpDuration = meter.createHistogram('http.server.duration', { unit: 'ms' });
278
+ const ordersCreated = meter.createCounter('orders.created');
279
+
280
+ httpDuration.record(durationMs, { method, route, status: String(statusCode) });
281
+ ordersCreated.add(1, { plan: order.plan });
282
+ ```
283
+
284
+ Cardinality rule: never tag with user_id, email, or unbounded values — explodes time-series storage. Use `route`, `status`, `plan`, etc.
285
+
286
+ ---
287
+
288
+ ## 7. Health Checks
289
+
290
+ Two endpoints, distinct semantics:
291
+
292
+ ```ts
293
+ app.get('/healthz', (_, res) => res.json({ ok: true })); // liveness — am I running?
294
+
295
+ app.get('/readyz', async (_, res) => { // readiness — can I serve?
296
+ const checks = await Promise.allSettled([
297
+ db.raw('SELECT 1'),
298
+ redis.ping(),
299
+ ]);
300
+ const allOk = checks.every(c => c.status === 'fulfilled');
301
+ res.status(allOk ? 200 : 503).json({ ok: allOk, checks });
302
+ });
303
+ ```
304
+
305
+ Kubernetes uses `livenessProbe` → `/healthz` (restart on fail) and `readinessProbe` → `/readyz` (remove from LB on fail).
306
+
307
+ ---
308
+
309
+ ## 8. Audit Log — Separate Stream
310
+
311
+ Security-relevant events go to a dedicated, append-only stream:
312
+
313
+ - Logins (success + failure)
314
+ - Authorization denials
315
+ - Permission/role changes
316
+ - Admin actions (impersonation, data exports, deletes)
317
+ - Payment events
318
+ - Data access (when required by compliance: HIPAA, SOC 2)
319
+
320
+ Different retention (often longer), different access (security team), different integrity guarantees (immutable, hash-chained).
321
+
322
+ ---
323
+
324
+ ## Pre-Commit Checklist
325
+
326
+ - [ ] Logger configured with redact paths for password/token/cookie/authorization
327
+ - [ ] All endpoints emit `request.start` / `request.end` with `request_id`
328
+ - [ ] Errors include stack trace and `trace_id`
329
+ - [ ] No `console.log` / `print` / `dd()` left in code (use the logger)
330
+ - [ ] No PII in info-level logs
331
+ - [ ] Sentry initialized with `beforeSend` scrubber
332
+ - [ ] Tracing initialized at process start (before app code)
333
+ - [ ] `/healthz` + `/readyz` endpoints exist
334
+
335
+ ## FORBIDDEN
336
+
337
+ | Pattern | Reason |
338
+ |---|---|
339
+ | `console.log(req.body)` | Leaks passwords, tokens |
340
+ | Logger without redaction | Future caller will leak |
341
+ | Unbounded label cardinality (user_id as metric tag) | Cost explosion |
342
+ | Same severity for everything (all `info`) | No alerting signal |
343
+ | Tracing in dev only | Prod is where you need it |
344
+ | Sentry without scrubber | PII in error reports |
345
+ | Audit log in same stream as app log | Tamper risk, retention conflict |
346
+
347
+ ## See Also
348
+
349
+ - `secrets-management` — what NEVER to log
350
+ - `error-handling` — Result types and error taxonomy
351
+ - `security-baseline` — A09: Security Logging Failures
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: performance-patterns
3
+ version: 1.0.0
4
+ ---
5
+
1
6
  # Performance Patterns
2
7
 
3
8
  **Invoke when app is slow or needs optimization.**
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: playwright-automation
3
+ version: 1.0.0
4
+ ---
5
+
1
6
  # Playwright Automation — E2E Testing
2
7
 
3
8
  **ALWAYS invoke when writing E2E tests or browser automation.**
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: quality-gate
3
+ version: 1.0.0
4
+ ---
5
+
1
6
  # Quality Gate — Verification System
2
7
 
3
8
  **ALWAYS invoke BEFORE any commit.**
@@ -1,3 +1,8 @@
1
+ ---
2
+ name: research-cache
3
+ version: 1.0.0
4
+ ---
5
+
1
6
  # Research Cache — Best Practices Storage
2
7
 
3
8
  **ALWAYS invoke BEFORE any web research.**