Repository navigation
feat(product-events): identify Maple's own events per org and user, and cover in-product actions - #2473
Merged
Maple Review Bot / Maple / review
succeeded
Nov 11, 2026 in 5m 30s
Confidence 10/10 · No issues found
🟢 Confidence 10/10 · safe to merge. Every source hunk is read and the identity, webhook and span-attribute paths are test-pinned; only new test-file diffs went unread.
no findings · tests covered · risk medium · 3/3 new units observable
Identifies Maple's own product events with Clerk user and org, stops server events being projected twice as trace rows, and adds in-product events across web, webhook and MCP. Identity, dedupe and success-guard paths check out; safe to merge, but the Clerk webhook must be registered to deliver anything.
ProductEvents.trackrenames its span attributes tomaple.product_events.*, ending duplicate trace-sourced rowsidentify()carriesroleandplantraits and re-runs when the customer read settles- Webhook and existing spans identify
member_joined/member_removed,mcp_tool_called,investigation_started - Ten new web events cover invites, disconnects, acknowledgements and created objects
Before merge
- Manual · Register
POST /webhooks/clerkin the Clerk dashboard foruser.createdandorganizationMembership.*; until thensignup_completed,member_joinedandmember_removedstay empty
Production impact
Telemetry this change adds and removes (5)
- ➖ attribute
maple.product_event.name(~5/day today) ·packages/backend/src/services/product-events/ProductEventsService.ts:166 - ➖ attribute
maple.product_event.enabled(~5/day today) ·packages/backend/src/services/product-events/ProductEventsService.ts:166 - ➕ attribute
maple.product_events.event·packages/backend/src/services/product-events/ProductEventsService.ts:166 - ➕ attribute
maple.product_events.enabled·packages/backend/src/services/product-events/ProductEventsService.ts:167 - ➕ attribute
maple.product_events.dropped·packages/backend/src/services/product-events/ProductEventsService.ts:192
What was checked
- Empty
includeprojects zero span attributes: present-and-empty keeps no key inmapFilter(product-event-attributes.ts:106) member_removedis tracked only on a 200, andrevokeanswers 500 only when the sweep fails (clerk.http.ts:59)chainaccumulates every step's commands, so the addedTrackDisconnectedsteps are not dropped (update-status.ts:42)
Observability coverage: 3 of 3 changes observable
| Change | Kind | Observable | Evidence |
|---|---|---|---|
mcp_tool_called on the public MCP surface |
span-derived product event | yes | Annotates the existing McpToolExecutor.execute span (apps/ai/src/mcp/dispatcher.ts:235), pinned by dispatcher.test.ts:318 |
investigation_started when a run is claimed |
span-derived product event | yes | packages/backend/src/services/errors/InvestigationService.ts:604 annotates the claim's span with user, org and subject_type |
member_joined / member_removed from the Clerk webhook |
server product event | yes | Tracked inside the ClerkWebhook.membership span (clerk.http.ts:111, :122); ProductEvents.track annotates and logs a drop |
ca6620f · Reply "won't fix" to dismiss a finding, or mention @maple-review-bot to ask about one.
Loading