Files
zemion fa807cdcf2
Module Package Release / publish-packages (push) Successful in 10s
docs(decisions): complete German public reference
2026-08-22 20:25:17 +02:00

330 lines
14 KiB
Python

from __future__ import annotations
from pathlib import Path
from govoplan_core.core.institutional import CAPABILITY_DECISION_REGISTRY
from govoplan_core.core.module_guards import (
drop_table_retirement_provider,
persistent_table_uninstall_guard,
)
from govoplan_core.core.modules import (
CapabilityDocumentation,
DocumentationLink,
DocumentationTopic,
MigrationSpec,
ModuleContext,
ModuleInterfaceProvider,
ModuleManifest,
PermissionDefinition,
RoleTemplate,
)
from govoplan_core.core.provider_governance import declared_module_architecture
from govoplan_core.core.search import SearchSourceProviderRegistration
from govoplan_core.db.base import Base
from govoplan_decisions.backend.db import models as decision_models
from govoplan_decisions.backend.dsar_provider import (
DECISIONS_DSAR_CAPABILITY,
DecisionsDsarProvider,
)
from govoplan_decisions.backend.record_source import (
CAPABILITY_RECORD_SOURCE_DECISIONS,
create_decisions_record_source,
)
from govoplan_decisions.backend.service import SqlDecisionRegistry
from govoplan_decisions.backend.search_source import create_decisions_search_source
MODULE_ID = "decisions"
MODULE_NAME = "Decisions"
MODULE_VERSION = "0.1.19"
READ_SCOPE = "decisions:decision:read"
SENSITIVE_READ_SCOPE = "decisions:decision:read_sensitive"
WRITE_SCOPE = "decisions:decision:write"
ADMIN_SCOPE = "decisions:decision:admin"
def _permission(scope: str, label: str, description: str) -> PermissionDefinition:
module_id, resource, action = scope.split(":", 2)
return PermissionDefinition(
scope=scope,
label=label,
description=description,
category="Decisions",
level="tenant",
module_id=module_id,
resource=resource,
action=action,
)
def _router(_context: ModuleContext):
from govoplan_decisions.backend.router import router
return router
def _registry(_context: ModuleContext) -> SqlDecisionRegistry:
return SqlDecisionRegistry()
def _dsar_provider(_context: ModuleContext) -> DecisionsDsarProvider:
return DecisionsDsarProvider()
manifest = ModuleManifest(
id=MODULE_ID,
name=MODULE_NAME,
version=MODULE_VERSION,
optional_dependencies=(
"mandates",
"approvals",
"committee",
"cases",
"audit",
"policy",
"records",
"files",
"postbox",
"mail",
),
provides_interfaces=(
ModuleInterfaceProvider(name="decisions.formal_outcome", version="0.1.0"),
ModuleInterfaceProvider(name="decisions.reconstruction", version="0.1.0"),
ModuleInterfaceProvider(
name=CAPABILITY_RECORD_SOURCE_DECISIONS, version="1.0.0"
),
ModuleInterfaceProvider(name=DECISIONS_DSAR_CAPABILITY, version="0.1.0"),
),
permissions=(
_permission(
READ_SCOPE,
"View Decision metadata",
"View formal Decision metadata and evidence references.",
),
_permission(
SENSITIVE_READ_SCOPE,
"View protected Decisions",
"View protected reasoning, operative results, and conditions.",
),
_permission(
WRITE_SCOPE,
"Record Decisions",
"Record governed formal outcomes and lifecycle revisions.",
),
_permission(
ADMIN_SCOPE,
"Administer Decisions",
"Administer Decision access, lifecycle, and recovery.",
),
),
role_templates=(
RoleTemplate(
slug="decision_officer",
name="Decision officer",
description="Record and inspect formal Decisions.",
permissions=(READ_SCOPE, SENSITIVE_READ_SCOPE, WRITE_SCOPE),
),
RoleTemplate(
slug="decision_auditor",
name="Decision auditor",
description="Reconstruct protected formal outcomes.",
permissions=(READ_SCOPE, SENSITIVE_READ_SCOPE),
),
),
route_factory=_router,
capability_factories={
CAPABILITY_DECISION_REGISTRY: _registry,
CAPABILITY_RECORD_SOURCE_DECISIONS: create_decisions_record_source,
DECISIONS_DSAR_CAPABILITY: _dsar_provider,
},
capability_documentation={
CAPABILITY_DECISION_REGISTRY: CapabilityDocumentation(
label="Formal Decision registry",
summary="Records and resolves immutable, reconstructable formal outcomes.",
contract_version="0.1.0",
),
CAPABILITY_RECORD_SOURCE_DECISIONS: CapabilityDocumentation(
label="Formal Decision record source",
summary="Resolves complete, currently authorized immutable Decision revisions for Records filing.",
contract_version="1.0.0",
),
DECISIONS_DSAR_CAPABILITY: CapabilityDocumentation(
label="Decisions data-subject request provider",
summary=(
"Exports minimized formal-Decision creator attribution without "
"protected reasoning, outcomes, conditions, or payloads."
),
contract_version="0.1.0",
),
},
migration_spec=MigrationSpec(
module_id=MODULE_ID,
metadata=Base.metadata,
script_location=str(Path(__file__).with_name("migrations") / "versions"),
retirement_supported=True,
retirement_provider=drop_table_retirement_provider(
decision_models.FormalDecisionRevision, label="Decisions"
),
retirement_notes="Destructive retirement requires a database snapshot and removes formal Decision history.",
),
uninstall_guard_providers=(
persistent_table_uninstall_guard(
decision_models.FormalDecisionRevision, label="Decisions"
),
),
search_sources=(
SearchSourceProviderRegistration(
id="decisions.decisions",
factory=create_decisions_search_source,
),
),
documentation=(
DocumentationTopic(
id="decisions.data-subject-requests",
title="Formal Decision data-subject requests",
summary=(
"Export minimized creator attribution from immutable formal Decision "
"revisions without exposing protected Decision content."
),
body=(
"Decisions searches exact account, membership, identity, or explicit "
"actor identifiers inside the active tenant. An optional Decision "
"identifier only narrows that verified actor search and cannot disclose "
"a Decision by itself. The access record contains revision, type, state, "
"valid-time, recorded-time, and creator activity only. Protected "
"reasoning, operative results, conditions, evidence payloads, and "
"digests remain excluded. Formal Decision history is immutable legal "
"and institutional evidence, so the provider publishes retain-only "
"erasure outcomes and never rewrites a revision."
),
layer="configured",
documentation_types=("admin", "user"),
audience=("user", "operator", "module_admin", "auditor"),
related_modules=("core", "approvals", "committee", "records"),
metadata={
"help_contexts": ["privacy.data-subject-requests"],
"consequence_classes": {
"export_creator_attribution": (
"Returns lifecycle and creator context without protected payloads."
),
"retain_formal_history": (
"Preserves immutable institutional and legal evidence."
),
},
},
translations={
"de": {
"title": "Datenschutzanfragen zu formellen Entscheidungen",
"summary": (
"Minimierte Angaben zur erstellenden Person aus unveränderlichen "
"Entscheidungsrevisionen exportieren, ohne geschützte Inhalte offenzulegen."
),
"body": (
"Decisions sucht innerhalb des aktiven Mandanten nach exakten Konto-, "
"Mitgliedschafts-, Identitäts- oder ausdrücklich angegebenen Akteurskennungen. "
"Eine optionale Entscheidungskennung schränkt nur diese bereits verifizierte "
"Akteurssuche ein und kann für sich allein keine Entscheidung offenlegen. Der "
"Ausgabedatensatz enthält ausschließlich Revision, Typ, Status, Gültigkeits- und "
"Aufzeichnungszeit sowie die Aktivität der erstellenden Person. Geschützte "
"Begründungen, verfügende Ergebnisse, Bedingungen, Nachweisinhalte und Prüfsummen "
"bleiben ausgeschlossen. Die Historie formeller Entscheidungen ist unveränderlicher "
"rechtlicher und institutioneller Nachweis; deshalb veröffentlicht der Anbieter "
"ausschließlich Aufbewahrungsergebnisse und schreibt keine Revision um."
),
}
},
structured_translation_version="1",
structured_translations={
"de": {
"consequence_classes": {
"export_creator_attribution": (
"Gibt Lebenszyklus- und Erstellerkontext ohne geschützte Inhalte zurück."
),
"retain_formal_history": (
"Bewahrt unveränderliche institutionelle und rechtliche Nachweise auf."
),
}
}
},
),
DocumentationTopic(
id="decisions.formal-outcome",
title="Formal institutional Decisions",
summary="Reconstruct authority, evidence, reasoning, outcome, effects, and review history.",
body="Decisions preserves immutable formal outcomes. Corrections and revocations create linked revisions; requested and observed effects remain distinct for reconciliation. List and unversioned detail reads follow the titlebar valid-time and recorded-time selection; exact revision references remain exact and current authorization is unchanged. When Records is enabled, filing resolves one exact complete Decision revision only after current metadata and protected-read permissions are rechecked; Records retains the digest-bound source reference while Decisions remains authoritative. When Search is enabled, Decisions contributes only rebuildable lifecycle, subject, legal-basis, effect, and linked-Case metadata. Operative results, reasoning, and conditions are excluded, and every result receives a current permission check before disclosure.",
layer="configured",
documentation_types=("admin", "user"),
audience=("user", "operator", "module_admin", "auditor"),
links=(
DocumentationLink(
label="Decisions domain and recovery",
href="govoplan-decisions/docs/DECISIONS_DOMAIN.md",
kind="repository",
),
),
metadata={
"kind": "reference",
"help_contexts": [
"decisions.search.result",
"decisions.record.filing",
],
},
translations={
"de": {
"title": "Formelle institutionelle Entscheidungen",
"summary": (
"Zuständigkeit, Nachweise, Begründung, Ergebnis, Wirkungen und "
"Überprüfungshistorie nachvollziehbar rekonstruieren."
),
"body": (
"Decisions bewahrt formelle Ergebnisse als unveränderliche Revisionen auf. "
"Berichtigungen und Widerrufe erzeugen verknüpfte Revisionen; beabsichtigte und "
"beobachtete Wirkungen bleiben für den Abgleich getrennt. Listen und nicht "
"versionierte Detailansichten folgen der in der Titelleiste gewählten Gültigkeits- "
"und Aufzeichnungszeit; exakte Revisionsverweise bleiben exakt und die aktuelle "
"Berechtigungsprüfung gilt unverändert. Ist Records aktiviert, wird nur eine exakte, "
"vollständige Entscheidungsrevision abgelegt, nachdem aktuelle Metadaten- und "
"Leseberechtigungen erneut geprüft wurden. Records bewahrt den prüfsummengebundenen "
"Quellverweis, während Decisions maßgeblich bleibt. Ist Search aktiviert, trägt "
"Decisions ausschließlich wiederaufbaubare Lebenszyklus-, Betreff-, Rechtsgrundlagen-, "
"Wirkungs- und Fallverknüpfungsmetadaten bei. Verfügende Ergebnisse, Begründungen und "
"Bedingungen bleiben ausgeschlossen; vor jeder Offenlegung wird die aktuelle "
"Berechtigung erneut geprüft."
),
}
},
),
),
architecture=declared_module_architecture(
layer="governance_accountability",
kind="domain",
maturity="vertical_slice",
documentation_ref="docs/DECISIONS_DOMAIN.md",
test_ref="tests/test_decisions.py",
known_limits=(
"No dedicated Decision WebUI is included; consuming procedure modules present outcomes in context.",
),
supported_authority_modes=("native_authoritative",),
owned_concepts=(
"formal decision",
"decision correction",
"decision effect observation",
),
non_owned_concepts=(
"approval gate",
"committee deliberation",
"effect execution",
"record binary",
),
reference_packages=("product.service-to-decision",),
migration_docs=("docs/DECISIONS_DOMAIN.md",),
recovery_docs=("docs/DECISIONS_DOMAIN.md",),
security_docs=("docs/DECISIONS_DOMAIN.md",),
operations_docs=("docs/DECISIONS_DOMAIN.md",),
),
)
def get_manifest() -> ModuleManifest:
return manifest