zizi d97e194383 docs(治理): SoT注册表+docs-gate六检门,清缩历史档126→69
- 注册表:docs/architecture/README.md §2,37 份 canonical(frontmatter topic+canonical:true)与表双向机器对账
- 门:.agents/tools/docs-gate.py 六检(品牌根/canonical唯一/死链/入口卫生/留痕隔离/设计档申报),挂 .githooks/pre-commit(本仓已激活)+ .gitea/workflows/docs-gate.yml(待runner)+ wave-close 第8步;旧 check-deadlinks.sh 退役并入 G3
- 清缩:删 54 项历史档(plans 16/agent-specs 设计与spike 20/brainstorms 5/memorys 3/goals+作战清单完成史归档/王蓝莓design/SAA现状html/add-game-template);channel-spike 564K 代码资产迁仓级 spikes/;六件删前蒸馏已迁(代码评审16条open项→进度总账§5、prefix-cache字段表→cheap-model skill、意图基线29条→需求清单附录、九门降级rationale→验收门、A11 TODO→tech-decisions、3layer边界→littlejs-game-dev 指针)
- 修口径约90处:六处SAA『现行主线』旧标、Nacos/RocketMQ『未部署』旧述(07-01反转)、gameDefinition残留、全部死链改 git show 定位;AGENTS.md 249→136行(决策史归tech-decisions);_index 改纯在飞板;对外演示版 md→html
- 依据:docs/agent-specs/2026-07-02-文档治理-{全量普查与裁决-report,SoT注册表与治理门-设计}.md(四路普查191份md+Codex/Opus双评审必修项已折入);恢复基线 8ea97234(单档 git checkout 8ea97234 -- <路径>)
2026-07-02 14:24:12 +08:00

46 KiB
Raw Blame History

topic, canonical, date
topic canonical date
审核台运营 true 2026-06-22

运营域 · 审核台与内容安全运营

这是什么绘境AI 平台每天怎么把生成出来的内容审一遍、违规了怎么处置、运营在后台用什么台子干这摊活——也就是"审核台"这一整套机制的设计。它回答"双层审核怎么判、锁风三档怎么跟 IP 库绑、处置怎么联动信息流和创作者信用、人审队列怎么走 BPM、admin 审核台长什么样"。 给谁看:写 compliance / feed / admin 后台的工程师、做内容安全运营的同事、对接律所聊审核制度的人,以及创始人。 怎么读:先看 §1 它和合规闸门的分工——一个管"能不能上线这件事的法定门槛",一个管"上线之后每天怎么把内容守住";再按 §3 各小节看具体设计。 边界:合规闸门那 12+1 道法定上线门(ICP/版号/大模型登记…)在合规闸门,本页不重复。本页只讲"内容安全运营"——审、处置、台子。


1. 审核台和合规闸门是两件事

合规闸门讲的是绘境AI 作为一个平台,要合法地公开经营,必须先穿过哪些法定资质门:ICP 备案、版号、大模型登记、算法备案这些。那是一次性的、日历驱动的、过了就不用再过的前置条件,卡的是"平台能不能开门"。

审核台讲的是另一件事:门开了以后,平台上每天有人用一句话生成新游戏、传新素材、发新内容,这些**用户产生的内容(UGC)+ AI 生成的内容(AIGC)**得有人(和机器)一条条审过去,违规的要拦下来、要处置。这是持续运转的日常运营,卡的是"每一条内容能不能放出去、放出去之后表现不对怎么收回来"。

