Skip to content

test(web-e2e): align rotation-durability floor helpers with combined store#600

Merged
FSM1 merged 4 commits into
mainfrom
fix/web-e2e-rotation-durability-floor-store
Jul 10, 2026
Merged

test(web-e2e): align rotation-durability floor helpers with combined store#600
FSM1 merged 4 commits into
mainfrom
fix/web-e2e-rotation-durability-floor-store

Conversation

@FSM1

@FSM1 FSM1 commented Jul 10, 2026

Copy link
Copy Markdown
Owner

Problem

tests/web-e2e/tests/rotation-durability.spec.ts has been red on every main run since #598 (Phase 70.1). The SC#4-setup assertion at line 216 fails:

Error: expect(received).toBeDefined()
Received: undefined
  216 | expect(floors.generation).toBeDefined();

Root cause

Phase 70.1 (D-06, #598) collapsed the two IndexedDB stores generation-high-water and seq-high-water into a single rotation-floor store keyed by nodeId, holding a { generation?, seq?, wrappedKeyCheckpoint? } record (see packages/sdk/src/state/rotation-idb-store.ts). The v2 onupgradeneeded migration deletes the old stores.

The e2e helpers readDurableFloors / writeDurableSeqFloor still probed the retired store names, so readDurableFloors short-circuited at its contains(...) guard and returned { generation: undefined } unconditionally — decoupled from whether the floor was actually persisted.

This is a stale test helper, not a durability regression: the product write path (enforceResolvedidbPutFloorsrotation-floor) is intact, and the v2 migration folds legacy data forward. Fixing the helper does not mask a bug — the helper never read real data.

Fix (test-only)

Point both helpers at the rotation-floor combined store. writeDurableSeqFloor now does a read-modify-write so it preserves the node's existing generation/wrappedKeyCheckpoint floors (matching production's max-preserving write). No product code changed.

Verification

  • npx tsc --noEmit in tests/web-e2e — clean.
  • Helper shape verified against rotation-idb-store.ts (store name rotation-floor, out-of-line key = nodeId, put(value, key)).
  • Full confirmation lands on the main-push web-e2e run after merge (web-e2e only runs on main push).

Summary by CodeRabbit

  • Tests
    • Updated end-to-end durability checks to work with the consolidated rotation storage.
    • Preserved existing generation data when updating sequence durability values.
    • Improved handling for missing storage records and clarified storage behavior.

Added: sdk-e2e Test 21 (D-06) flake fix

