Skip to content

test(e2e): cover auth_flow TTL regression boundary - #124

Merged
aspiers merged 1 commit into
mainfrom
test/auth-flow-ttl
May 6, 2026
Merged

test(e2e): cover auth_flow TTL regression boundary#124
aspiers merged 1 commit into
mainfrom
test/auth-flow-ttl

Conversation

@aspiers

@aspiers aspiers commented Apr 30, 2026

Copy link
Copy Markdown
Contributor

Summary

Stacks on PR #122. Adds a second @otp-expiry scenario that asserts the auth_flow + cookie 60-minute TTL is actually enforced — backdates the auth_flow row + drops the cookie via the /_internal/test/expire-auth-flow hook (already shipped in #122), then submits a still-valid OTP. /auth/complete must show "Authentication session expired" because the OAuth ticket has aged out independently of the OTP.

Without this guardrail, nothing in CI would catch a future change quietly shortening AUTH_FLOW_TTL_MS back to the OTP TTL — the existing scenario in #122 only proves the 10-min-and-resend path works, not that the 60-min boundary exists.

Reuses every existing step except two new ones:

  • When more than 60 minutes pass before the user submits the OTP — backdates auth_flow + clears the cookie, leaves OTP untouched.
  • Then the auth-complete page shows an "Authentication session expired" error — asserts on the rendered error page at /auth/complete.

Test plan

  • pnpm format:check clean
  • pnpm lint clean
  • pnpm typecheck clean
  • pnpm test — 812 unit tests pass (no new tests; only e2e changes)
  • Local e2e: both @otp-expiry scenarios pass (29 steps, 18.7s) against docker-compose stack
  • Rebase onto main once test(e2e): cover OTP expiry without 10-minute wait #122 merges

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests
    • Added E2E scenarios verifying authentication sessions abort when more than 60 minutes elapse before OTP submission.
    • Added verifications that expired authentication sessions show the “Sign-in session expired” message and that the abort reason is recorded for diagnostics.

@vercel

vercel Bot commented Apr 30, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
epds-demo Ready Ready Preview, Comment May 5, 2026 6:33pm

Request Review

@changeset-bot

changeset-bot Bot commented Apr 30, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: c2ca73a

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@railway-app

railway-app Bot commented Apr 30, 2026

Copy link
Copy Markdown

🚅 Deployed to the ePDS-pr-124 environment in ePDS

Service Status Web Updated (UTC)
@certified-app/pds-core ✅ Success (View Logs) Web May 5, 2026 at 4:30 pm
@certified-app/demo ✅ Success (View Logs) Web May 5, 2026 at 3:27 pm
@certified-app/auth-service ✅ Success (View Logs) Web May 5, 2026 at 3:27 pm
@certified-app/demo untrusted ✅ Success (View Logs) Web May 5, 2026 at 3:27 pm

@coderabbitai

coderabbitai Bot commented Apr 30, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 78ea6146-add3-4302-b9a5-db7fd0fe947c

📥 Commits

Reviewing files that changed from the base of the PR and between 0421a95 and c2ca73a.

📒 Files selected for processing (3)
  • e2e/step-definitions/auth.steps.ts
  • e2e/support/world.ts
  • features/passwordless-authentication.feature
🚧 Files skipped from review as they are similar to previous changes (1)
  • e2e/step-definitions/auth.steps.ts

📝 Walkthrough

Walkthrough

Adds end-to-end test steps and a feature scenario that simulate the OAuth auth_flow expiring (>60 minutes) by calling an internal expire hook, intercepting the /auth/ping response to observe abort reason, and asserting the UI shows a sign-in session expired/abort flow.

Changes

OAuth Flow Expiry Test Coverage

