feat: feedback + observability flow — PostHog dataset isolation, /support, Sentry correlation, real-ingestion e2e - #116
Open
BSalaeddin wants to merge 3 commits into
Open
feat: feedback + observability flow — PostHog dataset isolation, /support, Sentry correlation, real-ingestion e2e#116BSalaeddin wants to merge 3 commits into
BSalaeddin wants to merge 3 commits into
Conversation
…r capture, identity, Sentry correlation, build args
…trix route, error-prompt dialog, usesend replyTo
…tion + CI secrets wiring
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.
Feedback + observability flow (/feedback-observability run, 2026-07-21)
Implements the standing feedback+observability prompt, self-scoped to what caramel actually has: Sentry + usesend email + Better Auth + sonner + withRoute + Playwright/Vitest, and wires PostHog (org self-hosted, posthog.devino.ca) — closing the "PostHog dark on dev" punch-list item from the 2026-07-16 compose cutover. Mastra / CopilotKit / RevenueCat / Turnstile sections don't apply (not in this app).
What landed (3 commits)
39f97f9PostHog foundationPOSTHOG_DATASET=production|e2e|disabledruntime isolation (server env +NEXT_PUBLIC_POSTHOG_DATASETmirror, boot fail-fast on mismatch). The Playwright-only query READ key is banned from app env — env.ts fail-fasts if it appears in any mode.posthog-js@1.405.3+posthog-node@5.46.0(exact-pinned). Browser provider inproviders.tsx: pageviews, session replay (inputs masked, same selectors as Sentry replay), super propsapp_id:'caramel'/app_version/environment/platform:'web'; identify = Better Auth user id (never email), reset on logout. Server capture viacaptureServerEvent(posthog-nodecaptureImmediate, never throws, returns checked boolean).posthog_session_id/posthog_distinct_idin Sentry context (high-cardinality),app_idas tag (low-cardinality).reportUserVisibleFailure(): exact per-callsentry_event_id(never global last-event) +user_visible_operation_failedPostHog event + per-fingerprint session rate limit.window.__CARAMEL_E2E__handshake registerstest_run_id/test_scenariosuper props + synthetic identity;opt_out_useragent_filteronly in e2e dataset (prod bot filtering untouched).ca1de2fSupport flow/supportpage (login problems reportable without auth) +POST /api/supportvia withRoute (mutation rate-limit, origin gate, zod, honeypotwebsitefield, length caps).feedback_idUUID per submission, client-generated, reused on retry, shared verbatim across the PostHogsupport_request_submittedevent and the support email (subject + body). Logged-in users' email comes from the session (server-side override; never re-asked).sendEmail(extended withreplyTo+ realtext): customer email is Reply-To, never sender; body carries feedback id, type, message, expected outcome, app/route/version/environment/platform, user id, posthog ids, sentry_event_id when present. Destination:SUPPORT_EMAIL_TO(defaultsupport@unotes.net, same inbox sites/suggest already mails).<dialog>support form carrying the exact sentry_event_id; wired to the two genuine blocked-action sites (coupons load failure, suggestion submit failure); once per fingerprint per session.support_request_submittedevent capture;POSTHOG_SUPPORT_SURVEY_IDnoted in code as the future swap-in (no invented IDs).10175beE2E + CIe2e/support/posthog.ts: read-key HogQL query helper against shared project #Shared_Apps_E2E_Testing (id 25), bounded polling (no fixed sleeps), key never logged.e2e/support-flow.spec.ts(4 tests): public render · anonymous submit verified by a real ingested PostHog row (feedback_id + app_id + environment:e2e + test_run_id matched — a 200 from /api/support is NOT accepted as proof) · browser$identifywith synthetice2e:caramel:<run>:<scenario>identity verified in project 25 · double-submit/retry feedback_id reuse (route-stubbed, ungated).e2e-pr: dataset=e2e env + 4 repo secrets (set + verified viagh secret list). The app process never sees the read key (blanked inplaywright.config.tswebServer.env).e2e-pushwiring deliberately deferred (TODO in workflow) until this merges + dev redeploys.Verification evidence
SUPPORT_EMAIL_TO=aladdin@devino.ca→ route returned{ok:true, email:'ok'}→ message confirmed in the Gmail inbox (subject[Caramel support] problem — 41c7c0d6-…, matching feedback_id, Reply-To=customer). No real customers emailed; e2e specs submit without wants_reply.pnpm lint(eslint) exits 1 on origin/dev too — 2 pre-existingno-consolewarnings in caramel-extension, unrelated to this PR.Deploy/env state (dev only; prod untouched per gate)
POSTHOG_DATASET=e2e+ shared-project capture pair (pre-launch dataset rule: no real users yet → dev captures into the shared test project, not a prod project). Inert until this merges; first dev deploy after merge lights PostHog up.POSTHOG_DATASET=production+NEXT_PUBLIC_POSTHOG_HOST/KEY(prod capture token) + redeploy. Read key never goes into any deployment env.Manual dashboard follow-ups (PostHog UI)
POSTHOG_SUPPORT_SURVEY_ID(today the flow capturessupport_request_submitted).support_request_submitted,user_visible_operation_failed, thumbs-equivalents when an AI chat surface exists.Known deliberate leftovers
e2e-pushPostHog wiring: TODO in checks-app.yml (enable after merge+deploy).disableddataset the matrix reportsanalytics:'failed'(cosmetic — capture is deliberately off there; prod/e2e datasets unaffected).🤖 Generated with Claude Code
https://claude.ai/code/session_01YKAWGPo8K34KZ1epqXE7WV