两者的关系可以这样讲:合规闸门是把平台这台机器通上电的总开关,审核台是机器跑起来之后的质检线和安全阀。它们在一个点上交汇——合规闸门里有一道门(A1 看板 #8 内容合规材料)要求平台"拿得出一套内容审核制度文本 + 审核记录留存机制",而这套制度文本描述的就是审核台怎么运转、审核记录从哪来。所以审核台不只是运营工具,它本身是法定合规材料的实现物;渠道提审、ICP 经营性升级都会要它。

flowchart LR
  subgraph 闸门["合规闸门(法定上线门 · 一次性)"]
    G["ICP / 版号 / 大模型登记 / 算法备案<br/>过了平台才能开门"]
  end
  subgraph 审核台["审核台(内容安全运营 · 持续)"]
    A["每条 UGC/AIGC 内容<br/>双层审核 + 锁风三档 + 违规处置"]
    REC["审核记录留存"]
  end
  G ==>|开门后| A
  REC -.->|实现物| MAT["#8 内容合规材料<br/>(渠道提审 / ICP 升级要)"]
  MAT -.->|是闸门的一道| 闸门

还有一条法定义务直接落在审核台上:AIGC 显式标识。绘境AI 上几乎每款游戏都是 AI 生成的,《人工智能生成合成内容标识办法》要求显著标注"AI 生成"。这道标识不是审核动作,但它和审核台共用同一批生成元数据(promptHash、生成来源),后面 §3.6 会讲它怎么和审核记录、隐式水印一起挂在内容溯源这条线上。


2. 现状:框架在、判定为空、处置半通

把审核台拆开看,它落在 compliance、feed、community 三个模块里,而这三处的现状很不一样——有的已经把骨架建好了,有的连桩都没有。设计要落在这个现状上,不能假装从零开始。

compliance 模块:锁风门框架真、判定原子全是桩、封禁链路半通。 锁风门 ComplianceGateApi.evaluate 已经是现行真相:它聚合各合规原子,按 block > review > pass 取最严裁决,落一条 game_compliance_gate_result 审计台账,顺带 upsert 一个内容分级(all/8+/12+/16+),裁决结果在 project 发布前检查(T-PRJ-05)里被真注入。但是——聚合进来的两个原子(StyleComplianceAtom 风格、IpComplianceSeam IP)目前都是桩,恒返回 pass。意味着今天的发布链对违规内容零自动拦截,纯靠人工兜底。封禁台账(UserBanDO + BanStatusEnum)和申诉状态机(AppealStatusEnum:0 待处理→1 通过/2 驳回)是真的,admin 侧 compliance:appeal:handle 能处理申诉,权限位现有 compliance:ban:create / :cancel / :query

封禁的下游联动只通了一半。封禁单个游戏目标时,UserBanServiceImpl.createBan 会调 ProjectApi.unlistIfPublished(gameId),走 project 权威状态机把那一款 PUBLISHED 游戏下架(Phase C 已收口,真实现非桩)。但封禁**账号(创作者)**这条断着:createBan 只写 game_user_ban 台账,既不置 game_player.status=DISABLE,也不遍历下架该创作者已发布的全部内容;而创作入口的 validateCreator(passport)只查 game_player.statuscreator_flag不查 game_user_ban。结果是封了一个创作者账号后,他的 game_player 仍是启用态,validateCreator 照样放行——封号拦不住本人继续创作。"封号连带全部内容下架"目前是零实现。本设计要补这条断链(§3.5)。

feed 模块:降权/下架的字段和管理端都在,但缺一个供 compliance 调的跨模块降权接缝。 现状是:FeedRankDO 上有 exposureLimit(限曝光降权因子,>=9999 是硬剔除哨兵,出流时直接踢掉)和 status(0 屏蔽,注释明写"举报降权/下架联动"),排序分公式是 sort_score = quality_score + boost exposureLimit;运营在 admin 侧有一个 setExposureLimit 端点(AdminFeedController,权限位 feed:featured:update)能手动调降权。但要注意——setExposureLimit管理端 HTTP 端点,不在 feed 对外的跨模块 FeedApi 契约上;FeedApi 目前只暴露 upsertRank(发布基线/算分回灌)和 offlineRank(按 gameId 全分区下架,status=0)两个方法。也就是说,compliance 现在能调 feed 的只有 offlineRank 这条下架接缝(已用于封禁联动下架),没有一个跨模块的降权接缝让 compliance 去调 exposureLimit

而且这个降权接缝是上一波刻意没建的:封禁联动的代码注释(UserBanServiceImpl,R5 降权出流屏蔽)写明"P1 本波不生效——不注入 feed、不建 FeedDownweightApi 孤儿 seam"。所以处置联动 feed 这件事,下架走现有 offlineRank 就够,降权则要么新建一个 feed 降权 -api(把 setExposureLimit 提升到跨模块契约),要么改走"下架 + 内容安全处置台账"的组合而不单独做降权——这是 §3.5 要定的事,别声称接缝已经焊好。

community 模块:创作者信用的宿主是等级引擎,但信用本身零实现。 "创作者信用"这个概念目前没有独立实体。community 有一个等级引擎(LevelDO,表 game_community_level,T-CMU-11),现有字段是 level/publishedCount/lastMilestone 这些,没有 credit_score,MVP 只维护发布计数 + 新人里程碑、分层留 P1;CommunityNotifyApi 也没有任何扣分端点。信用分要么挂上这条等级线(加列),要么另立一张独立扣分台账——两条路在 §3.5 里展开,创始人 2026-06-22 定放第一期、建简单扣分台账。

完全没有的: 双层机审的两层都没接——既没有自部署快检模型,也没有阿里云内容安全客户端(全仓只有 OSS 用到阿里云);人审队列只有"申诉"这一种工单,没有"内容初审/复审"的工作队列(带认领、分派、SLA);锁风三档强度只有分级(rating)这个结果字段,没有"按 IP 敏感度选标准/严格/人工复核档"的策略配置,IP 库本身还是 seam(寄宿 compliance,授权链未建)。

flowchart TB
  subgraph 真["已建成(真 / 框架真)"]
    GATE["锁风门聚合 + 台账 + 分级<br/>(原子是桩,恒 pass)"]
    BAN["封禁台账 + 申诉状态机<br/>(封游戏→下架那一款;封账号未联动)"]
    EXP["feed exposureLimit + status 字段<br/>+ admin setExposureLimit + 跨模块 offlineRank"]
    LV["community 等级引擎<br/>(信用宿主)"]
  end
  subgraph 缺["待建(本设计补)"]
    L1["自部署快检(第一层)"]
    L2["阿里云内容安全(第二层兜底)"]
    QUEUE["人审工作队列 + BPM 流转"]
    STR["锁风三档策略 + IP 库绑定"]
    DRIVE["feed 降权 -api + 封账号联动 + 信用扣分"]
  end

3. 设计

3.1 目标

把上面这堆"框架在、判定空、处置半通"补成一套能日常运转的内容安全运营机制,具体要做成:

  1. 一条贯通的审核判定流:任何要对外的内容(发布的游戏、上传的素材),先过自部署快检挡掉大面,拿不准的送阿里云兜底,再拿不准的进人审队列,人审走 BPM 工作流。三层各有明确的放行/拦截/转人工阈值,任何一条内容的最终裁决都能追到是哪一层、为什么判这个结果。
  2. 锁风三档是一个可配的运营旋钮:标准/严格/人工复核三档,按 IP 敏感度和内容类型选,和 IP 库绑定——给迪士尼这种高敏 IP 创作的内容自动走严格档甚至人工复核,UGC 原创走标准档。
  3. 违规处置真联动:封禁、举报降权、分级标签三类处置动作,真的去改 feed 的曝光权重、真的去扣创作者信用,而不是只在 compliance 自己库里记一笔。
  4. admin 审核台是运营的工作台:队列(看什么待审)、详情(看一条内容的全部判定证据)、处置(一键封禁/降权/打标)、锁风档位配置(调三档策略),权限分清楚谁能审、谁能配策略、谁能封号。

审核状态的唯一权威在 compliance。project 只持有游戏的生命周期状态(draft/published/…),审核结论(pass/review/block、人审队列状态、锁风裁决)归 compliance 拥有,project 只接收回写、不自己写审核态。这是为了避免"两个模块都在写审核状态"的脑裂——历史上 Wave3 评审就拍过这个归属切分,这里继承。

3.2 双层审核的判定流:快检挡大面、兜底定生死、人审兜疑难

审核判定的主干是一个三段瀑布:自部署快检 → 阿里云兜底 → 人审队列。设计的核心不在"调用三个检测器",而在路由——什么内容在哪一层被放掉、什么内容必须往下一层送。路由对了,既能把绝大多数内容用最便宜的方式放行,又不会让真正有问题的内容漏过去。

第一层 · 自部署快检(safe-content-ai)。 自己部署的轻量内容安全模型,对文本/图片做一遍快、免费、低延迟的扫描。它的职责是挡掉大面——明显没问题的直接放行(占绝大多数),明显违规的直接拦截,只把落在中间灰带的样本往下送。这一层的价值是成本:阿里云内容安全是按调用量收费的,如果每条内容都送阿里云,成本会随产能线性涨(三向审计早就点名"成本表漏了审核 API")。快检把大部分流量在本地消化掉,只让灰带样本花阿里云的钱。

第二层 · 阿里云内容安全(兜底)。 灰带样本送阿里云的文本/图像内容安全 API,拿它有合规背书的权威结论。这一层不是每条都过,是快检拿不准时才过。阿里云返回的标签(色情/暴恐/政治等)映射成平台的 block/review/pass:确定违规 → block,确定无问题 → pass,它也拿不准或返回需人工复核的标签 → review,转人审。

接入时点(创始人 2026-06-21 定):阿里云兜底在接真实公开流量之前接入——也就是渠道线③上线前。自有端邀请制内测阶段(②),内容面向的是邀请来的种子用户、量小可控,快检 + 人审已经够用;等真的要面向陌生公众放量(渠道线),阿里云的权威背书才成为合规刚需。所以这一层的代码接缝现在就留好(检测器抽象 + 一个本地快检实现),阿里云实现挂在 feature flag 后面,放量前接通。

第三层 · 人审队列。 两道机审都判 review(拿不准),或者锁风三档策略直接要求人工复核的,进人审队列。人审给出 approve/reject 的人工终裁,这一裁决是最高权威,覆盖机审结论。人审怎么组织成队列、怎么走 BPM,在 §3.4 单独讲。

下面这张图画的是单条内容的运行时路由。注意:第二层走不走阿里云,不是按内容逐条决策的,而是一个部署时点的 feature flag——放量前(渠道线③)把 flag 打开、灰带样本接通阿里云,放量前 flag 关着、灰带直接进人审。所以图里灰带出口标的是"flag 开 → 阿里云 / flag 关 → 人审",而不是一道按内容判的运行时分支。

flowchart TB
  IN["待审内容<br/>(发布游戏 / 上传素材)"] --> STR{"锁风三档策略<br/>(按 IP/类型选档)"}
  STR -->|"人工复核档:直接送人审"| QUEUE
  STR -->|"标准/严格档:走机审"| L1["第一层 自部署快检<br/>safe-content-ai"]
  L1 -->|明显 OK| PASS["pass 放行"]
  L1 -->|明显违规| BLOCK["block 拦截"]
  L1 -->|"灰带·拿不准<br/>(flag 开→阿里云 / flag 关→人审)"| ALY["第二层 阿里云内容安全<br/>(仅 flag 开 · 放量前接通)"]
  L1 -.->|"灰带 · flag 关(内测期)"| QUEUE["第三层 人审队列"]
  ALY -->|确定 OK| PASS
  ALY -->|确定违规| BLOCK
  ALY -->|仍拿不准| QUEUE
  QUEUE -->|人工 approve| PASS
  QUEUE -->|人工 reject| BLOCK
  PASS --> GATE["写锁风门台账<br/>game_compliance_gate_result"]
  BLOCK --> GATE

落到代码上,这套瀑布是对现有锁风门的扩展而非重建。今天 ComplianceGateServiceImpl.evaluate 已经在做"聚合原子 → max 取最严 → 落台账 → 出 verdict"。要做的是:

  • StyleComplianceAtom / IpComplianceSeam 之外,新增内容安全原子(文本/图像),内部就是"先快检、灰带再阿里云"这条瀑布,产出 ComplianceAtomResult{verdict, reason},和现有原子同构地塞进 evaluate 的聚合列表。这样三层瀑布的结果天然进了 max 聚合——任一层判 block,聚合就是 block。
  • review 的处理要扩。今天 GateVerdict 只是返回 verdict,没有"转人审后挂起、等人审回来再定"的环节。要补一个人审挂起态:聚合裁决为 review 时,不立即放行也不立即拦截,而是建一条人审工单(§3.4)、把 project 的发布卡在"待人审"上,人审终裁回来再驱动后续。
  • 阿里云调用是外部 API,必须按工程铁律处理超时/失败/重试:阿里云超时或报错时降级到 review(转人审),绝不降级到 pass——内容安全的降级口径只能往严格走,放行型降级等于把没审过的内容当审过了放出去。这条和变现侧"打款降级要 fail-fast"是同一个道理:涉及安全和钱的降级,方向永远朝保守。

3.2.1 事中召回:举报率超阈值把已上线内容拎回人审(创始人 2026-06-22 历史回收判定捡回)

上面那条三段瀑布管的是"内容上架前先审一遍",§3.5 的举报降权管的是"判定违规之后怎么处置"。这两者之间漏了一环:内容已经过审上线、在 feed 里正常跑,但它后来变坏了,或者一开始就擦着边没被机审拦住,玩家开始大量举报——这种情况下没有任何机制把它重新拎回审核。审核台只画了"事前审"和"事后处置"两端,中间"内容在线上由信号触发重审"这一环是空的。补上它,审核闭环才从"只防得住新内容"变成"也防得住上线后才变坏、才被举报的内容"。

触发信号取举报率,定义为 report_rate = 举报数 / 曝光数,是一个负向质量信号——分母用曝光而非绝对举报数,是为了不让高曝光的热门内容仅因为基数大就被误判,也不让冷门内容靠几次举报就轻易翻车。当一条内容的举报率在统计窗口内冲过阈值,系统自动给它建一条人审工单,把它反向召回到 §3.4 的人审队列,由人来定它该继续跑、降权还是下架。这条路径和上架前送审方向相反:一个是上线前主动送审拦截,一个是上线后被舆情反向召回;但它们汇入的是同一个人审队列、走同一套审核工单状态机,人审终裁同样是最高权威。

它接的是两个已有的点。一头接 feed 的举报埋点——举报本身是 feed/community 侧已有的玩家互动信号,事中召回要做的是把这个信号按曝光归一成举报率、并设一个可配阈值的监测;另一头接 §3.4 的人审队列,召回产出的工单和机审 review 产出的工单同构,只是 触发原因 标成"举报率超阈值"、证据里带上当前举报率和窗口内的举报样本。这样事中召回不另起一套人审基础设施,复用审核工单这一条主干。

阈值的高低和窗口长短是运营旋钮,要随真实举报分布调:定太低会把正常内容频繁拎回人审、加重人力;定太高则起不到事中拦截的作用,坏内容在被召回前已经伤害了一批玩家。这和快检阈值一样是运营常态、不是一次性调好的参数,落点是锁风档位配置那一类策略配置(§3.7)。

contract-first 清单(待落地):① 监测口径——举报率的计算依赖"举报数"和"曝光数"两个量,举报数在 community/feed 的互动埋点里、曝光数在 feed 的出流统计或 telemetry 里,要先确认这两个量能按 gameId 聚合取到(若现有埋点不足,需补一个按游戏聚合举报数/曝光数的只读查询,别新建写接缝);② 触发器——新增一个周期扫描的 job(或挂在现有 feed/compliance 的定时任务上),扫超阈值的内容、调 §3.4 的建工单入口,工单 触发原因 枚举加一个"举报率超阈值"值;③ 阈值配置——report_rate 阈值和统计窗口作为可配项落 admin 策略配置(复用 §3.7 锁风档位配置页那套策略表,不单建一张表),权限位沿用 compliance:lock-policy:config;④ 幂等——同一条内容在一个窗口内只召回一次,别让它每轮扫描都重复建工单(以 gameId + 窗口 为幂等键)。这一环放在第一期人审队列建成之后接,因为它依赖人审工单这条主干先在。

3.3 锁风三档与 IP 库怎么绑

锁风门(Gate)裁决的是"这条内容的风格/版权/内容安全过不过",而锁风三档调的是"用多严的力度去裁"。同一条内容,标准档可能放行、严格档可能转人审、人工复核档直接送人。这三档不是写死的,是个按内容的 IP 归属和类型动态选出来的策略

三档的语义:

  • 标准档:默认档,UGC 原创、低敏内容走这档。机审瀑布正常跑,只有灰带和违规才转人审/拦截。绝大多数内容在这档。
  • 严格档:中高敏内容(知名 IP 授权创作、品牌方营销内容)。降低机审放行的阈值——快检判"大概 OK"的也要送阿里云复核,阿里云判 review 的一律转人审。宁可多花成本和人力,也不让擦边内容溜过。
  • 人工复核档:最高敏(头部 IP、强约束授权、政治敏感题材)。跳过机审放行路径,所有内容直接进人审队列,人没点头就不放行。

和 IP 库怎么绑——这是三档的输入来源。 三档不该让运营对每条内容手动选,而该由内容的 IP 归属自动推导。绘境AI 的 IP 库(ip 模块,目前以 seam 寄宿 compliance、授权链待建)管的是"哪些 IP 形象、谁授权的、授权范围多大"。设计的终态是:锁风档位作为 IP 的一个授权属性挂在 IP 库上,每个注册 IP 带一个 lockStrength(标准/严格/人工复核),录入 IP 授权时由运营按 IP 方的敏感度和合同约束定下来。

但要说清现状——IP 库目前只是个 seam,授权链还没建,没有承载 lockStrength 的 IP 实体。所以 lockStrength 现阶段不挂在 IP 实体上,而是先落一张轻量的过渡表 lock_strength_policy(按 ipId 或题材关键词映射档位,admin 可配,详见下面的范围依赖说明),等 IP 授权模型成熟再把它收敛进 IP 实体。一条内容生成时声明了用哪个 IP,审核就拿这个 IP 去过渡表查档位,据此选档;没声明 IP 的纯 UGC,默认标准档。内容类型再叠一层兜底规则(比如题材黑名单——棋牌/捕鱼即便纯 UGC 也强制拉到人工复核档,对应历史回收 020 的生成侧题材审查)。

flowchart LR
  subgraph IPLIB["档位源(现阶段=过渡表 lock_strength_policy<br/>终态收敛进 IP 实体授权属性)"]
    IP1["迪士尼 IP<br/>lockStrength=严格"]
    IP2["王蓝莓 IP<br/>lockStrength=标准"]
    IP3["敏感题材<br/>lockStrength=人工复核"]
  end
  CONTENT["待审内容<br/>声明 ipId"] --> SEL["选档器"]
  IPLIB --> SEL
  TYPE["内容类型/题材黑名单<br/>(兜底拉档规则)"] --> SEL
  SEL -->|无 IP/低敏| STD["标准档"]
  SEL -->|IP 中高敏| STRICT["严格档"]
  SEL -->|IP 最高敏/黑名单| MANUAL["人工复核档"]
  STD --> FLOW["机审瀑布(§3.2)"]
  STRICT --> FLOW
  MANUAL --> Q["直接人审队列"]

范围依赖(创始人 2026-06-21 定):锁风三档和 IP 库绑定、随素材/IP 授权模型一起做。也就是说三档的策略落地依赖 IP 库把"IP 注册 + 授权链 + lockStrength 属性"这套建起来。在 IP 库授权模型落地前,三档可以先用一张轻量的 lock_strength_policy 配置表过渡(按 ipId 或题材关键词映射档位,admin 可配),等 IP 授权模型成熟再把 lockStrength 收敛进 IP 实体。这样三档不被 IP 库的进度卡死,又不产生两套并行的策略源。

锁风三档的裁决记录要能回答"为什么这条走了严格档",落点是现有的 game_compliance_gate_result 台账。但现状要讲清:这张表(GateResultDO)目前只有 id/gameId/versionId/verdict/rating/details/traceId 这几列,没有 lock_strengthip_id 字段。补记档位和命中 IP 有两条路:

  • 优先:写进已有的 details JSON 列。details 现在存的是各原子明细数组([{atom,verdict,reason}]),给它再加两个键 lockStrengthipId 即可,不改表结构、不加迁移,溯源时从 JSON 里读。
  • 若要按列查询/统计(比如按档位聚合审核量):则需 contract-first 补一次迁移——在 game_compliance_gate_resultADD COLUMN lock_strength VARCHAR / ip_id BIGINT(均 nullable、对存量行无影响,向后兼容),同步改 GateResultDO 加两个字段、GateResultMapper 不动(MyBatis-Plus 自动映射)。迁移版本号按落地时仓内最新版顺延分配(现仓已到 V25)。

MVP 阶段建议走第一条(写 details),只有在确有按档位做报表的需求时才升列。

3.4 人审走 BPM:从申诉单一队列到内容审核工作流

今天 compliance 只有"申诉"这一种人工工单——用户被处置后不服,提个申诉,admin 在 compliance:appeal:handle 里通过或驳回。但内容审核本身的人工环节(机审判 review → 人来定)还没有队列。这是人审要补的主体。

人审队列设计成一个审核工单(review task)的工作流。每当机审瀑布产出 review、或锁风三档要求人工复核,就建一条审核工单进队列。工单带:目标内容(gameId/versionId 或 materialId)、触发原因(哪层判的 review、命中什么)、机审证据(各原子的 verdict 和 reason、阿里云返回的标签)、锁风档位、优先级。审核员从队列认领工单,看完证据给 approve/reject,工单流转到终态,终裁回写驱动后续(放行则推进发布、拦截则触发处置)。

为什么走 BPM 而不是一个简单的 status 字段。 内容审核的人工流转比"待处理→通过/驳回"复杂:有认领(避免两个审核员审同一条)、有分派(高敏内容派给资深审核员)、有升级(初审拿不准升级到复审/主管)、有超时(舆情内容要求 2 小时内处置,超时要告警甚至自动升级)、有 SLA 统计(平均审核时长、积压量)。这些用裸 status 字段管会越写越乱,正是 BPM(业务流程引擎)擅长的——把"谁能干、干完去哪、超时怎么办"声明成一张流程图,引擎来驱动。

MVP 的务实形态:轻量状态机起步,Flowable 留远期。 这和 project 发布审核(T-PRJ-06)的口径一致——MVP 先用轻量审核状态机 + admin 审核队列把"建工单→认领→裁决→回写"这条主干跑通,认领用乐观锁(CAS 抢占,防双审)、超时用定时任务扫描告警。重型 BPM 引擎(Flowable)等审核复杂度真的上来了(多级审核、复杂分派规则)再引入。这样不在 MVP 阶段背一个重引擎,又给将来留了演进位——状态机的状态和流转设计成能平滑映射到 BPM 流程定义。

审核工单状态机:

stateDiagram-v2
  [*] --> 待认领: 机审 review / 锁风人工档建单
  待认领 --> 审核中: 审核员认领(CAS 抢占)
  审核中 --> 已通过: approve(终裁放行)
  审核中 --> 已拒绝: reject(终裁拦截→触发处置)
  审核中 --> 已升级: 拿不准,升级复审/主管
  已升级 --> 审核中: 上级接手
  待认领 --> 超时告警: 超 SLA 未认领
  审核中 --> 超时告警: 超 SLA 未裁决
  超时告警 --> 审核中: 介入处理
  已通过 --> [*]
  已拒绝 --> [*]

这套审核工单和现有的申诉工单是两条独立的人工流。但要说清现状:今天并不存在一套可复用的"队列基础设施"——申诉侧建成的只是 AppealStatusEnum(0 待处理→1 通过/2 驳回)状态机加一个 compliance:appeal:handle 处理端点,没有带认领/分派/SLA 的队列底座。所以准确说法是:这两条流将共用同一套将要新建的队列 UI 框架和 RBAC 模式——审核工单这条先把队列底座(认领、超时、列表筛选)建起来,申诉那条沿用同一套模式接进去。两者都是"待处理→终态"的人工裁决,但状态机和权限位分开(compliance:review:handle vs compliance:appeal:handle),其中 compliance:review:handle 是本设计新增、compliance:appeal:handle 已建。

人审工单落一张新表 game_compliance_review_task(继承 TenantBaseDO 拿审计列),关键字段:目标(target_type 游戏/素材 + target_id)、status(状态机)、assignee_id(认领人)、prioritylock_strengthevidence(机审证据 JSON)、sla_deadline(超时锚点)、verdict(人工终裁)、operator_id(终裁人,审计)。

3.5 违规处置怎么联动 feed 曝光与创作者信用

处置是审核链的最后一环——判定违规之后,平台要做出反应。三类处置动作,每一类都要真的联动到下游,而不是只在 compliance 自己库里记一笔。

封禁。 针对账号(创作者)的最重处置。封禁台账(UserBanDO + BanStatusEnum)已建,被封用户可走申诉(AppealDO.banId 已关联封禁台账)。封禁要联动两处,而这两处现状都不到位,是本设计要补的:

  • 鉴权侧:被封账号要在 validateCreator(见鉴权与权限 §5)里被拦,创作写入口直接拒。现状是 validateCreator 只查 game_player.status(禁用态拒)和 creator_flag,不查 game_user_ban,而 createBan不置 game_player.status=DISABLE——所以封一个创作者账号后他照样能创作。要补的机制二选一:封禁时同步把 game_player.statusDISABLE(走 passport 的 -api,复用既有禁用态判定),或让 validateCreator 在判定时多查一次生效中的 ban 记录。前者改动小、复用现有禁用态链路,推荐;两条路都要定义解封时的状态恢复、幂等(重复封/解封不出错)、审计留痕。
  • 内容侧:封号要连带把该创作者已发布的内容全部下架。现状只通了"封禁单个游戏目标 → 下架那一款"(UserBanServiceImplProjectApi.unlistIfPublished(gameId),仅 PUBLISHED 生效),封禁账号目标时不会遍历该创作者的全部游戏逐个下架,这条级联是零实现。要补一个"按 creatorId 查其全部已发布游戏 → 逐个走 offlineRank/unlistIfPublished 下架"的批量联动,并处理好部分失败的补偿(下架是封禁的附带副作用,不应回滚封禁主操作)。

封禁分级(警告/限制创作/永久封禁)和封禁期限挂在台账上。

举报降权 + 下架。 针对内容的处置,这是和 feed 联动最直接的一类。处置动作落到 feed 的两个既有字段(exposureLimit 降权因子、status 屏蔽态),但能不能跨模块调到它们,两条路现状不一样(§2):

  • 下架/屏蔽(内容违规,彻底踢出流):compliance 调 feed 现有的跨模块接缝 FeedApi.offlineRank(gameId),把该游戏全分区排序行 status0,buildStream 出流时直接踢掉。这条现成可用,封禁联动下架已经在走它。
  • 降权(内容有问题但不到下架,压低曝光):理想效果是把 exposureLimit 调高、sort_score = quality + boost exposureLimit 自动下沉,内容还在流里但排得很后。但 setExposureLimit 现在只是 AdminFeedController管理端 HTTP 端点(给运营手动调用),不在跨模块 FeedApi,compliance 调不到。要让 compliance 自动降权,得 contract-first 新建一个 feed 降权 -api(把 setExposureLimit 的能力提升到跨模块契约层)。

降权这条创始人 2026-06-22 定放第一期、单独做:新建 feed 降权 -api(契约面新增,见下)让 compliance 能自动降权,不只靠"offlineRank 下架"——"降权但不下架"这种中间态第一期就有。代价是现在就给 feed 开一个新的跨模块写入口(contract-first 补 FeedApi 降权方法 + compliance-server 补 feed-api 依赖)。

若采用新建降权 -api 这条路,contract-first 清单是:在 game-module-feed-apiFeedApi 上加一个方法(如 downweight(gameId, exposureLimit))+ 对应 DTO,FeedApiImpl 委托既有 FeedService.setExposureLimit(实现已在,不重写);compliance-server 的 pom 补 game-module-feed-api 依赖(现在没有,见 §2 编译缺口)。无 DB 迁移(exposure_limit 列 V25 已落)。

设计纪律不变:compliance 是处置的发起方,feed 是执行方,跨模块只走 feed 的 -api,不让 compliance 直接写 feed 的表(守模块边界)。

分级标签。 内容分级(all/8+/12+/16+,ContentRating 已建)既是处置结果也是展示依据。审核判定一款游戏适龄 16+,这个标签一方面在 feed/详情页对用户展示(青少年模式据此过滤),一方面喂给防沉迷——未成年用户的 feed 候选集要按分级过滤掉不适龄内容(对应历史回收 014:识别未成年后禁广告 + 禁付费 + 限时长 + 按分级最小化内容)。

创作者信用——把处置转成对人的长期影响。 单次处置是对单条内容的,但一个反复违规的创作者应该受到累积的约束。信用分就是这个累积器:每次违规处置(降权/下架/封禁)按严重度扣创作者信用分,信用分低于阈值的创作者,反向影响审核档位(自动拉到严格档,他的新内容审得更严)和分发(feed 基线曝光降低),形成"越违规越受限"的负反馈。

这套是全新待建合同,现在一点没有:community 的等级引擎 LevelDO(表 game_community_level)现有字段是 id/creatorUserId/level/publishedCount/lastMilestone/lastMilestoneTime,没有 credit_score;CommunityNotifyApi 只有通知投递和奖励发放方法,没有扣分端点。要让信用机制成立,contract-first 清单是:

  • DB:补一次迁移(在 game_community_levelADD COLUMN credit_score INT DEFAULT 100,nullable/带默认、对存量行无影响,向后兼容);或另立一张独立的信用扣分台账表(每次处置记一条 + 累计分),与等级表解耦,二选一。迁移版本号按落地时仓内最新版顺延分配(现仓已到 V25,§3.3 那条若也落库会占一个号,别和它撞)。
  • 跨模块 -api:在 community-apiCommunityNotifyApi(或另立一个信用专用 api)上加一个扣分方法,带幂等键(同一处置事件重复投递不重复扣分);compliance 处置后调它注入扣分。
  • compliance 编译依赖:compliance-server 的 pom 补 game-module-community-api 依赖(现在没有,见 §2 编译缺口)。

信用模型创始人 2026-06-22 定放第一期:第一期就把"简单扣分台账(只记不连带)"建起来——它牵涉新表 + 新跨模块端点(带幂等键)+ 误伤治理。第一期取保守形态(只扣分、不做激进连带封禁),复杂规则(信用分联动曝光基线等)留后细化,和等级引擎"MVP 仅计数、分层留 P1"的口径相容。

flowchart TB
  V["违规判定(机审 block / 人审 reject)"] --> DISPATCH{"处置类型"}
  DISPATCH -->|账号| BAN["封禁台账 UserBanDO(已建)"]
  DISPATCH -->|内容降权| DOWN["feed 降权 -api(待建)<br/>exposureLimit↑ → sort_score 下沉"]
  DISPATCH -->|内容下架| OFF["FeedApi.offlineRank(已有)<br/>status=0 出流剔除"]
  DISPATCH -->|分级| RATING["ContentRating 标签<br/>→ 青少年模式/防沉迷过滤"]
  BAN -.->|连带下架全部内容(待建)| OFF
  BAN -.->|拦截创作:置 player DISABLE 或查 ban 表(待建)| AUTH["validateCreator 拒"]
  BAN -.-> CREDIT["创作者信用扣分(待建)<br/>(community 等级体系/独立台账)"]
  DOWN -.-> CREDIT
  OFF -.-> CREDIT
  CREDIT -.->|信用低→拉严档| STR["锁风档位上调"]
  CREDIT -.->|信用低→降基线曝光| FEEDBASE["feed 基线曝光↓"]
  BAN -->|不服| APPEAL["申诉 AppealDO<br/>(已建状态机)"]

处置和审核状态的权威归属:处置决策由 compliance 拥有并发起,处置效果落在各下游模块的既有字段上。compliance 记"对谁、什么处置、什么原因、谁操作的"的处置台账(审计 + 申诉溯源用),feed/community 各自承载处置在自己域的效果。这样既守住"审核状态单一权威在 compliance",又不让 compliance 越界去写别人的业务表。

3.6 内容溯源:AIGC 标识 + 隐式水印 + 审核记录

审核链路天然沉淀一批内容溯源数据,把它们串起来能同时满足三个需求:AIGC 法定标识、版权追责、审核记录留存(合规闸门 #8 要的那套)。

  • AIGC 显式标识:每款生成游戏带"AI 生成"的显式标记,数据上挂在生成元数据(promptHash、生成来源)上,展示上在游戏卡片/详情页/分享页显著标注。这是《标识办法》的硬义务,在所有发行面都要带。
  • 隐式水印:给生成内容嵌入不可见的溯源标记(implicit watermark),是个全新工程件(历史回收 021)。它和显式标识互补——显式标识是给用户看的、可被去除,隐式水印是给追责用的、藏在内容里。MVP 可后置,随渠道线/放量排期。
  • 审核记录留存:锁风门台账(game_compliance_gate_result)+ 审核工单 + 处置台账,合起来就是"每条内容审了什么、谁审的、什么结论、怎么处置的"完整记录,留存 ≥180 天(对应 T-CMP 审计日志要求)。这套记录是合规闸门 #8 内容合规材料的实现物,也是渠道提审和被监管问询时的证据。

3.7 admin 审核台前端

审核台的运营出口是 game-admin(Vue3 + Element Plus,见前端域)上的一组页面。它服务运营和管理员,落在 admin 的 /admin-api/compliance/* 端点上。四块页面对应创始人定的四件事:

审核队列页。 审核台的主屏。展示待审工单列表(机审转 review 的 + 锁风人工档的)和申诉工单列表,支持按优先级/锁风档位/触发原因/超时状态筛选,标红超 SLA 的工单。审核员从这里认领工单进详情。队列数据来自审核工单台账分页 + 申诉台账分页(compliance:appeal:query 已建,新增 compliance:review:query)。

审核详情页。 一条工单的全部判定证据摊开:目标内容(游戏可试玩/素材可预览)、机审逐层结论(快检判了啥、阿里云返回什么标签、各原子 reason)、锁风档位和命中的 IP、历史处置记录。审核员在这页给 approve/reject。

处置操作页(或详情内嵌处置区)。 一键发起三类处置:封禁(选分级 + 期限 + 原因)、降权/下架(调 feed 曝光)、打分级标签。处置即时联动下游(§3.5),操作落审计台账。这些是重权限动作,封禁复用现有权限位 compliance:ban:create/:cancel;降权/下架和打分级标签是新端点,要新增对应权限位(见下表)。

锁风档位配置页。 运营在这里维护锁风三档策略:给 IP 配 lockStrength、维护题材黑名单的兜底拉档规则、调各档的机审阈值。这是策略配置而非单条处置,要新增权限位 compliance:lock-policy:config,只给高级运营/管理员。

权限模型鉴权与权限:admin 端走 B 端 RBAC,每个端点 @PreAuthorize("@ss.hasPermission('compliance:资源:动作')"),角色-菜单交集裁决、超管短路。要先讲清现状:compliance 现有的权限位只有 compliance:ban:create / :cancel / :querycompliance:appeal:handle / :query。审核台新增的页面要配套新增一批权限位,每个都得 contract-first 同步四处——端点上的 @PreAuthorize、admin 菜单种子(system_menu)、角色种子(把新权限位挂到对应角色)、验收用例(无权限 token 直连被 403)。下表里标"(新增)"的就是当前不存在、要随本设计建的:

角色 能干什么 关键权限位
审核员 看队列、认领工单、approve/reject、打分级标签 compliance:review:query(新增) / :handle(新增)、compliance:rating:set(新增)
处置专员 在审核员基础上 + 封禁、降权/下架、处理申诉 compliance:ban:create / :cancel(已有)、compliance:exposure:handle(新增)、compliance:appeal:handle(已有)
合规管理员 在处置专员基础上 + 配锁风三档策略、配 IP lockStrength compliance:lock-policy:config(新增)

权限的强制在后端可信边界(服务侧 @PreAuthorize),admin 前端的按钮显隐只是体验,不算数——这条铁律承自鉴权域,审核台尤其要守:能封号、能改曝光的端点,前端藏了按钮但 API 直连仍可达,必须后端拦死。

flowchart TB
  subgraph ADMIN["game-admin 审核台(Element Plus)"]
    Q["审核队列页<br/>待审工单 + 申诉"]
    D["审核详情页<br/>试玩 + 机审证据 + 锁风档"]
    DISP["处置操作<br/>封禁/降权/下架/打标"]
    CFG["锁风档位配置<br/>IP lockStrength + 题材黑名单"]
  end
  subgraph API["/admin-api/compliance/* (B 端 RBAC)"]
    R1["review:query/handle"]
    R2["appeal:handle/query"]
    R3["ban:create/cancel(已有) · exposure:handle/rating:set(新增)"]
    R4["lock-policy:config"]
  end
  Q --> R1 & R2
  D --> R1
  DISP --> R3
  CFG --> R4
  R3 -.->|联动| FEED["feed -api(曝光)"]
  R3 -.->|联动| CMU["community(信用)"]

4. 分期落地

创始人定了"全做",但四块有依赖先后,不是平铺并行。落地分三期,排序的依据是"什么先成立、什么被什么卡住"。

第一期 · 把判定流和处置联动跑通(自有端内测够用)。 这一期不依赖任何外部资质,可以马上动:

  • 内容安全原子(文本/图像)落地为自部署快检 + 桩位的阿里云接缝——快检真跑,阿里云实现挂 feature flag。原子接进现有锁风门聚合。
  • 审核工单台账 + 轻量状态机 + admin 审核队列/详情/处置页。把"机审 review → 建工单 → 人审认领裁决 → 回写驱动"主干打通。
  • 违规处置联动:下架走 feed 现有的 FeedApi.offlineRank(现成);封禁联动补两块断链——封账号时置 game_player.status=DISABLE(让 validateCreator 拦得住)+ 按 creatorId 批量下架其全部已发布内容。feed 自动降权与创作者信用模型也放第一期(创始人 2026-06-22 定):新建 feed 降权 -api 让 compliance 自动降权、建简单信用扣分台账(只记不连带),两者都 contract-first 补新跨模块写入口 / 新表(见 §3.5)。
  • 锁风三档用过渡的 lock_strength_policy 配置表起步(admin 可配),先按题材黑名单 + 手配 IP 映射选档。
  • 事中召回(§3.2.1,创始人 2026-06-22 历史回收判定捡回)接在人审队列建成之后:把举报率按曝光归一成负向信号、设可配阈值,超阈值的已上线内容自动建工单反向召回到人审队列。复用审核工单主干,不另起人审基础设施。

这一期做完,自有端邀请制内测就有了一套能日常运转的内容安全运营——机审挡大面、人审兜疑难、违规真下架真拦创作,且上线后变坏/被举报的内容也能被举报率信号拎回重审。

第二期 · 阿里云兜底接入(放量前的合规刚需)。 依赖"接真实公开流量"这个时点(渠道线③临近):把第一期留的阿里云接缝接通,灰带样本真送阿里云、按工程铁律处理超时/失败/降级(降级朝 review 走)。同时补内容溯源——AIGC 显式标识在各发行面带上,审核记录留存机制成文(喂合规闸门 #8 材料)。

第三期 · 锁风三档收敛进 IP 授权模型 + 隐式水印。 依赖 IP 库把"IP 注册 + 授权链 + lockStrength 属性"建起来(随素材/IP 授权模型一起做):把过渡配置表里的档位策略收敛进 IP 实体的授权属性,三档按 IP 授权敏感度自动选。隐式水印作为全新工程件,随这一期或渠道线排期落地。BPM 重引擎(Flowable)在审核复杂度真上来时再评估引入,不在前三期硬约束内。

flowchart LR
  P1["第一期<br/>快检+人审队列+处置联动+三档过渡表<br/>(零外部依赖,内测够用)"]
  P2["第二期<br/>阿里云兜底+AIGC标识+审核记录留存<br/>(依赖:接公开流量/渠道线③)"]
  P3["第三期<br/>三档收敛进IP授权+隐式水印<br/>(依赖:IP库授权模型)"]
  P1 --> P2 --> P3

5. 验收与风险

5.1 怎么算做对了

  • 判定流可追溯:任取一条审过的内容,能从台账还原它走了哪一档、哪层判的、机审给了什么结论、是否进人审、谁终裁、最终 verdict——全链证据齐全。
  • 机审真拦截:接进内容安全原子后,造一批已知违规样本(色情/暴恐/政治测试集),自部署快检对明显违规的能拦下来(不再像现在恒 pass);灰带样本能正确转下一层。这是从"零自动拦截"到"机审兜底"的硬验收。
  • 处置真联动:封一个号,该创作者已发布内容在 feed 出流被剔除、validateCreator 拒其再创作;降权一条内容,feed 排序真下沉;这些要在 staging 上 e2e 验到(feed 联动排序历史上 B2 已经在浏览器里 e2e 翻转过——2026-06-09 真人试玩玩过的游戏从第 2 位窜登顶,复用同套验法)。
  • 降级朝保守:阿里云接入后,模拟阿里云超时/报错,验证内容降级到 review 转人审、绝不放行。
  • 权限不可绕:审核台的封禁/改曝光端点,用无权限的 token 直连 API 被 403 拦(不靠前端藏按钮)。
  • 状态单一权威:验 project 不写审核态、只接 compliance 回写,不存在两处都改审核状态的脑裂。

5.2 风险

  • 快检模型的准确率是成本与漏判的平衡点。快检放得太松,违规内容漏到下游甚至漏过;判得太严,大量正常内容涌进人审,人力成本爆掉(历史回收 026:人审是台阶函数,月新增超 2000 款就要 +6000 元/月)。快检阈值要随真实样本持续调,这是个运营常态,不是一次性调好。
  • 阿里云内容安全是花钱的外部依赖,成本随放量线性涨,而 ¥4,300/月 那张成本表压根没算它(三向审计点名)。放量前要把审核 API 成本单列进成本台账,否则单位经济测算偏乐观。
  • 锁风三档依赖 IP 库,IP 库授权链还没建。三档用过渡配置表起步缓解了卡死风险,但如果 IP 授权模型迟迟不落地,三档会长期停在"手配映射"的粗糙形态,高敏 IP 的自动严审落不了地。这块的真正成熟绑在素材/IP 授权模型的进度上。
  • 人审是真正随产能咬人的成本,且舆情内容有"2 小时内下架"的 SLA(历史回收 021)。MVP 轻量状态机能不能扛住放量后的审核积压、SLA 告警够不够及时,要在放量灰度时压测,必要时提前引 BPM。
  • 创作者信用是新机制,要防误伤。信用扣分若规则太硬,一次误判处置可能连累创作者的长期曝光,而申诉救济的时效要跟上。信用规则若做,MVP 也要保守(只扣分、不做激进的连带封禁),复杂规则留 P1 再细化。

5.3 拍板结论与剩余开放项

原本三件待拍板,创始人 2026-06-22 已定前两件(feed 自动降权 + 创作者信用模型都放第一期、单独做);剩第三件(锁风记录升不升列)是工程细节,倾向写 JSON:

  1. feed 自动降权(创始人 2026-06-22 定:放第一期、单独做)。 contract-first 新建 feed 降权 -api(FeedApi 加降权方法 + DTO、compliance-server 补 feed-api 依赖)让 compliance 能自动降权,而非只靠 offlineRank 下架——"降权但不下架"的中间态第一期就有。
  2. 创作者信用模型(创始人 2026-06-22 定:放第一期)。 第一期建简单扣分台账(只记不连带,保守形态),contract-first 补新表(独立台账或 LevelDOcredit_score 列)+ community-api 带幂等键的扣分端点 + compliance-server 补 community-api 依赖。
  3. 锁风裁决记录升不升列(§3.3)。 现状:game_compliance_gate_result 没有 lock_strength/ip_id 列。取舍:MVP 把档位和命中 IP 写进已有的 details JSON(不改表),还是补一次 Flyway 迁移加两列(为了按档位做报表查询)。倾向写 JSON,但若确有报表需求需创始人点头升列。

6. 相关文档

文档 关系
合规闸门 法定上线门(本页 §1 讲清与它的分工);#8 内容合规材料由本页的审核记录留存实现
鉴权与权限 admin 审核台的 B 端 RBAC 模型、封禁联动 validateCreator 的承接点
13 模块 compliance(T-CMP-12 锁风门 / -06 状态机 / -09 人审队列)、ip(seam @ compliance)、feed(曝光联动)、community(等级=信用宿主)的模块边界与现状
前端域 game-admin 前端体系(Element Plus),审核台页面在其上
运营域 README 审核台在运营域的位置(上线/变现/发行之外的"内容安全运营"这一摊)

纪律:本页只讲"内容安全运营怎么运转"——审、处置、台子。法定上线门在合规闸门,模块边界在13 模块,钱怎么分在变现与单位经济,各域各司其职、互不重复。审核状态的唯一权威在 compliance,这条贯穿全页,任何模块都只读回写、不双写审核态。