合规与风险

本页是一篇完整方案指南:以 compliance 插件(com.auraboot.compliance,命名空间 compliance)为例,从用户场景一路讲到开发实施和典型错误。它是 config 型插件——6 个 model、49 条命令、14 个页面加 1 个看板全部是 DSL JSON 声明,没有一行后端 Java;下面每个标识符你都能在插件里 grep 到、对运行实例调得通。

合规域的标识符有一个容易踩的不对称:命名空间是 compliance,但 model 前缀、命令前缀、权限模块都缩写成 cmp。model 是 cmp_risk、命令是 cmp:assess_risk、权限是 cmp.risk.manage——不要写成 cmpl_*compliance:*


1. 用户场景

一家做 SaaS 的公司要拿 SOC 2,同时受 GDPR 约束、内部还跑 ISO 27001。合规负责人的日常:

  • 把一个合规框架(SOC 2 / ISO 27001 / GDPR…)拆成一批控制措施,逐条落实、验证;
  • 对流程、系统、供应商识别风险,评估可能性 × 影响,做缓解或接受,最后关闭;
  • 每个控制要留证据(日志、截图、配置、政策文档),证据要被审核、会过期;
  • 按框架排审计(内部 / 外部 / 抽查),记录范围、发现项、跟进;
  • 维护政策文档,带版本和生效状态。

合规管理员、审计员、普通查看者看到的数据和能做的操作各不相同。

2. 需求痛点

  • 证据散落、事后凑不齐:控制是不是真的执行过、证据在哪、有没有过期,平时记在 Excel 和邮件里,审计师来要的时候临时翻。
  • 风险无受控流转:风险从「识别」到「关闭」靠人记状态,没有强制的状态机,跳步、漏评估查不出来。
  • 操作无授权无审计:谁批准了哪份证据、谁关闭了哪条风险,没有结构化记录;给外部审计师开账号,权限要么开太大、要么靠人盯。
  • 集成困难:想让自动化规则或 AI 助手帮着「列出逾期未验证的控制」「起草发现项」,却没有可被程序调用的统一入口。

这些都不是「再加一张表」能解决的,而是受控状态变更 + 可索引审计的问题。

3. 产品方案

在 AuraBoot 里,每一个合规动作都是一条命令,走统一的 命令管道:

  • 风险详情页的「评估风险」按钮调用 cmp:assess_risk,而不是裸写 PUT /api/cmp_risk;命令在管道里统一鉴权 → 校验状态机 → 执行 → 审计 → 发事件
  • 状态流转用声明式的 state_transition:cmp:assess_risk 只允许从 identified 走到 assessed,跳步直接被管道拒绝。控制、审计、证据、政策、框架都是这种状态机。
  • 同一条命令既是 UI 按钮的目标,也能被自动化规则、BPM 步骤、AI agent 调用——每条命令都带 cmd_risk_levelagent_hint,告诉 agent 它能做什么、风险多大。
  • 命令管道本身产出结构化审计记录(谁、何时、权限评估、字段前后差异)。合规插件不"合成"证据,它索引管道本来就产出的东西。

4. 功能设计

4.1 数据模型(6 个)

Model用途关键状态值(字典)
cmp_framework合规框架(SOC 2 / ISO 27001 / GDPR / HIPAA / PCI DSS / CCPA / 其他)cmp_framework_status:planning → in_progress → certified → expired
cmp_control框架下的控制措施cmp_control_status:not_started → in_progress → implemented → verified(另有 non_compliant)
cmp_risk风险登记cmp_risk_status:identified → assessed → mitigated / accepted → closed
cmp_audit审计记录(关联框架)cmp_audit_status:scheduled → in_progress → completed → follow_up
cmp_evidence控制证据cmp_evidence_status:pending_review → approved / rejected → expired
cmp_policy政策文档(带版本)cmp_policy_status:draft → active → archived

风险用 5×5 矩阵评分:可能性字典 cmp_risk_likelihood(rare / unlikely / possible / likely / almost_certain)× 影响字典 cmp_risk_impact(negligible / minor / moderate / major / catastrophic)。风险分类 cmp_risk_category 的合法值是 data_breach / system_failure / insider_threat / vendor_risk / regulatory / operational(注意是 vendor_risk,不是 vendor)。

4.2 命令与状态机

