From 788de9a2452c7242fc83712ccdbe37972d5cfd37 Mon Sep 17 00:00:00 2001 From: Xiaoxia AI Date: Sun, 21 Jun 2026 02:15:56 +0800 Subject: [PATCH] refactor(adapters): deprecate postgres repository path --- docs/全面代码审计报告-2026-06-21.md | 20 ++++++++++++++++- packages/adapters/postgres/__init__.py | 26 ++++++++-------------- tests/unit/test_architecture_boundaries.py | 16 +++++++++++++ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/docs/全面代码审计报告-2026-06-21.md b/docs/全面代码审计报告-2026-06-21.md index 9acafe449..629a311dc 100644 --- a/docs/全面代码审计报告-2026-06-21.md +++ b/docs/全面代码审计报告-2026-06-21.md @@ -176,6 +176,24 @@ - 新增 `tests/unit/test_architecture_boundaries.py`,防止 route 层再次直接 import SQLAlchemy adapter。 - 同时守住 `domain.auth` 不再导出 Redis/SMTP 全局单例。 +### 10. P1:Postgres psycopg Adapter 与 SQLAlchemy Adapter 双轨 + +**涉及文件**:`packages/adapters/postgres/__init__.py`、`tests/unit/test_architecture_boundaries.py` + +**问题**: +- `packages/adapters/postgres/*` 与 `packages/adapters/sqlalchemy_impl/*` 同时存在。 +- 主运行链路实际使用 SQLAlchemy,但旧 postgres package 仍可被新代码误导入。 +- 双仓储会造成连接池、事务、模型字段、schema 迁移多头漂移。 + +**根因**: +- 历史 psycopg 实现被 SQLAlchemy 替代后没有明确废弃边界。 +- 缺少测试禁止运行时代码继续引用旧 adapter。 + +**修复**: +- `packages/adapters/postgres/__init__.py` 标记为 deprecated,并在导入 package 时抛出明确错误。 +- 新增架构守卫:`apps/`、`packages/`、`tests/` 非 postgres adapter 目录不得 import `packages.adapters.postgres` 或 `Postgres*`。 +- SQLAlchemy 明确为 SaaS 当前唯一主线持久化 adapter。 + ## 三、已补充测试 ### 新增 @@ -199,7 +217,7 @@ python -m pytest tests/unit/test_architecture_boundaries.py tests/unit/test_auth python -m pytest tests/unit/test_login_use_case.py tests/unit/test_register_user_use_case.py tests/unit/test_password_reset_use_case.py tests/unit/test_invite_member_use_case.py tests/unit/test_session_store.py tests/unit/test_email_service.py -q ``` -结果:`31 passed`,`52 passed` +结果:`33 passed`,`52 passed` ## 四、仍需继续治理的问题 diff --git a/packages/adapters/postgres/__init__.py b/packages/adapters/postgres/__init__.py index b80711f1b..bcad4c3c4 100644 --- a/packages/adapters/postgres/__init__.py +++ b/packages/adapters/postgres/__init__.py @@ -1,18 +1,10 @@ -""" -PostgreSQL 适配器 -""" -from packages.adapters.postgres.asset_repository import PostgresAssetRepository -from packages.adapters.postgres.project_repository import PostgresProjectRepository -from packages.adapters.postgres.user_repository import PostgresUserRepository -from packages.adapters.postgres.workspace_invitation_repository import PostgresWorkspaceInvitationRepository -from packages.adapters.postgres.workspace_member_repository import PostgresWorkspaceMemberRepository -from packages.adapters.postgres.workspace_repository import PostgresWorkspaceRepository +"""Deprecated psycopg/Postgres repository adapters. -__all__ = [ - "PostgresAssetRepository", - "PostgresUserRepository", - "PostgresWorkspaceRepository", - "PostgresWorkspaceMemberRepository", - "PostgresWorkspaceInvitationRepository", - "PostgresProjectRepository", -] +SQLAlchemy is the canonical persistence adapter for the SaaS runtime. This +package is kept only as a migration marker; do not import it in application, +API, worker, or new tests. +""" + +raise RuntimeError( + "packages.adapters.postgres is deprecated; use packages.adapters.sqlalchemy_impl instead" +) diff --git a/tests/unit/test_architecture_boundaries.py b/tests/unit/test_architecture_boundaries.py index b899a3552..d5481582f 100644 --- a/tests/unit/test_architecture_boundaries.py +++ b/tests/unit/test_architecture_boundaries.py @@ -26,3 +26,19 @@ def test_domain_auth_does_not_export_infrastructure_singletons(): assert "email_service," not in text assert '"session_store"' not in text assert '"email_service"' not in text + + +def test_runtime_code_does_not_import_deprecated_postgres_adapters(): + roots = [Path("apps"), Path("packages"), Path("tests")] + offenders: list[str] = [] + for root in roots: + for path in root.rglob("*.py"): + if path.resolve() == Path(__file__).resolve(): + continue + if path.parts[:3] == ("packages", "adapters", "postgres"): + continue + text = path.read_text(encoding="utf-8") + if "packages.adapters.postgres" in text or "Postgres" in text: + offenders.append(str(path)) + + assert offenders == []