Layer / File(s) Summary
Data Shape / World
e2e/support/world.ts
Adds pendingPingBody?: Promise<{ ok: boolean; reason?: string }> to store the next /auth/ping response body for later assertions.
Core Test Implementation
e2e/step-definitions/auth.steps.ts
Adds step "more than 60 minutes pass before the user submits the OTP" which calls /_internal/test/expire-auth-flow (asserts ≥1 row updated), intercepts **/auth/ping via page.route, captures and forwards the raw response body, stores captured JSON in this.pendingPingBody, and removes the route after first capture. Adds steps to assert auth/complete shows an error and that the OAuth flow aborts due to flow_expired (checks captured ping body and **/auth/abort h1 text). Also imports type Route.
Scenario / Feature
features/passwordless-authentication.feature
Adds @email @otp-expiry`` scenario "OAuth flow expires after the auth_flow TTL elapses" that exercises the above steps (initiates OAuth login, backdates auth_flow >60min via test hook, submits OTP, and asserts abort/expired UI).

Sequence Diagram(s)

sequenceDiagram
    participant TestRunner
    participant InternalHook
    participant Browser
    participant Server
    TestRunner->>InternalHook: POST /_internal/test/expire-auth-flow (backdate auth_flow)
    InternalHook-->>TestRunner: { rowsUpdated: N }
    TestRunner->>Browser: set up page.route("**/auth/ping")
    Browser->>Server: auth/ping (request)
    opt first ping after route set
      Browser->>Browser: route.fetch() -> raw Response
      Browser->>TestRunner: captured ping JSON (stored in pendingPingBody)
      Browser-->>Server: fulfilled response with same raw body
    end
    Browser->>Server: navigation triggers auth/complete or auth/abort
    Server-->>Browser: auth/abort (redirect)
    TestRunner->>Browser: assert pendingPingBody.reason == "flow_expired" and auth/abort UI
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Possibly related issues

Possibly related PRs

Suggested reviewers

  • Kzoeps
  • s-adamantine

Poem

🐰
I hopped through code and tunneled time,
Sixty minutes passed — the session's crime.
A ping was caught, the hook rang true,
"Flow expired" — the abort came through.
Celebrate tests, with carrot and rhyme.

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title 'test(e2e): cover auth_flow TTL regression boundary' accurately describes the main change: adding e2e test coverage for the auth_flow TTL enforcement at the 60-minute boundary.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch test/auth-flow-ttl

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Base automatically changed from test/otp-expiry-e2e to main April 30, 2026 14:30
@aspiers
aspiers force-pushed the test/auth-flow-ttl branch from 73c5c4e to ee1c28e Compare April 30, 2026 14:32
@railway-app
railway-app Bot temporarily deployed to ePDS / ePDS-pr-124 April 30, 2026 14:32 Destroyed
@coveralls-official

coveralls-official Bot commented Apr 30, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 25394910354

Coverage remained the same at 55.53%

Details

  • Coverage remained the same as the base build.
  • Patch coverage: No coverable lines changed in this PR.
  • No coverage regressions found.

Uncovered Changes

No uncovered changes found.

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 2934
Covered Lines: 1624
Line Coverage: 55.35%
Relevant Branches: 1804
Covered Branches: 1007
Branch Coverage: 55.82%
Branches in Coverage %: Yes
Coverage Strength: 5.73 hits per line

💛 - Coveralls

Copilot AI review requested due to automatic review settings May 5, 2026 15:25
@aspiers
aspiers force-pushed the test/auth-flow-ttl branch from ee1c28e to 0421a95 Compare May 5, 2026 15:25
@railway-app
railway-app Bot temporarily deployed to ePDS / ePDS-pr-124 May 5, 2026 15:25 Destroyed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds an additional e2e regression boundary for passwordless OAuth flows to ensure the auth_flow + epds_auth_flow cookie TTL (60 minutes) is enforced independently of OTP validity, asserting that /auth/complete reports an expired authentication session once the flow TTL elapses.

Changes:

  • Added a new @otp-expiry scenario asserting auth flow expiry after >60 minutes (even with a still-valid OTP).
  • Added Cucumber step definitions to expire the auth flow via an internal test hook, clear the flow cookie, and assert the /auth/complete error rendering.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated 1 comment.

