Files
govoplan/docs/architecture/PLATFORM_CONTROL_PLANE.md
zemion c66e1b768d
Dependency Audit / dependency-audit (push) Successful in 1m46s
Deployment Installer / deployment-installer (push) Successful in 9s
Security Audit / security-audit (push) Successful in 11m48s
docs: organize cross-product documentation
2026-08-17 16:52:51 +02:00

9.2 KiB

Platform Control Plane And Self-Description

Objective

GovOPlaN should be able to describe its installed structure without becoming a self-modifying application. The platform model is a declarative control plane: module manifests, UI contributions, schemas, policy provenance, runtime capabilities, and generated source evidence describe what can be configured. Ordinary administrators edit validated data through those contracts; they do not edit Python, TypeScript, routes, or database code from the product UI.

This distinction provides the requested overview while preserving reviewable releases, module boundaries, migrations, and security controls.

Canonical Sources

Concern Canonical source
Installed modules and dependency graph Runtime ModuleManifest registry
Backend routes Registered FastAPI application; Python AST is build-time evidence
Frontend routes and navigation PlatformWebModule contributions
View-filterable regions Versioned viewSurfaces declarations
Admin sections and module settings admin.sections, including moduleId, kind, scope group, permission guards, and surface ID
User settings settings.sections and core settings schemas
Labels and translations Generated translation catalogs plus source usage
Fields and help coverage Shared form components plus generated TypeScript AST inventory
API use by the WebUI Typed API clients plus generated static reference inventory
Stable platform interface IDs Typed manifest/WebUI declarations plus line-independent source anchors for low-level controls
Effective configuration Owning module data plus Policy provenance

Runtime introspection is authoritative for an installed system. Static source inventory is authoritative evidence for a checkout or release candidate. The two should be compared in CI and by Ops, not conflated.

Generated Inventory

Run:

cd /mnt/DATA/git/govoplan
./.venv/bin/python tools/inventory/platform-interface-inventory.py

The command writes:

  • audit-reports/platform-inventory/platform-interface-inventory.json
  • audit-reports/platform-inventory/platform-interface-inventory.md

Use --strict for the combined translation, endpoint, and declaration audit. Use --strict-declarations for duplicate/stale/undeclared interface checks without making existing translation coverage a release blocker. Use --strict-endpoints in the endpoint-surface CI gate so unrelated translation catalog work cannot disable route classification enforcement. Both strict modes require every backend endpoint without a statically visible WebUI path to have an exact entry in tools/inventory/endpoint-surface-declarations.json. The registry is keyed by repository, HTTP method, and canonical version-independent path. It accepts:

  • ui_reachable: a mounted router, generic action, or provider path hides the reference from static extraction;
  • intentionally_headless: a capability/API is deliberately consumed without its own UI;
  • public_integration: a documented public or interoperability endpoint;
  • worker_internal: a worker, scheduler, reconciliation, or monitoring path;
  • compatibility: a retained transition endpoint with a current replacement;
  • missing_ui: a real UI gap, which must include a Gitea tracking issue;
  • removable: a reviewed dead endpoint pending removal.

Strict mode also rejects declarations that no longer match source. When an endpoint is added, changed, or removed, update its declaration in the same change. Do not classify an endpoint from a string mismatch alone: first check mounted prefixes, dynamic action paths, public clients, worker use, and capability consumers.

It combines:

  1. loaded module manifests
  2. TypeScript AST extraction of fields, label attributes, visible text, translations, frontend routes, navigation, capabilities, and API references
  3. Python AST extraction of FastAPI route decorators and router prefixes
  4. normalized runtime declarations from every loaded ModuleManifest

The declaration set covers routes, navigation, View surfaces, fields, actions, help references, translations, admin/settings sections, widgets, search objects, permissions, provided interfaces, and backend capabilities. Typed module contributions keep their declared IDs. Shared controls may declare interfaceId and helpTopicId; otherwise the extractor assigns a deterministic source anchor based on repository, file, component context, control type, and semantic label rather than a line number. The JSON records which identity source was used.

