diff --git a/Codex-Project-Index.md b/Codex-Project-Index.md index 4be3618..36c2f50 100644 --- a/Codex-Project-Index.md +++ b/Codex-Project-Index.md @@ -7,13 +7,16 @@ This page is generated from repository and product-directory project files. - [Product govoplan-split-concept-action-plan](Product govoplan-split-concept-action-plan) - `/mnt/DATA/Nextcloud/ADD ideas UG/Products/govoplan/split-concept-action-plan.md` - [Repo-README](Repo-README) - `/mnt/DATA/git/govoplan-core/README.md` - [Repo-docs-ACCESS-EXTRACTION-PLAN](Repo-docs-ACCESS-EXTRACTION-PLAN) - `/mnt/DATA/git/govoplan-core/docs/ACCESS_EXTRACTION_PLAN.md` +- [Repo-docs-ACCESS-RBAC-MODEL](Repo-docs-ACCESS-RBAC-MODEL) - `/mnt/DATA/git/govoplan-core/docs/ACCESS_RBAC_MODEL.md` - [Repo-docs-API-CONDITIONAL-DELTA](Repo-docs-API-CONDITIONAL-DELTA) - `/mnt/DATA/git/govoplan-core/docs/API_CONDITIONAL_DELTA.md` - [Repo-docs-CATALOG-TRUST-AND-LICENSING](Repo-docs-CATALOG-TRUST-AND-LICENSING) - `/mnt/DATA/git/govoplan-core/docs/CATALOG_TRUST_AND_LICENSING.md` - [Repo-docs-CODEX-WORKFLOW](Repo-docs-CODEX-WORKFLOW) - `/mnt/DATA/git/govoplan-core/docs/CODEX_WORKFLOW.md` - [Repo-docs-CONFIGURATION-PACKAGES](Repo-docs-CONFIGURATION-PACKAGES) - `/mnt/DATA/git/govoplan-core/docs/CONFIGURATION_PACKAGES.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-EVENTS-AND-AUDIT](Repo-docs-EVENTS-AND-AUDIT) - `/mnt/DATA/git/govoplan-core/docs/EVENTS_AND_AUDIT.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-GOVERNMENT-OPERATIONS-VISION](Repo-docs-GOVERNMENT-OPERATIONS-VISION) - `/mnt/DATA/git/govoplan-core/docs/GOVERNMENT_OPERATIONS_VISION.md` - [Repo-docs-GOVOPLAN-MASTER-ROADMAP](Repo-docs-GOVOPLAN-MASTER-ROADMAP) - `/mnt/DATA/git/govoplan-core/docs/GOVOPLAN_MASTER_ROADMAP.md` - [Repo-docs-GOVOPLAN-MODULE-ROADMAP](Repo-docs-GOVOPLAN-MODULE-ROADMAP) - `/mnt/DATA/git/govoplan-core/docs/GOVOPLAN_MODULE_ROADMAP.md` @@ -21,9 +24,7 @@ This page is generated from repository and product-directory project files. - [Repo-docs-MODULE-BOUNDARY-DECISIONS](Repo-docs-MODULE-BOUNDARY-DECISIONS) - `/mnt/DATA/git/govoplan-core/docs/MODULE_BOUNDARY_DECISIONS.md` - [Repo-docs-POLICY-CONTRACTS](Repo-docs-POLICY-CONTRACTS) - `/mnt/DATA/git/govoplan-core/docs/POLICY_CONTRACTS.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-RBAC-MANIFEST](Repo-docs-RBAC-MANIFEST) - `/mnt/DATA/git/govoplan-core/docs/RBAC_MANIFEST.md` - [Repo-docs-RELEASE-CATALOG-WORKFLOW](Repo-docs-RELEASE-CATALOG-WORKFLOW) - `/mnt/DATA/git/govoplan-core/docs/RELEASE_CATALOG_WORKFLOW.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-SCALABILITY-AND-SIZING](Repo-docs-SCALABILITY-AND-SIZING) - `/mnt/DATA/git/govoplan-core/docs/SCALABILITY_AND_SIZING.md` -- [Repo-docs-SYSTEM-GOVERNANCE-MANIFEST](Repo-docs-SYSTEM-GOVERNANCE-MANIFEST) - `/mnt/DATA/git/govoplan-core/docs/SYSTEM_GOVERNANCE_MANIFEST.md` diff --git a/Repo-README.md b/Repo-README.md index cfae4fc..89f8e23 100644 --- a/Repo-README.md +++ b/Repo-README.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/README.md`. > Origin: `repository`. @@ -26,8 +26,9 @@ Feature modules own their backend routers, models, migrations, permissions, fron Canonical policy documents live in `docs/`: -- [RBAC_MANIFEST.md](docs/RBAC_MANIFEST.md) -- [SYSTEM_GOVERNANCE_MANIFEST.md](docs/SYSTEM_GOVERNANCE_MANIFEST.md) +- [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) @@ -63,7 +64,7 @@ ENABLED_MODULES=access,campaigns ./.venv/bin/python -m govoplan_core.devserver \ 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`. -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 old disposable SQLite fallback, run with `GOVOPLAN_DEV_DATABASE_BACKEND=sqlite`; that database lives at `runtime/multimailer-dev.db`. +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. diff --git a/Repo-docs-ACCESS-RBAC-MODEL.md b/Repo-docs-ACCESS-RBAC-MODEL.md new file mode 100644 index 0000000..9424d11 --- /dev/null +++ b/Repo-docs-ACCESS-RBAC-MODEL.md @@ -0,0 +1,295 @@ + + +> Mirrored from `/mnt/DATA/git/govoplan-core/docs/ACCESS_RBAC_MODEL.md`. +> Origin: `repository`. +> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context. + +--- +# GovOPlaN RBAC And Resource-Access Model + +**Updated:** 2026-07-09 + +## Authorization Equation + +An operation is permitted only when every applicable layer allows it: + +```text +effective role/API-key capability +AND resource ownership/share access +AND workflow state +AND active governance/policy constraints +``` + +RBAC answers what an actor may do. ACLs answer which resource the actor may do +it to. Workflow state and policy decide whether the operation is currently +valid. + +## Identity And Scope + +```text +Account global login identity ++- User membership tenant-local identity + +- direct tenant roles + +- active group memberships + | +- inherited tenant roles + +- tenant-local API keys + +Account ++- direct system-role assignments +``` + +A browser session has one active tenant membership. System privileges do not +silently grant tenant data access. API keys remain tenant-local and receive the +intersection of their configured scopes and their owner's live tenant scopes on +every request. + +## Wildcards + +```text +tenant:* every canonical tenant permission +system:* every canonical system permission +* legacy alias interpreted as tenant:* only +``` + +Tenant wildcards never grant system permissions. + +## Canonical Tenant Permissions + +Campaigns: + +```text +campaign:read +campaign:create +campaign:update +campaign:copy +campaign:archive +campaign:delete +campaign:share +campaign:validate +campaign:build +campaign:review +campaign:send_test +campaign:queue +campaign:control +campaign:send +campaign:retry +campaign:reconcile +``` + +Recipients: + +```text +recipients:read +recipients:write +recipients:import +recipients:export +``` + +Files: + +```text +files:read +files:download +files:upload +files:organize +files:share +files:delete +files:admin +``` + +Reports and audit: + +```text +reports:read +reports:export +reports:send +audit:read +``` + +Mail servers: + +```text +mail_servers:read +mail_servers:use +mail_servers:test +mail_servers:write +mail_servers:manage_credentials +``` + +Tenant administration: + +```text +admin:users:read +admin:users:create +admin:users:update +admin:users:suspend + +admin:groups:read +admin:groups:write +admin:groups:manage_members + +admin:roles:read +admin:roles:write +admin:roles:assign + +admin:api_keys:read +admin:api_keys:create +admin:api_keys:revoke + +admin:settings:read +admin:settings:write +admin:policies:read +admin:policies:write +``` + +## Canonical System Permissions + +```text +system:tenants:read +system:tenants:create +system:tenants:update +system:tenants:suspend + +system:accounts:read +system:accounts:create +system:accounts:update +system:accounts:suspend + +system:roles:read +system:roles:write +system:roles:assign + +system:access:read +system:access:assign + +system:audit:read +system:settings:read +system:settings:write +system:governance:read +system:governance:write +``` + +`system:access:*` remains a read/assignment boundary for cross-tenant and +system access handling. It is not a separate primary UI area. + +## Default Tenant Roles + +- **Owner:** `tenant:*`. At least one active operational owner must remain. +- **Tenant administrator:** settings, policies, users, groups, roles, API keys, + and read access to campaigns/files/reports/audit. Real delivery remains + separately delegable. +- **Administrator:** all tenant permissions for upgraded installations. +- **Access administrator:** membership and assignment management within + delegation limits. +- **Campaign manager:** prepare, validate, and build campaigns; no review + approval or real delivery by default. +- **Reviewer:** inspect and approve prepared campaign messages. +- **Sender:** mock-test, queue, control, send, retry, and reconcile prepared + campaigns; can use/test approved mail profiles. +- **File manager:** managed file operations without campaign delivery rights. +- **Viewer:** read campaigns, recipients, files, and reports. +- **Auditor:** read campaigns, recipient evidence, reports, and audit records; + export detailed evidence. + +## Default System Roles + +- **System owner:** `system:*`, protected. At least one active account must + retain it. +- **System administrator:** all specific system permissions, editable and not + protected. +- **System auditor:** read-only system registry/settings/governance/audit role, + editable. + +## Delegation Ceiling + +For role definition, assignment, and API-key creation: + +```text +requested scopes subset of actor delegateable scopes +``` + +Rules: + +1. Tenant roles may contain tenant scopes only. +2. System roles may contain system scopes only. +3. Definition rights and assignment rights are separate. +4. Group definition and group membership management are separate. +5. API-key scopes are intersected with the owner's current effective scopes on + every request. +6. Suspended accounts, users, tenants, or groups stop contributing access + immediately. +7. Administrative updates are field-sensitive; a user with only status + authority cannot change role assignments. + +## Campaign Ownership And ACLs + +A campaign has exactly one owner: + +```text +owner user OR owner group +``` + +Additional active shares may target users or groups with `read` or `write`. + +Resolution: + +- owner user: read and write; +- member of owner group: read and write; +- explicit read share: read; +- explicit write share: read and write; +- `tenant:*`: tenant-wide ACL bypass; +- ordinary campaign permission without ownership/share: no object access. + +ACLs do not add capabilities. A write share still needs the specific permission +for update, validation, review, send, report, retry, or reconciliation. + +## Files + +The current file access model distinguishes tenant-level file capabilities from +space/folder/file ownership: + +| Scope | Meaning | +| --- | --- | +| `files:read` | browse/read visible file spaces and metadata | +| `files:download` | download file content when ACL permits | +| `files:upload` | create files in writable spaces | +| `files:organize` | create folders, move files, and update metadata where ACL permits | +| `files:share` | share files/spaces according to owner and policy rules | +| `files:delete` | delete or retire files where ACL permits | +| `files:admin` | tenant-wide administration of user/group file spaces | + +External file connections and spaces are additionally constrained by connector +policy and owner/group assignment in the files module. + +## Mail Servers + +| Scope | Meaning | +| --- | --- | +| `mail_servers:read` | profile metadata and effective policy visibility | +| `mail_servers:use` | use an allowed profile for a campaign or message flow | +| `mail_servers:test` | run connectivity tests without revealing secrets | +| `mail_servers:write` | create/update profile metadata where policy allows | +| `mail_servers:manage_credentials` | create/replace SMTP/IMAP secrets or lower-level credentials where policy allows | + +Reusable encrypted profiles exist. Effective usability is also constrained by +hierarchical mail-profile policy, ownership, allowed/forced profile sets, +credential inheritance mode, lower-level override switches, and allow/deny +patterns. + +## Compatibility Aliases + +Compatibility aliases may exist in backend code for upgraded installations, but +new UI and docs should use canonical scopes. + +Current alias direction: + +```text +* -> tenant:* +system:tenants:write -> create/update/suspend tenant scopes +system:access:write -> system access assignment/write scopes +``` + +A separate `retention:*` family is not currently canonical because retention is +managed through system settings and tenant policy scopes. Add it only if +retention operation duties need separation from general policy/settings +administration. diff --git a/Repo-docs-API-CONDITIONAL-DELTA.md b/Repo-docs-API-CONDITIONAL-DELTA.md index 59935a3..dd0a8ea 100644 --- a/Repo-docs-API-CONDITIONAL-DELTA.md +++ b/Repo-docs-API-CONDITIONAL-DELTA.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/API_CONDITIONAL_DELTA.md`. > Origin: `repository`. @@ -36,6 +36,11 @@ changed inside a collection. Collection endpoints that can expose row-level changes should use the shared delta contract instead of inventing module-specific formats. +Core provides `core_change_sequence` as the shared monotonic change sequence. +Modules record append-only entries in the same database transaction as the +resource write. Watermarks are encoded as `seq:` and should be treated +as opaque by clients. + Backend shape: ```json @@ -51,8 +56,8 @@ Backend shape: Fields: - `items`: changed or current items since the requested watermark. -- `deleted`: deleted item markers with at least `id`, and optionally `revision` - and `deleted_at`. +- `deleted`: deleted item markers with at least `id`, and optionally + `resource_type`, `revision`, and `deleted_at`. - `watermark`: opaque value the client sends as `since` on the next request. - `has_more`: true when the client should request the next page with the returned watermark. @@ -66,6 +71,18 @@ Recommended query parameters: - `limit`: maximum number of changed items plus deleted markers. - `include_deleted`: whether deleted markers should be returned. -Modules should base watermarks on a monotonic revision, audit/event sequence, or -updated/deleted timestamp that is scoped to the same tenant and authorization -rules as the endpoint response. +Modules should record changes with: + +- `module_id`: the owning module, for example `files`. +- `collection`: the delta collection, for example `files.assets`. +- `resource_type`: stable row kind, for example `file` or `folder`. +- `resource_id`: stable resource identifier. +- `operation`: `created`, `updated`, or `deleted`. +- `tenant_id`: tenant scope when the change is tenant-owned. +- `payload`: small, non-secret routing metadata that helps determine whether a + tombstone belongs to the requested view. + +The first concrete consumer is `GET /api/v1/files/delta`. Without `since`, it +returns the current files/folders snapshot for the requested owner/campaign +scope. With `since=seq:`, it returns changed files, changed folders, +and tombstones for resources that left the current view. diff --git a/Repo-docs-DEPLOYMENT-OPERATOR-GUIDE.md b/Repo-docs-DEPLOYMENT-OPERATOR-GUIDE.md index 71d063a..88eb76a 100644 --- a/Repo-docs-DEPLOYMENT-OPERATOR-GUIDE.md +++ b/Repo-docs-DEPLOYMENT-OPERATOR-GUIDE.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/DEPLOYMENT_OPERATOR_GUIDE.md`. > Origin: `repository`. @@ -165,8 +165,8 @@ prefer `FILE_STORAGE_*`. | Setting | Default | Notes | | --- | --- | --- | | `CORS_ORIGINS` | local dev origins | Set to the exact WebUI origins in staging/production. | -| `AUTH_SESSION_COOKIE_NAME` | `msm_session` | Change only through a controlled rollout because it logs users out. | -| `AUTH_CSRF_COOKIE_NAME` | `msm_csrf` | Must match WebUI/API deployment. | +| `AUTH_SESSION_COOKIE_NAME` | configured default | Change only through a controlled rollout because it logs users out. | +| `AUTH_CSRF_COOKIE_NAME` | configured default | Must match WebUI/API deployment. | | `AUTH_COOKIE_SECURE` | `false` | Set `true` behind HTTPS. | | `AUTH_COOKIE_SAMESITE` | `lax` | Use a stricter value only after testing login and CSRF flows. | | `AUTH_COOKIE_DOMAIN` | empty | Set only when the API and WebUI intentionally share a parent domain. | @@ -264,15 +264,25 @@ GOVOPLAN_STOP_PROFILE_DEPENDENCIES_ON_EXIT=1 scripts/launch-production-like-dev. ## Module Install/Uninstall Operations -Use Admin > System > Modules for planning. Use the operator shell for package -changes: +Use Admin > System > Modules for planning. The running API server validates and +queues install plans; it does not run pip/npm or restart itself from an HTTP +request. Package mutation belongs to the trusted installer CLI/daemon in an +operator shell while maintenance mode is active. + +Preflight from the server shell: ```bash govoplan-module-installer --format shell +``` + +Apply a prepared plan directly from a controlled shell: + +```bash govoplan-module-installer --apply --build-webui ``` -For production-like runs, prefer supervised mode with restart and health checks: +For production-like runs, prefer supervised mode with migrations, database +backup/restore hooks, restart commands, and health checks: ```bash govoplan-module-installer \ @@ -286,6 +296,71 @@ govoplan-module-installer \ --database-restore-command 'pg_restore --clean --if-exists --dbname "$GOVOPLAN_DATABASE_URL_PGTOOLS" "$GOVOPLAN_DATABASE_BACKUP_PATH"' ``` +To let the admin UI submit work without executing package managers inside the +API process, run the daemon in a separate operator shell: + +```bash +govoplan-module-installer \ + --daemon \ + --migrate \ + --build-webui \ + --database-backup-command 'pg_dump --format=custom "$GOVOPLAN_DATABASE_URL_PGTOOLS" > "$GOVOPLAN_DATABASE_BACKUP_PATH"' \ + --database-restore-check-command 'pg_restore --list "$GOVOPLAN_DATABASE_BACKUP_PATH" >/dev/null' \ + --database-restore-command 'pg_restore --clean --if-exists --dbname "$GOVOPLAN_DATABASE_URL_PGTOOLS" "$GOVOPLAN_DATABASE_BACKUP_PATH"' \ + --health-url http://127.0.0.1:8000/health \ + --restart-command '' +``` + +The daemon claims one queued request at a time and writes request/run records +below `runtime/module-installer`. For process-manager one-shot usage or tests, +use `--daemon-once`. Check daemon status with: + +```bash +govoplan-module-installer --daemon-status --format json +``` + +The installer uses a runtime lock, snapshots `pip freeze` plus WebUI package +files, writes a run record, and marks planned rows as applied only after all +commands succeed. With `--migrate`, SQLite databases are backed up through +SQLite's backup API; non-SQLite databases require +`--database-backup-command`, `--database-restore-check-command`, and +`--database-restore-command`. + +Database hook commands receive: + +- `GOVOPLAN_INSTALLER_RUN_DIR` +- `GOVOPLAN_DATABASE_URL` +- `GOVOPLAN_DATABASE_URL_PGTOOLS` for PostgreSQL tools +- `GOVOPLAN_DATABASE_BACKUP_PATH` +- `GOVOPLAN_DATABASE_BACKUP_METADATA` + +Avoid embedding secrets directly in commands; prefer environment variables, +service credentials, or deployment-local secret injection. + +Inspect installer history and lock state from the operator shell: + +```bash +govoplan-module-installer --list-runs --format json +govoplan-module-installer --show-run --format json +govoplan-module-installer --lock-status --format json +govoplan-module-installer --list-requests --format json +govoplan-module-installer --show-request --format json +govoplan-module-installer --cancel-request --format json +govoplan-module-installer --retry-request --format json +``` + +Rollback uses the saved run snapshot: + +```bash +govoplan-module-installer --rollback +govoplan-module-installer --rollback --database-restore-command '' +``` + +Uninstall is non-destructive by default. A planned uninstall row can set +`destroy_data: true` to request destructive module retirement. The module must +provide an automated retirement provider, and the installer snapshots the +database before dropping module-owned tables. + Run the rollback drill before relying on installer automation in a new environment: @@ -293,8 +368,22 @@ environment: ./.venv/bin/python scripts/module-installer-rollback-drill.py --format json ``` -See `RELEASE_DEPENDENCIES.md` for release package refs, catalog trust, -installer daemon operation, rollback records, and destructive module retirement. +The drill uses temporary SQLite databases and simulated package commands. It +does not install or uninstall real packages. It exercises: + +- package command failure followed by supervised rollback; +- migration failure with a SQLite database snapshot; +- restart-command failure; +- health timeout after restart; +- destructive retirement executor failure with database rollback; +- PostgreSQL-style backup, restore-check, and restore hooks; +- daemon heartbeat, request queue claim/update, retry/cancel, and stale lock + detection/removal. + +See `RELEASE_DEPENDENCIES.md` for release package refs and migration baseline +checks. See `CATALOG_TRUST_AND_LICENSING.md` and +`RELEASE_CATALOG_WORKFLOW.md` for catalog trust, signing, keyring, replay, and +license operation. ## Operator Checklist diff --git a/Repo-docs-DOCUMENTATION-MAP.md b/Repo-docs-DOCUMENTATION-MAP.md new file mode 100644 index 0000000..aa4e496 --- /dev/null +++ b/Repo-docs-DOCUMENTATION-MAP.md @@ -0,0 +1,60 @@ + + +> 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, boundaries, lifecycle, and WebUI contribution rules. | +| Access extraction history | `ACCESS_EXTRACTION_PLAN.md` | Historical extraction plan and remaining ownership context only. | +| 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 package dependencies | `RELEASE_DEPENDENCIES.md` | Release package refs, migration baselines, release lockfiles, and release checklist. | +| Catalog publishing workflow | `RELEASE_CATALOG_WORKFLOW.md` | Release-machine steps for signed catalog/keyring publication through `govoplan-web`. | +| Catalog trust and licensing rules | `CATALOG_TRUST_AND_LICENSING.md` | Catalog shape, signatures, keyrings, replay protection, and offline licenses. | +| Remote WebUI bundle design | `REMOTE_WEBUI_BUNDLES.md` | Experimental controlled-deployment design; normal releases still use package builds. | +| Scalability and sizing | `SCALABILITY_AND_SIZING.md` | Core sizing profiles until `govoplan-ops` owns executable operations tooling. | + +## Product And Module Planning + +| Topic | Canonical document | Notes | +| --- | --- | --- | +| Product roadmap waves | `GOVOPLAN_MASTER_ROADMAP.md` | Product-level sequencing and implementation gates. | +| Module and issue routing | `GOVOPLAN_MODULE_ROADMAP.md` | Quick map from ideas to owning repositories and issues. | +| Durable boundary decisions | `MODULE_BOUNDARY_DECISIONS.md` | Native-vs-connector decisions and missing-module criteria. | +| 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. | +| Government operations vision | `GOVERNMENT_OPERATIONS_VISION.md` | Product vision and reference journeys; active work belongs in issues. | + +## 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. diff --git a/Repo-docs-GITEA-ISSUES.md b/Repo-docs-GITEA-ISSUES.md index 7f2b1dc..b127682 100644 --- a/Repo-docs-GITEA-ISSUES.md +++ b/Repo-docs-GITEA-ISSUES.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/GITEA_ISSUES.md`. > Origin: `repository`. @@ -215,6 +215,13 @@ Apply the wiki mirror: ./scripts/gitea-sync-wiki.py --env-file /home/zemion/.config/gitea/gitea.env --apply ``` +After renaming or deleting repository docs, prune previously managed wiki pages +that no longer have a source file: + +```bash +./scripts/gitea-sync-wiki.py --env-file /home/zemion/.config/gitea/gitea.env --repo govoplan-core --prune-managed --apply +``` + The default apply path uses the Gitea wiki git repository, not one REST API request per page. It keeps a local checkout cache below `/tmp/codex-gitea-wiki-sync`, commits changed pages once per repository, and diff --git a/Repo-docs-SYSTEM-GOVERNANCE-MANIFEST.md b/Repo-docs-GOVERNANCE-MODEL.md similarity index 52% rename from Repo-docs-SYSTEM-GOVERNANCE-MANIFEST.md rename to Repo-docs-GOVERNANCE-MODEL.md index 94bc982..c639085 100644 --- a/Repo-docs-SYSTEM-GOVERNANCE-MANIFEST.md +++ b/Repo-docs-GOVERNANCE-MODEL.md @@ -1,18 +1,18 @@ - + -> Mirrored from `/mnt/DATA/git/govoplan-core/docs/SYSTEM_GOVERNANCE_MANIFEST.md`. +> Mirrored from `/mnt/DATA/git/govoplan-core/docs/GOVERNANCE_MODEL.md`. > Origin: `repository`. > Active tasks and changing state belong in Gitea issues; this wiki page is durable project context. --- -# Multi Seal Mail - Current System and Tenant Governance Model +# GovOPlaN Governance Model -**Updated:** 2026-06-16 -**Current migration head:** `f5a6b7c8d9e0` +**Updated:** 2026-07-09 ## Governance Rule -System policy is authoritative for tenants and all lower levels. Each lower level may only narrow what it inherits: +System policy is authoritative for tenants and all lower levels. Each lower +level may only narrow what it inherits: ```text system @@ -21,52 +21,65 @@ system -> campaign ``` -Lower levels do not widen privileges, allowed profiles, retention durations or credential rights granted by a higher level. +Lower levels do not widen privileges, allowed profiles, retention durations, or +credential rights granted by a higher level. ## Administration Structure +GovOPlaN separates system administration from scoped configuration: + ```text -SYSTEM -- Settings -- Retention -- Mail servers +ADMINISTRATION +- Modules +- Packages +- Maintenance +- Changes + +GLOBAL - Tenants -- Users -- Groups -- System roles -- Tenant roles -- Audit +- Roles +- Groups and users +- File connectors +- Mail servers +- API keys +- Retention TENANT -- Settings boundary -- Users -- Groups - Roles -- API keys +- Groups and users +- File connectors - Mail servers +- API keys - Retention -- Audit - -USER -- User mail -- User retention GROUP -- Group mail -- Group retention +- File connectors +- Mail servers +- API keys +- Retention + +USER +- File connectors +- Mail servers +- API keys +- Retention ``` -There is no separate System access page. Compatibility access scopes remain in the backend for assignment/read boundaries. +System access scopes remain in the backend for assignment/read boundaries, but +the UI should present the configuration hierarchy rather than a separate +"system access" concept. ## Tenant Governance -System settings define tenant defaults and whether tenants may narrow selected options. Tenant overrides can only restrict: +System settings define tenant defaults and whether tenants may narrow selected +options. Tenant overrides can only restrict: - custom groups; - custom roles; - tenant API keys. -The backend enforces that tenant governance cannot widen system-denied privileges. +The backend enforces that tenant governance cannot widen system-denied +privileges. ## Mail-Profile Governance @@ -80,7 +93,10 @@ group campaign ``` -Effective campaign profile availability follows campaign ownership. A campaign owned by a user resolves through system, tenant, that user and campaign policy. A group-owned campaign resolves through system, tenant, that group and campaign policy. +Effective campaign profile availability follows campaign ownership. A campaign +owned by a user resolves through system, tenant, that user, and campaign +policy. A group-owned campaign resolves through system, tenant, that group, and +campaign policy. Policy semantics: @@ -88,12 +104,18 @@ Policy semantics: - lower levels can further restrict the set; - forced profiles mean the lower level must choose from the forced set; - a forced set with one profile effectively enforces that profile; -- campaign-level profile creation is allowed only if the effective policy permits it; -- SMTP/IMAP credentials use one inheritance decision per protocol: lower levels must inherit profile credentials, may inherit profile credentials, or must provide local credentials; -- the lower-level override switch for `smtp_credentials.inherit` and `imap_credentials.inherit` controls whether descendants may change that inheritance decision; +- campaign-level profile creation is allowed only if the effective policy + permits it; +- SMTP/IMAP credentials use one inheritance decision per protocol: lower levels + must inherit profile credentials, may inherit profile credentials, or must + provide local credentials; +- the lower-level override switch for `smtp_credentials.inherit` and + `imap_credentials.inherit` controls whether descendants may change that + inheritance decision; - deny patterns always win over allow patterns; - empty or `*` allowlist means allow all except denied; -- non-empty allowlist means at least one allow rule must match and no deny rule may match. +- non-empty allowlist means at least one allow rule must match and no deny rule + may match. Pattern targets: @@ -105,7 +127,23 @@ From header recipient domains ``` -Ownership transfer is intentionally deferred as a two-step workflow: original owner initiates, new owner accepts and reselects/repairs the mail profile if their effective policy requires it. +Ownership transfer is intentionally deferred as a two-step workflow: original +owner initiates, new owner accepts and reselects/repairs the mail profile if +their effective policy requires it. + +## File-Connector Governance + +File connector profiles and credentials are separated. Profiles describe +external endpoints; credentials bind authentication material and policy to a +scope. Concrete linked folders appear as file spaces in the files module. + +Governance follows the same inheritance shape as mail: + +- system and tenant policy can permit, require, or forbid lower-level + connections/credentials; +- user or group ownership controls which spaces appear to principals; +- spaces inherit endpoint and credential policy from their connector profile; +- connector health and credential tests must not reveal plaintext secrets. ## Retention Governance @@ -127,20 +165,27 @@ Rules: - system may set concrete defaults or unlimited retention; - system exposes allow-limiting toggles per field; -- tenants, users/groups and campaigns may only shorten inherited retention where the parent allows limiting; +- tenants, users/groups, and campaigns may only shorten inherited retention + where the parent allows limiting; - blank lower-level values inherit; -- mock mailbox retention is currently system-level because mock mailbox records do not yet carry tenant/campaign ownership metadata; -- dry-run/apply retention actions report affected classes before destructive cleanup. +- mock mailbox retention is currently system-level because mock mailbox records + do not yet carry tenant/campaign ownership metadata; +- dry-run/apply retention actions report affected classes before destructive + cleanup. -## Role Definitions and Assignments +## Role Definitions And Assignments -### System roles +### System Roles -System roles define instance-wide permissions. `system:*` is stored as one wildcard and displayed as granting the full system catalogue. System owner is protected. +System roles define instance-wide permissions. `system:*` is stored as one +wildcard and displayed as granting the full system catalogue. System owner is +protected. -### Tenant roles +### Tenant Roles -Tenant roles can be system-governed templates or tenant-local definitions, subject to system tenant-governance settings and actor delegation ceilings. Wildcard counts are expanded against the canonical tenant catalogue. +Tenant roles can be system-governed templates or tenant-local definitions, +subject to system tenant-governance settings and actor delegation ceilings. +Wildcard counts are expanded against the canonical tenant catalogue. ## Audit Access @@ -151,15 +196,17 @@ system audit -> system:audit:read tenant audit -> active tenant + audit:read ``` -Audit pages use server pagination, filtering and bounded grids. +Audit pages use server pagination, filtering, and bounded grids. ## Tenant Switching -Tenant switching preserves the current URL when possible and falls back when a route/resource is not accessible in the new tenant context. +Tenant switching preserves the current URL when possible and falls back when a +route/resource is not accessible in the new tenant context. -The tenant selector is hidden for ordinary single-tenant accounts and visible for multi-tenant or system tenant-management contexts. +The tenant selector is hidden for ordinary single-tenant accounts and visible +for multi-tenant or system tenant-management contexts. -## DataGrid Contract in Administration +## Administration DataGrid Contract Admin lists use bounded container grids: @@ -171,14 +218,12 @@ Admin lists use bounded container grids: - sticky headers where needed; - server pagination for audit. -## Still Deferred +## Deferred Work - real SMTP/IMAP test-bed verification and operator runbook; - recipient import with column mapping; -- Seafile/external connector governance; -- system/tenant/group/user file-space hierarchy and external storage hierarchy; - session/device revocation UI; -- backup/restore, monitoring and update procedures; +- backup/restore, monitoring, and update procedures; - DSAR workflows and evidence bundle verifier; - campaign ownership transfer workflow; - policy impact analysis before delete/disable/unshare/change; diff --git a/Repo-docs-GOVOPLAN-MODULE-ROADMAP.md b/Repo-docs-GOVOPLAN-MODULE-ROADMAP.md index e40298c..03911af 100644 --- a/Repo-docs-GOVOPLAN-MODULE-ROADMAP.md +++ b/Repo-docs-GOVOPLAN-MODULE-ROADMAP.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/GOVOPLAN_MODULE_ROADMAP.md`. > Origin: `repository`. @@ -53,12 +53,13 @@ Gitea wiki. Boundary decisions are recorded in | Installer/deployment operator flow | `govoplan-core`, later `govoplan-ops` | `add-ideas/govoplan-core#26` | | Production-like deployment documentation | `govoplan-core`, later `govoplan-ops` | `add-ideas/govoplan-core#28` | -## Proposed Missing Modules - ## Boundary Decision Register `docs/MODULE_BOUNDARY_DECISIONS.md` is the durable decision register for older -roadmap and boundary issues. Current decisions: +roadmap and boundary issues. Keep decision rationale there; keep this page as a +quick routing map from ideas to repositories and tracking issues. + +Current decisions: - templates and reporting are separate modules - RSS/source consume-publish starts in connectors; datasources/dataflow are not @@ -72,41 +73,15 @@ roadmap and boundary issues. Current decisions: ## Proposed Missing Modules -`govoplan-datasources` is not created yet. It should exist only if source -catalog ownership becomes broad enough to justify a module separate from -connectors, files, and reporting. Candidate responsibilities: +The following modules are intentionally not created yet. Their candidate +responsibilities and creation criteria live in `MODULE_BOUNDARY_DECISIONS.md`: -- source catalogue for SQL databases, CSV/Excel files, uploaded files, APIs, RSS feeds, and governed file locations -- credentials and connection profiles -- schema discovery and refresh cadence -- provenance, freshness, permission boundaries, and audit events +- `govoplan-datasources` +- `govoplan-dataflow` +- `govoplan-projects` -`govoplan-dataflow` is not created yet. It should exist only if pipelines and -publication become first-class product behavior beyond workflow, connectors, -and reporting. Candidate responsibilities: - -- ingestion, transformation, validation, scheduling, and lineage -- connecting datasources to reports, APIs, RSS, exports, and downstream systems -- the "consume sources, become source" lifecycle -- publication-state and audit integration - -`govoplan-projects` is intentionally not created yet. The decision is -connector-first through OpenProject. A native module is justified only if -GovOPlaN must own project semantics beyond cases, tasks, workflow, -appointments, documents, and reporting. - -## Boundary Notes - -- `govoplan-connectors` owns protocol and external-system integration strategy. It should not own business semantics once a domain module exists. -- `govoplan-files` owns file storage semantics and file-provider contracts. Remote provider implementations must stay optional. -- `govoplan-dms` owns document lifecycle, collaboration, versions, approvals, locks, retention, and legal hold. -- `govoplan-addresses` owns persons, organizations, postal/email addresses, distribution lists, and recipient import/export. -- `govoplan-calendar` owns events, availability, resources, recurrence, and groupware calendar adapters. -- `govoplan-scheduling` owns meeting scheduling polls, participant availability collection, candidate-slot ranking, and decision handoff. -- `govoplan-appointments` owns public/internal appointment-booking workflows. -- `govoplan-idm` owns directory, provisioning, and identity-provider integration; `govoplan-access` consumes resolved principals and permissions. -- `govoplan-reporting` owns report definitions, BI views, scheduled outputs, and export targets. -- `govoplan-templates` owns reusable renderable templates, not data selection or persistence. +Create a repository only after a concrete implementation package proves that +existing connector, files, reporting, workflow, or task ownership is too narrow. ## Integration Catalogue Routing @@ -120,23 +95,5 @@ When a target needs executable behavior, create the implementation issue in the owning module repository and keep only the cross-module routing or architecture decision in core. -## Release Tooling Note - -`scripts/push-release-tag.sh` covers the released full-product package set: - -- `govoplan-access` -- `govoplan-admin` -- `govoplan-tenancy` -- `govoplan-policy` -- `govoplan-audit` -- `govoplan-files` -- `govoplan-mail` -- `govoplan-campaign` -- `govoplan-calendar` -- `govoplan-core` - -It also includes existing roadmap/scaffold module repositories such as addresses, appointments, connectors, DMS, forms, IDM, reporting, scheduling, templates, workflow, XOE/V, and XRechnung as tag-only repositories. Tag-only repositories are committed, tagged, and pushed with the same release tag, but they are not added to `requirements-release.txt` or `webui/package.release.json` until they contain installable package metadata. - -Proposed modules without repositories, such as `govoplan-datasources`, -`govoplan-dataflow`, and `govoplan-projects`, cannot be included until a later -decision creates their repositories. +Release composition and tag-only repository handling are documented in +`RELEASE_DEPENDENCIES.md`. diff --git a/Repo-docs-MODULE-ARCHITECTURE.md b/Repo-docs-MODULE-ARCHITECTURE.md index 28ee8e8..220ff3e 100644 --- a/Repo-docs-MODULE-ARCHITECTURE.md +++ b/Repo-docs-MODULE-ARCHITECTURE.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/MODULE_ARCHITECTURE.md`. > Origin: `repository`. @@ -50,9 +50,9 @@ The kernel must not own product semantics such as users, tenants, RBAC decisions During the staged split, `govoplan-core` still contains compatibility surfaces for tenancy settings, governance/policy contracts, audit helpers, CSRF/API helpers, and secret helpers. The extracted access implementation lives in -`govoplan-access`; live legacy ORM table definitions have been split across -their platform owners while retaining historical table names. The old core -route, admin-service, and access-security re-export modules have been removed. +`govoplan-access`; live ORM table definitions have been split across their +platform owners using module-prefixed table names. The old core route, +admin-service, and access-security re-export modules have been removed. Callers must use module-owned imports, the public `govoplan_access.auth` request dependency API, or kernel capabilities. The remaining platform compatibility surfaces are temporary until the matching diff --git a/Repo-docs-RBAC-MANIFEST.md b/Repo-docs-RBAC-MANIFEST.md deleted file mode 100644 index 037ca6d..0000000 --- a/Repo-docs-RBAC-MANIFEST.md +++ /dev/null @@ -1,298 +0,0 @@ - - -> Mirrored from `/mnt/DATA/git/govoplan-core/docs/RBAC_MANIFEST.md`. -> Origin: `repository`. -> Active tasks and changing state belong in Gitea issues; this wiki page is durable project context. - ---- -# Multi Seal Mail - Current RBAC and Resource-Access Model - -**Updated:** 2026-06-16 -**Current migration head:** `f5a6b7c8d9e0` - -## Authorization Equation - -An operation is permitted only when every applicable layer allows it: - -```text -effective role/API-key capability -AND resource ownership/share access -AND workflow state -AND active governance/policy constraints -``` - -RBAC answers what an actor may do. ACLs answer which resource the actor may do it to. Workflow state and policy decide whether the operation is currently valid. - -## Identity and Scope - -```text -Account global login identity -+- User membership tenant-local identity - +- direct tenant roles - +- active group memberships - | +- inherited tenant roles - +- tenant-local API keys - -Account -+- direct system-role assignments -``` - -A browser session has one active tenant membership. System privileges do not silently grant tenant data access. API keys remain tenant-local and receive the intersection of their configured scopes and their owner's live tenant scopes on every request. - -## Wildcards - -```text -tenant:* every canonical tenant permission -system:* every canonical system permission -* legacy alias interpreted as tenant:* only -``` - -Tenant wildcards never grant system permissions. - -## Canonical Tenant Permissions - 53 - -### Campaigns - -```text -campaign:read -campaign:create -campaign:update -campaign:copy -campaign:archive -campaign:delete -campaign:share -campaign:validate -campaign:build -campaign:review -campaign:send_test -campaign:queue -campaign:control -campaign:send -campaign:retry -campaign:reconcile -``` - -### Recipients - -```text -recipients:read -recipients:write -recipients:import -recipients:export -``` - -### Files - -```text -files:read -files:download -files:upload -files:organize -files:share -files:delete -files:admin -``` - -### Reports and Audit - -```text -reports:read -reports:export -reports:send -audit:read -``` - -### Mail Servers - -```text -mail_servers:read -mail_servers:use -mail_servers:test -mail_servers:write -mail_servers:manage_credentials -``` - -### Tenant Administration - -```text -admin:users:read -admin:users:create -admin:users:update -admin:users:suspend - -admin:groups:read -admin:groups:write -admin:groups:manage_members - -admin:roles:read -admin:roles:write -admin:roles:assign - -admin:api_keys:read -admin:api_keys:create -admin:api_keys:revoke - -admin:settings:read -admin:settings:write -admin:policies:read -admin:policies:write -``` - -## Canonical System Permissions - 18 - -```text -system:tenants:read -system:tenants:create -system:tenants:update -system:tenants:suspend - -system:accounts:read -system:accounts:create -system:accounts:update -system:accounts:suspend - -system:roles:read -system:roles:write -system:roles:assign - -system:access:read -system:access:assign - -system:audit:read -system:settings:read -system:settings:write -system:governance:read -system:governance:write -``` - -`system:access:*` remains as a compatibility/read and assignment boundary for cross-tenant/system access handling. It is not a separate primary UI area. - -## Default Tenant Roles - -- **Owner:** `tenant:*`. At least one active operational owner must remain. -- **Tenant administrator:** settings, policies, users, groups, roles and API keys plus read access to campaigns/files/reports/audit. Real delivery remains separately delegable. -- **Administrator (legacy):** all tenant permissions for upgraded installations. -- **Access administrator:** membership and assignment management within delegation limits. -- **Campaign manager:** prepare, validate and build campaigns; no review approval or real delivery by default. -- **Reviewer:** inspect and approve prepared campaign messages. -- **Sender:** mock-test, queue, control, send, retry and reconcile prepared campaigns; can use/test approved mail profiles. -- **File manager:** managed file operations without campaign delivery rights. -- **Viewer:** read campaigns, recipients, files and reports. -- **Auditor:** read campaigns, recipient evidence, reports and audit records; export detailed evidence. - -## Default System Roles - -- **System owner:** `system:*`, protected. At least one active account must retain it. -- **System administrator:** all specific system permissions, editable and not protected. -- **System auditor:** read-only system registry/settings/governance/audit role, editable. - -## Delegation Ceiling - -For role definition, assignment and API-key creation: - -```text -requested scopes subset of actor delegateable scopes -``` - -Rules: - -1. Tenant roles may contain tenant scopes only. -2. System roles may contain system scopes only. -3. Definition rights and assignment rights are separate. -4. Group definition and group membership management are separate. -5. API-key scopes are intersected with the owner's current effective scopes on every request. -6. Suspended accounts, users, tenants or groups stop contributing access immediately. -7. Administrative updates are field-sensitive; a user with only status authority cannot change role assignments. - -## Campaign Ownership and ACLs - -A campaign has exactly one owner: - -```text -owner user OR owner group -``` - -Additional active shares may target users or groups with `read` or `write`. - -Resolution: - -- owner user: read and write; -- member of owner group: read and write; -- explicit read share: read; -- explicit write share: read and write; -- `tenant:*`: tenant-wide ACL bypass; -- ordinary campaign permission without ownership/share: no object access. - -ACLs do not add capabilities. A write share still needs the specific permission for update, validation, review, send, report, retry or reconciliation. - -## Sensitive Recipient Boundary - -Recipient-complete campaign JSON, message data and job detail require `recipients:read`. Recipient edits require `recipients:write`; exports require `recipients:export`; import is reserved for the dedicated recipient import/list workflow. - -## Files - -| Permission | Operations | -|---|---| -| `files:read` | list, search, inspect, resolve metadata | -| `files:download` | download file bytes and generated ZIP archives | -| `files:upload` | upload files and ZIP contents | -| `files:organize` | create folders, rename, move, copy and bulk rename | -| `files:share` | create/revoke file shares | -| `files:delete` | delete/hide files and folders subject to retention | -| `files:admin` | tenant-wide administration of user/group file spaces | - -## Mail Servers - -| Permission | Boundary | -|---|---| -| `mail_servers:read` | profile metadata and effective policy visibility | -| `mail_servers:use` | select an approved profile without reading secrets | -| `mail_servers:test` | run server-side connection tests | -| `mail_servers:write` | define/edit profiles in allowed scopes | -| `mail_servers:manage_credentials` | create/replace SMTP/IMAP secrets or campaign-level credentials where policy allows | - -Reusable encrypted profiles now exist. Effective usability is also constrained by hierarchical mail-profile policy, ownership, allowed/forced profile sets, credential inheritance mode, the lower-level override switch for that mode, and allow/deny patterns. - -## Sessions, API Keys and CSRF - -- Browser login creates an HttpOnly session cookie and a separate readable CSRF cookie. -- Unsafe cookie-authenticated requests require matching CSRF cookie/header and stored CSRF hash. -- API keys remain supported for CLI/automation and do not use browser CSRF. -- Login responses still expose a compatibility session token in the response body; the WebUI does not persist it. - -## Legacy Compatibility - -Runtime aliases remain only for names that are no longer canonical, including: - -```text -campaign:write -attachments:read -attachments:write -admin:users -admin:users:write -admin:api_keys:write -admin:settings -system:tenants:write -system:access:write -``` - -Canonical scopes are not widened by runtime alias expansion after migration. - -## Deferred Permission Families - -Add these only with their corresponding implemented features: - -```text -templates:* -address_books:* -recipient_lists:* -connectors:* -dsar:* -system:monitoring:read -system:backups:run -system:backups:restore -system:updates:apply -system:updates:rollback -``` - -A separate `retention:*` family is not currently canonical because retention is managed through system settings and tenant policy scopes. Add it only if retention operation duties need separation from general policy/settings administration. diff --git a/Repo-docs-RELEASE-CATALOG-WORKFLOW.md b/Repo-docs-RELEASE-CATALOG-WORKFLOW.md index 6505f79..51a86b2 100644 --- a/Repo-docs-RELEASE-CATALOG-WORKFLOW.md +++ b/Repo-docs-RELEASE-CATALOG-WORKFLOW.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/RELEASE_CATALOG_WORKFLOW.md`. > Origin: `repository`. @@ -39,7 +39,7 @@ Generate the signed catalog into `govoplan-web`: cd /mnt/DATA/git/govoplan-core KEY_DIR="$HOME/.config/govoplan/release-keys" scripts/publish-release-catalog.sh \ - --version 0.1.4 \ + --version \ --sequence 202607071340 \ --catalog-signing-key "release-key-1=$KEY_DIR/release-key-1.pem" \ --build-web @@ -89,9 +89,10 @@ https://govoplan.add-ideas.de/catalogs/v1/keyring.json ## Integrated Release Script `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 non-strict mode -by default; add `--strict-migration-audit` for stable releases after -`docs/migration-release-baselines.json` has been updated: +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 diff --git a/Repo-docs-RELEASE-DEPENDENCIES.md b/Repo-docs-RELEASE-DEPENDENCIES.md index d87630e..88735d9 100644 --- a/Repo-docs-RELEASE-DEPENDENCIES.md +++ b/Repo-docs-RELEASE-DEPENDENCIES.md @@ -1,4 +1,4 @@ - + > Mirrored from `/mnt/DATA/git/govoplan-core/docs/RELEASE_DEPENDENCIES.md`. > Origin: `repository`. @@ -7,9 +7,20 @@ --- # GovOPlaN Release Dependencies -Release installs must not depend on sibling checkout paths. Local development can keep editable installs and `file:` WebUI links, but release packaging should resolve modules from tagged git refs or from a package registry. +This document owns release package composition: Python package refs, WebUI +release package refs, release lockfiles, migration baselines, and the final +release checklist. -## Backend +Operator runtime configuration and module install/uninstall execution live in +`DEPLOYMENT_OPERATOR_GUIDE.md`. Catalog signatures, keyrings, replay +protection, and licensing live in `CATALOG_TRUST_AND_LICENSING.md`. Publishing +the public catalog through `govoplan-web` lives in `RELEASE_CATALOG_WORKFLOW.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: @@ -25,14 +36,17 @@ 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: +`.[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: +`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 @@ -46,452 +60,15 @@ 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 ``` -### PostgreSQL Release Check +## WebUI Packages -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: +Local development uses `webui/package.json`, which may point at sibling module +checkouts while active development is happening. -```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 -``` - -Use strict mode after the baseline file has been updated for the release: - -```bash -./.venv/bin/python scripts/release-migration-audit.py --strict -``` - -`scripts/push-release-tag.sh` runs the audit in non-strict mode by default so -release operators see the current migration heads before tagging. Pass -`--strict-migration-audit` when cutting a release whose migration baselines have -already been recorded, 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`. - -## Runtime Module Package Changes - -The admin module manager can hot-enable and hot-disable packages that are -already installed. It does not install or uninstall Python/npm packages from -inside the running server. - -For runtime package changes, create an operator install plan in Admin > System > -Modules. The module manager shows the trusted installer preflight status and -blocks unsafe uninstalls before the operator touches packages. - -Preflight from the server shell: - -```bash -govoplan-module-installer --format shell -``` - -Apply from a controlled operator shell while maintenance mode is active: - -```bash -govoplan-module-installer --apply --build-webui -``` - -For real install/uninstall work, prefer supervised mode with the deployment's -restart command and health endpoint: - -```bash -govoplan-module-installer \ - --supervise \ - --migrate \ - --build-webui \ - --health-url http://127.0.0.1:8000/health \ - --restart-command '' -``` - -To let the admin UI trigger package work without executing pip/npm inside a -FastAPI request, run the installer daemon in a separate operator shell. This is -the preferred development/early-production mode for now because the operator can -watch output, stop before queueing risky changes, and keep restart commands -deployment-specific: - -```bash -govoplan-module-installer \ - --daemon \ - --migrate \ - --build-webui \ - --database-backup-command 'pg_dump --format=custom "$GOVOPLAN_DATABASE_URL_PGTOOLS" > "$GOVOPLAN_DATABASE_BACKUP_PATH"' \ - --database-restore-check-command 'pg_restore --list "$GOVOPLAN_DATABASE_BACKUP_PATH" >/dev/null' \ - --database-restore-command 'pg_restore --clean --if-exists --dbname "$GOVOPLAN_DATABASE_URL_PGTOOLS" "$GOVOPLAN_DATABASE_BACKUP_PATH"' \ - --health-url http://127.0.0.1:8000/health \ - --restart-command '' -``` - -Admin > System > Modules can then queue the saved install plan as a supervised -request. Install rows can be planned directly from the approved package catalog; -uninstall rows are generated from installed, disabled modules so the Python -distribution and WebUI package names do not need to be typed by hand. The -daemon claims one queued request at a time and writes request/run records below -`runtime/module-installer`. For process-manager one-shot usage or tests, use -`--daemon-once`. The daemon also writes -`runtime/module-installer/daemon.status.json`; check it with: - -```bash -govoplan-module-installer --daemon-status --format json -``` - -The installer uses a runtime lock, snapshots `pip freeze` plus WebUI -`package.json`/`package-lock.json`, writes a run record below -`runtime/module-installer/runs`, and marks planned rows as applied only after -all commands succeed. When `--migrate` is used with a `sqlite:///` database URL, -the installer also snapshots the SQLite database with SQLite's backup API before -running migrations. For other database engines, pass external backup/restore -hooks: - -```bash -govoplan-module-installer \ - --supervise \ - --migrate \ - --database-backup-command 'pg_dump --format=custom "$GOVOPLAN_DATABASE_URL_PGTOOLS" > "$GOVOPLAN_DATABASE_BACKUP_PATH"' \ - --database-restore-check-command 'pg_restore --list "$GOVOPLAN_DATABASE_BACKUP_PATH" >/dev/null' \ - --database-restore-command 'pg_restore --clean --if-exists --dbname "$GOVOPLAN_DATABASE_URL_PGTOOLS" "$GOVOPLAN_DATABASE_BACKUP_PATH"' \ - --health-url http://127.0.0.1:8000/health \ - --restart-command '' -``` - -The backup command runs before migrations. The restore-check command validates -the produced backup artifact before migrations proceed, without restoring over -the live database. The restore command is stored in the run record and runs -during rollback unless an override is passed to `--rollback`. - -Supervised mode treats package command failure, migration failure, restart -failure, and health timeout as rollback triggers. It restores the Python/WebUI -package snapshots, re-runs the restart command when supplied, and restores the -saved install plan state so the operator can correct it. The supervisor must -run outside the FastAPI server process; the admin UI saves and validates plans -but does not mutate packages from an HTTP request. - -After a successful install plan, the installer adds installed modules to saved -startup state by default so the restarted server can discover and enable them. -After a successful uninstall plan, the installer removes uninstalled modules -from saved startup state by default. Use -`--no-activate-installed-modules` or -`--keep-uninstalled-modules-in-desired` only for staged rollout workflows that -will update module state separately. - -Uninstall is non-destructive by default. A planned uninstall row can set -`destroy_data: true` to request destructive module retirement. The module must -provide an automated retirement provider, and the installer snapshots the -database before dropping module-owned tables. For SQLite this uses the built-in -snapshot path; for PostgreSQL or another non-SQLite database, provide -`--database-backup-command`, `--database-restore-check-command`, and -`--database-restore-command`. If a destructive run fails during package removal, -the installer restores the database snapshot before returning the failed run -result; supervised restart/health failures also roll back through the normal -supervisor path. - -Package rollback is automatic. SQLite database rollback is automatic for -installer runs that used `--migrate` and captured a database snapshot. -Non-SQLite rollback is automatic when the run used -`--database-backup-command` and `--database-restore-command`; otherwise migrated -non-SQLite runs are blocked before package changes are applied. - -Rollback uses the saved run snapshot: - -```bash -govoplan-module-installer --rollback -govoplan-module-installer --rollback --database-restore-command '' -``` - -Database hook commands run with these environment variables: - -- `GOVOPLAN_INSTALLER_RUN_DIR`: the run snapshot directory -- `GOVOPLAN_DATABASE_URL`: the configured database URL -- `GOVOPLAN_DATABASE_URL_PGTOOLS`: the same PostgreSQL URL converted from - `postgresql+driver://` to `postgresql://` for `pg_dump`, `pg_restore`, and - `psql`; set only for PostgreSQL URLs -- `GOVOPLAN_DATABASE_BACKUP_PATH`: a suggested backup artifact path inside the - run directory -- `GOVOPLAN_DATABASE_BACKUP_METADATA`: optional JSON metadata path that backup - commands may write for operator diagnostics - -Avoid embedding secrets directly in commands; prefer environment variables, -service credentials, or deployment-local secret injection. - -Inspect installer history and lock state from the operator shell: - -```bash -govoplan-module-installer --list-runs --format json -govoplan-module-installer --show-run --format json -govoplan-module-installer --lock-status --format json -govoplan-module-installer --list-requests --format json -govoplan-module-installer --show-request --format json -govoplan-module-installer --cancel-request --format json -govoplan-module-installer --retry-request --format json -``` - -### Rollback Drill - -Before using the installer daemon in production, run the rollback drill in a -controlled shell from the core checkout: - -```bash -./.venv/bin/python scripts/module-installer-rollback-drill.py --format json -``` - -The drill uses temporary SQLite databases and simulated package commands. It -does not install or uninstall real packages. It exercises: - -- package command failure followed by supervised rollback -- migration failure with a SQLite database snapshot -- restart-command failure -- health timeout after restart -- destructive retirement executor failure with database rollback -- PostgreSQL-style backup, restore-check, and restore hooks -- daemon heartbeat, request queue claim/update, retry/cancel, and stale lock - detection/removal - -Keep the drill runtime for inspection with: - -```bash -./.venv/bin/python scripts/module-installer-rollback-drill.py \ - --keep-runtime \ - --runtime-root /srv/govoplan/drills/installer-rollback-$(date +%Y%m%d) -``` - -Each scenario writes an installer run record below -`//installer/runs//record.json`. For a successful -rollback drill, check: - -- `status` is `applied` only for the original package phase when rollback later - happens in the supervisor -- `rollback_status` is `rolled-back` when package/database snapshots were - restored -- `supervisor.status` is `rolled-back` for supervised package, migration, - restart, and health failures -- `supervisor.failure_reason` names the failing restart or health target -- `snapshot.database_backup` exists for migrated SQLite runs and destructive - retirement runs -- PostgreSQL hook drills write `database.external.backup`, - `restore-check.marker`, and `restore.marker` - -The PostgreSQL drill validates the hook interface without connecting to a live -database. In production, replace the documented example hooks with deployment -commands that target a disposable staging database first: - -```bash ---database-backup-command 'pg_dump --format=custom "$GOVOPLAN_DATABASE_URL_PGTOOLS" > "$GOVOPLAN_DATABASE_BACKUP_PATH"' ---database-restore-check-command 'pg_restore --list "$GOVOPLAN_DATABASE_BACKUP_PATH" >/dev/null' ---database-restore-command 'pg_restore --clean --if-exists --dbname "$GOVOPLAN_DATABASE_URL_PGTOOLS" "$GOVOPLAN_DATABASE_BACKUP_PATH"' -``` - -If a daemon request fails, inspect it and retry only after the underlying cause -is corrected: - -```bash -govoplan-module-installer --show-request --format json -govoplan-module-installer --show-run --format json -govoplan-module-installer --retry-request --format json -``` - -Cancel queued duplicate work before retrying: - -```bash -govoplan-module-installer --list-requests --format json -govoplan-module-installer --cancel-request --format json -``` - -For stale locks, first check the lock payload and confirm the recorded process -is no longer running on the host that owns the runtime directory: - -```bash -govoplan-module-installer --lock-status --format json -``` - -Only remove `runtime/module-installer/install.lock` after confirming there is -no active installer process and no package manager command still running. Then -rerun preflight before applying or retrying the request. - -Package catalogs can be local files or remote static resources, for example -served by `govoplan-web`. Set `GOVOPLAN_MODULE_PACKAGE_CATALOG` for a local file -or `GOVOPLAN_MODULE_PACKAGE_CATALOG_URL` for a remote catalog matching -`docs/module-package-catalog.example.json`; the admin UI will show those entries -and can save them into the install plan. This keeps the release approval -decision outside the running server while avoiding hand-typed package refs. -Remote catalogs can be cached for offline inspection: - -```bash -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 -``` - -Validate the catalog before handing it to operators: - -```bash -govoplan-module-installer --validate-package-catalog docs/module-package-catalog.example.json --format json -``` - -Release catalogs should be signed, channel-gated, expiring, and sequence -tracked. The supported signing format is an Ed25519 signature over the -canonical catalog JSON object with the `signature` and `signatures` fields -removed. Core accepts the legacy single `signature` field and the newer -`signatures` array used during key rotation. Sign a catalog with: - -```bash -govoplan-module-installer \ - --sign-package-catalog docs/module-package-catalog.example.json \ - --catalog-signing-key-id release-key-1 \ - --catalog-signing-private-key /path/to/ed25519-private.pem -``` - -Validate an approved release catalog with: - -```bash -govoplan-module-installer \ - --validate-package-catalog docs/module-package-catalog.example.json \ - --require-signed-catalog \ - --approved-catalog-channel stable \ - --catalog-trusted-key release-key-1= \ - --format json -``` - -For the admin UI/daemon path, configure the same policy through environment -variables: - -```bash -GOVOPLAN_MODULE_PACKAGE_CATALOG=/path/to/catalog.json -GOVOPLAN_MODULE_PACKAGE_CATALOG_REQUIRE_SIGNATURE=true -GOVOPLAN_MODULE_PACKAGE_CATALOG_APPROVED_CHANNELS=stable -GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS='{"release-key-1":""}' -GOVOPLAN_MODULE_PACKAGE_CATALOG_SEQUENCE_STATE=/srv/govoplan/runtime/catalog-sequences.json -GOVOPLAN_MODULE_PACKAGE_CATALOG_ENFORCE_SEQUENCE=true -``` - -Back up the sequence state with other runtime metadata. If it is lost or -corrupted, reconstruct the highest accepted sequence per channel from installer -run records or release records, never by lowering the sequence to admit an -older catalog. `docs/CATALOG_TRUST_AND_LICENSING.md` includes the recovery JSON -shape and reset procedure. - -Catalog module entries may include `artifact_integrity.python` and -`artifact_integrity.webui` metadata. Each artifact entry can declare: - -- `ref`: the exact Python or WebUI install ref expected in the plan -- `sha256`: the expected SHA-256 digest of the resolved artifact -- `path` or `artifact_path`: a local artifact path that the installer can hash - before applying the plan -- `sbom_url`: the published SBOM for the artifact -- `provenance_url`: the published provenance or attestation for the artifact -- `registry_identity` or `git_ref`: the expected registry or source identity - -When a saved install plan includes this metadata, installer preflight records -verification results in the run record under `preflight.artifact_integrity`. -Set `GOVOPLAN_MODULE_INSTALLER_REQUIRE_ARTIFACT_INTEGRITY=true` in production -to block package changes whose Python/WebUI artifacts are missing integrity -metadata or cannot be locally verified. - -Trusted keys can also be loaded from -`GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_FILE`. A URL-backed keyring is -supported for development and tightly controlled deployments through -`GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_URL` plus -`GOVOPLAN_MODULE_PACKAGE_CATALOG_TRUSTED_KEYS_CACHE`, but production systems -should pin trusted keys locally. - -Catalog entries can declare `license_features`. If -`GOVOPLAN_LICENSE_ENFORCEMENT=true`, core blocks planning catalog installs -whose required features are not present in the configured offline license: - -```bash -GOVOPLAN_LICENSE_FILE=/srv/govoplan/license.json -GOVOPLAN_LICENSE_TRUSTED_KEYS_FILE=/srv/govoplan/trust/license-keyring.json -GOVOPLAN_LICENSE_ENFORCEMENT=true -``` - -Operators can validate the imported license and required catalog entitlements: - -```bash -govoplan-module-installer \ - --validate-license /srv/govoplan/license.json \ - --license-trusted-key license-issuer-1="" \ - --require-trusted-license \ - --license-required-feature module.mail \ - --format json -``` - -Release or support operators can issue/renew signed offline licenses with -`govoplan-module-installer --issue-license`. Keep the signing private key off -the application server; the admin UI only displays public diagnostics such as -license id, subject, validity window, trusted key id, features, and missing -entitlements. - -See `docs/CATALOG_TRUST_AND_LICENSING.md` for key rotation, replay protection, -and licensing details. See `docs/RELEASE_CATALOG_WORKFLOW.md` for the concrete -release-machine workflow that generates signing keys and publishes signed -catalogs through `govoplan-web`. Unsigned catalogs remain usable for local -development when signature enforcement is off, but the admin UI labels them as -unsigned. - -Install rows must use tagged package/git refs or registry packages, not local -`file:` or workspace links. The installer daemon can run `npm install` and -`npm run build` for WebUI package changes; that is the supported path. Browser -remote bundles are still experimental and should be treated as a controlled -deployment option, not the normal install/uninstall mechanism. The target -design and follow-up slices are in `docs/REMOTE_WEBUI_BUNDLES.md`. - -Module manifests can declare core compatibility bounds and uninstall guard -providers. Preflight blocks incompatible manifest contracts/core versions, -active modules, desired startup state, protected modules, and active dependents. -Default uninstall is non-destructive: module data and schema remain dormant if -the package is removed. Persistent-data guards therefore warn by default instead -of requiring export/delete. A module that supports explicit data/schema -retirement should register a retirement provider. When `destroy_data` is set on -an uninstall plan row, that provider is allowed to destroy module-owned data -after the installer has captured a database snapshot; otherwise it is used only -for preflight reporting. - -## WebUI - -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: +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 @@ -500,16 +77,47 @@ 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`. +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`. -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: +### 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`. +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: @@ -538,17 +146,112 @@ Current tag-only module repositories: - `govoplan-xrechnung` - `govoplan-xta-osci` -### Release lockfile strategy +## PostgreSQL Release Check -The supported release composition currently is the full Multi Seal Mail 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. +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: -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. +```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 +``` + +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. +- `CATALOG_TRUST_AND_LICENSING.md`: catalog JSON shape, signature validation, + key rotation, sequence-state recovery, artifact integrity, and license + enforcement. +- `RELEASE_CATALOG_WORKFLOW.md`: release-machine steps for signing and + publishing `govoplan-web` catalog/keyring artifacts. +- `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`. -- Add separate release manifest/lockfile pairs only for module compositions that are shipped as their own products. +- 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 `RELEASE_CATALOG_WORKFLOW.md`. +- 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.