Skip to content

feat(peek): richer live page-inspection in get_element_detail#120

Merged
harry-harish merged 6 commits into
mainfrom
feat/peek-live-inspection-reads
Jun 28, 2026
Merged

feat(peek): richer live page-inspection in get_element_detail#120
harry-harish merged 6 commits into
mainfrom
feat/peek-live-inspection-reads

Conversation

@harry-harish

@harry-harish harry-harish commented Jun 27, 2026

Copy link
Copy Markdown
Member

Summary

Enriches the existing Level-1 read tool get_element_detail with three additions, all masked and DOM-only (no CDP, no eval, no new permission/tool/schema):

  • computedStyles — a curated 19-key allowlist read from getComputedStyle(el) (layout/box + typography/paint), not a full ~350-property dump.
  • description — the accessible description, resolved from aria-describedby (id-list → referenced text) or aria-description, clipped to 500 chars.
  • effectiveAriaHidden / effectiveAriaDisabled — ancestor-walk inheritance flags ("why can't the agent act on this?").

get_page_view (the bulk read) is unchanged — these land on the single-element drill-in only, keeping the compact view cheap. The tool description now also points agents at get_session_console_errors / get_session_network_errors for live console/network state.

Masking (defense in depth)

Every new data-bearing field is masked at both layers:

  • In-page (MAIN world): a .rr-mask/[data-private] element returns ••• for its description, and an aria-describedby reference pointing into a masked region is redacted per-reference — mirroring how name/text/context.heading already behave.
  • Service-worker side: description runs through the PII masker; every url() in background-image (incl. comma-separated multi-backgrounds) has its query string redacted via maskUrl. All other style values are non-sensitive layout/paint and pass through untouched.

The MAIN-world buildElementDetail stays fully self-contained (.toString()-serializable) — all new logic is inline, no module-scope helpers.

Test Plan

  • @peekdev/extension suite green (incl. snapshot + masking tests; the in-page is self-contained serialization guard still passes)
  • new tests: curated allowlist, aria-describedby/aria-description resolution, aria inheritance, masked-region redaction of description, multi-url() background masking, plain-style pass-through
  • @peekdev/mcp server.test.ts green (enriched get_element_detail dispatch surfaces the new fields)
  • typecheck + biome clean across changed files
  • changeset (@peekdev/extension + @peekdev/mcp minor)

Summary by CodeRabbit

  • New Features
    • Expanded live element inspection results with richer accessible description, effective inherited aria-hidden/aria-disabled, and a curated allowlist of computed style values.
    • Improved masking for privacy-protected elements, including safe redaction of background-image url(...) values while keeping non-sensitive styles available.
  • Bug Fixes
    • Strengthened URL parsing and redaction for quoted, multi-layer, and parenthesized background-image strings without leaking per-layer secrets.
  • Tests
    • Added coverage for description resolution, aria inheritance, computed-style allowlisting, and background-image masking behavior.

…description + aria inheritance (H2.3)

Signed-off-by: harry-harish <22562634+harry-harish@users.noreply.github.com>
… bg-image url) (H2.3)

Signed-off-by: harry-harish <22562634+harry-harish@users.noreply.github.com>
…11y) + point at session tools for console/network (H2.3)

Signed-off-by: harry-harish <22562634+harry-harish@users.noreply.github.com>
Signed-off-by: harry-harish <22562634+harry-harish@users.noreply.github.com>
@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@harry-harish, we couldn't start this review because you've reached your PR review rate limit.

More reviews will be available in 58 minutes and 24 seconds. Learn how PR review limits work.

To continue reviewing without waiting, enable usage-based billing in the billing tab.

⌛ How to resolve this issue?

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 credits.

🚦 How do rate 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 see our Fair Usage Limits Policy for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: 2266f36e-1d48-4749-bd8c-e23c556f419d

📥 Commits

Reviewing files that changed from the base of the PR and between b720ccb and 4dd6f5d.

📒 Files selected for processing (7)
  • .changeset/peek-live-inspection-reads.md
  • packages/peek-extension/src/__tests__/action-handler.test.ts
  • packages/peek-extension/src/__tests__/snapshot.test.ts
  • packages/peek-extension/src/permissions/mask-view.ts
  • packages/peek-extension/src/permissions/snapshot.ts
  • packages/peek-mcp/src/mcp/server.ts
  • packages/peek-mcp/test/server.test.ts
📝 Walkthrough

Walkthrough

ElementDetail adds computedStyles, description, effectiveAriaHidden, and effectiveAriaDisabled. buildElementDetail computes them from CSS and ARIA attributes, maskElementDetail applies masking to the new fields, and the MCP get_element_detail description is updated.

