Skip to content

feat(flags): deliver flag calls to destinations on flag_evaluations_mode 2 - #113654

Merged
trunk-io[bot] merged 2 commits into
masterfrom
haacked/flag-calls-destinations-mode-2
Oct 9, 2026
Merged

trunk-io[bot] merged 2 commits into
masterfrom
haacked/flag-calls-destinations-mode-2

Conversation

@haacked

@haacked haacked commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Problem

  • Organizations on flag evaluations mode 2 stop receiving $feature_flag_called in realtime destinations, event-triggered workflows and legacy plugins.
  • Mode 2 stops ingestion writing the event to clickhouse_events_json, and every CDP consumer reads that topic.
  • feat(flags): hide $feature_flag_called in pickers past events mode #111148 hides the event in destination and workflow pickers on modes 1 and 2 for this reason.
  • The clickhouse_flag_evaluations row is a poor substitute input, because it carries no person properties.

Part of the feasibility review for #88126.

Changes

  • Ingestion sends a mode-2 flag call to a new realtime_only_events_json topic instead of dropping it.
  • ClickHouse does not read that topic, so the call still stays out of the events table.
  • The topic carries the same row clickhouse_events_json would have carried, person properties included.
  • The fork step makes one decision per event, so a call lands on exactly one topic and a mode change cannot double-send.
  • Every fallback keeps the call on events: fork off, team excluded, invalid flag key, past retention, fork error, or INGESTION_FLAG_EVALUATIONS_ONLY_DISABLED.
  • CdpEventsConsumer reads its topic and group from CDP_EVENTS_CONSUMER_TOPIC and CDP_EVENTS_CONSUMER_GROUP_ID, so a second deployment can read the new topic.
  • The hogflow subscription matcher reads the topic as a fifth stream when CDP_HOGFLOW_SUBSCRIPTION_MATCHER_REALTIME_ONLY_EVENTS_TOPIC is set.
  • Event links to a flag call name the event, in destination payloads and in workflow logs. Other links stay unchanged.
  • The name makes the events page read flag_evaluations, because a mode-2 call has no events row.
  • On modes 1 and 2, a named link misses the few calls the fork skips, such as a call with no flag key. Those exist only in events, and the activity page filtered to flag calls misses them the same way.
  • The destination Invocations tab link names no event, because invocation results store no event name. fix(flags): open flag calls from event links that name no event #114210 makes the events page find a mode-2 flag call from a link like that.
  • Legacy plugins still miss flag calls on mode 2, as they do today. A second cdp-legacy-on-event deployment that reads the new topic with its own consumer group would restore them without a code change. This PR leaves it out.
  • A second Kafka consumer inside one CdpEventsConsumer was rejected. Its dead-letter service flushes one shared failure buffer per batch, so concurrent streams could commit offsets before failure records exist.
  • Mechanical: topic constants, output registration, type unions, and test helpers.

Before, on mode 2:

flowchart LR
    flagCall([Mode 2 flag call]) --> fork[Fork step]
    fork --> fe[(clickhouse_flag_evaluations)]
    fe --> table[flag_evaluations table]
    fork -. removed .-> none[Not produced]
    ej[(clickhouse_events_json)] --> cdp[CDP consumers]
    classDef phBlue fill:#1d4aff,stroke:#1d4aff,color:#fff;
    classDef phRed fill:#f54e00,stroke:#f54e00,color:#fff;
    classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000;
    classDef phGray fill:#e5e7eb,stroke:#c7ccd1,color:#000;
    class flagCall phYellow;
    class fork phBlue;
    class fe,ej,table,none phGray;
    class cdp phRed;
Loading

After, on mode 2 with the topic set:

flowchart LR
    flagCall([Mode 2 flag call]) --> fork[Fork step]
    fork --> fe[(clickhouse_flag_evaluations)]
    fe --> table[flag_evaluations table]
    fork --> emit[Emit event]
    emit --> ro[(realtime_only_events_json)]
    ro --> cdp[CDP consumers]
    classDef phBlue fill:#1d4aff,stroke:#1d4aff,color:#fff;
    classDef phRed fill:#f54e00,stroke:#f54e00,color:#fff;
    classDef phYellow fill:#f9bd2b,stroke:#f9bd2b,color:#000;
    classDef phGray fill:#e5e7eb,stroke:#c7ccd1,color:#000;
    class flagCall phYellow;
    class fork,emit phBlue;
    class fe,ro,table phGray;
    class cdp phRed;
Loading

Note

Nothing changes in production when this PR deploys. The new topic keys default to '', and the CDP keys default to today's topic and group. Rollout order:

  1. Create realtime_only_events_json in each region, with the same retention and max.message.bytes as clickhouse_events_json.
  2. Deploy a second cdp-processed-events consumer with the topic and group overrides, set the matcher topic, and add lag and absent() alerts.
  3. Set INGESTION_OUTPUT_REALTIME_ONLY_EVENTS_TOPIC on every lane that sets INGESTION_OUTPUT_FLAG_EVALUATIONS_TOPIC.

Warning

  • A failed produce to the new topic fails the batch, like a failed events produce.
  • Clearing INGESTION_OUTPUT_REALTIME_ONLY_EVENTS_TOPIC rolls back to dropping the calls.
  • The emitted_events* TopHog sums and eventProcessedAndIngestedCounter now count routed calls. Use ingestion_outputs_*{output} to tell the two outputs apart.

