Skip to content

test(e2e): stop the SLS masking spec asserting over its own warm-up traffic - #890

Merged
jarvis9443 merged 2 commits into
mainfrom
test/sls-masked-capture-warmup-race
Aug 4, 2026
Merged

test(e2e): stop the SLS masking spec asserting over its own warm-up traffic#890
jarvis9443 merged 2 commits into
mainfrom
test/sls-masked-capture-warmup-race

Conversation

@jarvis9443

@jarvis9443 jarvis9443 commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Fixes #889

Fixes a CI-only failure in sls-content-capture-masked-e2e, seen on #888:

AssertionError: expected '...' not to contain 'alice@example.com'

Cause

The spec waits for config propagation by sending warm-up chats until the masked form shows up on the wire. Those warm-up requests are exported to SLS too, and the ones served before the guardrail went live carry the unmasked reply — which is correct behaviour for a gateway that has no masking rule yet.

decodedTextFor joins every PutLogs body the mock has ever received, so expect(fullText).not.toContain(EMAIL) was also asserting over those pre-propagation exports. On a fast machine the guardrail is live by the first warm-up, nothing unmasked is ever exported, and the spec passes; on slower CI it is not, and the raw address is there.

The product behaviour under test is fine — the assertion population was wrong.

Fix

Snapshot sls.requests.length once the config is confirmed live, and scope the assertions to what was exported after it. decodedTextFor and waitForToken take a fromIndex (default 0, so the other SLS specs are unchanged).

Verification

The condition is timing-dependent, so I forced it rather than guessing: inserting one request that is served after the model is live but before the guardrail exists reproduces the CI failure exactly with the old assertion scope, and passes with this change. All four SLS specs pass locally.

Summary by CodeRabbit

  • Tests
    • Improved end-to-end validation of masked chat and bridge responses.
    • Excluded configuration warm-up traffic from exporter assertions to prevent false results.
    • Enhanced test polling and decoding to focus on responses received after setup.
    • Continued verifying that masked responses contain no raw email data.

…raffic

`sls-content-capture-masked-e2e` waits for config propagation by sending
warm-up chats until the masked form appears on the wire. Those warm-up
requests are exported too, and the ones served before the guardrail went
live carry the UNMASKED reply — correct behaviour for a gateway that has
no masking rule yet.

`decodedTextFor` joins every PutLogs body the mock ever received, so
`expect(fullText).not.toContain(EMAIL)` was also asserting over those
pre-propagation exports. On a fast machine the guardrail is live by the
first warm-up and nothing unmasked is ever exported; on slower CI it is
not, and the spec fails with the raw address present.

Snapshot `sls.requests.length` once the config is confirmed live and scope
the assertions to what was exported after it, via a `fromIndex` argument
on `decodedTextFor` / `waitForToken` (default 0, so other callers are
unchanged).

Verified by forcing the condition: a request served after the model is
live but before the guardrail exists reproduces the CI failure exactly,
and passes with this change.
@coderabbitai

coderabbitai Bot commented Aug 4, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

You’ve reached a temporary PR review limit under our Fair Usage Limits Policy.

Your recent review volume is higher than typical usage, so adaptive limits are currently applied.

Next review available in: 45 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 271099aa-fe6e-4c9d-8ed7-307cd0ce640c

📥 Commits

Reviewing files that changed from the base of the PR and between d31e80d and 99fd09e.

📒 Files selected for processing (1)
  • tests/e2e/src/cases/sls-content-capture-masked-e2e.test.ts
📝 Walkthrough

Walkthrough

The SLS mock now supports request-index filtering for decoded text and token polling. The masked content capture test records the post-warm-up index and applies it to chat and bridge export assertions.

Changes

Masked SLS capture assertions

Layer / File(s) Summary
Scope SLS decoding and polling
tests/e2e/src/harness/sls-mock.ts
decodedTextFor and waitForToken accept fromIndex and ignore earlier SLS requests.
Apply the post-warm-up request index
tests/e2e/src/cases/sls-content-capture-masked-e2e.test.ts
The test records the request index after warm-up and uses it for chat and bridge export checks.

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

Possibly related issues

🚥 Pre-merge checks | ✅ 6
✅ Passed checks (6 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately describes the main change: fixing a test that was asserting over warm-up traffic instead of excluding it from the SLS masking specification.
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.
E2e Test Quality Review ✅ Passed E2E test correctly isolates warm-up traffic from assertions by snapshotting request count after guardrail propagation. All real services used appropriately, assertions straightforward, error handli...
Security Check ✅ Passed This PR modifies only test code (E2E test harness and test case). The changes add an optional fromIndex parameter to decodedTextFor and waitForToken functions with default value 0, maintain...
✨ 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/sls-masked-capture-warmup-race

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

@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

🤖 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/e2e/src/cases/sls-content-capture-masked-e2e.test.ts`:
- Around line 194-200: Ensure the warm-up boundary in the test aligns with
exporter completion before capturing afterWarmup: after waitConfigPropagation,
explicitly drain or flush the SLS exporter, or wait long enough for its 5-second
buffer interval to elapse before snapshotting sls.requests.length.
Alternatively, add and use a correlation marker or request ID so decodedTextFor
can distinguish warm-up records from post-mask traffic.
🪄 Autofix

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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 1f37a747-62d5-46d1-83e5-f4ba9db55b65

📥 Commits

Reviewing files that changed from the base of the PR and between 81e4fc6 and d31e80d.

📒 Files selected for processing (2)
  • tests/e2e/src/cases/sls-content-capture-masked-e2e.test.ts
  • tests/e2e/src/harness/sls-mock.ts

Comment thread tests/e2e/src/cases/sls-content-capture-masked-e2e.test.ts
…boundary

An index boundary alone is not deterministic: the sink buffers records and
flushes on a 5s tick (`PipelineConfig { max_batch: 100, flush_interval: 5s }`),
so a warm-up record still in that buffer ships in the SAME PutLogs body as
the requests under test, and slicing by request index cannot separate them.

Send one marker request after the guardrail is live — masked, so it carries
no raw PII — and wait for it to arrive before snapshotting. The sink flushes
its buffer in order, so the marker being visible proves every warm-up record
has already shipped.
@jarvis9443
jarvis9443 merged commit 17141a6 into main Aug 4, 2026
11 checks passed
@jarvis9443
jarvis9443 deleted the test/sls-masked-capture-warmup-race branch August 4, 2026 14:55
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.

flaky/possible mask race: streaming SLS full-capture intermittently contains raw PII on CI (sls-content-capture-masked-e2e)

1 participant