feat: validate receipt-bound storage configuration

This commit is contained in:
2026-08-07 11:15:50 +02:00
parent 04e2bae190
commit cb37079465
5 changed files with 906 additions and 0 deletions
+64
View File
@@ -48,6 +48,9 @@ from govoplan_core.core.search import SearchSourceProviderRegistration
from govoplan_core.core.views import ViewSurface
from govoplan_core.db.base import Base
from govoplan_files.backend.change_tracking import register_files_change_tracking
from govoplan_files.backend.configuration_provider import (
FILES_CONFIGURATION_CAPABILITY,
)
from govoplan_files.backend.db import models as file_models # noqa: F401 - populate Files ORM metadata
from govoplan_files.backend.documentation import documentation_topics
from govoplan_files.backend.form_evidence import (
@@ -85,6 +88,15 @@ _files_table_retirement_provider = drop_table_retirement_provider(
)
def _configuration_provider(context: ModuleContext) -> object:
del context
from govoplan_files.backend.configuration_provider import (
FilesConfigurationProvider,
)
return FilesConfigurationProvider()
def _files_retirement_provider(session: object | None, module_id: str):
plan = _files_table_retirement_provider(session, module_id)
base_executor = plan.destroy_data_executor
@@ -568,6 +580,57 @@ manifest = ModuleManifest(
),
),
documentation=(
DocumentationTopic(
id="files.configuration-package.managed-storage",
title="Validate deployment-managed file storage",
summary="Compare Files runtime storage with the non-secret deployment receipt without rewriting infrastructure settings.",
body=(
"The Files configuration provider validates the files.storage capability against the effective local or S3 runtime. "
"It checks the backend, sanitized endpoint, bucket, trust or management marker, durable local path, and presence of referenced environment secrets. "
"Matching configuration is already effective and therefore reports skip on every apply. Drift blocks the package; Files never copies secret values, rewrites process environment, "
"or treats a storage replacement as an implicit migration. Run Files integrity and Ops checks after deployment changes."
),
layer="configured",
documentation_types=("admin",),
audience=("file_manager", "administrator", "operator"),
related_modules=("core", "ops"),
conditions=(
DocumentationCondition(
required_modules=("files", "access"),
any_scopes=("admin:settings:read", "system:settings:read"),
),
),
links=(
DocumentationLink(
label="Configuration packages",
href="/admin?section=configuration-packages",
kind="runtime",
),
DocumentationLink(
label="Files handbook",
href="govoplan-files/docs/FILES_HANDBOOK.md",
kind="repository",
),
),
translations={
"de": {
"title": "Bereitstellungsverwalteten Dateispeicher prüfen",
"summary": "Den Laufzeitspeicher von Files mit dem nicht geheimen Bereitstellungsnachweis vergleichen, ohne Infrastruktureinstellungen umzuschreiben.",
"body": (
"Der Files-Konfigurationsprovider prüft die Fähigkeit files.storage gegen die wirksame lokale oder S3-Laufzeitkonfiguration. "
"Geprüft werden Backend, bereinigter Endpunkt, Bucket, Vertrauens- oder Verwaltungskennzeichen, dauerhafter lokaler Pfad sowie das Vorhandensein referenzierter Umgebungsgeheimnisse. "
"Eine passende Konfiguration ist bereits wirksam und meldet deshalb bei jeder Anwendung skip. Abweichungen blockieren das Paket; Files kopiert keine Geheimwerte, verändert keine Prozessumgebung "
"und behandelt einen Speicherwechsel nicht als stillschweigende Migration. Nach Bereitstellungsänderungen sind die Integritäts- und Ops-Prüfungen auszuführen."
),
}
},
metadata={
"kind": "workflow",
"route": "/admin?section=configuration-packages",
"help_contexts": ["admin.configuration-packages", "files.admin.tenant-integrity"],
},
order=4,
),
DocumentationTopic(
id="files.quick-access-and-product-area",
title="Files in Records and documents and Quick Access",
@@ -1407,6 +1470,7 @@ manifest = ModuleManifest(
),
),
capability_factories={
FILES_CONFIGURATION_CAPABILITY: _configuration_provider,
CAPABILITY_FILES_ACCESS: lambda context: __import__(
"govoplan_files.backend.capabilities", fromlist=["access_capability"]
).access_capability(context),