A follow-up PR lifts the picker hide in destination filters, mappings and workflow event filters, after step 3 is live in both regions.

How did you test this code?

Test rationale:

  • fork-flag-evaluations-step.test.ts: the mode-2 case runs with routing on and off. It fails if a routed call is dropped or the $experiment_exposure copy is retargeted.
  • The fallback rows in the same file run with routing on and assert each output, so a fallback call that moves off events fails.
  • A routed row in the oversize it.each catches a second ingestion warning for one event.
  • flag-evaluations-service.test.ts: routing stays off for an empty topic, which would fail every produce at runtime.
  • cdp-hogflow-subscription-matcher.consumer.test.ts: the wiring test fails if the matcher creates the fifth consumer on an empty topic, which fails start().
  • flag-evaluations-e2e.test.ts: the mode-2 case asserts the realtime copy carries person_properties from $set, and events holds only $experiment_exposure. Only a Kafka round trip catches a topic-key typo or an unregistered output.
  • utils.test.ts: fails if a flag-call link loses the event name, or if another event's link gains it.
  • log-utils.test.tsx: the same check for the workflow log link.

Run locally: those six files and cdp-events-consumer.test.ts.

Run by hand: the 11 local scenarios in the manual plan below, which all passed.
No mode-2 call reached clickhouse_events_json, so every mode-2 delivery came through the new consumers.

Not run: the four Dev scenarios, which need the charts changes.

Manual test plan

The unit and e2e tests cover the routing decision, the produced payload, the oversize warning, and the matcher's consumer wiring. This plan covers what crosses the topic boundary: CDP delivery, workflow wakes, mode changes, rollback, and the dev rollout.

Local setup

  • Setup: Confirm .env.development keeps INGESTION_FLAG_EVALUATIONS_MODE=dual_write, INGESTION_FLAG_EVALUATIONS_TEAMS=* and INGESTION_OUTPUT_FLAG_EVALUATIONS_TOPIC=clickhouse_flag_evaluations. Set INGESTION_OUTPUT_REALTIME_ONLY_EVENTS_TOPIC=realtime_only_events_json and CDP_HOGFLOW_SUBSCRIPTION_MATCHER_REALTIME_ONLY_EVENTS_TOPIC=realtime_only_events_json, then start the stack. Start a second plugin server with PLUGIN_SERVER_MODE=cdp-processed-events, CDP_EVENTS_CONSUMER_TOPIC=realtime_only_events_json, CDP_EVENTS_CONSUMER_GROUP_ID=cdp-realtime-only-events-consumer and HTTP_SERVER_PORT=6760. Put a test organization on mode 2 with the flags staff tool. Confirm both plugin servers return 200 on /_health.

Destinations

  • Destination fires on mode 2: Create a webhook destination that matches $feature_flag_called with the person property filter plan = pro. Send a $feature_flag_called with $feature_flag, $feature_flag_response and $set: {plan: 'pro'}. Confirm the destination's logs show one delivery. Confirm ClickHouse events has no row for that uuid, and flag_evaluations has one.
  • Person filter excludes on mode 2: Send a $feature_flag_called from a person without plan = pro. Confirm the destination does NOT fire.
  • Exposure copy delivers once: Add the team to EXPERIMENT_EXPOSURE_DUPLICATION_TEAMS and restart ingestion. Create a second destination that matches $experiment_exposure. Send a flag call with a variant string response. Confirm each destination fires exactly once.

Workflows

  • Event-triggered workflow on mode 2: Create a workflow triggered by $feature_flag_called with one webhook step. Send a flag call. Confirm one workflow run appears and its step fires once.
  • Wait-until wakes from the new stream: Create a workflow triggered by $pageview with a wait-until step on $feature_flag_called. Send a $pageview and confirm the job parks in cyclotron_jobs. Send a flag call for the same person. Confirm the job wakes and continues.

No double send

  • Mode 1 single delivery: Move the organization to mode 1. Send one flag call. Confirm the destination fires exactly once. Confirm realtime_only_events_json receives no message (kcat -C -t realtime_only_events_json -o end).
  • Mode 2 to mode 1 switch: On mode 2, send a flag call and confirm one delivery. Move the organization to mode 1, then wait past the team cache refresh (about 2.5 minutes). Send another flag call. Confirm each call fires the destination exactly once, and only the second call lands in events.
  • Kill switch: Set INGESTION_FLAG_EVALUATIONS_ONLY_DISABLED=true and restart ingestion. Send a flag call on mode 2. Confirm the destination fires once, the call lands in events, and realtime_only_events_json receives nothing.

Rollback and failure

  • Rollback: Clear INGESTION_OUTPUT_REALTIME_ONLY_EVENTS_TOPIC and restart ingestion. Send a flag call on mode 2. Confirm the destination does NOT fire, events has no row, and flag_evaluations has one.
  • Missing topic fails startup: Set INGESTION_OUTPUT_REALTIME_ONLY_EVENTS_TOPIC to a topic that does not exist. Restart ingestion. Confirm startup fails with a topic check error that names the topic. (Local Redpanda creates the topic during the failed check, so only the first startup fails locally.)

