ForcePilot/backend/package/yuxi/channels/contract/dtos/identity_merge.py
Kris 6ddc2a8c25 feat: 新增批量配置查询、路由绑定管理等功能并优化现有逻辑
1. 新增config/get_many批量配置查询接口与Redis实现
2. 新增路由绑定相关端口与事件校验
3. 优化插件目录展示,新增last_error与重启提示字段
4. 新增插件配置更新与重启状态跟踪逻辑
5. 优化会话搜索参数支持,新增account_id过滤
6. 替换部分ValueError为ValidationError统一错误类型
7. 新增多类DTO与参数校验逻辑
8. 优化SQLAlchemy事务处理与乐观锁实现
9. 新增能力画像矩阵过滤功能
2026-07-11 15:52:20 +08:00

146 lines
5.6 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

"""身份合并回滚 DTOC-13
定义身份合并回滚用例的命令与结果值对象,供 ``IdentityMergeService`` 与
``identity/rollback-merge`` 控制面操作使用。所有 DTO 均为
``dataclass(frozen=True)``,仅依赖标准库,用于坏合并的回滚编排。
"""
from __future__ import annotations
from dataclasses import dataclass
from yuxi.channels.contract.errors import ValidationError
@dataclass(frozen=True)
class MergeRollbackCmd:
"""合并回滚命令。
将已合并的 sibling 从 canonical 分离,恢复 sibling 独立身份。
操作不可逆sibling 的 user_id 仅在 ``restore_user_id`` 非 None 时恢复),
调用方需确保 ``canonical_identity_id`` 与 ``merged_identity_id`` 确实
存在合并关系。
字段:
canonical_identity_id: 规范身份 ID合并目标
merged_identity_id: 被回滚的 sibling identity_id合并来源
restore_user_id: 恢复 sibling 的 user_id``None`` 时不恢复
sibling 保持未绑定系统用户状态)。默认为 ``None``。
"""
canonical_identity_id: str
merged_identity_id: str
restore_user_id: str | None = None
def __post_init__(self) -> None:
"""校验 canonical_identity_id 与 merged_identity_id 非空。
必填身份 ID 必须非空,在构造时即抛出 ``ValidationError``,避免空
ID 传播到 IdentityMergeService 后才暴露INV-8
"""
if not self.canonical_identity_id:
raise ValidationError("canonical_identity_id", "must not be empty")
if not self.merged_identity_id:
raise ValidationError("merged_identity_id", "must not be empty")
@dataclass(frozen=True)
class MergeRecord:
"""合并回滚结果记录。
描述一次合并回滚操作的产出,供控制面 handler 序列化返回给调用方。
字段:
canonical_identity_id: 规范身份 ID。
merged_identity_id: 被回滚的 sibling identity_id。
removed_bindings: 从 canonical 移除的 bindings结构为
``{channel_type: [peer_id, ...]}``(来自 sibling 的贡献)。
migrated_session_count: 迁移回 sibling 的会话数。
canonical_version: 回滚后 canonical 的内存版本号。
sibling_version: 回滚后 sibling 的内存版本号。
"""
canonical_identity_id: str
merged_identity_id: str
removed_bindings: dict[str, list[str]]
migrated_session_count: int
canonical_version: int
sibling_version: int
def __post_init__(self) -> None:
"""校验身份 ID 非空与计数/版本号非负。
``migrated_session_count`` / ``canonical_version`` /
``sibling_version`` 必须非负,在构造时即抛出 ``ValidationError``
避免负值进入控制面响应INV-8
"""
if not self.canonical_identity_id:
raise ValidationError("canonical_identity_id", "must not be empty")
if not self.merged_identity_id:
raise ValidationError("merged_identity_id", "must not be empty")
if self.migrated_session_count < 0:
raise ValidationError("migrated_session_count", "must not be negative")
if self.canonical_version < 0:
raise ValidationError("canonical_version", "must not be negative")
if self.sibling_version < 0:
raise ValidationError("sibling_version", "must not be negative")
@dataclass(frozen=True)
class MergeApproveCmd:
"""合并审批放行命令H-21
放行一个待审批的低置信度合并:将 ``pending_review`` 的 sibling 合并进
canonical清除 ``pending_review`` 标志。
字段:
canonical_identity_id: 规范身份 ID合并目标
merged_identity_id: 待审批的 sibling identity_id合并来源
"""
canonical_identity_id: str
merged_identity_id: str
def __post_init__(self) -> None:
"""校验 canonical_identity_id 与 merged_identity_id 非空。
必填身份 ID 必须非空,在构造时即抛出 ``ValidationError``,避免空
ID 传播到 IdentityMergeService 后才暴露INV-8
"""
if not self.canonical_identity_id:
raise ValidationError("canonical_identity_id", "must not be empty")
if not self.merged_identity_id:
raise ValidationError("merged_identity_id", "must not be empty")
@dataclass(frozen=True)
class MergeApproveResult:
"""合并审批放行结果记录H-21
字段:
canonical_identity_id: 规范身份 ID。
merged_identity_id: 被放行合并的 sibling identity_id。
canonical_version: 合并后 canonical 的内存版本号。
sibling_version: 清除 pending_review 后 sibling 的内存版本号。
"""
canonical_identity_id: str
merged_identity_id: str
canonical_version: int
sibling_version: int
def __post_init__(self) -> None:
"""校验身份 ID 非空与版本号非负。
``canonical_version`` / ``sibling_version`` 必须非负,在构造时即
抛出 ``ValidationError``避免负值进入控制面响应INV-8
"""
if not self.canonical_identity_id:
raise ValidationError("canonical_identity_id", "must not be empty")
if not self.merged_identity_id:
raise ValidationError("merged_identity_id", "must not be empty")
if self.canonical_version < 0:
raise ValidationError("canonical_version", "must not be negative")
if self.sibling_version < 0:
raise ValidationError("sibling_version", "must not be negative")