feat(replay): add opt-in custom-paint masking - #573
Conversation
posthog-flutter Compliance ReportDate: 2026-09-11 10:39:42 UTC ✅ All Tests Passed!45/45 tests passed Capture Tests✅ 29/29 tests passed View Details
Feature_Flags Tests✅ 16/16 tests passed View Details
|
|
Reviews (1): Last reviewed commit: "feat(replay): make custom-paint masking ..." | Re-trigger Greptile |
|
Validated commit The tests exercised the actual Flutter screenshot capture and masking path and checked the resulting replay image pixels:
The run also covered foreground painters, flag combinations, explicit masks, painter-less containers, transforms, and the debug-banner behavior when opted in. This used a temporary integration-test app against the PR worktree. PostHog platform calls and replay-state responses were mocked, so no events were sent to PostHog. This validates on-device rendering and screenshot masking, not ingestion or playback in the PostHog UI. |
💡 Motivation and Context
Related to #568.
Session replay masks ordinary text but does not mask text drawn by a
CustomPainter. Masking every custom painter by default would also hide Flutter decorations and could cover large parts of the screen.This PR adds
PostHogSessionReplayConfig.maskCustomPaint, defaulting tofalse. Apps can opt in with:The option works independently of
maskAllTextsandmaskAllImages, including when both are disabled. When enabled, it masks the full bounds ofCustomPaintwidgets with a painter or foreground painter, including their children. Painter-less containers still allow their children to be checked normally. The flag is used by both Flutter screenshot capture and the web mask-region provider.Default masking behavior remains unchanged. The docs clarify that custom-painted text and images require this option or an explicit
PostHogMaskWidget. Enabling the option can mask decorations too. Flutter's debug banner uses a full-windowCustomPaint, so the docs recommend disablingdebugShowCheckedModeBannerwhen using this option.💚 How did you test it?
maskCustomPaintenabled. A temporary app used a fake PostHog platform interface and mocked replay-state calls, so no events were sent to PostHog.git diff --checkpassed.a440e0af45e1b07aed9b549f6996386636811f28againstorigin/mainreported no actionable findings.📝 Checklist
If releasing new changes
🤖 Agent context
Autonomy: Human-driven (agent-assisted)
Pi implemented this feature using file tools, Git, Flutter tests, Chrome, an Android emulator, and the autoreview helper. The work was directed by @marandaneto and done in a dedicated worktree.
The initial implementation masked custom painters whenever text or image masking was enabled. After reviewing the risk of hiding non-sensitive UI, the human owner requested an independent
maskCustomPaintoption defaulting tofalse. Human review is required.