Dev, after the charts changes

  • Produces flow: Put a dev organization on mode 2 and send flag calls. Confirm ingestion_outputs_latency_seconds_count{output="realtime_only_events"} rises, and ingestion_outputs_errors_total{output="realtime_only_events"} stays at zero.
  • Consumers keep up: Confirm kminion_kafka_consumer_group_topic_partition_lag{topic_name="realtime_only_events_json"} stays near zero for cdp-realtime-only-events-consumer and cdp-hogflow-subscription-matcher-realtime-only-events-consumer.
  • Alerts stay quiet: Confirm the new absent() alerts and FlagEvaluationsForkStalled do NOT fire. Confirm ingestion_flag_evaluations_events_total{outcome="flag_evaluations_only"} keeps counting.
  • Other modes produce nothing: With no dev organization on mode 2, confirm ingestion_outputs_batch_size_count{output="realtime_only_events"} stays flat.

The test-new-events-schema label is not needed. The diff changes Node ingestion routing only, and no Python test reads event properties differently.

👉 Stay up-to-date with PostHog coding conventions for a smoother review.

Release status

  • No feature flag controls this change

Docs update

None. No doc under docs/ covers flag evaluations modes.

🤖 Agent context

Autonomy: Human-driven (agent-assisted)

Agent: Claude Code, Opus 5.5 (claude-opus-5-5)

  • I started by checking the candidate design against the code. That check moved the CDP side from one consumer reading two topics to a second deployment.
  • Skills invoked: /writing-tests, /writing-code-comments, /simplify, comment-cleanup, /reviewing-with-coderabbit, /writing-pr-descriptions.
  • CodeRabbit CLI, run with --deep, reported one finding. The matcher's _parseKafkaBatch swallows dependency errors, so a failed team lookup skips a call. I rejected it for this PR: the existing clickhouse_events_json stream shares that parser, and the new stream keeps parity with it. Changing retry behavior for both streams belongs in a separate PR.
  • Duplicate check: an open-PR search for this change found nothing.
  • Public artifact: everything here comes from the repository. No customer or session material is included.

https://claude.ai/code/session_01EvZDsoSPrQzLQit6kYQydV

…ode 2

On FLAG_EVALUATIONS_ONLY, the flag-evaluations fork sends each forked
$feature_flag_called to a new realtime_only_events output when
INGESTION_OUTPUT_REALTIME_ONLY_EVENTS_TOPIC is set. ClickHouse does not
read that topic, so the call stays out of the events table while the CDP
consumers can still deliver it. With the topic unset, the fork removes the
call from emission.

CdpEventsConsumer takes its topic and group from CDP_EVENTS_CONSUMER_TOPIC
and CDP_EVENTS_CONSUMER_GROUP_ID, so a second deployment can read the new
topic. The hogflow subscription matcher reads it when
CDP_HOGFLOW_SUBSCRIPTION_MATCHER_REALTIME_ONLY_EVENTS_TOPIC is set.

Claude-Session: https://claude.ai/code/session_01EvZDsoSPrQzLQit6kYQydV
@haacked haacked self-assigned this Oct 7, 2026
@trunk-io

trunk-io Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

😎 Merged successfully - details.

@haacked haacked added the reviewhog ($$$) Reviews pull requests before humans do label Oct 7, 2026
@haacked
haacked requested a balanced review from Copilot October 7, 2026 22:15
@github-actions

github-actions Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

🤖 CI report

🚨 Trunk lane — universal lane

This PR is assigned to the universal lane. It cannot merge in parallel with other PRs, so it can take longer to merge. Ask dev-ex if you think this is wrong.

⚠️ Complexity (TypeScript) — 1 function above the limit (max 13)

Cyclomatic complexity above the limit in changed typescript files (10 for production files, 15 for test files). Warn only: worth simplifying when you next touch these functions.

Function Location Complexity Limit
renderWorkflowLogMessage products/workflows/frontend/Workflows/logs/log-utils.tsx:23 13 10
✅ Duplication (Python) — clean

New Python code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

✅ Duplication (TypeScript) — clean

New TypeScript code duplication introduced by this branch. Fails at 70+ tokens in app code, or 150+ tokens when both copies live in test files. Advisory while the gate proves itself: extract a shared helper instead of copying.

🚨 Comment density — 8% of added code lines are comments (21 of 271)

This section warns when comments are more than 3% of the code lines a PR adds, and alerts above 6%. Before agent-assisted PRs, the typical share was about 2%. Only full-line comments count. Docstrings, generated files, snapshots, migrations, and workflow files are left out.

Comments that restate the code, record how the change came about, or narrate the next line add noise for the next reader. Keep the comments that explain a reason the code cannot show, and remove the rest. See .agents/skills/writing-code-comments/SKILL.md for the house rules.

Files with the most added comment lines:

File Comment lines Added lines
nodejs/src/ingestion/config.ts 6 10
nodejs/src/ingestion/common/steps/event-processing/fork-flag-evaluations-step.ts 4 23
nodejs/src/cdp/consumers/cdp-hogflow-subscription-matcher.consumer.ts 3 27
products/workflows/frontend/Workflows/logs/log-utils.tsx 3 5
nodejs/src/cdp/utils.ts 2 7
nodejs/src/ingestion/common/steps/event-processing/fork-flag-evaluations-step.test.ts 2 66
nodejs/src/ingestion/pipelines/analytics/event-subpipeline.ts 1 9

This check does not block merging. It updates on every push and clears when the share drops.

⚠️ Bundle size — 🔺 +247.3 KiB (+0.3%)

Uncompressed size of every built .js bundle, compared against the base branch.

Total: 76.75 MiB · 🔺 +247.3 KiB (+0.3%)

