test_security_governance_contract.py 4.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. from pathlib import Path
  2. from app.core.system.permissions import (
  3. SECURITY_GOVERNANCE_MANAGE,
  4. SECURITY_GOVERNANCE_OPERATE,
  5. SECURITY_GOVERNANCE_READ,
  6. permission_for_request,
  7. permissions_for_roles,
  8. )
  9. ROOT = Path(__file__).resolve().parents[1]
  10. def test_security_migration_is_additive_forward_only_and_evidence_bearing():
  11. migration = (ROOT / "migrations/versions/20260802_460_security_governance.py").read_text()
  12. assert 'revision = "20260802_460"' in migration
  13. assert 'down_revision = "20260802_450"' in migration
  14. for table in (
  15. "security_classification_profiles", "security_classification_scans",
  16. "security_classification_findings", "security_access_policies",
  17. "security_access_decisions", "security_egress_requests",
  18. "security_retention_policies", "security_siem_sinks",
  19. "security_siem_deliveries", "security_sboms",
  20. "security_vulnerabilities", "security_governance_events",
  21. "access_control_audit_events",
  22. ):
  23. assert f"CREATE TABLE public.{table}" in migration
  24. assert "raise RuntimeError" in migration
  25. assert "DROP TABLE" not in migration.upper()
  26. def test_security_permission_matrix_is_monotonic_and_risk_aware():
  27. assert SECURITY_GOVERNANCE_READ in permissions_for_roles(["viewer"])
  28. assert SECURITY_GOVERNANCE_OPERATE not in permissions_for_roles(["viewer"])
  29. assert SECURITY_GOVERNANCE_OPERATE in permissions_for_roles(["editor"])
  30. assert SECURITY_GOVERNANCE_MANAGE not in permissions_for_roles(["editor"])
  31. assert SECURITY_GOVERNANCE_MANAGE in permissions_for_roles(["admin"])
  32. assert permission_for_request("/api/system/security-governance/dashboard", "GET") == (SECURITY_GOVERNANCE_READ,)
  33. assert permission_for_request("/api/system/security-governance/scans", "POST") == (SECURITY_GOVERNANCE_OPERATE,)
  34. assert permission_for_request("/api/system/security-governance/findings/x/review", "POST") == (SECURITY_GOVERNANCE_MANAGE,)
  35. assert permission_for_request("/api/system/security-governance/egress/x/reconcile", "POST") == (SECURITY_GOVERNANCE_MANAGE,)
  36. assert permission_for_request("/api/system/security-governance/sboms", "POST") == (SECURITY_GOVERNANCE_MANAGE,)
  37. def test_security_surface_reuses_work_center_and_expands_safe_audit_categories():
  38. repository = (ROOT / "app/core/system/security_governance_repository.py").read_text()
  39. service = (ROOT / "app/core/system/security_governance.py").read_text()
  40. audit = (ROOT / "app/core/system/governance_audit_repository.py").read_text()
  41. work_center = (ROOT / "app/core/governance/work_center.py").read_text()
  42. assert "UnifiedWorkCenterService" in repository
  43. assert '"data_egress"' in work_center
  44. assert '"security_request"' in work_center
  45. assert "highly_sensitive_egress_disabled" in service
  46. assert '"authorization"' in audit
  47. assert '"workflow_task"' in audit
  48. assert '"data_product"' in audit
  49. assert '"agent"' in audit
  50. assert '"security_governance"' in audit
  51. assert "sample_values" not in repository
  52. def test_data_security_workbench_replaces_placeholder_with_operational_surfaces():
  53. client = (ROOT / "frontend/src/api/securityGovernance.js").read_text()
  54. view = (ROOT / "frontend/src/views/dataGovernance/dataSecurity/index.vue").read_text()
  55. routes = (ROOT / "frontend/src/router/routes.js").read_text()
  56. for operation in (
  57. "listSecurityFindings", "reviewSecurityFinding", "evaluateSecurityAccess",
  58. "createSecurityEgress", "reconcileSecurityEgress", "listSecurityRetention",
  59. "dispatchSecuritySiem", "registerSecuritySbom", "importSecurityVulnerabilities",
  60. "assignSecurityVulnerability", "resolveSecurityVulnerability", "closeSecurityVulnerability",
  61. ):
  62. assert operation in client
  63. for capability in (
  64. "数据安全治理", "分类发现与人工复核", "访问决策", "出域审批",
  65. "SBOM 与漏洞整改", "审计投递", "留存边界", "高敏感数据出域默认拒绝",
  66. "样本原值不落库", "不会自动删除",
  67. ):
  68. assert capability in view
  69. assert "功能将在后续迭代中建设" not in view
  70. assert "security-governance:read" in routes