202 lines
9.2 KiB
Markdown
202 lines
9.2 KiB
Markdown
# 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:
|
|
|
|
```bash
|
|
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:
|
|
|
|
```bash
|
|
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.
|