Add governed organization template upgrades

This commit is contained in:
2026-08-04 01:46:36 +02:00
parent 97acfcba7d
commit fcfd67b0b5
17 changed files with 2357 additions and 6 deletions
+110
View File
@@ -135,6 +135,81 @@ export type OrganizationModel = {
functions: OrganizationFunctionItem[];
};
export type OrganizationTemplateVersion = {
id: string;
template_id: string;
version: string;
status: string;
definition_sha256: string;
release_notes?: string | null;
published_at?: string | null;
};
export type OrganizationTemplateCatalogItem = {
id: string;
slug: string;
name: string;
description?: string | null;
versions: OrganizationTemplateVersion[];
};
export type OrganizationTemplateCatalog = {
templates: OrganizationTemplateCatalogItem[];
};
export type OrganizationModelInstantiation = {
id: string;
tenant_id: string;
template_id: string;
template_version_id: string;
source_definition_sha256: string;
status: string;
object_counts: Record<string, number>;
provenance: Record<string, unknown>;
created_at: string;
updated_at: string;
};
export type OrganizationUpgradeDecisionAction = "keep_local" | "use_target" | "map_to";
export type OrganizationUpgradeDiffEntry = {
id: string;
collection: string;
key: string;
classification: string;
requires_decision: boolean;
base?: Record<string, unknown> | null;
local?: Record<string, unknown> | null;
target?: Record<string, unknown> | null;
allowed_actions: OrganizationUpgradeDecisionAction[];
};
export type OrganizationModelUpgrade = {
id: string;
tenant_id: string;
template_id: string;
source_instantiation_id: string;
source_template_version_id: string;
target_template_version_id: string;
status: string;
revision: number;
preview: {
entries: OrganizationUpgradeDiffEntry[];
counts: Record<string, number>;
requires_decisions: number;
blocking_invalid_references: number;
silent_mutation: boolean;
};
decisions: Record<string, { action: OrganizationUpgradeDecisionAction; target_key?: string | null }>;
created_at: string;
updated_at: string;
};
export type OrganizationModelUpgradeList = {
current_instantiation?: OrganizationModelInstantiation | null;
upgrades: OrganizationModelUpgrade[];
};
export type OrganizationChangeRequestPayload = {
change_request_id?: string | null;
};
@@ -190,6 +265,41 @@ export function getOrganizationModel(settings: ApiSettings): Promise<Organizatio
return apiFetch<OrganizationModel>(settings, "/api/v1/organizations/model");
}
export function getOrganizationTemplateCatalog(settings: ApiSettings): Promise<OrganizationTemplateCatalog> {
return apiFetch<OrganizationTemplateCatalog>(settings, "/api/v1/organizations/model-templates");
}
export function getOrganizationModelUpgrades(settings: ApiSettings): Promise<OrganizationModelUpgradeList> {
return apiFetch<OrganizationModelUpgradeList>(settings, "/api/v1/organizations/model-upgrades");
}
export function previewOrganizationModelUpgrade(settings: ApiSettings, targetTemplateVersionId: string): Promise<OrganizationModelUpgrade> {
return apiPostJson(settings, "/api/v1/organizations/model-upgrades/preview", {
target_template_version_id: targetTemplateVersionId,
idempotency_key: crypto.randomUUID()
});
}
export function cancelOrganizationModelUpgrade(settings: ApiSettings, upgradeId: string, expectedRevision: number): Promise<OrganizationModelUpgrade> {
return apiPostJson(settings, `/api/v1/organizations/model-upgrades/${encodeURIComponent(upgradeId)}/cancel`, {
expected_revision: expectedRevision
});
}
export function applyOrganizationModelUpgrade(
settings: ApiSettings,
upgradeId: string,
expectedRevision: number,
decisions: Record<string, { action: OrganizationUpgradeDecisionAction; target_key?: string }>,
changeRequestId?: string
): Promise<{ upgrade: OrganizationModelUpgrade; instantiation: OrganizationModelInstantiation }> {
return apiPostJson(settings, `/api/v1/organizations/model-upgrades/${encodeURIComponent(upgradeId)}/apply`, {
expected_revision: expectedRevision,
decisions,
change_request_id: changeRequestId || null
});
}
export function getOrganizationSettings(settings: ApiSettings): Promise<OrganizationSettingsItem> {
return apiFetch<OrganizationSettingsItem>(settings, "/api/v1/organizations/settings");
}