The JSON includes exact repository, file, and line evidence. A missing-help entry is a review candidate because dynamic parent components may supply help. A backend route without a static frontend reference is also a review candidate: public APIs, workers, callbacks, health checks, connectors, and dynamic URL assembly are valid explanations.

The module matrix enforces endpoint and interface declarations with --strict-endpoints --strict-declarations. Combined --strict additionally fails when used translation keys are absent from generated locale catalogs. Help-text findings remain review candidates rather than a release gate because dynamic parent components can supply help.

Runtime Comparison

Core exposes a sanitized read-only catalog at GET /api/v1/platform/interface-catalog. Access requires admin:module:read or system:settings:read. Tenant module entitlements are applied before serialization, so the response describes only the effective installed combination. It contains IDs, paths, authorization metadata, versions, counts, and canonical digests; it excludes factories, callbacks, credentials, and mutable runtime state.

Capture and compare a running installation:

curl --fail --silent \
  -H "Authorization: Bearer $GOVOPLAN_ACCESS_TOKEN" \
  "$GOVOPLAN_URL/api/v1/platform/interface-catalog" \
  > /tmp/govoplan-runtime-interface.json

./.venv/bin/python tools/inventory/platform-interface-inventory.py \
  --runtime-snapshot /tmp/govoplan-runtime-interface.json \
  --strict-declarations \
  --strict-endpoints

The comparison accepts any installed subset. Every module present in the runtime response must have the same contract version, module version, and declaration digest as the static release inventory. Unknown, duplicate, or mismatched runtime modules fail strict declaration mode.

Admin Information Architecture

The Admin host uses a tree because system, tenant, group, user, and module settings form a hierarchy rather than one flat list. Every contributed section can identify:

  • its owning moduleId
  • whether it is management or settings
  • its system/tenant/group/user scope group
  • an optional future parentId
  • permission and View visibility requirements

Existing panels remain their own render owners. The tree only changes discovery and grouping. A later embedded-settings contract may add named slots inside an owning page; it must not allow one module to import another module's private component.

Navigation And Workflow

The intended maximum visible navigation stack is:

  1. global shell context
  2. one task/object navigation surface
  3. one workflow stage surface when a workflow is active

Workflow instance pages should reuse the Campaign stage language: clear stage state, optional/skipped/blocked semantics, partial progress, and a stable current step. Workflow definition pages remain graph editors. Views may activate a focused workflow view that suppresses unrelated shell and module surfaces while retaining an explicit way out.

Nested module submenus should not be added merely because a data hierarchy exists. Prefer a tree inside configuration/directory surfaces, tabs for sibling views, and the workflow stage rail for ordered work.

Safe Meta-Configuration

The platform can eventually render many configuration editors from versioned JSON Schema and UI Schema supplied by modules. Generated editors remain bounded by:

  • explicit typed schemas and migrations
  • module-owned validation and preview
  • Policy locks and provenance
  • permission and View filtering
  • preflight, consequence, and rollback information
  • auditable apply operations

Custom code, new routes, arbitrary SQL, and executable workflow nodes remain release artifacts. Modeling them as ordinary configuration would create an unreviewed code-execution and migration channel.

Enforced Contract

  1. Public WebUI routes and View surfaces must reconcile with runtime manifest metadata; stale runtime routes and source-only public surfaces fail CI.
  2. Duplicate stable IDs fail CI. Shared controls support explicit field/action and help-topic identities; fallback anchors remain visible review evidence.
  3. Every statically unreferenced backend endpoint has an exact reviewed consumer classification, and stale classifications fail CI.
  4. Runtime module combinations can be compared exactly with static release evidence through versioned per-module digests.
  5. Runtime introspection is authorized, tenant-filtered, and read-only. It is safe for Ops/Docs projection but is not a generic configuration or code mutation channel.

Generated JSON and Markdown remain build/audit artifacts. Do not hand-edit or use them as a backlog; change the owning manifest, typed WebUI contribution, translation/help declaration, or exact endpoint classification instead.