Changes

ElementDetail enrichment and masking

Layer / File(s) Summary
ElementDetail and masked output types
packages/peek-extension/src/permissions/snapshot.ts, packages/peek-extension/src/permissions/mask-view.ts
ElementDetail and the masked output shape add computedStyles, description, effectiveAriaHidden, and effectiveAriaDisabled.
buildElementDetail enrichment
packages/peek-extension/src/permissions/snapshot.ts
buildElementDetail computes curated computedStyles, resolves description from aria-describedby or aria-description, and derives effective ARIA flags from ancestor attributes.
maskElementDetail masking
packages/peek-extension/src/permissions/mask-view.ts
maskElementDetail masks description, preserves effective ARIA booleans, and rewrites backgroundImage url() values inside computedStyles.
Tests, MCP text, and changeset
packages/peek-extension/src/__tests__/snapshot.test.ts, packages/peek-extension/src/__tests__/action-handler.test.ts, packages/peek-mcp/src/mcp/server.ts, packages/peek-mcp/test/server.test.ts, .changeset/peek-live-inspection-reads.md
Snapshot and action-handler tests cover allowlisted styles, description resolution, ARIA inheritance, and masking behavior; the MCP tool description and changeset entry are updated to match the new element detail fields.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

  • Cubenest/rrweb-stack#104: Extends the same get_element_detail / maskElementDetail pipeline with new element-detail fields and masking behavior.
  • Cubenest/rrweb-stack#63: Updates the MCP get_element_detail tool description in the same server registration area.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 75.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main change: richer live page inspection in get_element_detail.
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.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/peek-live-inspection-reads

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.

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

🧹 Nitpick comments (1)
packages/peek-mcp/test/server.test.ts (1)

770-776: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Assert the JSON details payload instead of substring-matching the serialized body.

These toContain(...) checks can still pass if the same text shows up elsewhere in the response. Parsing once and asserting details.description / details.computedStyles.display would lock the MCP contract this test is meant to cover.

Suggested tightening
-      expect(textOf(res as never)).toContain('Submits the login form');
-      expect(textOf(res as never)).toContain('display');
+      const body = JSON.parse(textOf(res as never)) as {
+        details?: {
+          description?: string;
+          computedStyles?: { display?: string };
+        };
+      };
+      expect(body.details?.description).toBe('Submits the login form');
+      expect(body.details?.computedStyles?.display).toBe('inline-block');
🤖 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 `@packages/peek-mcp/test/server.test.ts` around lines 770 - 776, The server
test is too loose because it substring-matches the serialized response instead
of validating the MCP `details` payload directly. Update the assertions in the
test around `textOf(res as never)` to parse the JSON once and verify the
`details` object fields explicitly, such as `details.description` and
`details.computedStyles.display`, so the contract is checked through the actual
structured response rather than incidental text.
🤖 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 `@packages/peek-extension/src/__tests__/snapshot.test.ts`:
- Around line 683-707: Replace the sensitive-looking fixture text in the
snapshot test with synthetic non-PII content while keeping the same masking
behavior coverage. Update the DOM setup in the `redacts the accessible
description inside a masked region` test so `buildPageView` and
`buildElementDetail` still verify redaction for masked descriptions, but avoid
real card-number/email literals in the `data-private`/`aria-describedby` nodes.

In `@packages/peek-extension/src/permissions/mask-view.ts`:
- Around line 126-129: The URL-masking regex in mask-view.ts is too restrictive
for quoted CSS urls, so it misses values containing ) and can leave secrets
unmasked. Update the replacement in the style masking path to correctly parse
quoted url(...) values with embedded ) while preserving the current
masked-by-default behavior, and keep the maskUrl(u) handling intact for all
matched URLs. Also make sure the fix still treats this as a potential PII
leakage path and masks sensitive query data consistently.

In `@packages/peek-extension/src/permissions/snapshot.ts`:
- Around line 897-902: The computed style snapshot in `snapshot.ts` is leaking
masked element `backgroundImage` values across the in-page boundary before
SW-side redaction runs. Update the logic that builds `computedStyles` (where
`getComputedStyle`, `STYLE_KEYS`, and the `.rr-mask` / `[data-private]` handling
are used) to explicitly strip or neutralize `backgroundImage` for masked
elements before returning the snapshot, ensuring no URL text leaves the page.

---

Nitpick comments:
In `@packages/peek-mcp/test/server.test.ts`:
- Around line 770-776: The server test is too loose because it substring-matches
the serialized response instead of validating the MCP `details` payload
directly. Update the assertions in the test around `textOf(res as never)` to
parse the JSON once and verify the `details` object fields explicitly, such as
`details.description` and `details.computedStyles.display`, so the contract is
checked through the actual structured response rather than incidental text.
🪄 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 Plus

