"""控制面 DTO。 定义控制面端口的命令与结果值对象,包括控制命令与控制结果。所有 DTO 均为 ``dataclass(frozen=True)``,仅依赖标准库与契约层内部类型,用于向导、诊断、 白名单、目录、配对、配置、会话、插件、健康、审计等控制面操作的命令传递 与结果返回。集合字段使用 tuple 以保证 frozen dataclass 的不可变语义。 """ from __future__ import annotations from dataclasses import dataclass from typing import Any, Literal from yuxi.channels.contract.dtos.channel import ChannelType from yuxi.channels.contract.dtos.common import FailureDetail, Operator from yuxi.channels.contract.errors import ValidationError @dataclass(frozen=True) class ControlCmd: """控制命令(CON-001)。 由控制面端口方法引用,描述一次控制面操作请求,携带操作类型、目标渠道、 参数与操作人。``operation`` 为带子域前缀的自由字符串(如 ``dashboard/overview`` / ``config/update`` / ``session/merge``), 具体合法值由 ``operation_audit_meta`` 与各 handler 的 ``operations()`` 共同约束,DTO 仅校验非空。 字段: operation: 操作类型(带子域前缀的自由字符串,非空)。 operator: 操作人(审计用)。 target_channel: 目标渠道类型(可选)。 params: 操作参数(可选)。 """ operation: str operator: Operator target_channel: ChannelType | None = None params: dict[str, Any] | None = None def __post_init__(self) -> None: """校验必填字段非空。 ``operation`` 必须非空,在构造时即抛出 ``ValidationError``, adapter 不再做该校验(INV-8)。 """ if not self.operation: raise ValidationError("operation", "must not be empty") @dataclass(frozen=True) class ControlResult: """控制结果(CON-001)。 描述控制面操作的执行结果,携带状态、数据与错误详情,用于结果汇报与 错误聚合。集合字段使用 tuple 以保证不可变。 字段: status: 执行状态(success | failed | partial)。 data: 返回数据(可选)。 errors: 错误详情列表(默认空 tuple)。 """ status: Literal["success", "failed", "partial"] data: dict[str, Any] | None = None errors: tuple[FailureDetail, ...] = ()