命令命名 cmp:<动词>_<名词>,全插件 49 条。每个域有一套相似的命令:create / update / delete(带 preconditions)/ detail / list,加上各自的状态流转。代表性命令:

命令作用
cmp:create_risk / cmp:assess_risk / cmp:mitigate_risk / cmp:accept_risk / cmp:close_risk风险全生命周期
cmp:create_control / cmp:start_control / cmp:implement_control / cmp:verify_control / cmp:flag_non_compliant控制实施与验证
cmp:create_audit / cmp:start_audit / cmp:complete_audit / cmp:followup_audit审计周期
cmp:create_evidence / cmp:approve_evidence / cmp:reject_evidence / cmp:expire_evidence证据审核
cmp:create_policy / cmp:activate_policy / cmp:archive_policy政策生效
cmp:create_framework / cmp:start_framework / cmp:certify_framework / cmp:expire_framework框架认证

每条命令都是一段声明。例如 cmp:assess_risk(config/commands/cmp_risk.json)的真实定义:

{
  "code": "cmp:assess_risk",
  "displayName:zh-CN": "评估风险",
  "displayName:en": "Assess Risk",
  "type": "state_transition",
  "modelCode": "cmp_risk",
  "stateField": "cmp_risk_status",
  "fromStates": ["identified"],
  "toState": "assessed",
  "permissions": ["cmp.risk.manage"],
  "agent_hint": "Transition risk from identified to assessed.",
  "cmd_risk_level": "L1"
}

读出来的设计信息:这是一条 state_transition,把 cmp_risk_statusidentified 推到 assessed,只有 fromStates 里的来源状态才允许执行(在 mitigated 上点「评估」会被管道拒绝);要求 cmp.risk.manage 权限,风险级 L1,并通过 agent_hint 告诉 agent 它能做什么。

create 类命令则用 autoSetFields 自动生成编码并钉初始状态——例如 cmp:create_risk"cmp_risk_code": { "strategy": "auto_generate", "pattern": "RISK-{yyyyMMdd}-{seq}" } 生成风险编号,用 "cmp_risk_status": { "strategy": "fixed_value", "value": "identified" } 把新建风险钉在 identified,新记录从此进入状态机。delete 类命令带 preconditions(如删除风险要求 cmp_risk_status IN [identified]),拦截误删已进入流程的记录。

4.3 权限与角色

12 个权限码(<模块>.<资源>.<动作>,module 都是 compliance,每资源 manage + read):

cmp.framework.manage    cmp.framework.read
cmp.control.manage      cmp.control.read
cmp.risk.manage         cmp.risk.read
cmp.audit.manage        cmp.audit.read
cmp.evidence.manage     cmp.evidence.read
cmp.policy.manage       cmp.policy.read

3 个角色:

  • cmp_admin(合规管理员)—— 全部 12 个权限。
  • cmp_auditor(合规审计员)—— 所有资源 read + 审计与证据的 manage(cmp.audit.manage / cmp.evidence.manage),正好对应「能跑审计、能审核证据,但不改框架和控制定义」。
  • cmp_viewer(合规查看者)—— 只读 6 个 read

要做「外部审计师——只读」这种临时角色,组合 6 个 .read 权限即可;数据可见范围进一步用平台的权限五层模型(RBAC + 组织域 + ReBAC + ABAC + 字段级)收窄,这部分是平台底座能力,不在本插件配置里。

4.4 页面

14 个页面 + 1 个看板:

  • 每个 model 的 list / form(cmp_*_list / cmp_*_form),框架和控制额外有 detail 页(cmp_framework_detail / cmp_control_detail)。
  • cmp_dashboard 看板,消费 4 个命名查询:cmp_dashboard_kpi(总框架数 / 已认证 / 控制覆盖率 / 未关闭风险 / 90 天内待审计 / 生效政策)、cmp_control_coverage(控制按状态分组)、cmp_risk_matrix(风险按可能性 × 影响分布)、cmp_upcoming_audits(90 天内到期框架)。

5. 具体开发与实施

先掌握基础。本插件没有任何后端 Java,全靠平台的几个核心契约。动手前请先读:Model 与 Field · Command · 命令管道 · Permission · 插件清单 · 纯配置 Plugin · Page Designer

