Decomposed "Foundation Setup - Install Dependencies & Configure Tailwind" phase into 6 executable tasks: 1. Install Tailwind CSS, PostCSS & Autoprefixer 2. Map MUI theme to Tailwind design tokens 3. Setup CSS variables for dynamic theming 4. Install Radix UI primitives 5. Initialize shadcn/ui and setup component directory 6. Move MUI to devDependencies and verify setup Tasks follow logical dependency chain with final human verification checkpoint before proceeding with component migration. Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
435 lines
11 KiB
Markdown
435 lines
11 KiB
Markdown
# Execution Artifacts
|
|
|
|
Execution produces artifacts that document what happened, enable debugging, and provide context for future work.
|
|
|
|
## Artifact Types
|
|
|
|
| Artifact | Created By | Purpose |
|
|
|----------|------------|---------|
|
|
| PLAN.md | Architect | Executable instructions for a plan |
|
|
| SUMMARY.md | Worker | Record of what actually happened |
|
|
| VERIFICATION.md | Verifier | Goal-backward verification results |
|
|
| UAT.md | Verifier + User | User acceptance testing results |
|
|
| STATE.md | All agents | Session state (see [session-state.md](session-state.md)) |
|
|
|
|
---
|
|
|
|
## PLAN.md
|
|
|
|
Plans are **executable prompts**, not documents that transform into prompts.
|
|
|
|
### Structure
|
|
|
|
```yaml
|
|
---
|
|
# Frontmatter
|
|
phase: 2
|
|
plan: 3
|
|
type: execute # execute | tdd
|
|
wave: 1
|
|
depends_on: [2-2-PLAN]
|
|
files_modified:
|
|
- src/api/auth/refresh.ts
|
|
- src/middleware/auth.ts
|
|
- db/migrations/002_refresh_tokens.sql
|
|
autonomous: true # false if checkpoints required
|
|
must_haves:
|
|
observable_truths:
|
|
- "Refresh token extends session"
|
|
- "Old token invalidated after rotation"
|
|
required_artifacts:
|
|
- src/api/auth/refresh.ts
|
|
required_wiring:
|
|
- "refresh endpoint -> token storage"
|
|
user_setup: [] # Human prereqs if any
|
|
---
|
|
|
|
# Phase 2, Plan 3: Refresh Token Rotation
|
|
|
|
## Objective
|
|
Implement refresh token rotation to extend user sessions securely while preventing token reuse attacks.
|
|
|
|
## Context
|
|
@file: PROJECT.md (project overview)
|
|
@file: 2-CONTEXT.md (phase decisions)
|
|
@file: 2-1-SUMMARY.md (prior work)
|
|
@file: 2-2-SUMMARY.md (prior work)
|
|
|
|
## Tasks
|
|
|
|
### Task 1: Create refresh_tokens table
|
|
- **type:** auto
|
|
- **files:** db/migrations/002_refresh_tokens.sql, src/db/schema/refreshTokens.ts
|
|
- **action:** Create table with: id (uuid), user_id (fk), token_hash (sha256), family (uuid for rotation tracking), expires_at, created_at, revoked_at. Index on token_hash and user_id.
|
|
- **verify:** `cw db migrate` succeeds, schema matches
|
|
- **done:** Migration applies, drizzle schema matches SQL
|
|
|
|
### Task 2: Implement rotation endpoint
|
|
- **type:** auto
|
|
- **files:** src/api/auth/refresh.ts
|
|
- **action:** POST /api/auth/refresh accepts refresh token in httpOnly cookie. Validate token exists and not expired. Generate new access + refresh tokens. Store new refresh, revoke old. Set cookies. Return 200 with new access token.
|
|
- **verify:** curl with valid refresh cookie returns new tokens
|
|
- **done:** Rotation works, old token invalidated
|
|
|
|
### Task 3: Add token family validation
|
|
- **type:** auto
|
|
- **files:** src/api/auth/refresh.ts
|
|
- **action:** If revoked token reused, revoke entire family (reuse detection). Log security event.
|
|
- **verify:** Reusing old token revokes all tokens in family
|
|
- **done:** Reuse detection active
|
|
|
|
## Verification Criteria
|
|
- [ ] New refresh token issued on rotation
|
|
- [ ] Old refresh token no longer valid
|
|
- [ ] Reused token triggers family revocation
|
|
- [ ] Access token returned in response
|
|
- [ ] Cookies set with correct flags (httpOnly, secure, sameSite)
|
|
|
|
## Success Criteria
|
|
- All tasks complete with passing verify steps
|
|
- No TypeScript errors
|
|
- Tests cover happy path and reuse detection
|
|
```
|
|
|
|
### Key Elements
|
|
|
|
| Element | Purpose |
|
|
|---------|---------|
|
|
| `type: execute\|tdd` | Execution strategy |
|
|
| `wave` | Parallelization grouping |
|
|
| `depends_on` | Must complete first |
|
|
| `files_modified` | Git tracking, conflict detection |
|
|
| `autonomous` | Can run without checkpoints |
|
|
| `must_haves` | Verification criteria |
|
|
| `@file` references | Context to load |
|
|
|
|
---
|
|
|
|
## SUMMARY.md
|
|
|
|
Created after plan execution. Documents what **actually happened**.
|
|
|
|
### Structure
|
|
|
|
```yaml
|
|
---
|
|
phase: 2
|
|
plan: 3
|
|
subsystem: auth
|
|
tags: [jwt, security, tokens]
|
|
requires:
|
|
- users table
|
|
- jose library
|
|
provides:
|
|
- refresh token rotation
|
|
- reuse detection
|
|
affects:
|
|
- auth flow
|
|
- session management
|
|
tech_stack:
|
|
- jose (JWT)
|
|
- drizzle (ORM)
|
|
- sqlite
|
|
key_files:
|
|
- src/api/auth/refresh.ts: "Rotation endpoint"
|
|
- src/db/schema/refreshTokens.ts: "Token storage"
|
|
decisions:
|
|
- "Token family for reuse detection"
|
|
- "SHA256 hash for token storage"
|
|
metrics:
|
|
tasks_completed: 3
|
|
tasks_total: 3
|
|
deviations: 2
|
|
execution_time: "45 minutes"
|
|
context_usage: "38%"
|
|
---
|
|
|
|
# Phase 2, Plan 3 Summary: Refresh Token Rotation
|
|
|
|
## What Was Built
|
|
Implemented refresh token rotation with security features:
|
|
- Rotation endpoint at POST /api/auth/refresh
|
|
- Token storage with family tracking
|
|
- Reuse detection that revokes entire token family
|
|
|
|
## Implementation Notes
|
|
|
|
### Token Storage
|
|
Tokens stored as SHA256 hashes (never plaintext). Family UUID links related tokens for rotation tracking.
|
|
|
|
### Rotation Flow
|
|
1. Receive refresh token in cookie
|
|
2. Hash and lookup in database
|
|
3. Verify not expired, not revoked
|
|
4. Generate new access + refresh tokens
|
|
5. Store new refresh with same family
|
|
6. Revoke old refresh token
|
|
7. Set new cookies, return access token
|
|
|
|
### Reuse Detection
|
|
If a revoked token is presented, the entire family is revoked. This catches scenarios where an attacker captured an old token.
|
|
|
|
## Deviations
|
|
|
|
### Rule 2: Added rate limiting
|
|
```yaml
|
|
deviation:
|
|
rule: 2
|
|
type: missing_critical
|
|
description: "Added rate limiting to refresh endpoint"
|
|
location: src/api/auth/refresh.ts:12
|
|
reason: "Prevent brute force token guessing"
|
|
```
|
|
|
|
### Rule 1: Fixed async handler
|
|
```yaml
|
|
deviation:
|
|
rule: 1
|
|
type: bug_fix
|
|
description: "Added await to database query"
|
|
location: src/api/auth/refresh.ts:34
|
|
reason: "Query returned promise, not result"
|
|
```
|
|
|
|
## Commits
|
|
- `feat(2-3): create refresh_tokens table and schema`
|
|
- `feat(2-3): implement token rotation endpoint`
|
|
- `feat(2-3): add token family reuse detection`
|
|
- `fix(2-3): add await to token lookup query`
|
|
- `feat(2-3): add rate limiting to refresh endpoint`
|
|
|
|
## Verification Status
|
|
- [x] New refresh token issued on rotation
|
|
- [x] Old refresh token invalidated
|
|
- [x] Reuse detection works
|
|
- [x] Cookies set correctly
|
|
- [ ] **Pending human verification:** Cookie flags in production
|
|
|
|
## Notes for Next Plan
|
|
- Rate limiting added; may need tuning based on load
|
|
- Token family approach may need cleanup job for old families
|
|
```
|
|
|
|
### What to Include
|
|
|
|
| Section | Content |
|
|
|---------|---------|
|
|
| Frontmatter | Metadata for future queries |
|
|
| What Was Built | High-level summary |
|
|
| Implementation Notes | Technical details worth preserving |
|
|
| Deviations | All Rules 1-4 deviations with details |
|
|
| Commits | Git commit messages created |
|
|
| Verification Status | What passed, what's pending |
|
|
| Notes for Next Plan | Context for future work |
|
|
|
|
---
|
|
|
|
## VERIFICATION.md
|
|
|
|
Created by Verifier after phase completion.
|
|
|
|
### Structure
|
|
|
|
```yaml
|
|
---
|
|
phase: 2
|
|
status: PASS # PASS | GAPS_FOUND
|
|
verified_at: 2024-01-15T10:30:00Z
|
|
verified_by: verifier-agent
|
|
---
|
|
|
|
# Phase 2 Verification: JWT Implementation
|
|
|
|
## Observable Truths
|
|
|
|
| Truth | Status | Evidence |
|
|
|-------|--------|----------|
|
|
| User can log in with email/password | VERIFIED | Login endpoint returns tokens, sets cookies |
|
|
| Sessions persist across page refresh | VERIFIED | Cookie-based token survives reload |
|
|
| Token refresh extends session | VERIFIED | Refresh endpoint issues new tokens |
|
|
| Expired tokens rejected | VERIFIED | 401 returned for expired access token |
|
|
|
|
## Required Artifacts
|
|
|
|
| Artifact | Status | Check |
|
|
|----------|--------|-------|
|
|
| src/api/auth/login.ts | EXISTS | Exports login handler |
|
|
| src/api/auth/refresh.ts | EXISTS | Exports refresh handler |
|
|
| src/middleware/auth.ts | EXISTS | Exports auth middleware |
|
|
| db/migrations/002_refresh_tokens.sql | EXISTS | Creates table |
|
|
|
|
## Required Wiring
|
|
|
|
| From | To | Status | Evidence |
|
|
|------|-----|--------|----------|
|
|
| Login handler | Token generation | WIRED | login.ts:45 calls createTokens |
|
|
| Auth middleware | Token validation | WIRED | auth.ts:23 calls verifyToken |
|
|
| Refresh handler | Token rotation | WIRED | refresh.ts:67 calls rotateToken |
|
|
| Protected routes | Auth middleware | WIRED | routes.ts uses auth middleware |
|
|
|
|
## Anti-Patterns
|
|
|
|
| Pattern | Found | Location |
|
|
|---------|-------|----------|
|
|
| TODO comments | NO | - |
|
|
| Stub implementations | NO | - |
|
|
| Console.log in handlers | YES | src/api/auth/login.ts:34 (debug log) |
|
|
| Empty catch blocks | NO | - |
|
|
|
|
## Human Verification Needed
|
|
|
|
| Check | Reason |
|
|
|-------|--------|
|
|
| Cookie flags in production | Requires deployed environment |
|
|
| Token timing accuracy | Requires wall-clock testing |
|
|
|
|
## Gaps Found
|
|
None blocking. One console.log should be removed before production.
|
|
|
|
## Remediation
|
|
- Task created: "Remove debug console.log from login handler"
|
|
```
|
|
|
|
---
|
|
|
|
## UAT.md
|
|
|
|
User Acceptance Testing results.
|
|
|
|
### Structure
|
|
|
|
```yaml
|
|
---
|
|
phase: 2
|
|
tested_by: user
|
|
tested_at: 2024-01-15T14:00:00Z
|
|
status: PASS # PASS | ISSUES_FOUND
|
|
---
|
|
|
|
# Phase 2 UAT: JWT Implementation
|
|
|
|
## Test Cases
|
|
|
|
### 1. Login with email and password
|
|
**Prompt:** "Can you log in with your email and password?"
|
|
**Result:** PASS
|
|
**Notes:** Login successful, redirected to dashboard
|
|
|
|
### 2. Session persists on refresh
|
|
**Prompt:** "Refresh the page. Are you still logged in?"
|
|
**Result:** PASS
|
|
**Notes:** Still authenticated after refresh
|
|
|
|
### 3. Logout clears session
|
|
**Prompt:** "Click logout. Can you access the dashboard?"
|
|
**Result:** PASS
|
|
**Notes:** Redirected to login page
|
|
|
|
### 4. Expired session prompts re-login
|
|
**Prompt:** "Wait 15 minutes (or we can simulate). Does the session refresh?"
|
|
**Result:** SKIPPED
|
|
**Reason:** "User chose to trust token rotation implementation"
|
|
|
|
## Issues Found
|
|
None.
|
|
|
|
## Sign-Off
|
|
User confirms Phase 2 JWT Implementation meets requirements.
|
|
Next: Proceed to Phase 3 (OAuth Integration)
|
|
```
|
|
|
|
---
|
|
|
|
## Artifact Storage
|
|
|
|
### File Structure
|
|
|
|
```
|
|
.planning/
|
|
├── phases/
|
|
│ ├── 1/
|
|
│ │ ├── 1-CONTEXT.md
|
|
│ │ ├── 1-1-PLAN.md
|
|
│ │ ├── 1-1-SUMMARY.md
|
|
│ │ ├── 1-2-PLAN.md
|
|
│ │ ├── 1-2-SUMMARY.md
|
|
│ │ └── 1-VERIFICATION.md
|
|
│ └── 2/
|
|
│ ├── 2-CONTEXT.md
|
|
│ ├── 2-1-PLAN.md
|
|
│ ├── 2-1-SUMMARY.md
|
|
│ ├── 2-2-PLAN.md
|
|
│ ├── 2-2-SUMMARY.md
|
|
│ ├── 2-3-PLAN.md
|
|
│ ├── 2-3-SUMMARY.md
|
|
│ ├── 2-VERIFICATION.md
|
|
│ └── 2-UAT.md
|
|
├── STATE.md
|
|
└── config.json
|
|
```
|
|
|
|
### Naming Convention
|
|
|
|
| Pattern | Meaning |
|
|
|---------|---------|
|
|
| `{phase}-CONTEXT.md` | Discussion decisions for phase |
|
|
| `{phase}-{plan}-PLAN.md` | Executable plan |
|
|
| `{phase}-{plan}-SUMMARY.md` | Execution record |
|
|
| `{phase}-VERIFICATION.md` | Phase verification |
|
|
| `{phase}-UAT.md` | User acceptance testing |
|
|
|
|
---
|
|
|
|
## Commit Strategy
|
|
|
|
Each task produces an atomic commit:
|
|
|
|
```
|
|
{type}({phase}-{plan}): {description}
|
|
|
|
- Detail 1
|
|
- Detail 2
|
|
```
|
|
|
|
### Types
|
|
- `feat`: New functionality
|
|
- `fix`: Bug fix
|
|
- `test`: Test additions
|
|
- `refactor`: Code restructuring
|
|
- `perf`: Performance improvement
|
|
- `docs`: Documentation
|
|
- `style`: Formatting only
|
|
- `chore`: Maintenance
|
|
|
|
### Examples
|
|
```
|
|
feat(2-3): implement refresh token rotation
|
|
|
|
- Add refresh_tokens table with family tracking
|
|
- Implement rotation endpoint at POST /api/auth/refresh
|
|
- Add reuse detection with family revocation
|
|
|
|
fix(2-3): add await to token lookup query
|
|
|
|
- Token lookup was returning promise instead of result
|
|
- Added proper await in refresh handler
|
|
|
|
feat(2-3): add rate limiting to refresh endpoint
|
|
|
|
- [Deviation Rule 2] Added express-rate-limit
|
|
- 10 requests per minute per IP
|
|
- Prevents brute force token guessing
|
|
```
|
|
|
|
### Metadata Commit
|
|
|
|
After plan completion:
|
|
```
|
|
chore(2-3): complete plan execution
|
|
|
|
Artifacts:
|
|
- 2-3-SUMMARY.md created
|
|
- STATE.md updated
|
|
- 3 tasks completed, 2 deviations handled
|
|
```
|