/data/flow-pipelines/[id]/edit. The legacy single-pane
pipeline-flow-editor (PipelineNode/Edge model) was deleted on
2026-04-28 — every pipeline is now IR-native (irVersion: "1.0").
Layout
The AI Panel (Pipeline mode) is not in the right pane — it is a shell-level
panel docked at the top-right of the page that auto-activates whenever the URL
is under
/data/flow-pipelines.
A top bar shows the pipeline name, status pill, IR version pill, Publish
button, and a Run-now button. A bottom strip shows the last run, next
scheduled fire, DLQ count, and quick links. Run history lives on the
dedicated Pipeline Runs page reached from the
sidebar — the editor’s previous “Recent runs” left pane was redundant
and was removed on 2026-05-02.
Tab reference
Visual
React Flow canvas, kind-coloured nodes (source / transform / validate / target / branch / join / enrich / outcomes), deterministic vertical waterfall layout. Each node card shows a one-line config summary inline (source: path · pattern · format; target: schema · loadMode; transform: op types; validate: rule count; outcomes: resolution mode · attribution window). Click a node → right pane swaps to Node Config, an editable per-kind form (thejoin kind is the one
exception — it shows a read-only JSON view with a jump to the JSON IR tab).
Above the canvas there is an Add Node toolbar with six buttons:
**+ Transform / + Validate / + Enrich / + Branch / + Target /
- Outcomes** (the addable kinds, from
ADDABLE_KINDSinnode-defaults.ts). Click a chainable button (Transform / Validate / Enrich / Branch) and kaireon inserts a default-configured node into the IR between the last upstream and your first sink, repoints the sinks that consumed the prior upstream so they now flow through the new node, and selects it so you can edit. + Target and + Outcomes are terminal sinks — they append a new node that consumes the same upstream as the existing chain rather than being spliced into it (see the Target and Outcomes sections below). Defaults intentionally use placeholder values (e.g. a transform with arename: from_field → to_fieldop, or an outcomes node mapping the_kaireon_ridtoken) so you can tell at a glance which fields to customize.
atomicity config (successFolder / failureFolder) moves
the source file to a date-templated archive folder on parse success
and to a failure folder on parse error. See
file ingestion for the full atomic
staging flow.
JSON IR
Read/write IR editor with format-on-blur. Server-side validation goes throughparsePipelineIR — invalid IR is rejected with the structured
errors array rendered verbatim. Save creates a new IR version (POST
/api/v1/pipelines/:id/ir) and bumps the version pill.
SQL Preview
Renders the exactINSERT … SELECT each target node would execute,
using the same builders the runtime uses (buildLoadSql +
buildSelectExpr). blue_green, incremental_watermark, and
cdc_mirror targets render an explicit “preview not available — runtime
load-mode helper handles it” note rather than fabricated SQL.
GET /api/v1/pipelines/:id/sql-preview powers this tab.
Lineage
See Flow Lineage.Schedule
See Flow Schedule.Run history
Run history is a dedicated page at Sidebar → Data → Pipeline Runs (/data/flow-runs) — the editor’s previous in-pane “Recent runs”
preview was redundant once the standalone page landed and was removed
on 2026-05-02. It is a run-level table (Run id / Status / Started /
Completed / Rows In / Rows Out / Processed / Error), one row per run.
Node config — what each form does
The right pane swaps to a per-kind form when you click a node:- Source — Path / file mask / format / wait policy. If the parent connector already supplies the bucket (S3 / GCS / Azure), the form hides the bucket input and only asks for the prefix.
- Transform — Add op rows in order; each op has its own subform
(cast type, formula, rename pair, etc.). A collapsible Sample row
preview at the bottom takes one JSON row and shows the before /
after diff for each op (added / removed / changed fields highlighted).
Complex ops (
aggregate,lookup_join,vector_embed,geo_resolve,sentiment_score,language_detect) preview as “not previewable client-side — run the pipeline” because they need runtime context. Note thatsummarize,vector_embed,geo_resolve, andsentiment_scoreinllmmode are passthrough at runtime (they return rows unchanged until a provider is wired);aggregate,lookup_join,sentiment_scoreinrulemode, andlanguage_detectdo run. See Transforms. - Validate — Row-level rules (
notNull,regex,range,fieldType,maxLength), optional dataset-level row-count check, optional quarantine table for failed rows. The same Sample row preview at the bottom shows pass/fail per rule. - Enrich (Beta — not yet runnable) — Provider picker (
llm_tag/geocode/ml_score) with a per-provider config block. The output-field input checks the destination DataSchema in real time: if the column doesn’t exist, it shows a red “missing column” badge with an inline + Add as <dataType> button that POSTs to/api/v1/schemas/fieldswith a sensible default type (stringforllm_tag,floatforgeocodelat/lon andml_score). The form itself carries a BETA banner because the enrich executor throws at runtime — the providers are not wired in this build. The node validates and saves, but a pipeline that contains it will fail when run; remove the enrich node (or implement the provider call) before running. - Branch —
whenpredicate +thenroute per case, plus a default route. The route inputs are dropdowns populated from the current IR’s other nodes (excluding the branch itself and source nodes). Stale references (athenvalue that no longer matches any node id) render with a red border so they’re easy to spot and fix. - Target — Substantial form. Includes:
- Reads from Select listing every other node in the IR — so multi-target IRs (one source fan-out to multiple destinations) are editable in the visual surface.
- Schema name (
schema.table, defaults topublic.). - Load mode (
append/truncate/upsert/blue_green/incremental_watermark/cdc_mirror).cdc_mirrorapplies an op-column change feed — configure the op column and CDC key. See Loading Modes & Validation. - Full-refresh hard warning — picking
truncateon a one-source-one-target shape surfaces a recommend-blue_green banner with a one-click switch. failOnEmptySourceSwitch (default on) for destructive modes — aborts before TRUNCATE / blue_green when upstream is empty.backupBeforeLoadSwitch for destructive modes — opt-in pre-load snapshot to<table>_backup_<runId>with retain-N pruning.- Mode-specific config blocks:
upsertKey,watermarkColumn, and forcdc_mirrorthe op column (cdcOpColumn) + CDC key (upsertKey). - Inbound-FK probe when
blue_greenis picked — firesGET /api/v1/schemas/:id/incoming-fksand surfaces an amber warning listing referencing tables that would block the swap’s final DROP. - Inline mode-switch validation — empty
upsertKey, missing watermark column, all-keys upsert, etc. all surface as inline errors that block save.
- Outcomes — Inbound response-file ingestion (opens / clicks /
bounces / conversions / unsubscribes) into interaction history and
model learning; there is no output table. Includes:
- Reads from Select — the upstream node carrying the vendor rows (sources / transforms, not other sinks).
- Column mapping — a Resolve the offer by switch (Creative
token
_kaireon_ridor Offer id/name) that shows exactly one offer-resolution input, plus requiredcustomerId+outcomeKeyand optionalchannelId/timestamp/conversionValue/eventId. Cleared optional columns storeundefined(not"") so the IR’s.min(1)optionals don’t reject on save. A destructive inline error appears if neither offer-resolution column is set (mirrors the IRsuperRefine). - Attribution window (days) — number input,
1–365, default 7. - Suppression rules — an enable Switch (default on), the trigger
outcomeKeys, a mechanism select (consent_revoke/do_not_contact), and — forconsent_revoke— therevokePurposeslist. The column mapping references the upstream vendor file columns, so these inputs deliberately do not autocomplete from the destination schema (an outcomes node has no destination schema). See Pipeline IR → Outcomes node for the full behaviour.
Honest residuals
Documented gaps, deferred to follow-up plans:- Drag-to-create-edge / right-click “Delete” on the visual canvas.
- Pane collapse buttons (react-resizable-panels v4 typing settles).
- Run-over-run trend chart (hardening pass).
- Visual DAG highlight when clicking a lineage row (Wave 4 polish).
- Selective replay-from-DLQ runtime (
replayDlqOnlyflag). - Sample row preview’s
expressionop shows the formula text rather than evaluating client-side — the server-side formula engine is the source of truth and replicating it in the browser would risk drift. - The 1500-line
node-config-panel.tsxis partially extracted (constants + field-input primitives moved tocomponents/flow-editor/forms/); the per-kind subforms still live in the panel. Full per-form file split is a follow-up refactor.