Skip to content

User token metrics - #2085

Merged
pikonha merged 11 commits into
devfrom
chore/user-api-tokens
Jul 29, 2026
Merged

User token metrics#2085
pikonha merged 11 commits into
devfrom
chore/user-api-tokens

Conversation

@pikonha

@pikonha pikonha commented Jul 27, 2026

Copy link
Copy Markdown
Member

Note

Medium Risk
Touches metrics exposure (optional bearer on /metrics), periodic DB + Authful calls at startup, and a new Authful listing API; misconfigured tokens could block scrapes or leak metrics if left unset in prod.

Overview
Adds low-cardinality validation observability for the self-service User API: account totals, live/created API keys, and “active today” users bucketed by newest key age (0-1d30d+), using a minute refresh that joins User API DB counts with Authful’s notion of tokens used since São Paulo midnight (GMT-3).

Authful exposes GET /tokens/active?since= (provisioning scope) returning only user:* token IDs with lastUsedAt at or after since, excluding ops tenants; covered by integration tests.

User API wires MetricsSnapshotService + registerValidationMetrics when Authful provisioning is configured, calls Authful via activeTokenIds, and optionally protects /metrics with USER_API_METRICS_TOKEN (public when unset).

Monitoring: Prometheus scrapes User API with bearer auth; new Grafana User API Validation dashboard; TSDB retention bumped to 180d / 40GB; PR-environment NOOP deploy overrides removed from Grafana/Prometheus Railway configs.

Reviewed by Cursor Bugbot for commit a7730fc. Configure here.

@vercel

vercel Bot commented Jul 27, 2026

Copy link
Copy Markdown

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

Project Deployment Actions Updated (UTC)
anticapture-storybook Ready Ready Preview, Comment Jul 28, 2026 6:31pm
1 Skipped Deployment
Project Deployment Actions Updated (UTC)
anticapture Ignored Ignored Jul 28, 2026 6:31pm

Request Review

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c5ad1cd2e4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/user-api/src/index.ts Outdated
Comment thread apps/user-api/src/services/metrics/index.ts Outdated
Comment thread apps/authful/src/repositories/tokens/index.ts Outdated
@railway-app
railway-app Bot temporarily deployed to anticapture-infra / anticapture-pr-2085 July 27, 2026 14:24 Destroyed
@railway-app

railway-app Bot commented Jul 27, 2026

Copy link
Copy Markdown

🚅 Deployed to the anticapture-pr-2085 environment in anticapture-infra

Service Status Web Updated (UTC)
prometheus ✅ Success (View Logs) Jul 28, 2026 at 6:30 pm
authful ✅ Success (View Logs) Web Jul 28, 2026 at 6:30 pm
loki ✅ Success (View Logs) Jul 28, 2026 at 6:30 pm
otelcol ✅ Success (View Logs) Jul 28, 2026 at 6:30 pm
gateful ✅ Success (View Logs) Web Jul 28, 2026 at 6:30 pm
grafana ✅ Success (View Logs) Web Jul 28, 2026 at 6:30 pm
tempo ✅ Success (View Logs) Jul 28, 2026 at 6:29 pm
alertmanager ✅ Success (View Logs) Jul 28, 2026 at 6:29 pm
gitcoin-indexer-offchain ✅ Success (View Logs) Jul 28, 2026 at 1:34 pm
ens-indexer-offchain ✅ Success (View Logs) Jul 28, 2026 at 1:24 pm
compound-indexer-offchain ✅ Success (View Logs) Jul 28, 2026 at 1:22 pm
uniswap-indexer-offchain ✅ Success (View Logs) Jul 28, 2026 at 1:22 pm
shutter-indexer-offchain ✅ Success (View Logs) Jul 28, 2026 at 1:21 pm
user-api ✅ Success (View Logs) Web Jul 27, 2026 at 11:50 pm
gitcoin-api ✅ Success (View Logs) Jul 27, 2026 at 7:45 pm
gitcoin-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:44 pm
obol-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:44 pm
fluid-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:44 pm
shutter-api ✅ Success (View Logs) Jul 27, 2026 at 7:43 pm
ens-api ✅ Success (View Logs) Jul 27, 2026 at 7:43 pm
uniswap-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:43 pm
scroll-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:43 pm
shutter-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:43 pm
nouns-api ✅ Success (View Logs) Jul 27, 2026 at 7:43 pm
tornado-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
ens-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
compound-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
fluid-api ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
uniswap-api ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
nouns-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
scroll-api ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
obol-api ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
aave-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:42 pm
docs ✅ Success (View Logs) Web Jul 27, 2026 at 7:41 pm
tornado-api ✅ Success (View Logs) Jul 27, 2026 at 7:41 pm
lil-nouns-indexer ✅ Success (View Logs) Jul 27, 2026 at 7:41 pm
compound-api ✅ Success (View Logs) Jul 27, 2026 at 7:41 pm
aave-api ✅ Success (View Logs) Jul 27, 2026 at 7:41 pm
erpc ✅ Success (View Logs) Web Jul 27, 2026 at 7:41 pm
mcp ✅ Success (View Logs) Web Jul 27, 2026 at 7:41 pm
lil-nouns-api ❌ Build Failed (View Logs) Jul 27, 2026 at 7:41 pm
address-enrichment ✅ Success (View Logs) Web Jul 27, 2026 at 2:28 pm
ens-relayer ✅ Success (View Logs) Jul 27, 2026 at 2:28 pm
nodeful ✅ Success (View Logs) Jul 27, 2026 at 2:28 pm

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: a7730fc8d7

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/user-api/src/metrics.ts Outdated
@github-actions

