Sync wiki from project files
@@ -14,28 +14,39 @@ This page is generated from repository and product-directory project files.
|
|||||||
- [Repo-docs-COMPATIBILITY-INVENTORY](Repo-docs-COMPATIBILITY-INVENTORY) - `/mnt/DATA/git/govoplan-core/docs/COMPATIBILITY_INVENTORY.md`
|
- [Repo-docs-COMPATIBILITY-INVENTORY](Repo-docs-COMPATIBILITY-INVENTORY) - `/mnt/DATA/git/govoplan-core/docs/COMPATIBILITY_INVENTORY.md`
|
||||||
- [Repo-docs-COMPATIBILITY-POLICY](Repo-docs-COMPATIBILITY-POLICY) - `/mnt/DATA/git/govoplan-core/docs/COMPATIBILITY_POLICY.md`
|
- [Repo-docs-COMPATIBILITY-POLICY](Repo-docs-COMPATIBILITY-POLICY) - `/mnt/DATA/git/govoplan-core/docs/COMPATIBILITY_POLICY.md`
|
||||||
- [Repo-docs-CONFIGURATION-PACKAGES](Repo-docs-CONFIGURATION-PACKAGES) - `/mnt/DATA/git/govoplan-core/docs/CONFIGURATION_PACKAGES.md`
|
- [Repo-docs-CONFIGURATION-PACKAGES](Repo-docs-CONFIGURATION-PACKAGES) - `/mnt/DATA/git/govoplan-core/docs/CONFIGURATION_PACKAGES.md`
|
||||||
|
- [Repo-docs-CONTEXTUAL-HELP-CONTRACT](Repo-docs-CONTEXTUAL-HELP-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/CONTEXTUAL_HELP_CONTRACT.md`
|
||||||
- [Repo-docs-DATAGRID-SIZING-CONTRACT](Repo-docs-DATAGRID-SIZING-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/DATAGRID_SIZING_CONTRACT.md`
|
- [Repo-docs-DATAGRID-SIZING-CONTRACT](Repo-docs-DATAGRID-SIZING-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/DATAGRID_SIZING_CONTRACT.md`
|
||||||
- [Repo-docs-DEPENDENCY-AUDITS](Repo-docs-DEPENDENCY-AUDITS) - `/mnt/DATA/git/govoplan-core/docs/DEPENDENCY_AUDITS.md`
|
- [Repo-docs-DEPENDENCY-AUDITS](Repo-docs-DEPENDENCY-AUDITS) - `/mnt/DATA/git/govoplan-core/docs/DEPENDENCY_AUDITS.md`
|
||||||
- [Repo-docs-DEPLOYMENT-OPERATOR-GUIDE](Repo-docs-DEPLOYMENT-OPERATOR-GUIDE) - `/mnt/DATA/git/govoplan-core/docs/DEPLOYMENT_OPERATOR_GUIDE.md`
|
- [Repo-docs-DEPLOYMENT-OPERATOR-GUIDE](Repo-docs-DEPLOYMENT-OPERATOR-GUIDE) - `/mnt/DATA/git/govoplan-core/docs/DEPLOYMENT_OPERATOR_GUIDE.md`
|
||||||
- [Repo-docs-DOCUMENTATION-MAP](Repo-docs-DOCUMENTATION-MAP) - `/mnt/DATA/git/govoplan-core/docs/DOCUMENTATION_MAP.md`
|
- [Repo-docs-DOCUMENTATION-MAP](Repo-docs-DOCUMENTATION-MAP) - `/mnt/DATA/git/govoplan-core/docs/DOCUMENTATION_MAP.md`
|
||||||
|
- [Repo-docs-DURABLE-RECOVERY-OPERATIONS](Repo-docs-DURABLE-RECOVERY-OPERATIONS) - `/mnt/DATA/git/govoplan-core/docs/DURABLE_RECOVERY_OPERATIONS.md`
|
||||||
- [Repo-docs-EVENTS-AND-AUDIT](Repo-docs-EVENTS-AND-AUDIT) - `/mnt/DATA/git/govoplan-core/docs/EVENTS_AND_AUDIT.md`
|
- [Repo-docs-EVENTS-AND-AUDIT](Repo-docs-EVENTS-AND-AUDIT) - `/mnt/DATA/git/govoplan-core/docs/EVENTS_AND_AUDIT.md`
|
||||||
- [Repo-docs-EXTERNAL-REFERENCES-AND-INTEGRATION-MATURITY](Repo-docs-EXTERNAL-REFERENCES-AND-INTEGRATION-MATURITY) - `/mnt/DATA/git/govoplan-core/docs/EXTERNAL_REFERENCES_AND_INTEGRATION_MATURITY.md`
|
- [Repo-docs-EXTERNAL-REFERENCES-AND-INTEGRATION-MATURITY](Repo-docs-EXTERNAL-REFERENCES-AND-INTEGRATION-MATURITY) - `/mnt/DATA/git/govoplan-core/docs/EXTERNAL_REFERENCES_AND_INTEGRATION_MATURITY.md`
|
||||||
- [Repo-docs-GITEA-ISSUES](Repo-docs-GITEA-ISSUES) - `/mnt/DATA/git/govoplan-core/docs/GITEA_ISSUES.md`
|
- [Repo-docs-GITEA-ISSUES](Repo-docs-GITEA-ISSUES) - `/mnt/DATA/git/govoplan-core/docs/GITEA_ISSUES.md`
|
||||||
- [Repo-docs-GOVERNANCE-MODEL](Repo-docs-GOVERNANCE-MODEL) - `/mnt/DATA/git/govoplan-core/docs/GOVERNANCE_MODEL.md`
|
- [Repo-docs-GOVERNANCE-MODEL](Repo-docs-GOVERNANCE-MODEL) - `/mnt/DATA/git/govoplan-core/docs/GOVERNANCE_MODEL.md`
|
||||||
- [Repo-docs-GOVOPLAN-MASTER-ROADMAP](Repo-docs-GOVOPLAN-MASTER-ROADMAP) - `/mnt/DATA/git/govoplan-core/docs/GOVOPLAN_MASTER_ROADMAP.md`
|
- [Repo-docs-GOVOPLAN-MASTER-ROADMAP](Repo-docs-GOVOPLAN-MASTER-ROADMAP) - `/mnt/DATA/git/govoplan-core/docs/GOVOPLAN_MASTER_ROADMAP.md`
|
||||||
|
- [Repo-docs-INFORMATION-GOVERNANCE-ADOPTION](Repo-docs-INFORMATION-GOVERNANCE-ADOPTION) - `/mnt/DATA/git/govoplan-core/docs/INFORMATION_GOVERNANCE_ADOPTION.md`
|
||||||
- [Repo-docs-INSTITUTIONAL-CONTEXT-CONTRACT](Repo-docs-INSTITUTIONAL-CONTEXT-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/INSTITUTIONAL_CONTEXT_CONTRACT.md`
|
- [Repo-docs-INSTITUTIONAL-CONTEXT-CONTRACT](Repo-docs-INSTITUTIONAL-CONTEXT-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/INSTITUTIONAL_CONTEXT_CONTRACT.md`
|
||||||
- [Repo-docs-INTERFACE-ETHICS-AND-DESIGN-DOCTRINE](Repo-docs-INTERFACE-ETHICS-AND-DESIGN-DOCTRINE) - `/mnt/DATA/git/govoplan-core/docs/INTERFACE_ETHICS_AND_DESIGN_DOCTRINE.md`
|
- [Repo-docs-INTERFACE-ETHICS-AND-DESIGN-DOCTRINE](Repo-docs-INTERFACE-ETHICS-AND-DESIGN-DOCTRINE) - `/mnt/DATA/git/govoplan-core/docs/INTERFACE_ETHICS_AND_DESIGN_DOCTRINE.md`
|
||||||
|
- [Repo-docs-INTERFACE-PATTERN-MIGRATION](Repo-docs-INTERFACE-PATTERN-MIGRATION) - `/mnt/DATA/git/govoplan-core/docs/INTERFACE_PATTERN_MIGRATION.md`
|
||||||
|
- [Repo-docs-LOCALIZATION-AND-HELP-QUALITY](Repo-docs-LOCALIZATION-AND-HELP-QUALITY) - `/mnt/DATA/git/govoplan-core/docs/LOCALIZATION_AND_HELP_QUALITY.md`
|
||||||
- [Repo-docs-MODULE-ARCHITECTURE](Repo-docs-MODULE-ARCHITECTURE) - `/mnt/DATA/git/govoplan-core/docs/MODULE_ARCHITECTURE.md`
|
- [Repo-docs-MODULE-ARCHITECTURE](Repo-docs-MODULE-ARCHITECTURE) - `/mnt/DATA/git/govoplan-core/docs/MODULE_ARCHITECTURE.md`
|
||||||
|
- [Repo-docs-MODULE-LIFECYCLE-RECOVERY](Repo-docs-MODULE-LIFECYCLE-RECOVERY) - `/mnt/DATA/git/govoplan-core/docs/MODULE_LIFECYCLE_RECOVERY.md`
|
||||||
- [Repo-docs-POLICY-CONTRACTS](Repo-docs-POLICY-CONTRACTS) - `/mnt/DATA/git/govoplan-core/docs/POLICY_CONTRACTS.md`
|
- [Repo-docs-POLICY-CONTRACTS](Repo-docs-POLICY-CONTRACTS) - `/mnt/DATA/git/govoplan-core/docs/POLICY_CONTRACTS.md`
|
||||||
- [Repo-docs-POSTBOX-E2EE-ARCHITECTURE](Repo-docs-POSTBOX-E2EE-ARCHITECTURE) - `/mnt/DATA/git/govoplan-core/docs/POSTBOX_E2EE_ARCHITECTURE.md`
|
- [Repo-docs-POSTBOX-E2EE-ARCHITECTURE](Repo-docs-POSTBOX-E2EE-ARCHITECTURE) - `/mnt/DATA/git/govoplan-core/docs/POSTBOX_E2EE_ARCHITECTURE.md`
|
||||||
- [Repo-docs-PUBLIC-SECTOR-INTEGRATION-STRATEGY](Repo-docs-PUBLIC-SECTOR-INTEGRATION-STRATEGY) - `/mnt/DATA/git/govoplan-core/docs/PUBLIC_SECTOR_INTEGRATION_STRATEGY.md`
|
- [Repo-docs-PUBLIC-SECTOR-INTEGRATION-STRATEGY](Repo-docs-PUBLIC-SECTOR-INTEGRATION-STRATEGY) - `/mnt/DATA/git/govoplan-core/docs/PUBLIC_SECTOR_INTEGRATION_STRATEGY.md`
|
||||||
- [Repo-docs-RELEASE-DEPENDENCIES](Repo-docs-RELEASE-DEPENDENCIES) - `/mnt/DATA/git/govoplan-core/docs/RELEASE_DEPENDENCIES.md`
|
- [Repo-docs-RELEASE-DEPENDENCIES](Repo-docs-RELEASE-DEPENDENCIES) - `/mnt/DATA/git/govoplan-core/docs/RELEASE_DEPENDENCIES.md`
|
||||||
- [Repo-docs-REMOTE-WEBUI-BUNDLES](Repo-docs-REMOTE-WEBUI-BUNDLES) - `/mnt/DATA/git/govoplan-core/docs/REMOTE_WEBUI_BUNDLES.md`
|
- [Repo-docs-REMOTE-WEBUI-BUNDLES](Repo-docs-REMOTE-WEBUI-BUNDLES) - `/mnt/DATA/git/govoplan-core/docs/REMOTE_WEBUI_BUNDLES.md`
|
||||||
|
- [Repo-docs-SEARCH-EVENT-INDEXING-CONTRACT](Repo-docs-SEARCH-EVENT-INDEXING-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/SEARCH_EVENT_INDEXING_CONTRACT.md`
|
||||||
- [Repo-docs-SECURITY-AUDIT](Repo-docs-SECURITY-AUDIT) - `/mnt/DATA/git/govoplan-core/docs/SECURITY_AUDIT.md`
|
- [Repo-docs-SECURITY-AUDIT](Repo-docs-SECURITY-AUDIT) - `/mnt/DATA/git/govoplan-core/docs/SECURITY_AUDIT.md`
|
||||||
- [Repo-docs-SELF-HOSTED-INSTALLABILITY](Repo-docs-SELF-HOSTED-INSTALLABILITY) - `/mnt/DATA/git/govoplan-core/docs/SELF_HOSTED_INSTALLABILITY.md`
|
- [Repo-docs-SELF-HOSTED-INSTALLABILITY](Repo-docs-SELF-HOSTED-INSTALLABILITY) - `/mnt/DATA/git/govoplan-core/docs/SELF_HOSTED_INSTALLABILITY.md`
|
||||||
- [Repo-docs-STATE-AND-RECOVERY-CONTRACT](Repo-docs-STATE-AND-RECOVERY-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/STATE_AND_RECOVERY_CONTRACT.md`
|
- [Repo-docs-STATE-AND-RECOVERY-CONTRACT](Repo-docs-STATE-AND-RECOVERY-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/STATE_AND_RECOVERY_CONTRACT.md`
|
||||||
|
- [Repo-docs-TABULAR-SOURCE-CONTRACT](Repo-docs-TABULAR-SOURCE-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/TABULAR_SOURCE_CONTRACT.md`
|
||||||
|
- [Repo-docs-TEMPLATE-CAPABILITY-CONTRACT](Repo-docs-TEMPLATE-CAPABILITY-CONTRACT) - `/mnt/DATA/git/govoplan-core/docs/TEMPLATE_CAPABILITY_CONTRACT.md`
|
||||||
|
- [Repo-docs-TEMPORAL-DATA-CONTEXT](Repo-docs-TEMPORAL-DATA-CONTEXT) - `/mnt/DATA/git/govoplan-core/docs/TEMPORAL_DATA_CONTEXT.md`
|
||||||
- [Repo-docs-THEMING](Repo-docs-THEMING) - `/mnt/DATA/git/govoplan-core/docs/THEMING.md`
|
- [Repo-docs-THEMING](Repo-docs-THEMING) - `/mnt/DATA/git/govoplan-core/docs/THEMING.md`
|
||||||
- [Repo-docs-THROTTLING](Repo-docs-THROTTLING) - `/mnt/DATA/git/govoplan-core/docs/THROTTLING.md`
|
- [Repo-docs-THROTTLING](Repo-docs-THROTTLING) - `/mnt/DATA/git/govoplan-core/docs/THROTTLING.md`
|
||||||
- [Repo-docs-UI-UX-DECISION-LEDGER](Repo-docs-UI-UX-DECISION-LEDGER) - `/mnt/DATA/git/govoplan-core/docs/UI_UX_DECISION_LEDGER.md`
|
- [Repo-docs-UI-UX-DECISION-LEDGER](Repo-docs-UI-UX-DECISION-LEDGER) - `/mnt/DATA/git/govoplan-core/docs/UI_UX_DECISION_LEDGER.md`
|
||||||
- [Repo-docs-WEBUI-BUNDLE-BUDGETS](Repo-docs-WEBUI-BUNDLE-BUDGETS) - `/mnt/DATA/git/govoplan-core/docs/WEBUI_BUNDLE_BUDGETS.md`
|
- [Repo-docs-WEBUI-BUNDLE-BUDGETS](Repo-docs-WEBUI-BUNDLE-BUDGETS) - `/mnt/DATA/git/govoplan-core/docs/WEBUI_BUNDLE_BUDGETS.md`
|
||||||
|
- [Repo-docs-WEBUI-MODULE-PACKAGE-LAYOUT](Repo-docs-WEBUI-MODULE-PACKAGE-LAYOUT) - `/mnt/DATA/git/govoplan-core/docs/WEBUI_MODULE_PACKAGE_LAYOUT.md`
|
||||||
- [Repo-docs-audits-2026-07-09-dependency-audit](Repo-docs-audits-2026-07-09-dependency-audit) - `/mnt/DATA/git/govoplan-core/docs/audits/2026-07-09-dependency-audit.md`
|
- [Repo-docs-audits-2026-07-09-dependency-audit](Repo-docs-audits-2026-07-09-dependency-audit) - `/mnt/DATA/git/govoplan-core/docs/audits/2026-07-09-dependency-audit.md`
|
||||||
|
|||||||
-178
@@ -1,178 +0,0 @@
|
|||||||
<!-- codex-wiki-sync:1311c05df40139316e1e93fb -->
|
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/README.md`.
|
|
||||||
> Origin: `repository`.
|
|
||||||
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
|
||||||
|
|
||||||
---
|
|
||||||
# govoplan-core
|
|
||||||
|
|
||||||
<!-- govoplan-repository-type:start -->
|
|
||||||
**Repository type:** system (kernel).
|
|
||||||
<!-- govoplan-repository-type:end -->
|
|
||||||
|
|
||||||
GovOPlaN core is the platform runner and shared foundation. It owns the server entry point, database/session primitives, module discovery, migration orchestration, capability contracts, install/uninstall orchestration, and the shared WebUI shell. Platform and feature behavior is supplied by installed modules.
|
|
||||||
|
|
||||||
## Repository ownership
|
|
||||||
|
|
||||||
Core owns:
|
|
||||||
|
|
||||||
- `govoplan_core.server.app:app`, the FastAPI entry point used by uvicorn
|
|
||||||
- `GovoplanServerConfig`, module discovery, registry validation, and route aggregation
|
|
||||||
- SQLAlchemy base/session helpers and module migration registration
|
|
||||||
- kernel APIs for platform metadata, module lifecycle, health, and development diagnostics
|
|
||||||
- `@govoplan/core-webui`, including login, CSRF/API helpers, shell layout, generic UI components, IconRail, DataGrid, access boundaries, and module route/nav contracts
|
|
||||||
|
|
||||||
The shared DataGrid sizing and resize invariants are specified in
|
|
||||||
[`docs/DATAGRID_SIZING_CONTRACT.md`](docs/DATAGRID_SIZING_CONTRACT.md).
|
|
||||||
|
|
||||||
Platform and feature modules own their backend routers, models, migrations,
|
|
||||||
permissions, frontend packages, nav items, and route contributions. Access,
|
|
||||||
tenancy, policy, audit, and admin behavior live in their owning platform
|
|
||||||
modules. Core should not import feature pages directly; it imports module
|
|
||||||
manifests and renders their route contributions.
|
|
||||||
|
|
||||||
## Governance docs
|
|
||||||
|
|
||||||
Canonical policy documents live in `docs/`:
|
|
||||||
|
|
||||||
- [DOCUMENTATION_MAP.md](docs/DOCUMENTATION_MAP.md)
|
|
||||||
- [ACCESS_RBAC_MODEL.md](docs/ACCESS_RBAC_MODEL.md)
|
|
||||||
- [GOVERNANCE_MODEL.md](docs/GOVERNANCE_MODEL.md)
|
|
||||||
- [MODULE_ARCHITECTURE.md](docs/MODULE_ARCHITECTURE.md)
|
|
||||||
- [DEPLOYMENT_OPERATOR_GUIDE.md](docs/DEPLOYMENT_OPERATOR_GUIDE.md)
|
|
||||||
- [CODEX_WORKFLOW.md](docs/CODEX_WORKFLOW.md)
|
|
||||||
|
|
||||||
Modules define module-specific permissions and policy behavior. Shared DTOs and
|
|
||||||
composition rules live in core only where they are stable kernel contracts.
|
|
||||||
|
|
||||||
## Backend development
|
|
||||||
|
|
||||||
For whole-product development, create the virtualenv from the meta repository:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan
|
|
||||||
python3 -m venv .venv
|
|
||||||
./.venv/bin/python -m pip install --upgrade pip
|
|
||||||
./.venv/bin/python -m pip install -r requirements-dev.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
Run the platform server from core through the module-aware development runner. The default config reads `ENABLED_MODULES` and discovers installed module entry points. Local development defaults to the modules listed by `govoplan_core.settings.Settings.enabled_modules`, including Views when its package is installed; set `ENABLED_MODULES` explicitly when testing a smaller module permutation.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
/mnt/DATA/git/govoplan/.venv/bin/python -m govoplan_core.devserver \
|
|
||||||
--host 127.0.0.1 \
|
|
||||||
--port 8000
|
|
||||||
```
|
|
||||||
|
|
||||||
For example, to test campaign without files or mail:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
ENABLED_MODULES=access,campaigns /mnt/DATA/git/govoplan/.venv/bin/python -m govoplan_core.devserver \
|
|
||||||
--host 127.0.0.1 \
|
|
||||||
--port 8000
|
|
||||||
```
|
|
||||||
|
|
||||||
The runner loads the same `GovoplanServerConfig` as `govoplan_core.server.app:app`, builds the platform registry, and passes core plus enabled module source roots to uvicorn as reload directories. After reinstalling the editable package, the same command is also available as `govoplan-devserver`.
|
|
||||||
|
|
||||||
For focused backend work, keep the complete module graph active while watching
|
|
||||||
only the module being edited. Core/config sources and explicit `--reload-dir`
|
|
||||||
paths remain watched:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
/mnt/DATA/git/govoplan/.venv/bin/python -m govoplan_core.devserver \
|
|
||||||
--reload-module calendar \
|
|
||||||
--reload-module campaign
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `--reload-core-only` when no optional module source tree should trigger a
|
|
||||||
restart. Omitting both options preserves the broad default and watches every
|
|
||||||
enabled module. Startup, migration, and compatibility checks still run against
|
|
||||||
the complete enabled graph whenever the backend restarts.
|
|
||||||
|
|
||||||
The default development database is PostgreSQL at `postgresql+psycopg://govoplan_dev@127.0.0.1:5432/govoplan_dev`. Store the password in `~/.pgpass`. To force the disposable SQLite fallback, run with `GOVOPLAN_DEV_DATABASE_BACKEND=sqlite`; that database lives below `runtime/`.
|
|
||||||
|
|
||||||
Local devserver runs do not require Redis. `CELERY_ENABLED` defaults to `false`, so campaign queue actions update database state without publishing Celery tasks. Use the synchronous send flow for local send tests, or set `CELERY_ENABLED=true` only when a Redis broker and worker are running.
|
|
||||||
|
|
||||||
To run the production-like local profile with PostgreSQL, Redis, a Celery
|
|
||||||
worker, explicit module configuration, and persistent local file storage:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan
|
|
||||||
tools/launch/launch-production-like-dev.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
See `/mnt/DATA/git/govoplan/dev/production-like/README.md` for ports,
|
|
||||||
environment overrides, and cleanup commands. Core keeps wrapper commands during
|
|
||||||
the migration, but whole-product profiles are owned by the meta repository.
|
|
||||||
|
|
||||||
## Security audit
|
|
||||||
|
|
||||||
The repository includes a containerized audit toolbox for SAST, secret scanning,
|
|
||||||
dependency checks, filesystem misconfiguration scans, duplication, and complexity
|
|
||||||
reports. See [SECURITY_AUDIT.md](docs/SECURITY_AUDIT.md) for the operating model.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan
|
|
||||||
tools/checks/security-audit/run.sh --mode ci --scope govoplan
|
|
||||||
tools/checks/security-audit/run.sh --mode full --scope govoplan
|
|
||||||
```
|
|
||||||
|
|
||||||
CI runs the `ci` profile in report-only mode and uploads `audit-reports/` as an
|
|
||||||
artifact. Once the baseline is clean, set `SECURITY_AUDIT_FAIL_ON_FINDINGS=1`
|
|
||||||
or pass `--strict` locally to turn findings into a failing gate.
|
|
||||||
|
|
||||||
`govoplan_core.devserver` enables the development bootstrap before loading settings. In dev, startup migrations create or upgrade the schema and the bootstrap creates the default development login if needed. Explicitly setting `DEV_BOOTSTRAP_ENABLED=false` disables this convenience. Production deployments should use migrations and managed database provisioning instead.
|
|
||||||
|
|
||||||
To verify the effective runtime paths and bootstrap behavior without starting uvicorn, run the smoke mode:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
/mnt/DATA/git/govoplan/.venv/bin/python -m govoplan_core.devserver --smoke --no-reload
|
|
||||||
```
|
|
||||||
|
|
||||||
The smoke mode prints the effective config, runtime root, database URL, modules, reload state, and bootstrap decision, then creates the ASGI app and runs startup once.
|
|
||||||
|
|
||||||
The meta repository owns whole-product `requirements-dev.txt`,
|
|
||||||
`requirements-release.txt`, and the root `.env.example` operator template. Core
|
|
||||||
keeps package metadata and runtime commands. See
|
|
||||||
[RELEASE_DEPENDENCIES.md](docs/RELEASE_DEPENDENCIES.md).
|
|
||||||
|
|
||||||
For the install/runtime configuration contract and operator deployment flow, see [DEPLOYMENT_OPERATOR_GUIDE.md](docs/DEPLOYMENT_OPERATOR_GUIDE.md).
|
|
||||||
For self-hosted config bootstrap and validation:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
/mnt/DATA/git/govoplan/.venv/bin/python -m govoplan_core.commands.config env-template --profile self-hosted --generate-secrets
|
|
||||||
/mnt/DATA/git/govoplan/.venv/bin/python -m govoplan_core.commands.config validate --profile self-hosted
|
|
||||||
```
|
|
||||||
|
|
||||||
## WebUI development
|
|
||||||
|
|
||||||
Install and run from the core WebUI host:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core/webui
|
|
||||||
PATH=/home/zemion/.nvm/versions/node/v22.22.3/bin:$PATH /home/zemion/.nvm/versions/node/v22.22.3/bin/npm install
|
|
||||||
PATH=/home/zemion/.nvm/versions/node/v22.22.3/bin:$PATH /home/zemion/.nvm/versions/node/v22.22.3/bin/npm run dev
|
|
||||||
```
|
|
||||||
|
|
||||||
The local host links sibling module WebUI packages through local file dependencies and Vite filesystem allowances. Release builds should use `webui/package.release.json`, which points WebUI module packages at tagged git refs. See [RELEASE_DEPENDENCIES.md](docs/RELEASE_DEPENDENCIES.md).
|
|
||||||
|
|
||||||
Production builds lazy-load enabled module descriptors and enforce initial and
|
|
||||||
asynchronous JavaScript budgets. See
|
|
||||||
[WEBUI_BUNDLE_BUDGETS.md](docs/WEBUI_BUNDLE_BUDGETS.md).
|
|
||||||
|
|
||||||
## Module contract
|
|
||||||
|
|
||||||
Backend modules register through the `govoplan.modules` entry point and return a `ModuleManifest`. A manifest can contribute:
|
|
||||||
|
|
||||||
- permissions and role templates
|
|
||||||
- API routers
|
|
||||||
- SQLAlchemy metadata and migration locations
|
|
||||||
- nav metadata and frontend package metadata
|
|
||||||
- resource ACL providers and tenant summary/delete-veto providers
|
|
||||||
|
|
||||||
WebUI modules export a `PlatformWebModule` with nav items and route contributions. Core renders those routes with `settings` and `auth` context. Frontend nav icons must be supplied as core-resolved `iconName` strings, not imported icon components. See [MODULE_ARCHITECTURE.md](docs/MODULE_ARCHITECTURE.md) for the full module-building contract.
|
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:1311c05df40139316e1e93fb -->
|
<!-- codex-wiki-sync:d2061aab7fb17630e8194f44 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/README.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/README.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -124,7 +124,7 @@ CI runs the `ci` profile in report-only mode and uploads `audit-reports/` as an
|
|||||||
artifact. Once the baseline is clean, set `SECURITY_AUDIT_FAIL_ON_FINDINGS=1`
|
artifact. Once the baseline is clean, set `SECURITY_AUDIT_FAIL_ON_FINDINGS=1`
|
||||||
or pass `--strict` locally to turn findings into a failing gate.
|
or pass `--strict` locally to turn findings into a failing gate.
|
||||||
|
|
||||||
`govoplan_core.devserver` enables the development bootstrap before loading settings. In dev, startup migrations create or upgrade the schema and the bootstrap creates the default development login if needed. Explicitly setting `DEV_BOOTSTRAP_ENABLED=false` disables this convenience. Production deployments should use migrations and managed database provisioning instead.
|
`govoplan_core.devserver` enables the development bootstrap before loading settings. In dev, startup migrations create or upgrade the schema and the bootstrap creates the default development login if needed. Explicitly setting `DEV_BOOTSTRAP_ENABLED=false` disables this convenience. Production deployments use the separate, expiring single-use flow exposed by `python -m govoplan_core.commands.first_admin`; it cannot enable or consume development bootstrap credentials.
|
||||||
|
|
||||||
To verify the effective runtime paths and bootstrap behavior without starting uvicorn, run the smoke mode:
|
To verify the effective runtime paths and bootstrap behavior without starting uvicorn, run the smoke mode:
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:cb35e75b65354a4e7c849b7d -->
|
<!-- codex-wiki-sync:61a4a08ed312d8c78a7dc884 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/ACTION_EFFECT_AUTOMATION_LAYER.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/ACTION_EFFECT_AUTOMATION_LAYER.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -54,6 +54,9 @@ Recommended fields:
|
|||||||
irreversible
|
irreversible
|
||||||
- expected effects
|
- expected effects
|
||||||
- idempotency key strategy
|
- idempotency key strategy
|
||||||
|
- recovery mode: atomic, compensating, snapshot restore, forward recovery, or
|
||||||
|
irreversible
|
||||||
|
- concrete verification steps which prove whether the effect occurred
|
||||||
- audit event names
|
- audit event names
|
||||||
- preview provider
|
- preview provider
|
||||||
|
|
||||||
@@ -96,10 +99,14 @@ The runner should execute an action plan as follows:
|
|||||||
4. Run permission and policy checks.
|
4. Run permission and policy checks.
|
||||||
5. Generate a consequence preview.
|
5. Generate a consequence preview.
|
||||||
6. Reserve or verify the idempotency key.
|
6. Reserve or verify the idempotency key.
|
||||||
7. Execute the owning module capability.
|
7. Create a durable recovery operation and acquire its execution fence.
|
||||||
8. Record observed effects.
|
8. Persist dispatch evidence before a non-atomic provider call.
|
||||||
9. Emit events and audit records.
|
9. Execute the owning module capability.
|
||||||
10. Mark the command complete, retryable, quarantined, or requiring manual
|
10. Verify the provider result and every announced effect using the action's
|
||||||
|
declared recovery checks.
|
||||||
|
11. Commit the local projection and verified recovery checkpoint together.
|
||||||
|
12. Emit events and audit records.
|
||||||
|
13. Mark the command complete, retryable, quarantined, or requiring manual
|
||||||
intervention.
|
intervention.
|
||||||
|
|
||||||
The runner must never advance workflow state past a required side effect unless
|
The runner must never advance workflow state past a required side effect unless
|
||||||
@@ -117,7 +124,16 @@ between:
|
|||||||
6. reconciled, corrected, or compensated outcome.
|
6. reconciled, corrected, or compensated outcome.
|
||||||
|
|
||||||
An API timeout after dispatch is not a failed effect and must not be retried as
|
An API timeout after dispatch is not a failed effect and must not be retried as
|
||||||
a fresh command. The actor context should retain the real identity/account,
|
an ordinary process failure or a fresh command. The runner records an unknown
|
||||||
|
outcome, releases its execution authority, and blocks continuation until an
|
||||||
|
operator or provider reconciliation proves either that the effect occurred or
|
||||||
|
that it is absent.
|
||||||
|
|
||||||
|
`ActionDefinition.recovery_mode` and `recovery_verification` are part of the
|
||||||
|
provider contract. The default is conservative forward recovery with explicit
|
||||||
|
provider-result and effect verification. Atomic mode is valid only when the
|
||||||
|
provider effect and its local projection share the same database transaction.
|
||||||
|
The actor context should retain the real identity/account,
|
||||||
represented function or party, delegation or power, and mandate/jurisdiction
|
represented function or party, delegation or power, and mandate/jurisdiction
|
||||||
references when applicable. Domain modules remain responsible for deciding
|
references when applicable. Domain modules remain responsible for deciding
|
||||||
which of those references are required for their action.
|
which of those references are required for their action.
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:7044620091f59357c2d54606 -->
|
<!-- codex-wiki-sync:e061e92d2a49d037ba6ca7c3 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/COMPATIBILITY_INVENTORY.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/COMPATIBILITY_INVENTORY.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -38,6 +38,7 @@ such as Redis degradation and language fallback are not compatibility paths.
|
|||||||
| Legacy tenant aliases in API response schemas | Preserves active-tenant response fields used by `0.1.x` clients. | Tagged `0.1.x` API window. | Remove at `0.2` with response-schema migration notes. |
|
| Legacy tenant aliases in API response schemas | Preserves active-tenant response fields used by `0.1.x` clients. | Tagged `0.1.x` API window. | Remove at `0.2` with response-schema migration notes. |
|
||||||
| Optional fields in Poll response references | Accepts providers built against the earlier Poll contract. | Tagged `0.1.x` runtime contract window. | Remove or require a new interface version at `0.2`. |
|
| Optional fields in Poll response references | Accepts providers built against the earlier Poll contract. | Tagged `0.1.x` runtime contract window. | Remove or require a new interface version at `0.2`. |
|
||||||
| Legacy single-tenant summary providers | Allows modules without the batch provider introduced in `0.1.x`. | Tagged `0.1.x` module contract window. | Remove at `0.2` after manifests advertise the batch provider contract. |
|
| Legacy single-tenant summary providers | Allows modules without the batch provider introduced in `0.1.x`. | Tagged `0.1.x` module contract window. | Remove at `0.2` after manifests advertise the batch provider contract. |
|
||||||
|
| WebUI `react-router-dom` build alias | Resolves tagged `0.1.x` module source imports to Core's single `react-router` runtime so one composition never loads two router contexts. | Tagged `0.1.x` WebUI source window. | Remove at `0.2` after every supported module tag imports `react-router` directly. |
|
||||||
|
|
||||||
## Removed Paths
|
## Removed Paths
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,72 @@
|
|||||||
|
<!-- codex-wiki-sync:36ef3d60d759b0b0592f554b -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/CONTEXTUAL_HELP_CONTRACT.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Contextual Help Contract
|
||||||
|
|
||||||
|
GovOPlaN exposes context-sensitive help through `F1` and the titlebar help
|
||||||
|
control. The shell resolves a stable help identity from the focused control,
|
||||||
|
its containing surface, and the current route. The Docs module then projects
|
||||||
|
the best visible user or administrator topic for that identity.
|
||||||
|
|
||||||
|
## Resolution Order
|
||||||
|
|
||||||
|
The WebUI resolves help in this order:
|
||||||
|
|
||||||
|
1. an explicit `helpContextId` or `data-help-context-id` on the focused item
|
||||||
|
2. the focused shared control's `interfaceId`, `helpTopicId`, and label key
|
||||||
|
3. a containing dialog, card, administration section, or page surface
|
||||||
|
4. the current registered route, including dynamic module routes
|
||||||
|
5. a stable route-derived fallback when no explicit identity is available
|
||||||
|
|
||||||
|
Focused field and action contexts retain the page context as
|
||||||
|
`fallback_context`. This lets Docs show a field-specific topic when one exists
|
||||||
|
and otherwise open the owning page or module documentation instead of a generic
|
||||||
|
help page.
|
||||||
|
|
||||||
|
## Documentation Lookup
|
||||||
|
|
||||||
|
Static `DocumentationTopic` contributions announce exact contexts through
|
||||||
|
`metadata.help_contexts`. Core publishes that catalogue with the enabled module
|
||||||
|
manifest, allowing the shell to link directly to an exact topic when possible.
|
||||||
|
Docs still performs the authoritative audience, permission, configured-state,
|
||||||
|
and documentation-type filtering.
|
||||||
|
|
||||||
|
Core also maps explicit route, navigation, settings, and View surface IDs to
|
||||||
|
the module's static user or administrator documentation baseline. This makes a
|
||||||
|
page association complete by default and gives every derived field/action
|
||||||
|
context a useful fallback. Exact `metadata.help_contexts` remain the preferred
|
||||||
|
authoring mechanism for consequential or unfamiliar controls.
|
||||||
|
|
||||||
|
When there is no exact topic, Docs resolves the page fallback and then the first
|
||||||
|
visible topic owned by the module. If Docs is unavailable, the shell opens the
|
||||||
|
hosted documentation with the same context parameters.
|
||||||
|
|
||||||
|
## Authoring Controls
|
||||||
|
|
||||||
|
Core shared controls expose stable help metadata. Prefer these props rather
|
||||||
|
than adding custom `F1` listeners:
|
||||||
|
|
||||||
|
- `interfaceId` identifies a durable UI surface or action.
|
||||||
|
- `helpContextId` identifies a documentation context when it differs from the
|
||||||
|
interface identity.
|
||||||
|
- `helpTopicId` links directly to a module-owned documentation topic.
|
||||||
|
- translated label keys provide deterministic field identities for ordinary
|
||||||
|
`FormField`, `ToggleSwitch`, search, date/time, email, button, dialog, and card
|
||||||
|
controls.
|
||||||
|
|
||||||
|
Module routes, public routes, settings sections, and administration sections
|
||||||
|
may also declare `helpContextId` and `helpTopicId`. Each module must keep a
|
||||||
|
static user/admin documentation baseline and should list its important route,
|
||||||
|
workflow, setting, permission, and limitation identities in
|
||||||
|
`metadata.help_contexts`.
|
||||||
|
|
||||||
|
## Boundary
|
||||||
|
|
||||||
|
Help identities describe presentation context; they are not authorization
|
||||||
|
claims. Opening help never bypasses route or documentation permissions. Docs
|
||||||
|
owns documentation projection, feature modules own their content, and Core owns
|
||||||
|
focus capture, context resolution, and fallback routing.
|
||||||
@@ -1,74 +0,0 @@
|
|||||||
<!-- codex-wiki-sync:ae21d8bbf9ec197990927237 -->
|
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/DEPENDENCY_AUDITS.md`.
|
|
||||||
> Origin: `repository`.
|
|
||||||
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
|
||||||
|
|
||||||
---
|
|
||||||
# Dependency Audits
|
|
||||||
|
|
||||||
GovOPlaN keeps dependency vulnerability checks reproducible but separate from
|
|
||||||
the fast local smoke suite, because both Python and npm audits need network
|
|
||||||
metadata and can fail for newly disclosed advisories without a source change.
|
|
||||||
|
|
||||||
## Local Workflow
|
|
||||||
|
|
||||||
Install the development audit dependency once:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
./.venv/bin/python -m pip install -r requirements-dev.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
Run both backend and WebUI production audits:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
bash scripts/check-dependency-audits.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The script runs:
|
|
||||||
|
|
||||||
- `scripts/check-dependency-hygiene.sh` for pip resolver consistency, stale
|
|
||||||
legacy editable package metadata, deprecated framework constants, and the
|
|
||||||
Starlette `TestClient` deprecation smoke when test dependencies are present
|
|
||||||
- `python -m pip_audit --progress-spinner off`
|
|
||||||
- `npm audit --omit=dev` in `webui`
|
|
||||||
|
|
||||||
For fast local checks without vulnerability metadata lookups, run:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
CHECK_TESTCLIENT_DEPRECATIONS=1 bash scripts/check-dependency-hygiene.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
This is also part of `scripts/check-focused.sh`, so resolver drift and
|
|
||||||
deprecation regressions fail close to the code change that introduced them.
|
|
||||||
|
|
||||||
Override tool paths when testing from a disposable environment:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
PYTHON=/tmp/govoplan-audit/bin/python \
|
|
||||||
NPM=/home/zemion/.nvm/versions/node/v22.22.3/bin/npm \
|
|
||||||
bash scripts/check-dependency-audits.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
## CI Workflow
|
|
||||||
|
|
||||||
`.gitea/workflows/dependency-audit.yml` installs release dependencies from
|
|
||||||
tagged package refs, installs `pip-audit`, and runs the same script on pushes,
|
|
||||||
pull requests, and a weekly schedule.
|
|
||||||
|
|
||||||
The workflow intentionally uses release dependency refs instead of local
|
|
||||||
`file:` or editable sibling paths. Development lockfiles may keep local module
|
|
||||||
links, but release audit results should represent the installable product.
|
|
||||||
|
|
||||||
## Recording Results
|
|
||||||
|
|
||||||
When closing or triaging dependency-audit issues, add a short dated note under
|
|
||||||
`docs/audits/`. Record:
|
|
||||||
|
|
||||||
- the commands that were run
|
|
||||||
- whether Python and npm passed
|
|
||||||
- any advisories accepted as temporary risk
|
|
||||||
- follow-up issue links for required upgrades
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:6d9c69d4008b7843efa050fd -->
|
<!-- codex-wiki-sync:f357e8246adfdef6d50a3e37 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/DEPLOYMENT_OPERATOR_GUIDE.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/DEPLOYMENT_OPERATOR_GUIDE.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -43,7 +43,7 @@ set +a
|
|||||||
| Setting | Required outside dev | Purpose |
|
| Setting | Required outside dev | Purpose |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `APP_ENV` | yes | Runtime profile. Use `prod`, `staging`, or a deployment-specific value outside local development. |
|
| `APP_ENV` | yes | Runtime profile. Use `prod`, `staging`, or a deployment-specific value outside local development. |
|
||||||
| `MASTER_KEY_B64` | yes | Fernet key or base64 encoded 32-byte key used for encrypted module secrets. Rotate through an explicit operator plan. |
|
| `MASTER_KEY_B64` | yes | Fernet key or base64 encoded 32-byte deployment root used for encrypted module secrets and, when enabled, the Encryption module's local server-envelope provider. Rotate only through an explicit provider-aware migration plan. |
|
||||||
| `DATABASE_URL` | yes | SQLAlchemy database URL for core and installed modules. SQLite is supported for dev/small installs; PostgreSQL is the preferred production target. |
|
| `DATABASE_URL` | yes | SQLAlchemy database URL for core and installed modules. SQLite is supported for dev/small installs; PostgreSQL is the preferred production target. |
|
||||||
| `ENABLED_MODULES` | yes | Comma-separated startup module set. Keep `tenancy,access` enabled; keep `admin` enabled for operator UI. |
|
| `ENABLED_MODULES` | yes | Comma-separated startup module set. Keep `tenancy,access` enabled; keep `admin` enabled for operator UI. |
|
||||||
|
|
||||||
@@ -64,6 +64,8 @@ PY
|
|||||||
| `GOVOPLAN_MIGRATION_TRACK` | `release` | Use the release track for normal runtime and deployments. Use `dev` only for fresh/disposable databases that intentionally replay detailed development migrations. |
|
| `GOVOPLAN_MIGRATION_TRACK` | `release` | Use the release track for normal runtime and deployments. Use `dev` only for fresh/disposable databases that intentionally replay detailed development migrations. |
|
||||||
| `DEV_AUTO_MIGRATE_ENABLED` | `true` | Dev convenience only. Production should run migration commands explicitly during deployment. |
|
| `DEV_AUTO_MIGRATE_ENABLED` | `true` | Dev convenience only. Production should run migration commands explicitly during deployment. |
|
||||||
| `DEV_BOOTSTRAP_ENABLED` | `false` | Dev bootstrap only. `govoplan_core.devserver` and `govoplan/tools/launch/launch-dev.sh` default it to `true`; use controlled first-admin creation outside dev. |
|
| `DEV_BOOTSTRAP_ENABLED` | `false` | Dev bootstrap only. `govoplan_core.devserver` and `govoplan/tools/launch/launch-dev.sh` default it to `true`; use controlled first-admin creation outside dev. |
|
||||||
|
| `FIRST_ADMIN_ENROLLMENT_TTL_SECONDS` | `1800` | Lifetime of a locally issued production enrollment credential. Allowed range: 60 seconds to 24 hours. |
|
||||||
|
| `FIRST_ADMIN_ENROLLMENT_FILE` | `/run/govoplan/first-admin-enrollment.json` | Local operator artifact. The command creates it with mode `0600` and never prints the secret. |
|
||||||
|
|
||||||
Operator rule: take a database backup before applying migrations or destructive
|
Operator rule: take a database backup before applying migrations or destructive
|
||||||
module retirement. For non-SQLite databases, configure deployment-specific
|
module retirement. For non-SQLite databases, configure deployment-specific
|
||||||
@@ -165,6 +167,7 @@ release evidence.
|
|||||||
| `REDIS_URL` | `redis://redis:6379/0` | Celery broker/result backend when async workers are enabled. |
|
| `REDIS_URL` | `redis://redis:6379/0` | Celery broker/result backend when async workers are enabled. |
|
||||||
| `CELERY_ENABLED` | `false` | Local/dev can send synchronously. Production campaign delivery should run workers and set this to `true`. |
|
| `CELERY_ENABLED` | `false` | Local/dev can send synchronously. Production campaign delivery should run workers and set this to `true`. |
|
||||||
| `CELERY_QUEUES` | `send_email,append_sent,notifications,mail,calendar,dataflow,workflow,postbox,events,idm,default` | Queue list expected by worker/process manager definitions. Keep this aligned with every enabled module task route; Ops reports missing worker queue consumers. |
|
| `CELERY_QUEUES` | `send_email,append_sent,notifications,mail,calendar,dataflow,workflow,postbox,events,idm,default` | Queue list expected by worker/process manager definitions. Keep this aligned with every enabled module task route; Ops reports missing worker queue consumers. |
|
||||||
|
| `CELERY_VISIBILITY_TIMEOUT_SECONDS` | `3600` | Maximum time before Redis may redeliver work left unacknowledged by a lost worker. Set this above the longest supported task duration; changing it requires a worker-loss acceptance drill. |
|
||||||
| `PLATFORM_EVENT_OUTBOX_MAX_ATTEMPTS` | `8` | Failed durable consumer deliveries are quarantined after this many attempts. |
|
| `PLATFORM_EVENT_OUTBOX_MAX_ATTEMPTS` | `8` | Failed durable consumer deliveries are quarantined after this many attempts. |
|
||||||
| `PLATFORM_EVENT_OUTBOX_TERMINAL_RETENTION_DAYS` | `90` | Successful event envelopes older than this are removed by the daily retention task. Quarantined evidence is retained. |
|
| `PLATFORM_EVENT_OUTBOX_TERMINAL_RETENTION_DAYS` | `90` | Successful event envelopes older than this are removed by the daily retention task. Quarantined evidence is retained. |
|
||||||
|
|
||||||
@@ -184,6 +187,13 @@ crashes, and expired worker leases:
|
|||||||
python -m celery -A govoplan_core.celery_app:celery beat --loglevel INFO
|
python -m celery -A govoplan_core.celery_app:celery beat --loglevel INFO
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Before promoting a worker composition, run the repository worker-runtime drill
|
||||||
|
against the same Redis and Core build. It uses the bounded
|
||||||
|
`govoplan.worker.acceptance` task and records publish/consume, retry, warm
|
||||||
|
SIGTERM, and worker-loss redelivery evidence without accessing tenant data.
|
||||||
|
Production evidence must use the deployed queue configuration and a visibility
|
||||||
|
timeout that is longer than every supported business task.
|
||||||
|
|
||||||
### Storage
|
### Storage
|
||||||
|
|
||||||
| Setting | Default | Notes |
|
| Setting | Default | Notes |
|
||||||
@@ -299,8 +309,34 @@ configuration, not the core runtime contract. Store them in a local ignored
|
|||||||
3. Build the WebUI from `webui/package.release.json` or deploy a prebuilt
|
3. Build the WebUI from `webui/package.release.json` or deploy a prebuilt
|
||||||
artifact from the same release tag.
|
artifact from the same release tag.
|
||||||
4. Run database migrations with the target `DATABASE_URL`.
|
4. Run database migrations with the target `DATABASE_URL`.
|
||||||
5. Create the first tenant and system owner through the controlled bootstrap or
|
5. Create the first tenant and system owner through the controlled bootstrap:
|
||||||
one-time admin command for the deployment.
|
|
||||||
|
```bash
|
||||||
|
python -m govoplan_core.commands.first_admin status
|
||||||
|
python -m govoplan_core.commands.first_admin issue \
|
||||||
|
--reason "initial production installation"
|
||||||
|
```
|
||||||
|
|
||||||
|
The issue command fails when an active system administrator already exists,
|
||||||
|
writes the random credential only to `FIRST_ADMIN_ENROLLMENT_FILE`, and does
|
||||||
|
not print it. Check `GET /api/v1/bootstrap/status`, then submit the account
|
||||||
|
and initial tenant fields to `POST /api/v1/bootstrap/first-admin` with the
|
||||||
|
secret in `X-GovOPlaN-Enrollment-Token`. The operation creates the protected
|
||||||
|
system owner and initial tenant-owner membership in one transaction and
|
||||||
|
retires the credential. A repeated identical request returns the same result
|
||||||
|
without creating another owner.
|
||||||
|
|
||||||
|
If the artifact is lost or expires before use, a local operator may rotate
|
||||||
|
it only while no durable system administrator exists:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
python -m govoplan_core.commands.first_admin recover \
|
||||||
|
--reason "expired installation handoff"
|
||||||
|
```
|
||||||
|
|
||||||
|
Issue and recovery write hash-chained Core evidence and an audit event. They
|
||||||
|
never enable or reuse `DEV_BOOTSTRAP_ENABLED`, `DEV_BOOTSTRAP_PASSWORD`, or
|
||||||
|
`DEV_BOOTSTRAP_API_KEY`.
|
||||||
6. Start the API service with `govoplan_core.server.app:app`.
|
6. Start the API service with `govoplan_core.server.app:app`.
|
||||||
7. Start workers when `CELERY_ENABLED=true`.
|
7. Start workers when `CELERY_ENABLED=true`.
|
||||||
8. Start the WebUI/reverse proxy and verify CORS/cookie settings.
|
8. Start the WebUI/reverse proxy and verify CORS/cookie settings.
|
||||||
@@ -430,6 +466,14 @@ SQLite's backup API; non-SQLite databases require
|
|||||||
`--database-backup-command`, `--database-restore-check-command`, and
|
`--database-backup-command`, `--database-restore-check-command`, and
|
||||||
`--database-restore-command`.
|
`--database-restore-command`.
|
||||||
|
|
||||||
|
Every non-dry run also owns the database-fenced
|
||||||
|
`core:module-lifecycle:deployment` recovery operation. The run record includes
|
||||||
|
its operation id and status. A supervised run reaches durable `succeeded` only
|
||||||
|
after restart and health verification. `recovery_required` or `outcome_unknown`
|
||||||
|
blocks another lifecycle mutation until the recorded operation is reconciled;
|
||||||
|
do not bypass this by deleting `install.lock`. See
|
||||||
|
[`MODULE_LIFECYCLE_RECOVERY.md`](MODULE_LIFECYCLE_RECOVERY.md).
|
||||||
|
|
||||||
Database hook commands receive:
|
Database hook commands receive:
|
||||||
|
|
||||||
- `GOVOPLAN_INSTALLER_RUN_DIR`
|
- `GOVOPLAN_INSTALLER_RUN_DIR`
|
||||||
@@ -492,7 +536,7 @@ checks, catalog trust, signing, keyring, replay, and license operation.
|
|||||||
## Operator Checklist
|
## Operator Checklist
|
||||||
|
|
||||||
- Runtime secrets are injected outside git.
|
- Runtime secrets are injected outside git.
|
||||||
- `MASTER_KEY_B64` is set and backed up securely.
|
- `MASTER_KEY_B64` is set and backed up securely; restores of locally encrypted content fail closed without the exact matching key.
|
||||||
- Database backup and restore commands are tested.
|
- Database backup and restore commands are tested.
|
||||||
- File/object storage is durable and backed up.
|
- File/object storage is durable and backed up.
|
||||||
- `CORS_ORIGINS` and cookie settings match the deployed WebUI origin.
|
- `CORS_ORIGINS` and cookie settings match the deployed WebUI origin.
|
||||||
|
|||||||
@@ -1,55 +0,0 @@
|
|||||||
<!-- codex-wiki-sync:0d96ef04b8301216aa2acad4 -->
|
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/DOCUMENTATION_MAP.md`.
|
|
||||||
> Origin: `repository`.
|
|
||||||
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
|
||||||
|
|
||||||
---
|
|
||||||
# GovOPlaN Documentation Map
|
|
||||||
|
|
||||||
This map defines the source-of-truth documents for the current repository docs.
|
|
||||||
Use it to avoid duplicating long procedures across architecture, release,
|
|
||||||
operator, and roadmap pages.
|
|
||||||
|
|
||||||
## Core Platform
|
|
||||||
|
|
||||||
| Topic | Canonical document | Notes |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Module architecture and kernel contracts | `MODULE_ARCHITECTURE.md` | Stable module contracts, API efficiency contracts, durable boundary decisions, lifecycle, and WebUI contribution rules. |
|
|
||||||
| RBAC and resource access | `ACCESS_RBAC_MODEL.md` | Current permission, role, API-key, and resource-access model. |
|
|
||||||
| Governance hierarchy | `GOVERNANCE_MODEL.md` | System, tenant, user/group, campaign policy inheritance and admin UI structure. |
|
|
||||||
| Policy decision DTOs and provenance | `POLICY_CONTRACTS.md` | Shared explain/provenance shape; module-specific policy docs should link here. |
|
|
||||||
| Events and audit trace context | `EVENTS_AND_AUDIT.md` | Event dispatch semantics and audit payload conventions. |
|
|
||||||
|
|
||||||
## Release And Operations
|
|
||||||
|
|
||||||
| Topic | Canonical document | Notes |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Runtime configuration and operator flow | `DEPLOYMENT_OPERATOR_GUIDE.md` | Production/staging configuration, migrations, backups, installer operation, and rollback drill. |
|
|
||||||
| Release dependencies and catalogs | `RELEASE_DEPENDENCIES.md` | Release package refs, migration baselines, release lockfiles, catalog trust/licensing, catalog publishing, and release checklist. |
|
|
||||||
| Dependency vulnerability audits | `DEPENDENCY_AUDITS.md` | Local and CI audit commands plus dated audit result notes. |
|
|
||||||
| Remote WebUI bundle design | `REMOTE_WEBUI_BUNDLES.md` | Experimental controlled-deployment design; normal releases still use package builds. |
|
|
||||||
|
|
||||||
## Product And Module Planning
|
|
||||||
|
|
||||||
| Topic | Canonical document | Notes |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Product roadmap and module routing | `GOVOPLAN_MASTER_ROADMAP.md` | Product-level sequencing, implementation gates, issue routing, and missing-module decisions. |
|
|
||||||
| UI/UX decisions | `UI_UX_DECISION_LEDGER.md` | Binding guided-UI decisions, open decisions, impact index, and review checklist. |
|
|
||||||
| Public-sector integration posture | `PUBLIC_SECTOR_INTEGRATION_STRATEGY.md` | Strategy index; executable target inventory lives in `govoplan-connectors`. |
|
|
||||||
| Configuration packages | `CONFIGURATION_PACKAGES.md` | Package model, provider contract, import/export flow, and tracking slices. |
|
|
||||||
|
|
||||||
## Workflow Docs
|
|
||||||
|
|
||||||
| Topic | Canonical document | Notes |
|
|
||||||
| --- | --- | --- |
|
|
||||||
| Gitea issues and wiki sync | `GITEA_ISSUES.md` | Issue labels, imports, wiki mirroring, and Codex state updates. |
|
|
||||||
| Codex local workflow | `CODEX_WORKFLOW.md` | Local agent setup and focused verification commands. |
|
|
||||||
|
|
||||||
## Cross-Repo Rule
|
|
||||||
|
|
||||||
Core docs may keep strategy, kernel contracts, and routing decisions. Module
|
|
||||||
repositories should own executable module behavior, concrete API/UI contracts,
|
|
||||||
and operator notes for their own module. When content spans both, keep the
|
|
||||||
durable decision in core and link to the module document for implementation
|
|
||||||
details.
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:e55cae782a56e382c94b7d39 -->
|
<!-- codex-wiki-sync:794f1910b9dc31a0103bfeee -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/DOCUMENTATION_MAP.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/DOCUMENTATION_MAP.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -24,8 +24,13 @@ operator, and roadmap pages.
|
|||||||
| Action/effect automation layer | `ACTION_EFFECT_AUTOMATION_LAYER.md` | Action/effect contracts, consequence preview, runner semantics, and module boundary for automation. |
|
| Action/effect automation layer | `ACTION_EFFECT_AUTOMATION_LAYER.md` | Action/effect contracts, consequence preview, runner semantics, and module boundary for automation. |
|
||||||
| External references and integration maturity | `EXTERNAL_REFERENCES_AND_INTEGRATION_MATURITY.md` | Stable external identity and cumulative connector maturity; configured source authority is defined by the meta target architecture. |
|
| External references and integration maturity | `EXTERNAL_REFERENCES_AND_INTEGRATION_MATURITY.md` | Stable external identity and cumulative connector maturity; configured source authority is defined by the meta target architecture. |
|
||||||
| Institutional context and governed references | `INSTITUTIONAL_CONTEXT_CONTRACT.md` | Shared temporal, actor/representation, institution, mandate, service, party, decision, evidence, legal-basis, information-governance, presentation, and geo DTO/provider contracts. |
|
| Institutional context and governed references | `INSTITUTIONAL_CONTEXT_CONTRACT.md` | Shared temporal, actor/representation, institution, mandate, service, party, decision, evidence, legal-basis, information-governance, presentation, and geo DTO/provider contracts. |
|
||||||
|
| Temporal data read context | `TEMPORAL_DATA_CONTEXT.md` | Valid-time and recorded-time titlebar selection, HTTP/cache contract, security boundary, and module-adoption rule. |
|
||||||
|
| Cross-module information governance adoption | `INFORMATION_GOVERNANCE_ADOPTION.md` | Manifest evidence and enforcement rules for temporal browsing, purpose-aware access, retention, and institutional context. |
|
||||||
|
| Context-sensitive F1 help | `CONTEXTUAL_HELP_CONTRACT.md` | Focus, route, module-manifest documentation contexts, Docs projection, and hosted fallback. |
|
||||||
|
| German localization and help quality gate | `LOCALIZATION_AND_HELP_QUALITY.md` | German reference locale, new-installation default, catalog completeness, automatic page associations, and explicit-help review priorities. |
|
||||||
| Postbox E2EE target architecture | `POSTBOX_E2EE_ARCHITECTURE.md` | Strategic encrypted postbox/mailbox model, key ownership, role mailbox semantics, and retraction limits. |
|
| Postbox E2EE target architecture | `POSTBOX_E2EE_ARCHITECTURE.md` | Strategic encrypted postbox/mailbox model, key ownership, role mailbox semantics, and retraction limits. |
|
||||||
| Shared state, runtime coordination, and recovery | `STATE_AND_RECOVERY_CONTRACT.md` | State profiles, object storage, node registration/drain, fenced leases, migration ordering, and recovery evidence. |
|
| Shared state, runtime coordination, and recovery | `STATE_AND_RECOVERY_CONTRACT.md` | State profiles, object storage, node registration/drain, fenced leases, migration ordering, and recovery evidence. |
|
||||||
|
| Module lifecycle recovery | `MODULE_LIFECYCLE_RECOVERY.md` | Installer/live-graph recovery modes, deployment fence, evidence, retry blocking, and operator reconciliation. |
|
||||||
|
|
||||||
## Release And Operations
|
## Release And Operations
|
||||||
|
|
||||||
@@ -43,8 +48,11 @@ operator, and roadmap pages.
|
|||||||
| Topic | Canonical document | Notes |
|
| Topic | Canonical document | Notes |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| Product roadmap and module routing | `GOVOPLAN_MASTER_ROADMAP.md` | Product-level sequencing, implementation gates, issue routing, and missing-module decisions. |
|
| Product roadmap and module routing | `GOVOPLAN_MASTER_ROADMAP.md` | Product-level sequencing, implementation gates, issue routing, and missing-module decisions. |
|
||||||
|
| Stable platform ideas | `govoplan/docs/PLATFORM_CORE_IDEAS.md` | Cross-product thesis, canonical distinctions, product experience rule, maturity rule, and decision test. |
|
||||||
|
| Current cross-product reconciliation | `govoplan/docs/STRATEGY_STATUS.md` | The only current prose status source; generated evidence and Gitea remain authoritative inputs. |
|
||||||
| Institutional governance target | `govoplan/docs/INSTITUTIONAL_GOVERNANCE_TARGET_ARCHITECTURE.md` | Cross-product semantic layers, source-authority modes, candidate Mandates/Services/Parties/Decisions boundaries, and migration sequence. |
|
| Institutional governance target | `govoplan/docs/INSTITUTIONAL_GOVERNANCE_TARGET_ARCHITECTURE.md` | Cross-product semantic layers, source-authority modes, candidate Mandates/Services/Parties/Decisions boundaries, and migration sequence. |
|
||||||
| UI/UX decisions | `UI_UX_DECISION_LEDGER.md` | Binding guided-UI decisions, open decisions, impact index, and review checklist. |
|
| UI/UX decisions | `UI_UX_DECISION_LEDGER.md` | Binding guided-UI decisions, open decisions, impact index, and review checklist. |
|
||||||
|
| Core interface migration | `INTERFACE_PATTERN_MIGRATION.md` | Core-owned settings, credential, retention, lifecycle, and shared-component evidence for the product pattern language. |
|
||||||
| Interface ethics and design doctrine | `INTERFACE_ETHICS_AND_DESIGN_DOCTRINE.md` | Product-level doctrine for context, decision, consequence, contestability, responsibility, and traceability. |
|
| Interface ethics and design doctrine | `INTERFACE_ETHICS_AND_DESIGN_DOCTRINE.md` | Product-level doctrine for context, decision, consequence, contestability, responsibility, and traceability. |
|
||||||
| Public-sector integration posture | `PUBLIC_SECTOR_INTEGRATION_STRATEGY.md` | Strategy index; executable target inventory lives in `govoplan-connectors`. |
|
| Public-sector integration posture | `PUBLIC_SECTOR_INTEGRATION_STRATEGY.md` | Strategy index; executable target inventory lives in `govoplan-connectors`. |
|
||||||
| Configuration packages | `CONFIGURATION_PACKAGES.md` | Package model, provider contract, import/export flow, and tracking slices. |
|
| Configuration packages | `CONFIGURATION_PACKAGES.md` | Package model, provider contract, import/export flow, and tracking slices. |
|
||||||
|
|||||||
@@ -0,0 +1,51 @@
|
|||||||
|
<!-- codex-wiki-sync:a46c674f2fd3b147211efa00 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/DURABLE_RECOVERY_OPERATIONS.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Durable Recovery Operations
|
||||||
|
|
||||||
|
Modules must use `begin_durable_recovery_operation` for work whose effects can
|
||||||
|
outlive the caller's SQLAlchemy transaction. The helper commits the canonical
|
||||||
|
request hash, recovery plan, precondition evidence, running state, and lease
|
||||||
|
fence before the caller mutates object storage, a queue, a filesystem, or an
|
||||||
|
external provider.
|
||||||
|
|
||||||
|
Each later checkpoint is written through an independent database session. A
|
||||||
|
business-transaction rollback therefore cannot erase evidence of an earlier
|
||||||
|
effect. Successful completion requires concrete verification checks and a valid
|
||||||
|
hash chain. Compensation likewise records recovery-required, recovering, and
|
||||||
|
verified-recovered checkpoints rather than reporting an ordinary failure.
|
||||||
|
A definitive pre-effect or provider rejection records terminal `rejected`
|
||||||
|
evidence instead of being mislabeled as success, atomic rollback, or recovery
|
||||||
|
work.
|
||||||
|
|
||||||
|
If a runtime disappears, another runtime may claim the operation only after the
|
||||||
|
lease expires. The takeover records both fences. A stale compensatable operation
|
||||||
|
becomes recovery-required; a stale forward-only or irreversible external effect
|
||||||
|
becomes outcome-unknown; a database-only atomic operation is recorded failed
|
||||||
|
because its transaction rolled back. Takeover never re-executes the original
|
||||||
|
request automatically.
|
||||||
|
|
||||||
|
Evidence and metadata may contain opaque references, digests, counts, and
|
||||||
|
provider result codes. They must never contain credentials or resolved secrets.
|
||||||
|
Ops is the platform surface for unresolved operation status; owning modules must
|
||||||
|
provide the reconciliation action and business-level explanation.
|
||||||
|
|
||||||
|
Database-only operations must use the durable handle's atomic terminal methods
|
||||||
|
when their module rows and final recovery checkpoint belong to one invariant.
|
||||||
|
Those methods stage the terminal checkpoint and lease release in the caller's
|
||||||
|
SQLAlchemy transaction, then commit the domain rows and recovery evidence
|
||||||
|
together. A failed commit rolls both back and leaves the previously durable
|
||||||
|
`running` record available for stale-fence handling; modules must not commit
|
||||||
|
their domain state first and close an `atomic` recovery record afterwards.
|
||||||
|
|
||||||
|
An owning module may reconcile an `outcome_unknown` provider effect through the
|
||||||
|
claimed durable handle's `resolve_unknown` method. External evidence that the
|
||||||
|
effect occurred records verified success. Evidence that it did not occur moves
|
||||||
|
the operation through recovery-required and recovering to verified recovered,
|
||||||
|
so any later attempt must use a new deliberate idempotency key. The method does
|
||||||
|
not infer provider state and requires the same terminal verification structure
|
||||||
|
and hash-chain checks as ordinary completion.
|
||||||
@@ -0,0 +1,138 @@
|
|||||||
|
<!-- codex-wiki-sync:9f789b07fb72ce4cdc12dd40 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/INFORMATION_GOVERNANCE_ADOPTION.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Information Governance Adoption
|
||||||
|
|
||||||
|
## Platform Rule
|
||||||
|
|
||||||
|
Temporal browsing, purpose-aware access, retention, and institutional context
|
||||||
|
are platform-wide information-governance dimensions. Every module receives the
|
||||||
|
same contract by default. A module may claim `partial` or `enforced` only with
|
||||||
|
repository-owned object scope, evidence, and limitations; it may claim
|
||||||
|
`not_applicable` only when the dimension genuinely does not apply.
|
||||||
|
|
||||||
|
Historical business data is always authorized under the current security
|
||||||
|
state. No module may use a historical permission, membership, role, function
|
||||||
|
assignment, or policy projection to weaken present-day access.
|
||||||
|
|
||||||
|
Platform-wide adoption is tracked in
|
||||||
|
[GovOPlaN #40](https://git.add-ideas.de/GovOPlaN/govoplan/issues/40), with
|
||||||
|
temporal reads detailed in
|
||||||
|
[GovOPlaN #39](https://git.add-ideas.de/GovOPlaN/govoplan/issues/39).
|
||||||
|
|
||||||
|
## Manifest Declaration
|
||||||
|
|
||||||
|
`ModuleManifest.information_governance` publishes four dimensions:
|
||||||
|
|
||||||
|
- `temporal_browsing`;
|
||||||
|
- `purpose_aware_access`;
|
||||||
|
- `retention`;
|
||||||
|
- `institutional_context`.
|
||||||
|
|
||||||
|
Each dimension declares:
|
||||||
|
|
||||||
|
- adoption: `not_applicable`, `contract_only`, `partial`, or `enforced`;
|
||||||
|
- object types covered;
|
||||||
|
- repository-local test/documentation evidence;
|
||||||
|
- the remaining limitation for `contract_only` or `partial`.
|
||||||
|
|
||||||
|
The default is intentionally `contract_only`. It applies the platform rule
|
||||||
|
without pretending that existing domain queries and effects already enforce
|
||||||
|
it. `reference_ready`, `supported`, and `lts` modules cannot retain an
|
||||||
|
applicable dimension below `enforced`.
|
||||||
|
|
||||||
|
## Read Contract
|
||||||
|
|
||||||
|
For every persistent domain object, the owner classifies the read:
|
||||||
|
|
||||||
|
1. **Current-only:** historical semantics do not exist and the API says so.
|
||||||
|
2. **Valid-time:** select facts effective now or at the requested instant.
|
||||||
|
3. **Bitemporal:** additionally select only revisions known by `recorded_at`.
|
||||||
|
4. **All-validity:** return effective revisions in a bounded history view.
|
||||||
|
|
||||||
|
The Core temporal middleware supplies the request context. Owners apply it in
|
||||||
|
repositories or query helpers, include it in cache keys, return evaluated
|
||||||
|
context, and test current/at/all plus recorded-time boundaries. Search,
|
||||||
|
reporting, exports, selectors, counts, and drill-through must use the same
|
||||||
|
projection as the owning list/detail API.
|
||||||
|
|
||||||
|
## Purpose-Aware Access Contract
|
||||||
|
|
||||||
|
Permission establishes a technical action ceiling. Purpose-aware access asks
|
||||||
|
whether this actor, represented capacity, case/work item, legal basis, and
|
||||||
|
declared use may access this object now.
|
||||||
|
|
||||||
|
- A client-supplied purpose is an assertion, never authority by itself.
|
||||||
|
- The owner or Policy capability validates the purpose and returns explainable
|
||||||
|
provenance.
|
||||||
|
- Sensitive access can require case assignment, mandate, reason capture,
|
||||||
|
approval, or break-glass evidence.
|
||||||
|
- Search, selectors, reporting, exports, background jobs, and connectors apply
|
||||||
|
the same decision.
|
||||||
|
- Audit records the validated purpose identifier and decision reference, not
|
||||||
|
unnecessary content.
|
||||||
|
|
||||||
|
## Retention Contract
|
||||||
|
|
||||||
|
Every persistent object declares an owner, retention class or policy reference,
|
||||||
|
trigger, start instant, hold behavior, review/disposition action, and evidence.
|
||||||
|
Retention is not a generic timestamp deletion job.
|
||||||
|
|
||||||
|
- Domain owners enumerate and execute their own effects through a typed
|
||||||
|
retention provider.
|
||||||
|
- Policy resolves inherited ceilings and simulation.
|
||||||
|
- Records owns record disposition; Files owns byte/object effects; Audit owns
|
||||||
|
audit-detail behavior; external providers declare their own effect and
|
||||||
|
recovery semantics.
|
||||||
|
- Dry-run, legal hold, exact revision, idempotency, outcome unknown,
|
||||||
|
reconciliation, correction, and destruction evidence are mandatory for
|
||||||
|
consequential removal.
|
||||||
|
|
||||||
|
## Institutional Context Contract
|
||||||
|
|
||||||
|
Consequential objects and effects carry the relevant tenant, institution,
|
||||||
|
organization unit, function, mandate/jurisdiction, service/case/work item,
|
||||||
|
party/representation, decision, and record references. Context is minimized to
|
||||||
|
what the operation needs. Organizational membership is not itself permission
|
||||||
|
or mandate.
|
||||||
|
|
||||||
|
Events, automation intents, audit evidence, records, and external effects retain
|
||||||
|
the same governed context envelope or an exact reference to it. Consumers must
|
||||||
|
not reconstruct authority later from mutable current structures.
|
||||||
|
|
||||||
|
## Adoption Order
|
||||||
|
|
||||||
|
1. Inventory every domain list/detail/search/export/effect and classify all
|
||||||
|
four dimensions.
|
||||||
|
2. Migrate institutional owners first: Access, IDM, Organizations, Mandates,
|
||||||
|
Services, Parties, Cases, Approvals, Committee, Decisions, Voting, and
|
||||||
|
Records.
|
||||||
|
3. Migrate communication and content: Addresses, Distribution Lists, Campaign,
|
||||||
|
Postbox, Mail, Calendar, Files, Templates, and Forms Runtime.
|
||||||
|
4. Migrate data projections: Connectors, Datasources, Dataflow, Reporting,
|
||||||
|
Search, Risk Compliance, and Dashboard.
|
||||||
|
5. Migrate workflow/task/background/provider operations and prove that no
|
||||||
|
asynchronous path drops context.
|
||||||
|
6. Advance manifest claims only after owner tests and browser/reference-journey
|
||||||
|
evidence pass.
|
||||||
|
|
||||||
|
The generated platform inventory reports adoption counts and module details.
|
||||||
|
Gitea tracks individual migrations; the declaration is evidence and a maturity
|
||||||
|
gate, not a substitute for implementation.
|
||||||
|
|
||||||
|
## Definition Of Enforced
|
||||||
|
|
||||||
|
A dimension is `enforced` only when:
|
||||||
|
|
||||||
|
- all declared object types and public reads/effects use it;
|
||||||
|
- list/detail/count/search/export/worker behavior is consistent;
|
||||||
|
- cache and pagination semantics cannot cross contexts;
|
||||||
|
- absence, invalid values, and inaccessible referenced context fail safely;
|
||||||
|
- tests cover current, historical, unauthorized, replay, and module-absence
|
||||||
|
combinations appropriate to the dimension;
|
||||||
|
- user/admin documentation explains behavior and limitations;
|
||||||
|
- the manifest cites those tests and docs.
|
||||||
@@ -1,166 +0,0 @@
|
|||||||
<!-- codex-wiki-sync:c61d4e854c9fddd8b2222b97 -->
|
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/INSTITUTIONAL_CONTEXT_CONTRACT.md`.
|
|
||||||
> Origin: `repository`.
|
|
||||||
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
|
||||||
|
|
||||||
---
|
|
||||||
# Institutional Context And Governed References
|
|
||||||
|
|
||||||
GovOPlaN consequential work must retain enough context to answer who acted,
|
|
||||||
for whom, through which function, under which mandate and jurisdiction, using
|
|
||||||
which rule and evidence versions, and with which requested and observed effect.
|
|
||||||
The shared contract lives in `govoplan_core.core.institutional`.
|
|
||||||
|
|
||||||
Core owns reference shapes and provider protocols only. It does not own shared
|
|
||||||
Mandate, Service, Party, Decision, evidence, or geography tables. Domain modules
|
|
||||||
own persistence and authorization; optional capabilities resolve the references.
|
|
||||||
|
|
||||||
## Envelope
|
|
||||||
|
|
||||||
`GovernedContextEnvelope` version 1 carries:
|
|
||||||
|
|
||||||
- a tenant and `TemporalRevision` with validity, recording, supersession, and
|
|
||||||
change reason;
|
|
||||||
- the real account or service account and represented account, function,
|
|
||||||
procedure party, assignment, delegation/power, and mandate;
|
|
||||||
- institution, organization unit, function, task, mandate, jurisdiction,
|
|
||||||
service, case, party, work item, workflow, approval, decision, and record
|
|
||||||
references;
|
|
||||||
- versioned legal bases and evidence references;
|
|
||||||
- information classification, purposes, retention/holds, minimization, and
|
|
||||||
disclosure state;
|
|
||||||
- external-source authority, maturity, freshness, health, and conflict state;
|
|
||||||
- language, accessibility, channel, explanation, and availability references.
|
|
||||||
|
|
||||||
Every institutional reference includes the owner module, tenant, stable object
|
|
||||||
identity, optional version/effective instant, and a protected display label.
|
|
||||||
Cross-tenant references are rejected. Safe serialization omits labels,
|
|
||||||
inspection URLs, formal reasoning, operative results, and conditions unless a
|
|
||||||
caller explicitly requests the protected projection.
|
|
||||||
|
|
||||||
## Semantic Providers
|
|
||||||
|
|
||||||
The first provider-neutral capabilities are:
|
|
||||||
|
|
||||||
- `mandates.resolver`: resolve competence for a task/authority type at an
|
|
||||||
effective instant and return the governing Mandate definition and evidence;
|
|
||||||
- `services.definitions`: obtain versioned institutional service definitions;
|
|
||||||
- `parties.resolver`: obtain effective procedure-local parties and powers of
|
|
||||||
representation without copying Identity or Organizations subjects; and
|
|
||||||
- `decisions.registry`: record and retrieve formal Decisions under optimistic
|
|
||||||
revision control.
|
|
||||||
|
|
||||||
The Mandate, Service, Party/representation, and Decision DTOs have strict
|
|
||||||
mapping round-trips so they can cross capability, event, package, and storage
|
|
||||||
boundaries without shared ORM models. Their lifecycle states are explicit:
|
|
||||||
Mandates distinguish draft/active/suspended/replaced/retired, Services retain
|
|
||||||
publication state, Parties retain effective representation and revocation, and
|
|
||||||
Decisions retain correction, revocation, and supersession references.
|
|
||||||
|
|
||||||
The DTOs are a repository threshold, not a mandate to create four modules.
|
|
||||||
Independent persistence, lifecycle, security/operations behavior, release
|
|
||||||
reason, reuse, and tests are still required before extraction.
|
|
||||||
|
|
||||||
Mandate resolution is deterministic: Core filters candidates by tenant,
|
|
||||||
effective interval, active state, task and authority type, stable
|
|
||||||
organization/function identity, jurisdiction coverage, and subject type. A
|
|
||||||
result is competent only when exactly one matching Mandate remains and it has
|
|
||||||
no unresolved conflicts. Evidence from matching definitions is deduplicated
|
|
||||||
and retained in the explanation result. `revise_mandate_definition` applies
|
|
||||||
optimistic concurrency and the allowed activation, suspension, replacement,
|
|
||||||
and retirement transitions while leaving the previous revision immutable.
|
|
||||||
|
|
||||||
`revise_formal_decision` provides the equivalent lifecycle primitive for
|
|
||||||
formal outcomes. Every accepted transition requires a new recorded revision
|
|
||||||
and change reason, links `supersedes_ref` to the prior version, updates the
|
|
||||||
authority envelope to the new version, and records explicit correction or
|
|
||||||
revocation provenance. Terminal and backward transitions fail closed. Each
|
|
||||||
Decision also records whether responsibility was human, human-reviewed
|
|
||||||
automation, or an automated service account acting under mandate. Automation
|
|
||||||
preparation/recommendation references remain inspectable without being
|
|
||||||
mistaken for the responsible outcome.
|
|
||||||
|
|
||||||
Procedure-party corrections use `revise_procedure_party`: the stable party
|
|
||||||
identity is retained, a new revision and reason are required, stale writes are
|
|
||||||
rejected, and revoked/expired/superseded assignments are terminal.
|
|
||||||
`revoke_party_representation` separately records when a limited power ceased
|
|
||||||
to authorize actions. This allows consuming procedures to evaluate historical
|
|
||||||
delivery or representation authority without rewriting Identity,
|
|
||||||
Organizations, or Addresses records.
|
|
||||||
|
|
||||||
Service templates and package/tenant specializations use
|
|
||||||
`derive_service_restriction`. The derived definition retains an explicit
|
|
||||||
parent-version reference, cannot extend the parent's validity, audience,
|
|
||||||
channels, or publication ceiling, and cannot remove inherited prerequisites,
|
|
||||||
required evidence, legal bases, or bindings. This is the fail-closed semantic
|
|
||||||
rule; configuration-package signature and provenance checks remain the package
|
|
||||||
transport rule.
|
|
||||||
|
|
||||||
`ServiceAvailabilityRequirement` represents module, capability, mandate,
|
|
||||||
policy, connector, maintenance, audience, and configuration prerequisites with
|
|
||||||
an explicit unavailable-or-hidden failure mode and explanation reference. The
|
|
||||||
optional `services.availability` evaluator returns policy-scoped boolean
|
|
||||||
assessments, reason codes, and evidence. Unknown consequential requirements
|
|
||||||
fail closed; a reference itself never grants access.
|
|
||||||
|
|
||||||
## Service Launch
|
|
||||||
|
|
||||||
`ServiceLaunchRequest` and `ServiceLaunchResult` define the owner-neutral
|
|
||||||
boundary between Portal entry and a case, form, or workflow runtime effect.
|
|
||||||
The request carries the exact published Service definition, exact selected
|
|
||||||
binding, tenant, acting identity, timezone-aware request time, bounded
|
|
||||||
parameters, and idempotency key. The result must retain that exact Service and
|
|
||||||
binding, a same-tenant target reference, optional same-tenant evidence, and
|
|
||||||
only a relative or credential-free HTTP(S) destination.
|
|
||||||
|
|
||||||
`service_launch_capability(kind)` maps bindings to owner capabilities:
|
|
||||||
|
|
||||||
- `case` -> `cases.service_launcher`
|
|
||||||
- `form` -> `forms_runtime.service_launcher`
|
|
||||||
- `workflow` -> `workflow_engine.service_launcher`
|
|
||||||
|
|
||||||
`FormDefinition`, `FormFieldDefinition`, and `forms.definitions` provide the
|
|
||||||
owner-neutral exact-schema boundary used by Forms Runtime. Definitions carry an
|
|
||||||
exact tenant/revision, field types/options/constraints/defaults, publication,
|
|
||||||
draft, attachment, signature, policy, and handoff requirements. Forms owns
|
|
||||||
those immutable definitions; Forms Runtime persists instances and validation
|
|
||||||
evidence. A form Service binding uses `<form-id>/<revision>` and the launcher
|
|
||||||
rejects missing, superseded, unpublished, cross-tenant, or invalid definitions.
|
|
||||||
|
|
||||||
Portal may discover and invoke those capabilities but cannot write owner
|
|
||||||
tables. The owner must revalidate its definition/binding and current
|
|
||||||
authorization, produce its normal audit/event state, and make replay after an
|
|
||||||
ambiguous response safe. If the capability is absent, the service is
|
|
||||||
explainably unavailable. URL-only entries pass through the same launch-time
|
|
||||||
availability check and destination validation. Forms Runtime now supplies the
|
|
||||||
definition-aware form launcher when both Forms and Forms Runtime are active;
|
|
||||||
otherwise Portal continues to fail closed.
|
|
||||||
|
|
||||||
## Propagation
|
|
||||||
|
|
||||||
`PlatformEvent`, `ActionExecutionRequest`, and `AuditEvent` can carry the
|
|
||||||
envelope. Audit persistence stores only its safe projection; platform-event
|
|
||||||
outbox serialization preserves it across asynchronous delivery. A module must
|
|
||||||
not invent a parallel context dictionary when the shared fields apply.
|
|
||||||
|
|
||||||
## First Proof
|
|
||||||
|
|
||||||
Committee's `committee.decision_path` capability is the first bounded proof. It
|
|
||||||
requires one effective, conflict-free Mandate covering the organization unit
|
|
||||||
function, and jurisdiction, an approval reference, fact evidence, versioned legal bases,
|
|
||||||
operative result, and reasoning. It emits a reconstructable `FormalDecision`,
|
|
||||||
including requested/observed effects and information governance. If a Decision
|
|
||||||
registry is installed it persists there; Committee does not take ownership of
|
|
||||||
the generic Decision lifecycle.
|
|
||||||
|
|
||||||
## Compatibility And Security
|
|
||||||
|
|
||||||
- Contract version changes follow Core compatibility policy.
|
|
||||||
- Unknown tenant or reference-kind combinations fail closed.
|
|
||||||
- Datetimes that affect authority must be timezone-aware.
|
|
||||||
- Protected labels, reasoning, evidence inspection links, and source details
|
|
||||||
remain subject to the owning module's access policy.
|
|
||||||
- References do not grant access to their targets.
|
|
||||||
- Evidence and audit payloads must contain stable references/checksums, not
|
|
||||||
plaintext secrets.
|
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:f1292668197e8a694ddf8f39 -->
|
<!-- codex-wiki-sync:0024c559045ddaee764d4715 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/INSTITUTIONAL_CONTEXT_CONTRACT.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/INSTITUTIONAL_CONTEXT_CONTRACT.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -15,6 +15,9 @@ The shared contract lives in `govoplan_core.core.institutional`.
|
|||||||
Core owns reference shapes and provider protocols only. It does not own shared
|
Core owns reference shapes and provider protocols only. It does not own shared
|
||||||
Mandate, Service, Party, Decision, evidence, or geography tables. Domain modules
|
Mandate, Service, Party, Decision, evidence, or geography tables. Domain modules
|
||||||
own persistence and authorization; optional capabilities resolve the references.
|
own persistence and authorization; optional capabilities resolve the references.
|
||||||
|
Interactive reads use the separate platform temporal-data context documented in
|
||||||
|
`TEMPORAL_DATA_CONTEXT.md`; it never changes current authorization or supplies
|
||||||
|
mutation dates.
|
||||||
|
|
||||||
## Envelope
|
## Envelope
|
||||||
|
|
||||||
@@ -120,14 +123,22 @@ only a relative or credential-free HTTP(S) destination.
|
|||||||
- `form` -> `forms_runtime.service_launcher`
|
- `form` -> `forms_runtime.service_launcher`
|
||||||
- `workflow` -> `workflow_engine.service_launcher`
|
- `workflow` -> `workflow_engine.service_launcher`
|
||||||
|
|
||||||
|
`FormDefinition`, `FormFieldDefinition`, and `forms.definitions` provide the
|
||||||
|
owner-neutral exact-schema boundary used by Forms Runtime. Definitions carry an
|
||||||
|
exact tenant/revision, field types/options/constraints/defaults, publication,
|
||||||
|
draft, attachment, signature, policy, and handoff requirements. Forms owns
|
||||||
|
those immutable definitions; Forms Runtime persists instances and validation
|
||||||
|
evidence. A form Service binding uses `<form-id>/<revision>` and the launcher
|
||||||
|
rejects missing, superseded, unpublished, cross-tenant, or invalid definitions.
|
||||||
|
|
||||||
Portal may discover and invoke those capabilities but cannot write owner
|
Portal may discover and invoke those capabilities but cannot write owner
|
||||||
tables. The owner must revalidate its definition/binding and current
|
tables. The owner must revalidate its definition/binding and current
|
||||||
authorization, produce its normal audit/event state, and make replay after an
|
authorization, produce its normal audit/event state, and make replay after an
|
||||||
ambiguous response safe. If the capability is absent, the service is
|
ambiguous response safe. If the capability is absent, the service is
|
||||||
explainably unavailable. URL-only entries pass through the same launch-time
|
explainably unavailable. URL-only entries pass through the same launch-time
|
||||||
availability check and destination validation. A missing form runtime must
|
availability check and destination validation. Forms Runtime now supplies the
|
||||||
therefore fail closed rather than create a submission without definition-aware
|
definition-aware form launcher when both Forms and Forms Runtime are active;
|
||||||
validation.
|
otherwise Portal continues to fail closed.
|
||||||
|
|
||||||
## Propagation
|
## Propagation
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<!-- codex-wiki-sync:092a2224eb18042233ecae79 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/INTERFACE_PATTERN_MIGRATION.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Core Interface Pattern Migration
|
||||||
|
|
||||||
|
This document records the Core-owned part of the product-wide interface
|
||||||
|
pattern-language rollout. The normative product grammar and complete route
|
||||||
|
inventory live in the `govoplan` meta repository. Core owns reusable behavior;
|
||||||
|
domain modules own their compositions.
|
||||||
|
|
||||||
|
## Core Surfaces
|
||||||
|
|
||||||
|
| Surface | Pattern | Consequence and provenance contract | Evidence |
|
||||||
|
| --- | --- | --- | --- |
|
||||||
|
| User settings | Two-zone settings workspace with typed controls and unsaved-change protection | Save actions distinguish busy, unchanged, and test-in-progress states; contextual help resolves through Docs or the hosted fallback | `SettingsPage.tsx`, `test-core-interface-patterns.mjs` |
|
||||||
|
| Reusable credentials | Repeated administration with an adaptive create/edit dialog, optional password generator, and destructive confirmation | Secret values are write-only; generated candidates use the browser cryptographic API without a weak fallback and do not replace the field until explicitly confirmed; scope/permission blockers name the required action, responsible actor, and destination; unavailable row actions remain keyboard-explainable | `CredentialEnvelopeManager.tsx`, shared `PasswordField`, `PasswordGeneratorDialog`, `ActionBlockerHint`, `Button`, `TableActionGroup`, and `ConfirmDialog` |
|
||||||
|
| Retention policy | Effective-policy editor with inherited source paths and typed, narrowing-only controls | Parent locks and missing write authority are explicit; the save action distinguishes locks, missing target, loading, clean draft, and active save | `RetentionPolicyManagement.tsx`, policy logic tests, `test-core-interface-patterns.mjs` |
|
||||||
|
| Module lifecycle | Guided operator projection over durable installer-queue evidence | Preflight, handoff, progress, stale evidence, recovery, and rollback consequences remain visible | Admin module lifecycle tests and the Core installer-queue contract |
|
||||||
|
| Shared configuration primitives | Cross-module component contract | Dialog focus, blocker structure, disabled-action focus, route/page/field/action F1 help, unsaved changes, confirmation, loading, alerts, problem lists, and policy provenance are centralized | Core component tests, `CONTEXTUAL_HELP_CONTRACT.md`, and module-permutation build |
|
||||||
|
|
||||||
|
## Boundary
|
||||||
|
|
||||||
|
Files and Mail are the first two external consumers of the layered
|
||||||
|
server/credential/policy pattern. Their own repositories retain provider
|
||||||
|
discovery, transport behavior, authorization, and migration evidence. Remaining
|
||||||
|
module surfaces are tracked by bounded module-owned issues under GovOPlaN #11;
|
||||||
|
they are not reasons to add sibling-private behavior to Core.
|
||||||
|
|
||||||
|
Raw JSON remains permitted only for diagnostics, expert inspection,
|
||||||
|
interchange, or conflict evidence. It is not a primary Core configuration
|
||||||
|
editor.
|
||||||
@@ -0,0 +1,67 @@
|
|||||||
|
<!-- codex-wiki-sync:e12f3c538da0037bcfbd2a00 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/LOCALIZATION_AND_HELP_QUALITY.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Localization And Contextual Help Quality
|
||||||
|
|
||||||
|
## Reference Language
|
||||||
|
|
||||||
|
German (`de`) is GovOPlaN's first-class reference target. Every translation key
|
||||||
|
used by a shipped WebUI must exist in German and English. German completeness is
|
||||||
|
a release gate; English remains the source-code fallback language so existing
|
||||||
|
literal labels and external developer APIs do not change semantics.
|
||||||
|
|
||||||
|
New installations and tenants default to German. Existing system, tenant, and
|
||||||
|
user preferences are preserved. The available-language and policy model can
|
||||||
|
still select another default or disable a package at the relevant scope.
|
||||||
|
|
||||||
|
Explicit high-risk help content and browser acceptance are tracked in
|
||||||
|
[Core #284](https://git.add-ideas.de/GovOPlaN/govoplan-core/issues/284).
|
||||||
|
|
||||||
|
The platform inventory recognizes both inline locale objects and generated
|
||||||
|
catalogs declared as `const de` / `const en`. Its strict mode requires both
|
||||||
|
locales and reports `de` explicitly as the reference locale.
|
||||||
|
|
||||||
|
## Help Resolution
|
||||||
|
|
||||||
|
Every focusable field and action receives a stable derived F1 identity from the
|
||||||
|
shared shell, even when the component has no dedicated help text. Resolution
|
||||||
|
falls back from field/action to dialog or page and then to the module's visible
|
||||||
|
documentation baseline.
|
||||||
|
|
||||||
|
Backend manifests publish explicit topic associations first. Core additionally
|
||||||
|
associates declared route, navigation, settings, and View surface IDs with the
|
||||||
|
module's static user or administrator documentation baseline. Feature modules
|
||||||
|
should still add exact `metadata.help_contexts` entries for consequential,
|
||||||
|
unfamiliar, policy-controlled, destructive, security-sensitive, or legally
|
||||||
|
meaningful fields and actions.
|
||||||
|
|
||||||
|
The generated `help_review_candidates` list is therefore a content-depth queue,
|
||||||
|
not a list of controls on which F1 cannot work. It should prioritize:
|
||||||
|
|
||||||
|
1. effect, deletion, delivery, retention, disclosure, encryption, and recovery;
|
||||||
|
2. identity, representation, mandate, institutional context, and purpose;
|
||||||
|
3. valid-time versus recorded-time selection;
|
||||||
|
4. provider authority, synchronization, conflict, and outcome unknown;
|
||||||
|
5. fields whose consequences are not evident from their label.
|
||||||
|
|
||||||
|
## Verification
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd /mnt/DATA/git/govoplan
|
||||||
|
/mnt/DATA/git/govoplan/.venv/bin/python \
|
||||||
|
tools/inventory/platform-interface-inventory.py \
|
||||||
|
--strict --strict-declarations --strict-endpoints
|
||||||
|
```
|
||||||
|
|
||||||
|
The check must report:
|
||||||
|
|
||||||
|
- reference locale `de` present and complete;
|
||||||
|
- no used key missing from `de` or `en`;
|
||||||
|
- every field has a resolvable F1 context;
|
||||||
|
- no duplicate stable IDs;
|
||||||
|
- no undeclared public WebUI surface;
|
||||||
|
- no stale runtime route or endpoint declaration.
|
||||||
File diff suppressed because it is too large
Load Diff
+141
-6
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:ce8c6801ea5b697488555e32 -->
|
<!-- codex-wiki-sync:754dca1bc8283d2d296f9b31 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/MODULE_ARCHITECTURE.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/MODULE_ARCHITECTURE.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -214,12 +214,20 @@ Other stable runtime capabilities currently include:
|
|||||||
|
|
||||||
- `identity.directory` and `identity.search`
|
- `identity.directory` and `identity.search`
|
||||||
- `organizations.directory`
|
- `organizations.directory`
|
||||||
- `idm.directory`
|
- `idm.directory`, `idm.function_assignments`, `idm.relationships`, and
|
||||||
- `calendar.outbox` and `calendar.scheduling`
|
`idm.assignment_lifecycle`
|
||||||
|
- `calendar.outbox`, `calendar.scheduling`, `calendar.invitations`, and
|
||||||
|
`calendar.externalProfiles`
|
||||||
- `poll.scheduling`
|
- `poll.scheduling`
|
||||||
- `notifications.dispatch`
|
- `notifications.dispatch`
|
||||||
- `workflow.definitionContributions` and `workflow.runtimeWorker`
|
- `workflow.definitionContributions` and `workflow.runtimeWorker`
|
||||||
|
|
||||||
|
The provider-neutral `idm.relationships` contract carries tenant-scoped typed
|
||||||
|
groups, effective-dated identity relationships, and explicit membership
|
||||||
|
decisions. It deliberately does not expose IDM persistence models or imply an
|
||||||
|
Access permission. Consumers can retain source revisions and inclusion or
|
||||||
|
exclusion provenance while remaining optional-module safe.
|
||||||
|
|
||||||
Modules contribute reusable process baselines through
|
Modules contribute reusable process baselines through
|
||||||
`ModuleManifest.workflow_definitions`. Each contribution pins its origin module
|
`ModuleManifest.workflow_definitions`. Each contribution pins its origin module
|
||||||
and version, stable key, schema and content hash, native graph/BPMN content,
|
and version, stable key, schema and content hash, native graph/BPMN content,
|
||||||
@@ -292,8 +300,10 @@ such as `calendar:sync-source:<id>`.
|
|||||||
Current named interfaces, generated from the source manifests by the workspace
|
Current named interfaces, generated from the source manifests by the workspace
|
||||||
contract checks, are:
|
contract checks, are:
|
||||||
|
|
||||||
- `addresses.contact_writer`, `addresses.lookup`, `addresses.recipient_source`
|
- `addresses.contact_point_resolution`, `addresses.contact_writer`,
|
||||||
- `calendar.outbox`, `calendar.scheduling`
|
`addresses.lookup`, `addresses.recipient_source`
|
||||||
|
- `calendar.external_profiles`, `calendar.invitations`, `calendar.outbox`,
|
||||||
|
`calendar.scheduling`
|
||||||
- `campaigns.access`, `campaigns.delivery_tasks`,
|
- `campaigns.access`, `campaigns.delivery_tasks`,
|
||||||
`campaigns.mail_policy_context`, `campaigns.policy_context`,
|
`campaigns.mail_policy_context`, `campaigns.policy_context`,
|
||||||
`campaigns.retention`
|
`campaigns.retention`
|
||||||
@@ -735,6 +745,13 @@ effects, transitions partial/unknown outcomes honestly, and records verified
|
|||||||
completion or recovery. Plaintext secrets must never enter recovery metadata or
|
completion or recovery. Plaintext secrets must never enter recovery metadata or
|
||||||
evidence.
|
evidence.
|
||||||
|
|
||||||
|
For a conclusive external result, modules may commit their local success
|
||||||
|
projection and the verified terminal checkpoint in one database transaction via
|
||||||
|
`DurableRecoveryOperation.commit_verified_success`. This does not make the
|
||||||
|
external provider effect atomic. It prevents a local `succeeded` state from
|
||||||
|
becoming authoritative when the recovery evidence chain is damaged or the
|
||||||
|
terminal checkpoint cannot commit.
|
||||||
|
|
||||||
## Install, Uninstall, And Catalogs
|
## Install, Uninstall, And Catalogs
|
||||||
|
|
||||||
Core owns the install plan, signed catalog validation, license entitlement
|
Core owns the install plan, signed catalog validation, license entitlement
|
||||||
@@ -824,12 +841,34 @@ the shared loading and retryable error state around route rendering. The
|
|||||||
initial static import closure and largest asynchronous chunk are enforced by
|
initial static import closure and largest asynchronous chunk are enforced by
|
||||||
the budgets documented in [WEBUI_BUNDLE_BUDGETS.md](WEBUI_BUNDLE_BUDGETS.md).
|
the budgets documented in [WEBUI_BUNDLE_BUDGETS.md](WEBUI_BUNDLE_BUDGETS.md).
|
||||||
|
|
||||||
|
Every public platform interface has a stable declaration identity. Backend
|
||||||
|
routes, capabilities, interfaces, search providers/sources, permissions,
|
||||||
|
frontend routes/navigation, and View surfaces derive that identity from typed
|
||||||
|
`ModuleManifest` values. Typed WebUI capabilities declare IDs for settings,
|
||||||
|
admin sections, widgets, search contexts, and extension actions. Shared form
|
||||||
|
and action controls accept `interfaceId` and `helpTopicId`; use module-namespaced
|
||||||
|
values when another contract, documentation topic, or automated check must
|
||||||
|
refer to the control across source changes. The static inventory assigns a
|
||||||
|
line-independent source anchor when an explicit ID is absent and reports that
|
||||||
|
fact for later review.
|
||||||
|
|
||||||
|
Core exposes the sanitized runtime declaration set at
|
||||||
|
`GET /api/v1/platform/interface-catalog`. The endpoint is read-only, requires
|
||||||
|
`admin:module:read` or `system:settings:read`, and includes only modules
|
||||||
|
effective in the caller's active tenant context. It never serializes factories,
|
||||||
|
credentials, executable callbacks, or mutable module state. Registry validation
|
||||||
|
rejects conflicting declaration IDs before startup.
|
||||||
|
|
||||||
WebUI modules receive only the core route context:
|
WebUI modules receive only the core route context:
|
||||||
|
|
||||||
- `settings`
|
- `settings`
|
||||||
- `auth`
|
- `auth`
|
||||||
|
|
||||||
A module should call its own API client and module-owned backend routes. Shared API helpers should live in core only when they are truly platform-level concerns.
|
A module should call its own API client and module-owned backend routes. Shared API helpers should live in core only when they are truly platform-level concerns.
|
||||||
|
For ordinary JSON mutations, use Core's `apiPostJson` and `apiPatchJson`
|
||||||
|
helpers. They preserve the shared authentication, CSRF, error, and request
|
||||||
|
invalidation behavior while leaving endpoint types and feature semantics in the
|
||||||
|
owning module.
|
||||||
|
|
||||||
Modules can also contribute named UI capabilities for explicit extension
|
Modules can also contribute named UI capabilities for explicit extension
|
||||||
points. Capability values must be narrow, typed contracts, not imports from a
|
points. Capability values must be narrow, typed contracts, not imports from a
|
||||||
@@ -1012,6 +1051,16 @@ Decision: templates and reporting are separate modules.
|
|||||||
and export targets
|
and export targets
|
||||||
- report permissions, report execution history, generated report evidence, and
|
- report permissions, report execution history, generated report evidence, and
|
||||||
report-specific retention inputs
|
report-specific retention inputs
|
||||||
|
|
||||||
|
Cross-module reports use Core's versioned
|
||||||
|
`reporting.report_provider.<provider-id>` contract. Source modules own
|
||||||
|
authorization, parameters, source revisions, effective scope, result schema,
|
||||||
|
and privacy transforms; Reporting owns discovery, validation, governed
|
||||||
|
execution, provenance, export history, and the global `/reports` route. The
|
||||||
|
optional `policy.reporting_governance` capability can only tighten execution,
|
||||||
|
retention, export, and re-identification-risk handling. Reporting exposes
|
||||||
|
`reporting.retention` so the Policy-owned retention run can minimize expired
|
||||||
|
provider results without importing Reporting models.
|
||||||
- downstream export handoff to files, dataflow, connectors, or publication
|
- downstream export handoff to files, dataflow, connectors, or publication
|
||||||
surfaces
|
surfaces
|
||||||
|
|
||||||
@@ -1104,7 +1153,7 @@ from workflow semantics.
|
|||||||
- form definitions, schemas, validation rules, field visibility rules,
|
- form definitions, schemas, validation rules, field visibility rules,
|
||||||
localization, versioning, admin editing, and reusable form package fragments
|
localization, versioning, admin editing, and reusable form package fragments
|
||||||
|
|
||||||
`govoplan-forms-runtime` owns, when implemented:
|
`govoplan-forms-runtime` owns:
|
||||||
|
|
||||||
- public/internal submissions, drafts, submitted values, validation evidence,
|
- public/internal submissions, drafts, submitted values, validation evidence,
|
||||||
attachment references, submission receipts, and handoff events
|
attachment references, submission receipts, and handoff events
|
||||||
@@ -1117,6 +1166,16 @@ Boundary:
|
|||||||
- Reporting/dataflow may consume submitted data through governed DTOs or
|
- Reporting/dataflow may consume submitted data through governed DTOs or
|
||||||
source lifecycle contracts.
|
source lifecycle contracts.
|
||||||
|
|
||||||
|
Implemented contract:
|
||||||
|
|
||||||
|
- Core owns the provider-neutral `FormDefinition`/`FormFieldDefinition` DTOs.
|
||||||
|
- Forms persists immutable exact definitions and provides `forms.definitions`.
|
||||||
|
- Forms Runtime resolves that capability, persists revisioned instances and
|
||||||
|
events, validates draft/final values, and provides
|
||||||
|
`forms_runtime.service_launcher`.
|
||||||
|
- Portal delegates exact `<form-id>/<revision>` bindings and never writes either
|
||||||
|
owner's tables.
|
||||||
|
|
||||||
### OpenDesk Integration Profile
|
### OpenDesk Integration Profile
|
||||||
|
|
||||||
Tracking: `govoplan-core#195`, `govoplan-connectors#5`,
|
Tracking: `govoplan-core#195`, `govoplan-connectors#5`,
|
||||||
@@ -1205,6 +1264,61 @@ devserver, development bootstrap, background worker registry, and migration
|
|||||||
metadata plan all read the saved desired state from `system_settings` before
|
metadata plan all read the saved desired state from `system_settings` before
|
||||||
building their module registry.
|
building their module registry.
|
||||||
|
|
||||||
|
### Tenant entitlement and personal visibility
|
||||||
|
|
||||||
|
Deployment activation remains process-wide: one installed and active registry
|
||||||
|
is shared by every tenant served by that process. Tenant module selection is a
|
||||||
|
separate entitlement document in `core_scopes.settings.module_entitlements`:
|
||||||
|
|
||||||
|
- a system policy marks each installed module `unavailable`, `available`, or
|
||||||
|
`forced` for one tenant;
|
||||||
|
- the tenant selection may enable or disable only available modules;
|
||||||
|
- protected platform modules, forced modules, and transitive dependencies stay
|
||||||
|
effective;
|
||||||
|
- malformed explicit entitlement fails closed to protected modules, while an
|
||||||
|
absent document preserves the pre-entitlement behavior for upgraded tenants;
|
||||||
|
- an optimistic revision prevents concurrent system and tenant administrators
|
||||||
|
from silently replacing each other's changes.
|
||||||
|
|
||||||
|
The authenticated platform metadata and module route guard intersect global
|
||||||
|
runtime activation with the active tenant's effective entitlement. Entitlement
|
||||||
|
does not grant a permission. Access authorization must still allow every API
|
||||||
|
operation and resource.
|
||||||
|
|
||||||
|
The same boundary applies outside authenticated request handling:
|
||||||
|
|
||||||
|
- capability factories retain their owning module, and tenant-scoped capability
|
||||||
|
lookup treats a provider that is unavailable to the tenant as absent;
|
||||||
|
- workers partition scheduled scans by tenant before claiming rows;
|
||||||
|
- new work is rejected while a module is unavailable, while already accepted
|
||||||
|
durable work remains in provider-owned storage and is reported as
|
||||||
|
`operator_action_required` instead of being dropped or executed;
|
||||||
|
- Workflow, Dataflow, event consumers, reconciliation jobs, and external-effect
|
||||||
|
outboxes run inside a tenant execution context, so their optional capability
|
||||||
|
calls inherit the same provider checks;
|
||||||
|
- public signed-link modules declare a `public_tenant_resolver`; valid token
|
||||||
|
context is resolved before the route runs and the module entitlement is then
|
||||||
|
enforced without requiring an authenticated principal.
|
||||||
|
|
||||||
|
Entitlement resolution uses a bounded process-local cache. A local policy
|
||||||
|
mutation invalidates its tenant entry immediately; changes made by another node
|
||||||
|
become authoritative after `TENANT_MODULE_ENTITLEMENT_CACHE_TTL_SECONDS`
|
||||||
|
(five seconds by default). This is a bounded staleness optimization, not an
|
||||||
|
authorization grant: a cache miss or resolution failure fails closed.
|
||||||
|
|
||||||
|
Users and groups do not own another module-runtime state. Every WebUI module
|
||||||
|
already contributes a root `<module>.module` View surface, so personal and
|
||||||
|
group module visibility is expressed through Views. View policy controls who
|
||||||
|
may select, assign, edit, derive, or workflow-activate those projections;
|
||||||
|
required View assignments can retain required UI. Thus tenant entitlement owns
|
||||||
|
operational availability, Views own presentation, and Access owns authority.
|
||||||
|
|
||||||
|
Capability-style modules such as Encryption must keep activation separate from
|
||||||
|
domain data state. Making Encryption effective only exposes its capability and
|
||||||
|
administration surfaces. Encrypting, rekeying, decrypting, or migrating data is
|
||||||
|
an explicit versioned protection-policy operation owned by Encryption and the
|
||||||
|
module that owns the data.
|
||||||
|
|
||||||
Hot enable/disable is a core design principle for every module:
|
Hot enable/disable is a core design principle for every module:
|
||||||
|
|
||||||
- Core keeps one mutable active `PlatformRegistry` object and swaps its manifest
|
- Core keeps one mutable active `PlatformRegistry` object and swaps its manifest
|
||||||
@@ -1312,6 +1426,11 @@ The package install-plan API records operator intent only:
|
|||||||
default; successful uninstalls are removed from saved startup state by default.
|
default; successful uninstalls are removed from saved startup state by default.
|
||||||
Use `--no-activate-installed-modules` or
|
Use `--no-activate-installed-modules` or
|
||||||
`--keep-uninstalled-modules-in-desired` only for staged rollout workflows.
|
`--keep-uninstalled-modules-in-desired` only for staged rollout workflows.
|
||||||
|
- Every non-dry installer and live active-graph mutation acquires the
|
||||||
|
deployment-wide `core:module-lifecycle:deployment` lease and records a Core
|
||||||
|
recovery operation. Unresolved effects block later lifecycle changes. The
|
||||||
|
operation modes and operator reconciliation contract are defined in
|
||||||
|
`MODULE_LIFECYCLE_RECOVERY.md`.
|
||||||
- `govoplan-module-installer --supervise --migrate --health-url http://127.0.0.1:8000/health --restart-command '<restart govoplan server>'`
|
- `govoplan-module-installer --supervise --migrate --health-url http://127.0.0.1:8000/health --restart-command '<restart govoplan server>'`
|
||||||
is the preferred disruptive-change path. It applies the plan, optionally runs
|
is the preferred disruptive-change path. It applies the plan, optionally runs
|
||||||
migrations in a fresh Python process after a fresh-process manifest
|
migrations in a fresh Python process after a fresh-process manifest
|
||||||
@@ -1464,6 +1583,22 @@ The first implementation is a platform access gate. It does not replace
|
|||||||
database backups, process supervision, migration checks, or external load
|
database backups, process supervision, migration checks, or external load
|
||||||
balancer maintenance pages.
|
balancer maintenance pages.
|
||||||
|
|
||||||
|
## Connector Runtime Contract
|
||||||
|
|
||||||
|
Core defines provider-neutral connector preview and diagnostic primitives in
|
||||||
|
`govoplan_core.core.connector_runtime`. The contract keeps optional modules
|
||||||
|
decoupled: Connectors owns transport, endpoint discovery, retries, and protocol
|
||||||
|
health; the consuming domain module owns mappings, validation, reconciliation,
|
||||||
|
and mutations of its records.
|
||||||
|
|
||||||
|
Every dry run is bounded and identifies the source revision, source fingerprint,
|
||||||
|
immutable input hash, effects, and redacted diagnostics. Its summary must match
|
||||||
|
the returned effect list exactly. An apply token is usable only when the preview
|
||||||
|
is complete, current, conflict-free, and contains no error diagnostic. Endpoint
|
||||||
|
URLs never contain credentials; only credential-envelope references cross the
|
||||||
|
contract. Provider-specific details belong in sanitized provenance rather than
|
||||||
|
in a shared domain schema.
|
||||||
|
|
||||||
## Build And Verification
|
## Build And Verification
|
||||||
|
|
||||||
Backend verification from core:
|
Backend verification from core:
|
||||||
|
|||||||
@@ -0,0 +1,73 @@
|
|||||||
|
<!-- codex-wiki-sync:fe2bb7877728c785ea7f864f -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/MODULE_LIFECYCLE_RECOVERY.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Module Lifecycle Recovery
|
||||||
|
|
||||||
|
## Migration Revision Namespace
|
||||||
|
|
||||||
|
All enabled module migration directories are assembled into one Alembic graph. Revision IDs are therefore global across Core and every module even though each module owns a separate `migrations/versions` directory. Core validates literal revision declarations before constructing the graph and rejects duplicates with both file paths. A module must assign a new globally unique revision ID; reusing another module's ID can otherwise make Alembic treat an unrelated schema change as already applied or report an ancestor/head overlap.
|
||||||
|
|
||||||
|
When correcting a collision that has already reached a database, first verify the schema objects that identify which migration actually ran. Rename the unapplied migration, or transactionally translate the corresponding `alembic_version` row when the applied owner is unambiguous. Never add both colliding IDs as heads or blindly stamp the database.
|
||||||
|
|
||||||
|
Package changes and live module-graph changes use Core's durable recovery
|
||||||
|
ledger. The local `install.lock` still prevents duplicate work in one runtime
|
||||||
|
directory; the database lease `core:module-lifecycle:deployment` is the
|
||||||
|
deployment-wide authority across API, installer, worker, and scheduler nodes.
|
||||||
|
|
||||||
|
## Declared Boundaries
|
||||||
|
|
||||||
|
| Operation | Recovery mode | Completion condition |
|
||||||
|
| --- | --- | --- |
|
||||||
|
| `module-lifecycle.pre-migration` | compensation | package, WebUI, manifest, and desired-graph evidence match |
|
||||||
|
| `module-lifecycle.post-migration` | forward recovery | migration tasks, manifests, desired graph, restart, and health are verified |
|
||||||
|
| `module-retirement.destroy-data` | snapshot restore | a hashed, restore-checked backup exists and retirement state is verified |
|
||||||
|
| `module-runtime.apply-graph` | compensation | hooks, capability contexts, active graph, and workflow contributions match |
|
||||||
|
|
||||||
|
The installer prepares the recovery operation before it captures the database
|
||||||
|
snapshot. A full database restore therefore retains the prepared operation and
|
||||||
|
its fence instead of erasing the fact that a mutation was attempted. Backup
|
||||||
|
artifacts are hashed and sized before any package, migration, or retirement
|
||||||
|
effect starts.
|
||||||
|
|
||||||
|
Every command boundary records the command source and canonical hashes of the
|
||||||
|
redacted command/result records. Credentials, database URLs, command output,
|
||||||
|
and package-registry secrets are never copied into recovery evidence.
|
||||||
|
|
||||||
|
## Failure And Retry Rules
|
||||||
|
|
||||||
|
- A conclusive failure before effects is terminal `failed`.
|
||||||
|
- A command or compensatable effect that started but did not complete is
|
||||||
|
`recovery_required`.
|
||||||
|
- A lost or unexpected outcome after a migration/external boundary is
|
||||||
|
`outcome_unknown`.
|
||||||
|
- A verified package/database rollback becomes `recovered`.
|
||||||
|
- A supervised install becomes `succeeded` only after restart and all configured
|
||||||
|
health probes succeed.
|
||||||
|
|
||||||
|
An unresolved lifecycle operation blocks every later lifecycle mutation on the
|
||||||
|
same deployment fence, even after its execution lease is released. Operators
|
||||||
|
must inspect the checkpoint chain and run record, restore or complete the
|
||||||
|
declared recovery path, and explicitly reconcile the operation. A new install
|
||||||
|
must not be used as an implicit retry.
|
||||||
|
|
||||||
|
Live graph changes use the same fence. A non-migrating hook or registry failure
|
||||||
|
restores the prior in-process graph and records verified compensation. A failure
|
||||||
|
after migrations begin remains unresolved because restoring the process-local
|
||||||
|
registry does not reverse database schema effects.
|
||||||
|
|
||||||
|
## Operator Evidence
|
||||||
|
|
||||||
|
The installer run record contains the recovery operation id, mode, plan hash,
|
||||||
|
and current lifecycle status. The Ops recovery view is authoritative for the
|
||||||
|
durable state and evidence-chain result. Keep both the run directory and the
|
||||||
|
state-service backup evidence until the operation is terminal and the normal
|
||||||
|
retention policy permits removal.
|
||||||
|
|
||||||
|
Run the module installer rollback drill and recovery-runtime test matrix before
|
||||||
|
enabling lifecycle mutation in a new deployment. Shared-state deployments must
|
||||||
|
still use immutable release images; the ledger does not make in-place package
|
||||||
|
mutation across replicas safe.
|
||||||
@@ -1,629 +0,0 @@
|
|||||||
<!-- codex-wiki-sync:fdd627b54750063ec1e0e28a -->
|
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/RELEASE_DEPENDENCIES.md`.
|
|
||||||
> Origin: `repository`.
|
|
||||||
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
|
||||||
|
|
||||||
---
|
|
||||||
# GovOPlaN Release Dependencies
|
|
||||||
|
|
||||||
This document owns release package composition, signed package catalogs,
|
|
||||||
license checks, catalog publishing, migration baselines, and the final release
|
|
||||||
checklist.
|
|
||||||
|
|
||||||
Operator runtime configuration and module install/uninstall execution live in
|
|
||||||
`DEPLOYMENT_OPERATOR_GUIDE.md`.
|
|
||||||
|
|
||||||
## Backend Packages
|
|
||||||
|
|
||||||
Release installs must not depend on sibling checkout paths. Local development
|
|
||||||
can keep editable installs and `file:` WebUI links, but release packaging must
|
|
||||||
resolve modules from tagged git refs or from a package registry.
|
|
||||||
|
|
||||||
Local development:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
./.venv/bin/python -m pip install -r requirements-dev.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
Release install from a core checkout plus tagged module repositories:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
./.venv/bin/python -m pip install -r requirements-release.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
`.[server]` is resolved relative to the current working directory. If you
|
|
||||||
create the virtualenv elsewhere, still run the install command from the core
|
|
||||||
checkout:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
/tmp/govoplan-release-test/bin/python -m pip install -r requirements-release.txt
|
|
||||||
```
|
|
||||||
|
|
||||||
`requirements-release.txt` pins the module repositories to the release tag.
|
|
||||||
Update those refs when cutting a release:
|
|
||||||
|
|
||||||
```text
|
|
||||||
govoplan-access git@git.add-ideas.de:add-ideas/govoplan-access.git v0.1.6
|
|
||||||
govoplan-admin git@git.add-ideas.de:add-ideas/govoplan-admin.git v0.1.6
|
|
||||||
govoplan-tenancy git@git.add-ideas.de:add-ideas/govoplan-tenancy.git v0.1.6
|
|
||||||
govoplan-policy git@git.add-ideas.de:add-ideas/govoplan-policy.git v0.1.6
|
|
||||||
govoplan-audit git@git.add-ideas.de:add-ideas/govoplan-audit.git v0.1.6
|
|
||||||
govoplan-files git@git.add-ideas.de:add-ideas/govoplan-files.git v0.1.6
|
|
||||||
govoplan-mail git@git.add-ideas.de:add-ideas/govoplan-mail.git v0.1.6
|
|
||||||
govoplan-campaign git@git.add-ideas.de:add-ideas/govoplan-campaign.git v0.1.6
|
|
||||||
govoplan-calendar git@git.add-ideas.de:add-ideas/govoplan-calendar.git v0.1.6
|
|
||||||
```
|
|
||||||
|
|
||||||
## WebUI Packages
|
|
||||||
|
|
||||||
Local development uses `webui/package.json`, which may point at sibling module
|
|
||||||
checkouts while active development is happening.
|
|
||||||
|
|
||||||
Release WebUI installs should use `webui/package.release.json`. It points
|
|
||||||
module dependencies at the same tagged git repositories. After the module tags
|
|
||||||
referenced there exist, generate the committed release lockfile without
|
|
||||||
touching the development package files:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
scripts/generate-release-lock.sh
|
|
||||||
cd webui
|
|
||||||
PATH=/home/zemion/.nvm/versions/node/v22.22.3/bin:$PATH /home/zemion/.nvm/versions/node/v22.22.3/bin/npm run build
|
|
||||||
```
|
|
||||||
|
|
||||||
The module repositories include root-level npm package manifests so git
|
|
||||||
installs can resolve `@govoplan/access-webui`, `@govoplan/admin-webui`,
|
|
||||||
`@govoplan/files-webui`, `@govoplan/mail-webui`,
|
|
||||||
`@govoplan/campaign-webui`, and `@govoplan/calendar-webui` from repository
|
|
||||||
roots even though their source lives below `webui/src`.
|
|
||||||
|
|
||||||
### Release Lockfile Strategy
|
|
||||||
|
|
||||||
The supported release composition currently is the full GovOPlaN product: core
|
|
||||||
plus access, admin, tenancy, policy, audit, files, mail, campaign, and
|
|
||||||
calendar. Keep one committed full-product release lockfile at
|
|
||||||
`webui/package-lock.release.json`, generated from
|
|
||||||
`webui/package.release.json` in a clean release workspace. Development
|
|
||||||
`package-lock.json` may continue to point at local `file:` dependencies.
|
|
||||||
|
|
||||||
Frontend module permutations are regression-tested through
|
|
||||||
`GOVOPLAN_WEBUI_MODULE_PACKAGES` and temporary build output, not through
|
|
||||||
committed lockfiles for every possible combination. If a smaller composition
|
|
||||||
becomes a separately shipped product, add an explicit release manifest and
|
|
||||||
lockfile pair for that product, for example
|
|
||||||
`package.release.files-mail.json` and `package-lock.release.files-mail.json`,
|
|
||||||
generated in a clean release workspace from tagged git dependencies.
|
|
||||||
|
|
||||||
## Release Tag Script
|
|
||||||
|
|
||||||
The normal release path is automated by `scripts/push-release-tag.sh`: it bumps
|
|
||||||
or accepts the target version, updates Python/WebUI/module manifest versions,
|
|
||||||
commits/tags/pushes the module repositories first, regenerates
|
|
||||||
`webui/package-lock.release.json`, and then commits/tags/pushes core. If the
|
|
||||||
working tree has already been bumped, pass the current version explicitly:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
scripts/push-release-tag.sh --version 0.1.6
|
|
||||||
```
|
|
||||||
|
|
||||||
The script also includes GovOPlaN roadmap/scaffold module repositories that do
|
|
||||||
not yet have package metadata. Those repositories are committed, tagged, and
|
|
||||||
pushed with the same release tag, but they are tag-only until they contain
|
|
||||||
`pyproject.toml`, module manifests, or WebUI packages. Tag-only repositories
|
|
||||||
are not listed in `requirements-release.txt` or `webui/package.release.json`.
|
|
||||||
|
|
||||||
Current tag-only module repositories:
|
|
||||||
|
|
||||||
- `govoplan-addresses`
|
|
||||||
- `govoplan-appointments`
|
|
||||||
- `govoplan-cases`
|
|
||||||
- `govoplan-connectors`
|
|
||||||
- `govoplan-dms`
|
|
||||||
- `govoplan-erp`
|
|
||||||
- `govoplan-fit-connect`
|
|
||||||
- `govoplan-forms`
|
|
||||||
- `govoplan-identity-trust`
|
|
||||||
- `govoplan-idm`
|
|
||||||
- `govoplan-ledger`
|
|
||||||
- `govoplan-notifications`
|
|
||||||
- `govoplan-ops`
|
|
||||||
- `govoplan-payments`
|
|
||||||
- `govoplan-portal`
|
|
||||||
- `govoplan-reporting`
|
|
||||||
- `govoplan-scheduling`
|
|
||||||
- `govoplan-search`
|
|
||||||
- `govoplan-tasks`
|
|
||||||
- `govoplan-templates`
|
|
||||||
- `govoplan-workflow`
|
|
||||||
- `govoplan-xoev`
|
|
||||||
- `govoplan-xrechnung`
|
|
||||||
- `govoplan-xta-osci`
|
|
||||||
|
|
||||||
## Catalog Trust And Licensing
|
|
||||||
|
|
||||||
GovOPlaN module install and uninstall must remain operator-controlled. The
|
|
||||||
running server may plan and validate package changes, but package mutation is
|
|
||||||
performed by the separate installer daemon or an operator shell during
|
|
||||||
maintenance mode.
|
|
||||||
|
|
||||||
`govoplan-web` is the public static distribution surface for official catalog
|
|
||||||
resources:
|
|
||||||
|
|
||||||
- signed module package catalogs, grouped by release channel
|
|
||||||
- public catalog keyrings
|
|
||||||
- public license verification keyrings
|
|
||||||
- examples and operator-facing download paths
|
|
||||||
|
|
||||||
`govoplan-core` is the verifier and orchestrator:
|
|
||||||
|
|
||||||
- fetches a local or remote module catalog
|
|
||||||
- verifies catalog signatures against configured trusted keys
|
|
||||||
- enforces approved release channels
|
|
||||||
- rejects expired or not-yet-valid catalogs
|
|
||||||
- records accepted catalog sequence numbers for replay protection
|
|
||||||
- checks catalog entry license feature requirements before planning installs
|
|
||||||
- writes installer plans and request records
|
|
||||||
|
|
||||||
Feature and platform modules own their package artifacts, manifests, migration
|
|
||||||
metadata, retirement providers, and optional lifecycle behavior.
|
|
||||||
|
|
||||||
Core accepts either a local catalog file or a remote URL:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG=/srv/govoplan/catalogs/stable.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_URL=https://govoplan.example/catalogs/v1/channels/stable.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_CACHE=/srv/govoplan/runtime/catalog-cache/stable.json
|
|
||||||
```
|
|
||||||
|
|
||||||
If both file and URL are set, the URL wins. The cache is used when a remote
|
|
||||||
fetch fails, so an operator can still inspect the last known catalog. A cached
|
|
||||||
catalog must still pass signature, freshness, channel, and replay validation.
|
|
||||||
|
|
||||||
An official catalog is a JSON object with:
|
|
||||||
|
|
||||||
- `catalog_version`
|
|
||||||
- `channel`
|
|
||||||
- `sequence`
|
|
||||||
- `generated_at`
|
|
||||||
- `not_before` when delayed activation is needed
|
|
||||||
- `expires_at`
|
|
||||||
- `modules`
|
|
||||||
- `signatures`
|
|
||||||
|
|
||||||
Each module entry can declare:
|
|
||||||
|
|
||||||
- backend package name and pinned install reference
|
|
||||||
- WebUI package name and pinned install reference
|
|
||||||
- display metadata and tags
|
|
||||||
- `license_features`, the feature entitlements required to plan that install
|
|
||||||
|
|
||||||
The signature is Ed25519 over canonical JSON with both `signature` and
|
|
||||||
`signatures` removed. Core accepts the legacy single `signature` field and the
|
|
||||||
new `signatures` array.
|
|
||||||
|
|
||||||
Trusted catalog keys are configured locally:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_FILE=/srv/govoplan/trust/catalog-keyring.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS='{"release-key-1":"<base64 public key>"}'
|
|
||||||
```
|
|
||||||
|
|
||||||
For development or tightly controlled deployments, a keyring can be read from a
|
|
||||||
URL and cached:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_URL=https://govoplan.example/catalogs/v1/keyring.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_CACHE=/srv/govoplan/runtime/catalog-cache/keyring.json
|
|
||||||
```
|
|
||||||
|
|
||||||
Production installations should pin the trusted keyring locally or ship it
|
|
||||||
through deployment configuration. Fetching trusted keys from the same public
|
|
||||||
origin as the catalog is convenient, but that origin must not become the only
|
|
||||||
trust root.
|
|
||||||
|
|
||||||
## Dependency Audits
|
|
||||||
|
|
||||||
Dependency vulnerability checks are documented in
|
|
||||||
[`DEPENDENCY_AUDITS.md`](DEPENDENCY_AUDITS.md). The local audit runner is:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
bash scripts/check-dependency-audits.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
The Gitea workflow in `.gitea/workflows/dependency-audit.yml` runs the same
|
|
||||||
check against release dependency refs on pushes, pull requests, and a weekly
|
|
||||||
schedule.
|
|
||||||
|
|
||||||
Keyring entries support:
|
|
||||||
|
|
||||||
- `key_id`
|
|
||||||
- `public_key` or `public_key_base64`
|
|
||||||
- `status`: `active`, `next`, `retired`, `revoked`, or `disabled`
|
|
||||||
- `not_before`
|
|
||||||
- `not_after`
|
|
||||||
|
|
||||||
Rotation process:
|
|
||||||
|
|
||||||
1. Add the next public key to the local trusted keyring with status `next`.
|
|
||||||
2. Publish catalogs signed by both current and next keys.
|
|
||||||
3. Upgrade installations so the next key is locally trusted.
|
|
||||||
4. Promote the next key to `active`.
|
|
||||||
5. Retire the old key only after every supported installation trusts the new
|
|
||||||
key.
|
|
||||||
6. Mark a compromised key `revoked` and publish a higher sequence catalog
|
|
||||||
signed by an uncompromised key.
|
|
||||||
|
|
||||||
Use replay state in production:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_SEQUENCE_STATE=/srv/govoplan/runtime/catalog-sequences.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_ENFORCE_SEQUENCE=true
|
|
||||||
```
|
|
||||||
|
|
||||||
Core records the accepted sequence per channel after a catalog entry is planned
|
|
||||||
from the admin interface. With strict sequence enforcement, a previously
|
|
||||||
accepted sequence is rejected; without strict enforcement, only older sequences
|
|
||||||
are rejected. Catalogs should always expire.
|
|
||||||
|
|
||||||
The sequence state file is operational state, not a trust root. Keep it on
|
|
||||||
persistent storage and include it in normal backups:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"channels": {
|
|
||||||
"stable": {
|
|
||||||
"last_sequence": 42,
|
|
||||||
"accepted_at": "2026-07-07T12:00:00Z",
|
|
||||||
"key_id": "release-key-1",
|
|
||||||
"source": "https://govoplan.example/catalogs/v1/channels/stable.json"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
If the file is lost, restore it from backup. If no backup exists, reconstruct
|
|
||||||
each channel from the highest sequence already accepted in installer run
|
|
||||||
records, release records, or the currently deployed module package set. Do not
|
|
||||||
lower `last_sequence` to make an older catalog pass; publish a new higher
|
|
||||||
sequence catalog when the accepted point is uncertain.
|
|
||||||
|
|
||||||
If the file is corrupted, copy it aside for incident review, validate the
|
|
||||||
current signed catalog with channel and freshness enforcement, then rewrite the
|
|
||||||
state with the known accepted sequence. Keep
|
|
||||||
`GOVOPLAN_MODULE_PACKAGE_CATALOG_REQUIRE_SIGNATURE=true` and approved-channel
|
|
||||||
checks enabled during recovery. Temporarily disabling
|
|
||||||
`GOVOPLAN_MODULE_PACKAGE_CATALOG_ENFORCE_SEQUENCE` allows revalidating the same
|
|
||||||
sequence, but older sequences remain rejected once the reconstructed
|
|
||||||
`last_sequence` is in place.
|
|
||||||
|
|
||||||
Approved channels are deployment policy:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_APPROVED_CHANNELS=stable,lts
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_REQUIRE_SIGNATURE=true
|
|
||||||
```
|
|
||||||
|
|
||||||
The admin UI can display other catalog metadata, but core rejects catalogs from
|
|
||||||
unapproved channels when validation is configured.
|
|
||||||
|
|
||||||
Catalog entries can require license features:
|
|
||||||
|
|
||||||
```json
|
|
||||||
"license_features": ["module.mail", "support.standard"]
|
|
||||||
```
|
|
||||||
|
|
||||||
Core checks those requirements against an offline license file before allowing
|
|
||||||
the entry into the install plan.
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GOVOPLAN_LICENSE_FILE=/srv/govoplan/license.json
|
|
||||||
GOVOPLAN_LICENSE_ENFORCEMENT=true
|
|
||||||
GOVOPLAN_LICENSE_TRUSTED_KEYS_FILE=/srv/govoplan/trust/license-keyring.json
|
|
||||||
```
|
|
||||||
|
|
||||||
License files are JSON objects with:
|
|
||||||
|
|
||||||
- `license_id`
|
|
||||||
- `subject`
|
|
||||||
- `features`
|
|
||||||
- `valid_from`
|
|
||||||
- `valid_until`
|
|
||||||
- `signature`
|
|
||||||
|
|
||||||
Issue or renew a license from an operator/release shell that has the Ed25519
|
|
||||||
private key:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
govoplan-module-installer \
|
|
||||||
--issue-license /srv/govoplan/license.json \
|
|
||||||
--license-id customer-2026-07 \
|
|
||||||
--license-subject "Example Municipality" \
|
|
||||||
--license-feature module.mail \
|
|
||||||
--license-feature support.standard \
|
|
||||||
--license-valid-until 2027-07-31T23:59:59Z \
|
|
||||||
--license-signing-key-id license-issuer-1 \
|
|
||||||
--license-signing-private-key /srv/govoplan/secrets/license-issuer-1.pem \
|
|
||||||
--format json
|
|
||||||
```
|
|
||||||
|
|
||||||
Validate an imported license without exposing secrets:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
govoplan-module-installer \
|
|
||||||
--validate-license /srv/govoplan/license.json \
|
|
||||||
--license-trusted-key license-issuer-1="<base64 public key>" \
|
|
||||||
--require-trusted-license \
|
|
||||||
--license-required-feature module.mail \
|
|
||||||
--format json
|
|
||||||
```
|
|
||||||
|
|
||||||
The CLI and admin module catalog panel report the license id, subject,
|
|
||||||
validity window, signing key id, signed/trusted state, available features, and
|
|
||||||
missing entitlements for the configured package catalog. They do not expose
|
|
||||||
private signing material.
|
|
||||||
|
|
||||||
License enforcement can run in observe-only mode by leaving
|
|
||||||
`GOVOPLAN_LICENSE_ENFORCEMENT` unset. In that mode, missing or invalid license
|
|
||||||
data is surfaced as a warning but does not block planning.
|
|
||||||
|
|
||||||
Renewal is an ordinary re-issuance with a new `license_id`, extended
|
|
||||||
`valid_until`, and the full intended feature set. Import the renewed JSON to
|
|
||||||
`GOVOPLAN_LICENSE_FILE`, keep the previous file for audit, and validate it
|
|
||||||
before setting enforcement.
|
|
||||||
|
|
||||||
Revocation is handled through the trusted license keyring. Mark a compromised
|
|
||||||
or invalid issuer key as `revoked` or `disabled`, publish or deploy the updated
|
|
||||||
keyring, then reissue affected licenses with an active key. Installations that
|
|
||||||
run with `GOVOPLAN_LICENSE_ENFORCEMENT=true` reject licenses signed only by a
|
|
||||||
revoked key after the local keyring is updated.
|
|
||||||
|
|
||||||
Emergency fallback is deliberately explicit. Operators can temporarily unset
|
|
||||||
`GOVOPLAN_LICENSE_ENFORCEMENT` to keep package planning observable while a
|
|
||||||
license or keyring is recovered. Record the change in the operational incident
|
|
||||||
log, keep catalog signature and channel enforcement enabled, and restore
|
|
||||||
license enforcement after a trusted renewal validates successfully.
|
|
||||||
|
|
||||||
Licensing is intentionally separate from open-source code licensing. The
|
|
||||||
catalog/license mechanism can govern support channels, official release
|
|
||||||
eligibility, hosted update access, professional support, or commercial
|
|
||||||
entitlements without changing the source license of the repositories.
|
|
||||||
|
|
||||||
Production-grade distribution still needs remote registry/git artifact
|
|
||||||
resolution before package-manager apply, a hardened catalog publishing pipeline
|
|
||||||
in `govoplan-web`, and automated key rotation and emergency revocation drills.
|
|
||||||
|
|
||||||
## Release Catalog Publishing
|
|
||||||
|
|
||||||
GovOPlaN release catalogs are published by `govoplan-web` as static JSON and
|
|
||||||
verified by `govoplan-core` before installer plans are accepted. Private signing
|
|
||||||
keys must stay outside all git repositories. Public keyrings are published with
|
|
||||||
the website.
|
|
||||||
|
|
||||||
Create the first catalog signing key on the release machine:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
KEY_DIR="$HOME/.config/govoplan/release-keys"
|
|
||||||
mkdir -p "$KEY_DIR"
|
|
||||||
./.venv/bin/python scripts/generate-catalog-keypair.py \
|
|
||||||
--key-id release-key-1 \
|
|
||||||
--private-key "$KEY_DIR/release-key-1.pem" \
|
|
||||||
--public-key "$KEY_DIR/release-key-1.pub" \
|
|
||||||
--keyring "$KEY_DIR/catalog-keyring.json"
|
|
||||||
```
|
|
||||||
|
|
||||||
Keep `release-key-1.pem` private. The generated keyring contains only public
|
|
||||||
material.
|
|
||||||
|
|
||||||
Generate the signed catalog into `govoplan-web`:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
KEY_DIR="$HOME/.config/govoplan/release-keys"
|
|
||||||
scripts/publish-release-catalog.sh \
|
|
||||||
--version <x.y.z> \
|
|
||||||
--sequence 202607071340 \
|
|
||||||
--catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem" \
|
|
||||||
--build-web
|
|
||||||
```
|
|
||||||
|
|
||||||
This writes:
|
|
||||||
|
|
||||||
- `/mnt/DATA/git/govoplan-web/public/catalogs/v1/channels/stable.json`
|
|
||||||
- `/mnt/DATA/git/govoplan-web/public/catalogs/v1/keyring.json`
|
|
||||||
|
|
||||||
The wrapper validates the catalog with core using the generated public keyring.
|
|
||||||
|
|
||||||
For normal module/core releases, first audit and record migration baselines,
|
|
||||||
then tag and push the module/core repos. Finally publish the website catalog:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
./.venv/bin/python scripts/release-migration-audit.py --strict
|
|
||||||
```
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
KEY_DIR="$HOME/.config/govoplan/release-keys"
|
|
||||||
scripts/publish-release-catalog.sh \
|
|
||||||
--version <x.y.z> \
|
|
||||||
--catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem" \
|
|
||||||
--build-web \
|
|
||||||
--commit \
|
|
||||||
--tag \
|
|
||||||
--push
|
|
||||||
```
|
|
||||||
|
|
||||||
The website tag is `catalog-v<x.y.z>`. The public URL is:
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://govoplan.add-ideas.de/catalogs/v1/channels/stable.json
|
|
||||||
```
|
|
||||||
|
|
||||||
The public keyring URL is:
|
|
||||||
|
|
||||||
```text
|
|
||||||
https://govoplan.add-ideas.de/catalogs/v1/keyring.json
|
|
||||||
```
|
|
||||||
|
|
||||||
`scripts/push-release-tag.sh` can publish the web catalog after module and core
|
|
||||||
tags have been pushed. It runs the migration release audit in automatic mode:
|
|
||||||
warning-only before the first recorded migration baseline, strict after a
|
|
||||||
baseline exists. Add `--strict-migration-audit` when you want to force strict
|
|
||||||
mode explicitly:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
KEY_DIR="$HOME/.config/govoplan/release-keys"
|
|
||||||
scripts/push-release-tag.sh \
|
|
||||||
--bump subversion \
|
|
||||||
--strict-migration-audit \
|
|
||||||
--publish-web-catalog \
|
|
||||||
--catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem" \
|
|
||||||
--build-web-catalog
|
|
||||||
```
|
|
||||||
|
|
||||||
Use `--catalog-signing-key` more than once during a key rotation window. The
|
|
||||||
catalog will contain multiple signatures and the public keyring will include the
|
|
||||||
corresponding public keys.
|
|
||||||
|
|
||||||
On a GovOPlaN installation that should consume the official stable catalog:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_URL=https://govoplan.add-ideas.de/catalogs/v1/channels/stable.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_CACHE=/srv/govoplan/runtime/catalog-cache/stable.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_REQUIRE_SIGNATURE=true
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_APPROVED_CHANNELS=stable
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_FILE=/srv/govoplan/trust/catalog-keyring.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_SEQUENCE_STATE=/srv/govoplan/runtime/catalog-sequences.json
|
|
||||||
GOVOPLAN_MODULE_PACKAGE_CATALOG_ENFORCE_SEQUENCE=true
|
|
||||||
```
|
|
||||||
|
|
||||||
For production, copy the public keyring into deployment configuration and pin it
|
|
||||||
locally. Do not rely on a URL-fetched keyring as the only trust root.
|
|
||||||
|
|
||||||
`stable.json` includes a top-level `core_release` section for operator/update
|
|
||||||
tooling. Core is intentionally not listed as a normal module entry because it
|
|
||||||
must not be added to saved enabled-module state. Core upgrades should remain an
|
|
||||||
operator-supervised package update with restart and health checks.
|
|
||||||
|
|
||||||
Key rotation for published catalogs:
|
|
||||||
|
|
||||||
1. Generate the next private key outside git.
|
|
||||||
2. Run `publish-release-catalog.sh` with both signing keys.
|
|
||||||
3. Publish the web catalog/keyring.
|
|
||||||
4. Roll the new public keyring into installations.
|
|
||||||
5. Stop signing with the old key after the supported fleet trusts the new key.
|
|
||||||
6. Mark compromised keys as revoked in the public keyring and publish a higher
|
|
||||||
sequence catalog signed by a trusted uncompromised key.
|
|
||||||
|
|
||||||
## PostgreSQL Release Check
|
|
||||||
|
|
||||||
Release candidates should pass a disposable PostgreSQL migration and startup
|
|
||||||
smoke check before tagging or publishing catalogs. Start the local testbed,
|
|
||||||
then run the permutation check from the core checkout:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core/dev/postgres
|
|
||||||
cp .env.example .env
|
|
||||||
docker compose --env-file .env up -d
|
|
||||||
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
set -a
|
|
||||||
. dev/postgres/.env
|
|
||||||
set +a
|
|
||||||
./.venv/bin/python scripts/postgres-integration-check.py \
|
|
||||||
--database-url "$GOVOPLAN_POSTGRES_DATABASE_URL" \
|
|
||||||
--reset-schema
|
|
||||||
```
|
|
||||||
|
|
||||||
The script checks migrations and `/health` startup for core-only, files-only,
|
|
||||||
mail-only, campaign-only, campaign+files, campaign+mail, and full-product
|
|
||||||
module sets. `--reset-schema` is destructive and must only be used against a
|
|
||||||
throwaway database.
|
|
||||||
|
|
||||||
## Migration Baselines
|
|
||||||
|
|
||||||
Development migrations may be small and numerous while a feature is moving.
|
|
||||||
Before a stable release, unreleased migrations may be rewritten or squashed into
|
|
||||||
a release-level baseline or release-to-release upgrade migration. After a
|
|
||||||
release tag has shipped, released migration revision IDs are immutable.
|
|
||||||
|
|
||||||
The release policy is:
|
|
||||||
|
|
||||||
- unreleased migrations may be folded before release;
|
|
||||||
- released migrations are never rewritten or deleted;
|
|
||||||
- each stable release records the public migration head revisions in
|
|
||||||
`docs/migration-release-baselines.json`;
|
|
||||||
- fresh installations should apply release-level baselines/upgrades, not
|
|
||||||
unreleased create-then-rename churn;
|
|
||||||
- release-to-release schema changes should be folded into one reviewed
|
|
||||||
migration per migration owner where practical.
|
|
||||||
|
|
||||||
Audit the current graph during release preparation:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
./.venv/bin/python scripts/release-migration-audit.py
|
|
||||||
```
|
|
||||||
|
|
||||||
Generate the reviewed/manual squash checklist:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./.venv/bin/python scripts/release-migration-audit.py --squash-plan
|
|
||||||
```
|
|
||||||
|
|
||||||
After the release migrations have been reviewed and the graph is final, record
|
|
||||||
the release baseline:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./.venv/bin/python scripts/release-migration-audit.py --record-release <x.y.z>
|
|
||||||
```
|
|
||||||
|
|
||||||
Use strict mode to verify that the current heads are recorded:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
./.venv/bin/python scripts/release-migration-audit.py --strict
|
|
||||||
```
|
|
||||||
|
|
||||||
`scripts/push-release-tag.sh` runs the audit by default in automatic mode:
|
|
||||||
non-strict while no release baseline exists, strict after the first baseline is
|
|
||||||
recorded. Pass `--warn-migration-audit` for an explicit non-strict audit,
|
|
||||||
`--strict-migration-audit` to force strict mode, or `--skip-migration-audit`
|
|
||||||
only for emergency/manual release work.
|
|
||||||
|
|
||||||
Before the first stable release, fold the current development chain into the
|
|
||||||
first public baseline and record that baseline in
|
|
||||||
`docs/migration-release-baselines.json`. The tracking issue is
|
|
||||||
`add-ideas/govoplan-core#223`.
|
|
||||||
|
|
||||||
## Related Operator Documents
|
|
||||||
|
|
||||||
- `DEPLOYMENT_OPERATOR_GUIDE.md`: runtime environment, explicit migrations,
|
|
||||||
backup/restore commands, module installer daemon/supervisor operation, and
|
|
||||||
rollback drills.
|
|
||||||
- `REMOTE_WEBUI_BUNDLES.md`: experimental browser-loaded module bundles for
|
|
||||||
controlled deployments; normal releases use package builds.
|
|
||||||
|
|
||||||
## Release Checklist
|
|
||||||
|
|
||||||
- Keep Python package versions, WebUI package versions, and git tags aligned.
|
|
||||||
- Tag core, access, admin, tenancy, policy, audit, files, mail, campaign,
|
|
||||||
calendar, and scaffold module repositories together.
|
|
||||||
- Update `requirements-release.txt` and `webui/package.release.json` when the
|
|
||||||
release tag changes.
|
|
||||||
- Generate the committed full-product release lockfile from
|
|
||||||
`package.release.json` with `scripts/generate-release-lock.sh`.
|
|
||||||
- Run `scripts/release-migration-audit.py --strict` after recording a release
|
|
||||||
baseline.
|
|
||||||
- Run the PostgreSQL release check against a disposable database.
|
|
||||||
- Publish the signed catalog through the release catalog publishing flow above.
|
|
||||||
- Add separate release manifest/lockfile pairs only for module compositions
|
|
||||||
that are shipped as their own products.
|
|
||||||
- Do not commit local sibling paths into release manifests.
|
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<!-- codex-wiki-sync:fac6bcabf19aa97dc0535f40 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/SEARCH_EVENT_INDEXING_CONTRACT.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Search event indexing contract
|
||||||
|
|
||||||
|
Core defines, but does not implement, the optional Search indexing boundary.
|
||||||
|
Feature modules register `SearchSourceProvider` implementations for bounded
|
||||||
|
backfills and live authorization checks. A provider may additionally implement
|
||||||
|
`SearchEventSourceProvider` to translate a committed `PlatformEvent` into one
|
||||||
|
or more authoritative `SearchIndexChange` values.
|
||||||
|
|
||||||
|
When the Search index-writer capability is active, the platform event worker
|
||||||
|
uses the durable consumer identity `search.indexing.v1`. It accepts only public
|
||||||
|
and internal events, passes the outbox delivery key to each event-capable
|
||||||
|
source, and then advances a bounded batch of queued index changes in the same
|
||||||
|
worker transaction. Stable change IDs make delivery replay idempotent.
|
||||||
|
|
||||||
|
The boundary has three non-negotiable rules:
|
||||||
|
|
||||||
|
- a source may emit changes only for its registered module, provider, resource
|
||||||
|
type, and event tenant;
|
||||||
|
- Search validates every upsert document before queueing it and rejects secret
|
||||||
|
metadata keys;
|
||||||
|
- an index ACL is only a candidate filter. Resources marked for authorization
|
||||||
|
recheck are returned only after the owning source explicitly allows the
|
||||||
|
current principal at query time.
|
||||||
|
|
||||||
|
Search and its worker remain optional. Core-only startup and feature-module
|
||||||
|
operation do not require the Search package.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:b4ad4ff05b882582ca6bdd3d -->
|
<!-- codex-wiki-sync:87320eb0e82f9897b4fd8744 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/STATE_AND_RECOVERY_CONTRACT.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/STATE_AND_RECOVERY_CONTRACT.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -35,6 +35,11 @@ module artifacts. It provides bounded read/write/list/stat/delete operations
|
|||||||
for local and S3-compatible storage. Modules own their object-key namespace and
|
for local and S3-compatible storage. Modules own their object-key namespace and
|
||||||
business metadata; Core does not interpret module files.
|
business metadata; Core does not interpret module files.
|
||||||
|
|
||||||
|
`stat` and `list_objects` return object size plus a UTC `modified_at` value when
|
||||||
|
the backend can prove it. Reconciliation and retention code may use that value
|
||||||
|
for conservative grace periods, but must treat a missing timestamp as
|
||||||
|
ineligible for automatic deletion rather than guessing an age.
|
||||||
|
|
||||||
Rules for modules:
|
Rules for modules:
|
||||||
|
|
||||||
- Store only opaque object keys in business records, never local absolute
|
- Store only opaque object keys in business records, never local absolute
|
||||||
@@ -59,6 +64,13 @@ software version, module-composition hash, queues, start time, and heartbeat.
|
|||||||
The registration identity includes a process incarnation so a stale process
|
The registration identity includes a process incarnation so a stale process
|
||||||
cannot update a replacement's row.
|
cannot update a replacement's row.
|
||||||
|
|
||||||
|
Worker metadata also records the orchestrator pool and declared concurrency.
|
||||||
|
Every Celery prefork child disposes the SQLAlchemy pool inherited from its
|
||||||
|
parent and creates a process-local pool before handling work. Deployment
|
||||||
|
rendering must therefore budget one database pool for the worker parent and
|
||||||
|
each child. Ops compares active queue ownership, software versions, and the
|
||||||
|
order-independent module-composition hash with the graph loaded by the API.
|
||||||
|
|
||||||
Drain is durable operator intent:
|
Drain is durable operator intent:
|
||||||
|
|
||||||
- an API enters not-ready state after observing drain;
|
- an API enters not-ready state after observing drain;
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
<!-- codex-wiki-sync:f469c87e57956d859f9bf088 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/TABULAR_SOURCE_CONTRACT.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Tabular Source Preview Contract
|
||||||
|
|
||||||
|
Core defines provider-neutral DTOs for optional tabular source providers. A
|
||||||
|
source declares whether it is live, cached, file-backed, or static; its schema
|
||||||
|
and immutable fingerprint; structured health; and the exact projection,
|
||||||
|
pagination, filter, aggregation, and sorting operations that the provider can
|
||||||
|
push down. Consumers must not infer pushdown support from a provider name.
|
||||||
|
|
||||||
|
Every preview request carries independent row, byte, and elapsed-time budgets.
|
||||||
|
A provider may tighten these values but must return its effective limits,
|
||||||
|
returned byte count, elapsed milliseconds, truncation state, and structured
|
||||||
|
diagnostics. Equivalent fields on the Datasources read request and result
|
||||||
|
preserve that evidence when a live source is consumed through the catalogue.
|
||||||
|
A row that cannot fit within the byte budget fails explicitly rather than
|
||||||
|
leaking a partial value. Timeout, stale fingerprint, unavailable source, and
|
||||||
|
authorization failures remain distinct provider-neutral errors.
|
||||||
|
|
||||||
|
Connector health and preview diagnostics must contain no credentials, endpoint
|
||||||
|
userinfo, row values, or unbounded remote error bodies. A Datasource origin
|
||||||
|
preserves this contract so registration and staging do not erase source mode,
|
||||||
|
health, pushdown, or preview-limit evidence.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<!-- codex-wiki-sync:3d790d5eb8b0c6a63bc1e4bb -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/TEMPLATE_CAPABILITY_CONTRACT.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Template And Generated Artifact Capability Contracts
|
||||||
|
|
||||||
|
Core defines provider-neutral contracts for optional template libraries and
|
||||||
|
generated artifact storage. Core does not render templates or store generated
|
||||||
|
files itself.
|
||||||
|
|
||||||
|
## Templates
|
||||||
|
|
||||||
|
- `templates.catalog` lists typed, versioned template references and checks a
|
||||||
|
consumer's available fields, usage, and output format.
|
||||||
|
- `templates.renderer` accepts a `TemplateRenderRequest` containing pinned
|
||||||
|
input data and returns immutable render evidence plus an artifact reference.
|
||||||
|
|
||||||
|
The DTOs contain identifiers, hashes, plain mappings, and scalar metadata. They
|
||||||
|
do not expose Template ORM models or require Campaign, Distribution Lists,
|
||||||
|
Addresses, Reporting, Forms, or Mail.
|
||||||
|
|
||||||
|
## Generated Artifacts
|
||||||
|
|
||||||
|
`files.artifact_store` accepts a `ManagedArtifactWriteRequest` and returns a
|
||||||
|
`ManagedArtifactRef`. Producers supply bytes, a safe filename/content type,
|
||||||
|
idempotency key, and non-secret provenance. Files owns path normalization,
|
||||||
|
authorization, versions, storage, and download behavior.
|
||||||
|
|
||||||
|
Consumers must discover both contracts through the module registry and degrade
|
||||||
|
only the unavailable path. A template renderer may return a bounded download
|
||||||
|
when Files is absent. A caller must not infer successful external delivery from
|
||||||
|
successful rendering or artifact persistence.
|
||||||
@@ -0,0 +1,75 @@
|
|||||||
|
<!-- codex-wiki-sync:534915685bbd5e48278250b5 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/TEMPORAL_DATA_CONTEXT.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# Temporal Data Context
|
||||||
|
|
||||||
|
GovOPlaN exposes one read context for data validity and system knowledge. The
|
||||||
|
calendar control in the authenticated titlebar applies that context to
|
||||||
|
supported list and detail reads for the current account and tenant.
|
||||||
|
|
||||||
|
## Two Independent Axes
|
||||||
|
|
||||||
|
- **Valid time** answers when a fact applied in the represented domain.
|
||||||
|
- **Recorded time** answers what the system had recorded by a particular
|
||||||
|
instant.
|
||||||
|
|
||||||
|
The default is data valid now under the latest recorded state. `At time`
|
||||||
|
selects a valid-time instant. `All` removes the valid-time interval filter but
|
||||||
|
still uses the selected recorded state. The optional recorded-state cutoff can
|
||||||
|
be combined with any valid-time mode, which keeps correction history distinct
|
||||||
|
from changes in real-world validity.
|
||||||
|
|
||||||
|
An interval is half open: `valid_from <= instant < valid_to`. A revision belongs
|
||||||
|
to a recorded-state snapshot when `recorded_at <= cutoff` and it was not
|
||||||
|
superseded at or before that cutoff.
|
||||||
|
|
||||||
|
## Security And Mutation Rules
|
||||||
|
|
||||||
|
The temporal data context is a read projection, not an authorization context.
|
||||||
|
Authentication, permissions, active delegations, tenant boundaries, module
|
||||||
|
policy, and maintenance controls are always evaluated under current security
|
||||||
|
state. A historical projection never restores an expired permission.
|
||||||
|
|
||||||
|
The context also does not supply mutation dates. Writes continue to target the
|
||||||
|
current lifecycle revision and must carry their explicit valid/effective dates,
|
||||||
|
expected revision, reason, and evidence where the owning contract requires
|
||||||
|
them. A screen showing historical data must not silently turn a normal edit
|
||||||
|
into a historical correction.
|
||||||
|
|
||||||
|
## HTTP Contract
|
||||||
|
|
||||||
|
Core accepts these request headers:
|
||||||
|
|
||||||
|
| Header | Meaning |
|
||||||
|
| --- | --- |
|
||||||
|
| `X-Govoplan-Validity-Mode` | `current`, `at`, or `all` |
|
||||||
|
| `X-Govoplan-Valid-At` | Timezone-aware ISO 8601 instant required by `at` |
|
||||||
|
| `X-Govoplan-Recorded-At` | Optional timezone-aware system-knowledge cutoff |
|
||||||
|
|
||||||
|
Invalid or naive timestamps fail with HTTP 400. Responses expose the resolved
|
||||||
|
mode and evaluated instant. Conditional JSON responses vary by all three
|
||||||
|
request headers, and the shared WebUI API client includes them in request
|
||||||
|
deduplication and conditional-cache keys.
|
||||||
|
|
||||||
|
## Module Adoption
|
||||||
|
|
||||||
|
Revision-owning modules apply
|
||||||
|
`govoplan_core.db.temporal.apply_temporal_revision_filter` only to read queries
|
||||||
|
that are meant to follow the platform context. Explicit version references and
|
||||||
|
explicit resolver `effective_at` arguments take precedence. Current-row
|
||||||
|
lookups used for optimistic concurrency, authorization, routing, effects, or
|
||||||
|
other mutations must remain explicit and context-independent.
|
||||||
|
|
||||||
|
The initial bitemporal adoption covers Decisions, Mandates, Parties, and
|
||||||
|
Services. Their immutable revisions have indexed valid, recorded, and
|
||||||
|
superseded timestamps. Modules with effective-dated security records or
|
||||||
|
recorded-only revision histories require separate display-query adoption so
|
||||||
|
the global selector cannot affect current authorization or execution.
|
||||||
|
|
||||||
|
The WebUI selection is stored in session storage per account and tenant. A
|
||||||
|
change remounts the active module route so existing page loaders issue a fresh
|
||||||
|
request. Returning both axes to their defaults removes the stored selection.
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<!-- codex-wiki-sync:fbf3b6d8ee7099df271bbc0e -->
|
<!-- codex-wiki-sync:029a1fbb80ae23e7e586b321 -->
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/UI_UX_DECISION_LEDGER.md`.
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/UI_UX_DECISION_LEDGER.md`.
|
||||||
> Origin: `repository`.
|
> Origin: `repository`.
|
||||||
@@ -57,6 +57,13 @@ contestability, responsibility, and traceability at the point of action.
|
|||||||
| UX-024 | Explicit `Discard` actions and dirty in-application navigation use the shared `UnsavedChangesProvider` dialog. A page registers save/discard behavior with `useUnsavedDraftGuard`; its Discard button calls `requestDiscard`, and route changes use `useGuardedNavigate` or `requestNavigation`. | Accepted | All create/edit surfaces |
|
| UX-024 | Explicit `Discard` actions and dirty in-application navigation use the shared `UnsavedChangesProvider` dialog. A page registers save/discard behavior with `useUnsavedDraftGuard`; its Discard button calls `requestDiscard`, and route changes use `useGuardedNavigate` or `requestNavigation`. | Accepted | All create/edit surfaces |
|
||||||
| UX-025 | `window.alert` and the global `alert` function are prohibited. A narrowly necessary exception requires product-owner authorization and an entry in the alert exception register before implementation. | Accepted | All WebUI code |
|
| UX-025 | `window.alert` and the global `alert` function are prohibited. A narrowly necessary exception requires product-owner authorization and an entry in the alert exception register before implementation. | Accepted | All WebUI code |
|
||||||
| UX-026 | A table defines one stable ordered action set. A row-level unavailable action remains in its normal position and is disabled, preferably with `disabledReason`; structurally irrelevant actions are omitted for the entire table. Empty rows reserve the same slots so their Add action stays in the normal left-most action position. | Accepted | All structured tables |
|
| UX-026 | A table defines one stable ordered action set. A row-level unavailable action remains in its normal position and is disabled, preferably with `disabledReason`; structurally irrelevant actions are omitted for the entire table. Empty rows reserve the same slots so their Add action stays in the normal left-most action position. | Accepted | All structured tables |
|
||||||
|
| UX-027 | The platform icon rail keeps its brand header and utility footer visible. Only the module-navigation region scrolls when installed and permitted modules exceed the available viewport height. | Accepted | Core WebUI shell |
|
||||||
|
| UX-028 | Maintenance and offline states use their established textual warning banners centered in the titlebar. They must not recolor the shell or add decorative status icons. Global search is a right-side command, so warnings do not replace its trigger or overlay. | Accepted | Core WebUI shell |
|
||||||
|
| UX-029 | Recoverable page and module errors use the central compact `DismissibleAlert` presentation with an explicit recovery action where one exists. Full-height workspaces must overlay page feedback instead of allowing an alert to become a stretched workspace row. | Accepted | Core and module WebUIs |
|
||||||
|
| UX-030 | At narrow widths, the titlebar uses separate context and command rows. Context selectors remain horizontally reachable, search retains its compact trigger, and language/help/notification/account commands remain fixed icon controls without overlap. Shared content padding contracts so domain workspaces retain usable width. | Accepted | Core WebUI shell and all module workspaces |
|
||||||
|
| UX-031 | Public controls and extension contributions use stable, module-namespaced interface identities. Shared controls expose `interfaceId` and `helpTopicId`; generated source anchors are inventory evidence, not a substitute for an explicit ID when documentation, policy, or automation refers to the control. | Accepted | Core and module WebUIs |
|
||||||
|
| UX-032 | `F1` resolves help from the focused field or action, then its dialog/section/page and registered route. Focused contexts retain the page fallback; Docs applies audience and permission filtering and falls back to visible module documentation. | Accepted | Core shell, Docs, and all module WebUIs |
|
||||||
|
| UX-033 | Global search is the left-most titlebar command, immediately before language selection. Its icon, `F3`, and `Ctrl`/`Cmd`+`K` all open the same permission-aware search overlay; the titlebar does not reserve a persistent query field. | Accepted | Core shell and Search WebUI |
|
||||||
|
|
||||||
## Confirmed Implementation Decisions
|
## Confirmed Implementation Decisions
|
||||||
|
|
||||||
@@ -230,6 +237,10 @@ instead of reproducing their behavior.
|
|||||||
- `help` content is contextual guidance, not the accessible name. The persisted
|
- `help` content is contextual guidance, not the accessible name. The persisted
|
||||||
`show_inline_help_hints` user preference hides only the `InlineHelp` marker by
|
`show_inline_help_hints` user preference hides only the `InlineHelp` marker by
|
||||||
applying `ui-hide-help-hints` at the document root.
|
applying `ui-hide-help-hints` at the document root.
|
||||||
|
- Shared action-bearing components accept an optional disabled reason. In
|
||||||
|
particular, `MailServerSettingsPanel` forwards protocol-specific test
|
||||||
|
blockers into the shared focusable disabled-action tooltip; modules provide
|
||||||
|
the domain-specific required field, permission, or in-progress reason.
|
||||||
- A dirty editor registers once with `useUnsavedDraftGuard`. An explicit
|
- A dirty editor registers once with `useUnsavedDraftGuard`. An explicit
|
||||||
Discard button calls `useUnsavedChanges().requestDiscard(afterResolve)`; SPA
|
Discard button calls `useUnsavedChanges().requestDiscard(afterResolve)`; SPA
|
||||||
navigation uses `useGuardedNavigate` or `requestNavigation`. Both paths show
|
navigation uses `useGuardedNavigate` or `requestNavigation`. Both paths show
|
||||||
@@ -279,7 +290,7 @@ UI documentation until a central cross-repository audit is available.
|
|||||||
|
|
||||||
| Core scope | Why `FieldLabel` is omitted | Accessible/context label source |
|
| Core scope | Why `FieldLabel` is omitted | Accessible/context label source |
|
||||||
| --- | --- | --- |
|
| --- | --- | --- |
|
||||||
| `PasswordField`, `ColorPickerField`, `DateField`, `TimeField`, and `DateTimeField` input internals | These are label-neutral composite primitives and are placed inside `FormField`/`FieldLabel` by the consuming form. Rendering another label inside the primitive would duplicate it. | Enclosing label; a direct consumer must pass an accessible name and record that direct composition here. |
|
| `PasswordField`, `ColorPickerField`, `DateField`, `TimeField`, and `DateTimeField` input internals | These are label-neutral composite primitives and are placed inside `FormField`/`FieldLabel` by the consuming form. Rendering another label inside the primitive would duplicate it. `PasswordField` may opt into the shared cryptographic generator; the candidate dialog is subordinate to the enclosing field and commits only through its explicit Use action. | Enclosing label; a direct consumer must pass an accessible name and record that direct composition here. |
|
||||||
| `ToggleSwitch` native checkbox | The shared component already renders its visible text through `FieldLabel`; the native input must not render a second label. | The enclosing native label and derived `aria-label`. |
|
| `ToggleSwitch` native checkbox | The shared component already renders its visible text through `FieldLabel`; the native input must not render a second label. | The enclosing native label and derived `aria-label`. |
|
||||||
| `FileDropZone` hidden file input | The input is an implementation detail of the labelled keyboard-operable drop target. | Drop target text and `inputLabel`/`aria-label`. |
|
| `FileDropZone` hidden file input | The input is an implementation detail of the labelled keyboard-operable drop target. | Drop target text and `inputLabel`/`aria-label`. |
|
||||||
| `AdminSelectionList` and `DataGrid` list-filter checkboxes | Each option is self-explanatory and already enclosed by its visible option label. | Enclosing native option label. |
|
| `AdminSelectionList` and `DataGrid` list-filter checkboxes | Each option is self-explanatory and already enclosed by its visible option label. | Enclosing native option label. |
|
||||||
@@ -310,14 +321,14 @@ converted or reviewed.
|
|||||||
|
|
||||||
| Surface | Repository | UX State | Next Action |
|
| Surface | Repository | UX State | Next Action |
|
||||||
| --- | --- | --- | --- |
|
| --- | --- | --- | --- |
|
||||||
| File connector settings | `govoplan-files` | First adaptive modal slice started: connections and credentials now use full-state create/edit forms with conditional fields, advanced panels, and blocker primitives. Wizard shell is retained for later assisted setup. Central policy card still needs a layered editor. | Finish provider discovery/test-in-flow, then convert policy editing. |
|
| File connector settings | `govoplan-files` | Migrated to the shared adaptive server/credential/policy pattern with provider discovery, typed controls, actionable blockers, consequence-aware removal, and module-owned verification evidence. | Continue only through bounded Files-owned follow-ups. |
|
||||||
| Mail server settings | `govoplan-mail` / `govoplan-core` | Uses the shared server/credential model visually, but create/edit still needs the same adaptive pattern as files. | Migrate to adaptive server/credential/policy dialogs, with optional assisted wizard later. |
|
| Mail server settings | `govoplan-mail` / `govoplan-core` | Migrated to the same layered profile/server/credential/policy pattern, including focused connection tests, unsaved-state handling, contextual help, and permission/target blockers. | Continue only through bounded Mail-owned follow-ups. |
|
||||||
| Connector policy/effective rows | `govoplan-core`, module UIs | Effective-policy direction exists, but many editors still expose broad option sets. | Put effective value first, move overrides into modal, and explain blocked edits. |
|
| Connector policy/effective rows | `govoplan-core`, module UIs | Effective-policy direction exists, but many editors still expose broad option sets. | Put effective value first, move overrides into modal, and explain blocked edits. |
|
||||||
| Admin module management | `govoplan-admin` | Has preflight concepts, but operational choices are still technical and dense. | Convert install/uninstall/package changes to operator wizards. |
|
| Admin module management | `govoplan-admin` | Has preflight concepts, but operational choices are still technical and dense. | Convert install/uninstall/package changes to operator wizards. |
|
||||||
| Configuration packages | `govoplan-admin` | Catalog/import work exists, but package editing can still drift toward technical fields. | Add guided import/review/problem-list flow. |
|
| Configuration packages | `govoplan-admin` | Catalog/import work exists, but package editing can still drift toward technical fields. | Add guided import/review/problem-list flow. |
|
||||||
| Retention and privacy | `govoplan-core` | Functional editor exists; consequence language and provenance can be stronger. | Layer advanced retention options and add review for broad changes. |
|
| Retention and privacy | `govoplan-core` | Typed effective-policy editor exposes source paths, narrowing semantics, platform locks, permission/target blockers, and explicit clean/loading/save states. | Broader governed-change review remains module-owned where a policy change requires approval. |
|
||||||
| API keys | `govoplan-access` / admin UI | Security-sensitive creation needs least-privilege guidance. | Add scoped creation wizard with expiry/owner review. |
|
| API keys | `govoplan-access` / admin UI | Security-sensitive creation needs least-privilege guidance. | Add scoped creation wizard with expiry/owner review. |
|
||||||
| User settings | `govoplan-core` | Preferences persistence exists; interface navigation issue was fixed earlier, but the surface still needs UX review. | Keep simple sections, remove double-click traps, and add quiet explanations. |
|
| User settings | `govoplan-core` | Simple typed sections use unsaved-change guards, quiet result feedback, contextual help, and explicit busy/clean disabled-action reasons. | Keep bounded; new contributed sections must satisfy the checklist. |
|
||||||
|
|
||||||
## Impact Index
|
## Impact Index
|
||||||
|
|
||||||
@@ -346,6 +357,11 @@ Every new or changed admin/configuration surface should answer:
|
|||||||
- Does the screen explain disabled actions and failed validation in plain
|
- Does the screen explain disabled actions and failed validation in plain
|
||||||
language?
|
language?
|
||||||
- Does it say who can fix a blocker and where?
|
- Does it say who can fix a blocker and where?
|
||||||
|
- Does a module-localized blocker pass its translated row labels through the
|
||||||
|
shared `ActionBlockerHint` contract instead of reproducing the component?
|
||||||
|
- Does longer field or blocker guidance use a stable `DocumentationHelpLink`
|
||||||
|
topic/context reference, with hosted fallback when the optional Docs module
|
||||||
|
is absent?
|
||||||
- Does it reuse existing core patterns for wizard steps, problem lists, modals,
|
- Does it reuse existing core patterns for wizard steps, problem lists, modals,
|
||||||
help, and review?
|
help, and review?
|
||||||
- Is there a review or preflight step before broad, destructive, or risky
|
- Is there a review or preflight step before broad, destructive, or risky
|
||||||
|
|||||||
@@ -0,0 +1,19 @@
|
|||||||
|
<!-- codex-wiki-sync:01b8d1b23b466bdd1471f970 -->
|
||||||
|
|
||||||
|
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/WEBUI_MODULE_PACKAGE_LAYOUT.md`.
|
||||||
|
> Origin: `repository`.
|
||||||
|
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
||||||
|
|
||||||
|
---
|
||||||
|
# WebUI Module Package Layout
|
||||||
|
|
||||||
|
Core discovers a module contribution from `src/module.ts` when `node_modules`
|
||||||
|
links directly to a module's `webui` package. Tagged release dependencies are
|
||||||
|
installed from repository-root packages and expose the same contribution at
|
||||||
|
`webui/src/module.ts`. The Vite registry accepts both layouts and imports the
|
||||||
|
contribution descriptor directly so route-level lazy loading is preserved.
|
||||||
|
|
||||||
|
A release package is invalid if neither entry exists. The module-permutation CI
|
||||||
|
matrix builds source-linked and installed release compositions; it must not fall
|
||||||
|
back to a package root barrel because that would eagerly pull module pages into
|
||||||
|
the shell bundle.
|
||||||
@@ -1,78 +0,0 @@
|
|||||||
<!-- codex-wiki-sync:576ede02ac9fec1bc104f3eb -->
|
|
||||||
|
|
||||||
> Mirrored from `/mnt/DATA/git/govoplan-core/docs/audits/2026-07-09-dependency-audit.md`.
|
|
||||||
> Origin: `repository`.
|
|
||||||
> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context.
|
|
||||||
|
|
||||||
---
|
|
||||||
# Dependency Audit - 2026-07-09
|
|
||||||
|
|
||||||
Commands:
|
|
||||||
|
|
||||||
```bash
|
|
||||||
cd /mnt/DATA/git/govoplan-core
|
|
||||||
bash scripts/check-dependency-audits.sh
|
|
||||||
```
|
|
||||||
|
|
||||||
Status: remediated.
|
|
||||||
|
|
||||||
Initial result:
|
|
||||||
|
|
||||||
- Python audit failed: 24 advisories were reported across `cryptography`,
|
|
||||||
`pip`, `python-multipart`, `pyzipper`, and `starlette`.
|
|
||||||
- npm production audit passed: `npm audit --omit=dev` reported 0
|
|
||||||
vulnerabilities.
|
|
||||||
|
|
||||||
Python findings:
|
|
||||||
|
|
||||||
| Package | Installed | Advisory count | Minimum reported fix |
|
|
||||||
| --- | ---: | ---: | --- |
|
|
||||||
| `cryptography` | `44.0.0` | 5 | `48.0.1` |
|
|
||||||
| `pip` | `26.0.1` | 3 | `26.1.2` |
|
|
||||||
| `python-multipart` | `0.0.17` | 7 | `0.0.31` |
|
|
||||||
| `pyzipper` | `0.3.6` | 1 | `0.4.0` |
|
|
||||||
| `starlette` | `0.41.3` | 8 | `1.3.1` |
|
|
||||||
|
|
||||||
Private GovOPlaN packages were skipped by `pip-audit` because they are not
|
|
||||||
published on PyPI. That is expected for local editable development installs.
|
|
||||||
|
|
||||||
The remediation below upgrades those dependencies and records the compatibility
|
|
||||||
checks run against core, files, and campaign behavior.
|
|
||||||
|
|
||||||
## Remediation
|
|
||||||
|
|
||||||
Remediation applied on 2026-07-09:
|
|
||||||
|
|
||||||
- upgraded core's FastAPI floor to `fastapi>=0.139,<1`, resolving Starlette to
|
|
||||||
`starlette==1.3.1`
|
|
||||||
- upgraded core's cryptography floor to `cryptography>=48.0.1,<50`, resolving
|
|
||||||
to `cryptography==49.0.0`
|
|
||||||
- declared the files module upload parser dependency as
|
|
||||||
`python-multipart>=0.0.31,<1`, resolving to `python-multipart==0.0.32`
|
|
||||||
- upgraded the campaign ZIP dependency to `pyzipper>=0.4,<1`, resolving to
|
|
||||||
`pyzipper==0.4.0`
|
|
||||||
- upgraded the local audit environment to `pip==26.1.2`
|
|
||||||
- removed the obsolete local `govoplan-module-multimailer` editable install
|
|
||||||
from the audit environment so the audit reflects the split module product
|
|
||||||
|
|
||||||
Post-remediation result:
|
|
||||||
|
|
||||||
- `bash scripts/check-dependency-audits.sh`: passed, no known Python
|
|
||||||
vulnerabilities found and npm production audit reported 0 vulnerabilities.
|
|
||||||
- `python -m pip check`: passed.
|
|
||||||
- `bash scripts/check-module-matrix.sh`: passed.
|
|
||||||
- `python -m unittest tests.test_api_smoke`: passed.
|
|
||||||
- campaign encrypted/plain ZIP smoke with `pyzipper==0.4.0`: passed.
|
|
||||||
|
|
||||||
Notes:
|
|
||||||
|
|
||||||
- `pip-audit` still reports private GovOPlaN packages as skipped because they
|
|
||||||
are not published on PyPI. That is expected for editable local development
|
|
||||||
installs.
|
|
||||||
- `httpx2>=2.5,<3` is included in development requirements so Starlette's
|
|
||||||
`TestClient` uses the non-deprecated backend. `httpx==0.28.1` remains in dev
|
|
||||||
requirements for tests that mock connector HTTP responses directly.
|
|
||||||
- Split-module API routers now use Starlette's renamed
|
|
||||||
`HTTP_422_UNPROCESSABLE_CONTENT` status constant. This preserves the 422
|
|
||||||
status code while avoiding the deprecated `HTTP_422_UNPROCESSABLE_ENTITY`
|
|
||||||
alias.
|
|
||||||
Reference in New Issue
Block a user