The SDK E2E Tests leg flaked red on this PR (orthogonal to the diff). Root cause: Test 21 in ipns-publish-gate.test.ts fires two concurrent first-publishes of the same new ipnsName with the same CID at sequence=1 and asserted exactly one 200 + one 409. But same-CID / same-sequence is idempotent by design (#599) — a loser that serializes after the winner commits re-reads the identical CID and returns an idempotent 200, so two 200s is also correct. The assertion now accepts both shapes (at least one winner; any loser is a clean 409, never a 5xx), keeping the exactly-one-row-at-seq-1 resolve check. Test-only.

@coderabbitai

coderabbitai Bot commented Jul 10, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@FSM1, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 58 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: f1ac40e5-59a2-42e6-8818-98b60308b378

📥 Commits

Reviewing files that changed from the base of the PR and between a8d16cd and e375b2a.

📒 Files selected for processing (4)
  • tests/sdk-e2e/src/suites/ipns-publish-gate.test.ts
  • tests/web-e2e/tests/full-workflow.spec.ts
  • tests/web-e2e/tests/rotation-durability.spec.ts
  • tests/web-e2e/tests/writable-shares.spec.ts

Walkthrough

The rotation durability test now uses the single rotation-floor IndexedDB store for durable floor reads and sequence staging, preserving existing record fields during sequence updates.

Changes

Rotation floor migration

Layer / File(s) Summary
Read combined durable floors
tests/web-e2e/tests/rotation-durability.spec.ts
readDurableFloors checks rotation-floor and reads the per-node record for generation and seq.
Stage sequence floor updates
tests/web-e2e/tests/rotation-durability.spec.ts
writeDurableSeqFloor reads the existing record, updates seq, and writes it back while preserving other fields and using out-of-line keys.

Estimated code review effort: 2 (Simple) | ~10 minutes

Possibly related PRs

  • FSM1/cipher-box#587: Introduced the rotation durability test and its durable rotation state logic.

Suggested labels: release:web:feat

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
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.
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: updating web-e2e rotation-durability helpers to use the combined store.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/web-e2e-rotation-durability-floor-store

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.

@github-actions

Copy link
Copy Markdown
Contributor

Release Preview

No version bumps detected. All changes are in unversioned paths or use exempt commit types.

@greptile-apps

greptile-apps Bot commented Jul 10, 2026

Copy link
Copy Markdown

Greptile Summary

This PR fixes a broken e2e test helper that was probing retired IndexedDB store names after Phase 70.1 collapsed two stores (generation-high-water / seq-high-water) into a single combined rotation-floor store. No product code is changed.

  • rotation-durability.spec.ts: Both readDurableFloors and writeDurableSeqFloor are updated to target rotation-floor. The write helper is upgraded to a read-modify-write so it preserves existing generation/wrappedKeyCheckpoint fields, mirroring the production idbPutFloors pattern — verified against rotation-idb-store.ts.
  • ipns-publish-gate.test.ts: Test 21 now accepts two 200s (idempotent same-CID race) alongside the original one 200 + one 409 shape, while keeping the hard invariants: at least one winner and any loser is a clean 409, never a 5xx.
  • full-workflow.spec.ts / writable-shares.spec.ts: Timeout bumps and a poll-based version-restore check replace a version-count gate that provided no real wait.

Confidence Score: 5/5

Test-only changes that fix stale helper references; no product code is touched and all helper logic aligns with the canonical IDB store implementation.

The IDB store name, key shape, and read-modify-write pattern in both helpers match rotation-idb-store.ts exactly. The concurrent-test assertion relaxation correctly preserves the hard invariants. Timeout bumps are conservative and well-motivated.

The expect.poll block in full-workflow.spec.ts (test 6.6.2) has a mild cleanup gap if waitForContentLoaded times out before clickCancel runs.

Important Files Changed

Filename Overview
tests/web-e2e/tests/rotation-durability.spec.ts Core fix: updates readDurableFloors and writeDurableSeqFloor to target the Phase 70.1 combined rotation-floor store; store name, key shape, and read-modify-write pattern match rotation-idb-store.ts exactly
tests/sdk-e2e/src/suites/ipns-publish-gate.test.ts Test 21 assertion relaxed to accept two 200s (idempotent winner) or one 200+one 409 (insert-race); hard invariants preserved: at least one winner, any loser is clean 409 never 5xx, and follow-up resolve still asserts exactly one row at sequence=1
tests/web-e2e/tests/full-workflow.spec.ts Timeout increases and version-restore check replaced with expect.poll; poll has a potential cleanup gap if inner waitForContentLoaded times out before clickCancel runs
tests/web-e2e/tests/writable-shares.spec.ts Straightforward timeout increases for shared-write mkdir round-trips under parallel-worker CI load; no logic changes

Reviews (4): Last reviewed commit: "test: stabilize web-e2e batch-op and sha..." | Re-trigger Greptile

@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: 1

🧹 Nitpick comments (1)
tests/web-e2e/tests/rotation-durability.spec.ts (1)

66-78: 🎯 Functional Correctness | 🔵 Trivial | 💤 Low value

Consider aligning readDurableFloors with production's fail-closed sanitization.

Production idbGetCombined (Context snippet 3, rotation-idb-store.ts:190-203) sanitizes the raw record via sanitizeRecord / isValidFloorValue, treating non-integer or negative values as undefined. This test helper reads rec?.generation and rec?.seq directly without validation. In a controlled E2E environment this is unlikely to matter, but if the store ever contains stale or corrupt data from a prior test run, the test could resolve a bogus floor and produce a false-positive pass.

♻️ Optional: add inline validation to mirror production
              tx.oncomplete = () => {
                const rec = getReq.result as { generation?: number; seq?: number } | undefined;
-               resolve({ generation: rec?.generation, seq: rec?.seq });
+               const valid = (v: unknown): v is number =>
+                 typeof v === 'number' && Number.isSafeInteger(v) && v >= 0;
+               resolve({
+                 generation: rec && valid(rec.generation) ? rec.generation : undefined,
+                 seq: rec && valid(rec.seq) ? rec.seq : undefined,
+               });
              };
🤖 Prompt for 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.

In `@tests/web-e2e/tests/rotation-durability.spec.ts` around lines 66 - 78, Update
the readDurableFloors helper to validate rotation-floor values before resolving
them, matching production idbGetCombined sanitization: only retain integer,
non-negative generation and seq values, and convert invalid, negative, or
non-integer values to undefined. Apply this validation to the rec fields read in
the rotation-floor transaction.
🤖 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 `@tests/web-e2e/tests/rotation-durability.spec.ts`:
- Around line 99-103: Clarify the comment above the rotation-floor helper to
state that the read-modify-write preserves existing generation and
wrappedKeyCheckpoint fields, but directly overwrites seq and does not apply
production’s max-preserving behavior. Update the parenthetical reference
accordingly.

---

Nitpick comments:
In `@tests/web-e2e/tests/rotation-durability.spec.ts`:
- Around line 66-78: Update the readDurableFloors helper to validate
rotation-floor values before resolving them, matching production idbGetCombined
sanitization: only retain integer, non-negative generation and seq values, and
convert invalid, negative, or non-integer values to undefined. Apply this
validation to the rec fields read in the rotation-floor transaction.
🪄 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: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: 7d5db5b8-bfdb-4620-a8c6-fc6ccfe9cfea

📥 Commits

Reviewing files that changed from the base of the PR and between 703bc00 and a8d16cd.

📒 Files selected for processing (1)
  • tests/web-e2e/tests/rotation-durability.spec.ts

Comment thread tests/web-e2e/tests/rotation-durability.spec.ts Outdated
FSM1 added a commit that referenced this pull request Jul 10, 2026
The doc comment claimed the read-modify-write "matches production's
max-preserving write", which is misleading: production idbPutFloors
max-preserves seq, whereas this staging helper intentionally overwrites seq
so a test can pin an exact sequence floor. Only the preservation of the
other fields (generation / wrappedKeyCheckpoint) matches production.
Comment-only; no behavior change. Addresses CodeRabbit review on #600.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: f73432632360
FSM1 added a commit that referenced this pull request Jul 10, 2026
…ublish

Test 21 (D-06) fires two concurrent first-publishes of the same brand-new
ipnsName with the SAME CID at sequence=1, and asserted exactly one 200 plus
one 409. But same-CID / same-sequence is idempotent by design (#599): when
the loser serializes after the winner commits, it re-reads the identical CID
and returns an idempotent 200 -- so both calls can legitimately succeed,
flaking the strict one-409 assertion (observed red on #600's SDK E2E leg).

Accept both correct shapes: at least one winner (never zero) and any loser is
a clean 409 (never a 5xx). The follow-up resolve still asserts exactly one row
at sequence=1. Test-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: d752b84767ae
FSM1 and others added 4 commits July 10, 2026 04:54
…store

Phase 70.1 (D-06, #598) collapsed the generation-high-water and
seq-high-water IndexedDB stores into a single rotation-floor store keyed
by nodeId holding a { generation?, seq?, wrappedKeyCheckpoint? } record.
The rotation-durability e2e helpers still probed the retired store names,
so readDurableFloors short-circuited and returned generation: undefined,
failing the SC#4 setup assertion at line 216 on every main run since #598.

Point readDurableFloors and writeDurableSeqFloor at the rotation-floor
store; the write does a read-modify-write so it preserves the node's
existing generation/wrappedKeyCheckpoint floors. Test-only -- the product
write path (rotation-idb-store.ts) is unchanged.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: 545aa91edc15
The doc comment claimed the read-modify-write "matches production's
max-preserving write", which is misleading: production idbPutFloors
max-preserves seq, whereas this staging helper intentionally overwrites seq
so a test can pin an exact sequence floor. Only the preservation of the
other fields (generation / wrappedKeyCheckpoint) matches production.
Comment-only; no behavior change. Addresses CodeRabbit review on #600.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: f73432632360
…ublish

Test 21 (D-06) fires two concurrent first-publishes of the same brand-new
ipnsName with the SAME CID at sequence=1, and asserted exactly one 200 plus
one 409. But same-CID / same-sequence is idempotent by design (#599): when
the loser serializes after the winner commits, it re-reads the identical CID
and returns an idempotent 200 -- so both calls can legitimately succeed,
flaking the strict one-409 assertion (observed red on #600's SDK E2E leg).

Accept both correct shapes: at least one winner (never zero) and any loser is
a clean 409 (never a 5xx). The follow-up resolve still asserts exactly one row
at sequence=1. Test-only.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: d752b84767ae
Batch delete/move (4.10/4.11), version restore poll (6.6.2), the serial
root-file delete chain (8.2), and recipient-side shared mkdirs each drive
IPNS publish round-trips whose serial-calibrated waits were too tight,
flaking locally and under parallel-worker CI load. Raise the explicit
per-call timeouts (CI already floors waiters to 60s via ciFloor) and make
6.6.2 poll the editor for the restored content instead of reading once.

Verified: full-workflow.spec.ts 53/53 green locally under the CI 60s-floor
timeout regime.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Entire-Checkpoint: 1fe70eb98011
@FSM1 FSM1 force-pushed the fix/web-e2e-rotation-durability-floor-store branch from 84b0c9f to e375b2a Compare July 10, 2026 02:54
@FSM1 FSM1 merged commit 64d5b0a into main Jul 10, 2026
36 checks passed
@FSM1 FSM1 deleted the fix/web-e2e-rotation-durability-floor-store branch July 10, 2026 03:12
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