Add durable reconciliation decisions

This commit is contained in:
2026-08-06 12:42:20 +02:00
parent 3dae80b6b8
commit b14c693bde
14 changed files with 2037 additions and 19 deletions
+85
View File
@@ -205,6 +205,7 @@ export type TabularSource = {
columns: TabularSourceColumn[];
schema_version: string;
fingerprint: string;
decisions_included: boolean;
row_count?: number | null;
byte_count?: number | null;
updated_at?: string | null;
@@ -217,6 +218,38 @@ export type TabularSourceCatalogue = {
sources: TabularSource[];
};
export type ReconciliationDecisionAction = "accept" | "reject" | "correct" | "defer";
export type ReconciliationDecision = {
ref: string;
id: string;
revision: number;
key_hash: string;
input_hash: string;
action: ReconciliationDecisionAction;
reason: string;
correction?: Record<string, unknown> | null;
actor_ref: string;
decided_at: string;
};
export type ReconciliationDecisionSet = {
ref: string;
id: string;
pipeline_id: string;
name: string;
node_id?: string | null;
resource_revision: number;
etag: string;
fingerprint: string;
current_decisions: ReconciliationDecision[];
history: ReconciliationDecision[];
created_by?: string | null;
updated_by?: string | null;
created_at: string;
updated_at: string;
};
export type PipelineRun = {
ref: string;
pipeline_id: string;
@@ -363,6 +396,58 @@ export function createDataflowSourceSnapshot(
});
}
export async function listDataflowDecisionSets(
settings: ApiSettings,
pipelineId: string
): Promise<ReconciliationDecisionSet[]> {
const response = await apiFetch<{ decision_sets: ReconciliationDecisionSet[] }>(
settings,
`/api/v1/dataflow/pipelines/${encodeURIComponent(pipelineId)}/decision-sets`
);
return response.decision_sets;
}
export function createDataflowDecisionSet(
settings: ApiSettings,
pipelineId: string,
payload: { name: string; node_id?: string | null }
): Promise<ReconciliationDecisionSet> {
return apiFetch(
settings,
`/api/v1/dataflow/pipelines/${encodeURIComponent(pipelineId)}/decision-sets`,
{ method: "POST", body: JSON.stringify(payload) }
);
}
export function getDataflowDecisionSet(
settings: ApiSettings,
decisionSetId: string
): Promise<ReconciliationDecisionSet> {
return apiFetch(
settings,
`/api/v1/dataflow/decision-sets/${encodeURIComponent(decisionSetId)}`
);
}
export function recordDataflowDecision(
settings: ApiSettings,
decisionSetId: string,
payload: {
base_revision: number;
key_hash: string;
input_hash: string;
action: ReconciliationDecisionAction;
reason: string;
correction?: Record<string, unknown> | null;
}
): Promise<ReconciliationDecisionSet> {
return apiFetch(
settings,
`/api/v1/dataflow/decision-sets/${encodeURIComponent(decisionSetId)}/decisions`,
{ method: "POST", body: JSON.stringify(payload) }
);
}
export async function listDataflowPipelines(settings: ApiSettings): Promise<Pipeline[]> {
const response = await apiFetch<{ pipelines: Pipeline[] }>(settings, "/api/v1/dataflow/pipelines");
return response.pipelines;