← all branches

feat/ph-replay

needs attentionviewing older commit
8d1b744 · incrementalPR #361reviewed 2026-07-30 21:44 UTC0H · 5M · 10L · 5I
The branch
Purpose
Batu platform lacked session replay data despite PostHog being configured — disable_session_recording local kill-switch was always true, confirmed by 0 $snapshot events vs 1,604 $pageview events in 14 days.
Goal
Enable PostHog session replay on apps/platform (prod only) with a two-part gate, and harden privacy so secrets rendered outside <input> are excluded from capture.
Sub-goals
  • SG-1: Wire disable_session_recording: false when both gate halves pass
  • SG-2: Keep apps/web, staging, and preview branches out of recording
  • SG-3: Mask all input values unconditionally (CFE credentials)
  • SG-4: Block non-input secrets via ph-no-capture class
  • SG-5: Extract gate logic to pure testable session-replay.ts
  • SG-6: Test all 4 gate combinations to guard silent PII recording regressions
  • SG-7: Remove dead maskTextSelector: '.sensitive'
The changes (whole branch)
What
PostHogProvider delegates to session-replay.ts; ph-no-capture added to SecretRevealCard and EnvPanel; dead .sensitive maskTextSelector removed; 71-line test suite added; docs updated.
Why
disable_session_recording: true in posthog.init() overrode the PostHog console config. maskAllInputs only covers <input>; API keys in <code> blocks were recorded in clear.
Areas
apps/platform+113packages/analytics+20319docs/analytics+4815
Blast
8 files +262/−37. Additive only, gate defaults OFF without env var, no schema/API/domain touched.
Merge alone is a no-op — requires NEXT_PUBLIC_POSTHOG_SESSION_REPLAY=true in Vercel (Production only) PostHog console sampling/duration/recording-limit settings still need server-side config post-merge
ci· No CI checks reported for this PRcoderabbit· No .coderabbit.yaml in repo

Findings · 20

correctness2

low

useEffect empty deps silently ignores post-mount sessionReplay prop changes

packages/analytics/src/providers/PostHogProvider.tsx:111

Intentional and documented — both gate halves are build-time constants. Risk is future confusion if sessionReplay is ever made dynamic.

low

SESSION_REPLAY_ENABLED_FOR_ENV frozen at module load — test ordering constraint

packages/analytics/src/providers/session-replay.ts:34

Tests that set process.env after import see stale value. Fine in practice (tests pass explicit booleans).

security4

low

ph-no-capture is the only defense for non-input secrets — no structural enforcement

packages/analytics/src/providers/PostHogProvider.tsx

mask_all_text: false + autocapture: true means any non-input secret without ph-no-capture ancestor will be captured. Convention-only; no lint rule or component wrapper guards future misses.

info

Removal of dead .sensitive selector — no regression

packages/analytics/src/providers/PostHogProvider.tsx

info

EnvPanel bearer token has double coverage — appropriate for most sensitive credential

apps/platform/src/app/[locale]/(docs)/_components/EnvPanel.tsx:125

info

ph-no-capture on parent div correctly blocks descendant secrets

apps/platform/src/app/[locale]/(dashboard)/credentials/api/_components/SecretRevealCard.tsx:39

conventions4

medium

@file JSDoc block violates no-multi-line-comment rule

packages/analytics/src/providers/session-replay.ts:1

6-line @file/@description JSDoc block. CLAUDE.md prohibits multi-paragraph docstrings. Collapse to: // Pure gate: no imports so vitest/node can run this without posthog-js.

low

Test-file block comment is multi-paragraph

packages/analytics/src/providers/__tests__/session-replay.test.ts:1

Collapse to single-line comment. The silent-failure-mode rationale is valuable but the format violates CLAUDE.md.

low

sessionReplayInitOptions describe block has multi-line comment

packages/analytics/src/providers/__tests__/session-replay.test.ts

The negation-trap explanation should be a single comment on the assertion line, not a block above the test.

info

Extraction to session-replay.ts is architecturally sound FCIS move

packages/analytics/src/providers/session-replay.ts

tests5

medium

No test pins the env var name read by SESSION_REPLAY_ENABLED_FOR_ENV

packages/analytics/src/providers/__tests__/session-replay.test.ts

A misspelled env var name silently disables replay in prod. Add test with vi.stubEnv + vi.resetModules() to pin NEXT_PUBLIC_POSTHOG_SESSION_REPLAY as the correct name.

medium

No regression test asserting maskTextSelector is absent

packages/analytics/src/providers/__tests__/session-replay.test.ts

The commit removes dead maskTextSelector: '.sensitive'. Add: expect(sessionReplayInitOptions(true,true)).not.toHaveProperty('session_recording.maskTextSelector')

low

Redundant assertions: it.each + named test re-cover same 2 cases

packages/analytics/src/providers/__tests__/session-replay.test.ts:28

low

No component tests verify SecretRevealCard/EnvPanel apply ph-no-capture

packages/analytics/src/providers/__tests__/session-replay.test.ts

low

PH_NO_CAPTURE_CLASS test is circular — consumers use raw string

packages/analytics/src/providers/__tests__/session-replay.test.ts:62

improvement5

medium

PH_NO_CAPTURE_CLASS not re-exported from package index — consumers use raw string

packages/analytics/src/index.ts

Both SecretRevealCard.tsx and EnvPanel.tsx hardcode 'ph-no-capture'. Export PH_NO_CAPTURE_CLASS from the package index so consumers can import the typed constant.

medium

sessionReplayInitOptions double-evaluates the gate

packages/analytics/src/providers/PostHogProvider.tsx:82

PostHogProvider calls isSessionReplayEnabled() on line 82, then passes the same two args to sessionReplayInitOptions() on line 95 which internally re-runs the same gate. Prefer sessionReplayInitOptions(enabled: boolean).

low

ph-no-capture gap: CredentialsForm PasswordInput visibility-toggle path

apps/platform/src/app/[locale]/(dashboard)/credentials/cfe/_components/CredentialsForm.tsx

When visibility toggle switches to type='text', maskAllInputs stops masking. If no ph-no-capture wrapper, session replay captures the CFE password.

low

SESSION_REPLAY_ENABLED_FOR_ENV baked at module load — limits future env-branch testing

packages/analytics/src/providers/session-replay.ts:34

info

isSessionReplayEnabled is a trivial &&-alias — fine as named test target

packages/analytics/src/providers/session-replay.ts:43

History · 3 commits

  1. ab8cd04safeincremental0H · 0M · 1L2026-07-31 00:23
  2. 8d1b744needs attentionincremental0H · 5M · 10L2026-07-30 21:44current
  3. 069e020needs attentionfull3H · 6M · 7L2026-07-30 21:06