feat: define bulk governance projection contract

This commit is contained in:
2026-08-20 19:46:53 +02:00
parent 604f20eed7
commit 8e687c4420
3 changed files with 212 additions and 0 deletions
+61
View File
@@ -5506,6 +5506,67 @@ class ApiSmokeTests(unittest.TestCase):
self.assertEqual(deleted_delta.status_code, 200, deleted_delta.text)
self.assertTrue(any(item["id"] == template_id and item["resource_type"] == "governance_template" for item in deleted_delta.json()["deleted"]))
def test_governance_template_bulk_synchronization_previews_and_applies(self) -> None:
headers, login = self._login()
tenant_id = login["tenant"]["id"]
approver_headers = self._create_system_approver(
headers,
tenant_id=tenant_id,
email="governance-sync-approver@example.local",
)
create_payload = {
"kind": "role",
"slug": "governance-sync",
"name": "Governance Sync",
"description": "Bulk reconciliation contract",
"permissions": ["admin:roles:read"],
"is_active": True,
"assignments": [{"tenant_id": tenant_id, "mode": "required"}],
}
change_request_id = self._approved_configuration_change(
headers,
approver_headers,
key="governance_templates",
value=create_payload,
target={"kind": "role", "slug": "governance-sync"},
)
created = self.client.post(
"/api/v1/admin/system/governance-templates",
headers=headers,
json={**create_payload, "change_request_id": change_request_id},
)
self.assertEqual(201, created.status_code, created.text)
template_id = created.json()["id"]
preview = self.client.post(
"/api/v1/admin/system/governance-templates/synchronize",
headers=headers,
json={"template_ids": [template_id], "dry_run": True},
)
self.assertEqual(200, preview.status_code, preview.text)
self.assertTrue(preview.json()["dry_run"])
self.assertEqual({"unchanged": 1}, preview.json()["counts"])
self.assertEqual("1", preview.json()["version"])
self.assertEqual("admin.bulk-synchronization", preview.json()["outcomes"][0]["provenance"]["source"])
applied = self.client.post(
"/api/v1/admin/system/governance-templates/synchronize",
headers=headers,
json={"template_ids": [template_id], "dry_run": False},
)
self.assertEqual(200, applied.status_code, applied.text)
self.assertFalse(applied.json()["dry_run"])
self.assertEqual({"unchanged": 1}, applied.json()["counts"])
audit = self.client.get(
"/api/v1/admin/audit",
headers=headers,
params={"all_tenants": True, "limit": 500},
)
actions = {item["action"] for item in audit.json()["items"]}
self.assertIn("governance_template.synchronization_previewed", actions)
self.assertIn("governance_template.synchronized", actions)
def test_module_installer_history_supports_cursor_windows(self) -> None:
from govoplan_core.core.module_installer import default_installer_runtime_dir