11 KiB
11 KiB
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) |
PLAN.md
Plans are executable prompts, not documents that transform into prompts.
Structure
---
# 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
---
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
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 schemafeat(2-3): implement token rotation endpointfeat(2-3): add token family reuse detectionfix(2-3): add await to token lookup queryfeat(2-3): add rate limiting to refresh endpoint
Verification Status
- New refresh token issued on rotation
- Old refresh token invalidated
- Reuse detection works
- 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
---
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 functionalityfix: Bug fixtest: Test additionsrefactor: Code restructuringperf: Performance improvementdocs: Documentationstyle: Formatting onlychore: 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