Complete governed reporting execution and publication

This commit is contained in:
2026-08-04 02:23:24 +02:00
parent a81151391b
commit 8337aec19a
29 changed files with 3611 additions and 81 deletions
+146
View File
@@ -103,9 +103,69 @@ export type ReportExecution = {
kind: string;
requested_kind?: string;
category?: string | null;
series?: string | null;
measures?: string[];
options?: Record<string, unknown>;
fallback_reason?: string | null;
};
delivery_authorization?: Record<string, unknown>;
};
export type ReportingDrillContext = {
token: string;
drill_context_id: string;
execution_id: string;
dimension_path: Array<{ dimension: string; label: string; value: unknown }>;
expires_at: string;
};
export type ReportingDrillResult = Omit<ReportingDrillContext, "token"> & {
rows: Array<Record<string, unknown>>;
schema: Array<{ name: string; type: string }>;
total_rows: number;
truncated: boolean;
source_fingerprints: Array<Record<string, unknown>>;
policy_provenance: Record<string, unknown>;
};
export type ReportingSchedule = {
schedule_id: string;
report_id: string;
report_revision: number;
name: string;
revision: number;
trigger_kind: "scheduled" | "interval";
trigger_config: Record<string, unknown>;
parameters: Record<string, unknown>;
query: ReportingQuery;
publication_target: Record<string, unknown>;
enabled: boolean;
next_run_at?: string | null;
last_run_at?: string | null;
last_execution_id?: string | null;
};
export type ReportingPublicationTarget = {
capability: string;
label: string;
available: boolean;
reason?: string | null;
formats: string[];
target_label: string;
target_required: boolean;
required_options: string[];
};
export type ReportingPublication = {
publication_id: string;
execution_id: string;
target_capability: string;
target_ref?: string | null;
format: string;
status: string;
evidence: Record<string, unknown>;
error?: string | null;
completed_at?: string | null;
};
export type ReportingSavedView = {
@@ -307,6 +367,26 @@ export function listExecutions(
return apiFetch(settings, `/api/v1/reporting/reports/${encodeURIComponent(reportId)}/executions?limit=30`, { signal });
}
export function createDrillContext(
settings: ApiSettings,
executionId: string,
aggregateRow: Record<string, unknown>,
limit = 200
): Promise<ReportingDrillContext> {
return apiFetch(settings, `/api/v1/reporting/executions/${encodeURIComponent(executionId)}/drill-contexts`, {
method: "POST",
body: JSON.stringify({ aggregate_row: aggregateRow, limit })
});
}
export function resolveDrillContext(
settings: ApiSettings,
token: string,
signal?: AbortSignal
): Promise<ReportingDrillResult> {
return apiFetch(settings, `/api/v1/reporting/drill-contexts/${encodeURIComponent(token)}`, { signal });
}
export function listSavedViews(
settings: ApiSettings,
reportId: string,
@@ -364,6 +444,72 @@ export function createIntervalSchedule(
});
}
export function listSchedules(
settings: ApiSettings,
reportId: string,
signal?: AbortSignal
): Promise<{ schedules: ReportingSchedule[] }> {
return apiFetch(settings, apiPath("/api/v1/reporting/schedules", { report_id: reportId }), { signal });
}
export function updateSchedule(
settings: ApiSettings,
schedule: ReportingSchedule,
changes: Partial<Pick<ReportingSchedule, "enabled" | "name">>
): Promise<ReportingSchedule> {
return apiFetch(settings, `/api/v1/reporting/schedules/${encodeURIComponent(schedule.schedule_id)}`, {
method: "PUT",
body: JSON.stringify({
schedule_id: schedule.schedule_id,
report_id: schedule.report_id,
report_revision: schedule.report_revision,
name: changes.name ?? schedule.name,
trigger_kind: schedule.trigger_kind,
trigger_config: schedule.trigger_config,
parameters: schedule.parameters,
query: schedule.query,
publication_target: schedule.publication_target,
enabled: changes.enabled ?? schedule.enabled,
next_run_at: schedule.next_run_at ?? null,
expected_revision: schedule.revision
})
});
}
export function listPublicationTargets(
settings: ApiSettings,
signal?: AbortSignal
): Promise<{ targets: ReportingPublicationTarget[] }> {
return apiFetch(settings, "/api/v1/reporting/publication-targets", { signal });
}
export function listPublications(
settings: ApiSettings,
executionId: string,
signal?: AbortSignal
): Promise<{ publications: ReportingPublication[] }> {
return apiFetch(settings, apiPath("/api/v1/reporting/publications", { execution_id: executionId }), { signal });
}
export function publishExecution(
settings: ApiSettings,
executionId: string,
request: {
target_capability: string;
target_ref?: string | null;
format: string;
options: Record<string, unknown>;
}
): Promise<ReportingPublication> {
return apiFetch(settings, `/api/v1/reporting/executions/${encodeURIComponent(executionId)}/publications`, {
method: "POST",
body: JSON.stringify({
...request,
idempotency_key: crypto.randomUUID()
})
});
}
export async function downloadExecution(
settings: ApiSettings,
executionId: string,