Skip to content

feat: org analytics + devpass profile updates - #2833

Merged
smakosh merged 17 commits into
mainfrom
feat/org-analytics-devpass-profile
Jun 26, 2026
Merged

smakosh merged 17 commits into
mainfrom
feat/org-analytics-devpass-profile

Conversation

@smakosh

@smakosh smakosh commented Jun 26, 2026

Copy link
Copy Markdown
Member

Summary

A batch of dashboard + DevPass improvements.

Org-level analytics (apps/ui) — Enterprise

  • New Organization analytics page at dashboard/[orgId]/org/analytics (sidebar → Organization → Analytics). Summary stat cards (total spend / requests / tokens) plus cost & usage charts aggregated across every project in the org.
  • Reads exclusively from the hourly rollup tables (projectHourlyStats, projectHourlyModelStats, apiKeyHourlyStats) — never raw logs.
  • New GET /analytics/activity endpoint, gated by requireEnterpriseAdmin, supporting groupBy=model | project | apiKey. Models collapse to their canonical id server-side so a model routed through several providers is one series.
  • Group-by toggle (model / project / API key) on the page, mirroring the existing group-by-API-key control on Model Usage.

Enterprise-only sidebar indicators

  • Small amber "Ent" badge next to enterprise-only items (Analytics, Guardrails, Compliance, Security Events, Audit Logs) — shown only to non-enterprise orgs so they can tell what's gated before clicking.

Enterprise contact form

  • New deployment preference field: Self-hosted / Cloud (managed) / Not sure yet.
  • Threaded through the form schema, the /public/contact/enterprise API, the enterprise_contact_submission table (new nullable deployment column + migration), the notification email, and the Discord webhook.

