Skip to content

feat(ppr): expose navigation replay hits - #774

Merged
ivogt merged 1 commit into
mainfrom
feat/ppr-replay-status
Jul 11, 2026
Merged

ivogt merged 1 commit into
mainfrom
feat/ppr-replay-status

Conversation

@ivogt

@ivogt ivogt commented Jul 11, 2026

Copy link
Copy Markdown
Collaborator

Problem

Consumers could confirm a PPR document shell with x-rango-shell, but a partial navigation exposed no signal showing whether its captured canonical segment record was reused. A replay hit, an explicit cache() scope, and a correctness fallback all looked identical without inspecting generic timings or private store data.

This PR adds the positive replay signal from #772 without changing transition semantics. Bypass reasons and replay-safe transition({ when }) behavior remain separate work.

Before vs. after

Before, a consumer could only observe document shell status:

assertShellStatus(documentResponse, "HIT");
// The following partial response had no PPR-specific status.

After, a confirmed segment replay is directly assertable:

assertShellStatus(documentResponse, "HIT");
assertPprReplayStatus(partialResponse, "HIT");

The wire signal is:

X-Rango-PPR-Replay: HIT

End-to-end example

import { assertPprReplayStatus } from "@rangojs/router/testing/e2e";

const partialResponsePromise = page.waitForResponse((response) => {
  const url = new URL(response.url());
  return url.pathname === "/products/42" && url.searchParams.has("_rsc_partial");
});

await page.getByRole("link", { name: "Product 42" }).click();
const partialResponse = await partialResponsePromise;

assertPprReplayStatus(
  { headers: new Headers(partialResponse.headers()) },
  "HIT",
);

Semantics

Partial-navigation outcome Header
Captured PPR segment decodes and supplies the implicit document cache scope x-rango-ppr-replay: HIT
A route-authored cache() scope wins absent
Seeded segment is missing or corrupt absent
PPR replay is ineligible or bypassed absent
Document shell HIT/MISS unchanged; still uses x-rango-shell

HIT is recorded after successful segment deserialization and handle restoration. Finding a shell entry or installing a seeded store is not enough, so a corrupt record or a higher-priority explicit cache cannot produce a false positive.

Code changes

  • rsc-rendering.ts attaches the header to the partial RSC response only after the implicit replay scope reports a successful hit.
  • cache-scope.ts owns the exact post-decode confirmation boundary through a module-private observer; the public CacheScope API is unchanged.
  • shell-status.ts exports assertPprReplayStatus, parsePprReplayStatus, PPR_REPLAY_STATUS_HEADER, and PprReplayStatus from both testing entry points.
  • The PPR execution model, testing guide, and skills document the signal and its absence semantics.

Test plan

  • Red-before-green unit coverage: seeded replay initially returned no x-rango-ppr-replay header; the new pipeline and store tests failed before implementation and pass after it.
  • Unit: successful decode reports HIT; explicit cache() precedence and corrupt decode do not.
  • Public helper: parse/assert behavior through @rangojs/router/testing exports.
  • Router test app: partial navigation replays the PPR segment shell... in dev and production.
  • Cloudflare consumer app with CFCacheStore: same case in dev and production.
  • Semantic matrix: 69 tests in dev and production.
  • pnpm run typecheck
  • pnpm run test:unit:all
  • pnpm run lint
  • pnpm run format
  • docs API, skills, e2e bucketing, and strict parity guards

Notes

  • This deliberately reports only confirmed HITs. MISS/BYPASS classification and bounded reasons need a stable taxonomy and are not inferred from absence.
  • Existing transition({ when }) routes still bypass PPR segment replay; a follow-up PR will address replay-safe predicate semantics.

Part of #772.

@pkg-pr-new

pkg-pr-new Bot commented Jul 11, 2026

Copy link
Copy Markdown

Open in StackBlitz

npm i https://pkg.pr.new/@rangojs/router@774

commit: 70b07f2

@ivogt
ivogt merged commit 824ad44 into main Jul 11, 2026
36 checks passed
@ivogt
ivogt deleted the feat/ppr-replay-status branch July 11, 2026 11:46
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