github-actions Bot commented Jul 27, 2026

Copy link
Copy Markdown
Contributor

🔍 Vercel preview: https://anticapture-o6v8jyv3r-ful.vercel.app

- serve before initial metrics refresh so slow Authful can't keep /health down
- publish DB counts independently of Authful in metrics refresh
- derive daily-active from usage records, not lastUsedAt (survives Gateful cache hits)

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: f231dbec87

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/authful/src/repositories/tokens/index.ts
Comment thread apps/user-api/src/index.ts
- export user_api_keys_created_total as a real counter incremented on
  creation instead of a mutable row count (cascade delete on account
  removal read as a counter reset / false increase() spike)
- guard MetricsSnapshotService.refresh against overlapping runs so a
  slow Authful can't clobber a newer snapshot or pile up fetches

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

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 9f6d3996a9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/user-api/src/services/metrics/index.ts Outdated
@railway-app
railway-app Bot temporarily deployed to anticapture-infra / anticapture-pr-2085 July 27, 2026 23:08 Destroyed

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d1e5e39ab6

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/user-api/src/app.ts

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6d0dcc8be4

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread apps/user-api/src/metrics.ts
isadorable-png and others added 2 commits July 28, 2026 15:29
Save-key modal: default width on both steps, no key name or em-dash in
the description, 'Key' and 'MCP' titles at the same font size, no
'waiting for the first call' status, and animated code-block height
when switching client tabs. Keys table truncates long names with an
ellipsis. Usage section: key switcher is a dropdown with a max width,
blank slate for the empty state, and reduced height. Connect section
retitled 'MCP' with 'connect your AI agent' in the description. Modal
close button uses the small icon-button size.

ClickUp: 86ajr888u

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…erflow

Long API key names are truncated to 24 chars in the usage chart series
(tooltip and legend), with the id suffix disambiguating names that
collapse to the same truncated label. The stacked-bar-chart legend now
scrolls instead of wrapping, so many/long series names no longer
overflow into the x-axis on narrow screens.

ClickUp: 86ajr888u

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 77becf7808

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines +107 to +109
const res = await fetch(
`${this.baseUrl}/tokens/active?since=${encodeURIComponent(since.toISOString())}`,
{ headers: this.headers() },

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 Badge Bound the active-token fetch

When Authful accepts the connection but never finishes /tokens/active, this fetch has no abort signal or timeout. With the current serialized MetricsSnapshotService.refresh() path, that single pending promise keeps refreshing true and every later interval tick returns immediately, so the User API's validation metrics can remain frozen until the process restarts; add a bounded AbortSignal.timeout(...) like the other Authful clients use for internal calls.

Useful? React with 👍 / 👎.

Copy link
Copy Markdown
Collaborator

🎨 UI Review

Automated review · Figma: 🔐 Login & API Keys — V1 screens (baseline API Keys screens — reference only) · Spec: ux review: api key page (ClickUp checklist this diff was built from)
ℹ️ This diff is a polish pass authored directly against Isadora's own itemized ClickUp checklist (86ajr888u), closed with every box checked — not against a new Figma frame. Findings below are grounded in that checklist text plus direct code reading; Figma was consulted for baseline dimensions (e.g. modal width) where useful.
⚠️ Two visual sources were unreachable in this environment: the checklist's own 5 mockup screenshots (blocked by egress policy on *.p.clickup-attachments.com — same restriction hit reviewing PR #2084) and the Vercel preview (https://anticapture-k9nfu1yt0-ful.vercel.app → 403, SSO-gated, no bypass token configured). Worth a quick manual glance at the live preview before merge.


API Keys page — Save-key modal

Validated against the ClickUp checklist, no change needed on any of these:

  • Modal width no longer differs between the create step and the save step — the max-w-3xl override is gone and both now fall through to Modal's default (max-w-150 = 600px), which also matches the two Figma modal frames (3374:20219, 3374:20325) at 600px. [Figma-confirmed] + [ClickUp-confirmed]
  • Description drops the key name and the em dash exactly as specced: "This is the only time your key is shown. Save it or connect your AI agent now. You can't retrieve it again." [ClickUp-confirmed]
  • "Key" title above the secret and "MCP" title above the connect section both render text-primary text-sm font-medium — same size, as required. [ClickUp-confirmed]
  • "Waiting for the first call…" status line is now gated on variant === "section", so it's hidden inside the modal but still shows on the page section. [ClickUp-confirmed]
  • Close button dropped to the small IconButton size (-m-1, no forced size-11) — checklist calls this out as desktop-only (mobile uses the Drawer), which holds since ModalHeader isn't rendered in the mobile sheet. [ClickUp-confirmed]

Keys table

Nice-to-have — full-name-on-hover uses the browser's native tooltip instead of the DS Tooltip
ApiKeysTable.tsx:234-237 truncates the name with title={row.original.label}, which works but gives an inconsistent look/delay versus the rest of the app. The DS Tooltip is already imported one file over in this same feature (UsageSection.tsx) — swap the native title for it so hovering a long key name matches the hover styling used elsewhere on this page. [Code-only]

Truncation itself (max-w-70 block truncate) is correct and matches the checklist ask. [ClickUp-confirmed]


Usage section

Validated against the ClickUp checklist, no change needed on any of these:

  • Key filter is now a Select on all breakpoints (segmented control removed), capped at max-w-48, and the Select truncates its own label internally — long names get an ellipsis inside the dropdown trigger. [ClickUp-confirmed]
  • Empty state now renders the DS BlankSlate (variant="title", Inbox icon) instead of a bare "No requests yet" string. [ClickUp-confirmed]
  • Loading/error/chart height dropped 300px → 200px; the blank slate itself is intentionally left un-fixed-height (h-fit) per the DS component, matching "empty state is now the compact blank slate." [ClickUp-confirmed]
  • Chart series names truncate at 24 chars + ellipsis in transform.ts, with the id-suffix disambiguation computed against the truncated label (so two long names that truncate identically still get distinct suffixes). [ClickUp-confirmed]

Mobile

  • Legend switches to type: "scroll" in StackedBarChart.tsx instead of wrapping — confirmed this only affects the legend row and doesn't touch the x-axis grid reserve, so the chart no longer overflows on narrow widths. [ClickUp-confirmed]
  • UsageSection's Card drops its border/background/padding below lg: and restores them at lg: (border-0 bg-transparent p-0 lg:border lg:bg-surface-default lg:p-4) — verified this resolves correctly through cn's tailwind-merge setup (no leftover border/bg bleeding through from Card's base classes on mobile). [Code-only]

MCP section (formerly "Connect your AI agent")

Validated against the ClickUp checklist, no change needed:

  • Section/modal title is now "MCP" everywhere it renders. [ClickUp-confirmed]
  • Description copy matches the checklist's wording exactly: "Connect your AI agent: pick your tool and run one command in your terminal. Your key is already in it." (and the disconnected variant). [ClickUp-confirmed]

Design-system adherence

No new hand-rolled primitives — the diff only reconfigures existing Modal, Select, BlankSlate, Card, and CodeBlock usage (see the native-tooltip nit under Keys table above, the one place a DS component was available but not used). [Code-only]

Scope note

This is a UI-only review (visual fidelity, DS adherence, UX, copy, responsive behavior) — architecture, hook structure, and other code-quality concerns are left to the code reviewer.


Generated by Claude Code

@pikonha
pikonha merged commit 9f60ccd into dev Jul 29, 2026
62 checks passed
@pikonha
pikonha deleted the chore/user-api-tokens branch July 29, 2026 12:50
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants