Skip to content

Release: identity segmentation, SDK reliability, ingest gates, OG rebrand#540

Merged
izadoesdev merged 31 commits into
mainfrom
staging
Jul 4, 2026
Merged

Release: identity segmentation, SDK reliability, ingest gates, OG rebrand#540
izadoesdev merged 31 commits into
mainfrom
staging

Conversation

@izadoesdev

@izadoesdev izadoesdev commented Jul 4, 2026

Copy link
Copy Markdown
Member

What's in this release

Identity & segmentation

  • Trait filters everywhere: trait:<key> filters resolve to identified-user segments server-side and apply across query builders (users page UI with key/value picker, agent get_data, all custom-events builders). Builders that can't segment return an explicit error instead of silently unsegmented data.
  • Revenue on user detail: new profile_revenue builder attributes transactions via profile id, device set, and session stitching; revenue section on the user detail page.
  • New profiles.traitKeys / profiles.traitValues endpoints for filter autocomplete.

SDK reliability

  • Calls made before the tracker script loads are queued and flushed on load instead of silently dropped (fixes identify calls racing the async script).
  • Methods missing from a stale cached script warn and no-op instead of throwing console errors.

Tracker

  • Segment-aware pathname masking (maskPathname), with unit + e2e coverage; dashboard now masks its own high-cardinality paths and drops website id/name tracking attributes.

Ingest hardening

  • API-key /track and /identify paths now enforce website existence, org match, and ACTIVE status (paused sites stop ingesting).

Perf & fixes

  • Autumn billing proxy reads cached in Redis (30s customer / 5min plans) with write-path invalidation.
  • Users page resolves display names/emails server-side in one round trip (no more profile-id flicker); loading-state machine simplified.
  • Insights queries persist to the localStorage cache.
  • Builder EXPLAIN sweep now runs with every allowed filter applied and its reachability probe fixed (was silently skipping).

Docs & brand

  • Payments integration page (Stripe/Paddle webhook setup + attribution metadata).
  • OG images rebranded with the LT Superior brand kit across dashboard and docs.

Summary by cubic

Release adds trait-based identity segmentation across queries, improves SDK/tracker reliability, hardens API‑key ingest (now requires org‑scoped keys) with org/status checks, and refreshes OG branding. It also surfaces user revenue, caches billing reads, and persists key dashboard queries with owner‑scoped, session‑gated hydration for a faster UX. Ships @databuddy/sdk 2.6.0.

  • New Features

    • Trait filters trait:<key> resolve to identified-user segments across query builders; unsupported builders return clear errors.
    • Revenue on profile: new profile_revenue builder with transactions; revenue section on the user detail page.
    • Trait filter UX: autocomplete via profiles.traitKeys and profiles.traitValues.
    • Tracker + dashboard: segment-aware maskPathname; dashboard masks high‑cardinality paths and drops website id/name tracking attributes.
    • Dashboard caching + brand: persist select query caches to localStorage with owner‑scoped, session‑gated hydration; OG images rebranded with the LT Superior kit and payments docs added.
  • Bug Fixes

    • SDK: calls before the tracker script loads are queued and flushed; missing methods on a stale cached script warn and no‑op. Released as @databuddy/sdk 2.6.0.
    • Ingest: API keys must be org‑scoped; /track and /identify enforce website existence, org match, ACTIVE status; query website_id is honored.
    • Billing: Autumn proxy reads cached in Redis with write‑path invalidation; skip invalidation on read‑only methods.
    • Querying: builder EXPLAIN applies all allowed filters; ClickHouse reachability probe fixed; empty trait in/not_in filters short‑circuit; trait autocomplete ordering stabilized.
    • Dashboard: users list resolves names/emails server‑side to remove flicker; persisted cache cleared on logout/session change.
    • Tracker: maskPathname enforces middle fragments in multi‑wildcard patterns; tests added.
    • Docs OG: memoized font loading for faster image generation.

Written for commit 3eb00a3. Summary will update on new commits.

Review in cubic

@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Vercel for GitHub.

Project Deployment Actions Updated (UTC)
dashboard (staging) Ready Ready Preview, Comment Jul 4, 2026 3:48pm
databuddy-status Ready Ready Preview, Comment Jul 4, 2026 3:48pm
documentation (staging) Ready Ready Preview, Comment Jul 4, 2026 3:48pm

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Important

Review skipped

Auto reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: ASSERTIVE

Plan: Pro

Run ID: ce3ff417-811e-4ade-9bc5-2ecedabf5cb6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch staging

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@unkey-deploy

unkey-deploy Bot commented Jul 4, 2026

Copy link
Copy Markdown

The latest updates on your projects. Learn more about Unkey Deploy

Name Status Preview Inspect Updated (UTC)
api (preview) Ready Visit Preview Inspect Jul 4, 2026 3:47pm

@socket-security

socket-security Bot commented Jul 4, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Added@​tanstack/​query-sync-storage-persister@​5.100.101001006999100

View full report

Comment thread packages/ai/src/ai/tools/get-data.ts Fixed
@dosubot

dosubot Bot commented Jul 4, 2026

Copy link
Copy Markdown

📄 Knowledge review

🆕 New pages

1 new page was drafted from this PR.

Page Library
Query Filtering by User Traits Databuddy's Space

Leave Feedback Ask Dosu about Databuddy Add Dosu to your team

@vercel
vercel Bot temporarily deployed to staging – dashboard July 4, 2026 15:03 Inactive
@vercel
vercel Bot temporarily deployed to staging – documentation July 4, 2026 15:03 Inactive
@railway-app
railway-app Bot temporarily deployed to Databuddy / production July 4, 2026 15:03 Inactive

@cubic-dev-ai cubic-dev-ai 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.

2 issues found across 14 files (changes from recent commits).

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/tracker/src/core/utils.ts">

<violation number="1" location="packages/tracker/src/core/utils.ts:76">
P2: Root-path masking can be rewritten to a wildcard path when using `/**`, which changes `/` into `/*` and can mis-group homepage traffic. This happens because the `**` check counts the trailing empty split segment as remaining path content; checking for non-empty remaining segments avoids masking `/`.</violation>
</file>

<file name="apps/dashboard/components/providers/session-guard.tsx">

<violation number="1" location="apps/dashboard/components/providers/session-guard.tsx:15">
P2: If `clearPersistedQueryCache()` throws (e.g., localStorage access denied), the subsequent `authClient.signOut()` and redirect never run, leaving the user stuck on a broken page with no session. Wrap in try-catch so a cache-clearing failure doesn't block the mandatory redirect.</violation>
</file>

<file name="apps/dashboard/app/(dby)/dby/og/route.tsx">

<violation number="1" location="apps/dashboard/app/(dby)/dby/og/route.tsx:144">
P2: OG image requests now re-read all three font files on every hit, which adds avoidable IO latency and load for a hot endpoint. Caching the font promise at module scope (and reusing it in `fonts`) would keep the branding change while avoiding per-request filesystem work.</violation>
</file>

<file name="apps/docs/lib/og.tsx">

<violation number="1" location="apps/docs/lib/og.tsx:6">
P2: Two newly added brand files (`apps/docs/lib/og.tsx` and `apps/dashboard/app/(dby)/dby/og/brand.tsx`) are exact duplicates — the same SVG components, color palette, and font-loading logic. Since this is a monorepo with a `packages/` directory for shared code, the duplicate will drift over time as the brand evolves. Consider extracting the shared OG brand primitives (colors, font loading, logo SVGs) into a shared package or library so both apps consume a single source of truth. This keeps future brand updates atomic and prevents subtle visual inconsistencies between the docs and dashboard OG images.</violation>

<violation number="2" location="apps/docs/lib/og.tsx:24">
P1: The memoized `loadOgFonts()` caches a rejected promise permanently. If `readOgFonts()` fails once (e.g., transient filesystem error), `ogFontsPromise` holds a rejected Promise object, which is not `null`/`undefined`, so `ogFontsPromise ??= readOgFonts()` is skipped on every subsequent call. All OG-image requests then fail until the process restarts. Consider resetting `ogFontsPromise` to `undefined` in a `.catch()` handler so the next call retries the read.</violation>
</file>

<file name="apps/dashboard/app/(dby)/dby/og/brand.tsx">

<violation number="1" location="apps/dashboard/app/(dby)/dby/og/brand.tsx:24">
P2: Memoizing the font-read promise with `??=` improves performance, but it also permanently caches a rejected promise if the first `readFile` fails (e.g., transient I/O error during a cold-start container). Once `ogFontsPromise` is set to a rejected promise, every subsequent call to `loadOgFonts()` will immediately throw without retrying, breaking OG image generation for the lifetime of the process. Consider resetting the cache on rejection so the next request can retry.</violation>
</file>

Shadow auto-approve: would not auto-approve because issues were found.
Tip: Review your code locally with the cubic CLI to iterate faster.

Re-trigger cubic

Comment thread apps/docs/lib/og.tsx
let ogFontsPromise: ReturnType<typeof readOgFonts> | undefined;

export function loadOgFonts() {
ogFontsPromise ??= readOgFonts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P1: The memoized loadOgFonts() caches a rejected promise permanently. If readOgFonts() fails once (e.g., transient filesystem error), ogFontsPromise holds a rejected Promise object, which is not null/undefined, so ogFontsPromise ??= readOgFonts() is skipped on every subsequent call. All OG-image requests then fail until the process restarts. Consider resetting ogFontsPromise to undefined in a .catch() handler so the next call retries the read.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/docs/lib/og.tsx, line 24:

<comment>The memoized `loadOgFonts()` caches a rejected promise permanently. If `readOgFonts()` fails once (e.g., transient filesystem error), `ogFontsPromise` holds a rejected Promise object, which is not `null`/`undefined`, so `ogFontsPromise ??= readOgFonts()` is skipped on every subsequent call. All OG-image requests then fail until the process restarts. Consider resetting `ogFontsPromise` to `undefined` in a `.catch()` handler so the next call retries the read.</comment>

<file context>
@@ -18,7 +18,14 @@ export const OG_COLORS = {
+let ogFontsPromise: ReturnType<typeof readOgFonts> | undefined;
+
+export function loadOgFonts() {
+	ogFontsPromise ??= readOgFonts();
+	return ogFontsPromise;
+}
</file context>
Suggested change
ogFontsPromise ??= readOgFonts();
ogFontsPromise ??= readOgFonts().catch((err) => {
ogFontsPromise = undefined;
throw err;
});

let ogFontsPromise: ReturnType<typeof readOgFonts> | undefined;

export function loadOgFonts() {
ogFontsPromise ??= readOgFonts();

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

P2: Memoizing the font-read promise with ??= improves performance, but it also permanently caches a rejected promise if the first readFile fails (e.g., transient I/O error during a cold-start container). Once ogFontsPromise is set to a rejected promise, every subsequent call to loadOgFonts() will immediately throw without retrying, breaking OG image generation for the lifetime of the process. Consider resetting the cache on rejection so the next request can retry.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At apps/dashboard/app/(dby)/dby/og/brand.tsx, line 24:

<comment>Memoizing the font-read promise with `??=` improves performance, but it also permanently caches a rejected promise if the first `readFile` fails (e.g., transient I/O error during a cold-start container). Once `ogFontsPromise` is set to a rejected promise, every subsequent call to `loadOgFonts()` will immediately throw without retrying, breaking OG image generation for the lifetime of the process. Consider resetting the cache on rejection so the next request can retry.</comment>

<file context>
@@ -18,7 +18,14 @@ export const OG_COLORS = {
+let ogFontsPromise: ReturnType<typeof readOgFonts> | undefined;
+
+export function loadOgFonts() {
+	ogFontsPromise ??= readOgFonts();
+	return ogFontsPromise;
+}
</file context>
Suggested change
ogFontsPromise ??= readOgFonts();
ogFontsPromise ??= readOgFonts().catch((err) => {
ogFontsPromise = undefined;
throw err;
});

@cubic-dev-ai cubic-dev-ai 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.

0 issues found across 1 file (changes from recent commits).

Shadow auto-approve: would not auto-approve. Auto-approval blocked by 6 unresolved issues from previous reviews.

Re-trigger cubic

@izadoesdev
izadoesdev merged commit 676b576 into main Jul 4, 2026
22 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant