Reconcile product inputs and prove durable work handoffs
Dependency Audit / dependency-audit (push) Successful in 1m48s
Deployment Installer / deployment-installer (push) Successful in 6s
Security Audit / security-audit (push) Successful in 12m2s

This commit is contained in:
2026-08-06 16:06:18 +02:00
parent 69ba1037bf
commit b269791c48
18 changed files with 523 additions and 40 deletions
+1 -1
View File
@@ -15,7 +15,7 @@ GOVOPLAN_DB_MAX_OVERFLOW=10
GOVOPLAN_DB_POOL_TIMEOUT_SECONDS=30
GOVOPLAN_DB_POOL_RECYCLE_SECONDS=1800
ENABLED_MODULES=tenancy,organizations,identity,idm,access,admin,dashboard,policy,audit,files,templates,mail,campaigns,calendar,poll,scheduling,connectors,datasources,dataflow,dist_lists,workflow_engine,workflow,views,search,risk_compliance,postbox,notifications,services,parties,mandates,decisions,portal,cases,committee,docs,ops
ENABLED_MODULES=tenancy,organizations,identity,idm,access,admin,dashboard,policy,audit,files,templates,mail,campaigns,calendar,poll,scheduling,connectors,datasources,dataflow,dist_lists,workflow_engine,workflow,tasks,views,search,risk_compliance,postbox,notifications,services,parties,mandates,decisions,portal,cases,committee,docs,ops
CELERY_ENABLED=true
REDIS_URL=redis://127.0.0.1:6379/0
+15 -1
View File
@@ -61,6 +61,12 @@ next responsible action, reason, deadline, consequence, and completion
evidence. Workflow Engine coordinates machine and human transitions; focused
views guide people through the relevant platform surfaces.
Tasks owns explicit work items and the unified work inbox. Workflow Engine owns
process execution and resumable handoffs. Notifications attract attention, and
domain modules retain their business objects. These boundaries prevent an
inbox, workflow, or notification from becoming a second copy of institutional
state.
### 7. Views reduce complexity without changing authority
The interface is a task- and role-sensitive projection of installed
@@ -84,6 +90,11 @@ records who entered information, for whom, from which source, with which
attestation, and how the affected person receives a usable receipt and
correction path.
Responsive, mobile, desktop, and embedded launch surfaces are additional ways
to enter the same governed context, not separate products with weaker authority
or evidence. Common task-local actions may open in bounded overlays while their
owning modules retain validation, policy, and persistence.
### 10. Successful configurations are portable products
Modules are ingredients. A usable product is a signed configuration package
@@ -106,6 +117,10 @@ deployment tiers.
| Data and integration | Connectors, datasources, dataflow, search, external references, provider health, and reconciliation |
| Runtime and assurance | Module composition, operations, deployment, recovery, security evidence, and signed packages |
Collected product ideas and normalized actor outcomes are preserved in the
[Product Input Register](PRODUCT_INPUT_REGISTER.md). They enter implementation
only through a named journey, package, or explicit discovery issue.
## Canonical Distinctions
The platform must not collapse these pairs:
@@ -170,4 +185,3 @@ institutional journey and can answer:
6. How can it operate with an external owner without losing autonomy?
7. How will a person discover and complete it without learning the module
graph?
+195
View File
@@ -0,0 +1,195 @@
# GovOPlaN Product Input Register
## Purpose
This document preserves and normalizes product ideas and user-story notes that
inform GovOPlaN without turning a private note file into a second backlog.
Gitea issues remain the source of live work state; the stable platform direction
remains in [Platform Core Ideas](PLATFORM_CORE_IDEAS.md), the
[Connected Governance Platform Roadmap](CONNECTED_GOVERNANCE_PLATFORM_ROADMAP.md),
and the [Reference Journey Program](REFERENCE_JOURNEY_PROGRAM.md).
The register was reconciled on 2026-08-06 from:
- `/mnt/DATA/Nextcloud/ADD ideas UG/Products/govoplan/ideas.md`;
- `/mnt/DATA/Nextcloud/ADD ideas UG/Products/govoplan/user_stories.txt`.
The source notes remain useful as the original capture. This maintained version
uses consistent terminology, makes ownership explicit, and records where an
idea enters the product program.
## Product Themes
### Operable and scalable installation
An operator should be able to install, update, reconfigure, scale, back up,
restore, pause, and retire GovOPlaN through one explainable control plane.
Existing infrastructure may be reused or managed components may be provisioned.
The WebUI and CLI must invoke the same governed operations, show the planned and
completed effects, preserve recovery evidence, and never claim rollback for an
external effect that cannot actually be reversed.
This theme is owned by Core, Admin, Ops, Policy, Files, and the signed product
package. It is tracked primarily by GovOPlaN #13 and the production evidence
issues. It advances in parallel with, but does not replace, actor-facing
reference journeys.
### Focused, consistent work
People should see the work and tools relevant to the current task, not the
installed module graph. Views may be defined by administrators, groups, or
users within policy. Workflow instances may pin a governed View. Contextual
help, predictable action placement, consistent central components, visible
intermediate results, and plain institutional terminology are product
requirements.
Small task-local actions such as writing a Mail or Postbox message, completing
a Template, or manipulating Files should be launchable without abandoning the
current context. These actions remain owned by their modules and use bounded
overlays or workspaces; the shell supplies discovery and return context rather
than reimplementing them.
This theme is owned by Core experience contracts, Views, Dashboard, Tasks,
Workflow Engine, Docs, and the contributing feature modules. The first proof is
the resumable service-to-decision/eAkte journey in GovOPlaN #42.
### Governed human work
An intake or event becomes owned work with a responsible actor or function,
priority, deadline, current action, consequence, source context, and completion
evidence. Tasks owns explicit work items and the unified work inbox. Workflow
Engine owns process execution, waits, retries, and handoffs. Domain modules own
the business objects and commands. Notifications attract attention but do not
replace durable work state.
This distinction applies to service requests, technical support, approvals,
data reconciliation, campaigns, meetings, decisions, records, and failed
automation. It is the immediate shared implementation priority because users
must be able to leave work and resume it safely.
### Institutional responsibility and workforce context
Organization units, functions, mandates, assignments, delegations, and acting
context determine institutional responsibility. Presence, absence, illness,
availability, and similar status are effective-dated operational facts used to
route work, suppress or redirect notifications, explain planning, and trigger
policy. They are not merely profile decorations and they do not replace the IDM
lifecycle status of an identity or account.
Time recording, absence management, sickness reporting, return-to-work
management, and applicant management form a possible workforce package. The
first implementation must be driven by a real journey and legal/privacy
profile; no new module boundary is implied solely by this register.
### Integration-first and provider-neutral operation
GovOPlaN should integrate tightly with software already used by an institution
and offer native alternatives only where that produces a better governed
outcome. Core-mediated provider contracts expose stable, vendor-neutral
capabilities; adapters encapsulate specific products. Authority, synchronized
fields, conflict behavior, health, credential custody, provenance, and
retirement must be explicit.
The LBV Baden-Wuerttemberg idea is retained as a candidate workforce/payroll
integration profile and as a test of provider-neutral contracts. Desktop and
groupware integration for Microsoft Office, Outlook, LibreOffice, Thunderbird,
file managers, Windows, Unix, and macOS should use standards, deep links,
protocol handlers, synchronization, and governed connectors before custom
desktop software is introduced.
### Inclusive channels and device surfaces
Portal, Postbox, Mail, telephone, paper, in-person assistance, API, desktop,
and mobile are channels around the same governed work. A responsive or native
mobile surface must not create a second authority or data model. Assisted work
records representation, source, attestation, receipt, correction, and delivery
choice. People may opt into permitted distribution channels while policy keeps
mandatory channels and legal delivery requirements explicit.
Video meetings, chat, instant messaging, and forums are retained as governed
collaboration-channel candidates. The default direction is integration with an
established provider through typed message, meeting, participant, evidence, and
retention contracts before building another communications stack.
### Meetings, deliberation, decisions, and voting
An institutional meeting spans scheduling, participants and mandates,
documents, agenda, discussion, formal motions, votes, decisions, minutes,
follow-up work, publication, and eligible expense settlement. Committee owns
the meeting and deliberation semantics while Calendar, Scheduling, Files,
Templates, Decisions, Tasks, Reporting, Ledger, and Voting contribute optional
capabilities.
Voting requiring certified assurance remains a provider program. POLYAS is the
first external profile; a native provider may progress only through the
controlled assurance and certification program already tracked in Voting.
### Controlled data work and understandable reporting
People should manipulate data through immutable inputs, previewed operations,
intermediate materializations, reversible definition changes, durable review
decisions, quality rules, and complete lineage. Reports expose their definitions
and source revisions so controllers can understand and change how a result is
produced. Technical support may package controlled workflows that let
non-technical users safely operate otherwise hidden data.
The monthly-data journey is the first proof. Sanctions screening follows on the
same source, snapshot, transformation, review, reporting, workflow, and
delivery contracts.
### Institutional memory and consequence
Decisions should be prepared, discussed, made, communicated, implemented, and
filed with their authority and consequences visible. A record/eAkte provides
the familiar administrative context across exact source revisions without
copying ownership from Cases, Decisions, Files, Forms, Campaign, Postbox, or
other modules. The institutional digital twin may later use governed
projections to model and simulate organizational change, but simulation output
never becomes authority without an explicit adoption decision.
## Normalized Story Catalogue
The following catalogue preserves the intent of the collected notes. It is an
orientation index, not a completion checklist.
| Actor and desired outcome | Product owner or composition | First proof |
| --- | --- | --- |
| Operator installs, updates, scales, backs up, restores, and rolls back through one explainable workflow | Core, Admin, Ops, signed package | GovOPlaN #13 and target-evidence lane |
| System and tenant module administrators govern module availability and lifecycle | Core, Admin, Policy, Tenancy | Module entitlement and lifecycle composition |
| User works in a decluttered, consistent and task-sensitive interface | Views, Core, Dashboard, Workflow, Docs | Service-to-decision workspace |
| Policy maker defines inherited, explainable and enforced rules | Policy plus every consequential owner | Information-governance adoption gate |
| Controller and auditor reconstruct results, rules, evidence and correction paths | Audit, Reporting, Records, Dataflow | Monthly-data and eAkte journeys |
| User sees institutional terminology, current progress, intermediate results and consequences | Domain owner, Tasks, Workflow, Views | All reference journey acceptance tests |
| Voting body and voter obtain independently assured democratic voting | Voting, Committee, Identity Trust, Encryption | POLYAS profile and controlled native-provider program |
| Support staff packages safe guided manipulation of hidden data | Workflow, Dataflow, Tasks, Views | Monthly reconciliation workflow |
| Data worker performs controlled, understandable and recoverable transformations | Datasources, Connectors, Dataflow, Reporting | GovOPlaN #8 |
| Decision maker prepares, deliberates, decides, records and follows consequences | Committee, Decisions, Tasks, Records, Reporting | Service-to-decision journey |
| Management delegates responsibility and receives governed activity reports | Organizations, IDM, Access, Policy, Reporting | Function-bound Postbox and work inbox |
| Institution models and simulates organizational change | Organizations, Policy, Dataflow, Reporting, Digital Twin | Later governed digital-twin package |
| Sender distributes generated files to functions without knowing incumbents | Campaign, Distribution Lists, Postbox, Organizations, IDM | Governed communication package |
| Function holder receives current and policy-selected historical work and information | IDM, Access, Postbox, Tasks, Records | Postbox reassignment/history tests |
| Administrative worker accesses one familiar eAkte context across exact owned objects | Records and record-source providers | GovOPlaN #42 and Records #8 |
| User invokes common message, template and file actions without leaving the current task | Core shell, Views, Workflow and contributing modules | Task-local action contract and service workspace |
## Idea Preservation Map
| Original idea cluster | Preserved direction |
| --- | --- |
| Time recording, absence, sickness, reintegration, applicant management | Governed workforce-context journey; effective-dated status and privacy profile before module expansion |
| LBV BW interface | Candidate provider-neutral workforce/payroll connector profile |
| Abstract interfaces | Versioned Core contracts with product adapters and explicit source authority |
| Desktop and groupware integration | Standards, connectors, deep launch and synchronization before custom clients |
| GovOPlaN app/mobile-first pages | Responsive shared semantics; native shell only when a proven journey needs device capabilities |
| Video, chat, instant messaging and forum | Optional governed collaboration providers with retention/evidence contracts |
| Somacos Session-style meeting management | Committee-led meeting composition across Calendar, Files, Decisions, Templates, Tasks, Reporting and Ledger |
| Stronger software integration | Integration-first roadmap rule and first full external product connectors |
## Maintenance
When a source idea becomes actionable:
1. link it to a named reference journey or explicit discovery issue;
2. identify the owning module and external authority;
3. create or update the Gitea issue with acceptance criteria;
4. keep live status out of this document;
5. update this register only when the durable interpretation changes.
+3
View File
@@ -14,6 +14,7 @@ volatile repository, issue, release, or maturity counts as current facts.
| Which institutional concepts and owners form the target architecture? | [Institutional Governance Target Architecture](INSTITUTIONAL_GOVERNANCE_TARGET_ARCHITECTURE.md) |
| Which end-to-end proofs should guide implementation? | [Reference Journey Program](REFERENCE_JOURNEY_PROGRAM.md) |
| What is the reconciled state now? | [Strategy Status](STRATEGY_STATUS.md) |
| Which collected ideas and user stories inform the product direction? | [Product Input Register](PRODUCT_INPUT_REGISTER.md) |
The dated [Strategic Review](STRATEGIC_REVIEW_2026-08-05.md) explains why the
current reset and sequencing were chosen. It is an assessment record, not a
@@ -74,3 +75,5 @@ be edited manually.
repository. Meta documentation defines cross-module outcomes and contracts.
6. A new strategy document must replace, narrow, or link an existing source;
it must not introduce a parallel roadmap.
7. The Product Input Register preserves external idea and story notes, but only
Gitea issues carry live priority, ownership, and implementation state.
+13 -3
View File
@@ -46,9 +46,11 @@ and archive-neutral package simulation. Forms Runtime, Cases, and Decisions
expose exact, permission-rechecked source revisions for explicit filing, and
all three contribute metadata-only native Search projections that can be
rebuilt from authoritative state. The executable fixtures prove those native
transitions without claiming archival custody. The journey still needs
resumable user handoffs, pinned-composition reconstruction evidence, and one
target-tested archive profile.
transitions without claiming archival custody. A persisted Workflow Engine
handoff is now reloaded through the Tasks aggregation surface and remains
visible until the authoritative Workflow transition completes. The journey
still needs pinned-composition reconstruction evidence and one target-tested
archive profile.
## Why this sequence
@@ -124,6 +126,14 @@ journey needs and supplies contracts shared by all five stages.
Module manifests state `contract_only`, `partial`, `enforced`, or
`not_applicable` adoption with evidence; supported maturity is blocked until
every applicable dimension is enforced.
11. **Durable human work.** Tasks aggregates explicit work and module-owned
attention items; Workflow Engine persists process state and handoffs;
Notifications attracts attention; Views focuses the relevant surfaces.
Leaving or refreshing the browser never becomes the only record that work
remains unfinished.
12. **Task-local tools.** Mail, Postbox, Templates, Files, and other common
actions may contribute bounded launch surfaces with return context. The
shell and Workflow compose them without copying their data or validation.
## Documentation contract for every reference stage
+25 -17
View File
@@ -7,6 +7,7 @@
| Reconciled on | 2026-08-06 |
| Source scope | Local workspace manifests, source inventory, focused journey checks, signed release evidence, and live Gitea issue state |
| Stable direction | [Platform Core Ideas](PLATFORM_CORE_IDEAS.md) and [Connected Governance Platform Roadmap](CONNECTED_GOVERNANCE_PLATFORM_ROADMAP.md) |
| Collected product input | [Product Input Register](PRODUCT_INPUT_REGISTER.md) |
| Delivery source | Gitea issues |
This is the only prose source for current cross-product status. It is a
@@ -15,8 +16,8 @@ evidence remain authoritative for specific maturity claims.
## Portfolio Snapshot
- 65 source module manifests were loadable and architecture-declared.
- 47 modules declared `vertical_slice`; 18 declared `scaffold`.
- 66 source module manifests were loadable and architecture-declared.
- 48 modules declared `vertical_slice`; 18 declared `scaffold`.
- No module declared `reference_ready`, `supported`, or `lts`.
- The live portfolio had 133 open issues, including 39 priority-P1 items.
- 117 open issues had no milestone, so issue labels do not yet express a
@@ -30,19 +31,20 @@ document.
## Interface And Contract Evidence
The 2026-08-05 source inventory found:
The 2026-08-06 source inventory found:
- 1,247 UI fields and 1,220 UI actions;
- 7,929 stable interface declarations with no duplicate IDs;
- 39 frontend routes and 872 backend endpoints;
- 1,307 UI fields and 1,291 UI actions;
- 8,157 stable interface declarations with no duplicate IDs;
- 43 frontend routes and 920 backend endpoints;
- no public WebUI surfaces missing runtime declarations;
- no stale runtime route declarations;
- no unclassified endpoint without a static UI reference;
- all 1,247 fields with a resolvable F1 context; 1,087 remain candidates for
- all 1,307 fields with a resolvable F1 context; 1,143 remain candidates for
richer field-specific content beyond page/module fallback;
- German (`de`) as the complete reference locale and no used key missing from
the required German or English catalogs;
- 260 module information-governance dimensions classified as `contract_only`.
- 3 module information-governance dimensions classified as `enforced`, 1 as
`partial`, and 260 as `contract_only`.
This is an honest platform-wide baseline, not a claim that temporal,
purpose, retention, and institutional-context adoption is complete.
@@ -70,24 +72,28 @@ Voting, Decisions, Portal, Postbox, and Audit have an executable service-to-
decision fixture. Public and invitation intake can retain Files-backed
evidence; Forms submissions, Cases, and formal Decisions can be explicitly
filed as exact eAkte source revisions and reconstructed through permission-
rechecked native Search projections. Browser-complete assisted intake,
resumable work guidance, production identity and delivery, a named archive
profile, and target evidence remain.
rechecked native Search projections. A durable Workflow Engine handoff now
survives session restart and appears through the Tasks work inbox until the
authoritative transition completes. Browser-complete assisted intake, broader
work projections and escalation, production identity and delivery, a named
archive profile, and target evidence remain.
### Governed data and assurance
Connectors, Datasources, Dataflow, Reporting, Search, Policy, Risk Compliance,
and Workflow provide source governance, immutable snapshots, transformation,
quality, semantic reporting, and provenance foundations. The monthly-data and
sanctions journeys still need real connectors, complete interactive
reconciliation, publication/export, and guided handoff evidence.
sanctions compositions now prove immutable connector snapshots, pinned
Dataflow publication, Risk Compliance review, and rescreening in process. The
journeys still need target connector profiles, complete interactive
reconciliation, governed export/delivery, and browser-level handoff evidence.
## Material Gaps
| Gap | Consequence | Next proof |
| --- | --- | --- |
| No reference-ready product package | The platform cannot yet make a bounded supported-product claim | Complete one named target composition and evidence bundle |
| Human-work spine incomplete | Users still navigate modules and remember unfinished work | Task/work inbox, resumable guided journey, deadlines and handoffs |
| Human-work spine is only an MVP | Tasks aggregates explicit work plus Workflow, Approval, and unread Postbox projections, but broad domain coverage, deadline escalation, assignment lifecycle, and focused product UX remain | Extend source providers through the three reference journeys and prove overdue/reassignment behavior in browser tests |
| Records/eAkte target integration incomplete | Native lifecycle, retention, holds, approval, recovery, and transfer simulation are implemented, but real custody is not proved | Target-test one archive/xdomea profile and complete the assisted reference journey |
| Cross-cutting governance adoption uneven | Historical and purpose-sensitive behavior varies by module | Enforced adoption declarations and route/query/effect migration |
| Explicit help/accessibility depth incomplete | German/reference and F1 association gates now pass, but generic fallback remains too common | High-risk German help content and browser/a11y matrix |
@@ -103,9 +109,11 @@ reconciliation, publication/export, and guided handoff evidence.
sanctions screening.
4. Complete the browser and resumable-work proof for the digital and assisted
service-to-decision journey with its existing exact eAkte filing contracts.
5. Extend native PostgreSQL search coverage from the implemented service-to-
decision objects to the communication and monthly-data journeys; keep
OpenSearch optional.
5. Complete native PostgreSQL search coverage for remaining journey-owned
objects and prove reauthorization and reindex operations at target volume;
keep OpenSearch optional. Communication, Records, service-to-decision,
Dataflow, Reporting, Risk Compliance, and Datasource catalogue sources now
exist.
6. Prove one external product connector and one GovOPlaN federation exchange.
7. Finish multi-host, restore, provider, accessibility, and independent signed
target evidence before increasing maturity claims.
+1
View File
@@ -72,6 +72,7 @@ full = [
"govoplan-search==0.1.18",
"govoplan-services==0.1.18",
"govoplan-soap==0.1.18",
"govoplan-tasks==0.1.18",
"govoplan-templates==0.1.18",
"govoplan-tickets==0.1.18",
"govoplan-transparency==0.1.18",
@@ -28,5 +28,7 @@ The artifact remains a `product` package. Promotion to `reference` requires:
access; and
- version-pinned user and administrator documentation.
Optional Notifications, Portal, Reporting, and Workflow Engine integrations do
not change the package boundary when absent.
Optional Notifications, Portal, Reporting, Tasks, and Workflow Engine
integrations do not change the package boundary when absent. When Tasks is
present, acknowledgement, reconciliation, and operator intervention remain
owned by their source modules and are projected into the common work inbox.
@@ -21,6 +21,7 @@
{"module_id": "notifications"},
{"module_id": "portal"},
{"module_id": "reporting"},
{"module_id": "tasks"},
{"module_id": "workflow_engine"}
],
"evidence": [
@@ -37,8 +37,10 @@ The artifact remains a `product` package. Promotion to `reference` requires:
aggregate disclosure; and
- version-pinned user and administrator documentation.
Optional Connectors, Files, Notifications, and Workflow Engine integrations
must remain capability-based and absence-safe.
Optional Connectors, Files, Notifications, Tasks, and Workflow Engine
integrations must remain capability-based and absence-safe. Tasks may present
review and recovery handoffs, but Dataflow and Risk Compliance remain the
authoritative owners of run and screening state.
## Executable evidence
@@ -21,6 +21,7 @@
{"module_id": "connectors"},
{"module_id": "files"},
{"module_id": "notifications"},
{"module_id": "tasks"},
{"module_id": "workflow_engine"}
],
"evidence": [
+11 -4
View File
@@ -33,6 +33,11 @@ values, evidence payloads, Decision reasoning, operative results, and
conditions are excluded; every candidate is authorized again before it is
shown.
When Tasks is present, explicit work and source-owned Workflow handoffs appear
in one resumable inbox with typed account, group, role, function, or assignment
responsibility. Workflow Engine retains process state and completion commands;
Tasks retains only explicit tasks and the aggregation surface.
## Security And Recovery
Every provider is tenant-bound. Missing or conflicting authority fails closed.
@@ -46,9 +51,11 @@ The executable fixture in
`tests/test_institutional_governance_journey.py` proves SQL-backed Service,
Case, Party, Mandate, Committee meeting/agendum/vote/minute, and Decision state.
`tests/test_institutional_service_journey.py` separately proves exact Portal
Form launch, persisted submission provenance, and idempotent replay.
Form launch, persisted submission provenance, idempotent replay, and a durable
Workflow handoff that remains visible through Tasks after the database session
is reopened and disappears only after the Workflow Engine records completion.
Module-level Records source tests prove exact Form submission, Case revision,
and Decision revision filing. Target-environment browser accessibility,
resumable work guidance, production identity and delivery, a named archive
profile, and recovery evidence are still required before this product package
may claim `reference_ready` maturity.
production identity and delivery, a named archive profile, and recovery evidence
are still required before this product package may claim `reference_ready`
maturity.
+1
View File
@@ -35,6 +35,7 @@
-e ../govoplan-dataflow
-e ../govoplan-workflow-engine
-e ../govoplan-workflow
-e ../govoplan-tasks
-e ../govoplan-views
-e ../govoplan-voting
-e ../govoplan-search
+238 -8
View File
@@ -2,11 +2,14 @@ from __future__ import annotations
from dataclasses import dataclass
from datetime import UTC, datetime, timedelta
from types import SimpleNamespace
import unittest
from sqlalchemy import create_engine
from sqlalchemy.orm import Session
from sqlalchemy.orm import Session, sessionmaker
from govoplan_core.auth import ApiPrincipal
from govoplan_core.core.access import PrincipalRef
from govoplan_core.core.institutional import (
CAPABILITY_FORM_DEFINITIONS,
CAPABILITY_SERVICE_DEFINITIONS,
@@ -18,6 +21,17 @@ from govoplan_core.core.institutional import (
TemporalRevision,
service_launch_capability,
)
from govoplan_core.core.runtime_coordination import (
DistributedLease,
RuntimeIdentity,
bind_process_runtime_identity,
)
from govoplan_core.core.tasks import (
RegisteredWorkItemProvider,
WorkItemProviderRegistration,
WorkItemQuery,
)
from govoplan_core.core.recovery import RecoveryCheckpoint, RecoveryOperation
from govoplan_cases.backend.service_intake import (
CAPABILITY_CASES_SERVICE_INTAKE,
CaseServiceIntake,
@@ -37,6 +51,34 @@ from govoplan_forms_runtime.backend.service import (
FormsServiceLauncher,
)
from govoplan_portal.backend.service_directory import PortalServiceDirectory
from govoplan_tasks.backend.aggregation import aggregate_work_items
from govoplan_workflow_engine.backend.db.models import (
WorkflowDefinition,
WorkflowDefinitionRevision,
WorkflowInstance,
WorkflowInstanceEvent,
WorkflowInstanceStep,
WorkflowTrigger,
WorkflowTriggerDelivery,
WorkflowWaitState,
)
from govoplan_workflow_engine.backend.instance_service import (
resolve_step,
start_instance,
)
from govoplan_workflow_engine.backend.schemas import (
WorkflowDefinitionCreateRequest,
WorkflowEdge,
WorkflowGraph,
WorkflowInstanceStartRequest,
WorkflowNode,
WorkflowStepActionRequest,
)
from govoplan_workflow_engine.backend.service import (
activate_definition,
create_definition,
)
from govoplan_workflow_engine.backend.work_items import WorkflowWorkItemProvider
NOW = datetime(2026, 8, 1, 10, 0, tzinfo=UTC)
@@ -74,10 +116,14 @@ class _Provider:
def __init__(self, definition: ServiceDefinition) -> None:
self.definition = definition
def get_service_definition(self, session, principal, *, reference, effective_at=None):
def get_service_definition(
self, session, principal, *, reference, effective_at=None
):
return self.definition
def list_service_definitions(self, session, principal, *, tenant_id, query="", limit=100):
def list_service_definitions(
self, session, principal, *, tenant_id, query="", limit=100
):
return (self.definition,)
@@ -111,17 +157,58 @@ class _Principal:
class _FormRegistry(_Registry):
def __init__(self, definition: ServiceDefinition) -> None:
super().__init__(definition)
self.capabilities[CAPABILITY_FORM_DEFINITIONS] = (
SqlFormDefinitionProvider()
)
self.capabilities[service_launch_capability("form")] = (
FormsServiceLauncher(self)
self.capabilities[CAPABILITY_FORM_DEFINITIONS] = SqlFormDefinitionProvider()
self.capabilities[service_launch_capability("form")] = FormsServiceLauncher(
self
)
def has(self, module_id: str) -> bool:
return module_id in {"portal", "forms", "forms_runtime"}
class _WorkflowTaskRegistry:
def __init__(self) -> None:
self.provider = WorkflowWorkItemProvider(registry=self)
self.registered = RegisteredWorkItemProvider(
module_id="workflow_engine",
registration=WorkItemProviderRegistration(
id="workflow_engine.handoffs",
factory=lambda _context: self.provider,
order=20,
),
)
def has_capability(self, _name: str) -> bool:
return False
def capability(self, name: str) -> object:
raise KeyError(name)
def work_item_providers(self):
return ((self.registered, self.provider),)
def _workflow_principal() -> ApiPrincipal:
return ApiPrincipal(
principal=PrincipalRef(
account_id="account-1",
membership_id="membership-1",
tenant_id="tenant-1",
scopes=frozenset(
{
"tasks:item:read",
"workflow:definition:read",
"workflow:instance:read",
"workflow:instance:start",
"workflow:instance:transition",
}
),
),
account=SimpleNamespace(id="account-1"),
user=SimpleNamespace(id="membership-1"),
)
class InstitutionalServiceJourneyTests(unittest.TestCase):
def test_one_service_version_drives_portal_and_case_intake(self) -> None:
definition = _service()
@@ -266,6 +353,149 @@ class InstitutionalServiceJourneyTests(unittest.TestCase):
session.close()
engine.dispose()
def test_workflow_handoff_survives_session_reopen_and_projects_into_tasks(
self,
) -> None:
engine = create_engine("sqlite+pysqlite:///:memory:")
tables = (
DistributedLease.__table__,
RecoveryOperation.__table__,
RecoveryCheckpoint.__table__,
WorkflowDefinition.__table__,
WorkflowDefinitionRevision.__table__,
WorkflowInstance.__table__,
WorkflowInstanceStep.__table__,
WorkflowInstanceEvent.__table__,
WorkflowTrigger.__table__,
WorkflowTriggerDelivery.__table__,
WorkflowWaitState.__table__,
)
for table in tables:
table.create(engine)
sessions = sessionmaker(bind=engine)
registry = _WorkflowTaskRegistry()
principal = _workflow_principal()
bind_process_runtime_identity(
RuntimeIdentity(
installation_id="service-journey",
node_id="journey-node",
incarnation="journey-run",
role="web",
software_version="test",
composition_hash="c" * 64,
)
)
try:
with sessions() as session:
definition = create_definition(
session,
tenant_id="tenant-1",
actor_id="account-1",
payload=WorkflowDefinitionCreateRequest(
name="Permit decision",
graph=WorkflowGraph(
nodes=[
WorkflowNode(
id="start",
type="workflow.start.manual",
),
WorkflowNode(
id="review",
type="workflow.activity",
config={
"title": "Decide the permit application",
"instructions": "Review the filed evidence and record the decision.",
"assignee": "account:account-1",
"due_after": "2d",
},
),
WorkflowNode(
id="done",
type="workflow.end.completed",
),
],
edges=[
WorkflowEdge(
id="start-review",
source="start",
target="review",
),
WorkflowEdge(
id="review-done",
source="review",
target="done",
),
],
),
execution_mode="guided",
),
)
activate_definition(
session,
tenant_id="tenant-1",
definition_id=definition.id,
actor_id="account-1",
)
instance, replayed = start_instance(
session,
tenant_id="tenant-1",
definition_id=definition.id,
actor_id="account-1",
principal=principal,
registry=registry,
payload=WorkflowInstanceStartRequest(
idempotency_key="permit-decision-1",
input={"case_id": "case-1"},
correlation_id="case-1",
),
)
self.assertFalse(replayed)
session.commit()
instance_id = instance.id
step_id = instance.current_step_id
with sessions() as reopened:
work = aggregate_work_items(
registry,
reopened,
principal,
query=WorkItemQuery(tenant_id="tenant-1"),
)
self.assertEqual(1, work.total)
self.assertEqual(step_id, work.items[0].id)
self.assertEqual(
"Decide the permit application",
work.items[0].title,
)
self.assertTrue(work.items[0].action_url.startswith("/workflow?"))
self.assertIn(f"run={instance_id}", work.items[0].action_url)
resolve_step(
reopened,
tenant_id="tenant-1",
instance_id=instance_id,
step_id=step_id,
actor_id="account-1",
principal=principal,
registry=registry,
payload=WorkflowStepActionRequest(action="complete"),
)
reopened.commit()
with sessions() as verified:
self.assertEqual(
0,
aggregate_work_items(
registry,
verified,
principal,
query=WorkItemQuery(tenant_id="tenant-1"),
).total,
)
finally:
bind_process_runtime_identity(None)
engine.dispose()
if __name__ == "__main__":
unittest.main()
@@ -54,6 +54,7 @@ FULL_MODULES = (
"dataflow",
"workflow_engine",
"workflow",
"tasks",
"views",
"search",
"risk_compliance",
@@ -1819,6 +1819,13 @@
"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"
},
{
"category": "intentionally_headless",
"method": "GET",
"path": "/tasks/{}",
"rationale": "Task command clients retrieve one explicit task and its strong revision token; the Work UI already receives the same projection through the aggregated list.",
"repository": "govoplan-tasks"
}
],
"schema_version": 1
+1 -1
View File
@@ -51,7 +51,7 @@ set +a
export APP_ENV="${APP_ENV:-staging}"
export GOVOPLAN_INSTALL_PROFILE="${GOVOPLAN_INSTALL_PROFILE:-production-like}"
export ENABLED_MODULES="${ENABLED_MODULES:-tenancy,organizations,identity,idm,access,admin,dashboard,policy,audit,campaigns,files,mail,calendar,poll,scheduling,connectors,datasources,dataflow,dist_lists,templates,workflow_engine,workflow,views,search,risk_compliance,notifications,docs,ops}"
export ENABLED_MODULES="${ENABLED_MODULES:-tenancy,organizations,identity,idm,access,admin,dashboard,policy,audit,campaigns,files,mail,calendar,poll,scheduling,connectors,datasources,dataflow,dist_lists,templates,workflow_engine,workflow,tasks,views,search,risk_compliance,notifications,docs,ops}"
export DATABASE_URL="${DATABASE_URL:-${GOVOPLAN_PRODUCTION_LIKE_DATABASE_URL:-postgresql+psycopg://govoplan:govoplan-dev@127.0.0.1:55433/govoplan}}"
export GOVOPLAN_DATABASE_URL_PGTOOLS="${GOVOPLAN_DATABASE_URL_PGTOOLS:-${GOVOPLAN_PRODUCTION_LIKE_DATABASE_URL_PGTOOLS:-postgresql://govoplan:govoplan-dev@127.0.0.1:55433/govoplan}}"
export REDIS_URL="${REDIS_URL:-${GOVOPLAN_PRODUCTION_LIKE_REDIS_URL:-redis://127.0.0.1:56379/0}}"
+1 -1
View File
@@ -66,7 +66,7 @@ export DATABASE_URL="${DATABASE_URL:-${GOVOPLAN_PRODUCTION_LIKE_DATABASE_URL:-po
export GOVOPLAN_DATABASE_URL_PGTOOLS="${GOVOPLAN_DATABASE_URL_PGTOOLS:-${GOVOPLAN_PRODUCTION_LIKE_DATABASE_URL_PGTOOLS:-postgresql://govoplan:govoplan-dev@127.0.0.1:55433/govoplan}}"
export REDIS_URL="${REDIS_URL:-${GOVOPLAN_PRODUCTION_LIKE_REDIS_URL:-redis://127.0.0.1:56379/0}}"
export CELERY_ENABLED="${CELERY_ENABLED:-true}"
export ENABLED_MODULES="${ENABLED_MODULES:-tenancy,organizations,identity,idm,access,admin,dashboard,policy,audit,campaigns,files,mail,calendar,poll,scheduling,connectors,datasources,dataflow,dist_lists,templates,workflow_engine,workflow,views,search,risk_compliance,notifications,docs,ops}"
export ENABLED_MODULES="${ENABLED_MODULES:-tenancy,organizations,identity,idm,access,admin,dashboard,policy,audit,campaigns,files,mail,calendar,poll,scheduling,connectors,datasources,dataflow,dist_lists,templates,workflow_engine,workflow,tasks,views,search,risk_compliance,notifications,docs,ops}"
export FILE_STORAGE_BACKEND="${FILE_STORAGE_BACKEND:-local}"
export FILE_STORAGE_LOCAL_ROOT="${FILE_STORAGE_LOCAL_ROOT:-$META_ROOT/runtime/production-like/files}"
export DEV_AUTO_MIGRATE_ENABLED="${DEV_AUTO_MIGRATE_ENABLED:-false}"