File Size Δ vs base
render-query/src/render-query/render-query.js 25.67 MiB 🔺 +144.7 KiB (+0.6%)
exporter/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.62_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/react-shadow.esm-DFvHTPVL.js 76.7 KiB 🔺 +76.7 KiB (new)
posthog-app/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.62_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/react-shadow.esm-DFvHTPVL.js 76.7 KiB 🔺 +76.7 KiB (new)
exporter/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.60_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/react-shadow.esm-B4-N-ucD.js removed 🟢 -76.7 KiB (-100.0%)
posthog-app/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.60_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/react-shadow.esm-B4-N-ucD.js removed 🟢 -76.7 KiB (-100.0%)
posthog-app/_parent/products/workflows/frontend/WorkflowsScene.js 48.5 KiB 🔺 +22.3 KiB (+85.2%)
posthog-app/_parent/products/replay_vision/frontend/replay_scanners/ReplayScannersScene.js 86.2 KiB 🟢 -17.5 KiB (-16.9%)
posthog-app/_parent/products/ai_gateway/frontend/AIGatewayScene.js removed 🟢 -16.0 KiB (-100.0%)
posthog-app/_parent/products/autoresearch/frontend/AutoresearchNewScene.js 28.7 KiB 🔺 +11.9 KiB (+70.2%)
posthog-app/src/scenes/data-pipelines/batch-exports/BatchExportScene.js 79.4 KiB 🔺 +11.7 KiB (+17.3%)
posthog-app/src/scenes/experiments/Experiment.js 308.3 KiB 🔺 +10.8 KiB (+3.6%)
posthog-app/_parent/products/autoresearch/frontend/AutoresearchPipelineScene.js 65.7 KiB 🔺 +10.8 KiB (+19.6%)
toolbar/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.62_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/chunk-react-shadow.esm-DFvHTPVL.js 7.8 KiB 🔺 +7.8 KiB (new)
toolbar/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.60_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/chunk-react-shadow.esm-B4-N-ucD.js removed 🟢 -7.8 KiB (-100.0%)
posthog-app/src/layout/today/TodaySpaceHoverCard.js removed 🟢 -6.9 KiB (-100.0%)
posthog-app/_parent/products/workflows/frontend/Workflows/WorkflowScene.js 75.9 KiB 🔺 +6.8 KiB (+9.8%)
posthog-app/_parent/products/metrics/frontend/MetricsScene.js 25.0 KiB 🟢 -6.5 KiB (-20.7%)
posthog-app/_parent/products/business_intelligence/frontend/BusinessIntelligenceScene.js 104.5 KiB 🔺 +6.3 KiB (+6.5%)
exporter/src/queries/schema.js 1.26 MiB 🔺 +5.4 KiB (+0.4%)
posthog-app/src/queries/schema.js 1.26 MiB 🔺 +5.4 KiB (+0.4%)
posthog-app/_parent/products/error_tracking/frontend/scenes/ErrorTrackingIssueScene/ErrorTrackingIssueScene.js 102.0 KiB 🔺 +4.5 KiB (+4.6%)
posthog-app/_parent/products/customer_analytics/frontend/scenes/CustomerAnalyticsAccountScene/CustomerAnalyticsAccountScene.js 62.7 KiB 🔺 +3.6 KiB (+6.1%)
posthog-app/src/layout/today/TodaySpacesPane.js 34.1 KiB 🟢 -3.1 KiB (-8.3%)
posthog-app/_parent/products/canvas/frontend/scene/CanvasScene.js 70.8 KiB 🔺 +2.9 KiB (+4.3%)
posthog-app/src/scenes/dashboard/dashboards/Dashboards.js 35.2 KiB 🔺 +2.7 KiB (+8.4%)
exporter/src/exporter/scenes/ExporterNotebookScene.js 3.74 MiB 🔺 +2.6 KiB (+0.1%)
posthog-app/src/scenes/project-homepage/today/TodayHome.js 13.1 KiB 🔺 +2.6 KiB (+24.4%)
posthog-app/src/layout/today/TodayProductsSidebar.js 6.3 KiB 🔺 +2.4 KiB (+62.2%)
posthog-app/src/scenes/feature-flags/FeatureFlag.js 132.9 KiB 🔺 +2.4 KiB (+1.9%)
posthog-app/src/scenes/marketing-analytics/MarketingAnalyticsScene.js 158.4 KiB 🔺 +2.1 KiB (+1.4%)
posthog-app/_parent/products/tasks/frontend/spaces/SpacesScene.js 11.8 KiB 🔺 +1.5 KiB (+14.4%)
exporter/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.62_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/dist.js 1.2 KiB 🔺 +1.2 KiB (new)
posthog-app/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.62_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/dist.js 1.2 KiB 🔺 +1.2 KiB (new)
toolbar/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.62_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/chunk-dist.js 1.2 KiB 🔺 +1.2 KiB (new)
exporter/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.60_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/dist.js removed 🟢 -1.2 KiB (-100.0%)
posthog-app/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.60_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/dist.js removed 🟢 -1.2 KiB (-100.0%)
toolbar/_parent/node_modules/.pnpm/@posthog+hedgehog-mode@0.0.60_prop-types@15.8.1_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/hedgehog-mode/dist/chunk-dist.js removed 🟢 -1.2 KiB (-100.0%)
posthog-app/_parent/products/business_intelligence/frontend/BIWorksheetsScene.js 8.8 KiB 🔺 +1.1 KiB (+14.8%)

Posted automatically by build-bundle-size-report · uncompressed bytes from dist-report

✅ Eager graph — within budget

