feat: govern file lifecycle and connector writes

This commit is contained in:
2026-08-20 22:06:57 +02:00
parent 95aef18955
commit 6c3cf1c55e
27 changed files with 2721 additions and 65 deletions
+15 -1
View File
@@ -17,6 +17,7 @@ from govoplan_files.backend.routes.folders import router as folders_router
from govoplan_files.backend.routes.form_evidence import router as form_evidence_router
from govoplan_files.backend.routes.integrity import router as integrity_router
from govoplan_files.backend.routes.listing import router as listing_router
from govoplan_files.backend.routes.lifecycle import router as lifecycle_router
from govoplan_files.backend.routes.shares import router as shares_router
from govoplan_files.backend.routes.spaces import router as spaces_router
from govoplan_files.backend.routes.transfers import router as transfers_router
@@ -38,6 +39,7 @@ class FilesRouterContractTests(unittest.TestCase):
folders_router,
form_evidence_router,
integrity_router,
lifecycle_router,
listing_router,
uploads_router,
connector_settings_router,
@@ -55,7 +57,7 @@ class FilesRouterContractTests(unittest.TestCase):
actual = self._operation_keys(router)
self.assertEqual(expected, actual)
self.assertEqual(54, len(actual))
self.assertEqual(62, len(actual))
self.assertFalse(
[operation for operation, count in Counter(actual).items() if count > 1]
)
@@ -81,6 +83,7 @@ class FilesRouterContractTests(unittest.TestCase):
(("GET",), "/files/connectors/profiles/{profile_id}/browse"),
(("POST",), "/files/connectors/profiles/{profile_id}/import"),
(("POST",), "/files/connectors/profiles/{profile_id}/sync"),
(("POST",), "/files/connector-spaces/{space_id}/write-back"),
(("GET",), "/files/connectors/credentials"),
(("POST",), "/files/connectors/credentials"),
(("GET",), "/files/connector-spaces"),
@@ -119,6 +122,17 @@ class FilesRouterContractTests(unittest.TestCase):
routes,
)
def test_governed_lifecycle_routes_are_exposed(self) -> None:
routes = {
(tuple(sorted(route.methods or ())), route.path) for route in router.routes
}
self.assertIn((("PATCH",), "/files/{file_id}/lifecycle"), routes)
self.assertIn((("POST",), "/files/assets/{file_id}/restore"), routes)
self.assertIn((("POST",), "/files/purge/preview"), routes)
self.assertIn((("POST",), "/files/purge/execute"), routes)
self.assertIn((("POST",), "/files/purge/blobs"), routes)
def test_file_listing_exposes_structured_property_filters(self) -> None:
route = next(
route