fix(replay): gate event-trigger starts behind the replay checks - #758
Draft
Conversation
A matching event trigger called start() directly, so it skipped the master switch, the project flag and the sampling decision that every other start path applies. An app that gates replay behind its own feature flag kept recording the users the flag excludes. start() then set startedWithAutomaticDisabled, so the recording counted as manually started and survived every later check. onEvent now reuses isRecordingPermittedForCurrentSession() before it starts, after it records the trigger activation, so the trigger only lifts the event-trigger gate. start() remembers an explicit start asked for while automatic replay is off. The trigger gate defers that start, so without this the manual intent is lost and the deferred recording is refused once the trigger matches. Generated-By: PostHog Desktop Task-Id: d4a23d7a-bccc-4e65-9061-9223a7937811
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
💡 Motivation and Context
start()directly. That skipped every gate the other start paths apply, and never readconfig.sessionReplayat all.start()setsstartedWithAutomaticDisabled, so the recording counted as manually started and survived rotation and every later check until an explicitstopSessionReplay().startSessionReplayonSessionIdChangedconfig.sessionReplaymaster switchisSessionReplayFlagActive)flowchart LR E["captured event<br/>matches a trigger"] --> A["record the activation"] A --> G{"master switch,<br/>project flag,<br/>sampling"} G -- "all allow" --> S["start recording"] G -- "any rejects" --> N["do not start<br/>(new)"]Stacked on #757, which added the
reevaluateRecordingState()/isRecordingPermittedForCurrentSession()policy this reuses, and touches the same files.Changes
isRecordingPermittedForCurrentSession()before it starts, so a matched trigger only lifts the event-trigger gate and the rest of the policy still decides.start()now remembers an explicit start asked for while automatic replay is off. The trigger gate defers such a start, so without this the manual intent is lost and the deferred recording would be refused as an automatic one once the trigger matched.PostHogConfig.sessionReplaycorrected: an event trigger is not a manual start.Note
Behavior change for one configuration: a project with event triggers whose app never sets
sessionReplay = trueand never callsstartSessionReplay()no longer records. That is the reported symptom.💚 How did you test it?
Ran locally on JDK 17 with the Android SDK:
make test(all modules),make checkFormat, andapiCheckall pass. No public API change, so the.apidumps are unchanged.Three new tests in
PostHogReplayIntegrationTest, next to the existing trigger tests and reusing their fixture:sessionReplay = truethen does record, which proves the activation was kept.start()asked for while the master switch is off still starts once the trigger matches.Non-vacuity check
Each test was confirmed to fail with its half of the fix removed: the first two fail without the gate, the third fails without the manual-intent line.
One existing test (
trigger started replay does not resume on a session the trigger has not activated) setsessionReplay = falseand asserted the trigger started recording, which is the defect. It now setssessionReplay = trueand asserts the same outcome for its own subject, the trigger gate blocking a resume after rotation.No emulator run: the symptom is behavioral, and the tests drive the real integration through the trigger, rotation, remote config, and master switch paths.
📝 Checklist
If releasing new changes
pnpm changesetto generate a changeset file🤖 Agent context
Autonomy: Fully autonomous
onSessionIdChangedgate by gate. The report suggested that shape.isRecordingPermittedForCurrentSession()already encodes the same decision and fix(replay): honor PostHogConfig.sessionReplay writes after setup #757 made it the single source, so duplicating the three checks inline would have been a second copy to keep in sync.onSessionIdChangedand the resume path both post. Doing that here would delay a trigger start and widen the diff past the missing gate, and the gate check plusstart()run on one thread as it is.startSessionReplay()whilesessionReplayis false, on a project with triggers. The trigger gate defers that start and the intent was never recorded, so the gate would refuse it later. Hence the second change, with its own test.Created with PostHog Desktop from this inbox report.