Skip to content

test(e2e): PKCE-on-the-wire, per-user scoping, and desk clash coverage - #477

Open
camreeves wants to merge 3 commits into
e2e/ci-verifyfrom
e2e/coverage
Open

test(e2e): PKCE-on-the-wire, per-user scoping, and desk clash coverage#477
camreeves wants to merge 3 commits into
e2e/ci-verifyfrom
e2e/coverage

Conversation

@camreeves

Copy link
Copy Markdown

Stacked on #476 — please review that one first, this branches off it.

Adds three specs to the workplace e2e suite. All P0s in the coverage contract are now done.

Spec Covers Why it matters
pkce.spec.ts AUTH-E2E-01 Asserts the login handshake on the wire, not on the response. A client that leaked a secret or silently dropped PKCE would still get a valid token and a working app, so the response can't tell you the exchange was sound. Checks S256 (never plain), a real base64url challenge, a code_verifier, the expected client_id, no client_secret anywhere, and that the password never appears in a URL. Ported from tasks/PPT-2536/, where nothing ran it.
booking-scoping.spec.ts WP-E2E-08, AUTH-E2E-05 A second user can't see your booking in their listing and can't delete it. Locks down something we learned the hard way: GET /bookings is caller-scoped, and an early leak check written as an admin reported zero bookings while the database held one.
desk-clash.spec.ts REG-02 No double-booking. Maps to the shipped fix in 2607.1. Attempted as a second user, since a check that only consulted your own bookings would pass a single-user version.

13 specs, green locally and on the runner.

Every assertion is red-checked

Each was deliberately inverted and observed to fail against real data, because a test that has never been seen to fail is a guess rather than a guard:

  • clash → genuinely 409 Conflict
  • scoping → the other user's listing really is [] while the booking exists
  • PKCE → a real code_challenge_method=S256 and base64url challenge on the wire

Controls, so nothing passes for the wrong reason

  • A non-overlapping slot must still be accepted, or a backend that rejected everything would look like perfect clash detection
  • You can see your own booking, or "nobody sees anything" would read as a working privacy boundary
  • The desk frees up after deletion, since a cancelled booking that still blocks is harder to diagnose than a plain double-booking

Also corrects the contract

Lockers and parking were listed as following the desk metadata pattern. They don't. Lockers come from banks and then lockers within them; parking needs level zones tagged parking plus a separate spaces API. Both are materially more setup than desks, and the rows now say so rather than implying quick wins.

🤖 Generated with Claude Code

camreeves and others added 3 commits August 3, 2026 18:05
Closes the last outstanding P0. login.spec.ts proves a login works and that the
token is usable; this proves the handshake that produced it was safe, which is a
different question. A client that leaked a secret or quietly dropped PKCE would
still end up with a valid token and a working app, so nothing in the response
tells you the exchange was sound. You have to look at what the browser sent.

loginViaUI now records every /auth/* request it observes, and the new spec asserts
S256 (never "plain"), a real base64url challenge, a code_verifier, the expected
client_id, and no client_secret anywhere. Plus: the password never appears in a
URL, and only ever reaches /auth/signin.

Red-checked. These assertions previously lived in tasks/PPT-2536/, where nothing
ran them.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Covers WP-E2E-08 and AUTH-E2E-05. A second seeded user cannot see the booking in
their listing, and cannot delete it; the owner still can. Includes a control
asserting you can see your own booking, otherwise "nobody sees anything" would
pass as success.

This locks down something we learned the hard way: GET /bookings is scoped to the
caller. An early leak check written as an admin reported zero bookings while the
database plainly held one. It is both a privacy boundary and a trap for anyone
writing tooling, and a regression would leak quietly rather than fail loudly.

Red-checked: inverting the assertion shows the other user's listing really is
empty while the booking exists.

Also corrects two rows in the contract. Lockers and parking do NOT follow the desk
metadata pattern as claimed - lockers come from banks then lockers within them,
parking needs level zones tagged `parking` plus a separate spaces API. Both are
more setup than desks, and the contract now says so rather than implying they are
quick wins.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
Maps to a shipped fix, "Fix rejecting overlapping bookings on desk assignment"
(2607.1). Double-booking is the kind of regression that doesn't announce itself:
nothing errors, nobody notices, and two people turn up to the same desk on
Tuesday.

Attempted as a SECOND user deliberately, because that's the real scenario and
because a clash check that only consulted your own bookings would still pass a
single-user version of this. Covers the identical slot and a partial overlap,
which is the case a naive check misses.

Two controls, so the test can't pass for the wrong reason: a genuinely
non-overlapping slot must still be accepted (otherwise a backend that rejected
everything would look correct), and the desk must free up once the booking is
deleted (a cancelled booking that still blocks the desk is harder to diagnose than
a plain double-booking).

Red-checked: the API really does return 409.

Co-Authored-By: Claude Opus 5 (1M context) <[email protected]>
@vercel

vercel Bot commented Aug 3, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
frontend-templates Ignored Ignored Aug 3, 2026 8:21am

@camreeves
camreeves requested review from MrYuion and stakach August 3, 2026 08:21
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