import { apiFetch, type ApiSettings } from "@govoplan/core-webui"; export type DocsModuleArchitecture = { contract_version: string; layer: string; kind: string; maturity: string; evidence: Array<{ kind: string; reference: string; summary: string }>; known_limits: string[]; supported_authority_modes: string[]; owned_concepts: string[]; non_owned_concepts: string[]; reference_packages: string[]; target_tested_providers: string[]; documentation: Record; }; export type DocsExternalProvider = { id: string; module_id: string; label: string; maturity: string; operations: string[]; authority_modes: string[]; behavior?: Record; known_outage_behavior?: string | null; runtime_state?: { configured?: boolean; active?: boolean; authority_mode?: string | null; authority_modes?: string[]; health?: string; freshness?: string; conflict?: string; recovery?: string; observed_at?: string; } | null; }; export type DocsModule = { id: string; name: string; version: string; dependencies: string[]; optional_dependencies: string[]; permission_count: number; role_template_count: number; nav_count: number; route_count: number; frontend_package?: string | null; backend_route_contributed: boolean; migration_module_id?: string | null; capabilities: string[]; documentation_count: number; documentation_provider_count: number; architecture?: DocsModuleArchitecture | null; external_provider_count: number; external_providers: DocsExternalProvider[]; }; export type DocsRoute = { module_id: string; path: string; label: string; icon?: string | null; section?: string | null; source: string; component?: string | null; required_all: string[]; required_any: string[]; order: number; visible: boolean; reason: string; }; export type DocsPermission = { scope: string; label: string; description: string; category: string; level: "system" | "tenant"; module_id: string; resource: string; action: string; deprecated: boolean; granted: boolean; }; export type DocsOptionalModuleEvidence = { module_id: string; source_module_id: string; status: "installed" | "not_installed" | string; reason: string; }; export type DocsSource = { id: string; kind: string; owner_module_id: string; label: string; state: "configured" | "disabled" | "unavailable"; state_reason?: string | null; inspection_url: string; provenance: { source: string; version?: string | null; revision?: string | null; published_at?: string | null; checksum?: string | null; }; }; export type DocsSourceDetail = DocsSource & { visibility: { documentation_types: string[]; required_modules: string[]; any_modules: string[]; missing_modules: string[]; required_capabilities: string[]; required_scopes: string[]; any_scopes: string[]; configuration_keys: string[]; }; inspection: Record; }; export type DocsDocumentationCondition = { required_modules: string[]; any_modules: string[]; missing_modules: string[]; required_capabilities: string[]; required_scopes: string[]; any_scopes: string[]; configuration_keys: string[]; }; export type DocsDocumentationLink = { label: string; href: string; kind: string; }; export type DocsTopicKind = "workflow" | "reference" | "pattern" | "system" | string; export type DocsDocumentationTopic = { id: string; source_module_id: string; kind: DocsTopicKind; anchor_id: string; title: string; summary: string; body: string; layer: "always" | "configured" | "available" | "evidence" | string; target_layer: string; documentation_types: Array<"admin" | "user" | string>; active: boolean; reason: string; blockers: { modules: string[]; capabilities: string[]; scopes: string[]; configuration: string[]; }; audience: string[]; order: number; i18n_key: string; locale: string; translation_locale: string; structured_translation_locale: string; structured_translation_version?: string | null; version: { resolved: string; minimum?: string | null; maximum_exclusive?: string | null; range: string; fallback: "unversioned" | "matching_range" | string; }; conditions: DocsDocumentationCondition[]; links: DocsDocumentationLink[]; related_modules: string[]; unlocks: string[]; configuration_keys: string[]; configuration_states: Array<{ key: string; state: "enabled" | "disabled" | "inherited" | "unavailable"; source?: string | null; reason?: string | null; }>; metadata: Record; }; export type DocsContext = { versions: { mode: "installed" | "selected"; selected_version?: string | null; status: "installed" | "stable" | "older_supported" | "unsupported" | string; latest_version?: string | null; stable_version?: string | null; supported_versions: string[]; installed_versions: Record; fallback_policy: string; }; actor: { tenant_id?: string; user_id?: string; scope_count?: number; documentation_type: "admin" | "user"; locale: string; available_documentation_types: Array<"admin" | "user">; }; summary: { module_count: number; architecture_declared_module_count: number; external_provider_count: number; visible_route_count: number; available_route_count: number; permission_count: number; granted_permission_count: number; optional_module_count: number; documentation_topic_count: number; configured_documentation_topic_count: number; workflow_topic_count: number; reference_topic_count: number; pattern_topic_count: number; system_topic_count: number; }; topic_groups: { workflow: DocsDocumentationTopic[]; reference: DocsDocumentationTopic[]; pattern: DocsDocumentationTopic[]; system: DocsDocumentationTopic[]; [kind: string]: DocsDocumentationTopic[]; }; layers: { always: { documentation: DocsDocumentationTopic[]; }; configured: { modules: DocsModule[]; routes: DocsRoute[]; permissions: DocsPermission[]; documentation: DocsDocumentationTopic[]; }; available: { routes: DocsRoute[]; permissions: DocsPermission[]; documentation: DocsDocumentationTopic[]; }; evidence: { optional_modules: DocsOptionalModuleEvidence[]; sources: DocsSource[]; documentation: DocsDocumentationTopic[]; }; }; }; export function fetchDocsContext(settings: ApiSettings, options: { documentationType?: "admin" | "user"; locale?: string; version?: string | null } = {}): Promise { const params = new URLSearchParams(); if (options.documentationType) params.set("type", options.documentationType); if (options.locale) params.set("locale", options.locale); if (options.version) params.set("version", options.version); const query = params.toString(); return apiFetch(settings, `/api/v1/docs/context${query ? `?${query}` : ""}`); } export function fetchDocsSource( settings: ApiSettings, sourceId: string, options: { documentationType?: "admin" | "user"; locale?: string } = {} ): Promise { const params = new URLSearchParams(); if (options.documentationType) params.set("type", options.documentationType); if (options.locale) params.set("locale", options.locale); const query = params.toString(); return apiFetch( settings, `/api/v1/docs/sources/${encodeURIComponent(sourceId)}${query ? `?${query}` : ""}` ); } export type SemanticSubjectReference = { module_id: string; tenant_id: string; subject_kind: string; subject_id: string; anchor?: { kind: string; id: string } | null; observed_revision?: string | null; observed_fingerprint?: string | null; }; export type SemanticSubjectDescriptor = { reference: SemanticSubjectReference; labels: Record; descriptions: Record; route?: string | null; route_anchor?: string | null; }; export type SemanticContent = { title: string; summary: string; body: string; meaning: string; intended_use: string; non_intended_use: string; examples: string[]; owner_account_id: string | null; steward_account_id: string | null; audience: string[]; classification: "internal" | "restricted"; links: Array<{ label: string; href: string }>; }; export type SemanticEntry = { id: string; subject: SemanticSubjectReference; subject_resolution: { availability: "available" | "changed" | "superseded" | "missing" | "temporarily_unavailable"; reason_code?: string | null; }; locale: string; requested_locale: string; locale_fallback: boolean; lifecycle_state: "draft" | "published" | "superseded" | "retired"; pending_draft: boolean; current_revision: number; published_revision?: number | null; content: SemanticContent; content_redacted: boolean; updated_at: string; }; export async function fetchSemanticSubjects( settings: ApiSettings, query = "" ): Promise { const params = new URLSearchParams({ query }); const response = await apiFetch<{ providers: Array<{ subjects: SemanticSubjectDescriptor[] }> }>( settings, `/api/v1/docs/semantic/subjects?${params}` ); return response.providers.flatMap((provider) => provider.subjects); } export async function fetchSemanticEntries( settings: ApiSettings, locale: string, includeDrafts = true ): Promise { const params = new URLSearchParams({ locale, include_drafts: String(includeDrafts) }); const response = await apiFetch<{ items: SemanticEntry[] }>( settings, `/api/v1/docs/semantic/entries?${params}` ); return response.items; } export function createSemanticEntry( settings: ApiSettings, payload: { subject: SemanticSubjectReference; locale: string; content: SemanticContent; change_reason: string } ): Promise { return apiFetch(settings, "/api/v1/docs/semantic/entries", { method: "POST", body: JSON.stringify(payload) }); } export function updateSemanticEntry( settings: ApiSettings, entryId: string, payload: { expected_revision: number; content: SemanticContent; change_reason: string } ): Promise { return apiFetch(settings, `/api/v1/docs/semantic/entries/${encodeURIComponent(entryId)}`, { method: "PUT", body: JSON.stringify(payload) }); } export function transitionSemanticEntry( settings: ApiSettings, entryId: string, transition: "publish" | "retire", expectedRevision: number, changeReason: string ): Promise { return apiFetch( settings, `/api/v1/docs/semantic/entries/${encodeURIComponent(entryId)}/${transition}`, { method: "POST", body: JSON.stringify({ expected_revision: expectedRevision, change_reason: changeReason }) } ); }