How much code each root ships on the eager path — downloaded and parsed before the surface is interactive. Measured from the esbuild output chunks (post-tree-shake, static imports only); lazy import() / React.lazy chunks are not counted.

Root Eager (shipped) Δ vs base Budget
entry (logged-out pages, app bootstrap)
src/index.tsx
1.65 MiB · 23 files 🔺 +4.4 KiB (+0.3%) █████████░ 89.8% of 1.84 MiB
logged-out boot: index + App + bootApp (preloaded by every page, including /login)
src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
3.80 MiB · 675 files 🔺 +10.6 KiB (+0.3%) █████████░ 94.3% of 4.03 MiB
authenticated shell (every logged-in page)
src/scenes/AuthenticatedShell.tsx
7.74 MiB · 2,456 files 🔺 +30.7 KiB (+0.4%) █████████░ 92.8% of 8.34 MiB
dashboard scene
src/scenes/dashboard/Dashboard.tsx
9.97 MiB · 3,538 files 🔺 +47.2 KiB (+0.5%) █████████░ 91.3% of 10.92 MiB
today home path
src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
7.76 MiB · 2,466 files 🔺 +27.5 KiB (+0.3%) █████████░ 90.4% of 8.58 MiB
events scene
src/scenes/activity/explore/EventsScene.tsx
9.59 MiB · 3,389 files 🔺 +46.4 KiB (+0.5%) █████████░ 91.3% of 10.51 MiB
replay detail scene
src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
12.29 MiB · 4,185 files 🔺 +39.9 KiB (+0.3%) ████████░░ 78.2% of 15.72 MiB

🟢 node_modules/monaco-editor/ stays out of src/index.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/index.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/index.tsx
🟢 node_modules/monaco-editor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/layout/navigation-3000/navigationLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/scenes/dashboard/dashboardLogic.tsx stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/lemon-ui/LemonMarkdown/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/RichContentEditor/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/lib/components/CodeSnippet/ stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 src/taxonomy/core-filter-definitions-by-group.json stays out of src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
🟢 node_modules/monaco-editor/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/lib/components/ActivityLog/describers stays out of src/scenes/AuthenticatedShell.tsx
🟢 products/dashboards/frontend/widgets/previews/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/player/sessionRecordingPlayerLogic.ts stays out of src/scenes/AuthenticatedShell.tsx
🟢 zod/v4/locales/de.js stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/svg/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 node_modules/@posthog/brand/dist/generated/hoggies/components/ stays out of src/scenes/AuthenticatedShell.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/dashboard/Dashboard.tsx
🟢 src/scenes/project-homepage/ai-first/AiFirstHomepage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/project-homepage/today/TodayReportPage.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/queries/Query/Query.tsx stays out of src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
🟢 src/scenes/session-recordings/playlist/SessionRecordingsPlaylist.tsx stays out of src/scenes/activity/explore/EventsScene.tsx
🟢 src/scenes/web-analytics/tiles/WebAnalyticsTile.tsx stays out of src/scenes/activity/explore/EventsScene.tsx

Largest files eagerly shipped from src/index.tsx
Size File
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
24.6 KiB ../node_modules/.pnpm/buffer@6.0.3/node_modules/buffer/index.js
6.3 KiB ../node_modules/.pnpm/react@18.3.1/node_modules/react/cjs/react.production.min.js
4.5 KiB ../node_modules/.pnpm/@jspm+core@2.1.0/node_modules/@jspm/core/nodelibs/browser/process.js
3.9 KiB ../node_modules/.pnpm/scheduler@0.23.2/node_modules/scheduler/cjs/scheduler.production.min.js
1.4 KiB ../node_modules/.pnpm/base64-js@1.5.1/node_modules/base64-js/index.js
1.3 KiB src/index.tsx
1.3 KiB src/RootErrorBoundary.tsx
912 B ../node_modules/.pnpm/ieee754@1.2.1/node_modules/ieee754/index.js
839 B src/scenes/ChunkLoadErrorBoundary.tsx
Largest files eagerly shipped from src/index.tsx + src/scenes/App.tsx + src/scenes/bootApp.ts
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
220.8 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
99.8 KiB src/lib/api.ts
92.8 KiB src/products.tsx
69.0 KiB src/lib/lemon-ui/icons/icons.tsx
40.7 KiB src/lib/utils/eventUsageLogic.ts
38.7 KiB ../node_modules/.pnpm/@dnd-kit+core@6.0.8_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@dnd-kit/core/dist/core.esm.js
33.9 KiB ../node_modules/.pnpm/kea@4.0.0-pre.6_patch_hash=139b8d1f1304f9d9da452a9a1244c94ea679dbcb85687d8999563146879fb6f5_react@18.3.1/node_modules/kea/lib/index.cjs.js
29.0 KiB ../node_modules/.pnpm/zod@4.3.6/node_modules/zod/v4/core/schemas.js
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
220.8 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.8 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.8 KiB src/products.tsx
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
Largest files eagerly shipped from src/scenes/dashboard/Dashboard.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
220.8 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
181.9 KiB src/queries/validators.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.8 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.8 KiB src/products.tsx
Largest files eagerly shipped from src/scenes/AuthenticatedShell.tsx + src/scenes/project-homepage/ProjectHomepage.tsx + src/scenes/project-homepage/today/TodayHome.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
220.8 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.8 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.8 KiB src/products.tsx
90.6 KiB ../node_modules/.pnpm/@tiptap+core@3.20.6_@tiptap+pm@3.20.6/node_modules/@tiptap/core/dist/index.js
Largest files eagerly shipped from src/scenes/activity/explore/EventsScene.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
220.8 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
181.9 KiB src/queries/validators.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.8 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js
92.8 KiB src/products.tsx
Largest files eagerly shipped from src/scenes/session-recordings/detail/SessionRecordingDetail.tsx
Size File
316.7 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/module.mjs
316.0 KiB ../node_modules/.pnpm/posthog-js@1.438.1_@types+react@18.3.27_react@18.3.1/node_modules/posthog-js/dist/rrweb.js
281.0 KiB src/taxonomy/core-filter-definitions-by-group.json
220.8 KiB ../node_modules/.pnpm/@posthog+icons@0.38.0_react-dom@18.3.1_react@18.3.1__react@18.3.1/node_modules/@posthog/icons/dist/posthog-icons.es.js
181.9 KiB src/queries/validators.js
153.7 KiB ../node_modules/.pnpm/re2js@0.4.1/node_modules/re2js/build/index.esm.js
126.8 KiB ../node_modules/.pnpm/react-dom@18.3.1_react@18.3.1/node_modules/react-dom/cjs/react-dom.production.min.js
112.3 KiB ../packages/quill/packages/quill/dist/index.js
99.8 KiB src/lib/api.ts
93.3 KiB ../node_modules/.pnpm/prosemirror-view@1.40.1/node_modules/prosemirror-view/dist/index.js

Posted automatically by check-eager-graph · sizes are eager output bytes (shipped, post-tree-shake) from the esbuild metafile · part of #32479

✅ Toolbar bundle — eager 2.24 MiB within budget

What the toolbar ships to customer pages, measured from the esbuild output (minified, post-tree-shake). The eager set is the entry plus everything statically imported from it — fetched before any feature runs; deferred chunks load lazily. The eager guardrail is 5.72 MiB. Each output file must also stay below 10 MB, where CloudFront stops compressing it. The module boundary is enforced separately by check-toolbar-graph.

Metric Size Δ vs base Budget
Eager (shipped)
entry + static imports
2.24 MiB · 19 files 🔺 +3.5 KiB (+0.2%) ████░░░░░░ 39.1% of 5.72 MiB
Deferred (lazy) 2.18 MiB · 44 files 🔺 +73.2 KiB (+3.4%) n/a — loads on demand
Loader dist/toolbar.js 1.2 KiB no change █░░░░░░░░░ 6.0% of 19.5 KiB
Largest eagerly-shipped chunks
Size File
861.3 KiB dist/toolbar/toolbar-app-NVPQAEP5.css
669.8 KiB dist/toolbar/chunk-chunk-G4SZFXYJ.js
259.4 KiB dist/toolbar/chunk-chunk-YKNMISGG.js
138.2 KiB dist/toolbar/chunk-chunk-UC3W3UE3.js
131.8 KiB dist/toolbar/chunk-chunk-FDH2IBXT.js
75.2 KiB dist/toolbar/toolbar-app-G6JVKXLU.js
69.0 KiB dist/toolbar/chunk-chunk-TSAL54PB.js
35.6 KiB dist/toolbar/chunk-chunk-ECCIHXAA.js
21.7 KiB dist/toolbar/chunk-chunk-T3C2GF5C.js
6.8 KiB dist/toolbar/chunk-chunk-DV7IWQNF.js

Posted automatically by check-toolbar-size · sizes are toolbar output bytes (shipped, post-tree-shake) from the esbuild metafile

✅ Dist folder size — 🔺 +4.42 MiB (+0.4%)

Total size of the built frontend/dist folder (all assets), compared against the base branch.

Total: 1010.05 MiB · 🔺 +4.42 MiB (+0.4%)

⚠️ Playwright — 1 flaky

🎭 Playwright report · View test results →

⚠️ 1 flaky test:

  • Inline editing insight description via compact card popover (chromium)

These issues are not necessarily caused by your changes.
Annoyed by this section? Help fix flakies and failures and it will go green!

✅ Hogbox preview — ready, open the preview

▶ Open the preview

🔑 Login test@posthog.com / 12345678 (demo data)
🧩 Running this PR's backend and frontend, on the PostHog :master base
🔗 Link stable across rebuilds: a re-push swaps the box underneath, the URL stays
🔒 Access tailnet only (PostHog VPN)
🛠️ Admin inspect & debug state in hogland
💤 Idle sleeps after ~30 min idle (snapshot to S3, zero node cost) and wakes on your next visit in ~30s, behind a brief "waking up" screen

commit f4c00f6 · box box-746a2857ce88 · ready in 1180s (push → usable) · build log · rebuilds on every push, torn down on close

✅ Hobby preview — passed

Hobby deployment smoke test passed successfully.


Run 37836141626

@posthog

posthog Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

🦔 PostHog Review reviewed this pull request

Found 0 must fix, 1 should fix, 0 consider.

Published 1 finding (view the review).

Resolved comments: 2 left for you

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔵 Needs a closer look

Delivery through the new CDP topic remains unverified, and the documented rollout omits the separate legacy-plugin consumer.

1 open finding
What changed in this PR

Adds an opt-in path for mode-2 flag calls to reach realtime destinations and workflows without storing them in the events table.

Changes:

  • Routes eligible flag calls to a dedicated realtime-only Kafka topic.
  • Adds configurable CDP subscriptions while preserving current defaults.
  • Extends routing, fallback, and payload tests.
File Description
posthog/​kafka_client/​topics.py Defines the Python topic constant.
nodejs/​tests/​ingestion/​flag-evaluations-e2e.test.ts Checks routed payloads and person properties.
nodejs/​tests/​helpers/​kafka.ts Registers the test topic.
nodejs/​tests/​helpers/​ingestion-outputs.ts Adds the test output.
nodejs/​src/​ingestion/​pipelines/​analytics/​outputs/​registry.ts Registers realtime-only output configuration.
nodejs/​src/​ingestion/​pipelines/​analytics/​joined-ingestion-pipeline.ts Extends supported output types.
nodejs/​src/​ingestion/​pipelines/​analytics/​event-subpipeline.ts Allows realtime-only event routing.
nodejs/​src/​ingestion/​ingestion-consumer.ts Extends consumer configuration and output types.
nodejs/​src/​ingestion/​config.ts Adds disabled-by-default routing settings.
nodejs/​src/​ingestion/​common/​steps/​event-processing/​fork-flag-evaluations-step.ts Retargets eligible calls and avoids duplicate warnings.
nodejs/​src/​ingestion/​common/​steps/​event-processing/​fork-flag-evaluations-step.test.ts Tests routing, fallbacks, and oversized messages.
nodejs/​src/​ingestion/​common/​flag-evaluations/​flag-evaluations-service.ts Derives routing enablement from configuration.
nodejs/​src/​ingestion/​common/​flag-evaluations/​flag-evaluations-service.test.ts Tests topic-based enablement.
nodejs/​src/​common/​outputs/​index.ts Defines the realtime-only output type.
nodejs/​src/​common/​config/​kafka-topics.ts Defines the Node.js topic constant.
nodejs/​src/​cdp/​consumers/​cdp-hogflow-subscription-matcher.consumer.ts Adds an optional realtime-only stream.
nodejs/​src/​cdp/​consumers/​cdp-hogflow-subscription-matcher.consumer.test.ts Tests optional consumer creation.
nodejs/​src/​cdp/​consumers/​cdp-events.consumer.ts Reads topic/group defaults from configuration.
nodejs/​src/​cdp/​config.ts Adds CDP subscription settings.
docker/​kafka/​topics.txt Provisions the local topic.

🧠 Review effort: Balanced


Give feedback about Copilot approvals in this survey to enter a drawing for a $150 gift card.

Comment thread nodejs/src/cdp/consumers/cdp-events.consumer.ts
@coderabbitai

coderabbitai Bot commented Oct 7, 2026 •

Copy link
Copy Markdown
Contributor

Review in Change Stack →

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration
  • Configuration used: Repository: PostHog/posthog/.coderabbit.yaml
  • Review profile: QUIET
  • Plan: Enterprise
  • Run ID: ac7511e2-7f64-4df1-94fb-e70a53320b6e
📥 Commits

Reviewing files that changed from the base of the PR and between 7d18311 and f4c00f6.

📒 Files selected for processing (4)
  • nodejs/src/cdp/utils.test.ts
  • nodejs/src/cdp/utils.ts
  • products/workflows/frontend/Workflows/logs/log-utils.test.tsx
  • products/workflows/frontend/Workflows/logs/log-utils.tsx

Included review availability: This review used your included allowance. Your plan provides up to 12 included reviews per hour; 11 remain after this review.


📝 Walkthrough

Walkthrough

The ingestion pipeline adds a configurable realtime_only_events_json output. For teams that stop event writes, the flag-evaluation fork routes eligible feature-flag calls to this output when configured; otherwise, it removes them from emission. The CDP HogFlow subscription matcher can consume the topic when configured and processes its messages as events. CDP and workflow event links include the event name for $feature_flag_called links. Tests cover routing behavior, output configuration, event links, and CDP consumer wiring.

Priority: ➖ Normal

Merge Risk: ⚪ Minimal · up to f4c00

The new routing is opt-in, and the supplied coverage addresses its fallback and consumption paths. No concrete merge-blocking regression is established.

Architecture Summary

Architecture risk: 🔵 Low · up to f4c00

The change affects 4 systems.

Changed systems: nodejs, products, docker, posthog

Architecture concerns
No architecture-level concerns identified.

Review details

Systems and components

  • observed — nodejs (service) was modified; 20 changed files map to changed impact.
  • observed — products (ui) was modified; 2 changed files map to changed impact.
  • observed — docker (service) was modified; 1 changed file maps to changed impact.
  • observed — posthog (service) was modified; 1 changed file maps to changed impact.

Before / after behavior

  • observed — Modified behavior in docker/kafka/topics.txt: Added realtime_only_events_json to the pre-created Kafka topics list.
  • observed — Modified behavior in nodejs/src/cdp/config.ts: CdpConfig adds string settings for the CDP events consumer topic and group ID, plus the HogFlow subscription matcher realtime-only events topic.
  • observed — Modified behavior in nodejs/src/cdp/config.ts: getDefaultCdpConfig() sets the events consumer topic to KAFKA_EVENTS_JSON, its group ID to cdp-processed-events-consumer, and the realtime-only events topic to an empty string.
  • observed — Modified behavior in nodejs/src/cdp/consumers/cdp-events.consumer.ts: Removed the KAFKA_EVENTS_JSON import; the constructor no longer uses that constant as its default topic.
