~ knotless Search/
↑↓ move↵ open⇧↵ all results

chadtmiller.com/pds.js

An atproto PDS in JavaScript, for Cloudflare Workers and Node

0
0
main
463 lines · 10.5 KB Raw History
# Fix Remaining E2E Tests Implementation Plan

> **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.

**Goal:** Fix remaining 27 failing e2e tests on Node (and corresponding Cloudflare failures)

**Architecture:** The tests exercise core PDS functionality. Most failures are in `packages/core/pds.js` handlers that have missing validations, incorrect responses, or missing headers. OAuth scope tests depend on `getOAuthTokenWithScope` helper which needs the full PAR→authorize→token flow to work.

**Tech Stack:** JavaScript, Vitest, Node.js test runner

---

## Current Status

- Node: 44 passed, 27 failed
- Cloudflare: 27 passed, 44 failed

## Failure Categories

1. **Root path** (1 test) - Text missing "PDS"
2. **Blob operations** (4 tests) - Missing headers and validation
3. **OAuth token flow** (5 tests) - PAR→authorize→token broken
4. **OAuth scope tests** (7 tests) - Depend on token flow
5. **Foreign DID/proxy** (5 tests) - Not implemented
6. **Misc** (5 tests) - Various issues

---

### Task 1: Fix Root Path Response

**Files:**
- Modify: `packages/core/pds.js:1447`

**Step 1: Update handleRoot text**

Change line 1447 from:
```javascript
 ATProto Personal Data Server
```
to:
```javascript
 ATProto PDS - Personal Data Server
```

**Step 2: Run test to verify**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "root returns ASCII"`
Expected: PASS

**Step 3: Commit**

```bash
git add packages/core/pds.js
git commit -m "fix: add PDS text to root path response"
```

---

### Task 2: Fix getBlob Missing Headers

**Files:**
- Modify: `packages/core/pds.js:1780-1785`

**Step 1: Add security headers to handleGetBlob**

Replace response creation:
```javascript
    return new Response(result.data, {
      headers: {
        'Content-Type': result.mimeType,
        'Cache-Control': 'public, max-age=31536000, immutable',
        'X-Content-Type-Options': 'nosniff',
      },
    })
```

**Step 2: Run test to verify**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "getBlob retrieves data"`
Expected: PASS

**Step 3: Commit**

```bash
git add packages/core/pds.js
git commit -m "fix: add X-Content-Type-Options header to getBlob"
```

---

### Task 3: Fix getBlob DID Validation

**Files:**
- Modify: `packages/core/pds.js:1761-1770`

**Step 1: Add DID validation to handleGetBlob**

After the missing parameters check, add:
```javascript
    // Validate DID matches this PDS
    const myDid = await this.getDid()
    if (did !== myDid) {
      return Response.json(
        { error: 'InvalidRequest', message: 'DID does not match this PDS' },
        { status: 400 }
      )
    }

    // Validate CID format (basic check)
    if (!cid.startsWith('b') || cid.length < 10) {
      return Response.json(
        { error: 'InvalidRequest', message: 'Invalid CID format' },
        { status: 400 }
      )
    }
```

**Step 2: Run tests to verify**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "getBlob"`
Expected: All 4 getBlob tests PASS

**Step 3: Commit**

```bash
git add packages/core/pds.js
git commit -m "fix: add DID and CID validation to getBlob"
```

---

### Task 4: Fix refreshSession Access Token Rejection

**Files:**
- Modify: `packages/core/pds.js` - handleRefreshSession

**Step 1: Find and read handleRefreshSession**

Run: `grep -n "handleRefreshSession" packages/core/pds.js`

**Step 2: Add access token detection**

The handler should check if the token is an access token (not refresh token) and reject with 400.

Look for the token validation logic and ensure it distinguishes between access and refresh tokens.

**Step 3: Run test to verify**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "refreshSession rejects access token"`
Expected: PASS

**Step 4: Commit**

```bash
git add packages/core/pds.js
git commit -m "fix: reject access tokens in refreshSession endpoint"
```

---

### Task 5: Fix putPreferences

**Files:**
- Modify: `packages/core/pds.js` - handlePutPreferences

**Step 1: Find and read handlePutPreferences**

Run: `grep -n "handlePutPreferences\|putPreferences" packages/core/pds.js`

**Step 2: Investigate the failure**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "putPreferences works"`
Read the error output to understand what's failing.

**Step 3: Fix the issue**

Based on error output, fix the handler.

**Step 4: Run test to verify**

Expected: PASS

**Step 5: Commit**

```bash
git add packages/core/pds.js
git commit -m "fix: putPreferences handler"
```

---

### Task 6: Fix Wrong Repo Rejection (403)

**Files:**
- Modify: `packages/core/pds.js` - repo operation handlers

**Step 1: Investigate the failure**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "wrong repo rejected"`
Read the error output.

**Step 2: Find the handler**

The test likely calls createRecord with a DID that doesn't match auth. The handler should return 403, not another status.

**Step 3: Fix the issue**

Ensure repo operations check that `auth.did` matches the requested repo DID and return 403 Forbidden if not.

**Step 4: Run test to verify**

Expected: PASS

**Step 5: Commit**

```bash
git add packages/core/pds.js
git commit -m "fix: return 403 for wrong repo access"
```

---

### Task 7: Fix deleteRecord Blob Cleanup

**Files:**
- Modify: `packages/core/pds.js` - handleDeleteRecord

