release(main): 同步 dev 最新候选改动
Storage Persistence Guard / storage-persistence-audit (push) Has been cancelled
Client Quality Gates / Shared client and Web (push) Has been cancelled
Client Quality Gates / macOS Desktop (push) Has been cancelled
Client Quality Gates / Shared client and Web (pull_request) Has been cancelled
Client Quality Gates / macOS Desktop (pull_request) Has been cancelled
Storage Persistence Guard / storage-persistence-audit (pull_request) Has been cancelled

This commit is contained in:
Cheng Zhou
2026-07-16 17:15:50 +08:00
parent 32167fba02
commit d5279b124f
393 changed files with 51630 additions and 9711 deletions
+44 -18
View File
@@ -272,6 +272,18 @@ def test_faq_and_precautions_are_shared_library_sibling_sections():
assert API_ENDPOINT_PERMISSIONS["precautions:read"]["module"] == "shared_library"
def test_collaboration_is_an_independent_shared_library_section():
shared_library_keys = OPERATION_TO_ENDPOINTS["shared_library"]
assert "collaboration:read" in shared_library_keys["read"]
assert "collaboration:create" in shared_library_keys["write"]
assert "collaboration:edit" in shared_library_keys["write"]
assert "collaboration:manage" in shared_library_keys["write"]
assert "collaboration:export" in shared_library_keys["write"]
assert "collaboration:delete" in shared_library_keys["write"]
assert API_ENDPOINT_PERMISSIONS["collaboration:read"]["module"] == "shared_library"
assert API_ENDPOINT_PERMISSIONS["collaboration:read"]["default_roles"] == ["PM", "CRA", "PV", "QA", "CTA"]
def test_precautions_runtime_code_uses_business_entity_names():
"""运行时代码不应继续使用 knowledge_note 作为注意事项实体命名。"""
backend_root = Path(__file__).resolve().parents[1] / "app"
@@ -565,6 +577,16 @@ def test_project_permission_config_is_system_level_permission():
assert "PM" in SYSTEM_PERMISSIONS["system:permissions:project_config"]["roles"]
def test_pm_system_management_navigation_matches_backend_permission_contract():
"""PM 系统管理导航中的审计日志和权限管理应与后端角色权限保持一致。"""
assert "PM" in API_ENDPOINT_PERMISSIONS["audit_logs:read"]["default_roles"]
assert "PM" in SYSTEM_PERMISSIONS["system:permissions:read"]["roles"]
assert "PM" in SYSTEM_PERMISSIONS["system:permissions:project_config"]["roles"]
audit_route = Path(__file__).resolve().parents[1] / "app" / "api" / "v1" / "audit_logs.py"
assert 'require_api_permission("audit_logs:read")' in audit_route.read_text()
def test_project_api_permission_routes_use_system_project_config_permission():
"""项目权限矩阵 API 应明确依赖 system:permissions:project_config。"""
route_path = Path(__file__).resolve().parents[1] / "app" / "api" / "v1" / "api_permissions.py"
@@ -652,24 +674,30 @@ def test_subject_audit_uses_structured_business_snapshot():
assert 'detail=f"参与者 {subject_id} 已删除"' not in delete_subject_source
def test_faq_audit_uses_business_descriptions():
"""医学咨询审计详情应使用业务描述,避免 FAQ 技术文案"""
def test_shared_library_does_not_write_audits():
"""共享库各模块及其附件不应写入业务审计"""
api_dir = Path(__file__).resolve().parents[1] / "app" / "api" / "v1"
category_source = (api_dir / "faq_categories.py").read_text()
item_source = (api_dir / "faqs.py").read_text()
services_dir = Path(__file__).resolve().parents[1] / "app" / "services"
non_audited_sources = [
(api_dir / "faq_categories.py").read_text(),
(api_dir / "faqs.py").read_text(),
(api_dir / "precautions.py").read_text(),
(services_dir / "collaboration_service.py").read_text(),
(services_dir / "collaboration_share_service.py").read_text(),
(services_dir / "onlyoffice_collaboration_service.py").read_text(),
]
assert 'description": f"创建“{category.name}”分类"' in category_source
assert 'description": f"更新“{updated.name}”分类"' in category_source
assert 'description": f"删除“{category_name}”分类"' in category_source
assert 'f"创建医学咨询问题“{question_name}"' in item_source
assert 'f"更新医学咨询问题“{question_name}"' in item_source
assert 'f"回复医学咨询问题“{question_name}"' in item_source
assert 'f"删除医学咨询问题“{question_name}"' in item_source
assert 'f"删除医学咨询问题“{question_name}”的回复"' in item_source
assert "FAQ 分类 {category.name} 已创建" not in category_source
assert 'detail="FAQ 已创建"' not in item_source
assert 'detail = "FAQ updated"' not in item_source
assert '"description": "创建医学咨询问题"' not in item_source
for source in non_audited_sources:
assert "audit_crud" not in source
assert "._audit(" not in source
attachment_source = (api_dir / "attachments.py").read_text()
assert 'SHARED_LIBRARY_ENTITY_TYPES = {"precaution", "faq_replies"}' in attachment_source
assert "if entity_type not in SHARED_LIBRARY_ENTITY_TYPES:" in attachment_source
assert "if attachment.entity_type not in SHARED_LIBRARY_ENTITY_TYPES:" in attachment_source
onlyoffice_source = (api_dir / "onlyoffice.py").read_text()
assert "OFFICE_PREVIEW_OPEN" not in onlyoffice_source
def test_domain_audits_use_business_object_names():
@@ -682,7 +710,6 @@ def test_domain_audits_use_business_object_names():
"material_equipments.py",
"visits.py",
"aes.py",
"precautions.py",
"fees_contracts.py",
"startup.py",
"subject_histories.py",
@@ -693,7 +720,6 @@ def test_domain_audits_use_business_object_names():
assert "_equipment_audit_detail" in sources["material_equipments.py"]
assert "_visit_audit_detail" in sources["visits.py"]
assert "_ae_audit_detail" in sources["aes.py"]
assert "_precaution_audit_detail" in sources["precautions.py"]
assert "_contract_audit_detail" in sources["fees_contracts.py"]
assert "_payment_audit_detail" in sources["fees_contracts.py"]
assert "_feasibility_audit_detail" in sources["startup.py"]