Skip to content

feat(observer): Data Observer Phase 3 foundation — Dagster read client + Supabase write client (WIP, Tasks 1–2 of 6)#29

Open
oldhero5 wants to merge 3 commits into
mainfrom
feat/observer-phase3-quality
Open

feat(observer): Data Observer Phase 3 foundation — Dagster read client + Supabase write client (WIP, Tasks 1–2 of 6)#29
oldhero5 wants to merge 3 commits into
mainfrom
feat/observer-phase3-quality

Conversation

@oldhero5

@oldhero5 oldhero5 commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary

⚠️ Work in progress — Phase 3 foundation only (Tasks 1–2 of 6). This branch lands the two server-side integration clients + config that the Quality board is built on. The board itself, the routers, the operator ack/snooze/resolve actions, and the /quality UI (Tasks 3–6) are not in this PR yet. Opening it as a checkpoint of the self-contained, tested foundation.

Phase 3 of the internal Data Observer is the cross-platform Quality/Veracity board + operator issue actions. This PR is its groundwork: observer-api's first outbound integrations. Follows #27 (Phase 1) and #28 (Phase 2).

What's included (Tasks 1–2)

  • Config (src/energex/observer/config.py) — adds optional SUPABASE_URL, SUPABASE_SERVICE_KEY, and DAGSTER_GRAPHQL_URL (default http://dagster-webserver:3000/graphql). Optional-safe: the module still imports without them.
  • Dagster GraphQL read client (dagster_client.py) — get_pipeline_health() returns a normalized {available, checks, runs, schedules, error}. Validated against a live Dagster 1.13.9 (the initially-assumed query was schema-incompatible in three ways and was corrected to assetNodes + executionForLatestMaterialization, runsOrError, workspaceOrError). Fully resilient — any transport/HTTP/parse error or missing field degrades to available: false, never raises (so the board can't 500 when Dagster is down). Read-only; TTL-cached.
  • Supabase PostgREST client (supabase_client.py) — observer-api's first write path: read_issue_acks, write_issue_ack, write_audit_log, using the service key server-side only (never exposed to the browser); is_configured() + typed SupabaseError for graceful 503/502 handling by the callers.

Both use sync httpx (matching the sync observer routers) and are covered by offline, mocked-httpx tests.

Not in this PR (Tasks 3–6, still to build)

  • Board assembly + GET /quality/board, GET /issues (viewer).
  • Operator POST /issues/{key}/ack|snooze|resolve with audit logging (operator role).
  • The /quality frontend view + operator action controls (+ POST-capable proxy).

Testing

  • 281 backend tests pass (uv run --all-extras pytest); ruff check + format clean. New: 11 Dagster-client tests (parse + total resilience + TTL-cache hit + data: null) and 8 Supabase-client tests (PostgREST URL/headers/payload + not-configured).
  • No frontend changes in this PR.

Review status & notes

  • Task 1 (Dagster client) went through task review; two Important findings were fixed (last_run_status now carries the status not the run id; a TTL-cache-hit test was added). Task 2 (Supabase client) is committed and tested but has not yet had its task review — treat accordingly.
  • Deploy caveat: because observer-api now makes outbound calls to Supabase (which runs on the host), its SUPABASE_URL must be host-reachable from the container (http://host.docker.internal:54321 in compose on macOS) — distinct from the browser's NEXT_PUBLIC_SUPABASE_URL. This is wired in the compose task (not yet in this PR).
  • No changes to energex.orchestration. No new Supabase migrations.

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