Files
zooqueen 252e1cb076 Generated clients call the API where it is mounted
`insights/mount.py` is explicit: `/v1/` is the mount and `/api/` is the older
spelling, kept on the wire for released CLI builds and personal-API-key
holders and rewritten once at the edge by `ApiRewriteMiddleware`. Our own
frontend was still on the older spelling: the orval clients were generated
two days before the mount moved and the move did not regenerate them, so 70
files and 2323 paths said `/api/`.

That is not only a spelling. `prepareUrl` in `lib/api.ts` rewrites `/v1/*` to
the selected region's host in OAuth mode and nothing else, because that is
what the cloud CORS allowlist covers — so every generated call quietly stayed
same-origin, and `getExportsContentRetrieveUrl` builds an `<img src>` that
never reaches `lib/api.ts` at all.

The clients are regenerated from a spec that needs postgres, the datastore and
Django, so this is the path strings only, which is the whole of what the mount
move changes in them: orval copies paths verbatim from the spec, and the spec
takes them from the URLconf. Doc comments carried the same stale prefix and
move with them; their Python docstrings already say `/v1/`. The two frozen
OAuth client-metadata paths are identifiers rather than API surface and appear
in none of these files.

The Slack task prompt told the agent to POST to
`$INSIGHTS_API_URL/api/projects/...`, which is a live request path, not prose.
2026-08-24 23:13:08 -07:00
..

Batch exports frontend

The batch exports frontend code currently lives in frontend/src/scenes/data-pipelines/batch-exports/.

Architecture

Component tree

graph TD
    S[BatchExportScene<br/><i>BindLogic: configFormLogic</i>]
    S --> Conf[BatchExportConfiguration]
    S --> Runs[BatchExportRuns]
    S --> BF[BatchExportBackfills]
    S --> Met[BatchExportsMetrics]

    Conf --> GEF[BatchExportGeneralEditFields]
    Conf --> DEF[BatchExportsEditFields]
    Conf --> SB[BatchExportConfigurationSaveButton]
    Conf --> CCB[BatchExportConfigurationClearChangesButton]
    Conf --> CT[BatchExportConfigurationTests]
    Runs --> BFM[BatchExportBackfillModal]
    BF --> BFM
Component Logics used Description
BatchExportScene batchExportConfigFormLogic, batchExportSceneLogic Top-level scene. Mounts batchExportConfigFormLogic via BindLogic, renders tabs.
BatchExportConfiguration batchExportConfigFormLogic Configuration/editing form.
BatchExportConfigurationSaveButton batchExportConfigFormLogic Save button for the config form.
BatchExportConfigurationClearChangesButton batchExportConfigFormLogic Clear-changes button for the config form.
BatchExportConfigurationTests batchExportConfigFormLogic Destination-specific configuration tests.
BatchExportGeneralEditFields — General form fields (name, interval, model).
BatchExportsEditFields — Destination-specific form fields.
BatchExportRuns batchExportRunsLogic Runs tab — table of latest runs.
BatchExportBackfills batchExportBackfillsLogic Backfills tab — table of backfills with cancel/create actions.
BatchExportBackfillModal batchExportBackfillModalLogic Modal for creating a new backfill with date range picker. Rendered by both BatchExportRuns and BatchExportBackfills.
BatchExportsMetrics appMetricsLogic Metrics tab — batch export metrics charts.
RenderBatchExportIcon — Renders the icon for a batch export destination type.

Logic dependencies

Each arrow represents a connect() call (the source logic reads values/actions from the target).

graph TD
    A[batchExportDataLogic]

    B[batchExportConfigFormLogic] -->|connect| A
    C[batchExportRunsLogic] -->|connect| A
    D[batchExportBackfillsLogic] -->|connect| A
    D -->|connect| E
    E[batchExportBackfillModalLogic] -->|connect| A

    F[batchExportSceneLogic]
Logic Description
batchExportDataLogic Loads and caches a batch export's configuration from the API. Keyed by export ID. All other logics connect here for config data.
batchExportConfigFormLogic Form logic for creating/editing batch export configurations. Owns form state, validation, test steps, save, and delete. Mounted by BatchExportScene via BindLogic.
batchExportRunsLogic Loads and manages batch export runs. Handles grouping by date, retry, cancel, and pagination.
batchExportBackfillsLogic Loads and manages batch export backfills. Handles listing, cancellation, and polling for row count estimates after creation.
batchExportBackfillModalLogic Form logic for the backfill creation modal. Manages date range selection, schedule display, and submission.
batchExportSceneLogic Tab navigation and URL sync for the batch export scene. Defined inline in BatchExportScene.tsx.

External consumers

InsightsFunctionBackfills (in scenes/insights-functions/backfills/) renders the backfills tab for script function destinations backed by a batch export. It mounts batchExportDataLogic and batchExportBackfillsLogic via BindLogic — this works because these logics only depend on the data logic, not the form logic.

Tests

Kea logic tests

pnpm --filter=@hanzo/frontend jest batchExportConfigFormLogic --no-coverage

Covers: default configuration per service, required field validation, S3 bucket name validation, create/update flows, and API loading.

If tests fail with Cannot find module 'react' from kea-router, run pnpm install --force to fix broken pnpm symlinks.

Storybook stories

pnpm storybook

Then navigate to Scenes-App / BatchExports in the sidebar. Stories: NewS3Export, NewPostgresExport, ExistingBigQueryExport.

Playwright E2E tests

pnpm --filter=playwright test e2e/batch-exports.spec.ts

Covers creating a new S3 export and validating required fields.

Requires a running backend (./bin/start).

You will also need to install Playwright using pnpm exec playwright install.