You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
apps/ui/src/routes/subnets.$netuid.tsx (ProfileShell, line 194 and line 220) reads exactly one freshness value — meta?.generated_at from subnetProfileQuery (the /api/v1/subnets/{netuid}/profile envelope, a daily registry-build snapshot) — and threads it into the single FreshnessIndicator rendered in SubnetMasthead (apps/ui/src/components/metagraphed/subnet-masthead.tsx:294). That one dot is shown regardless of which tab the user has open, including panels backed by materially fresher, chain-derived queries: subnetEventsQuery (Activity tab, STALE_SHORT, apps/ui/src/lib/metagraphed/queries.ts:2683), MetagraphTableLoader/ValidatorsTableLoader (live metagraph snapshot), and EconomicsPanel (the live KV-tier economics route). Each of those already returns its ownres.meta.generated_at independent of the profile snapshot, but nothing in the masthead or tab chrome tells the user "this tab reflects a live/near-realtime chain read" vs. "this tab reflects the last ~6h registry snapshot" — the page silently implies one freshness for everything.
Requirement
Add an honest, per-context freshness label to the subnet detail page that distinguishes the realtime/chain-derived data tier (events, metagraph, validators, live economics) from the daily registry/metagraph-snapshot tier (profile, surfaces, endpoints, candidates), so a viewer can tell which timestamp actually describes what they're looking at. This is a small UI-truthfulness fix, not a new panel or new endpoint — no backend change is required since every relevant query already carries its own generated_at.
Deliverable
File(s) to change:apps/ui/src/routes/subnets.$netuid.tsx (ProfileShell, OverviewPanel, ActivityPanel/MetagraphPanel call sites) and apps/ui/src/components/metagraphed/subnet-masthead.tsx (the FreshnessIndicator usage at line 294). Reuse the existing FreshnessIndicator (apps/ui/src/components/metagraphed/freshness.tsx) and formatFreshness/formatFreshnessAbsolute helpers (apps/ui/src/lib/metagraphed/freshness.ts) — do not invent a second formatter.
Exact anchor:ProfileShell (subnets.$netuid.tsx:190-280) currently derives stale from meta?.generated_at alone (line 194) and passes only that single value into SubnetMasthead (line 220) and StaleBanner (line 226); SubnetMasthead renders it via the one FreshnessIndicator at subnet-masthead.tsx:294. Tab-scoped panels like ActivityTableLoader (line 476-488) already receive data.meta?.generated_at from their own query but never label it as a different tier from the masthead's stamp.
What "done" looks like concretely: each realtime/chain-derived panel (Activity, Metagraph, Validators, Economics) surfaces a short qualifier — e.g. "live chain read" / "realtime" — next to its own freshness stamp, visually distinct from a "daily registry snapshot" qualifier used for the masthead/profile-driven stamp and for Surfaces/Endpoints/Candidates. No new query is added; this only labels timestamps the app already fetches. Reasonable implementation: a small tier prop/variant on FreshnessIndicator (or a thin wrapper) that renders a realtime/daily badge alongside the existing relative-time text, driven by which query's meta.generated_at is being shown.
apps/ui/src/routes/subnets.$netuid.tsx and apps/ui/src/components/metagraphed/subnet-masthead.tsx appear in the diff
The realtime/chain-derived tabs (Activity, Metagraph, Validators, Economics) render a freshness label that is visibly distinct (copy and/or styling) from the label shown for the daily registry-snapshot tier (masthead, Surfaces, Endpoints, Candidates)
The distinction is driven by each panel's own already-fetched meta.generated_at (e.g. subnetEventsQuery's envelope) — no new API call or endpoint is introduced
FreshnessIndicator (or a thin wrapper around it) is reused rather than a second freshness component being built from scratch
Existing staleness behavior (the stale banner driven by isStaleFreshness) is preserved unchanged for the daily tier
apps/ui/src/lib/metagraphed/freshness.test.ts (or an added test alongside it) covers the new tier-labeling logic
Non-goals
No backend/schema change — every timestamp needed already exists in the current query responses (res.meta.generated_at per endpoint)
Do not add a new panel, chart, or endpoint; this is a labeling fix on existing data
Context
apps/ui/src/routes/subnets.$netuid.tsx(ProfileShell, line 194 and line 220) reads exactly one freshness value —meta?.generated_atfromsubnetProfileQuery(the/api/v1/subnets/{netuid}/profileenvelope, a daily registry-build snapshot) — and threads it into the singleFreshnessIndicatorrendered inSubnetMasthead(apps/ui/src/components/metagraphed/subnet-masthead.tsx:294). That one dot is shown regardless of which tab the user has open, including panels backed by materially fresher, chain-derived queries:subnetEventsQuery(Activity tab,STALE_SHORT,apps/ui/src/lib/metagraphed/queries.ts:2683),MetagraphTableLoader/ValidatorsTableLoader(live metagraph snapshot), andEconomicsPanel(the live KV-tier economics route). Each of those already returns its ownres.meta.generated_atindependent of the profile snapshot, but nothing in the masthead or tab chrome tells the user "this tab reflects a live/near-realtime chain read" vs. "this tab reflects the last ~6h registry snapshot" — the page silently implies one freshness for everything.Requirement
Add an honest, per-context freshness label to the subnet detail page that distinguishes the realtime/chain-derived data tier (events, metagraph, validators, live economics) from the daily registry/metagraph-snapshot tier (profile, surfaces, endpoints, candidates), so a viewer can tell which timestamp actually describes what they're looking at. This is a small UI-truthfulness fix, not a new panel or new endpoint — no backend change is required since every relevant query already carries its own
generated_at.Deliverable
apps/ui/src/routes/subnets.$netuid.tsx(ProfileShell,OverviewPanel,ActivityPanel/MetagraphPanelcall sites) andapps/ui/src/components/metagraphed/subnet-masthead.tsx(theFreshnessIndicatorusage at line 294). Reuse the existingFreshnessIndicator(apps/ui/src/components/metagraphed/freshness.tsx) andformatFreshness/formatFreshnessAbsolutehelpers (apps/ui/src/lib/metagraphed/freshness.ts) — do not invent a second formatter.ProfileShell(subnets.$netuid.tsx:190-280) currently derivesstalefrommeta?.generated_atalone (line 194) and passes only that single value intoSubnetMasthead(line 220) andStaleBanner(line 226);SubnetMastheadrenders it via the oneFreshnessIndicatoratsubnet-masthead.tsx:294. Tab-scoped panels likeActivityTableLoader(line 476-488) already receivedata.meta?.generated_atfrom their own query but never label it as a different tier from the masthead's stamp.FreshnessIndicator(or a thin wrapper) that renders arealtime/dailybadge alongside the existing relative-time text, driven by which query'smeta.generated_atis being shown.Acceptance criteria
apps/ui/src/routes/subnets.$netuid.tsxandapps/ui/src/components/metagraphed/subnet-masthead.tsxappear in the diffmeta.generated_at(e.g.subnetEventsQuery's envelope) — no new API call or endpoint is introducedFreshnessIndicator(or a thin wrapper around it) is reused rather than a second freshness component being built from scratchstalebanner driven byisStaleFreshness) is preserved unchanged for the daily tierapps/ui/src/lib/metagraphed/freshness.test.ts(or an added test alongside it) covers the new tier-labeling logicNon-goals
res.meta.generated_atper endpoint)Size
Size: S — keep this PR small (aim for ≤10 files / ≤1000 LOC).
Part of #2542.