Skip to content

test(examples): runnable anonymous-sessions example + tiered tests - #2814

Open
tusharpandey13 wants to merge 1 commit into
feat/anon-sessions-implfrom
chore/anon-sessions-example
Open

test(examples): runnable anonymous-sessions example + tiered tests#2814
tusharpandey13 wants to merge 1 commit into
feat/anon-sessions-implfrom
chore/anon-sessions-example

Conversation

@tusharpandey13

@tusharpandey13 tusharpandey13 commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Summary

Stacked PR (2/2): example + tests. Adds examples/with-anonymous-sessions/, a runnable example consuming the local SDK that demonstrates the full anonymous-session flow. Stacked on top of the SDK implementation PR (#2797); review and merge that one first.

What it demonstrates

  • Guest session creation with set-once metadata (a cart id), via createAnonymousSession() behind a POST /api/anon/create route.
  • Server Component read (SSR) and live client-hook read (useAnonymousSession()) side by side.
  • Login-to-link: an anonymous session present at login is linked to the authenticated user at callback (the demo surfaces anonymousSessionLinked as a ?linked=true banner).
  • Logout that clears the anonymous cookie.

Tests

  • Unit and MSW: wire-contract and client-hook coverage.
  • Browser (Playwright): the session-fixation strip end-to-end and the logout and error-banner UI run without credentials; the live login-to-link callback runs against a tenant test user (pnpm test:e2e).
  • Offline mock tier (pnpm test:e2e:offline): 17 deterministic tests covering the full lifecycle (create, read, logout, error-code mappings, renewal, set-once retention) through the real SDK against a mocked Auth0 network hop. No tenant required. It does not prove the real /anonymous/token wire contract; the live tier does.

COVERAGE.md documents the tier-by-tier matrix and disclosed gaps.

Notes

  • The offline mock, its scenario-control route, and the env-gated customFetch seam are marked test-only, with a production checklist in the README and a warning in .env.example.
  • No real secrets in any spec or fixture (synthetic token-shaped values only).
  • Not wired into CI.

@tusharpandey13
tusharpandey13 requested a review from a team as a code owner August 19, 2026 11:37
@coderabbitai

coderabbitai Bot commented Aug 19, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 73ae8e1c-50ba-41d0-afd6-a3216c994f05

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

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.

Comment on lines +11 to +21
import {
SYNTHETIC_ACCESS_TOKEN,
SYNTHETIC_ACCESS_TOKEN_RENEWED,
SYNTHETIC_DOMAIN,
SYNTHETIC_METADATA,
SYNTHETIC_SESSION_TOKEN,
WIRE_CREATE_RESPONSE,
WIRE_LOGOUT_WITH_SESSION_TOKEN_ERROR,
WIRE_RENEW_RESPONSE,
WIRE_RENEW_WITH_METADATA_ERROR
} from "./fixtures/synthetic-tokens";
natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}

next@16.2.5:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High severity vulnerability may affect your project—review required:
Line 2177 lists a dependency (next) with a known High severity vulnerability.

ℹ️ Why this matters

Affected versions of next are vulnerable to Server-Side Request Forgery (SSRF). This Next.js config defines a rewrites()/redirects() rule whose destination builds an external hostname from a dynamic :param segment. Because the segment is not constrained to hostname-safe characters, an attacker can inject a value (e.g. containing a dot) that escapes the intended hostname suffix, causing Next.js to proxy the request server-side to an arbitrary host (SSRF) or redirect the client to an attacker-controlled destination (open redirect). Constrain each dynamic segment used in a destination hostname to hostname-safe characters (e.g. [a-z0-9-]+), or upgrade Next.js.

References: GHSA

To resolve this comment:
Check if you define a rewrites() or redirects() rule in next.config.js whose destination hostname is assembled from a dynamic :param segment.

💬 Ignore this finding

To ignore this, reply with:

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

You can view more details on this finding in the Semgrep AppSec Platform here.

natural-compare@1.4.0:
resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==}

next@16.2.5:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High severity vulnerability may affect your project—review required:
Line 2177 lists a dependency (next) with a known High severity vulnerability.

ℹ️ Why this matters

Affected versions of next are vulnerable to Excessive Iteration. Next.js App Router validates multi-page-application (MPA) form submissions by iterating over every $ACTION_REF_-prefixed form field without an upper bound, decoding a bound-argument descriptor for each one. An attacker can POST a form containing a large number of these fields, forcing excessive CPU usage that blocks processing of further requests in the same process, resulting in a denial of service. Declaring any Server Action ("use server") registers it in the server module map and arms this handler.

References: GHSA

To resolve this comment:
Check if you are using the App Router with at least one Server Action.

💬 Ignore this finding

To ignore this, reply with:

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

You can view more details on this finding in the Semgrep AppSec Platform here.

resolution: {integrity: sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==}
engines: {node: '>= 0.4'}

sharp@0.34.5:

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

High severity vulnerability introduced by a package you're using:
Line 2526 lists a dependency (sharp) with a known High severity vulnerability. Fixing requires upgrading or replacing the dependency.

ℹ️ Why this matters

Affected versions of sharp are vulnerable to Dependency on Vulnerable Third-Party Component. sharp bundles a vulnerable version of the native libvips library, inheriting four memory-safety flaws: an integer overflow leading to a heap-based buffer overflow in the VIPS loader (vipsload, CVE-2026-33327), an integer overflow in the GIF loader (gifload, CVE-2026-33328) causing a denial of service on 32-bit hosts only, a heap-based buffer overflow in the TIFF loader (tiffload, CVE-2026-35591) when handling JPEG or JPEG2000-encoded tiles, and an out-of-bounds read in the EXIF directory decoder (CVE-2026-35590). An attacker who can supply a crafted image can crash the process or corrupt heap memory. Because sharp selects the libvips loader by sniffing the input bytes, no call site can be shown to be safe, and the EXIF flaw is reachable from the JPEG, TIFF, WebP, PNG and HEIF loaders as well. Upgrade to sharp 0.35.0 or later, which bundles libvips 8.18.3. Blocking the affected loaders with sharp.block({ operation: ["VipsForeignLoadNsgif", "VipsForeignLoadTiff", "VipsForeignLoadVips"] }) is only a partial stopgap and does not mitigate the EXIF out-of-bounds read (CVE-2026-35590), for which no workaround exists.

References: GHSA

To resolve this comment:
Upgrade this dependency to at least version 0.35.0 at examples/with-anonymous-sessions/pnpm-lock.yaml.

💬 Ignore this finding

To ignore this, reply with:

  • /fp <comment> for false positive
  • /ar <comment> for acceptable risk
  • /other <comment> for all other reasons

You can view more details on this finding in the Semgrep AppSec Platform here.

@tusharpandey13

Copy link
Copy Markdown
Contributor Author

Anonymous-sessions example: browser e2e (Playwright) results

Browser-tier coverage for examples/with-anonymous-sessions/. This tier is a deliberately thin slice over the SDK's unit/integration coverage (see examples/with-anonymous-sessions/COVERAGE.md for the full behavior-by-tier matrix and disclosed gaps). It is not wired into CI, and the live-gated flows are intended to fold into the centralized root e2e/ harness once that suite lands in main.

Local run (Chromium)

Passing:

  • Session-fixation strip (creds-free): a caller-supplied session_token on /auth/login never reaches /authorize, both with no cookie present and when a legitimate anonymous cookie exists (only the cookie-derived token survives).
  • Logout UI (creds-free): clicking logout clears the anonymous cookie and returns home.
  • Error banner (creds-free): a failed session load renders the client hook's error banner.

Gated (skip without a tenant test user):

  • Login-to-link callback: completing a real Universal Login with an anonymous cookie present links the session at callback. Verified live against the dev tenant.

Notes

  • A credential-less run executes the creds-free tests; the fixation-with-cookie case and the live callback skip. Green on such a run is therefore not full security coverage; the load-bearing fixation assertion needs the tenant-minted cookie.
  • The cookie-tamper link-rejection negative is covered by the SDK unit tests (the link flag is asserted false on a digest mismatch), not at the browser tier.

No real secrets in any spec or fixture: gated tests read credentials from a git-ignored .env.local; mocked tests use synthetic token-shaped strings.

@tusharpandey13

Copy link
Copy Markdown
Contributor Author

Offline e2e tier added (mock-backed, tenant-free)

Follow-up to the browser-tier discussion: the example now ships a deterministic offline Playwright suite that exercises the full anonymous-session flow through the real SDK, mocking only the Auth0 network hop.

How it works

A test-only customFetch (gated by E2E_ANON_MOCK=1) fakes POST /anonymous/token + /anonymous/logout. The SDK still performs its real cookie encrypt / persist / decrypt / renew, so these tests cover the SDK's read/persist/renew/error-mapping paths and the example wiring without a live tenant. Runs on a separate config + port; the existing live-gated specs are untouched.

Run: pnpm test:e2e:offline

Coverage (17 tests, all run unconditionally)

  • Lifecycle: create, create with metadata, client-panel resolution, no-session empty state, metadata render, guest-button create, logout (cookie clear + redirect).
  • Errors: feature-not-enabled and unauthorized-client (403), invalid-target and invalid-scope (400), server-error (500), and oversized metadata rejected client-side (400) before any network call. Each asserts the mapped HTTP status.
  • Renewal + retention: silent renewal on expiry (fresh expiry asserted); metadata set-once retained across renewal (the mock renew omits metadata, so survival proves the SDK retains it from the cookie); single-cookie storage for typical payloads.

Example bug found + fixed

app/api/anon/create/route.ts returned HTTP 500 for every failure (it relied on a status field the error type doesn't carry). It now maps the code via the public getStatusForAnonymousError (@auth0/nextjs-auth0/errors), so create errors surface 401/403/400/500 correctly. Verified across all error scenarios.

Honest scope

  • This tier proves the SDK consume/persist/renew/error-map paths plus example UX, deterministically. It does not prove the real /anonymous/token wire contract (signature, claims, scope): the mock uses an unsigned synthetic token and omits those fields. That remains the live tier.
  • Cookie chunking above the single-cookie threshold is unreachable through the public create path (metadata is capped at 1KB), so it stays covered by the SDK cookie unit tests; the offline test asserts the single-cookie case and documents this.
  • The mock, its scenario-control route, and the gated seam are marked TEST-ONLY / DO NOT COPY TO PRODUCTION; README.md has a production checklist and .env.example warns on the gate. COVERAGE.md maps every behavior to its tier.

Reviewed via a multi-lens quorum (mock fidelity, test quality, prod-safety); all findings applied. No real secrets (synthetic token-shaped values only). Not wired into CI.

…ests

Add examples/with-anonymous-sessions/, a runnable example consuming the
local SDK that demonstrates the full anonymous-session flow: guest session
creation with metadata, Server Component and client-hook reads, login-to-link,
and logout.

Tiered test suite:
- Unit/MSW: wire-contract and client-hook coverage.
- Browser (Playwright): the session-fixation strip end-to-end and the
  logout and error-banner UI run without credentials; the live login-to-link
  callback runs against a tenant test user.
- Offline mock tier (pnpm test:e2e:offline): 17 deterministic tests covering
  the full lifecycle, error-code mappings, renewal, and set-once retention
  through the real SDK against a mocked Auth0 network hop, no tenant required.

COVERAGE.md documents the tier-by-tier matrix and disclosed gaps. The mock,
its scenario-control route, and the gated seam are marked test-only with a
production checklist in the README. No real secrets; synthetic tokens only.
Not wired into CI.

Depends on the anonymous-sessions SDK implementation (stacked base).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@tusharpandey13
tusharpandey13 force-pushed the chore/anon-sessions-example branch from be98137 to c58504c Compare August 19, 2026 12:28
@codecov-commenter

Copy link
Copy Markdown

Codecov Report

✅ All modified and coverable lines are covered by tests.
✅ Project coverage is 87.74%. Comparing base (8ef6a5f) to head (c58504c).

Additional details and impacted files
@@                   Coverage Diff                    @@
##           feat/anon-sessions-impl    #2814   +/-   ##
========================================================
  Coverage                    87.74%   87.74%           
========================================================
  Files                           84       84           
  Lines                        12253    12253           
  Branches                      2540     2540           
========================================================
  Hits                         10751    10751           
  Misses                        1455     1455           
  Partials                        47       47           

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.
  • 📦 JS Bundle Analysis: Save yourself from yourself by tracking and limiting bundle sizes in JS merges.

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.

3 participants