Skip to content

Give the e2e-server a real v2-primary lane and delete the /api/send shadows (rebuild W3 PR-F)#141

Merged
MaxGhenis merged 1 commit into
mainfrom
w3-prf-e2e
Jul 19, 2026
Merged

Give the e2e-server a real v2-primary lane and delete the /api/send shadows (rebuild W3 PR-F)#141
MaxGhenis merged 1 commit into
mainfrom
w3-prf-e2e

Conversation

@MaxGhenis

Copy link
Copy Markdown
Owner

Rebuild W3 PR-F — real v2-primary e2e lane + delete /api/send shadows

The e2e-server's hand-rolled /api/send shadow omitted the idempotency key, so a Playwright "Retry" passed while production 409'd forever (the A4 trap). This replaces the shadows with the production surface so the browser suite validates what ships.

The review catch that made this correct

First build mounted the v1 routes but left the lane at v2_primary=false — so the frontend (which routes on status.v2_primary) kept posting legacy /api/send, the four Playwright mock flips were dead, and the lane validated the legacy path while claiming v2. Opus review flagged it BLOCKER; confirmed by grep (no V2Primary/Reads in the lane) and curl (v2_primary:false). Fixed: the lane now sets V2Primary:true + Reads: v2read.New(store) mirroring serve.go, migrates legacy fixtures into the v2 store, and the two status-mocking specs advertise v2_primary:true.

Factual gate (verified outside the sandbox)

Built the e2e-server and curled it directly:

  • GET /api/statusv2_primary: true (was false)
  • POST /api/v1/outbox/messagesHTTP 200 with a real outbox_id + state:queued

So the browser now genuinely exercises the production v1 handler. CI's Web E2E job (real Playwright + real e2e-server) is the end-to-end gate on the four flipped tests.

Also

  • /api/send + /api/drafts/send shadows deleted; fixture controls confined to /_e2e/*.
  • Structural guard walks every .go file in the package and strips an optional METHOD prefix, so a re-added mux.HandleFunc("POST /api/send", …) is caught (the review showed the original guard missed exactly this idiom).
  • Fake-bridge round-trip: next-result:uncertain → durable uncertain row via the real dispatcher; repeat submit dedupes (same outbox_id, dispatch count == 1).

Verification

Independent full GOWORK=off go test -race ./... outside the sandbox: 32/32 packages, exit 0 including cmd/e2e-server. Scope: cmd/e2e-server/** + e2e/ui.spec.js only; no production handler/storage changes.

🤖 Generated with Claude Code

…hadows (rebuild W3 PR-F)

The e2e-server hand-rolled an /api/send shadow that omitted the idempotency
key, so a Playwright "Retry" passed while production 409'd forever. This
replaces the shadows with the production surface so the browser suite
exercises what ships.

- v2-primary lane: real sqlite.Store + blob store over a temp dir, a
  bridge.Registry of scripted fake adapters declaring TextSender/MediaSender
  capabilities, the real v2wire services, the production /api/v1 routes, and
  a PrimaryNotifier over the fake Events. The web options set
  V2Primary: true and Reads: v2read.New(store) exactly as serve.go does, so
  GET /api/status reports v2_primary:true, the frontend routes sends to
  /api/v1/outbox/messages, and reads come from the v2 path (RR-2 reactions
  included) rather than the legacy shadow. Legacy fixtures migrate into the
  v2 store so conversation/message reads keep working on native v2 ids.
- Shadows deleted: /api/send and /api/drafts/send are gone. Fixture controls
  live only under /_e2e/* (POST /_e2e/bridges/{account}/next-result drives
  scripted send outcomes).
- Structural guard: a test fails if the e2e-server registers any /api route
  itself. It walks every .go file in the package and strips an optional
  METHOD prefix before the check, so a re-added "POST /api/send" mux pattern
  is caught, not just a bare "/api/..." literal.
- Fake-bridge round-trip test: next-result uncertain -> submit -> the outbox
  row lands uncertain via the real dispatcher, a repeat HTTP submit dedupes
  (same outbox_id, deduplicated:true) with dispatch count exactly one.
- Playwright send tests point at /api/v1/outbox/messages; the two that mock
  /api/status advertise v2_primary:true so their send-request counters
  observe the route the frontend now uses.
@MaxGhenis

Copy link
Copy Markdown
Owner Author

Updated after the primary-lane reconciliation: the suite now validates v2-primary honestly — locally 91 passed / 9 skipped / 0 failed in 53s (was: 20-min CI timeout). The 9 skips are test.fixme entries for genuinely-absent-in-primary mutations (mute, mentions-only, leave-group class, AI-draft send), each marked PRIMARY REGRESSION for Wave-4 triage — not paper-overs. Lane fixture injectors now project into the v2 store the frontend actually reads (receipts, typing, notifications, drafts, avatars), media sends confirm through the real /api/v1 outbox media lifecycle, and route-coalescing count shifts are asserted from ground-truthed DOM.

@MaxGhenis
MaxGhenis merged commit fb9c568 into main Jul 19, 2026
5 checks passed
@MaxGhenis
MaxGhenis deleted the w3-prf-e2e branch July 19, 2026 12:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant