Files
analytics/documentation/overview.md
T
JiriUhlir 6934f22253 first
2026-06-18 11:58:23 +02:00

3.1 KiB

analytics — overview

A stateless multi-tenant API proxy exposing two upstream services under one FastAPI app:

  1. Google Analytics 4 — Data API (reporting) + Admin API (read).
  2. Sklik (Seznam) — Drak JSON-RPC API.

The structure mirrors the sibling idoklad / csob services (config→env, credentials→headers, client per upstream, routers, central exception handling, Swagger at /docs), adapted to Python/FastAPI.

Design principles

  • Stateless / no stored secrets. Credentials arrive per request in X- headers and are used only to call the upstream. Nothing is persisted; the only in-memory state is a short-lived GA access-token cache (see below).
  • Thin passthrough. GA request/response bodies and most Sklik calls are forwarded as-is, so callers keep the full upstream API surface. Only authentication, base URL and error mapping are added.
  • No silent failures. Every error is logged (never the secret values) and surfaced as JSON. Upstream errors preserve the upstream status and body.

Layout

app/
  config.py            env-driven config (base URLs, scope, timeout) — no secrets
  logging_config.py    get_logger(); secrets are never logged
  errors.py            MissingCredentialsError, UpstreamError + handlers
  credentials.py       X- header dependencies (GA + Sklik)
  clients/
    ga_client.py       GA Data/Admin HTTP client + service-account token minting
    sklik_client.py    Sklik JSON-RPC client (login + session + report paging)
  routers/
    meta.py            /health, /version
    ga_data.py         /ga/data/...
    ga_admin.py        /ga/admin/...
    sklik.py           /sklik/...
  main.py              app factory, root_path, router + handler registration

Reverse proxy

ROOT_PATH (e.g. /apps/analytics) is passed to FastAPI's root_path, so the OpenAPI servers entry and Swagger "Try it out" use the public prefix. Internal routes are unprefixed (Caddy handle_path strips the prefix).

Authentication summary

Upstream Header(s) Behaviour
Google Analytics X-GA-Access-Token or X-GA-Credentials (+ X-GA-Quota-Project) Token used directly; else a token is minted from the base64 service-account JSON (scope analytics.readonly) and cached in memory until ~60 s before expiry.
Sklik X-Sklik-Token (+ X-Sklik-User-Id) client.loginByToken per request → session injected into the call.

Deliberately not wired

  • GA Admin write operations (create/update/delete properties, streams). The requested scope is read-only (analytics.readonly); add analytics.edit and endpoints if management is needed later.
  • Sklik header-credential encryption. Same deferral as idoklad/csob: header values are plaintext over TLS for now.
  • Sklik session reuse across requests — the chosen model logs in per request; a future X-Sklik-Session passthrough could save the login call.

Verification checklist (per AGENTS.md)

  • /health returns 200.
  • /docs loads; /openapi.json servers contains the proxy prefix.
  • New endpoints appear in Swagger with their X- headers in "Try it out".
  • Secrets never appear in logs or source.