feat(xrechnung): validate inbound invoices fail closed
Module Package Release / publish-packages (push) Successful in 12s
Module Package Release / publish-packages (push) Successful in 12s
This commit is contained in:
@@ -0,0 +1,144 @@
|
||||
from __future__ import annotations
|
||||
|
||||
from govoplan_core.core.access import (
|
||||
CAPABILITY_AUTH_PERMISSION_EVALUATOR,
|
||||
CAPABILITY_AUTH_PRINCIPAL_RESOLVER,
|
||||
)
|
||||
from govoplan_core.core.modules import (
|
||||
DocumentationCondition,
|
||||
DocumentationLink,
|
||||
DocumentationTopic,
|
||||
ModuleManifest,
|
||||
PermissionDefinition,
|
||||
RoleTemplate,
|
||||
)
|
||||
from govoplan_core.core.provider_governance import declared_module_architecture
|
||||
|
||||
|
||||
MODULE_ID = "xrechnung"
|
||||
MODULE_VERSION = "0.1.19"
|
||||
READ_SCOPE = "xrechnung:validation:read"
|
||||
EXECUTE_SCOPE = "xrechnung:validation:execute"
|
||||
HANDOFF_SCOPE = "xrechnung:handoff:create"
|
||||
|
||||
|
||||
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="XRechnung",
|
||||
level="tenant",
|
||||
module_id=module_id,
|
||||
resource=resource,
|
||||
action=action,
|
||||
)
|
||||
|
||||
|
||||
manifest = ModuleManifest(
|
||||
id=MODULE_ID,
|
||||
name="XRechnung",
|
||||
version=MODULE_VERSION,
|
||||
dependencies=("access",),
|
||||
optional_dependencies=("files", "procurement", "payments", "records", "audit"),
|
||||
required_capabilities=(
|
||||
CAPABILITY_AUTH_PRINCIPAL_RESOLVER,
|
||||
CAPABILITY_AUTH_PERMISSION_EVALUATOR,
|
||||
),
|
||||
permissions=(
|
||||
_permission(READ_SCOPE, "View XRechnung validation", "Read validation profiles, outcomes, and non-secret diagnostics."),
|
||||
_permission(EXECUTE_SCOPE, "Validate inbound XRechnung", "Run a pinned local KoSIT profile against an inbound invoice."),
|
||||
_permission(HANDOFF_SCOPE, "Handoff validated XRechnung", "Create a digest-bound handoff only from technically complete valid evidence."),
|
||||
),
|
||||
role_templates=(
|
||||
RoleTemplate(
|
||||
slug="xrechnung_processor",
|
||||
name="XRechnung processor",
|
||||
description="Validate inbound invoices and create governed valid-invoice handoffs.",
|
||||
permissions=(READ_SCOPE, EXECUTE_SCOPE, HANDOFF_SCOPE),
|
||||
),
|
||||
RoleTemplate(
|
||||
slug="xrechnung_reviewer",
|
||||
name="XRechnung reviewer",
|
||||
description="Inspect validation profiles, results, and diagnostics without creating effects.",
|
||||
permissions=(READ_SCOPE,),
|
||||
),
|
||||
),
|
||||
documentation=(
|
||||
DocumentationTopic(
|
||||
id="xrechnung.inbound-validation",
|
||||
title="Validate and hand off an inbound XRechnung",
|
||||
summary="Verify safe invoice XML with an exact locally pinned KoSIT engine and rule tree, then create a digest-bound handoff only from complete valid evidence.",
|
||||
body=(
|
||||
"An administrator must approve an exact XRechnung version, KoSIT validator release, configuration release, configuration-tree digest, engine digest, scenario file, and minimum validation-step count. The connector verifies those artifacts before each run and never downloads rules while processing an invoice. It rejects dangerous XML before invoking Java. Runner exit, bounded output, technical error markers, VARL identity, matched scenario, configured validation-step count, validity flag, and exactly one accept or reject assessment are checked independently. Technical failure or partial reports yield unknown conformance and can never be handed off. A valid handoff binds tenant, source reference, invoice digest, report digest, and profile digest for an owning Procurement or Payments workflow."
|
||||
),
|
||||
layer="configured",
|
||||
documentation_types=("admin", "user"),
|
||||
audience=("user", "operator", "module_admin", "auditor"),
|
||||
related_modules=("files", "procurement", "payments", "records", "audit"),
|
||||
conditions=(
|
||||
DocumentationCondition(
|
||||
any_scopes=(READ_SCOPE, EXECUTE_SCOPE, HANDOFF_SCOPE),
|
||||
),
|
||||
),
|
||||
links=(
|
||||
DocumentationLink(
|
||||
label="Inbound validation profile",
|
||||
href="docs/INBOUND_VALIDATION.md",
|
||||
kind="repository",
|
||||
),
|
||||
),
|
||||
translations={
|
||||
"de": {
|
||||
"title": "Eingehende XRechnung prüfen und übergeben",
|
||||
"summary": "Sicheres Rechnungs-XML mit exakt lokal festgelegter KoSIT-Engine und Regelstruktur prüfen und nur aus vollständigem gültigem Nachweis eine prüfsummengebundene Übergabe erzeugen.",
|
||||
"body": "Administrierende müssen eine exakte XRechnungs-Version, KoSIT-Validator-Version, Konfigurationsversion, Prüfsumme der Konfigurationsstruktur, Engine-Prüfsumme, Szenariodatei und Mindestzahl der Prüfschritte freigeben. Der Konnektor prüft diese Artefakte vor jedem Lauf und lädt während der Rechnungsverarbeitung keine Regeln herunter. Gefährliches XML wird vor dem Java-Aufruf abgewiesen. Prozessende, begrenzte Ausgabe, technische Fehlermarker, VARL-Identität, erkanntes Szenario, konfigurierte Prüfschrittzahl, Gültigkeitskennzeichen und genau eine Annahme- oder Ablehnungsempfehlung werden unabhängig geprüft. Technische Fehler oder Teilberichte ergeben unbekannte Konformität und dürfen niemals übergeben werden. Eine gültige Übergabe bindet Mandant, Quellreferenz, Rechnungsprüfsumme, Berichtsprüfsumme und Profilprüfsumme für einen fachlich verantwortlichen Procurement- oder Payments-Ablauf.",
|
||||
}
|
||||
},
|
||||
metadata={
|
||||
"kind": "workflow",
|
||||
"prerequisites": [
|
||||
"An exact KoSIT engine and self-contained XRechnung configuration have been installed locally.",
|
||||
"The administrator has approved all artifact digests and the expected validation-step count.",
|
||||
"The owning invoice workflow supplies a stable tenant and source reference.",
|
||||
],
|
||||
"steps": [
|
||||
"Verify the executable, engine digest, complete configuration-tree digest, and scenario location.",
|
||||
"Reject unsafe or oversized XML, then run the pinned profile with bounded time and output.",
|
||||
"Check technical completeness separately from the report's semantic validity.",
|
||||
"Create a handoff only when the report is complete, formally valid, and accepts the invoice.",
|
||||
],
|
||||
"limitations": [
|
||||
"No XRechnung/configuration version is activated by default in this release.",
|
||||
"The connector creates a handoff contract but does not own payable approval or booking.",
|
||||
"A syntactically valid report is not trusted when runner output signals a technical failure.",
|
||||
],
|
||||
"consequences": [
|
||||
"Changing any pinned artifact changes the profile digest and requires a new validation.",
|
||||
"Invalid invoices retain diagnostics but cannot enter the valid-invoice handoff.",
|
||||
"Technical failure produces unknown conformance, never a semantic rejection or acceptance.",
|
||||
],
|
||||
"verification": "Confirm artifact and profile digests, technical outcome, validation-step count, formal validity, VARL assessment, invoice digest, and report digest before following the handoff reference.",
|
||||
},
|
||||
order=100,
|
||||
),
|
||||
),
|
||||
architecture=declared_module_architecture(
|
||||
layer="data_reporting_integration",
|
||||
kind="integration",
|
||||
maturity="vertical_slice",
|
||||
documentation_ref="docs/INBOUND_VALIDATION.md",
|
||||
test_ref="tests/test_validation.py",
|
||||
known_limits=("A deployment-approved XRechnung and KoSIT configuration profile is required; none is activated by default.",),
|
||||
owned_concepts=("XRechnung validation profile", "validation result", "validated invoice handoff"),
|
||||
non_owned_concepts=("invoice payable", "procurement approval", "booking status", "invoice file storage"),
|
||||
recovery_docs=("docs/INBOUND_VALIDATION.md",),
|
||||
security_docs=("docs/INBOUND_VALIDATION.md",),
|
||||
operations_docs=("docs/INBOUND_VALIDATION.md",),
|
||||
),
|
||||
)
|
||||
|
||||
|
||||
def get_manifest() -> ModuleManifest:
|
||||
return manifest
|
||||
Reference in New Issue
Block a user