~ 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:

 ATProto Personal Data Server

to:

 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

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:

    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

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:

    // 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

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

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

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

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

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

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

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

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

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:

    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

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

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