🚥 Pre-merge checks | ✅ 1
✅ Passed checks (1 passed)
Check name Status Explanation
Description check Passed The description is complete and follows the repository template. It explains the problem, user-visible changes, rollout and rollback behavior, testing rationale, unrun scenarios, release status, docs …
✨ Finishing Touches 💡 1
📝 Generate docstrings
  • Commit to this branch
  • Create a new PR
🧪 Generate unit tests (beta)
  • Commit to this branch
  • Create a new PR
🛠️ Fix failing CI checks 💡
  • Commit to this branch
  • Create a new PR
  • Autopilot · Keep fixing CodeRabbit findings and required CI, and resolving merge conflicts

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

@posthog

posthog Bot commented Oct 7, 2026

Copy link
Copy Markdown
Contributor

PostHog Review alpha 🦔 If you find any issues helpful - please reply "valid", "invalid", etc., for evaluation purposes 🙏

Comment thread nodejs/src/cdp/consumers/cdp-events.consumer.ts
@posthog posthog Bot removed the reviewhog ($$$) Reviews pull requests before humans do label Oct 7, 2026
@trunk-io

trunk-io Bot commented Oct 7, 2026 •

Copy link
Copy Markdown

Static Badge   Static Badge   Static Badge

Failed Test Failure Summary Logs
Scenes-Other/Startup program NeedsBillingDetails smoke-test The test timed out while waiting for loading indicators or spinners to disappear. Logs ↗︎
Scenes-App/Notebooks/Nodes/Customer Journey AllStepsCompleted smoke-test The test timed out while waiting for an element with the class '.react-flow__node' to become visible. Logs ↗︎
Scenes-App/Project Homepage ProjectHomepage smoke-test The test timed out while waiting for loading indicators or spinners to disappear. Logs ↗︎
Scenes-App/OAuth/Authorize DefaultScopes smoke-test The test timed out while waiting for loading indicators or spinners to disappear. Logs ↗︎

... and 2 more

View Full Report ↗︎ ⋅ Docs

The events page reads flag calls from flag_evaluations only when the link
names the event. On flag_evaluations_mode 2 a flag call has no events row,
so destination and workflow log links without the name open an empty page.
Links to other events stay unchanged.

Claude-Session: https://claude.ai/code/session_01EvZDsoSPrQzLQit6kYQydV
@haacked
haacked marked this pull request as ready for review October 8, 2026 21:50
@haacked
haacked requested a review from a team as a code owner October 8, 2026 21:50
@parameterai

parameterai Bot commented Oct 8, 2026 •

Copy link
Copy Markdown

Risk: No findings

This PR routes mode-2 $feature_flag_called events to a new realtime_only_events_json Kafka topic so CDP destinations and workflows keep receiving them, and adds the event name to links pointing at flag calls. I traced every new surface — the fork-step retargeting, the two new Kafka consumers, the event-name-bearing URLs in destination payloads and workflow log links, and the config defaults — and found no vulnerability: the only user-influenced values reaching URLs are exact-match literals or passed through encodeURIComponent, and all consumer defaults preserve today's behavior.

Sentinel reviewed f4c00f6 · Review settings

@stamphog stamphog 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.

Not approved — this change needs a human reviewer.

Re-adding the stamphog label gives the same result unless the changed files change.

stamphog can't approve this pull request, and the refusal is final. Two gates failed. The deny-list gate flagged the workflows delivery paths, such as products/workflows/frontend/Workflows/logs/log-utils.tsx, which stamphog approves only for authors on team-workflows. The tier gate classified the change as T2-never, since it is a cross-cutting feature touching 24 files and 347 lines across ingestion, CDP consumers, and workflows.

Next, ask a human reviewer, ideally someone on team-workflows, to review this pull request. You could also split it, for example by separating the ingestion fork and topic changes from the CDP consumer and workflows log link changes, so each part gets reviewed on its own.

Gate mechanics and policy version
Gate Result
prerequisites ✓ all clear
deny-list ✗ matches: workflows_delivery (stamphog approves these paths only for authors on team-workflows)
size ✓ 141L, 15F substantive, 347L/24F incl. docs/generated/snapshots — within ceiling
tier ✗ classified as T2-never: T2-never (347L, 24F, cross-cutting, feat)
stamphog 2.4.1 .stamphog/policy.yml @ unknown · reviewed head f4c00f6

@stamphog stamphog Bot removed the stamphog Request AI approval (no full review) label Oct 8, 2026
@github-project-automation github-project-automation Bot moved this to Approved in Feature Flags Oct 9, 2026
@haacked

haacked commented Oct 9, 2026

Copy link
Copy Markdown
Contributor Author

/trunk merge

@trunk-io
trunk-io Bot merged commit 2aff7ff into master Oct 9, 2026
503 of 505 checks passed
@trunk-io
trunk-io Bot deleted the haacked/flag-calls-destinations-mode-2 branch October 9, 2026 16:24
@github-project-automation github-project-automation Bot moved this from Approved to Done in Feature Flags Oct 9, 2026
@deployment-status-posthog

deployment-status-posthog Bot commented Oct 9, 2026 •

Copy link
Copy Markdown

Deploy status

Environment Status Deployed At Workflow
dev ✅ Deployed 2026-10-09 17:01 UTC Run
prod-us ✅ Deployed 2026-10-09 17:14 UTC Run
prod-eu ✅ Deployed 2026-10-09 17:16 UTC Run

This branch was successfully deployed

1 active deployment
preview-pr-113654 — f4c00f67 Deployed Oct 8, 2026 by github-actions[bot]
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

3 participants