28 Commits
Author SHA1 Message Date
zemion 7c92565d9d Compose v0.1.35 resident permit configuration package
Dependency Audit / dependency-audit (push) Successful in 1m44s
Developer Meta-package Release / publish-package (push) Successful in 9s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m59s
2026-08-22 18:05:58 +02:00
zemion 23bfe5e2f8 Compose Core v0.1.34 and Mail v0.1.22
Dependency Audit / dependency-audit (push) Successful in 1m46s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m54s
Developer Meta-package Release / publish-package (push) Successful in 9s
2026-08-22 17:30:27 +02:00
zemion cf2f7f6890 Compose Core v0.1.33 and Connectors v0.1.22
Dependency Audit / dependency-audit (push) Successful in 1m44s
Deployment Installer / deployment-installer (push) Successful in 7s
Security Audit / security-audit (push) Failing after 12m8s
2026-08-22 16:31:58 +02:00
zemion 23b601bc0d build: compose external knowledge connector slice
Security Audit / security-audit (push) Failing after 12m23s
Dependency Audit / dependency-audit (push) Successful in 1m45s
Deployment Installer / deployment-installer (push) Successful in 6s
2026-08-22 14:44:55 +02:00
zemion 99c52c2153 build: compose governed Wiki vertical slice
Dependency Audit / dependency-audit (push) Successful in 1m44s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 12m20s
2026-08-22 13:33:31 +02:00
zemion ca68d98806 build: release ticket operations vertical slice
Dependency Audit / dependency-audit (push) Successful in 1m40s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m44s
2026-08-22 12:24:55 +02:00
zemion 79c4cb067a build: release localized documentation batch
Dependency Audit / dependency-audit (push) Successful in 1m39s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m41s
2026-08-22 08:45:51 +02:00
zemion cd498dc1d8 build: release seed documentation coverage batch
Dependency Audit / dependency-audit (push) Successful in 1m40s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m35s
2026-08-22 08:12:04 +02:00
zemion e07b3487e3 build: release documentation coverage batch
Dependency Audit / dependency-audit (push) Successful in 1m41s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m23s
2026-08-22 07:40:10 +02:00
zemion 72279de2c0 chore: sync Tasks and Postbox documentation releases
Dependency Audit / dependency-audit (push) Successful in 1m42s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m43s
2026-08-22 07:07:49 +02:00
zemion 88543ab115 chore: sync REST and SOAP reference releases
Dependency Audit / dependency-audit (push) Successful in 1m40s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m18s
2026-08-22 06:38:20 +02:00
zemion 81fe0f4680 chore: sync Docs German reference release
Dependency Audit / dependency-audit (push) Successful in 1m36s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m3s
2026-08-22 06:12:49 +02:00
zemion fe784cc562 chore: sync Mail German help release
Dependency Audit / dependency-audit (push) Successful in 1m36s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m0s
2026-08-22 05:45:12 +02:00
zemion 9fe7ad2cb4 chore: sync Mail POP3 legacy import release
Dependency Audit / dependency-audit (push) Successful in 1m31s
Deployment Installer / deployment-installer (push) Successful in 5s
Security Audit / security-audit (push) Failing after 11m3s
2026-08-22 05:09:01 +02:00
zemion f1eebd849c chore: sync Campaign portable transfer release
Dependency Audit / dependency-audit (push) Successful in 1m35s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 10m52s
2026-08-22 03:58:31 +02:00
zemion 4eb90079d5 chore: sync IDM governance releases
Dependency Audit / dependency-audit (push) Successful in 1m36s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 10m55s
Developer Meta-package Release / publish-package (push) Successful in 8s
2026-08-22 03:30:25 +02:00
zemion 628714804b chore: sync Campaign workflow hand-off releases
Dependency Audit / dependency-audit (push) Successful in 1m37s
Deployment Installer / deployment-installer (push) Successful in 7s
Security Audit / security-audit (push) Failing after 11m13s
2026-08-22 02:35:25 +02:00
zemion ff9fa37a88 chore: sync Campaign work assignment release
Dependency Audit / dependency-audit (push) Successful in 1m35s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 10m59s
2026-08-22 01:30:26 +02:00
zemion 4c7552f0dd chore: sync Campaign collaboration release
Dependency Audit / dependency-audit (push) Successful in 1m36s
Deployment Installer / deployment-installer (push) Successful in 7s
Security Audit / security-audit (push) Failing after 11m27s
2026-08-22 00:20:56 +02:00
zemion a20e02291d chore: sync Files folder sync release
Dependency Audit / dependency-audit (push) Successful in 1m39s
Deployment Installer / deployment-installer (push) Successful in 5s
Security Audit / security-audit (push) Failing after 11m32s
2026-08-21 23:08:35 +02:00
zemion b6452c6f53 chore: sync IDM relationship administration release
Security Audit / security-audit (push) Failing after 11m22s
Dependency Audit / dependency-audit (push) Successful in 1m41s
Deployment Installer / deployment-installer (push) Successful in 6s
2026-08-21 22:06:29 +02:00
zemion 75103d49af chore: sync Access credential help release
Dependency Audit / dependency-audit (push) Successful in 1m42s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m33s
2026-08-21 21:35:56 +02:00
zemion a60b8b0752 chore: sync datasource visibility release
Dependency Audit / dependency-audit (push) Successful in 1m43s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m27s
2026-08-21 20:52:01 +02:00
zemion 7f2f896a0f chore: sync governed tabular origins release
Dependency Audit / dependency-audit (push) Successful in 1m45s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 12m11s
2026-08-21 19:30:01 +02:00
zemion 60e04a324c chore: sync Dataflow reusable definitions release
Dependency Audit / dependency-audit (push) Successful in 1m45s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 12m1s
2026-08-21 18:44:09 +02:00
zemion 6a74e53a1c chore: recognize authored help contexts and sync packages
Dependency Audit / dependency-audit (push) Successful in 1m44s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m33s
2026-08-21 17:36:24 +02:00
zemion 6517b6ac27 chore: synchronize autonomous slice release evidence
Dependency Audit / dependency-audit (push) Successful in 1m43s
Deployment Installer / deployment-installer (push) Successful in 7s
Security Audit / security-audit (push) Failing after 11m29s
2026-08-21 16:35:21 +02:00
zemion 26a66814b4 test(privacy): enforce workspace DSAR coverage
Dependency Audit / dependency-audit (push) Successful in 1m45s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Failing after 11m42s
2026-08-21 13:59:56 +02:00
15 changed files with 1235 additions and 99 deletions
@@ -0,0 +1,87 @@
# DSAR Provider Coverage
This generated matrix is enforced by `tools/checks/check-dsar-coverage.py`.
A migration-owning module must register and document its canonical DSAR provider.
Every other active module requires a reviewed explanation of why it owns no
persistent subject-data store. Adding a migration invalidates that explanation.
- Active modules: 68
- Registered and documented DSAR providers: 48
- Reviewed no-store rationales: 20
- Unexplained coverage gaps: 0
| Module | Repository | Persistence | Coverage | Rationale |
| --- | --- | --- | --- | --- |
| `access` | `govoplan-access` | Migration-owned | Provider | Provider `privacy.dsar.access` is registered and documented. |
| `addresses` | `govoplan-addresses` | Migration-owned | Provider | Provider `privacy.dsar.addresses` is registered and documented. |
| `admin` | `govoplan-admin` | Migration-owned | Provider | Provider `privacy.dsar.admin` is registered and documented. |
| `approvals` | `govoplan-approvals` | Migration-owned | Provider | Provider `privacy.dsar.approvals` is registered and documented. |
| `assets` | `govoplan-assets` | No module migration | Reviewed no-store rationale | Contract-only module: asset persistence and lifecycle APIs are not implemented; reassess before adding a migration-owned store. |
| `audit` | `govoplan-audit` | Migration-owned | Provider | Provider `privacy.dsar.audit` is registered and documented. |
| `booking` | `govoplan-booking` | No module migration | Reviewed no-store rationale | Contract-only module: booking persistence and reservation workflows are not implemented; reassess before adding a migration-owned store. |
| `calendar` | `govoplan-calendar` | Migration-owned | Provider | Provider `privacy.dsar.calendar` is registered and documented. |
| `campaigns` | `govoplan-campaign` | Migration-owned | Provider | Provider `privacy.dsar.campaigns` is registered and documented. |
| `cases` | `govoplan-cases` | Migration-owned | Provider | Provider `privacy.dsar.cases` is registered and documented. |
| `certificates` | `govoplan-certificates` | No module migration | Reviewed no-store rationale | Contract-only module: certificate issuance and revocation persistence are not implemented; reassess before adding a migration-owned store. |
| `committee` | `govoplan-committee` | Migration-owned | Provider | Provider `privacy.dsar.committee` is registered and documented. |
| `connectors` | `govoplan-connectors` | Migration-owned | Provider | Provider `privacy.dsar.connectors` is registered and documented. |
| `consultation` | `govoplan-consultation` | No module migration | Reviewed no-store rationale | Contract-only module: consultation submissions and evaluation persistence are not implemented; reassess before adding a migration-owned store. |
| `contracts` | `govoplan-contracts` | No module migration | Reviewed no-store rationale | Contract-only module: contract, amendment, and obligation persistence are not implemented; reassess before adding a migration-owned store. |
| `dashboard` | `govoplan-dashboard` | Migration-owned | Provider | Provider `privacy.dsar.dashboard` is registered and documented. |
| `dataflow` | `govoplan-dataflow` | Migration-owned | Provider | Provider `privacy.dsar.dataflow` is registered and documented. |
| `datasources` | `govoplan-datasources` | Migration-owned | Provider | Provider `privacy.dsar.datasources` is registered and documented. |
| `decisions` | `govoplan-decisions` | Migration-owned | Provider | Provider `privacy.dsar.decisions` is registered and documented. |
| `dist_lists` | `govoplan-dist-lists` | Migration-owned | Provider | Provider `privacy.dsar.dist_lists` is registered and documented. |
| `docs` | `govoplan-docs` | Migration-owned | Provider | Provider `privacy.dsar.docs` is registered and documented. |
| `encryption` | `govoplan-encryption` | Migration-owned | Provider | Provider `privacy.dsar.encryption` is registered and documented. |
| `evaluation` | `govoplan-evaluation` | No module migration | Reviewed no-store rationale | Contract-only module: evaluation runs, responses, and scores are not persisted; reassess before adding a migration-owned store. |
| `facilities` | `govoplan-facilities` | No module migration | Reviewed no-store rationale | Contract-only module: facility and maintenance persistence are not implemented; reassess before adding a migration-owned store. |
| `files` | `govoplan-files` | Migration-owned | Provider | Provider `privacy.dsar.files` is registered and documented. |
| `forms` | `govoplan-forms` | Migration-owned | Provider | Provider `privacy.dsar.forms` is registered and documented. |
| `forms_runtime` | `govoplan-forms-runtime` | Migration-owned | Provider | Provider `privacy.dsar.forms_runtime` is registered and documented. |
| `grants` | `govoplan-grants` | No module migration | Reviewed no-store rationale | Contract-only module: grant applications, awards, and monitoring are not persisted; reassess before adding a migration-owned store. |
| `helpdesk` | `govoplan-helpdesk` | Migration-owned | Provider | Provider `privacy.dsar.helpdesk` is registered and documented. |
| `identity` | `govoplan-identity` | Migration-owned | Provider | Provider `privacy.dsar.identity` is registered and documented. |
| `identity_trust` | `govoplan-identity-trust` | Migration-owned | Provider | Provider `privacy.dsar.identity_trust` is registered and documented. |
| `idm` | `govoplan-idm` | Migration-owned | Provider | Provider `privacy.dsar.idm` is registered and documented. |
| `inspections` | `govoplan-inspections` | No module migration | Reviewed no-store rationale | Contract-only module: inspections, findings, and measures are not persisted; reassess before adding a migration-owned store. |
| `learning` | `govoplan-learning` | No module migration | Reviewed no-store rationale | Contract-only module: learning offers, enrollment, and completion are not persisted; reassess before adding a migration-owned store. |
| `mail` | `govoplan-mail` | Migration-owned | Provider | Provider `privacy.dsar.mail` is registered and documented. |
| `mandates` | `govoplan-mandates` | Migration-owned | Provider | Provider `privacy.dsar.mandates` is registered and documented. |
| `notifications` | `govoplan-notifications` | Migration-owned | Provider | Provider `privacy.dsar.notifications` is registered and documented. |
| `ops` | `govoplan-ops` | No module migration | Reviewed no-store rationale | Projection-only module: Ops reads bounded platform and provider status; durable recovery evidence remains owned by Core and domain modules. |
| `organizations` | `govoplan-organizations` | Migration-owned | Provider | Provider `privacy.dsar.organizations` is registered and documented. |
| `parties` | `govoplan-parties` | Migration-owned | Provider | Provider `privacy.dsar.parties` is registered and documented. |
| `payments` | `govoplan-payments` | Migration-owned | Provider | Provider `privacy.dsar.payments` is registered and documented. |
| `permits` | `govoplan-permits` | No module migration | Reviewed no-store rationale | Contract-only module: permit applications, assessments, and decisions are not persisted; reassess before adding a migration-owned store. |
| `policy` | `govoplan-policy` | Migration-owned | Provider | Provider `privacy.dsar.policy` is registered and documented. |
| `poll` | `govoplan-poll` | Migration-owned | Provider | Provider `privacy.dsar.poll` is registered and documented. |
| `portal` | `govoplan-portal` | No module migration | Reviewed no-store rationale | Projection-only module: Portal stores no applicant records; Services, Forms Runtime, Cases, and Postbox own and export authoritative subject data. |
| `postbox` | `govoplan-postbox` | Migration-owned | Provider | Provider `privacy.dsar.postbox` is registered and documented. |
| `procurement` | `govoplan-procurement` | No module migration | Reviewed no-store rationale | Contract-only module: procurement procedures, tenders, and awards are not persisted; reassess before adding a migration-owned store. |
| `projects` | `govoplan-projects` | Migration-owned | Provider | Provider `privacy.dsar.projects` is registered and documented. |
| `quick_access` | `govoplan-quick-access` | Migration-owned | Provider | Provider `privacy.dsar.quick_access` is registered and documented. |
| `records` | `govoplan-records` | Migration-owned | Provider | Provider `privacy.dsar.records` is registered and documented. |
| `reporting` | `govoplan-reporting` | Migration-owned | Provider | Provider `privacy.dsar.reporting` is registered and documented. |
| `resources` | `govoplan-resources` | No module migration | Reviewed no-store rationale | Contract-only module: resource catalog and allocation persistence are not implemented; reassess before adding a migration-owned store. |
| `rest` | `govoplan-rest` | No module migration | Reviewed no-store rationale | Transport-only module: REST binds explicitly published functions and owns no domain or subject-data store. |
| `risk_compliance` | `govoplan-risk-compliance` | Migration-owned | Provider | Provider `privacy.dsar.risk_compliance` is registered and documented. |
| `scheduling` | `govoplan-scheduling` | Migration-owned | Provider | Provider `privacy.dsar.scheduling` is registered and documented. |
| `search` | `govoplan-search` | Migration-owned | Provider | Provider `privacy.dsar.search` is registered and documented. |
| `services` | `govoplan-services` | Migration-owned | Provider | Provider `privacy.dsar.services` is registered and documented. |
| `soap` | `govoplan-soap` | No module migration | Reviewed no-store rationale | Transport-only module: SOAP binds explicitly published operations and owns no domain or subject-data store. |
| `tasks` | `govoplan-tasks` | Migration-owned | Provider | Provider `privacy.dsar.tasks` is registered and documented. |
| `templates` | `govoplan-templates` | Migration-owned | Provider | Provider `privacy.dsar.templates` is registered and documented. |
| `tenancy` | `govoplan-tenancy` | No module migration | Reviewed no-store rationale | Orchestration module: tenant lifecycle and settings use Core-owned storage; Access covers account and membership subject data. |
| `tickets` | `govoplan-tickets` | Migration-owned | Provider | Provider `privacy.dsar.tickets` is registered and documented. |
| `transparency` | `govoplan-transparency` | No module migration | Reviewed no-store rationale | Contract-only module: requests, disclosure reviews, and publications are not persisted; reassess before adding a migration-owned store. |
| `views` | `govoplan-views` | Migration-owned | Provider | Provider `privacy.dsar.views` is registered and documented. |
| `voting` | `govoplan-voting` | Migration-owned | Provider | Provider `privacy.dsar.voting` is registered and documented. |
| `wiki` | `govoplan-wiki` | Migration-owned | Provider | Provider `privacy.dsar.wiki` is registered and documented. |
| `workflow` | `govoplan-workflow` | No module migration | Reviewed no-store rationale | Presentation-only module: Workflow edits and projects Workflow Engine state; Workflow Engine owns persistence and DSAR coverage. |
| `workflow_engine` | `govoplan-workflow-engine` | Migration-owned | Provider | Provider `privacy.dsar.workflow_engine` is registered and documented. |
Provider search, export minimization, retention, and erasure behavior remains
documented and tested by each owning module. This matrix verifies adoption and
ownership coverage; Core continues to test disabled providers, partial failure,
retry, authorization evidence, and horizontally coordinated execution.
@@ -109,7 +109,9 @@ semantics as authenticated navigation routes.
| `/scheduling/public/:requestId/:token` | Scheduling | Public signed token | Public participation | Scheduling #8 complete in `c17cbda` |
| `/search` | Search | `search:result:read` | Keyboard-first global/context overlay and full results fallback | Search pattern migration complete in [Search #4](https://git.add-ideas.de/GovOPlaN/govoplan-search/issues/4); durable evidence in `govoplan-search/docs/INTERFACE_PATTERN_MIGRATION.md` |
| `/templates` | Templates | Template read/write/publish/render/admin | Governed library, immutable-revision editor, compatibility preview, and render evidence | Templates pattern migration complete in [Templates #5](https://git.add-ideas.de/GovOPlaN/govoplan-templates/issues/5), commit `72fafa2` |
| `/tickets` | Tickets | `tickets:ticket:read` | Governed operational queue/detail workspace with distinct report, triage, assignment, resolution, comment, reference and removal boundaries | Tickets vertical slice and pattern migration complete in [Tickets #1](https://git.add-ideas.de/GovOPlaN/govoplan-tickets/issues/1), release `v0.1.20` |
| `/voting` | Voting | `voting:ballot:read` | Governed ballot workspace | Voting pattern migration complete in [Voting #1](https://git.add-ideas.de/GovOPlaN/govoplan-voting/issues/1), commit `2625990` |
| `/wiki` | Wiki | `wiki:page:read` | Governed space-tree/page workspace with draft editing, immutable revision comparison, publication, comments, typed references and archival | Native Wiki vertical slice and pattern migration implemented in [Wiki #1](https://git.add-ideas.de/GovOPlaN/govoplan-wiki/issues/1), release `v0.1.20` |
| `/workflow` | Workflow | Definition read or instance admin | Native BPMN editor, governed revision actions and execution evidence | Workflow pattern migration complete in [Workflow #15](https://git.add-ideas.de/GovOPlaN/govoplan-workflow/issues/15); durable evidence in `govoplan-workflow/docs/INTERFACE_PATTERN_MIGRATION.md` |
## Final Module Closure Evidence
@@ -323,8 +325,8 @@ The generated manifest snapshot reports no WebUI package for:
`govoplan-learning`, `govoplan-mandates`, `govoplan-parties`,
`govoplan-permits`, `govoplan-poll`, `govoplan-procurement`,
`govoplan-records`, `govoplan-resources`, `govoplan-rest`,
`govoplan-services`, `govoplan-soap`, `govoplan-tickets`,
`govoplan-transparency`, `govoplan-wiki`, and `govoplan-workflow-engine`.
`govoplan-services`, `govoplan-soap`, `govoplan-transparency`, and
`govoplan-workflow-engine`.
Tenancy does provide composed administration surfaces despite having no direct
route. This section is only negative package evidence; connector-only,
+44 -44
View File
@@ -4,85 +4,85 @@ build-backend = "setuptools.build_meta"
[project]
name = "govoplan"
version = "0.1.18"
version = "0.1.35"
description = "Developer convenience package for a versioned GovOPlaN composition"
readme = "README.md"
requires-python = ">=3.12"
license = { text = "AGPL-3.0-or-later" }
dependencies = [
"govoplan-core[server]==0.1.18",
"govoplan-core[server]==0.1.35",
"govoplan-tenancy==0.1.18",
"govoplan-organizations==0.1.18",
"govoplan-identity==0.1.18",
"govoplan-idm==0.1.18",
"govoplan-access==0.1.18",
"govoplan-admin==0.1.18",
"govoplan-policy==0.1.18",
"govoplan-audit==0.1.18",
"govoplan-idm==0.1.20",
"govoplan-access==0.1.20",
"govoplan-admin==0.1.19",
"govoplan-policy==0.1.20",
"govoplan-audit==0.1.19",
"govoplan-dashboard==0.1.18",
"govoplan-files==0.1.18",
"govoplan-mail==0.1.18",
"govoplan-campaign==0.1.18",
"govoplan-files==0.1.20",
"govoplan-mail==0.1.22",
"govoplan-campaign==0.1.24",
"govoplan-calendar==0.1.18",
"govoplan-docs==0.1.18",
"govoplan-ops==0.1.18",
"govoplan-docs==0.1.20",
"govoplan-ops==0.1.19",
]
[project.optional-dependencies]
full = [
"govoplan-addresses==0.1.18",
"govoplan-approvals==0.1.18",
"govoplan-assets==0.1.18",
"govoplan-booking==0.1.18",
"govoplan-cases==0.1.18",
"govoplan-certificates==0.1.18",
"govoplan-assets==0.1.19",
"govoplan-booking==0.1.19",
"govoplan-cases==0.1.20",
"govoplan-certificates==0.1.19",
"govoplan-committee==0.1.18",
"govoplan-connectors==0.1.18",
"govoplan-consultation==0.1.18",
"govoplan-contracts==0.1.18",
"govoplan-dataflow==0.1.18",
"govoplan-datasources==0.1.18",
"govoplan-connectors==0.1.22",
"govoplan-consultation==0.1.19",
"govoplan-contracts==0.1.19",
"govoplan-dataflow==0.1.20",
"govoplan-datasources==0.1.20",
"govoplan-decisions==0.1.18",
"govoplan-dist-lists==0.1.18",
"govoplan-encryption==0.1.18",
"govoplan-evaluation==0.1.18",
"govoplan-facilities==0.1.18",
"govoplan-forms==0.1.18",
"govoplan-evaluation==0.1.19",
"govoplan-facilities==0.1.19",
"govoplan-forms==0.1.20",
"govoplan-forms-runtime==0.1.18",
"govoplan-grants==0.1.18",
"govoplan-helpdesk==0.1.18",
"govoplan-grants==0.1.19",
"govoplan-helpdesk==0.1.20",
"govoplan-identity-trust==0.1.18",
"govoplan-inspections==0.1.18",
"govoplan-learning==0.1.18",
"govoplan-inspections==0.1.19",
"govoplan-learning==0.1.19",
"govoplan-mandates==0.1.18",
"govoplan-notifications==0.1.18",
"govoplan-parties==0.1.18",
"govoplan-payments==0.1.20",
"govoplan-permits==0.1.18",
"govoplan-poll==0.1.18",
"govoplan-portal==0.1.18",
"govoplan-postbox==0.1.18",
"govoplan-procurement==0.1.18",
"govoplan-permits==0.1.19",
"govoplan-poll==0.1.19",
"govoplan-portal==0.1.19",
"govoplan-postbox==0.1.19",
"govoplan-procurement==0.1.19",
"govoplan-projects==0.1.18",
"govoplan-quick-access==0.1.18",
"govoplan-quick-access==0.1.19",
"govoplan-records==0.1.19",
"govoplan-reporting==0.1.18",
"govoplan-resources==0.1.18",
"govoplan-rest==0.1.18",
"govoplan-resources==0.1.19",
"govoplan-rest==0.1.19",
"govoplan-risk-compliance==0.1.18",
"govoplan-scheduling==0.1.18",
"govoplan-search==0.1.18",
"govoplan-services==0.1.18",
"govoplan-soap==0.1.18",
"govoplan-tasks==0.1.19",
"govoplan-soap==0.1.19",
"govoplan-tasks==0.1.20",
"govoplan-templates==0.1.18",
"govoplan-tickets==0.1.18",
"govoplan-transparency==0.1.18",
"govoplan-views==0.1.18",
"govoplan-tickets==0.1.20",
"govoplan-transparency==0.1.19",
"govoplan-views==0.1.19",
"govoplan-voting==0.1.18",
"govoplan-wiki==0.1.18",
"govoplan-workflow==0.1.18",
"govoplan-workflow-engine==0.1.18",
"govoplan-wiki==0.1.20",
"govoplan-workflow==0.1.21",
"govoplan-workflow-engine==0.1.19",
]
[project.urls]
@@ -17,6 +17,26 @@ human review handoff, formal outcome, Postbox delivery channel, and Records
filing/retention target. Generic permit wording is no longer acceptance
evidence for this package.
The package is now executable rather than metadata-only. Its Access fragments
create the bounded resident-permit clerk role, collect only the tenant-local
responsibility group key and name, create that group, and bind the role. The
Forms-owned fragment carries a digest-bound German-reference application schema
and imports it as a tenant-local draft with source provenance. Reapplying the
same source digest is a no-op; replacing an unrelated local definition remains
blocked unless the reviewed package explicitly selects a new revision. Normal
Forms review and publication are still required before the definition can serve
new applications. The Workflow Engine-owned fragment materializes and activates
the tenant review baseline, resolves the chosen responsibility group into each
human handoff, and preserves the evidence, decision, and EUR 30 payment-review
steps as a replay-safe contributed definition.
Services, Cases, Payments, Tasks, and the optional delivery and Records modules
already execute the pinned journey through their runtime
contracts, but their reusable configuration fragments are not yet claimed by
this package. Until those module-owned configuration providers are added, the
package preflight deliberately distinguishes the installed runtime composition
from the Access, Forms, and Workflow configurations it can currently materialize.
An installed Forms and Forms Runtime pair adds an alternative governed entry
path before case/workflow handoff:
@@ -76,3 +96,11 @@ and Decision revision filing. Target-environment browser accessibility,
production identity and delivery, a named archive profile, and recovery evidence
are still required before this product package may claim `reference_ready`
maturity.
The generic package orchestrator stops at the first provider apply or health
blocker. Access and Forms may commit in separate provider transactions, so the
operator must retain the reviewed pre-apply database snapshot until verification
is complete. The Admin result reports no-op, snapshot-required, or partial-apply
recovery state and never describes this as atomic cross-module undo. Exported
fragments carry source/module/operator/scope provenance; supplied values and
credentials are not serialized into that provenance.
@@ -8,36 +8,366 @@
"category": "institutional-governance",
"license": "AGPL-3.0-or-later",
"required_modules": [
{"module_id": "access"},
{"module_id": "audit"},
{"module_id": "cases"},
{"module_id": "decisions"},
{"module_id": "forms"},
{"module_id": "forms_runtime"},
{"module_id": "mandates"},
{"module_id": "parties"},
{"module_id": "payments"},
{"module_id": "policy"},
{"module_id": "portal"},
{"module_id": "services"}
{"module_id": "services"},
{"module_id": "tasks"},
{"module_id": "workflow_engine"}
],
"required_capabilities": [
"access.configuration",
"cases.party_context",
"cases.service_intake",
"decisions.registry",
"forms.configuration",
"forms.definitions",
"mandates.resolver",
"parties.resolver",
"payments.requests",
"portal.service_directory",
"services.availability",
"services.definitions"
"services.definitions",
"workflow.configuration"
],
"optional_modules": [
{"module_id": "approvals"},
{"module_id": "committee"},
{"module_id": "files"},
{"module_id": "forms"},
{"module_id": "forms_runtime"},
{"module_id": "postbox"},
{"module_id": "records"},
{"module_id": "search"},
{"module_id": "tasks"},
{"module_id": "workflow_engine"}
{"module_id": "search"}
],
"data_requirements": [
{
"key": "responsible_group_slug",
"label": "Responsible permit group key",
"data_type": "string",
"required": true,
"secret": false,
"description": "Tenant-local stable key for the group that reviews resident parking permit applications."
},
{
"key": "responsible_group_name",
"label": "Responsible permit group name",
"data_type": "string",
"required": true,
"secret": false,
"description": "Human-readable tenant-local name shown for the responsible permit group."
}
],
"fragments": [
{
"module_id": "access",
"fragment_type": "roles",
"fragment_id": "resident-parking-permit-clerk",
"payload": {
"items": [
{
"slug": "resident-parking-permit-clerk",
"name": "Resident parking permit clerk",
"description": "Reviews resident parking permit submissions, workflow handoffs, cases, decisions, and payment evidence.",
"permissions": [
"cases:case:read",
"cases:case:create",
"cases:case:update",
"decisions:decision:read",
"decisions:decision:write",
"forms:definition:read",
"forms_runtime:workspace:read",
"forms_runtime:workspace:write",
"payments:payment:read",
"payments:payment:write",
"tasks:item:read",
"tasks:item:write",
"workflow:definition:read",
"workflow:instance:read",
"workflow:instance:start",
"workflow:instance:transition"
]
}
]
}
},
{
"module_id": "access",
"fragment_type": "groups",
"fragment_id": "resident-parking-permit-responsibility",
"payload": {
"items": [
{
"slug": {"$data": "responsible_group_slug"},
"name": {"$data": "responsible_group_name"},
"description": "Tenant-local responsibility group for the resident parking permit reference journey."
}
]
}
},
{
"module_id": "access",
"fragment_type": "group_role_assignments",
"fragment_id": "resident-parking-permit-clerk-assignment",
"payload": {
"items": [
{
"group": {"$data": "responsible_group_slug"},
"role": "resident-parking-permit-clerk"
}
]
}
},
{
"module_id": "forms",
"fragment_type": "definition",
"fragment_id": "resident-parking-permit-application",
"payload": {
"on_conflict": "new_revision",
"change_reason": "Install the reviewed resident parking permit reference form.",
"fragment": {
"kind": "govoplan.forms.definition",
"contract_version": "0.1.0",
"definition": {
"reference": {
"kind": "form",
"owner_module": "forms",
"object_id": "resident-parking-permit-application",
"tenant_id": "reference-package",
"version": "3",
"valid_at": null,
"label": null
},
"key": "resident-parking-permit-application",
"temporal": {
"revision": "3",
"valid_from": null,
"valid_to": null,
"recorded_at": "2026-08-22T00:00:00+00:00",
"superseded_at": null,
"change_reason": "Reference package revision."
},
"title": "Resident parking permit",
"description": "Apply for a resident parking permit through a digital or assisted channel.",
"fields": [
{
"key": "applicant_name",
"label": "Name",
"value_type": "text",
"required": true,
"help_text": null,
"options": [],
"constraints": {"min_length": 2, "max_length": 200},
"default_value": null
},
{
"key": "applicant_email",
"label": "Email",
"value_type": "text",
"required": true,
"help_text": null,
"options": [],
"constraints": {"format": "email"},
"default_value": null
},
{
"key": "residence_address",
"label": "Primary residence",
"value_type": "text",
"required": true,
"help_text": null,
"options": [],
"constraints": {"max_length": 500},
"default_value": null
},
{
"key": "licence_plate",
"label": "Licence plate",
"value_type": "text",
"required": true,
"help_text": null,
"options": [],
"constraints": {"max_length": 20},
"default_value": null
}
],
"publication_state": "published",
"allow_drafts": true,
"max_attachments": 4,
"signature_requirement": "none",
"policy_refs": [
"law:resident-parking-permit",
"records:resident-parking-permit"
],
"handoff_kinds": ["case", "workflow"],
"metadata": {},
"pages": [
{
"key": "application",
"title": "Application",
"description": null,
"sections": [
{
"key": "applicant-and-vehicle",
"title": "Applicant and vehicle",
"description": null,
"field_keys": [
"applicant_name",
"applicant_email",
"residence_address",
"licence_plate"
]
}
]
}
],
"localizations": [
{
"locale": "de",
"title": "Anwohnerparkausweis beantragen",
"description": "Einen Anwohnerparkausweis digital oder mit Unterstützung beantragen.",
"field_labels": {
"applicant_name": "Name",
"applicant_email": "E-Mail-Adresse",
"residence_address": "Hauptwohnsitz",
"licence_plate": "Kennzeichen"
},
"field_help_texts": {},
"option_labels": {},
"page_titles": {"application": "Antrag"},
"section_titles": {
"applicant-and-vehicle": "Antragstellende Person und Fahrzeug"
}
}
],
"fallback_locale": "de"
},
"definition_sha256": "7dc108002d532c07e5e7f3b14029a9d4deb3836ebb65d97fb6b51166a70e0ed4",
"provenance": {
"owner_module": "forms",
"tenant_id": "reference-package",
"form_id": "resident-parking-permit-application",
"revision": "3",
"exported_at": "2026-08-22T12:00:00+00:00",
"exported_by": "GovOPlaN reference package"
}
}
}
},
{
"module_id": "workflow_engine",
"fragment_type": "workflow_definitions",
"fragment_id": "resident-parking-permit-workflow",
"payload": {
"schema_version": 1,
"origin_module_id": "configuration_package.service_to_decision",
"origin_module_version": "0.1.0",
"items": [
{
"definition_key": "resident-parking-permit-review",
"name": "Resident parking permit review",
"description": "Review evidence, record the formal decision, and verify payment evidence for the resident parking permit reference journey.",
"scope_type": "tenant",
"allow_start": true,
"allow_reuse": true,
"allow_automation": false,
"execution_mode": "guided",
"activate_on_install": true,
"graph": {
"schema_version": 1,
"nodes": [
{
"id": "start",
"type": "workflow.start.manual",
"label": "Application received",
"config": {"input_schema_ref": "form:resident-parking-permit-application"}
},
{
"id": "review-evidence",
"type": "workflow.review",
"label": "Review application evidence",
"config": {
"title": "Review resident parking permit evidence",
"reviewer": {
"kind": "group",
"id": {"$data": "responsible_group_slug"},
"label": {"$data": "responsible_group_name"}
},
"due_after": "P14D",
"required_evidence": [
"identity",
"primary_residence",
"vehicle_registration"
],
"view_surface_ids": []
}
},
{
"id": "record-decision",
"type": "workflow.activity",
"label": "Record formal decision",
"config": {
"title": "Record the resident parking permit decision",
"instructions": "Record the operative result, reasoning, legal basis, remedy, and exact evidence references through the Decisions capability.",
"assignee": {
"kind": "group",
"id": {"$data": "responsible_group_slug"},
"label": {"$data": "responsible_group_name"}
},
"due_after": "P7D",
"view_surface_ids": []
}
},
{
"id": "verify-payment",
"type": "workflow.activity",
"label": "Verify payment evidence",
"config": {
"title": "Verify the resident parking permit fee",
"instructions": "Verify the EUR 30.00 obligation, immutable receipt evidence, currency, amount, and transaction reference before completion.",
"assignee": {
"kind": "group",
"id": {"$data": "responsible_group_slug"},
"label": {"$data": "responsible_group_name"}
},
"due_after": "P14D",
"view_surface_ids": []
}
},
{
"id": "completed",
"type": "workflow.end.completed",
"label": "Permit journey complete",
"config": {"output_mapping": {}}
}
],
"edges": [
{"id": "start-review", "source": "start", "target": "review-evidence"},
{"id": "review-decision", "source": "review-evidence", "source_port": "approved", "target": "record-decision"},
{"id": "decision-payment", "source": "record-decision", "target": "verify-payment"},
{"id": "payment-completed", "source": "verify-payment", "target": "completed"}
],
"metadata": {
"reference_journey": "resident-parking-permit",
"locale": "de-DE",
"payment_amount_minor": 3000,
"payment_currency": "EUR"
}
},
"metadata": {
"reference_package": "product.service-to-decision",
"form_id": "resident-parking-permit-application"
}
}
]
}
}
],
"evidence": [
{
+10 -10
View File
@@ -4,15 +4,15 @@
govoplan-tenancy @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-tenancy.git@v0.1.18
govoplan-organizations @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-organizations.git@v0.1.18
govoplan-identity @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-identity.git@v0.1.18
govoplan-idm @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git@v0.1.18
govoplan-access @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git@v0.1.18
govoplan-admin @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git@v0.1.18
govoplan-policy @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git@v0.1.18
govoplan-audit @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git@v0.1.18
govoplan-idm @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-idm.git@v0.1.20
govoplan-access @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-access.git@v0.1.20
govoplan-admin @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-admin.git@v0.1.19
govoplan-policy @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-policy.git@v0.1.20
govoplan-audit @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-audit.git@v0.1.19
govoplan-dashboard @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-dashboard.git@v0.1.18
govoplan-files @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git@v0.1.18
govoplan-mail @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git@v0.1.18
govoplan-campaign @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git@v0.1.18
govoplan-files @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-files.git@v0.1.20
govoplan-mail @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-mail.git@v0.1.22
govoplan-campaign @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-campaign.git@v0.1.24
govoplan-calendar @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-calendar.git@v0.1.18
govoplan-docs @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git@v0.1.18
govoplan-ops @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git@v0.1.18
govoplan-docs @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-docs.git@v0.1.20
govoplan-ops @ git+ssh://git@git.add-ideas.de/GovOPlaN/govoplan-ops.git@v0.1.19
+167 -1
View File
@@ -5,9 +5,17 @@ import json
from pathlib import Path
import unittest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from govoplan_core.core.configuration_packages import (
ConfigurationApplyResult,
ConfigurationExportResult,
ConfigurationPackageManifest,
ConfigurationPlanItem,
ConfigurationPreflightContext,
ConfigurationPreflightResult,
ConfigurationProviderDescription,
configuration_package_claim_issues,
dry_run_configuration_package,
)
@@ -54,10 +62,19 @@ class ConfigurationPackageArtifactTests(unittest.TestCase):
f"Missing repository for {requirement.module_id}",
)
provider_module_ids = tuple(
sorted({fragment.module_id for fragment in manifest.fragments})
)
providers = tuple(_ArtifactProvider(module_id) for module_id in provider_module_ids)
supplied_data = {
str(item["key"]): _sample_value(item)
for item in manifest.data_requirements
}
result = dry_run_configuration_package(
manifest,
(),
providers,
ConfigurationPreflightContext(
supplied_data=supplied_data,
installed_modules={
item.module_id: item.version or "workspace"
for item in manifest.required_modules
@@ -74,6 +91,155 @@ class ConfigurationPackageArtifactTests(unittest.TestCase):
self.assertIn("product.governed-data-assurance", package_ids)
self.assertIn("product.service-to-decision", package_ids)
def test_service_to_decision_package_imports_its_form_as_an_idempotent_local_draft(self) -> None:
from govoplan_forms.backend.configuration_provider import (
_apply_definition,
_preflight_definition,
)
from govoplan_forms.backend.db.models import FormDefinitionRevision
from govoplan_forms.backend.service import get_form_definition
package = ConfigurationPackageManifest.from_mapping(json.loads(
(PACKAGE_ROOT / "product/service-to-decision/package.json").read_text(
encoding="utf-8"
)
))
fragment = next(
item
for item in package.fragments
if item.module_id == "forms" and item.fragment_type == "definition"
)
context = ConfigurationPreflightContext(
tenant_id="tenant-reference-test",
operator_user_id="operator-1",
operator_scopes=frozenset({"system:governance:write"}),
)
engine = create_engine("sqlite+pysqlite:///:memory:")
FormDefinitionRevision.__table__.create(engine)
session = Session(engine)
try:
preflight = _preflight_definition(session, fragment, context)
applied = _apply_definition(session, fragment, context)
session.commit()
replay = _apply_definition(session, fragment, context)
imported = get_form_definition(
session,
type("Principal", (), {"tenant_id": "tenant-reference-test"})(),
form_id="resident-parking-permit-application",
)
finally:
session.close()
engine.dispose()
self.assertFalse(any(item.severity == "blocker" for item in preflight.diagnostics))
self.assertEqual("create", preflight.plan[0].action)
self.assertEqual(1, len(applied.created_refs))
self.assertEqual({}, replay.created_refs)
self.assertIsNotNone(imported)
assert imported is not None
self.assertEqual("tenant-reference-test", imported.reference.tenant_id)
self.assertEqual("draft", imported.publication_state)
self.assertEqual("de", imported.fallback_locale)
def test_service_to_decision_package_materializes_its_tenant_workflow_idempotently(self) -> None:
from govoplan_core.core.configuration_packages import _resolve_fragment_data_references
from govoplan_workflow_engine.backend.configuration_provider import (
apply_workflow_definitions,
preflight_workflow_definitions,
)
from govoplan_workflow_engine.backend.db.models import (
WorkflowDefinition,
WorkflowDefinitionRevision,
)
package = ConfigurationPackageManifest.from_mapping(json.loads(
(PACKAGE_ROOT / "product/service-to-decision/package.json").read_text(
encoding="utf-8"
)
))
fragment = next(
item
for item in package.fragments
if item.module_id == "workflow_engine"
)
context = ConfigurationPreflightContext(
tenant_id="tenant-reference-test",
supplied_data={
"responsible_group_slug": "traffic-permits",
"responsible_group_name": "Traffic permits",
},
)
resolved = _resolve_fragment_data_references(
fragment,
context.supplied_data,
)
engine = create_engine("sqlite+pysqlite:///:memory:")
WorkflowDefinition.__table__.create(engine)
WorkflowDefinitionRevision.__table__.create(engine)
session = Session(engine)
try:
preflight = preflight_workflow_definitions(session, resolved, context)
applied = apply_workflow_definitions(
session,
resolved,
context,
registry=None,
)
replay = apply_workflow_definitions(
session,
resolved,
context,
registry=None,
)
session.commit()
finally:
session.close()
engine.dispose()
self.assertFalse(any(item.severity == "blocker" for item in preflight.diagnostics))
self.assertEqual("create", preflight.plan[0].action)
self.assertIn("resident-parking-permit-review", applied.created_refs)
self.assertEqual({}, replay.created_refs)
self.assertEqual({}, replay.updated_refs)
class _ArtifactProvider:
def __init__(self, module_id: str) -> None:
self.module_id = module_id
def describe(self) -> ConfigurationProviderDescription:
return ConfigurationProviderDescription(module_id=self.module_id)
def preflight(self, fragment, context) -> ConfigurationPreflightResult:
del context
return ConfigurationPreflightResult(plan=(ConfigurationPlanItem(
action="create",
module_id=fragment.module_id,
fragment_type=fragment.fragment_type,
fragment_id=fragment.fragment_id,
),))
def apply(self, fragment, supplied_data, context) -> ConfigurationApplyResult:
del fragment, supplied_data, context
return ConfigurationApplyResult()
def export(self, selection, context) -> ConfigurationExportResult:
del selection, context
return ConfigurationExportResult()
def health(self, import_result, context):
del import_result, context
return ()
def _sample_value(requirement: dict[str, object]) -> object:
data_type = str(requirement.get("data_type") or requirement.get("type") or "string")
if data_type == "boolean":
return False
if data_type in {"integer", "number"}:
return 1
return f"fixture-{requirement['key']}"
if __name__ == "__main__":
unittest.main()
+8 -3
View File
@@ -57,18 +57,23 @@ class PackageRegistryReleaseTests(unittest.TestCase):
self.assertEqual(ARTIFACTS._canonical_sha256(unsigned), digest)
def test_full_profile_is_derived_from_the_developer_meta_package(self) -> None:
core_version = tomllib.loads(
(ROOT.parent / "govoplan-core/pyproject.toml").read_text(
encoding="utf-8"
)
)["project"]["version"]
selected = PACKAGE_SET.parse_meta_package(
ROOT / "packages/govoplan-meta/pyproject.toml",
core_version="0.1.18",
core_version=core_version,
)
by_name = {item["name"]: item for item in selected}
self.assertIn("govoplan-core", by_name)
self.assertIn("govoplan-records", by_name)
self.assertEqual("0.1.19", by_name["govoplan-tasks"]["version"])
self.assertEqual("0.1.20", by_name["govoplan-tasks"]["version"])
payload = PACKAGE_SET.generate_package_set(
core_version="0.1.18",
core_version=core_version,
requirements=ROOT / "requirements-release.txt",
workspace=ROOT.parent,
profile="full",
+265
View File
@@ -0,0 +1,265 @@
#!/usr/bin/env python3
"""Require DSAR coverage or a reviewed no-store rationale for every module."""
from __future__ import annotations
import argparse
import importlib
import json
import re
import sys
from dataclasses import dataclass
from pathlib import Path
META_ROOT = Path(__file__).resolve().parents[2]
EXEMPTIONS_PATH = Path(__file__).with_name("dsar-coverage-exemptions.json")
REPORT_PATH = (
META_ROOT
/ "docs"
/ "evidence"
/ "snapshots"
/ "DSAR_PROVIDER_COVERAGE.generated.md"
)
MODULE_NAME_PATTERN = re.compile(r"[A-Za-z_][A-Za-z0-9_]*(?:\.[A-Za-z_][A-Za-z0-9_]*)*")
REQUIRED_DOCUMENTATION_TYPES = frozenset({"admin"})
@dataclass(frozen=True, slots=True)
class CoverageRow:
module_id: str
repository: str
migration_owned: bool
capability: str | None
rationale: str
def main() -> int:
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument(
"--workspace-root",
type=Path,
default=None,
help="Directory containing GovOPlaN repositories.",
)
parser.add_argument(
"--render",
action="store_true",
help="Print the current matrix instead of comparing the checked-in report.",
)
args = parser.parse_args()
catalog = json.loads((META_ROOT / "repositories.json").read_text(encoding="utf-8"))
workspace_root = (args.workspace_root or Path(catalog["default_parent"])).resolve()
exemptions = _exemptions()
manifests, load_errors = _load_manifests(
workspace_root=workspace_root,
repositories=tuple(catalog["repositories"]),
)
errors = list(load_errors)
rows: list[CoverageRow] = []
manifest_ids = {manifest.id for _, manifest in manifests}
stale_exemptions = sorted(set(exemptions) - manifest_ids)
if stale_exemptions:
errors.append(
"DSAR coverage exemptions reference unknown modules: "
+ ", ".join(stale_exemptions)
)
for repository, manifest in manifests:
expected = f"privacy.dsar.{manifest.id}"
provided = {
item.name
for item in manifest.provides_interfaces
if item.name.startswith("privacy.dsar.")
}
factories = {
name
for name in manifest.capability_factories
if name.startswith("privacy.dsar.")
}
migration_owned = manifest.migration_spec is not None
rationale = exemptions.get(manifest.id)
if provided != factories:
errors.append(
f"{repository}: DSAR interface/factory mismatch: "
f"interfaces={sorted(provided)!r}, factories={sorted(factories)!r}"
)
if provided and provided != {expected}:
errors.append(
f"{repository}: expected only {expected!r}, found {sorted(provided)!r}"
)
capability = (
expected if expected in provided and expected in factories else None
)
if migration_owned and capability is None:
errors.append(
f"{repository}: migration-owning module {manifest.id!r} must provide "
f"and register {expected!r}"
)
if migration_owned and rationale is not None:
errors.append(
f"{repository}: migration-owning module {manifest.id!r} cannot use a "
"no-store DSAR exemption"
)
if not migration_owned and capability is None and rationale is None:
errors.append(
f"{repository}: module {manifest.id!r} needs a DSAR provider or an "
"explicit reviewed no-store rationale"
)
if capability is not None and rationale is not None:
errors.append(
f"{repository}: module {manifest.id!r} has both DSAR coverage and a "
"stale exemption"
)
if capability is not None:
if capability not in manifest.capability_documentation:
errors.append(
f"{repository}: {capability!r} lacks capability documentation"
)
matching_topics = tuple(
topic
for topic in manifest.documentation
if "data-subject-request" in topic.id
)
if not matching_topics or not any(
REQUIRED_DOCUMENTATION_TYPES.issubset(topic.documentation_types)
for topic in matching_topics
):
errors.append(
f"{repository}: DSAR coverage needs a static administrator "
"data-subject-requests DocumentationTopic"
)
rows.append(
CoverageRow(
module_id=manifest.id,
repository=repository,
migration_owned=migration_owned,
capability=capability,
rationale=(
f"Provider `{capability}` is registered and documented."
if capability
else rationale or "MISSING"
),
)
)
report = _report(rows)
if args.render:
print(report, end="")
elif not REPORT_PATH.is_file():
errors.append(f"DSAR coverage report is missing: {REPORT_PATH}")
elif REPORT_PATH.read_text(encoding="utf-8") != report:
errors.append(
"DSAR coverage report is stale; review changes and replace it with "
"the output of tools/checks/check-dsar-coverage.py --render"
)
if errors:
print("\n".join(errors), file=sys.stderr)
return 1
provider_count = sum(row.capability is not None for row in rows)
print(
"DSAR coverage check passed: "
f"{provider_count} providers, {len(rows) - provider_count} reviewed "
f"no-store rationales, {len(rows)} active modules."
)
return 0
def _exemptions() -> dict[str, str]:
values = json.loads(EXEMPTIONS_PATH.read_text(encoding="utf-8"))
if not isinstance(values, dict) or any(
not isinstance(key, str) or not isinstance(value, str) or not value.strip()
for key, value in values.items()
):
raise ValueError("DSAR coverage exemptions must be non-empty string mappings.")
return {key: value.strip() for key, value in values.items()}
def _load_manifests(*, workspace_root: Path, repositories: tuple[dict, ...]):
sources: list[Path] = []
candidates: list[tuple[str, Path, Path]] = []
for repository in repositories:
source = workspace_root / repository["path"] / "src"
if not source.is_dir():
continue
sources.append(source)
candidates.extend(
(repository["name"], source, path)
for path in sorted(source.glob("*/backend/manifest.py"))
)
core_source = workspace_root / "govoplan-core" / "src"
sys.path[:0] = [
str(core_source),
*(str(source) for source in sources if source != core_source),
]
manifests = []
errors = []
for repository, source, path in candidates:
module_name = ".".join(path.relative_to(source).with_suffix("").parts)
if MODULE_NAME_PATTERN.fullmatch(module_name) is None:
errors.append(f"{repository}: unsafe manifest module name {module_name!r}")
continue
try:
module = importlib.import_module(module_name)
manifests.append((repository, module.get_manifest()))
except Exception as exc: # pragma: no cover - emitted as check evidence
errors.append(f"{repository}: could not load {module_name}: {exc}")
return manifests, errors
def _report(rows: list[CoverageRow]) -> str:
ordered = sorted(rows, key=lambda row: row.module_id)
providers = sum(row.capability is not None for row in ordered)
lines = [
"# DSAR Provider Coverage",
"",
"This generated matrix is enforced by `tools/checks/check-dsar-coverage.py`.",
"A migration-owning module must register and document its canonical DSAR provider.",
"Every other active module requires a reviewed explanation of why it owns no",
"persistent subject-data store. Adding a migration invalidates that explanation.",
"",
f"- Active modules: {len(ordered)}",
f"- Registered and documented DSAR providers: {providers}",
f"- Reviewed no-store rationales: {len(ordered) - providers}",
"- Unexplained coverage gaps: 0",
"",
"| Module | Repository | Persistence | Coverage | Rationale |",
"| --- | --- | --- | --- | --- |",
]
for row in ordered:
lines.append(
"| "
+ " | ".join(
(
f"`{row.module_id}`",
f"`{row.repository}`",
"Migration-owned" if row.migration_owned else "No module migration",
"Provider" if row.capability else "Reviewed no-store rationale",
row.rationale.replace("|", "\\|"),
)
)
+ " |"
)
lines.extend(
(
"",
"Provider search, export minimization, retention, and erasure behavior remains",
"documented and tested by each owning module. This matrix verifies adoption and",
"ownership coverage; Core continues to test disabled providers, partial failure,",
"retry, authorization evidence, and horizontally coordinated execution.",
"",
)
)
return "\n".join(lines)
if __name__ == "__main__":
raise SystemExit(main())
+7
View File
@@ -38,6 +38,7 @@ cd "$ROOT"
GOVOPLAN_CORE_ROOT="$ROOT" PYTHON="$PYTHON" CHECK_TESTCLIENT_DEPRECATIONS=1 bash "$META_ROOT/tools/checks/check-dependency-hygiene.sh"
"$PYTHON" "$META_ROOT/tools/checks/check-contracts.py" --no-impact
PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$META_ROOT/tools/checks/check-manifest-shapes.py" --require-architecture
PYTHONDONTWRITEBYTECODE=1 "$PYTHON" "$META_ROOT/tools/checks/check-dsar-coverage.py"
cd "$META_ROOT"
"$PYTHON" tools/inventory/platform-interface-inventory.py --strict-declarations --strict-endpoints
@@ -114,6 +115,7 @@ PY
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-approvals/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-identity-trust/tests
"$PYTHON" -m unittest discover -s /mnt/DATA/git/govoplan-encryption/tests
"$PYTHON" -m pytest -q /mnt/DATA/git/govoplan-wiki/tests
"$PYTHON" -m pytest -q /mnt/DATA/git/govoplan-campaign/tests/test_approval_gate.py
"$PYTHON" "$META_ROOT/tools/checks/check-datasource-composition.py"
"$PYTHON" "$META_ROOT/tools/checks/check-sanctions-screening-composition.py"
@@ -157,3 +159,8 @@ cd /mnt/DATA/git/govoplan-campaign/webui
"$NPM" run test:policy-ui
"$NPM" run test:template-preview
"$NPM" run test:accessibility-contract
"$NPM" run test:campaign-collaboration
"$NPM" run test:campaign-work
cd /mnt/DATA/git/govoplan-wiki/webui
"$NPM" run test:interface-pattern
@@ -262,6 +262,8 @@ cd "$WORK_ROOT/govoplan-campaign/webui"
"$NPM" run test:policy-ui
"$NPM" run test:template-preview
"$NPM" run test:import-utils
"$NPM" run test:campaign-collaboration
"$NPM" run test:campaign-work
echo
echo "Release integration check passed."
@@ -0,0 +1,22 @@
{
"assets": "Contract-only module: asset persistence and lifecycle APIs are not implemented; reassess before adding a migration-owned store.",
"booking": "Contract-only module: booking persistence and reservation workflows are not implemented; reassess before adding a migration-owned store.",
"certificates": "Contract-only module: certificate issuance and revocation persistence are not implemented; reassess before adding a migration-owned store.",
"consultation": "Contract-only module: consultation submissions and evaluation persistence are not implemented; reassess before adding a migration-owned store.",
"contracts": "Contract-only module: contract, amendment, and obligation persistence are not implemented; reassess before adding a migration-owned store.",
"evaluation": "Contract-only module: evaluation runs, responses, and scores are not persisted; reassess before adding a migration-owned store.",
"facilities": "Contract-only module: facility and maintenance persistence are not implemented; reassess before adding a migration-owned store.",
"grants": "Contract-only module: grant applications, awards, and monitoring are not persisted; reassess before adding a migration-owned store.",
"inspections": "Contract-only module: inspections, findings, and measures are not persisted; reassess before adding a migration-owned store.",
"learning": "Contract-only module: learning offers, enrollment, and completion are not persisted; reassess before adding a migration-owned store.",
"ops": "Projection-only module: Ops reads bounded platform and provider status; durable recovery evidence remains owned by Core and domain modules.",
"permits": "Contract-only module: permit applications, assessments, and decisions are not persisted; reassess before adding a migration-owned store.",
"portal": "Projection-only module: Portal stores no applicant records; Services, Forms Runtime, Cases, and Postbox own and export authoritative subject data.",
"procurement": "Contract-only module: procurement procedures, tenders, and awards are not persisted; reassess before adding a migration-owned store.",
"resources": "Contract-only module: resource catalog and allocation persistence are not implemented; reassess before adding a migration-owned store.",
"rest": "Transport-only module: REST binds explicitly published functions and owns no domain or subject-data store.",
"soap": "Transport-only module: SOAP binds explicitly published operations and owns no domain or subject-data store.",
"tenancy": "Orchestration module: tenant lifecycle and settings use Core-owned storage; Access covers account and membership subject data.",
"transparency": "Contract-only module: requests, disclosure reviews, and publications are not persisted; reassess before adding a migration-owned store.",
"workflow": "Presentation-only module: Workflow edits and projects Workflow Engine state; Workflow Engine owns persistence and DSAR coverage."
}
@@ -539,6 +539,125 @@
"rationale": "The Connector governance administration page constructs this review-decision URL from the selected run identifier.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/connectors/knowledge/profiles",
"rationale": "The External knowledge administration page lists MediaWiki and BlueSpice profiles through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/knowledge/profiles",
"rationale": "The External knowledge administration page creates a mapped, ACL-governed knowledge profile through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "PUT",
"path": "/connectors/knowledge/profiles/{}",
"rationale": "The External knowledge administration page constructs this revision-guarded profile URL from the selected profile identifier.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/knowledge/profiles/{}/discover",
"rationale": "The External knowledge administration page discovers product, version, capabilities, namespaces, and diagnostics through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/knowledge/profiles/{}/migration-dry-runs",
"rationale": "The External knowledge administration page runs a bounded, non-writing native-Wiki migration preview through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/connectors/knowledge/profiles/{}/objects",
"rationale": "The External knowledge administration page lists synchronized, identity-stable knowledge snapshots through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/knowledge/profiles/{}/pages/{}/publish",
"rationale": "The External knowledge administration page constructs this revision-checked external publication URL from the selected profile and page identifiers.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/knowledge/profiles/{}/sync",
"rationale": "The External knowledge administration page runs keyed full backfills and recent-change deltas through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/connectors/knowledge/runs",
"rationale": "The External knowledge administration page lists synchronization, migration-preview, and publication evidence through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/connectors/service-desk/profiles",
"rationale": "The External service desk administration page lists Znuny/OTRS profiles through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/service-desk/profiles",
"rationale": "The External service desk administration page creates route-, queue-, field-, authority-, and ACL-governed profiles through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "PUT",
"path": "/connectors/service-desk/profiles/{}",
"rationale": "The External service desk administration page constructs this revision-guarded profile URL from the selected profile identifier.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/service-desk/profiles/{}/discover",
"rationale": "The External service desk administration page discovers product, version, maturity, capabilities, route health, and diagnostics through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/connectors/service-desk/profiles/{}/objects",
"rationale": "The External service desk administration page lists synchronized identity-stable, ACL-governed external ticket projections through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/service-desk/profiles/{}/sync",
"rationale": "The External service desk administration page runs keyed bounded full and delta synchronization through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/connectors/service-desk/profiles/{}/tickets/{}/update",
"rationale": "The External service desk ticket list opens a separated revision-checked governed update dialog and constructs this URL from stable profile and provider ticket identifiers.",
"repository": "govoplan-connectors"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/connectors/service-desk/runs",
"rationale": "The External service desk administration page lists synchronization and external-mutation recovery evidence through this endpoint.",
"repository": "govoplan-connectors"
},
{
"category": "intentionally_headless",
"method": "GET",
@@ -574,6 +693,13 @@
"rationale": "This capability-first module intentionally exposes a headless API for other modules and integrations.",
"repository": "govoplan-connectors"
},
{
"category": "intentionally_headless",
"method": "POST",
"path": "/connectors/tabular-sources/files",
"rationale": "This capability-first module intentionally exposes a headless API for other modules and integrations.",
"repository": "govoplan-connectors"
},
{
"category": "intentionally_headless",
"method": "POST",
@@ -581,6 +707,13 @@
"rationale": "This capability-first module intentionally exposes a headless API for other modules and integrations.",
"repository": "govoplan-connectors"
},
{
"category": "intentionally_headless",
"method": "POST",
"path": "/connectors/tabular-sources/sql",
"rationale": "This capability-first module intentionally exposes a headless API for other modules and integrations.",
"repository": "govoplan-connectors"
},
{
"category": "intentionally_headless",
"method": "DELETE",
@@ -595,6 +728,13 @@
"rationale": "This capability-first module intentionally exposes a headless API for other modules and integrations.",
"repository": "govoplan-connectors"
},
{
"category": "intentionally_headless",
"method": "POST",
"path": "/connectors/tabular-sources/{}/refresh",
"rationale": "This capability-first module intentionally exposes a headless API for other modules and integrations.",
"repository": "govoplan-connectors"
},
{
"category": "public_integration",
"method": "GET",
@@ -763,6 +903,90 @@
"rationale": "The module WebUI constructs this endpoint through a mounted router prefix, generic action, or provider path.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/semantic/entries",
"rationale": "The Docs semantic authoring UI calls this mounted sub-router through the /docs prefix, which static endpoint matching cannot compose.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/semantic/entries",
"rationale": "The Docs semantic authoring UI calls this mounted sub-router through the /docs prefix, which static endpoint matching cannot compose.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/semantic/entries/{}",
"rationale": "The Docs semantic authoring UI constructs the entry identifier dynamically on the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "PUT",
"path": "/semantic/entries/{}",
"rationale": "The Docs semantic authoring UI constructs the entry identifier dynamically on the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/semantic/entries/{}/history",
"rationale": "The Docs semantic authoring UI constructs immutable history paths dynamically on the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/semantic/entries/{}/publish",
"rationale": "The Docs semantic authoring UI constructs lifecycle action paths dynamically on the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/semantic/entries/{}/retire",
"rationale": "The Docs semantic authoring UI constructs lifecycle action paths dynamically on the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "POST",
"path": "/semantic/entries/{}/supersede",
"rationale": "The Docs semantic authoring UI constructs lifecycle action paths dynamically on the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/semantic/export",
"rationale": "The Docs semantic authoring UI calls tenant export on the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/semantic/policy",
"rationale": "The Docs semantic authoring UI reads publication policy through the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "PUT",
"path": "/semantic/policy",
"rationale": "The Docs semantic authoring UI saves publication policy through the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "GET",
"path": "/semantic/subjects",
"rationale": "The Docs semantic authoring UI discovers authorized module subjects through the mounted semantic sub-router.",
"repository": "govoplan-docs"
},
{
"category": "ui_reachable",
"method": "GET",
@@ -1904,68 +2128,60 @@
"repository": "govoplan-campaign"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "GET",
"path": "/relationships",
"rationale": "IDM documents typed relationships but its current administration page exposes function assignments only.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "The IDM relationship administration grid lists effective-dated identity relationships and their lifecycle state.",
"repository": "govoplan-idm"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "POST",
"path": "/relationships",
"rationale": "IDM documents typed relationships but its current administration page exposes function assignments only.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "Authorized IDM administrators create relationships through the searchable relationship editor.",
"repository": "govoplan-idm"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "PATCH",
"path": "/relationships/{}",
"rationale": "IDM documents typed relationships but its current administration page exposes function assignments only.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "Authorized IDM administrators update a loaded relationship with its optimistic revision.",
"repository": "govoplan-idm"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "POST",
"path": "/relationships/{}/revoke",
"rationale": "IDM documents typed relationships but its current administration page exposes function assignments only.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "The IDM relationship grid exposes a separated destructive action with mandatory reason and confirmation.",
"repository": "govoplan-idm"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "GET",
"path": "/typed-groups",
"rationale": "IDM documents typed groups but its current administration page exposes function assignments only.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "The IDM typed-group administration grid lists active and optionally inactive groups.",
"repository": "govoplan-idm"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "POST",
"path": "/typed-groups",
"rationale": "IDM documents typed groups but its current administration page exposes function assignments only.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "Authorized IDM administrators create typed groups through the group editor.",
"repository": "govoplan-idm"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "PATCH",
"path": "/typed-groups/{}",
"rationale": "IDM documents typed groups but its current administration page exposes function assignments only.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "Authorized IDM administrators edit group metadata, lifecycle state, and provenance with optimistic revision checks.",
"repository": "govoplan-idm"
},
{
"category": "missing_ui",
"category": "ui_reachable",
"method": "GET",
"path": "/typed-groups/{}/memberships",
"rationale": "IDM lacks the typed-group membership explanation surface for this existing API.",
"repository": "govoplan-idm",
"tracking_issue": "https://git.add-ideas.de/GovOPlaN/govoplan-idm/issues/11"
"rationale": "The IDM membership inspector resolves a group at a selected time and shows included and excluded decisions.",
"repository": "govoplan-idm"
},
{
"category": "intentionally_headless",
@@ -56,8 +56,10 @@ const labelAttributes = new Set([
"title"
]);
const helpAttributes = new Set([
"data-help-context-id",
"description",
"help",
"helpContextId",
"helperText",
"helpText"
]);
+4
View File
@@ -571,6 +571,10 @@ run_manifest_shape_gate() {
"$META_ROOT/tools/checks/check-manifest-shapes.py" \
--workspace-root "$PARENT" \
--require-architecture
run env PYTHONDONTWRITEBYTECODE=1 \
"$PYTHON" \
"$META_ROOT/tools/checks/check-dsar-coverage.py" \
--workspace-root "$PARENT"
}
run_migration_release_audit() {