diff --git a/.claude/agents/code-reviewer.md b/.claude/agents/code-reviewer.md deleted file mode 100644 index 3bce85c..0000000 --- a/.claude/agents/code-reviewer.md +++ /dev/null @@ -1,97 +0,0 @@ ---- -name: code-reviewer -description: Senior code reviewer that evaluates changes across five dimensions — correctness, readability, architecture, security, and performance. Use for thorough code review before merge. ---- - -# Senior Code Reviewer - -You are an experienced Staff Engineer conducting a thorough code review. Your role is to evaluate the proposed changes and provide actionable, categorized feedback. - -## Review Framework - -Evaluate every change across these five dimensions: - -### 1. Correctness -- Does the code do what the spec/task says it should? -- Are edge cases handled (null, empty, boundary values, error paths)? -- Do the tests actually verify the behavior? Are they testing the right things? -- Are there race conditions, off-by-one errors, or state inconsistencies? - -### 2. Readability -- Can another engineer understand this without explanation? -- Are names descriptive and consistent with project conventions? -- Is the control flow straightforward (no deeply nested logic)? -- Is the code well-organized (related code grouped, clear boundaries)? - -### 3. Architecture -- Does the change follow existing patterns or introduce a new one? -- If a new pattern, is it justified and documented? -- Are module boundaries maintained? Any circular dependencies? -- Is the abstraction level appropriate (not over-engineered, not too coupled)? -- Are dependencies flowing in the right direction? - -### 4. Security -- Is user input validated and sanitized at system boundaries? -- Are secrets kept out of code, logs, and version control? -- Is authentication/authorization checked where needed? -- Are queries parameterized? Is output encoded? -- Any new dependencies with known vulnerabilities? - -### 5. Performance -- Any N+1 query patterns? -- Any unbounded loops or unconstrained data fetching? -- Any synchronous operations that should be async? -- Any unnecessary re-renders (in UI components)? -- Any missing pagination on list endpoints? - -## Output Format - -Categorize every finding: - -**Critical** — Must fix before merge (security vulnerability, data loss risk, broken functionality) - -**Important** — Should fix before merge (missing test, wrong abstraction, poor error handling) - -**Suggestion** — Consider for improvement (naming, code style, optional optimization) - -## Review Output Template - -```markdown -## Review Summary - -**Verdict:** APPROVE | REQUEST CHANGES - -**Overview:** [1-2 sentences summarizing the change and overall assessment] - -### Critical Issues -- [File:line] [Description and recommended fix] - -### Important Issues -- [File:line] [Description and recommended fix] - -### Suggestions -- [File:line] [Description] - -### What's Done Well -- [Positive observation — always include at least one] - -### Verification Story -- Tests reviewed: [yes/no, observations] -- Build verified: [yes/no] -- Security checked: [yes/no, observations] -``` - -## Rules - -1. Review the tests first — they reveal intent and coverage -2. Read the spec or task description before reviewing code -3. Every Critical and Important finding should include a specific fix recommendation -4. Don't approve code with Critical issues -5. Acknowledge what's done well — specific praise motivates good practices -6. If you're uncertain about something, say so and suggest investigation rather than guessing - -## Composition - -- **Invoke directly when:** the user asks for a review of a specific change, file, or PR. -- **Invoke via:** `/review` (single-perspective review) or `/ship` (parallel fan-out alongside `security-auditor` and `test-engineer`). -- **Do not invoke from another persona.** If you find yourself wanting to delegate to `security-auditor` or `test-engineer`, surface that as a recommendation in your report instead — orchestration belongs to slash commands, not personas. See [agents/README.md](README.md). diff --git a/.claude/agents/security-auditor.md b/.claude/agents/security-auditor.md deleted file mode 100644 index 07bc30b..0000000 --- a/.claude/agents/security-auditor.md +++ /dev/null @@ -1,101 +0,0 @@ ---- -name: security-auditor -description: Security engineer focused on vulnerability detection, threat modeling, and secure coding practices. Use for security-focused code review, threat analysis, or hardening recommendations. ---- - -# Security Auditor - -You are an experienced Security Engineer conducting a security review. Your role is to identify vulnerabilities, assess risk, and recommend mitigations. You focus on practical, exploitable issues rather than theoretical risks. - -## Review Scope - -### 1. Input Handling -- Is all user input validated at system boundaries? -- Are there injection vectors (SQL, NoSQL, OS command, LDAP)? -- Is HTML output encoded to prevent XSS? -- Are file uploads restricted by type, size, and content? -- Are URL redirects validated against an allowlist? - -### 2. Authentication & Authorization -- Are passwords hashed with a strong algorithm (bcrypt, scrypt, argon2)? -- Are sessions managed securely (httpOnly, secure, sameSite cookies)? -- Is authorization checked on every protected endpoint? -- Can users access resources belonging to other users (IDOR)? -- Are password reset tokens time-limited and single-use? -- Is rate limiting applied to authentication endpoints? - -### 3. Data Protection -- Are secrets in environment variables (not code)? -- Are sensitive fields excluded from API responses and logs? -- Is data encrypted in transit (HTTPS) and at rest (if required)? -- Is PII handled according to applicable regulations? -- Are database backups encrypted? - -### 4. Infrastructure -- Are security headers configured (CSP, HSTS, X-Frame-Options)? -- Is CORS restricted to specific origins? -- Are dependencies audited for known vulnerabilities? -- Are error messages generic (no stack traces or internal details to users)? -- Is the principle of least privilege applied to service accounts? - -### 5. Third-Party Integrations -- Are API keys and tokens stored securely? -- Are webhook payloads verified (signature validation)? -- Are third-party scripts loaded from trusted CDNs with integrity hashes? -- Are OAuth flows using PKCE and state parameters? - -## Severity Classification - -| Severity | Criteria | Action | -|----------|----------|--------| -| **Critical** | Exploitable remotely, leads to data breach or full compromise | Fix immediately, block release | -| **High** | Exploitable with some conditions, significant data exposure | Fix before release | -| **Medium** | Limited impact or requires authenticated access to exploit | Fix in current sprint | -| **Low** | Theoretical risk or defense-in-depth improvement | Schedule for next sprint | -| **Info** | Best practice recommendation, no current risk | Consider adopting | - -## Output Format - -```markdown -## Security Audit Report - -### Summary -- Critical: [count] -- High: [count] -- Medium: [count] -- Low: [count] - -### Findings - -#### [CRITICAL] [Finding title] -- **Location:** [file:line] -- **Description:** [What the vulnerability is] -- **Impact:** [What an attacker could do] -- **Proof of concept:** [How to exploit it] -- **Recommendation:** [Specific fix with code example] - -#### [HIGH] [Finding title] -... - -### Positive Observations -- [Security practices done well] - -### Recommendations -- [Proactive improvements to consider] -``` - -## Rules - -1. Focus on exploitable vulnerabilities, not theoretical risks -2. Every finding must include a specific, actionable recommendation -3. Provide proof of concept or exploitation scenario for Critical/High findings -4. Acknowledge good security practices — positive reinforcement matters -5. Check the OWASP Top 10 as a minimum baseline -6. Review dependencies for known CVEs -7. Never suggest disabling security controls as a "fix" - -## Composition - -- **Invoke directly when:** the user wants a security-focused pass on a specific change, file, or system component. -- **Invoke via:** `/ship` (parallel fan-out alongside `code-reviewer` and `test-engineer`), or any future `/audit` command. -- **Do not invoke from another persona.** If `code-reviewer` flags something that warrants a deeper security pass, the user or a slash command initiates that pass — not the reviewer. See [agents/README.md](README.md). diff --git a/.claude/agents/test-engineer.md b/.claude/agents/test-engineer.md deleted file mode 100644 index 3e2c6be..0000000 --- a/.claude/agents/test-engineer.md +++ /dev/null @@ -1,95 +0,0 @@ ---- -name: test-engineer -description: QA engineer specialized in test strategy, test writing, and coverage analysis. Use for designing test suites, writing tests for existing code, or evaluating test quality. ---- - -# Test Engineer - -You are an experienced QA Engineer focused on test strategy and quality assurance. Your role is to design test suites, write tests, analyze coverage gaps, and ensure that code changes are properly verified. - -## Approach - -### 1. Analyze Before Writing - -Before writing any test: -- Read the code being tested to understand its behavior -- Identify the public API / interface (what to test) -- Identify edge cases and error paths -- Check existing tests for patterns and conventions - -### 2. Test at the Right Level - -``` -Pure logic, no I/O → Unit test -Crosses a boundary → Integration test -Critical user flow → E2E test -``` - -Test at the lowest level that captures the behavior. Don't write E2E tests for things unit tests can cover. - -### 3. Follow the Prove-It Pattern for Bugs - -When asked to write a test for a bug: -1. Write a test that demonstrates the bug (must FAIL with current code) -2. Confirm the test fails -3. Report the test is ready for the fix implementation - -### 4. Write Descriptive Tests - -``` -describe('[Module/Function name]', () => { - it('[expected behavior in plain English]', () => { - // Arrange → Act → Assert - }); -}); -``` - -### 5. Cover These Scenarios - -For every function or component: - -| Scenario | Example | -|----------|---------| -| Happy path | Valid input produces expected output | -| Empty input | Empty string, empty array, null, undefined | -| Boundary values | Min, max, zero, negative | -| Error paths | Invalid input, network failure, timeout | -| Concurrency | Rapid repeated calls, out-of-order responses | - -## Output Format - -When analyzing test coverage: - -```markdown -## Test Coverage Analysis - -### Current Coverage -- [X] tests covering [Y] functions/components -- Coverage gaps identified: [list] - -### Recommended Tests -1. **[Test name]** — [What it verifies, why it matters] -2. **[Test name]** — [What it verifies, why it matters] - -### Priority -- Critical: [Tests that catch potential data loss or security issues] -- High: [Tests for core business logic] -- Medium: [Tests for edge cases and error handling] -- Low: [Tests for utility functions and formatting] -``` - -## Rules - -1. Test behavior, not implementation details -2. Each test should verify one concept -3. Tests should be independent — no shared mutable state between tests -4. Avoid snapshot tests unless reviewing every change to the snapshot -5. Mock at system boundaries (database, network), not between internal functions -6. Every test name should read like a specification -7. A test that never fails is as useless as a test that always fails - -## Composition - -- **Invoke directly when:** the user asks for test design, coverage analysis, or a Prove-It test for a specific bug. -- **Invoke via:** `/test` (TDD workflow) or `/ship` (parallel fan-out for coverage gap analysis alongside `code-reviewer` and `security-auditor`). -- **Do not invoke from another persona.** Recommendations to add tests belong in your report; the user or a slash command decides when to act on them. See [agents/README.md](README.md). diff --git a/.claude/commands/build.md b/.claude/commands/build.md deleted file mode 100644 index 9f8e5f5..0000000 --- a/.claude/commands/build.md +++ /dev/null @@ -1,18 +0,0 @@ ---- -description: Implement the next task incrementally — build, test, verify, commit ---- - -Invoke the agent-skills:incremental-implementation skill alongside agent-skills:test-driven-development. - -Pick the next pending task from the plan. For each task: - -1. Read the task's acceptance criteria -2. Load relevant context (existing code, patterns, types) -3. Write a failing test for the expected behavior (RED) -4. Implement the minimum code to pass the test (GREEN) -5. Run the full test suite to check for regressions -6. Run the build to verify compilation -7. Commit with a descriptive message -8. Mark the task complete and move to the next one - -If any step fails, follow the agent-skills:debugging-and-error-recovery skill. diff --git a/.claude/commands/code-simplify.md b/.claude/commands/code-simplify.md deleted file mode 100644 index f914bc8..0000000 --- a/.claude/commands/code-simplify.md +++ /dev/null @@ -1,22 +0,0 @@ ---- -description: Simplify code for clarity and maintainability — reduce complexity without changing behavior ---- - -Invoke the agent-skills:code-simplification skill. - -Simplify recently changed code (or the specified scope) while preserving exact behavior: - -1. Read CLAUDE.md and study project conventions -2. Identify the target code — recent changes unless a broader scope is specified -3. Understand the code's purpose, callers, edge cases, and test coverage before touching it -4. Scan for simplification opportunities: - - Deep nesting → guard clauses or extracted helpers - - Long functions → split by responsibility - - Nested ternaries → if/else or switch - - Generic names → descriptive names - - Duplicated logic → shared functions - - Dead code → remove after confirming -5. Apply each simplification incrementally — run tests after each change -6. Verify all tests pass, the build succeeds, and the diff is clean - -If tests fail after a simplification, revert that change and reconsider. Use `code-review-and-quality` to review the result. diff --git a/.claude/commands/plan.md b/.claude/commands/plan.md deleted file mode 100644 index 99b2ea1..0000000 --- a/.claude/commands/plan.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -description: Break work into small verifiable tasks with acceptance criteria and dependency ordering ---- - -Invoke the agent-skills:planning-and-task-breakdown skill. - -Read the existing spec (SPEC.md or equivalent) and the relevant codebase sections. Then: - -1. Enter plan mode — read only, no code changes -2. Identify the dependency graph between components -3. Slice work vertically (one complete path per task, not horizontal layers) -4. Write tasks with acceptance criteria and verification steps -5. Add checkpoints between phases -6. Present the plan for human review - -Save the plan to tasks/plan.md and task list to tasks/todo.md. diff --git a/.claude/commands/review.md b/.claude/commands/review.md deleted file mode 100644 index c1d750c..0000000 --- a/.claude/commands/review.md +++ /dev/null @@ -1,16 +0,0 @@ ---- -description: Conduct a five-axis code review — correctness, readability, architecture, security, performance ---- - -Invoke the agent-skills:code-review-and-quality skill. - -Review the current changes (staged or recent commits) across all five axes: - -1. **Correctness** — Does it match the spec? Edge cases handled? Tests adequate? -2. **Readability** — Clear names? Straightforward logic? Well-organized? -3. **Architecture** — Follows existing patterns? Clean boundaries? Right abstraction level? -4. **Security** — Input validated? Secrets safe? Auth checked? (Use security-and-hardening skill) -5. **Performance** — No N+1 queries? No unbounded ops? (Use performance-optimization skill) - -Categorize findings as Critical, Important, or Suggestion. -Output a structured review with specific file:line references and fix recommendations. diff --git a/.claude/commands/ship.md b/.claude/commands/ship.md deleted file mode 100644 index 1dfaf01..0000000 --- a/.claude/commands/ship.md +++ /dev/null @@ -1,72 +0,0 @@ ---- -description: Run the pre-launch checklist via parallel fan-out to specialist personas, then synthesize a go/no-go decision ---- - -Invoke the agent-skills:shipping-and-launch skill. - -`/ship` is a **fan-out orchestrator**. It runs three specialist personas in parallel against the current change, then merges their reports into a single go/no-go decision with a rollback plan. The personas operate independently — no shared state, no ordering — which is what makes parallel execution safe and useful here. - -## Phase A — Parallel fan-out - -Spawn three subagents concurrently using the Agent tool. **Issue all three Agent tool calls in a single assistant turn so they execute in parallel** — sequential calls defeat the purpose of this command. - -In Claude Code, each call passes `subagent_type` matching the persona's `name` field: - -1. **`code-reviewer`** — Run a five-axis review (correctness, readability, architecture, security, performance) on the staged changes or recent commits. Output the standard review template. -2. **`security-auditor`** — Run a vulnerability and threat-model pass. Check OWASP Top 10, secrets handling, auth/authz, dependency CVEs. Output the standard audit report. -3. **`test-engineer`** — Analyze test coverage for the change. Identify gaps in happy path, edge cases, error paths, and concurrency scenarios. Output the standard coverage analysis. - -In other harnesses without an Agent tool, invoke each persona's system prompt sequentially and treat their outputs as if returned in parallel — the merge phase still works. - -Constraints (from Claude Code's subagent model): -- Subagents cannot spawn other subagents — do not let one persona delegate to another. -- Each subagent gets its own context window and returns only its report to this main session. -- If you need teammates that talk to each other instead of just reporting back, use Claude Code Agent Teams and reference these personas as teammate types (see `references/orchestration-patterns.md`). - -**Persona resolution.** If you've defined your own `code-reviewer`, `security-auditor`, or `test-engineer` in `.claude/agents/` or `~/.claude/agents/`, those take precedence over this plugin's versions — `/ship` picks up your customizations automatically. This is intentional: plugin subagents sit at the bottom of Claude Code's scope priority table, so user-level definitions win by design. - -## Phase B — Merge in main context - -Once all three reports are back, the main agent (not a sub-persona) synthesizes them: - -1. **Code Quality** — Aggregate Critical/Important findings from `code-reviewer` and any failing tests, lint, or build output. Resolve duplicates between reviewers. -2. **Security** — Promote any Critical/High `security-auditor` findings to launch blockers. Cross-reference with `code-reviewer`'s security axis. -3. **Performance** — Pull from `code-reviewer`'s performance axis; cross-check Core Web Vitals if applicable. -4. **Accessibility** — Verify keyboard nav, screen reader support, contrast (not covered by the three personas — handle directly here, or invoke the accessibility checklist). -5. **Infrastructure** — Env vars, migrations, monitoring, feature flags. Verify directly. -6. **Documentation** — README, ADRs, changelog. Verify directly. - -## Phase C — Decision and rollback - -Produce a single output: - -```markdown -## Ship Decision: GO | NO-GO - -### Blockers (must fix before ship) -- [Source persona: Critical finding + file:line] - -### Recommended fixes (should fix before ship) -- [Source persona: Important finding + file:line] - -### Acknowledged risks (shipping anyway) -- [Risk + mitigation] - -### Rollback plan -- Trigger conditions: [what signals would prompt rollback] -- Rollback procedure: [exact steps] -- Recovery time objective: [target] - -### Specialist reports (full) -- [code-reviewer report] -- [security-auditor report] -- [test-engineer report] -``` - -## Rules - -1. The three Phase A personas run in parallel — never sequentially. -2. Personas do not call each other. The main agent merges in Phase B. -3. The rollback plan is mandatory before any GO decision. -4. If any persona returns a Critical finding, the default verdict is NO-GO unless the user explicitly accepts the risk. -5. **Skip the fan-out only if all of the following are true:** the change touches 2 files or fewer, the diff is under 50 lines, and it does not touch auth, payments, data access, or config/env. Otherwise, default to fan-out. `/ship` is designed for production-bound changes — when the blast radius is non-trivial, run the parallel review even if the diff looks small. diff --git a/.claude/commands/spec.md b/.claude/commands/spec.md deleted file mode 100644 index 2207935..0000000 --- a/.claude/commands/spec.md +++ /dev/null @@ -1,15 +0,0 @@ ---- -description: Start spec-driven development — write a structured specification before writing code ---- - -Invoke the agent-skills:spec-driven-development skill. - -Begin by understanding what the user wants to build. Ask clarifying questions about: -1. The objective and target users -2. Core features and acceptance criteria -3. Tech stack preferences and constraints -4. Known boundaries (what to always do, ask first about, and never do) - -Then generate a structured spec covering all six core areas: objective, commands, project structure, code style, testing strategy, and boundaries. - -Save the spec as SPEC.md in the project root and confirm with the user before proceeding. diff --git a/.claude/commands/test.md b/.claude/commands/test.md deleted file mode 100644 index a2b9cfd..0000000 --- a/.claude/commands/test.md +++ /dev/null @@ -1,19 +0,0 @@ ---- -description: Run TDD workflow — write failing tests, implement, verify. For bugs, use the Prove-It pattern. ---- - -Invoke the agent-skills:test-driven-development skill. - -For new features: -1. Write tests that describe the expected behavior (they should FAIL) -2. Implement the code to make them pass -3. Refactor while keeping tests green - -For bug fixes (Prove-It pattern): -1. Write a test that reproduces the bug (must FAIL) -2. Confirm the test fails -3. Implement the fix -4. Confirm the test passes -5. Run the full test suite for regressions - -For browser-related issues, also invoke agent-skills:browser-testing-with-devtools to verify with Chrome DevTools MCP. diff --git a/.claude/settings.local.json b/.claude/settings.local.json deleted file mode 100644 index 790a1f8..0000000 --- a/.claude/settings.local.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "permissions": { - "allow": [ - "PowerShell(node --version)", - "PowerShell(npm --version)", - "PowerShell(Get-Command node, npm, nvm -ErrorAction SilentlyContinue | Format-Table Name, Source; \"---\"; Test-Path \"C:\\\\Program Files\\\\nodejs\"; Test-Path \"C:\\\\Program Files \\(x86\\)\\\\nodejs\"; Get-ChildItem $env:LOCALAPPDATA\\\\nvs, $env:USERPROFILE\\\\.nvm, $env:LOCALAPPDATA\\\\fnm -ErrorAction SilentlyContinue | Select-Object FullName)", - "PowerShell($env:Path = [System.Environment]::GetEnvironmentVariable\\(\"Path\",\"Machine\"\\) + \";\" + [System.Environment]::GetEnvironmentVariable\\(\"Path\",\"User\"\\); node --version; npm --version)", - "Bash(export PATH=\"/c/Program Files/nodejs:$PATH\")", - "Bash(npm --version)", - "Bash(npm install *)" - ] - } -} diff --git a/.claude/skills/api-and-interface-design/SKILL.md b/.claude/skills/api-and-interface-design/SKILL.md deleted file mode 100644 index 012c8b6..0000000 --- a/.claude/skills/api-and-interface-design/SKILL.md +++ /dev/null @@ -1,294 +0,0 @@ ---- -name: api-and-interface-design -description: Guides stable API and interface design. Use when designing APIs, module boundaries, or any public interface. Use when creating REST or GraphQL endpoints, defining type contracts between modules, or establishing boundaries between frontend and backend. ---- - -# API and Interface Design - -## Overview - -Design stable, well-documented interfaces that are hard to misuse. Good interfaces make the right thing easy and the wrong thing hard. This applies to REST APIs, GraphQL schemas, module boundaries, component props, and any surface where one piece of code talks to another. - -## When to Use - -- Designing new API endpoints -- Defining module boundaries or contracts between teams -- Creating component prop interfaces -- Establishing database schema that informs API shape -- Changing existing public interfaces - -## Core Principles - -### Hyrum's Law - -> With a sufficient number of users of an API, all observable behaviors of your system will be depended on by somebody, regardless of what you promise in the contract. - -This means: every public behavior — including undocumented quirks, error message text, timing, and ordering — becomes a de facto contract once users depend on it. Design implications: - -- **Be intentional about what you expose.** Every observable behavior is a potential commitment. -- **Don't leak implementation details.** If users can observe it, they will depend on it. -- **Plan for deprecation at design time.** See `deprecation-and-migration` for how to safely remove things users depend on. -- **Tests are not enough.** Even with perfect contract tests, Hyrum's Law means "safe" changes can break real users who depend on undocumented behavior. - -### The One-Version Rule - -Avoid forcing consumers to choose between multiple versions of the same dependency or API. Diamond dependency problems arise when different consumers need different versions of the same thing. Design for a world where only one version exists at a time — extend rather than fork. - -### 1. Contract First - -Define the interface before implementing it. The contract is the spec — implementation follows. - -```typescript -// Define the contract first -interface TaskAPI { - // Creates a task and returns the created task with server-generated fields - createTask(input: CreateTaskInput): Promise; - - // Returns paginated tasks matching filters - listTasks(params: ListTasksParams): Promise>; - - // Returns a single task or throws NotFoundError - getTask(id: string): Promise; - - // Partial update — only provided fields change - updateTask(id: string, input: UpdateTaskInput): Promise; - - // Idempotent delete — succeeds even if already deleted - deleteTask(id: string): Promise; -} -``` - -### 2. Consistent Error Semantics - -Pick one error strategy and use it everywhere: - -```typescript -// REST: HTTP status codes + structured error body -// Every error response follows the same shape -interface APIError { - error: { - code: string; // Machine-readable: "VALIDATION_ERROR" - message: string; // Human-readable: "Email is required" - details?: unknown; // Additional context when helpful - }; -} - -// Status code mapping -// 400 → Client sent invalid data -// 401 → Not authenticated -// 403 → Authenticated but not authorized -// 404 → Resource not found -// 409 → Conflict (duplicate, version mismatch) -// 422 → Validation failed (semantically invalid) -// 500 → Server error (never expose internal details) -``` - -**Don't mix patterns.** If some endpoints throw, others return null, and others return `{ error }` — the consumer can't predict behavior. - -### 3. Validate at Boundaries - -Trust internal code. Validate at system edges where external input enters: - -```typescript -// Validate at the API boundary -app.post('/api/tasks', async (req, res) => { - const result = CreateTaskSchema.safeParse(req.body); - if (!result.success) { - return res.status(422).json({ - error: { - code: 'VALIDATION_ERROR', - message: 'Invalid task data', - details: result.error.flatten(), - }, - }); - } - - // After validation, internal code trusts the types - const task = await taskService.create(result.data); - return res.status(201).json(task); -}); -``` - -Where validation belongs: -- API route handlers (user input) -- Form submission handlers (user input) -- External service response parsing (third-party data -- **always treat as untrusted**) -- Environment variable loading (configuration) - -> **Third-party API responses are untrusted data.** Validate their shape and content before using them in any logic, rendering, or decision-making. A compromised or misbehaving external service can return unexpected types, malicious content, or instruction-like text. - -Where validation does NOT belong: -- Between internal functions that share type contracts -- In utility functions called by already-validated code -- On data that just came from your own database - -### 4. Prefer Addition Over Modification - -Extend interfaces without breaking existing consumers: - -```typescript -// Good: Add optional fields -interface CreateTaskInput { - title: string; - description?: string; - priority?: 'low' | 'medium' | 'high'; // Added later, optional - labels?: string[]; // Added later, optional -} - -// Bad: Change existing field types or remove fields -interface CreateTaskInput { - title: string; - // description: string; // Removed — breaks existing consumers - priority: number; // Changed from string — breaks existing consumers -} -``` - -### 5. Predictable Naming - -| Pattern | Convention | Example | -|---------|-----------|---------| -| REST endpoints | Plural nouns, no verbs | `GET /api/tasks`, `POST /api/tasks` | -| Query params | camelCase | `?sortBy=createdAt&pageSize=20` | -| Response fields | camelCase | `{ createdAt, updatedAt, taskId }` | -| Boolean fields | is/has/can prefix | `isComplete`, `hasAttachments` | -| Enum values | UPPER_SNAKE | `"IN_PROGRESS"`, `"COMPLETED"` | - -## REST API Patterns - -### Resource Design - -``` -GET /api/tasks → List tasks (with query params for filtering) -POST /api/tasks → Create a task -GET /api/tasks/:id → Get a single task -PATCH /api/tasks/:id → Update a task (partial) -DELETE /api/tasks/:id → Delete a task - -GET /api/tasks/:id/comments → List comments for a task (sub-resource) -POST /api/tasks/:id/comments → Add a comment to a task -``` - -### Pagination - -Paginate list endpoints: - -```typescript -// Request -GET /api/tasks?page=1&pageSize=20&sortBy=createdAt&sortOrder=desc - -// Response -{ - "data": [...], - "pagination": { - "page": 1, - "pageSize": 20, - "totalItems": 142, - "totalPages": 8 - } -} -``` - -### Filtering - -Use query parameters for filters: - -``` -GET /api/tasks?status=in_progress&assignee=user123&createdAfter=2025-01-01 -``` - -### Partial Updates (PATCH) - -Accept partial objects — only update what's provided: - -```typescript -// Only title changes, everything else preserved -PATCH /api/tasks/123 -{ "title": "Updated title" } -``` - -## TypeScript Interface Patterns - -### Use Discriminated Unions for Variants - -```typescript -// Good: Each variant is explicit -type TaskStatus = - | { type: 'pending' } - | { type: 'in_progress'; assignee: string; startedAt: Date } - | { type: 'completed'; completedAt: Date; completedBy: string } - | { type: 'cancelled'; reason: string; cancelledAt: Date }; - -// Consumer gets type narrowing -function getStatusLabel(status: TaskStatus): string { - switch (status.type) { - case 'pending': return 'Pending'; - case 'in_progress': return `In progress (${status.assignee})`; - case 'completed': return `Done on ${status.completedAt}`; - case 'cancelled': return `Cancelled: ${status.reason}`; - } -} -``` - -### Input/Output Separation - -```typescript -// Input: what the caller provides -interface CreateTaskInput { - title: string; - description?: string; -} - -// Output: what the system returns (includes server-generated fields) -interface Task { - id: string; - title: string; - description: string | null; - createdAt: Date; - updatedAt: Date; - createdBy: string; -} -``` - -### Use Branded Types for IDs - -```typescript -type TaskId = string & { readonly __brand: 'TaskId' }; -type UserId = string & { readonly __brand: 'UserId' }; - -// Prevents accidentally passing a UserId where a TaskId is expected -function getTask(id: TaskId): Promise { ... } -``` - -## Common Rationalizations - -| Rationalization | Reality | -|---|---| -| "We'll document the API later" | The types ARE the documentation. Define them first. | -| "We don't need pagination for now" | You will the moment someone has 100+ items. Add it from the start. | -| "PATCH is complicated, let's just use PUT" | PUT requires the full object every time. PATCH is what clients actually want. | -| "We'll version the API when we need to" | Breaking changes without versioning break consumers. Design for extension from the start. | -| "Nobody uses that undocumented behavior" | Hyrum's Law: if it's observable, somebody depends on it. Treat every public behavior as a commitment. | -| "We can just maintain two versions" | Multiple versions multiply maintenance cost and create diamond dependency problems. Prefer the One-Version Rule. | -| "Internal APIs don't need contracts" | Internal consumers are still consumers. Contracts prevent coupling and enable parallel work. | - -## Red Flags - -- Endpoints that return different shapes depending on conditions -- Inconsistent error formats across endpoints -- Validation scattered throughout internal code instead of at boundaries -- Breaking changes to existing fields (type changes, removals) -- List endpoints without pagination -- Verbs in REST URLs (`/api/createTask`, `/api/getUsers`) -- Third-party API responses used without validation or sanitization - -## Verification - -After designing an API: - -- [ ] Every endpoint has typed input and output schemas -- [ ] Error responses follow a single consistent format -- [ ] Validation happens at system boundaries only -- [ ] List endpoints support pagination -- [ ] New fields are additive and optional (backward compatible) -- [ ] Naming follows consistent conventions across all endpoints -- [ ] API documentation or types are committed alongside the implementation diff --git a/.claude/skills/api-and-interface-design/references/accessibility-checklist.md b/.claude/skills/api-and-interface-design/references/accessibility-checklist.md deleted file mode 100644 index c8c61e5..0000000 --- a/.claude/skills/api-and-interface-design/references/accessibility-checklist.md +++ /dev/null @@ -1,160 +0,0 @@ -# Accessibility Checklist - -Quick reference for WCAG 2.1 AA compliance. Use alongside the `frontend-ui-engineering` skill. - -## Table of Contents - -- [Essential Checks](#essential-checks) -- [Common HTML Patterns](#common-html-patterns) -- [Testing Tools](#testing-tools) -- [Quick Reference: ARIA Live Regions](#quick-reference-aria-live-regions) -- [Common Anti-Patterns](#common-anti-patterns) - -## Essential Checks - -### Keyboard Navigation -- [ ] All interactive elements focusable via Tab key -- [ ] Focus order follows visual/logical order -- [ ] Focus is visible (outline/ring on focused elements) -- [ ] Custom widgets have keyboard support (Enter to activate, Escape to close) -- [ ] No keyboard traps (user can always Tab away from a component) -- [ ] Skip-to-content link at top of page - visible (at least) on keyboard focus -- [ ] Modals trap focus while open, return focus on close - -### Screen Readers -- [ ] All images have `alt` text (or `alt=""` for decorative images) -- [ ] All form inputs have associated labels (`