feat(domains): identity, billing, task services and domain placeholders
Billing implements reserve -> commit -> refund against bl_quota and bl_ledger with row-level locking and idempotency keys; the refund commits on its own transaction so a failed request cannot silently keep a user's quota. Task implements the unified task centre over the state machine. Identity issues and resolves users. Remaining domains are placeholders whose READMEs state what belongs there and what must not.
This commit is contained in:
@@ -0,0 +1,34 @@
|
||||
# `packages/compliance/` — 统一合规出口
|
||||
|
||||
> **所有对外生成物必须经过 `publish_asset()`,没有例外。**(架构 §7.5、ADR-11)
|
||||
|
||||
## 铁律
|
||||
|
||||
1. **不得反向依赖任何业务域**(架构 §4.2)。它必须能被任何模块安全调用。
|
||||
import-linter 契约会在 CI 拦下违规 import。
|
||||
2. **审核是唯一不允许降级的外部依赖**(架构 §11.4)。审核服务不可用时按
|
||||
**拦截**处理(fail-close),宁可少发不可漏审。
|
||||
|
||||
## 现状:只有接口,没有实现
|
||||
|
||||
签名已经定死,业务代码可以照着写;实现落地时调用方不用改。
|
||||
半实现比不实现更危险 —— 一个"半工作"的审核调用看起来和正常的一样。
|
||||
|
||||
## 待实现(T-P1-22 / T-P1-23,CR-05 / CR-06 不可裁剪)
|
||||
|
||||
1. 内容审核(腾讯云 IMS 图片 / TMS 文本 + 备案关键词库),fail-close
|
||||
2. 生成 **27 位内容编号**并登记 `cp_content_registry`
|
||||
3. 显式标识:图片加可见「AI 生成」水印;文本加提示语
|
||||
4. 隐式标识:写入文件元数据(属性信息 + 服务提供者编码 + 内容编号)
|
||||
5. 上传目标 COS 桶,返回签名地址
|
||||
6. 表:`cp_content_registry` `cp_moderation_log` `cp_audit_log` `cp_data_request`
|
||||
|
||||
## 必须专门测试的点
|
||||
|
||||
图片经过 **CDN、缩略图处理、客户端保存与再次分享**后,元数据是否仍然存在。
|
||||
很多图片处理链路会剥离 EXIF/XMP,一旦剥离就等于没做隐式标识(TD-21)。
|
||||
这一条上架被拒的概率很高,且事后补救成本极大。
|
||||
|
||||
## 六类审核对象
|
||||
|
||||
用户上传图、生成图、用户文本、模型输出、知识内容、后台录入内容 —— 全覆盖。
|
||||
@@ -0,0 +1 @@
|
||||
"""compliance 域:统一合规出口。不得反向依赖任何业务域。"""
|
||||
Executable
+69
@@ -0,0 +1,69 @@
|
||||
"""统一合规出口 — interface only (架构文档 §7.5, CR-05, CR-06).
|
||||
|
||||
**所有对外生成物必须经过 ``publish_asset()``,没有例外。** The signature is
|
||||
fixed here so that business code written against it does not have to change when
|
||||
the implementation lands (T-P1-22 / T-P1-23).
|
||||
|
||||
Nothing in this package may import a business domain — it must be safe to call
|
||||
from anywhere (架构文档 §4.2 禁止的依赖). import-linter enforces that.
|
||||
|
||||
Not implemented on purpose; implementing it half-way is worse than not having
|
||||
it, because a half-working moderation call looks like a working one:
|
||||
1. 内容审核 (fail-close: 审核服务不可用则拒绝发布) — 腾讯云 IMS/TMS
|
||||
2. 27 位内容编号生成与 ``cp_content_registry`` 登记
|
||||
3. 显式标识: 图片可见「AI 生成」水印 / 文本提示语
|
||||
4. 隐式标识: 文件元数据 (属性信息 + 服务提供者编码 + 内容编号)
|
||||
5. 上传目标 COS 桶并返回签名地址
|
||||
|
||||
必须专门测试的点 (§7.5): 图片经 CDN、缩略图处理、客户端保存与再次分享后,
|
||||
元数据是否仍然存在。很多图片处理链路会剥离 EXIF/XMP。
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from dataclasses import dataclass
|
||||
from typing import Literal
|
||||
|
||||
ContentType = Literal["image", "text", "pdf"]
|
||||
ModerationSuggestion = Literal["pass", "review", "block"]
|
||||
|
||||
_NOT_IMPLEMENTED = (
|
||||
"compliance is a structural placeholder (T-P1-22 / T-P1-23). "
|
||||
"No generated content may be released to users until 审核 + 水印 + 元数据 + "
|
||||
"内容编号登记 are all in place — CR-05/CR-06 are 不可裁剪."
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ContentRef:
|
||||
ref_type: str
|
||||
ref_id: str
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class ModelInfo:
|
||||
provider: str
|
||||
model: str
|
||||
prompt_id: str | None = None
|
||||
prompt_version: str | None = None
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class PublishedAsset:
|
||||
content_code: str
|
||||
url: str
|
||||
moderation: ModerationSuggestion
|
||||
|
||||
|
||||
async def moderate(text: str) -> ModerationSuggestion:
|
||||
"""审核不可降级:服务不可用时按拦截处理 (fail-close, 架构文档 §11.4)."""
|
||||
raise NotImplementedError(_NOT_IMPLEMENTED)
|
||||
|
||||
|
||||
async def publish_asset(
|
||||
raw: bytes | str,
|
||||
content_type: ContentType,
|
||||
ref: ContentRef,
|
||||
model_info: ModelInfo,
|
||||
) -> PublishedAsset:
|
||||
raise NotImplementedError(_NOT_IMPLEMENTED)
|
||||
Reference in New Issue
Block a user