feat(observer): Data Observer Phase 2 — Catalog/Explorer + 4V Health dashboard#28
Merged
Conversation
added 10 commits
June 30, 2026 19:46
…library mode lookup
…panel + explorer smoke - Add same-origin GET proxy at /api/observer/[...path] that forwards to observer-api via apiFetch (session-gated, no open-proxy) - Add AsOfSlider component for point-in-time knowledge-time selection - Add SeriesChart component (ECharts line + DataZoom) that re-fetches on as_of change via the proxy route - Add QualityPanel component with gate verdict, failures table, gaps count, and anomalies summary - Wire Series + Quality tabs in SymbolTabs, removing Task-6 placeholders - Add Playwright @smoke explorer.spec.ts (deferred run needs composed stack) - Fix Task-6: VintageRow.version typed as number (was string); render with String(v.version) in VintagesTab; guard schema/vintages fetch on selectedSym
…ity no-schema as neutral, not fail
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.
Summary
Phase 2 of the internal Data Observer — the core "explore what I have." Builds a real catalog/explorer and a 4-V (Volume/Velocity/Variety/Veracity) Health dashboard on top of the Phase-1 auth/RBAC spine, sourced entirely from ArcticDB via
energex.core(no Dagster). Follows #27.What's included
Backend (
observer-api,src/energex/observer/) — all endpointsrequire_role(viewer):/catalognow useslib.get_description()(row count + latestvalid_time, no full-data read) + vintage sidecars, replacing the Phase-1 per-symbol full-scan./symbol/{lib}/{sym}/series(point-in-time viastorage.read_as_ofwith an explicitmode),/schema,/vintages./symbol/{lib}/{sym}/qualityre-runs the platform's own pandera gate (quality.validate) against stored data, so "broken" means exactly what the pipeline means (theercot_loadfreshness failure surfaces honestly); plusvalid_timegap counting and an OHLCV anomaly summary./metrics/overview+/metrics/health, backed by a per-symbol freshness heuristic (TTL-cached) whose tolerances mirrorschemas.py(importable constants imported; a test cross-checks against drift). The full gate stays on-demand per symbol, never a full scan at request time.library → core.schemasrouting map (schema_map.py) mirroringorchestration/checks.py.Frontend (
observer-web/, Next.js 16 + Tailwind v4 + ECharts):as_ofpoint-in-time slider over an ECharts chart ("what we knew then")./api/observer/[...path]) — the browser never reachesobserver-apidirectly (in-network URL, CORS-scoped); interactive fetches go through the proxy, which attaches the bearer server-side.Security & correctness
Every data endpoint is role-enforced server-side; the browser holds only the anon key + JWT. The proxy is not an open proxy (fixed observer-api base, no host/scheme injection) and never returns the bearer. A five-lens whole-branch review (spec / security / backend / frontend / cross-cutting) returned security PASS, backend PASS, and caught two cross-task contract mismatches (the
/seriesresponse shape vs the chart; a tri-statequality.passedrendering a false "fail" badge) — both fixed and now locked by contract tests on each side.Testing
/seriescontract assertions); ruff check + format clean.series-chart+quality-panelcontract tests) +npm run buildgreen; a Playwright@smokeexplorer flow (deferred run, needs the composed stack).Notes
overview()scanning the catalog twice, and totalizing the freshness-mirror drift guard.