DevPass profiles (apps/code)

  • README badge moved off the public profile and onto the edit-profile page only (it's an owner tool, not visitor-facing).
  • Models section reworked: shows canonical models with the provider-family logo (e.g. Alibaba for Qwen) regardless of which provider served the request, each card links through to the model page, and the redundant Providers section was removed.

Database

  • Adds deployment (nullable text) to enterprise_contact_submission. Migration: 1782486651_wealthy_tempest.sql.

Testing

  • pnpm build (full monorepo) ✅
  • pnpm format
  • API OpenAPI + typed UI client regenerated.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features
    • Added Enterprise “Organization Analytics” with date-range selection and activity charts (daily totals + per-day breakdown) with group-by: Model, Project, or API key.
    • Added the public profile “Powered by DevPass” README badge sharing option (when the profile is public).
  • Improvements
    • Profile “Models” now display canonicalized names/icons with improved linking; removed README badge from the wrapped share toolkit.
    • Enterprise contact form now supports an optional deployment preference, included in emails, notifications, and tracking.
    • Enterprise members/admin views now show a proper loading state while data resolves.
  • Bug Fixes
    • Fixed dashboard sidebar active highlighting between org-scoped and project-scoped routes.
  • Documentation
    • Added an “Organization Analytics” help page.

Org-level analytics (apps/ui):
- New enterprise-only Organization analytics page at org/analytics
  with summary stats and cost/usage charts aggregated across every
  project, read from the hourly rollup tables (not raw logs).
- New GET /analytics/activity endpoint (enterprise admin only) with a
  groupBy of model | project | api key; models collapse to canonical
  ids server-side.
- Group-by toggle (model / project / API key) on the org page, mirroring
  the existing group-by-API-key control.
- Small "Ent" indicator on enterprise-only sidebar items for non-
  enterprise orgs (Analytics, Guardrails, Compliance, Security Events,
  Audit Logs).

Enterprise contact form:
- Add a deployment preference field (self-host / cloud / not sure yet)
  to the form, API schema, enterprise_contact_submission table, the
  notification email, and the Discord webhook.

DevPass profiles (apps/code):
- Move the GitHub README badge off the public profile to the edit page.
- Models section now shows canonical models with the provider-family
  logo (e.g. Alibaba for Qwen) regardless of serving provider, is
  clickable through to the model page, and drops the Providers section.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

Walkthrough

Adds organization activity analytics, deployment metadata for enterprise contact submissions, canonical profile model grouping with README badge sharing, sidebar enterprise indicators, and a members loading state.

Changes

Organization activity analytics

Layer / File(s) Summary
Activity endpoint
apps/api/src/routes/analytics.ts
Adds the /activity response schema, UTC date helpers, access checks, and daily aggregation by model, project, or API key.
Analytics cards
apps/ui/src/components/analytics/chart-helpers.ts, apps/ui/src/components/analytics/dimension-usage-*.tsx
Adds dimension aggregation helpers plus the bar and area chart cards for grouped activity over time.
Dashboard page wiring
apps/ui/src/app/dashboard/[orgId]/org/analytics/page.tsx, apps/ui/src/app/dashboard/[orgId]/org/analytics/org-analytics-client.tsx
Adds the org analytics page, query-param management, /analytics/activity fetching, and enterprise/admin rendering states.
Analytics documentation
apps/docs/content/learn/org-analytics.mdx, apps/docs/content/learn/meta.json
Adds the Organization Analytics learn page and registers it in the docs navigation.

Enterprise contact deployment

Layer / File(s) Summary
Contact form field
apps/ui/src/components/enterprise/contact.tsx
Adds the deployment select, validation, defaults, and submission tracking payloads.
Server persistence and notifications
apps/api/src/routes/public-contact.ts, apps/api/src/utils/discord.ts
Accepts deployment on the public contact route, persists it, and includes the resolved label in email and Discord payloads.
Database migration
packages/db/src/schema.ts, packages/db/migrations/1782486651_wealthy_tempest.sql, packages/db/migrations/meta/_journal.json
Adds the deployment column to the enterprise contact submission table and records the migration.

Profile canonical models and badge sharing

Layer / File(s) Summary
Canonical model resolver
apps/code/src/lib/model-family.ts
Adds canonical model id resolution, lookup, icon overrides, and the returned canonical model shape.
Canonical model rendering
apps/code/src/components/profile/ProfileView.tsx
Groups profile models by canonical id and renders the Models section from the aggregated canonical records.
README badge sharing
apps/code/src/components/profile/ProfileReadmeBadge.tsx, apps/code/src/app/profile/ProfilePageClient.tsx, apps/code/src/components/profile/ProfileWrapped.tsx
Adds the README badge component, shows it on public profiles, and removes badge sharing from the wrapped share controls.

Enterprise navigation badges

Layer / File(s) Summary
Badge indicator and flags
apps/ui/src/components/dashboard/dashboard-sidebar.tsx
Adds the enterprise indicator, extends org-nav item props, and marks Members and Audit Logs as enterprise-only.
Sidebar enterprise gating
apps/ui/src/components/dashboard/dashboard-sidebar.tsx
Passes the org plan into the sidebar section and adjusts route matching across org-scoped and project-scoped dashboard paths.

Enterprise members loading state

Layer / File(s) Summary
Membership loading placeholder
apps/ui/src/app/dashboard/[orgId]/org/members/members-client.tsx
Adds a dedicated loading state for enterprise membership resolution before admin gating runs.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~60 minutes

Possibly related PRs

  • theopenco/llmgateway#2602: Adds the same Learn navigation file updated here (apps/docs/content/learn/meta.json) with another docs section entry.
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.88% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the two main change areas: organization analytics and DevPass profile updates.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/org-analytics-devpass-profile

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.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 7

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
apps/ui/src/components/enterprise/contact.tsx (1)

82-99: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Use the generated API client for this submit path.

This PR changes the request shape, but the form still posts with raw fetch(), so the new deployment contract is not tied to the generated Hono client and can drift silently. Please switch this call to useFetchClient()/useApi() here.

As per coding guidelines, "In frontend apps, always use the generated typed API client (useFetchClient() or useApi() from @/lib/fetch-client) to call the Hono API, never use raw fetch() for API calls."

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/ui/src/components/enterprise/contact.tsx` around lines 82 - 99, The
enterprise contact form submit path still uses raw fetch instead of the
generated typed Hono client. Update the onSubmit flow in ContactForm to use
useFetchClient() or useApi() from `@/lib/fetch-client` for the enterprise contact
request, and keep the payload aligned with the new deployment field through the
typed client so this contract stays source-of-truth and cannot drift.

Source: Coding guidelines

🧹 Nitpick comments (1)
apps/ui/src/components/dashboard/dashboard-sidebar.tsx (1)

350-352: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Remove these explanatory comments.

These blocks just restate what EnterpriseIndicator and showEnterpriseBadge = !isEnterprise already make obvious, so they add noise without preserving extra context. As per coding guidelines, **/*.{ts,tsx,js,jsx}: No unnecessary code comments.

Also applies to: 425-426

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/ui/src/components/dashboard/dashboard-sidebar.tsx` around lines 350 -
352, Remove the unnecessary explanatory comments in dashboard-sidebar.tsx around
the EnterpriseIndicator usage and the showEnterpriseBadge = !isEnterprise logic;
they only restate what the code already makes clear. Keep the implementation
as-is, but delete those comment blocks so the Sidebar rendering and enterprise
badge conditions remain self-explanatory without extra noise.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/api/src/routes/analytics.ts`:
- Around line 539-550: The eachDay() helper is silently truncating date ranges
after 1000 iterations, which can produce partial analytics series. Update the
range handling in analytics.ts to validate the requested span before calling
eachDay(), and reject oversized query-param windows instead of padding a
shortened result. Keep the fix anchored around eachDay() and the route logic
that builds the activity series/summary cards so the SQL totals and returned
buckets always cover the same requested range.
- Around line 803-810: The API-key breakdown query is filtering out deleted keys
because the `leftJoin` in `analytics.ts` is effectively turned into an inner
join by the `inArray(tables.apiKey.keyType, ...)` condition in the `where`
clause. Update the `apiKeyHourlyStats` query so the key-type filter is applied
on the joined `apiKey` side without excluding null joins, allowing
`row.description ?? "Deleted key"` to still label historical rows for removed
keys.

In `@apps/code/src/components/profile/ProfileReadmeBadge.tsx`:
- Around line 6-17: The badge snippet in ProfileReadmeBadge is hard-coding the
public origin, so copied Markdown always points to the production host. Update
ProfileReadmeBadge to receive the public base URL from config or page state
instead of using SITE_URL, and build profileUrl and badgeMarkdown from that
injected origin so preview, staging, and self-hosted deployments generate
correct links.

In `@apps/code/src/components/profile/ProfileView.tsx`:
- Around line 51-60: The fallback icon key in ProfileView’s model aggregation is
using resolveCanonicalModel(row.id).iconKey even when the model is unresolved,
which leaves getProviderIcon() with a raw model string instead of a provider
key. Update the branch that builds the byCanonical entry so unresolved rows use
row.provider as the iconKey fallback, while keeping resolved model data from
resolveCanonicalModel and preserving the existing aggregation logic in
ProfileView.

In `@apps/ui/src/app/dashboard/`[orgId]/org/analytics/org-analytics-client.tsx:
- Around line 132-139: The `isAdmin` check in `org-analytics-client.tsx` treats
`useTeamMembers()` as unauthorized while `teamData` is still undefined, which
causes a brief denial state and keeps analytics queries disabled on first
render. Update the logic around `currentUserRole`/`isAdmin` to distinguish
“membership still loading” from “not admin” and render a neutral/loading state
until team membership is resolved. Apply the same loading-aware handling in the
other affected analytics sections referenced by the existing `isAdmin`/query
gating logic.

In `@apps/ui/src/components/analytics/chart-helpers.ts`:
- Around line 211-243: The top-N selection in aggregateByDimension is still
always sorted by cost, which makes Requests and Tokens views rank the wrong
dimensions. Update the ranking/slicing logic in aggregateByDimension (and the
related helper in the other referenced block) to accept the active metric and
sort by that metric before applying the limit, while still accumulating all
totals correctly.

In `@packages/db/migrations/1782486651_wealthy_tempest.sql`:
- Line 1: The new deployment column on enterprise_contact_submission is
currently unconstrained text, so update the migration to add a database-level
check that limits values to the same enum-like set used elsewhere: self_host,
cloud, and not_sure. Keep the change localized to this migration and make sure
the constraint matches the existing deployment contract enforced by the UI,
route schema, and Drizzle model so invalid values cannot be stored.

---

Outside diff comments:
In `@apps/ui/src/components/enterprise/contact.tsx`:
- Around line 82-99: The enterprise contact form submit path still uses raw
fetch instead of the generated typed Hono client. Update the onSubmit flow in
ContactForm to use useFetchClient() or useApi() from `@/lib/fetch-client` for the
enterprise contact request, and keep the payload aligned with the new deployment
field through the typed client so this contract stays source-of-truth and cannot
drift.

---

Nitpick comments:
In `@apps/ui/src/components/dashboard/dashboard-sidebar.tsx`:
- Around line 350-352: Remove the unnecessary explanatory comments in
dashboard-sidebar.tsx around the EnterpriseIndicator usage and the
showEnterpriseBadge = !isEnterprise logic; they only restate what the code
already makes clear. Keep the implementation as-is, but delete those comment
blocks so the Sidebar rendering and enterprise badge conditions remain
self-explanatory without extra noise.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: bbef82b7-928e-48bb-9307-e555031cd9d1

📥 Commits

Reviewing files that changed from the base of the PR and between 7ec8d88 and 9758f1c.

📒 Files selected for processing (19)
  • apps/api/src/routes/analytics.ts
  • apps/api/src/routes/public-contact.ts
  • apps/api/src/utils/discord.ts
  • apps/code/src/app/profile/ProfilePageClient.tsx
  • apps/code/src/components/profile/ProfileReadmeBadge.tsx
  • apps/code/src/components/profile/ProfileView.tsx
  • apps/code/src/components/profile/ProfileWrapped.tsx
  • apps/code/src/lib/model-family.ts
  • apps/ui/src/app/dashboard/[orgId]/org/analytics/org-analytics-client.tsx
  • apps/ui/src/app/dashboard/[orgId]/org/analytics/page.tsx
  • apps/ui/src/components/analytics/chart-helpers.ts
  • apps/ui/src/components/analytics/dimension-usage-card.tsx
  • apps/ui/src/components/analytics/dimension-usage-over-time-card.tsx
  • apps/ui/src/components/dashboard/dashboard-sidebar.tsx
  • apps/ui/src/components/enterprise/contact.tsx
  • packages/db/migrations/1782486651_wealthy_tempest.sql
  • packages/db/migrations/meta/1782486651_snapshot.json
  • packages/db/migrations/meta/_journal.json
  • packages/db/src/schema.ts

Comment thread apps/api/src/routes/analytics.ts
Comment on lines +803 to +810
.leftJoin(tables.apiKey, eq(tables.apiKey.id, apiKeyHourlyStats.apiKeyId))
.where(
and(
inArray(apiKeyHourlyStats.projectId, projectIds),
inArray(tables.apiKey.keyType, ["user", "end_user_customer"]),
gte(apiKeyHourlyStats.hourTimestamp, startDate),
lte(apiKeyHourlyStats.hourTimestamp, endDate),
),

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

The API-key breakdown drops deleted keys entirely.

The leftJoin() is nullified by inArray(tables.apiKey.keyType, ...) in the WHERE clause, so historical rows for deleted keys are filtered out before row.description ?? "Deleted key" can run. That makes /activity?groupBy=apiKey under-report usage whenever keys have been removed.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/api/src/routes/analytics.ts` around lines 803 - 810, The API-key
breakdown query is filtering out deleted keys because the `leftJoin` in
`analytics.ts` is effectively turned into an inner join by the
`inArray(tables.apiKey.keyType, ...)` condition in the `where` clause. Update
the `apiKeyHourlyStats` query so the key-type filter is applied on the joined
`apiKey` side without excluding null joins, allowing `row.description ??
"Deleted key"` to still label historical rows for removed keys.

Comment thread apps/code/src/components/profile/ProfileReadmeBadge.tsx Outdated
Comment thread apps/code/src/components/profile/ProfileView.tsx
Comment thread apps/ui/src/components/analytics/chart-helpers.ts
Comment thread packages/db/migrations/1782486651_wealthy_tempest.sql Outdated
@smakosh

smakosh commented Jun 26, 2026

Copy link
Copy Markdown
Member Author

✅ Verified locally against seeded data

Ran the full stack (pnpm setup + API/UI dev servers) against the demo seed and signed in to the enterprise DataFlow AI org (3 projects, ~18.9k hourly-rollup rows).

Org-level analytics (/dashboard/[orgId]/org/analytics):

  • Summary stats roll up across every project — $1,407.40 spend · 54,447 requests · 98.1M tokens.
  • Breakdown by model → stacked "Cost by model over time" + top-models bar chart.
  • Breakdown by project → "Cost by project over time" across Production API / Internal Chatbot / Staging Environment, plus a per-project bar chart ranking spend.
  • Breakdown by API key → same shape, keyed by key description.
  • GET /analytics/activity reads only the hourly rollup tables; confirmed the JSON returns clean per-project daily buckets.

Enterprise gating + sidebar indicators (free org):

  • Org-only pages (Analytics, Guardrails, Compliance, Security Events) show the amber ENT badge; the analytics page shows the "Enterprise Feature → Contact Sales" upsell.

A ~13s screen recording of the org-analytics + breakdown-by-project flow was captured (GitHub doesn't accept video uploads via CLI — it can be dragged into this PR from the recording).

- Project and org nav items can share a trailing segment (e.g. /analytics),
  so gate isActive on whether the route is org-scoped — otherwise the project
  "Analytics" item also highlighted on the org analytics page.
- Enterprise indicator is now an icon-only subtle blue mark (dropped the
  "Ent" label, which read as noise).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
apps/ui/src/components/dashboard/dashboard-sidebar.tsx (1)

350-352: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Remove these explanatory comments.

They restate what the nearby JSX/logic already makes clear, and this repo explicitly avoids unnecessary comments. As per coding guidelines, "No unnecessary code comments".

Also applies to: 965-968

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/ui/src/components/dashboard/dashboard-sidebar.tsx` around lines 350 -
352, Remove the unnecessary explanatory comments in dashboard-sidebar.tsx around
the sidebar entry marker logic; the nearby JSX and conditional rendering already
make the intent clear. Delete the comment block near the enterprise-plan
indicator and the similar comment in the collapsed-sidebar section, keeping the
actual rendering logic in the dashboard sidebar component unchanged.

Source: Coding guidelines

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Nitpick comments:
In `@apps/ui/src/components/dashboard/dashboard-sidebar.tsx`:
- Around line 350-352: Remove the unnecessary explanatory comments in
dashboard-sidebar.tsx around the sidebar entry marker logic; the nearby JSX and
conditional rendering already make the intent clear. Delete the comment block
near the enterprise-plan indicator and the similar comment in the
collapsed-sidebar section, keeping the actual rendering logic in the dashboard
sidebar component unchanged.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: caeef04f-783b-4745-931e-eb07e0f954ec

📥 Commits

Reviewing files that changed from the base of the PR and between 9758f1c and 59ca99b.

📒 Files selected for processing (1)
  • apps/ui/src/components/dashboard/dashboard-sidebar.tsx

smakosh and others added 2 commits June 26, 2026 18:31
- Sidebar enterprise indicator now uses the Building2 icon (matching the
  navbar Resources → Enterprise item) instead of Sparkles.
- New knowledge-base page learn/org-analytics.mdx documenting Organization
  Analytics + breakdown by model/project/API key, with light/dark
  screenshots, added to the learn nav.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@steebchen

Copy link
Copy Markdown
Member

Images automagically compressed by Calibre's image-actions

Compression reduced images by 68.5%, saving 196.7 KB.

Filename Before After Improvement Visual comparison
apps/docs/public/learn/org-analytics-dark.png 143.0 KB 43.4 KB 69.6% View diff
apps/docs/public/learn/org-analytics-light.png 144.3 KB 47.1 KB 67.3% View diff

@steebchen

Copy link
Copy Markdown
Member

Images automagically compressed by Calibre's image-actions

Compression reduced images by 8.6%, saving 4.1 KB.

Filename Before After Improvement Visual comparison
apps/docs/public/learn/org-analytics-light.png 47.1 KB 43.1 KB 8.6% View diff

1 image did not require optimisation.

@coderabbitai

coderabbitai Bot commented Jun 26, 2026

Copy link
Copy Markdown
Contributor

Caution

Failed to replace (edit) comment. This is likely due to insufficient permissions or the comment being deleted.

Error details
{}

- analytics: cap org-activity window at 366 days and reject larger
  spans (400) instead of eachDay() silently truncating, so SQL totals
  and returned daily buckets always cover the same range.
- ProfileReadmeBadge: take the public origin via a baseUrl prop instead
  of a hard-coded host, so preview/staging/self-hosted builds emit
  correct links.
- ProfileView: unresolved models fall back to the serving provider's
  logo instead of passing a raw model string to getProviderIcon.
- analytics charts: aggregateByDimension / buildDimensionTimeseries now
  rank by the active metric, so Requests/Tokens views show the right
  top-N (not top spenders).
- org & member analytics: distinguish "membership loading" from "not
  admin" so the denial card no longer flashes before team resolves.
- enterprise contact form: submit via the generated typed Hono client
  instead of raw fetch.
- sidebar: drop redundant explanatory comments.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@apps/code/src/components/profile/ProfileReadmeBadge.tsx`:
- Around line 21-22: The README badge generation in ProfileReadmeBadge should
not depend on a client-only baseUrl from window.location.origin, since that is
empty during SSR and causes relative markdown plus hydration flicker. Update the
caller and ProfileReadmeBadge to require a stable absolute public origin before
rendering, and build profileUrl and badgeMarkdown from that server-resolved
baseUrl instead of deriving it at render time.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Pro

Run ID: 7eb20868-3b3b-4a8e-8bd6-61ddb9eda466

📥 Commits

Reviewing files that changed from the base of the PR and between 59ca99b and 8a14c65.

⛔ Files ignored due to path filters (2)
  • apps/docs/public/learn/org-analytics-dark.png is excluded by !**/*.png
  • apps/docs/public/learn/org-analytics-light.png is excluded by !**/*.png
📒 Files selected for processing (13)
  • apps/api/src/routes/analytics.ts
  • apps/code/src/app/profile/ProfilePageClient.tsx
  • apps/code/src/components/profile/ProfileReadmeBadge.tsx
  • apps/code/src/components/profile/ProfileView.tsx
  • apps/docs/content/learn/meta.json
  • apps/docs/content/learn/org-analytics.mdx
  • apps/ui/src/app/dashboard/[orgId]/org/analytics/org-analytics-client.tsx
  • apps/ui/src/app/dashboard/[orgId]/org/members/members-client.tsx
  • apps/ui/src/components/analytics/chart-helpers.ts
  • apps/ui/src/components/analytics/dimension-usage-card.tsx
  • apps/ui/src/components/analytics/dimension-usage-over-time-card.tsx
  • apps/ui/src/components/dashboard/dashboard-sidebar.tsx
  • apps/ui/src/components/enterprise/contact.tsx
✅ Files skipped from review due to trivial changes (1)
  • apps/docs/content/learn/meta.json
🚧 Files skipped from review as they are similar to previous changes (7)
  • apps/code/src/app/profile/ProfilePageClient.tsx
  • apps/ui/src/components/analytics/dimension-usage-card.tsx
  • apps/ui/src/components/analytics/dimension-usage-over-time-card.tsx
  • apps/code/src/components/profile/ProfileView.tsx
  • apps/api/src/routes/analytics.ts
  • apps/ui/src/app/dashboard/[orgId]/org/analytics/org-analytics-client.tsx
  • apps/ui/src/components/dashboard/dashboard-sidebar.tsx

Comment on lines +21 to +22
const profileUrl = `${baseUrl}/profiles/${username}`;
const badgeMarkdown = `[![Powered by DevPass](${baseUrl}/devpass-badge.svg)](${profileUrl})`;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Require a stable absolute baseUrl before rendering this snippet.

With the current caller, baseUrl comes from window.location.origin, which is "" during SSR. That makes the initial badge Markdown and preview image relative (/devpass-badge.svg, /profiles/...) and then flips them to absolute after hydration. For a README snippet, that first render is wrong and can also cause a hydration mismatch/flicker. Pass a server-resolved public origin into this component instead of deriving it from window at render time.

Also applies to: 41-41

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@apps/code/src/components/profile/ProfileReadmeBadge.tsx` around lines 21 -
22, The README badge generation in ProfileReadmeBadge should not depend on a
client-only baseUrl from window.location.origin, since that is empty during SSR
and causes relative markdown plus hydration flicker. Update the caller and
ProfileReadmeBadge to require a stable absolute public origin before rendering,
and build profileUrl and badgeMarkdown from that server-resolved baseUrl instead
of deriving it at render time.

smakosh and others added 5 commits June 26, 2026 19:15
- Order: Provider Keys, Your Discounts, then the enterprise cluster
  (Custom Models, Analytics, Guardrails, Compliance, Security Events,
  Master Keys), then Settings.
- Flag Custom Models, Master Keys, and the Members sub-item as
  enterprise-only.
- Replace the native title tooltip on the indicator with the Radix
  Tooltip (delayDuration=0 from the sidebar provider) so the hint is
  instant instead of the slow browser default.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Preferences, Policies, and Billing wrapped their content in an extra
max-w-3xl mx-auto container, so they rendered narrower than the rest of
the dashboard. Drop the width clamp (keep the vertical spacing) and
align the billing payment-status banner so they fill the content area
like every other page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Drop the leftover max-w-3xl mx-auto clamp on the Team page so it fills
the content area like the other org settings pages.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
enterprise_contact_submission.deployment is limited to
self_host/cloud/not_sure (NULL allowed) via a Drizzle check(), matching
the route/Zod schema and the text() enum. Column add + constraint ship
in a single migration (one migration per PR).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@smakosh
smakosh force-pushed the feat/org-analytics-devpass-profile branch from d85c71b to 2779b2e Compare June 26, 2026 17:58
smakosh and others added 2 commits June 26, 2026 20:12
- changelog: Organization-Wide Analytics (org-level rollup, breakdown by
  model/project/API key), with OG image.
- blog: enterprise LLM analytics announcement (cost by model, per-key,
  org-wide, and member analytics), enterprise-focused, with OG image.
- fix: dedupe changelog id 56 (claude-fable-5-access-suspended -> 62),
  which caused a duplicate React key on the changelog page.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@steebchen

Copy link
Copy Markdown
Member

Images automagically compressed by Calibre's image-actions

Compression reduced images by 77.1%, saving 2.0 MB.

Filename Before After Improvement Visual comparison
apps/ui/public/blog/enterprise-llm-analytics.png 1.3 MB 309.9 KB 76.6% View diff
apps/ui/public/changelog/organization-analytics.png 1.3 MB 287.3 KB 77.6% View diff

2 images did not require optimisation.

@steebchen

Copy link
Copy Markdown
Member

Images automagically compressed by Calibre's image-actions

Compression reduced images by 10.2%, saving 61.2 KB.

Filename Before After Improvement Visual comparison
apps/ui/public/blog/enterprise-llm-analytics.png 309.9 KB 277.8 KB 10.4% View diff
apps/ui/public/changelog/organization-analytics.png 287.3 KB 258.2 KB 10.1% View diff

2 images did not require optimisation.

@steebchen

Copy link
Copy Markdown
Member

Images automagically compressed by Calibre's image-actions

Compression reduced images by 15%, saving 80.4 KB.

Filename Before After Improvement Visual comparison
apps/ui/public/blog/enterprise-llm-analytics.png 277.8 KB 223.5 KB 19.5% View diff
apps/ui/public/changelog/organization-analytics.png 258.2 KB 232.0 KB 10.1% View diff

2 images did not require optimisation.

@steebchen

Copy link
Copy Markdown
Member

Images automagically compressed by Calibre's image-actions

Compression reduced images by 8.6%, saving 39.4 KB.

Filename Before After Improvement Visual comparison
apps/ui/public/blog/enterprise-llm-analytics.png 223.5 KB 198.5 KB 11.2% View diff
apps/ui/public/changelog/organization-analytics.png 232.0 KB 217.6 KB 6.2% View diff

2 images did not require optimisation.

@steebchen

Copy link
Copy Markdown
Member

Images automagically compressed by Calibre's image-actions

Compression reduced images by 7.4%, saving 14.6 KB.

Filename Before After Improvement Visual comparison
apps/ui/public/blog/enterprise-llm-analytics.png 198.5 KB 183.9 KB 7.4% View diff

3 images did not require optimisation.

@smakosh
smakosh enabled auto-merge June 26, 2026 18:24
@smakosh
smakosh added this pull request to the merge queue Jun 26, 2026
Merged via the queue into main with commit 615e710 Jun 26, 2026
12 checks passed
@smakosh
smakosh deleted the feat/org-analytics-devpass-profile branch June 26, 2026 18:35
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.

2 participants