Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
314 commits
Select commit Hold shift + click to select a range
4f73e8b
chore(cli): release v0.18.3 (#101479)
releaser-posthog-cli[bot] Sep 16, 2026
8152d31
fix(notebooks): repair widget generation and dataframe reuse (#100112)
mariusandra Sep 16, 2026
f956d22
feat(activity-log): show agent intent and task on audited changes (#1…
posthog[bot] Sep 16, 2026
d07580f
fix(visual-review): finish the retention sweep before deploys kill it…
webjunkie Sep 16, 2026
c053da3
fix(ci): retry pytest failures and preserve retry diagnostics (#101428)
webjunkie Sep 16, 2026
e766bf0
fix(subscriptions): normalize escaped prompt newlines (#100770)
vdekrijger Sep 16, 2026
64d854e
fix(ai): support SQL queries in create insight (#101198)
GeneralistDev Sep 16, 2026
ea7a011
feat(alerts): add a dedicated orchestration worker queue (#100854)
jonmcwest Sep 16, 2026
186d397
feat(conversations): structured investigation verdict and blocker-awa…
veryayskiy Sep 16, 2026
f8ec77c
feat(insights): filter chart annotations by scope (#101466)
sampennington Sep 16, 2026
05bd5c3
feat(replay-vision): measure the search embedding failure rate (#101087)
posthog[bot] Sep 16, 2026
3a74e7d
fix(replay-vision): tighten monitor yes that never looked up events i…
fasyy612 Sep 16, 2026
5140e65
fix(persons): honor -- no-transaction in the persons migration runner…
posthog[bot] Sep 16, 2026
479e05a
fix(workflows): stop blaming the daily cap when the rate limiter fail…
dmarchuk Sep 16, 2026
59e908f
fix(replay-vision): chunk on-demand bulk scans to the API's per-reque…
posthog[bot] Sep 16, 2026
fdf49f9
fix(replay-vision): cite moments in video time, not the footer clock …
TueHaulund Sep 16, 2026
976afed
feat(clickhouse): drain event deletions queued in postgres into the a…
TueHaulund Sep 16, 2026
662b4b5
refactor(ai-research): rename ml mirror privacy module to key manager…
robbie-c Sep 16, 2026
30007ac
chore(ai-research): align ML key store defaults with production (#101…
robbie-c Sep 16, 2026
86f1cc6
chore(ci): skip the image build on desktop-only master pushes (#98111)
pauldambra Sep 16, 2026
4ff2a81
fix(ci): read the whole push when deciding which workers deploy (#98181)
pauldambra Sep 16, 2026
d31fe4f
fix(ci): deploy the health check worker for product detectors (#98187)
pauldambra Sep 16, 2026
9353803
fix(hogql): resolve CTEs in language service validation (#101408)
orian Sep 16, 2026
d4ea871
perf(hogql): trim per-build I/O in database source fetching (#92325)
georgemunyoro Sep 16, 2026
09b69ce
fix(signals): keep the view task button compact (#100736)
andrewm4894 Sep 16, 2026
2a4f720
fix(data-warehouse): stop re-rendering SQL editor chrome on every key…
georgemunyoro Sep 16, 2026
3bca53a
fix(mcp): check business knowledge and docs first (#101431)
VojtechBartos Sep 16, 2026
7b5d0bb
feat(logs): add the JSON parse log attribute setting (#100759)
jonmcwest Sep 16, 2026
fd1bf63
fix(integrations): order the integration list so pagination keeps eve…
posthog[bot] Sep 16, 2026
e16cadb
feat(ai-research): seal ML objects with AES-256-GCM and send Kafka re…
robbie-c Sep 16, 2026
f920688
chore(tasks): gate cloud-run backend and desktop CI behind team revie…
tatoalo Sep 16, 2026
836337e
chore(hogql): generate language service function list (#100911)
orian Sep 16, 2026
dd67554
fix(stamphog): keep digest lines to what the reviewed text states (#1…
webjunkie Sep 16, 2026
fdc610c
fix(skills): make a skill 404 name the rows skill-list returns (#101549)
posthog[bot] Sep 16, 2026
4f6d598
fix(taxonomy): disambiguate lifecycle-only app version and build labe…
christiaan-ph Sep 16, 2026
3d8b7f4
fix(web-analytics): validate preset order field and stabilize paging …
posthog[bot] Sep 16, 2026
d0e92a2
fix(dashboards): restore the edit keyboard shortcut (#101562)
pauldambra Sep 16, 2026
d7da367
chore(llma): Update LLM costs (#101509)
scheduled-actions-posthog[bot] Sep 16, 2026
2894117
feat(prompts): validate prompt references on publish (#101471)
jurajmajerik Sep 16, 2026
a077546
feat(quill): 13px ui text, bold titles, base ui 1.8 (#101175)
adamleithp Sep 16, 2026
930b1c4
chore(experiments): drop single-case use_new_query_builder parameteri…
andehen Sep 16, 2026
6e030c3
fix(ci): keep the schema cache restore alive without an OIDC key (#10…
webjunkie Sep 16, 2026
64d6e3c
feat(marketing): add page visibility tab (#101369)
jabahamondes Sep 16, 2026
ccd0b25
fix(hogql): preserve editor positions and identifiers (#101563)
orian Sep 16, 2026
bc63ecb
feat(cdp): add beehiiv realtime destination (#101541)
dmarchuk Sep 16, 2026
a6fcb5c
fix(session-replay): queue observation events for deletion with the r…
TueHaulund Sep 16, 2026
6dff087
feat(logs): add per-team json attribute sniff metrics (#101599)
jonmcwest Sep 16, 2026
94a1871
chore(experiments): dedup the precompute gates across the query runne…
andehen Sep 16, 2026
5fc5bef
chore(metrics): add timestamp minmax index to metrics2 and bucketed m…
frankh Sep 16, 2026
f3274e3
chore(settings): Read all from env (#101474)
tomasfarias Sep 16, 2026
ac93a81
fix(tasks): accept a resume branch the previous run worked on (#101635)
tatoalo Sep 16, 2026
4711ba7
feat(project-tree): lazy-load unfiled reconciliation (#101243)
MattPua Sep 16, 2026
cf582ae
chore(hogql): extract shared query analysis from validation (#101613)
orian Sep 16, 2026
805dd9a
chore(experiments): cut duplicate query-layer snapshots (#101464)
andehen Sep 16, 2026
9e76b8c
fix(alerts): keep scheduling when metrics fail (#98580)
vdekrijger Sep 16, 2026
280b444
feat(auth): add oidc (#97388)
ReeceJones Sep 16, 2026
20ada85
fix(data-warehouse): drop the unreachable legacy frequency mode from …
sakce Sep 16, 2026
c8e082d
fix(signals): keep birth-day outcomes in ranking labels and the newbo…
posthog[bot] Sep 16, 2026
832be18
feat(signals): record first-event timestamps for every ranking label …
posthog[bot] Sep 16, 2026
bba801f
feat(buildkite): add team pipeline, member, schedule and queue tables…
Gilbert09 Sep 16, 2026
6c95a9f
feat(campfire): add product, customer, entity and subscription tables…
Gilbert09 Sep 16, 2026
16f4af6
feat(workflows): start new workflows from a PostHog AI composer behin…
mayteio Sep 16, 2026
4be0d13
fix(subscriptions): unblock saving an existing subscription (#101282)
kyleswank Sep 16, 2026
a239389
feat(signals): preserve scout display names separately from slugs (#1…
posthog[bot] Sep 16, 2026
a914374
feat(hogql): complete cte and subquery projected fields (#101638)
orian Sep 16, 2026
00602c9
fix(admin): restore the confirmation dialogs CSP was dropping (#101381)
Piccirello Sep 16, 2026
d1a665a
feat(alerts): add typed synthetic demand discovery (#101535)
jonmcwest Sep 16, 2026
de921ca
feat(canvas): make context reads reliable and expose run failures (#1…
posthog[bot] Sep 16, 2026
e19cecf
fix(personhog): run one fenced window at a time per partition (#101321)
z0br0wn Sep 16, 2026
a606ba5
fix(ai-research): keep recording under the organization a stored ML k…
robbie-c Sep 16, 2026
784aea2
feat(signals): read score calibration per head on both grading sides …
posthog[bot] Sep 16, 2026
9c019c7
feat(conversations): show the Slack ticket link to org members only (…
veryayskiy Sep 16, 2026
a6f7ebb
chore(hogql): add a local language service playground (#101600)
orian Sep 16, 2026
0decfb7
chore(web-analytics): lower warming selection cache TTL to 2h (#101390)
lricoy Sep 16, 2026
3341fd4
fix(context): publish dream edits and expose unpublished runs (#101199)
k11kirky Sep 16, 2026
885a787
fix(subscriptions): break list sort ties on id (#101567)
posthog[bot] Sep 16, 2026
723d7ee
feat(desktop): tell no-repo tasks to search business knowledge first …
veryayskiy Sep 16, 2026
6594427
feat(ai-research): drop the organization from the ML key encryption c…
robbie-c Sep 16, 2026
f903477
chore(owners): let a surfaces approval clear the tasks gate (#101704)
tatoalo Sep 16, 2026
4f66698
fix(warehouse-sources): keep an SES pool AWS refuses to describe (#10…
posthog[bot] Sep 16, 2026
c14c159
fix(conversations): stop attributing ticket events to the support pro…
veryayskiy Sep 16, 2026
d3dda2b
fix(replay): name a date range the preset list does not contain (#101…
HaynesPostHog Sep 16, 2026
939d1b5
fix(web-analytics): stop classifying cookieless events as bots (#98097)
jordanm-posthog Sep 16, 2026
25b6ee2
fix(warehouse-sources): honor a flat auth method in source payloads (…
posthog[bot] Sep 16, 2026
ee41ac1
chore(deps): Update @posthog/mcp to 0.16.3 (#100018)
posthog-js-upgrader[bot] Sep 16, 2026
039c4e8
chore(deps): Update posthog-react-native to 4.74.0 (#100019)
posthog-js-upgrader[bot] Sep 16, 2026
84d3226
chore(deps): Update posthog-rs to 0.25.5 (#101055)
posthog-js-upgrader[bot] Sep 16, 2026
09c99ca
feat(approvals): sync feature flag policies to hidden experiment poli…
yasen-posthog Sep 16, 2026
5420667
fix(admin): build the admin URL conf from the full lazy registry (#10…
webjunkie Sep 16, 2026
260d423
feat(signals): skip scout suggestion scans for projects with no data …
posthog[bot] Sep 16, 2026
cf6c510
chore(ci): stop an artifact upload blip failing the desktop update e2…
webjunkie Sep 16, 2026
8984ffb
perf(personhog): drop old status-predicated lifecycle mark indexes (#…
nickbest-ph Sep 16, 2026
2d6c6bd
fix(ci): report pytest retry attempts to trunk (#101493)
webjunkie Sep 16, 2026
7d8e024
feat(signals): fit the ranking heads on one birth-day row per report …
andrewm4894 Sep 16, 2026
16eb734
chore(ci): select backend tests from the integrated pr base (#101061)
rnegron Sep 16, 2026
970512c
feat(signals): shadow-evaluate the inbox ranking model against the se…
posthog[bot] Sep 16, 2026
24ab0ac
chore(approvals): give approvals to platform features (#101510)
yasen-posthog Sep 16, 2026
d24e32b
feat(tags): add generic pointer columns to tagged items (#101560)
yasen-posthog Sep 16, 2026
6ed004f
fix(desktop): run two test packages at a time in turbo (#100975)
pauldambra Sep 16, 2026
efcd3cf
fix(admin): restore the array field preview CSP was dropping (#101384)
Piccirello Sep 16, 2026
d928063
fix(devbox): use the template's default disk size (#101739)
rnegron Sep 16, 2026
878b2b5
feat(experiments): Warn before deleting a shared metric used by runni…
jurajmajerik Sep 16, 2026
258dd19
fix(data-quality): wrap the overview toolbar at narrow scene widths (…
thiagosalvatore Sep 16, 2026
3c79cfe
feat(data-quality): tighten the data quality overview states (#101047)
thiagosalvatore Sep 16, 2026
872ced7
chore(experiments): resolve the experiment-flag-cleanup-pr flag to on…
andehen Sep 16, 2026
ae586f5
feat(prompts): protect referenced prompts and labels (#101609)
jurajmajerik Sep 16, 2026
9609dcd
chore(replay): capture anchor diagnostic on recording load (#101317)
ksvat Sep 16, 2026
421c5a1
fix(data-quality): finish the suite before notifying (#101252)
thiagosalvatore Sep 16, 2026
436d449
fix(data-quality): gate notification recipients on the subjects the c…
thiagosalvatore Sep 16, 2026
40ea5c2
fix(data-quality): build the caller's HogQL database only when a defi…
thiagosalvatore Sep 16, 2026
cae61e5
fix(experiments): Stop logging running-time calculator drift to exper…
jurajmajerik Sep 16, 2026
9f55d65
fix(activity-log): retain intent from desktop oauth edits (#101677)
pauldambra Sep 16, 2026
4bbbb86
fix(signals): exclude departed commit authors from suggested reviewer…
posthog[bot] Sep 16, 2026
d3c9399
feat(experiments): Let show-recordings button link to recordings tab …
mp-hog Sep 16, 2026
b375d31
feat(customer-analytics): copy selected user emails (#101178)
arthurdedeus Sep 16, 2026
ab32e5e
feat(alerts): page source dispatchers from the tick (#101675)
jonmcwest Sep 16, 2026
82646da
feat(insights): add retention cohort line colors and a mean line (#10…
sampennington Sep 16, 2026
eeedd79
fix(signals): scope ranking outcome timestamps to the report's tenant…
posthog[bot] Sep 16, 2026
57a7816
feat(autoresearch): add the template and validation endpoints (14/22)…
andrewm4894 Sep 16, 2026
0ca57fa
fix(workflows): keep sandbox and production APNs credentials apart (#…
dmarchuk Sep 16, 2026
ef28eea
feat(warehouse_sources): add four bunny.net tables (#101633)
Gilbert09 Sep 16, 2026
29f773a
chore(warehouse-sources): remove the fast-return rollout flag (#101690)
danielcarletti Sep 16, 2026
1737787
chore(batch-exports): widen hourly SLA to 3 hours (#101757)
rossgray Sep 16, 2026
47c8659
refactor(warehouse-sources): split external data source view (#98377)
pauldambra Sep 16, 2026
76d95d6
fix(temporal): size the @asyncify thread pool to the worker's activit…
tatoalo Sep 16, 2026
d5aed5f
fix(error-tracking): show tooltips for preview tabs (#101765)
hpouillot Sep 16, 2026
658715d
feat(web-analytics): add screenshot access configuration api (#98081)
jordanm-posthog Sep 16, 2026
e868679
feat(ingress): route the GitHub App webhook through ingress (#100417)
webjunkie Sep 16, 2026
db4026e
feat(ingress): provider-owned parsing, a throttle lane and verificati…
webjunkie Sep 16, 2026
c9875d7
feat(devex): let products mount their own root routes, starting with …
webjunkie Sep 16, 2026
2bdbede
fix(marketing): isolate page visibility filter state (#101722)
jabahamondes Sep 16, 2026
ca6bb8f
feat(cdp): wake awaited workflow steps over the CDP API instead of Ka…
mayteio Sep 16, 2026
bee5141
chore(warehouse-sources): match the rewritten ssh tunnel error in syn…
posthog[bot] Sep 16, 2026
7574798
fix(data-warehouse): record a native panic during repartitioning (#99…
Gilbert09 Sep 16, 2026
86a3b98
fix(warehouse-sources): retry the team lookup after a postgres deadlo…
Gilbert09 Sep 16, 2026
b9e6467
fix(warehouse-sources): refuse vendor redirects in Persona, Sprig and…
jakesciotto Sep 16, 2026
040c0eb
feat(callrail): add accounts, leads, page_views and lead_timelines (#…
Gilbert09 Sep 16, 2026
cccf8fb
fix(warehouse-sources): fall back to pg_catalog for redshift columns …
jakesciotto Sep 16, 2026
97725d7
fix(postgres): stop retrying an unlogged table read on a read replica…
Gilbert09 Sep 16, 2026
65cac19
fix(mongodb): keep syncs enabled after a short cluster outage (#101378)
posthog[bot] Sep 16, 2026
a530198
chore(warehouse-sources): promote the Airtable source to GA (#101745)
Gilbert09 Sep 16, 2026
d69c917
fix(postgres): stop a duckgres pooler cooldown from flooding error tr…
Gilbert09 Sep 16, 2026
6f09c1a
feat(warehouse_sources): sync Campaign Monitor journeys and recipient…
Gilbert09 Sep 16, 2026
68ff9e3
feat(warehouse_sources): add CQC inspection-area tables (#101623)
Gilbert09 Sep 16, 2026
db55f0b
feat(warehouse_sources): add Azure DevOps work item, pipeline and PR …
Gilbert09 Sep 16, 2026
5fbd46a
feat(warehouse_sources): add BuildBetter tag and type tables (#101612)
Gilbert09 Sep 16, 2026
a22fabe
feat(capsule-crm): add entries, boards, stages and tag tables (#101611)
Gilbert09 Sep 16, 2026
d7e29b4
feat(warehouse_sources): add canny opportunities, insights, ideas and…
Gilbert09 Sep 16, 2026
a8d3ae4
fix(postgres): stop retrying a provider data-transfer quota block (#1…
Gilbert09 Sep 16, 2026
53248a8
feat(warehouse_sources): support LinkedIn Ads API version 202609 (#10…
Gilbert09 Sep 16, 2026
5599aab
feat(warehouse_sources): support Salesforce API version v68.0 (#101532)
Gilbert09 Sep 16, 2026
5143fd2
chore(warehouse-sources): promote the Mailgun source to GA (#101507)
Gilbert09 Sep 16, 2026
c59797c
feat(data-warehouse): scaffold the Quo source (#101482)
Gilbert09 Sep 16, 2026
5c84791
fix(pipedrive): say what to do when credential validation fails (#101…
Gilbert09 Sep 16, 2026
b59b128
fix(warehouse-sources): retry a table the worker has no schema for (#…
posthog[bot] Sep 16, 2026
63179b2
fix(langsmith): say what to do when the credential check fails (#100802)
Gilbert09 Sep 16, 2026
fb9684b
fix(leadfeeder): stop syncing an account past the vendor's page depth…
Gilbert09 Sep 16, 2026
e9561e7
chore: remove platform features ownership of common test files (#101768)
ReeceJones Sep 16, 2026
aa863e8
fix(warehouse-sources): skip the audit read when marking CDC schemas …
Gilbert09 Sep 16, 2026
2bf77ee
fix(clickhouse): classify a pyarrow mid-stream truncation as retryabl…
Gilbert09 Sep 16, 2026
43bff22
fix(error-tracking): hide sparkline event tags outside charted range …
hpouillot Sep 16, 2026
7b62af0
fix(warehouse-sources): bound the Decagon page walk by the server tot…
jakesciotto Sep 16, 2026
f8c8110
feat(data-modeling): stamp the endpoint version on its model node (#1…
sakce Sep 16, 2026
278bee3
fix(desktop): use backend regions for network metric paths (#101440)
pauldambra Sep 16, 2026
3981f33
fix(query-scan): insight banner fixes and persons-join false positive…
aspicer Sep 16, 2026
6ce9ced
fix(warehouse-sources): recognize cross-source non-retryable errors i…
Gilbert09 Sep 16, 2026
271aa7e
feat(personhog): add DeleteTombstonedPersons RPC (#97994)
eli-r-ph Sep 16, 2026
3cd5c72
fix(flags): stop renames and deletes breaking replay trigger groups (…
haacked Sep 16, 2026
0c19f4a
fix(replay): measure the inactivity map's video axis during capture (…
TueHaulund Sep 16, 2026
7ad3338
chore(deps): Update @posthog/react-native-plugin to 2.9.4 (#100024)
posthog-js-upgrader[bot] Sep 16, 2026
be6b534
chore(deps): Update posthog-js to 1.433.6 (#100739)
posthog-js-upgrader[bot] Sep 16, 2026
efadd1d
fix(warehouse-sources): record why an incremental sync is blocked (#9…
danielcarletti Sep 16, 2026
6f26b83
fix(warehouse-sources): probe the key an incremental sync merges on (…
danielcarletti Sep 16, 2026
9450a5b
fix(warehouse-sources): require a key before a table syncs incrementa…
danielcarletti Sep 16, 2026
43c1103
fix(signals): search the scout roster by the name on the card (#101836)
posthog[bot] Sep 16, 2026
7806f2c
feat(marketing): add session retention summary table (#101370)
jabahamondes Sep 16, 2026
3641342
fix(prompts): lock labels before versions in all prompt reference pat…
jurajmajerik Sep 16, 2026
c9461d4
fix(skills): accept the manifest key `path` on skill-file-get (#101741)
posthog[bot] Sep 16, 2026
a426d34
fix(charts): round only the outer cap of a diverging stack's negative…
sampennington Sep 16, 2026
4f691fc
feat(hogql): resolve select aliases in shared query analysis (#101724)
orian Sep 16, 2026
dc8f0a5
fix(experiments): Give lifecycle actions proper history copy (#101853)
jurajmajerik Sep 16, 2026
06dcf54
refactor(warehouse-sources): share the connect-time host check (#101362)
Piccirello Sep 16, 2026
cf4b4fb
perf(insights): lazy load tag filter options (#101779)
MattPua Sep 16, 2026
85925e8
fix(experiments): Surface shared metric save errors and block double …
jurajmajerik Sep 16, 2026
00c0c2b
fix(mcp): reject batched exec commands with one clear error (#101669)
posthog[bot] Sep 16, 2026
5d48c33
chore(devex): attribute trunk flaky tests through the owners.yaml map…
gantoine Sep 16, 2026
524e48b
fix(cdp): give batch workflow audience resolution its own timeout (#9…
jakesciotto Sep 16, 2026
231cce1
chore(stamphog): rewrite the readmes for a first-time reader (#101733)
webjunkie Sep 16, 2026
743c84f
perf(warehouse-sources): make a Metronome usage sync finishable (#101…
danielcarletti Sep 16, 2026
4f9ba03
chore(hogli): find the dev caches doctor:disk was missing (#101662)
gantoine Sep 16, 2026
a2de5be
fix(replay-vision): report every gemini call to llm analytics in priv…
TueHaulund Sep 16, 2026
50f5eae
chore(personhog): remove dropped lifecycle_op_person_mark from constr…
nickbest-ph Sep 16, 2026
a08394d
fix(auth): rate limit SSO login starts (#101627)
ReeceJones Sep 16, 2026
310d582
chore(tests): stop unrunnable tests reading as broken in trunk (#101213)
gantoine Sep 16, 2026
628ca36
fix(customer-analytics): exclude internal email account matches (#101…
arthurdedeus Sep 16, 2026
b5081aa
feat(web-analytics): send approved cookies in screenshot renders (#98…
jordanm-posthog Sep 16, 2026
adb6530
feat(hogql): suggest cte tables and query-start keywords (#101907)
orian Sep 16, 2026
136fc5d
fix(workflows): hold every duration field to one grammar (#101188)
dmarchuk Sep 16, 2026
fdd84fd
perf(dashboards): defer homepage dashboard loading (#101219)
MattPua Sep 16, 2026
c98bd27
feat(autoresearch): add the read-only model, run and training-run end…
andrewm4894 Sep 16, 2026
2748892
feat: schedule project deletion 48 hours in the future (#99317)
ReeceJones Sep 16, 2026
3aedcac
feat(clickhouse): add person_pg_cleanup_drain_job (#97995)
eli-r-ph Sep 16, 2026
3aaa11a
feat(engineering-analytics): add team delivery figures and a pr timel…
webjunkie Sep 16, 2026
42fe4c5
fix(quick-filters): give the list a stable pagination order (#101899)
posthog[bot] Sep 16, 2026
0260e37
feat(personhog): add keyset pagination for GetDistinctIdsForPerson RP…
nickbest-ph Sep 16, 2026
a65a9ac
fix(warehouse-sources): ask for a key only where discovery reads one …
danielcarletti Sep 16, 2026
c879357
fix(cdp): mark segment destination credential inputs as secret (#101911)
Piccirello Sep 16, 2026
5c69e17
chore(llma): Update LLM costs (#101913)
scheduled-actions-posthog[bot] Sep 16, 2026
dd0af54
fix(warehouse-sources): stop reporting integration-service blips duri…
Gilbert09 Sep 16, 2026
3cfcde9
fix(auth): stop desktop oauth attribution recursing into authenticati…
pauldambra Sep 16, 2026
a2b1460
feat(data-quality): move the materialization gate into settings (#101…
thiagosalvatore Sep 16, 2026
1fcbc5c
feat(error-tracking): add a surrounding logs tab to the exception car…
jzhu13 Sep 16, 2026
6b81193
feat(replay-vision): fold single-token outcomes into the watch feed c…
ksvat Sep 16, 2026
4242286
fix(experiments): offer buttons in empty "too-early" state on recordi…
mp-hog Sep 16, 2026
f1d37ea
chore(deps): Update posthog-node to 5.52.4 (#100137)
posthog-js-upgrader[bot] Sep 16, 2026
444fb0e
feat(hogql): disambiguate joined field completions (#101948)
orian Sep 16, 2026
7a673ae
chore(skills): simplify community publish rendering (#100083)
pauldambra Sep 16, 2026
1ba10da
chore(hogql): split oversized printer test module and cut C901 hotspo…
posthog[bot] Sep 16, 2026
143c25d
chore(data-modeling): split view enrichment into named units (#100750)
posthog[bot] Sep 16, 2026
b8f21c7
chore(elements): parse an elements chain in one place (#100986)
posthog[bot] Sep 16, 2026
947b32b
chore(replay): remove redundant comments from session batch manager (…
posthog[bot] Sep 16, 2026
1047331
fix(warehouse): log trino readiness failure reasons (#101953)
EDsCODE Sep 16, 2026
bd19f95
feat(growth): weight product push picks by member roles (#101271)
posthog[bot] Sep 16, 2026
d26baa3
feat(web-analytics): read an empty error tracking tile as good news (…
mjwarren3 Sep 16, 2026
42074a1
feat(pgcollector): parse query tags out of statements into a tags col…
nickbest-ph Sep 16, 2026
f45ce44
feat(pgapi): group, filter and label queries by their tags (#101956)
nickbest-ph Sep 16, 2026
fcfc2f6
chore(warehouse_sources): split amazon ads row loading into named hel…
posthog[bot] Sep 16, 2026
ab8127a
chore(canvas): split the grid layout validators (#101808)
posthog[bot] Sep 16, 2026
d1923dc
perf(exports): index exported assets by team and session for every ro…
TueHaulund Sep 16, 2026
f665411
feat(signals): lay out inbox autonomy settings as uniform rows (#101041)
cvolzer3 Sep 16, 2026
04937e3
feat(replay-vision): let scanners look up failed and slow network req…
TueHaulund Sep 16, 2026
4393937
fix(web-analytics): align responsive grid breakpoints (#101912)
mjwarren3 Sep 16, 2026
27d898c
fix(auth): cover saved insight login redirect (#99793)
pauldambra Sep 16, 2026
f42cf65
feat(desktop): improve the unconnected GitHub experience (#93871)
dmarticus Sep 16, 2026
acb94d6
fix(desktop): keep delegated reports out of triage (#100522)
dmarticus Sep 16, 2026
52a2323
feat(web-analytics): flag pageviews without a usable session id (#90564)
posthog[bot] Sep 16, 2026
1f9b50c
chore(revenue-analytics): drop narration comments from stripe subscri…
posthog[bot] Sep 16, 2026
7d27f0b
chore(marketing-analytics): remove the drill-down feature gate (#95403)
posthog[bot] Sep 16, 2026
42ccfaf
feat(web-analytics): add screenshot access settings ui (#97876)
jordanm-posthog Sep 16, 2026
55623ac
feat(customer-analytics): open accounts by external id (#101885)
arthurdedeus Sep 16, 2026
ee6be3d
feat(web-analytics): keep repeatedly check-missed shapes warm via sti…
lricoy Sep 16, 2026
8cf3911
feat(signals): let the web vitals scout audit public posthog.com page…
lricoy Sep 16, 2026
4765ace
feat(capture): split already-disabled GRL counter by over_budget (#10…
eli-r-ph Sep 16, 2026
2e79c78
feat(personhog): tag every identity service statement with its operat…
nickbest-ph Sep 16, 2026
781036a
feat(aeo): add citation-tracking POC behind a feature flag (#87304)
lricoy Sep 16, 2026
f25d2c5
feat(replay-vision): filter and search the watch feed (#99497)
ksvat Sep 17, 2026
6c2b1d5
fix(cohorts): surface a static cohort's failed population (#101285)
haacked Sep 17, 2026
d17348a
feat(csp): report every violation staff hit, not one in ten (#102020)
Piccirello Sep 17, 2026
a46dcc2
chore(cymbal): add shimforge to simplify tests
tanglearncode Sep 16, 2026
f5ddf79
Merge branch 'master' into chore/cymbal-shimforge-capture-test
tanglearncode Sep 17, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
The table of contents is too big for display.
Diff view
Diff view
  •  
  •  
  •  
The diff you're trying to view is too large. We only load the first 3000 changed files.
40 changes: 40 additions & 0 deletions .agents/security.md
Original file line number Diff line number Diff line change
Expand Up @@ -157,3 +157,43 @@ semgrep --test .semgrep/rules/security/
# Or via Docker
docker run --rm -v "${PWD}:/src" semgrep/semgrep semgrep --test /src/.semgrep/rules/security/
```

## Content Security Policy

`CSPMiddleware` in `posthog/middleware.py` attaches a policy to every HTML response.
Treat it as enforced.
A refused resource produces no user-visible error, so the feature simply does not work, and the only signal is a `$csp_violation` event in project 2.

Three policies exist, and a change lands in whichever one covers the page:

- **The app policy** governs every SPA page. It is enforced per user behind the `csp-enforce-app-policy` flag, and report-only otherwise.
- **The admin policy** governs `/admin/`. It is enforced for every staff member, with no flag, so a mistake here breaks admin immediately.
- **A view may set its own policy.** The canvas artifact and the workflow asset endpoint do this to sandbox untrusted HTML. `CSPMiddleware` returns a response that already carries the header unchanged, so do not expect the app policy on those documents.

### What the app policy forbids

| You want to | The policy says |
| ------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| Load a script from a new origin | Only `'self'`, our own CDNs, and a named list. Stripe, Turnstile and Unlayer are there because each vendor requires its own origin. Prefer serving the file yourself. |
| Call `eval` or `new Function` | Refused. `wasm-unsafe-eval` permits WebAssembly compilation only. |
| Start a worker | `'self'` and `blob:` only. Never `data:`: a `data:` worker body is code the policy cannot inspect. |
| Load a font from a CDN | Self-host it instead. A CDN font already caused a regression when the origin was removed. |
| Submit a form | `'self'` plus the admin OAuth origin. The directive is checked on every hop of a redirect chain, so a same-origin action that redirects off-origin is refused. |
| Set `<base href>` | Refused. Chromium judges the assignment even on a detached document. |

### Traps that have already cost us

- **A dependency can carry the origin.** Grep `node_modules` for the literal host before you call an origin unused. A font CDN was removed on the belief nothing used it, and a transitive dependency defaulted to it.
- **posthog-js wraps `fetch`, so an extension's request is reported with our bundle as the source file.** Never conclude a violation is ours from the source file alone. Corroborate with the blocked URL and the document.
- **A CSP report names the original URL, not the hop that failed.** For `form-action` and any redirected navigation, the blocked URL can be same-origin while the refusal happened later in the chain.
- **The Vite dev server cannot reproduce any of this.** It injects CSS as `<style>` blocks and emits absolute asset URLs, so paths that depend on a stylesheet's own href never run. Only the esbuild build matches production.

### Checking a change

Add the source to the policy that covers the document, which is not always `CSPMiddleware`.
An app or admin page takes the matching list in `CSPMiddleware`.
A canvas artifact takes `artifact_csp()` in `products/canvas/backend/contract.py`, and a workflow message asset takes the header its endpoint sets in `products/workflows/backend/api/hog_flow.py`.
`CSPMiddleware` returns a view-set header untouched, so widening the app policy does nothing for those two.
Say why the source is needed in a comment either way, then run `posthog/test/test_middleware.py::TestCSPMiddleware`.
To see what the policy currently blocks, query `$csp_violation` events in project 2.
Filter to the current policy text and exclude browser extensions on both the source file and the blocked URL, or the result is mostly noise.
8 changes: 6 additions & 2 deletions .agents/skills/adding-inbound-webhooks/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ Rules that decide whether this works:
- The handler runs synchronously inside the request. Enqueue a task for real work, the way stamphog and conversations do.
- A handler that reads the database wraps the read in `bounded_statement_timeout(ms, models=...)` from `posthog.ingress.dispatch.database`, passing only the models the read actually uses. Opening an alias is itself unbounded, so naming one the read never touches can stall the delivery on connection setup.
- An import-linter contract (`webhook consumers must only import facade`) holds the module to its own product's `facade/`. Reach product internals through the facade.
- A consumer whose resources are split across regions declares `ownership=`, pointing at a facade function that returns a `DeliveryOwnership`. Ingress forwards the signed request when the answer is `ELSEWHERE`, and dispatches locally either way. The lookup runs inside the request, so bound it with `bounded_statement_timeout(ms, models=...)`.

Tests: extend the product's existing webhook test module rather than starting a parallel one.
`products/stamphog/backend/tests/test_webhook_consumers.py` is the shape: drive the real view with a signed `RequestFactory` request and assert the enqueue, plus the event type the app does not register, the bad signature, the unparseable body, the non-POST, and the missing secret.
Expand All @@ -57,13 +58,16 @@ Copy `github/` for the full shape, or `vapi/` for a small one.
`provider.py` holds three things:

- `SPECS`, one `ProviderSpec` per app, naming the event types that app is subscribed to. The registry validates consumers against these.
- A `WebhookProvider` subclass with `scheme()` (from `posthog/ingress/verify/`), `deliveries()` (how to read the event type, delivery id and context off the verified request), and any status codes the provider's protocol fixes. Defaults are 403 on a bad signature, 500 when unconfigured, 202 on success.
- A `WebhookProvider` subclass with `scheme()` (from `posthog/ingress/verify/`), `deliveries(request, payload, facts)` (how to read the event type, delivery id and context off the verified request), and any status codes the provider's protocol fixes. Defaults are 403 on a bad signature, 500 when unconfigured, 202 on success.
- `verify(request)` answers a `Verification`: the outcome, plus `facts`, whatever the scheme proved on the way. A scheme that validates a signed token puts its verified claims there and `deliveries` cross-checks the body against them; an HMAC scheme leaves it empty and `deliveries` ignores it.
- `parse(request)` decodes the body, and defaults to JSON. Override it for a provider that posts a form, and raise `InvalidPayload` for a body it cannot read. Verification runs first and must, because reading `request.POST` consumes the request stream under ASGI.
- `throttle_class` names a DRF throttle from `posthog.rate_limit`, run in front of verification. Set one when the endpoint is public and its verification is expensive, such as a JWT signing-key lookup.
- A `build_<provider>_provider(...)` function returning it. Secrets and verifiers a product owns are **passed into this builder**, never imported: nothing under `posthog/ingress/` may import a product.

Then:

1. Add the module path to `_INCARNATION_MODULES` in `posthog/ingress/providers.py`, or the registry never sees its specs or core consumers.
2. Wire the URL with `build_webhook_view()`, for example `opt_slash_path("webhooks/<provider>", build_webhook_view(build_<provider>_provider()))`. GitHub and SES sit in `posthog/urls.py`; the others are declared by the owning product.
2. Wire the URL with `build_webhook_view()` where the App registration lives. The owner of the third-party App owns the route: a product that registered the App declares `urlpatterns` in its own `products/<product>/backend/routes.py`, for example `opt_slash_path("webhooks/<product>/<provider>", build_webhook_view(build_<provider>_provider()))`. The path must start with `webhooks/<product>/` or `api/<product>/`, or the URL conf fails to load. Only an App several products consume stays in `posthog/urls.py`, which today is the customer-facing GitHub App alone. See [docs/internal/url-routing.md](../../../docs/internal/url-routing.md).
3. Write `posthog/ingress/<provider>/README.md` with the fixed sections, in this order: headers, signature scheme, delivery id and event type, apps and secrets, quirks, consumers. `posthog/ingress/test/test_provider_readme_sections.py` fails on a provider folder without one, and on a README with different or reordered headings.
4. Add the provider's signature header name to the `$HEADER` regex in `.semgrep/rules/devex/inbound-webhooks-go-through-ingress.yaml`, plus a fixture case in the `.py` beside it. The header names are spelled out rather than matched generically because a generic header pattern makes semgrep time out on a large module, which drops that file from the scan without failing it.
5. Delete the migrated endpoint's line from `paths.exclude` in the same rule. That list is a ratchet of verifiers that predate ingress, and the migrating PR removes its own entry.
Expand Down
14 changes: 6 additions & 8 deletions .agents/skills/adding-personhog-rpc/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,14 +130,12 @@ The compiler guides you — once the proto is defined, `cargo build` errors tell

### 3c. Router wiring (personhog-router)

1. **Add the method** to `rust/personhog-router/src/router/mod.rs`
- Use the `route_request` function (imported from `routing.rs`) with the correct `DataCategory` and `OperationType`
- Call the replica (or leader) backend
- Use the `call_backend!` macro for instrumentation
2. **Add the service impl** to `rust/personhog-router/src/service/mod.rs`
- Invoke the `route_request!` macro (defined at the top of this file) to delegate to the router
3. **Add to the backend trait** in `rust/personhog-router/src/backend/mod.rs` and implement in `replica.rs`
4. **Add router tests** in `rust/personhog-router/tests/`
The router forwards request bytes without decoding them, so a new RPC needs no handler there.

1. **Add the method name** to `KNOWN_METHODS` in `rust/personhog-router/src/proxy.rs`, keeping the list sorted
- Methods that must reach the leader are matched by name in `proxy.rs`; everything else forwards to a replica
- `known_methods_is_sorted` and `known_methods_matches_service_proto` in the same file fail until the list matches `service.proto`
2. **Add the method** to every `PersonHogService` mock that implements the generated trait, including the ones outside personhog (`rust/personhog-router/tests/common/mod.rs`, `rust/property-defs-rs/tests/`); tonic traits have no default methods

Use `rstest` parameterized tests where multiple variations of the same behavior are being tested.

Expand Down
1 change: 1 addition & 0 deletions .agents/skills/establishing-code-ownership/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ For a path, it walks from the repo root down to the path collecting ownership fi
1. **`owners.yaml` — the canonical, distributed source.** Each directory can carry one. Fields (`owners`, `status`, `inherit`, per-path `rules`) fall through to the nearest ancestor unless overridden. `inherit: false` cuts the walk (Gerrit's `set noparent`) — nothing above it contributes. Within a file, `rules:` are last-match-wins. `owners: null` means **unowned by design** (exempt from the coverage check), distinct from a directory with no file at all (genuinely unowned).
2. **`products/<name>/product.yaml` — an accepted alias.** When a product dir has no `owners.yaml`, its `product.yaml` `owners:` list is read as the ownership for `products/<name>/**` (every other `product.yaml` field is ignored). A dir with both files is a lint error; `owners.yaml` wins.
3. **`.github/CODEOWNERS` — blocking approvals, never part of the walk.** It keeps GitHub-native semantics, stays hand-maintained (mostly infra, e.g. `team-security`), and is enforced by GitHub itself. The resolver does **not** read it — when you need to know whether a blocking approval is additionally required, consult the file directly. It never changes the resolved `owners`, and nothing here writes to it.
A tool that can only read CODEOWNERS gets a generated projection of the map instead, from `hogli owners:codeowners` (see [tools/owners/README.md](../../../tools/owners/README.md)); that projection covers test files and is never `.github/CODEOWNERS`.

Owners are a mixed list of **team slugs** (`team-devex`, `conversations`, `logs` — the GitHub team handle minus `@PostHog/`) and **`@handles`** for individuals; the first entry is the primary owner.

Expand Down
8 changes: 8 additions & 0 deletions .agents/skills/fixing-flaky-tests/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,14 @@ The `trunk` MCP server in `.mcp.json` queries it (tools are marked experimental

Authenticate once via `/mcp` → `trunk` (browser OAuth); headless environments instead add an `Authorization: Bearer` header with a `TRUNK_API_TOKEN` org token to the server entry.

Two limits worth knowing before you start here.
AI investigations are not enabled for this repo, so `fix-flaky-test` returns history or nothing, never a root cause.
And lookup only goes name to ID: a bare dashboard link identifies a test you cannot name, so ask for the test name rather than guessing at the ID.

Trunk attributes each test to a team through CODEOWNERS, which cannot express the `owners.yaml` map.
`.github/scripts/trunk-codeowners.sh` projects the map into a generated CODEOWNERS before each upload (`hogli owners:codeowners` builds the same file locally), so a test's owner in Trunk should match `hogli owners:who`.
Where it does not, the projection dropped a spelling two teams would both claim.

Like `ci:insights`, this is corroboration and history, not the classification authority — flaky-vs-deterministic and the rate still come from the run data above.

## 2. Extract the failure from CI
Expand Down
Loading
Loading