**Step 1: Investigate the failure**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "deleteRecord with blob cleans up"`
Read error output.

**Step 2: Check blob cleanup logic**

The handler should:
1. Find blobs referenced by the record
2. Unlink them from the record
3. Run cleanup to delete orphaned blobs

**Step 3: Fix the issue**

Ensure the delete flow properly cleans up blob references.

**Step 4: Commit**

```bash
git add packages/core/pds.js
git commit -m "fix: blob cleanup on record deletion"
```

---

### Task 8: Fix OAuth PAR → Authorize → Token Flow

**Files:**
- Modify: `packages/core/pds.js` or `packages/core/oauth.js`

**Step 1: Run the failing test with verbose output**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "full PAR" --reporter=verbose`

**Step 2: Trace the OAuth flow**

Check each step:
1. PAR request creates request_uri
2. Authorize POST with password validates and creates auth code
3. Token exchange validates code and returns tokens

**Step 3: Identify and fix the broken step**

Common issues:
- DPoP proof validation
- Auth code storage/retrieval
- Token generation

**Step 4: Run test to verify**

Expected: PASS

**Step 5: Commit**

```bash
git add packages/core/*.js
git commit -m "fix: OAuth PAR authorize token flow"
```

---

### Task 9: Fix DPoP Validation Issues

**Files:**
- Modify: `packages/core/oauth.js` or `packages/core/pds.js`

**Step 1: Run DPoP-related tests**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "DPoP"`

**Step 2: Fix DPoP key mismatch detection**

Ensure the token endpoint validates that the DPoP key matches the one used in PAR.

**Step 3: Fix DPoP jti replay detection**

Ensure jti values are stored and checked for replay.

**Step 4: Run tests to verify**

Expected: Both DPoP tests PASS

**Step 5: Commit**

```bash
git add packages/core/*.js
git commit -m "fix: DPoP validation for key mismatch and jti replay"
```

---

### Task 10: Fix PKCE and Redirect URI Validation

**Files:**
- Modify: `packages/core/oauth.js` or `packages/core/pds.js`

**Step 1: Run PKCE test**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "PKCE failure"`

**Step 2: Fix code_verifier validation**

Ensure token endpoint validates code_verifier against stored code_challenge.

**Step 3: Run redirect_uri test**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "redirect_uri mismatch"`

**Step 4: Fix redirect_uri validation**

Ensure redirect_uri in token request matches the one in PAR.

**Step 5: Run tests to verify**

Expected: Both tests PASS

**Step 6: Commit**

```bash
git add packages/core/*.js
git commit -m "fix: PKCE and redirect_uri validation"
```

---

### Task 11: Fix OAuth Scope Tests (Batch)

**Files:**
- Depends on Task 8 (OAuth flow must work first)

**Step 1: Verify OAuth flow is working**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "full PAR"`
Must PASS before proceeding.

**Step 2: Run all scope tests**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "scope"`

**Step 3: Investigate timeouts**

The 315ms timeouts suggest the `getOAuthTokenWithScope` helper is failing. If the OAuth flow works (Task 8), these should start passing.

**Step 4: Fix any remaining scope enforcement issues**

Check that scope is properly stored and enforced in token validation.

**Step 5: Commit**

```bash
git add packages/core/*.js
git commit -m "fix: OAuth scope enforcement"
```

---

### Task 12: Add Foreign DID / Proxy Stub Responses

**Files:**
- Modify: `packages/core/pds.js`

**Step 1: Check test expectations**

The tests expect:
- `proxies to AppView` - returns proxied response or error
- `unknown proxy service` - returns 400
- `malformed atproto-proxy header` - returns 400
- `returns local record for local DID` - returns the record
- `describeRepo handles foreign DID` - returns 404 for unknown DID

**Step 2: Add basic proxy header handling**

In the relevant handlers, add:
```javascript
    const proxyHeader = request.headers.get('atproto-proxy')
    if (proxyHeader) {
      // Parse and validate proxy header
      const match = proxyHeader.match(/^did:[\w:]+#[\w]+$/)
      if (!match) {
        return Response.json(
          { error: 'InvalidRequest', message: 'Malformed atproto-proxy header' },
          { status: 400 }
        )
      }
      // For now, return error for proxy requests (not implemented)
      return Response.json(
        { error: 'InvalidRequest', message: 'Unknown proxy service' },
        { status: 400 }
      )
    }
```

**Step 3: Run tests to verify**

Run: `PLATFORM=node pnpm vitest run test/e2e.test.js -t "proxy\|foreign"`
Expected: Most tests PASS

**Step 4: Commit**

```bash
git add packages/core/pds.js
git commit -m "feat: add basic atproto-proxy header handling"
```

---

### Task 13: Final Test Run and Cleanup

**Step 1: Run all Node tests**

Run: `pnpm test:e2e:node`
Target: 60+ tests passing

**Step 2: Run all Cloudflare tests**

Run: `pnpm test:e2e:cloudflare`
Target: 50+ tests passing

**Step 3: Commit any final fixes**

**Step 4: Summary commit**

```bash
git add .
git commit -m "test: fix e2e tests for dual platform support"
```

---

## Execution Notes

- Tasks 1-3 are straightforward fixes
- Tasks 4-7 require investigation
- Tasks 8-11 are interdependent (OAuth flow must work first)
- Task 12 is additive (new functionality)
- Run `pnpm test:e2e:node` frequently to track progress