feat: forward audited mutations to PostHog - #6058
Open
simplesagar wants to merge 3 commits into
Open
Conversation
Contributor
🦋 Changeset detectedLatest commit: 375d8ad The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
There was a problem hiding this comment.
All reported issues were addressed across 4 files
Reply with feedback, questions, or to request a fix.
Fix all with cubic | Re-trigger cubic
simplesagar
force-pushed
the
grw-66-pr2-stream-handler
branch
2 times, most recently
from
September 4, 2026 04:13
1c0db91 to
ba87bdb
Compare
Adds the stream handler that turns audit-log outbox events into `gram_activity`, and joins it to the existing webhook fan-out in the `gram streams` process. No new subscription and no new infrastructure. The handler filters on the `audit_log.` event-type prefix before decoding, because the whole webhook firehose reaches it and decoding every event would be wasted work. It then switches on the audit action rather than the event type: the type is a coarse bucket, and an MCP server creation and a tool-metadata edit share one, so only the action says which activity a record is. Every ignore path acks. A returned error nacks the Pub/Sub message and redelivers it forever, so an envelope that makes no sense, a payload that will not decode, and an excluded action are all logged and acked instead. Emission cannot fail the message either: the emitter logs and drops, because analytics must never hold up the stream. Temporal actions/month: 0 (rides the existing subscription). Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01761VcQZ1sW4TFb16AoozTA
Three findings from review. The topic is at-least-once and this handler shares a message with its siblings, so when any of them fails the whole message nacks and every handler sees the event again. Without a stable key that is a duplicate Slack line for something that happened once. Each activity now carries the outbox event id as PostHog's deduplication key, which is stable across redeliveries. The site URL is now rejected unless it is an absolute http(s) URL. `url.Parse` accepts a bare path or a custom scheme, and either produces a link Slack rejects — a misconfiguration worth failing on at startup rather than discovering one dead button at a time. Excluded actions now log at debug with the event id, so intentional filtering is distinguishable from a missing signal. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01761VcQZ1sW4TFb16AoozTA
simplesagar
force-pushed
the
grw-66-pr2-stream-handler
branch
from
September 4, 2026 04:24
ba87bdb to
3a5a791
Compare
This was referenced Sep 4, 2026
disintegrator
approved these changes
Sep 4, 2026
Comment on lines
+503
to
+521
| // Growth activities enrich against the primary rather than the read | ||
| // replica: an audit event arrives within milliseconds of the write it | ||
| // describes, so replica lag would leave a just-created project or | ||
| // organization unresolvable exactly when it is most interesting. | ||
| var siteURL *url.URL | ||
| if raw := c.String("site-url"); raw != "" { | ||
| siteURL, err = url.Parse(raw) | ||
| if err != nil { | ||
| return fmt.Errorf("parse site url: %w", err) | ||
| } | ||
| // url.Parse accepts a bare path or a custom scheme, and either | ||
| // would produce a link Slack rejects. A site URL that cannot | ||
| // address the dashboard is a misconfiguration worth failing on | ||
| // rather than discovering one dead button at a time. | ||
| if (siteURL.Scheme != "http" && siteURL.Scheme != "https") || siteURL.Host == "" { | ||
| return fmt.Errorf("site url must be an absolute http(s) URL, got %q", raw) | ||
| } | ||
| } | ||
| growthSignalHandler := growthsignals.NewEventHandler(logger, growthsignals.NewEmitter(logger, posthogClient, growthsignals.NewDatabaseEnricher(db), siteURL)) |
Contributor
There was a problem hiding this comment.
- move emitter construction to deps.go as newGrowthSignalsEmitter
- consider using the db read replica to relieve prod db. replication lag will not bite here.
Member
Author
There was a problem hiding this comment.
Both done in 375d8ad. Construction moved to newGrowthSignalsEmitter in deps.go, and enrichment now reads the replica — agreed lag is harmless here, since a miss omits a display-name property rather than dropping the event.
Review feedback. Emitter construction moves to newGrowthSignalsEmitter in deps.go, alongside the other dependency constructors. Enrichment moves to the read replica. The lookups are display names for an ops notification, not authority for anything, and a miss degrades the event by omitting a property rather than dropping it — so replication lag costs at most a missing slug on a very fresh row, which is not worth the primary's capacity. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01761VcQZ1sW4TFb16AoozTA
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.
Note
Stacked PR — merge bottom-up. Each PR targets the one above it, so its Files tab shows only its own diff.
Merging #6057 retargets #6058 to
mainautomatically, and so on down the stack.GRW-66
Second of a five-PR stack. Targets #6057, review that first.
Summary
Turns audit-log outbox events into
gram_activityand joins the handler to the existing webhook fan-out in thegram streamsprocess. No new subscription and no new infrastructure.Three behaviours worth a reviewer's attention:
audit_log.event-type prefix before decoding. The whole webhook firehose reaches this handler, so decoding every event would be wasted work. The prefix also means new audited subjects are covered as services add them, with no list here to extend.Two wiring choices:
The
streamscommand previously had no site URL source, so an optionalsite-urlflag is added, matchingworker.go's optional form rather thanstart.go's required one, so an unset variable cannot fail startup.Motivation
This is the step that makes the audit log's existing signal visible. Without it the taxonomy from #6057 has no producer.
Temporal actions/month: 0, scales with fixed. Rides the existing subscription; no workflows, schedules or activities are added.
Summary by cubic
Turns audit-log outbox events into
gram_activityevents in PostHog by joining a new growth-signals handler to the existing webhook fan-out ingram streams. This is the second step of the GRW-66 PostHog/Slack notifications revamp; no new subscription or infrastructure is added.Handler behavior
audit_log.event-type prefix before decoding, so the rest of the webhook firehose costs nothing.Wiring
site-urlflag togram streamsfor dashboard deep links; when set, startup fails unless it is an absolute http(s) URL.Written for commit 375d8ad. Summary will update on new commits.