feat: implement governed datasource catalogue metadata

This commit is contained in:
2026-08-01 17:48:28 +02:00
parent 8da8035693
commit 98d93e707f
14 changed files with 1382 additions and 12 deletions
+60 -2
View File
@@ -5,6 +5,39 @@ import {
export type DatasourceMode = "live" | "cached" | "static";
export type DatasourceShape = "tabular" | "document" | "binary" | "directory" | "stream";
export type SourceAuthorityMode =
| "native_authoritative"
| "external_authoritative"
| "external_mirror"
| "governed_sync"
| "governance_overlay"
| "linked_reference";
export type DatasourceGovernance = {
owner_ref?: string | null;
steward_ref?: string | null;
responsible_organization_ref?: string | null;
responsible_function_ref?: string | null;
authoritative_source_ref?: string | null;
authority_mode: SourceAuthorityMode;
legal_basis_refs: string[];
purposes: string[];
semantic_definition?: string | null;
schema_owner_ref?: string | null;
official_keys: string[];
classification: string;
privacy_profile_ref?: string | null;
retention_policy_ref?: string | null;
hold_refs: string[];
publication_state: string;
transfer_agreement_ref?: string | null;
freshness_policy: Record<string, unknown>;
quality_policy: Record<string, unknown>;
known_limits: string[];
correction_procedure_ref?: string | null;
affected_refs: string[];
dependency_refs: string[];
};
export type DatasourceField = {
name: string;
@@ -33,6 +66,7 @@ export type Datasource = {
capabilities: string[];
provenance: Record<string, unknown>;
metadata: Record<string, unknown>;
governance: DatasourceGovernance;
};
export type DatasourceMaterialization = {
@@ -50,6 +84,7 @@ export type DatasourceMaterialization = {
created_at?: string | null;
provenance: Record<string, unknown>;
metadata: Record<string, unknown>;
governance: DatasourceGovernance;
};
export type DatasourceStage = {
@@ -71,6 +106,7 @@ export type DatasourceStage = {
promoted_materialization_ref?: string | null;
provenance: Record<string, unknown>;
metadata: Record<string, unknown>;
governance: DatasourceGovernance;
};
export type DatasourceOrigin = {
@@ -102,9 +138,18 @@ export type DatasourcePreview = {
export async function listDatasources(
settings: ApiSettings,
query = ""
query = "",
filters: Partial<Pick<DatasourceGovernance, "authority_mode" | "classification" | "publication_state" | "owner_ref" | "responsible_organization_ref">> & {
affected_ref?: string;
dependency_ref?: string;
} = {}
): Promise<Datasource[]> {
const suffix = query.trim() ? `?query=${encodeURIComponent(query.trim())}` : "";
const params = new URLSearchParams();
if (query.trim()) params.set("query", query.trim());
for (const [key, value] of Object.entries(filters)) {
if (String(value ?? "").trim()) params.set(key, String(value).trim());
}
const suffix = params.size ? `?${params.toString()}` : "";
const response = await apiFetch<{ datasources: Datasource[] }>(
settings,
`/api/v1/datasources${suffix}`
@@ -158,6 +203,7 @@ export function createDatasourceStage(
description?: string | null;
mode: "static" | "cached";
target_datasource_ref?: string | null;
governance?: DatasourceGovernance | null;
} & (
{ format: "json"; rows: Record<string, unknown>[] }
| { format: "csv"; csv_text: string; delimiter: string }
@@ -188,6 +234,7 @@ export function registerDatasourceOrigin(
source_name: string;
mode: "live" | "cached";
description?: string | null;
governance?: DatasourceGovernance | null;
}
): Promise<Datasource> {
return apiFetch(settings, "/api/v1/datasources/origins/register", {
@@ -225,6 +272,17 @@ export function retireDatasource(
});
}
export function updateDatasourceGovernance(
settings: ApiSettings,
datasourceRef: string,
governance: DatasourceGovernance
): Promise<Datasource> {
return apiFetch(settings, `/api/v1/datasources/${refId(datasourceRef)}/governance`, {
method: "PATCH",
body: JSON.stringify({ governance })
});
}
function refId(ref: string): string {
const separator = ref.indexOf(":");
return encodeURIComponent(separator >= 0 ? ref.slice(separator + 1) : ref);