落地一个像 compliance 这样的 config 插件,步骤是:

  1. 定义 model 与字段 —— config/models.json + config/fields/,字段类型用平台 dataType(string / integer / enum / decimal / date…)。cmp_framework 等都是 modelType: entity。详见 Model 与 Field
  2. 声明命令 —— 每个 model 一个 config/commands/<model>.json(如 cmp_risk.json),状态流转用 type: state_transition + stateField + fromStates / toState,新建用 type: create + autoSetFields,并在 permissions 绑权限码。详见 Command
  3. 配字典 —— config/dicts.json,每个状态字段对应一个静态字典(cmp_risk_status 等),命令里 toState 的取值必须落在字典里。
  4. 配 model-field binding —— config/bindings/,并在 resourceDirs 注册(见「典型错误」)。
  5. 设计页面 —— config/pages/,列表 / 表单 / 详情用 Page Designer 出 DSL;看板放 config/dashboards/,数据来自 config/named-queries.json
  6. 权限、角色、菜单 —— config/permissions.json / roles.json / menus.json
  7. 打包导入 —— 用 aura CLI 的 import-directory-sync(参数是目录 path)或平台导入接口;校验返回 success:true 才算导入成功。plugin.jsonprovides 列出对外契约(6 个 model + 6 个 create 命令 + 4 个 query + 看板),导入器据此做引用校验。详见 插件清单

6. 常见配置

  • 多框架共享控制:控制通过 cmp_ctrl_framework_id 关联框架。一个 MFA 控制可以同时服务 SOC 2 与 ISO 27001——按需各建一条控制并分别引用,或在控制描述里标注覆盖的多框架条款。
  • 证据过期提醒:证据有 cmp_ev_valid_until,到期用自动化规则触发 cmp:expire_evidence 把状态推到 expired,看板的 cmp_dashboard_kpi 控制覆盖率随之下降,提示需要重新取证。
  • 审计排程:框架的 cmp_fw_next_audit_date 驱动 cmp_upcoming_audits 命名查询(90 天内到期);到期前用 cmp:create_audit(初始状态 scheduled)起一个审计,再 cmp:start_auditcmp:complete_audit
  • 暴露给 AI agent:只读 / 低风险命令(cmp:list_riskscmp:list_controls,cmd_risk_level: L0)适合让 agent 自由调用做汇总;delete 类是 L4、状态推进类是 L2,靠 cmd_risk_level 让 agent 接入面知道哪些动作需要人确认。详见 Agent 就绪度

7. 典型错误

  • 命令码用点号:写成 cmp.risk.assess 跑不通——真实是冒号 + 动词_名词:cmp:assess_risk。点号 cmp.risk.manage权限码,不是命令码,两者别混。
  • 前缀写错:model 是 cmp_risk(不是 cmpl_risk),命令前缀是 cmp:(不是 compliance:)。命名空间叫 compliance,但 model / 命令 / 权限模块都缩写成 cmp
  • 臆造不存在的 model / 命令:插件只有 6 个 model,没有 cmp_sod_policy 这类职责分离专用模型,也没有 cmp:audit_case_close 之类命令。关闭审计实际走 cmp:complete_audit(in_progress → completed)。配置前先 grep plugin.jsonprovides
  • 绕过命令直接改表:直接 UPDATE mt_cmp_risk.cmp_risk_status 会跳过状态机校验和审计记录,导致风险无凭据地跳步、审计链断裂。一切状态变更都走命令
  • 状态机跳步:在 mitigated 的风险上点「评估」会被拒——cmp:assess_riskfromStates 只含 identified。这是设计,不是 bug。
  • bindingRules 写进 commands.json 内联:不会被导入;必须独立 bindingRules.json(本插件该文件是 [])并在 resourceDirs 注册,否则报 [S-EXT-HANDLER] references unregistered handler。详见 纯配置 Plugin
  • 命令执行 payload 结构:字段放在 { "payload": { ... }, "operationType": ... },目标记录用 targetRecordId(不是 recordId)——放错位会出现「执行成功却字段为空」的迷惑性报错。

下一步

  • 系统总览 —— 插件、命令与运行时如何拼到一起
  • 命令管道 —— 上面每条命令都走的执行契约,审计记录就在这里产出
  • 权限 —— 外部审计师角色背后的五层模型
  • 插件清单 —— provides 如何声明对外契约
  • Agent 就绪度 —— 用 cmd_risk_level / agent_hint 决定哪些命令暴露给 agent