feat: implement governed service directory

This commit is contained in:
2026-08-01 17:48:38 +02:00
parent cadac23162
commit ff44ed5f4a
17 changed files with 1948 additions and 0 deletions
+220
View File
@@ -0,0 +1,220 @@
from __future__ import annotations
from govoplan_core.core.institutional import (
CAPABILITY_SERVICE_AVAILABILITY,
CAPABILITY_SERVICE_DEFINITIONS,
service_launch_capability,
)
from govoplan_core.core.modules import (
CapabilityDocumentation,
DocumentationLink,
DocumentationTopic,
FrontendModule,
FrontendRoute,
ModuleContext,
ModuleInterfaceProvider,
ModuleInterfaceRequirement,
ModuleManifest,
NavItem,
PermissionDefinition,
RoleTemplate,
)
from govoplan_core.core.provider_governance import (
ModuleArchitectureDeclaration,
ModuleArchitectureDocumentation,
ModuleMaturityEvidence,
)
from govoplan_portal.backend.service_directory import (
CAPABILITY_PORTAL_SERVICE_DIRECTORY,
PortalServiceDirectory,
)
from govoplan_core.core.views import ViewSurface
MODULE_ID = "portal"
MODULE_VERSION = "0.1.8"
READ_SCOPE = "portal:service:read"
SERVICE_LAUNCH_CAPABILITIES = tuple(
service_launch_capability(kind) for kind in ("case", "form", "workflow")
)
def _service_directory(context: ModuleContext) -> PortalServiceDirectory:
return PortalServiceDirectory(context.registry)
def _router(context: ModuleContext):
from govoplan_portal.backend.router import configure_registry, router
configure_registry(context.registry)
return router
manifest = ModuleManifest(
id=MODULE_ID,
name="Portal",
version=MODULE_VERSION,
optional_dependencies=(
"access",
"services",
"cases",
"forms",
"forms_runtime",
"workflow_engine",
),
optional_capabilities=(
CAPABILITY_SERVICE_DEFINITIONS,
CAPABILITY_SERVICE_AVAILABILITY,
*SERVICE_LAUNCH_CAPABILITIES,
),
permissions=(
PermissionDefinition(
scope=READ_SCOPE,
label="View service directory",
description="Discover services available to the current account and function assignments.",
category="Portal",
level="tenant",
module_id=MODULE_ID,
resource="service",
action="read",
),
),
role_templates=(
RoleTemplate(
slug="portal_user",
name="Portal user",
description="Discover and enter available institutional services.",
permissions=(READ_SCOPE,),
default_authenticated=True,
),
),
provides_interfaces=(
ModuleInterfaceProvider(name="portal.service_directory", version="0.1.0"),
),
requires_interfaces=(
ModuleInterfaceRequirement(name="services.definition", version_min="0.1.0", version_max_exclusive="0.2.0", optional=True),
ModuleInterfaceRequirement(name="services.availability", version_min="0.1.0", version_max_exclusive="0.2.0", optional=True),
*(
ModuleInterfaceRequirement(
name=capability,
version_min="0.1.0",
version_max_exclusive="0.2.0",
optional=True,
)
for capability in SERVICE_LAUNCH_CAPABILITIES
),
),
capability_factories={
CAPABILITY_PORTAL_SERVICE_DIRECTORY: _service_directory,
},
route_factory=_router,
nav_items=(
NavItem(
path="/portal",
label="Services",
icon="landmark",
required_any=(READ_SCOPE,),
order=25,
),
),
frontend=FrontendModule(
module_id=MODULE_ID,
package_name="@govoplan/portal-webui",
routes=(
FrontendRoute(
path="/portal",
component="PortalPage",
required_any=(READ_SCOPE,),
order=25,
),
),
nav_items=(
NavItem(
path="/portal",
label="Services",
icon="landmark",
required_any=(READ_SCOPE,),
order=25,
),
),
view_surfaces=(
ViewSurface(
id="portal.navigation",
module_id=MODULE_ID,
kind="navigation",
label="Services navigation",
order=10,
),
ViewSurface(
id="portal.directory",
module_id=MODULE_ID,
kind="route",
label="Service directory",
order=20,
),
),
),
capability_documentation={
CAPABILITY_PORTAL_SERVICE_DIRECTORY: CapabilityDocumentation(
label="Portal service directory",
summary="Projects governed service definitions into role-aware availability entries.",
contract_version="0.1.0",
),
},
documentation=(
DocumentationTopic(
id="portal.service-directory",
title="Service directory",
summary="Find services available in the configured institution and understand relevant availability limits.",
body=(
"Portal presents provider-owned, versioned service definitions. "
"Published services may be available, unavailable with a reason, "
"or undiscoverable when they do not apply to the current audience. "
"Opening a service re-evaluates that exact revision and delegates case, "
"form, or workflow startup to an installed owner capability."
),
layer="available",
documentation_types=("admin", "user"),
audience=("user", "operator", "module_admin"),
links=(
DocumentationLink(
label="Service directory architecture",
href="govoplan-portal/docs/SERVICE_DIRECTORY_CONCEPT.md",
kind="repository",
),
),
),
),
architecture=ModuleArchitectureDeclaration(
layer="communication_participation",
kind="domain",
maturity="vertical_slice",
evidence=(
ModuleMaturityEvidence(
kind="test",
reference="tests/test_service_directory.py",
summary="Proves provider-neutral service discovery and explained availability.",
),
ModuleMaturityEvidence(
kind="documentation",
reference="docs/SERVICE_DIRECTORY_CONCEPT.md",
summary="Defines Portal presentation and Services ownership boundaries.",
),
),
known_limits=(
"Portal does not persist service definitions; the Services provider remains authoritative.",
"Case, Forms Runtime, and Workflow Engine own launch effects. Portal keeps entries unavailable whenever the selected owner capability is absent.",
),
owned_concepts=("service discovery", "service presentation", "channel entry"),
non_owned_concepts=("institutional service definition", "case lifecycle"),
reference_packages=("product.service-to-decision",),
documentation=ModuleArchitectureDocumentation(
security=("docs/SERVICE_DIRECTORY_CONCEPT.md",),
operations=("docs/SERVICE_DIRECTORY_CONCEPT.md",),
),
),
)
def get_manifest() -> ModuleManifest:
return manifest