File Description
features/passwordless-authentication.feature Adds a new auth_flow TTL regression scenario (but currently includes an unresolved merge conflict marker).
e2e/step-definitions/auth.steps.ts Adds steps to expire the auth_flow + clear cookie, and a new assertion step for /auth/complete error content.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread features/passwordless-authentication.feature Outdated

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@e2e/step-definitions/auth.steps.ts`:
- Around line 491-500: The test fails because the expected string in the step
definition (the Then step using page.locator('p.error') in auth.steps.ts) does
not match the actual message rendered by the auth completion flow (complete.ts
-> "Your sign-in took too long to complete. Please start sign-in again."); fix
this by reconciling the two: either update the feature expectation to "Your
sign-in took too long to complete. Please start sign-in again." (so the Then
step continues to call expect(page.locator('p.error')).toContainText(expected))
or change the auth completion rendering in complete.ts (and any helper in
render-error.ts) to return "Authentication session expired" so the existing
feature text remains correct—pick one approach and apply the text change
consistently across the feature, auth.steps.ts expectation, and the
complete.ts/render-error.ts implementation.

In `@features/passwordless-authentication.feature`:
- Line 275: Remove the leftover Git conflict marker "<<<<<<< HEAD" from the
feature file (it appears as a raw line in the Gherkin text), ensure there are no
other conflict markers (like "=======" or ">>>>>>>") remaining, and keep the
existing content that follows intact so the Gherkin parser can parse the
feature; verify by running the Cucumber/Gherkin parser or test suite to confirm
the file loads cleanly.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 4b78b98b-80d8-46d6-bc58-4ebc36d3dbd2

📥 Commits

Reviewing files that changed from the base of the PR and between 72d9113 and 0421a95.

📒 Files selected for processing (2)
  • e2e/step-definitions/auth.steps.ts
  • features/passwordless-authentication.feature

Comment thread e2e/step-definitions/auth.steps.ts
Comment thread features/passwordless-authentication.feature Outdated
@blacksmith-sh

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 3 out of 3 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread features/passwordless-authentication.feature
Comment thread e2e/step-definitions/auth.steps.ts
Comment thread e2e/step-definitions/auth.steps.ts Outdated
@aspiers
aspiers force-pushed the test/auth-flow-ttl branch from 0831858 to 650c2cb Compare May 5, 2026 17:08
@railway-app
railway-app Bot temporarily deployed to ePDS / ePDS-pr-124 May 5, 2026 17:08 Destroyed
Adds a second @otp-expiry scenario that backdates the auth_flow row
via the existing /_internal/test/expire-auth-flow hook, then submits
a still-valid OTP. After PR #154's reactive abort gate the OTP form
pings /auth/ping before submitting; with the auth_flow row dead the
ping reports `flow_expired`, the gate navigates to /auth/abort, and
cleanExit serves its Tier-2 styled "Sign-in session expired" fallback
page (the OAuth client redirect path needs the dead row's clientId,
which is exactly what's missing here).

The scenario asserts both signals — the ping reason (proving
auth_flow specifically tripped, not PAR) and the abort fallback
page — so a regression that, say, swaps which timer the gate honours
would still be caught.

Without this guardrail nothing in CI would notice if AUTH_FLOW_TTL_MS
were quietly shortened back to the OTP TTL; the existing scenario
only proves the 10-min-and-resend path works, not that the 60-min
boundary is enforced.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@aspiers
aspiers force-pushed the test/auth-flow-ttl branch from 650c2cb to c2ca73a Compare May 5, 2026 18:32
@railway-app
railway-app Bot temporarily deployed to ePDS / ePDS-pr-124 May 5, 2026 18:32 Destroyed
@sonarqubecloud

sonarqubecloud Bot commented May 5, 2026

Copy link
Copy Markdown

@aspiers
aspiers merged commit e060e2f into main May 6, 2026
15 checks passed
@aspiers
aspiers deleted the test/auth-flow-ttl branch May 6, 2026 13:16
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.

2 participants