Run ID: 1779f707-07cb-4451-8438-d78098f63b67

📥 Commits

Reviewing files that changed from the base of the PR and between b720ccb and ff7aec1.

📒 Files selected for processing (7)
  • .changeset/peek-live-inspection-reads.md
  • packages/peek-extension/src/__tests__/action-handler.test.ts
  • packages/peek-extension/src/__tests__/snapshot.test.ts
  • packages/peek-extension/src/permissions/mask-view.ts
  • packages/peek-extension/src/permissions/snapshot.ts
  • packages/peek-mcp/src/mcp/server.ts
  • packages/peek-mcp/test/server.test.ts

Comment thread packages/peek-extension/src/__tests__/snapshot.test.ts
Comment thread packages/peek-extension/src/permissions/mask-view.ts
Comment thread packages/peek-extension/src/permissions/snapshot.ts
…xture, structured server-test assertions (H2.3)

Signed-off-by: harry-harish <22562634+harry-harish@users.noreply.github.com>
@harry-harish

Copy link
Copy Markdown
Member Author

Addressed all three review findings in 543573c:

  • Major (mask-view.ts url() regex): quoted/unquoted-aware regex so a URL containing ) is fully captured + masked; regression test added.
  • Minor (snapshot.test.ts): synthetic non-PII fixture (masked path returns ••• regardless of content).
  • Minor (server.test.ts): assertions now JSON.parse the response and check structured details.description / details.computedStyles.display instead of substring-on-text.

Extension 138/138 + MCP server 34/34 green; typecheck + biome clean.

@coderabbitai review

@coderabbitai

coderabbitai Bot commented Jun 27, 2026

Copy link
Copy Markdown
🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== Changed files in commit 543573c =="
git show --stat --oneline --no-renames 543573c

echo
echo "== Outline: packages/peek-extension/src/permissions/mask-view.ts =="
ast-grep outline packages/peek-extension/src/permissions/mask-view.ts --view expanded || true

echo
echo "== Relevant hunk: packages/peek-extension/src/permissions/mask-view.ts =="
git show --unified=40 543573c -- packages/peek-extension/src/permissions/mask-view.ts

echo
echo "== Relevant hunk: packages/peek-extension/src/__tests__/snapshot.test.ts =="
git show --unified=40 543573c -- packages/peek-extension/src/__tests__/snapshot.test.ts

echo
echo "== Relevant hunk: packages/peek-mcp/test/server.test.ts =="
git show --unified=40 543573c -- packages/peek-mcp/test/server.test.ts

Length of output: 13554



@harry-harish Reviewed the follow-up in 543573c — the three fixes look good to me.

  • packages/peek-extension/src/permissions/mask-view.ts: the url(...) masking is now quote-aware and handles the previously flagged case.
  • packages/peek-extension/src/__tests__/snapshot.test.ts: the fixture is now non-PII while still validating the masked-path behavior.
  • packages/peek-mcp/test/server.test.ts: structured JSON.parse(...) assertions are a clear improvement over substring checks.

No new concerns from this follow-up pass. Nice cleanup. 🐇✨


If you found this review helpful, would you consider giving us a shout-out on X%60%20safely%2C%20plus%20tests%20use%20synthetic%20fixtures%20%2B%20structured%20JSON%20asserts.%20Faster%2C%20safer%20reviews%20%F0%9F%9A%80%F0%9F%9B%A1%EF%B8%8F&url=https%3A%2F%2Fgithub.com%2FCubenest%2Frrweb-stack%2Fpull%2F120)?

Thank you for using CodeRabbit!

✅ Action performed

Review finished.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

…not leave the page (H2.3 review)

Signed-off-by: harry-harish <22562634+harry-harish@users.noreply.github.com>
@harry-harish

Copy link
Copy Markdown
Member Author

Fixed the third finding (masked-element backgroundImage in-page redaction) in 4dd6f5d, with a regression test. All three review findings now addressed; CI green, extension + mcp suites green, typecheck + biome clean.

@coderabbitai full review

@coderabbitai

coderabbitai Bot commented Jun 28, 2026

Copy link
Copy Markdown

@harry-harish Thanks for the update — I’ll do a full pass on #120 with the latest fixes in 4dd6f5d.

✅ Action performed

Full review finished.

@harry-harish harry-harish merged commit 9ddf4d1 into main Jun 28, 2026
7 checks passed
@harry-harish harry-harish deleted the feat/peek-live-inspection-reads branch June 28, 2026 03:09
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