skills/recovery-coach-patterns/SKILL.md
Follow Recovery Coach codebase patterns and conventions. Use when writing new code, components, API routes, or database queries. Activates for general development, code organization, styling, and architectural decisions in this project.
npx skillsauth add curiositech/windags-skills recovery-coach-patternsInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
Is this component handling user data?
├─ YES: Does it need real-time updates?
│ ├─ YES: Use Client Component with useEffect + fetch
│ └─ NO: Use Server Component with direct DB query
└─ NO: Is it interactive (forms, buttons, state)?
├─ YES: Use Client Component
└─ NO: Use Server Component
What data does this route access?
├─ Public data only → Basic rate limiting (100/min)
├─ User's own data → Auth + RLS + moderate rate limiting (30/min)
├─ Cross-user data → Auth + explicit permission check + PHI audit
└─ Admin data → requireAdmin() + strict rate limiting (10/min) + security audit
Who can access this data?
├─ User's own data only
│ └─ Use secure-db with RLS (filters automatically)
├─ Admin accessing any data
│ ├─ Call requireAdmin() first
│ └─ Log admin access with logSecurityEvent()
└─ System/background job
└─ Use regular db connection with explicit WHERE clauses
Symptoms: Using regular db instead of secure-db for user data queries
Detection: import { db } from '@/lib/db' in user-facing code
Fix:
import { db } from '@/db/secure-db'Symptoms: API route accepts unlimited requests, potential DoS
Detection: No createRateLimiter call in route handler
Fix:
rateLimitResult check before processingSymptoms: User health data appears in console.log or error messages
Detection: console.log or throw new Error containing user data
Fix:
logPHIAccess() for legitimate audit trailsSymptoms: API accepts malformed data, causing runtime errors
Detection: Missing z.object() schema or .safeParse() call
Fix:
.safeParse() and check success propertySymptoms: Component crashes when user logs out mid-session Detection: Assuming session exists without null checks Fix:
if (!session) before using session dataScenario: Add endpoint for users to submit daily wellness check-ins with mood and notes.
Expert Decision Process:
Implementation:
// src/app/api/check-in/route.ts
import { NextResponse } from 'next/server';
import { getSession } from '@/lib/auth';
import { createRateLimiter } from '@/lib/rate-limit';
import { logPHIAccess } from '@/lib/hipaa/audit';
import { db, checkIns } from '@/db/secure-db';
import { z } from 'zod';
const rateLimiter = createRateLimiter({
windowMs: 60000,
maxRequests: 30, // Health data = moderate limit
keyPrefix: 'api:check-in'
});
const CheckInSchema = z.object({
mood: z.number().min(1).max(10),
notes: z.string().max(1000).optional(),
symptoms: z.array(z.string()).max(10)
});
export async function POST(request: Request) {
// Auth check (required for user data)
const session = await getSession();
if (!session) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 });
}
// Rate limiting (prevent abuse)
const rateLimitResult = await rateLimiter.check(session.userId);
if (!rateLimitResult.allowed) {
return NextResponse.json({ error: 'Rate limit exceeded' }, { status: 429 });
}
// Input validation (prevent bad data)
const body = await request.json();
const parsed = CheckInSchema.safeParse(body);
if (!parsed.success) {
return NextResponse.json({
error: 'Invalid input',
details: parsed.error.issues
}, { status: 400 });
}
// Database operation (RLS auto-filters to user's data)
const checkIn = await db.insert(checkIns).values({
userId: session.userId,
mood: parsed.data.mood,
notes: parsed.data.notes,
symptoms: parsed.data.symptoms,
createdAt: new Date()
}).returning();
// PHI audit log (required for health data)
await logPHIAccess(session.userId, 'check-in', checkIn[0].id, 'CREATE');
return NextResponse.json(checkIn[0]);
}
What novices miss: Skip rate limiting, forget PHI audit logging, use console.log for debugging user data What experts catch: Health data needs all security layers, RLS handles user isolation automatically
Pre-submit checklist for all code changes:
getSession() called for protected routes.safeParse() usedsecure-db for user data querieslogPHIAccess() called for health data operationsany typesDO NOT use this skill for:
crisis-response-protocol insteadrecovery-community-moderator insteadmodern-drug-rehab-computer insteadWhen to delegate:
crisis-response-protocolrecovery-community-moderatormodern-drug-rehab-computerdata-ai
license: Apache-2.0 NOT for unrelated tasks outside this domain.
development
Use when designing caching strategies (cache-aside, write-through, write-behind), implementing distributed locks, building rate limiters, leaderboards, real-time streams (XADD/consumer groups), pub/sub, or tuning eviction policies. Triggers: thundering-herd on cache miss, dogpile on key expiry, Redlock vs SET-NX-PX choice, sliding-window rate limiter, hot-key on a single cluster slot, big-key blowup, MULTI/EXEC across slots, KEYS in production. NOT for Redis Cluster operations/admin (different domain), embedded KV (SQLite, leveldb), in-process LRU caches, or Memcached.
tools
Drawing the `'use client'` boundary correctly in React Server Components apps (Next.js App Router, RSC frameworks) — leaf-pushing, slot composition, serialization rules, and environment poisoning prevention. Grounded in react.dev and Next.js 16 docs.
development
Use when designing rate limiting for an API, choosing between token bucket / sliding window / leaky bucket / fixed window, implementing it in Redis, deciding edge (Cloudflare/Upstash) vs origin enforcement, sizing per-user vs per-IP vs per-endpoint quotas, returning the right 429 response with Retry-After, or fixing the boundary-burst bug in fixed-window limiters. Triggers: 429 too many requests, INCR + EXPIRE, ZADD + ZREMRANGEBYSCORE + ZCARD, X-RateLimit-Remaining header, Cloudflare WAF rate limiting rules, Upstash @upstash/ratelimit, leaky bucket shaping vs policing, distributed rate limiter consistency. NOT for DDoS mitigation specifically (different scale), CAPTCHA / bot management, full WAF design, or per-user quota billing.