SYSTEM OK | ACTION CONTRACTS 247 DOMAINS 35 DEMO ENVIRONMENT 无需申请 | 服务热线 18926139835
首页/洞察/技术系列/CASL 同构权限系统

CASL 同构权限系统

前端菜单是否显示某个按钮、后端接口是否放行某次请求、工具清单是否向外部 Agent 暴露某个操作—— 在 EAMX 中,这三处依据的是同一套能力定义。本文说明该定义的结构:15 个动作与 26 类资源、 权限字符串的解析方式、五个判定维度与三档数据范围,以及「同构」在调用方一侧的确切含义。

作者 EAMX 产品团队 · 平台工程 发布 2026-09-28 阅读 约 9 分钟 专题 技术系列 · 工程实现

01判定分散在三处

多端系统的权限判定通常由三处分别实现:前端界面以条件分支硬编码菜单与按钮的显隐; 后端接口以中间件配合令牌与角色判断是否放行;面向 AI 的工具注册表同样以条件分支硬编码可调用的操作。

三处代码各自演进,由此产生两类可复现的缺口:界面已隐藏入口,而接口未加对应保护; 接口返回拒绝,而工具清单仍向调用方建议该操作。两类缺口的共同点在于判定依据不止一套, 差异只在被哪一处先行暴露。

EAMX 的处理方式是把判定依据收敛为一处:packages/core/src/ability.ts 导出同一个能力对象类型 AppAbility,前端、接口与工具注册表均以该类型为准。 判定规则不随调用位置变化。

权限判定一处定义、三处消费:定义在 ability.ts,消费在界面、接口与工具清单。 三处之间的差异由此从实现问题转为配置问题。

02动作与资源

能力定义由两个基本量组成:动作(Action)表示可以执行的操作,资源(Subject)表示操作所指向的对象。 当前版本的 ability.ts 定义 15 个动作与 26 类资源,两者的组合构成权限的上限范围, 共 15 × 26 计 390 种。

表 1 · 15 个动作按其承担的操作分组
分组动作覆盖的操作
记录操作read · create · update · delete对记录本身的读取与增删改
通用管理export · manage数据导出与配置管理
派发与开工grab · dispatch · start抢单、指派执行人、开工
完工与关闭complete · accept · close完工报验、验收、关闭
指派与审批assign · approve指派责任人与审批处理
对话能力use使用受权限约束的对话式能力

动作的划分并不止于增删改查。工单的生命周期被拆分为抢单、派工、开工、完工、验收、关闭等独立动作, 其作用是让权限粒度足以区分「查看全部工单」与「从公池抢单」:前者为 read:workorder, 后者为 grab:workorder,两者可以分别授予同一角色。该区分由动作定义承担,不依赖界面处理。

资源一侧覆盖工单、故障报告、设备、备件、库存、采购申请、技术标准、保养计划、对话记录, 以及部门、用户、角色、租户等组织与账号对象,共 26 类。

依据:packages/core/src/ability.ts 的类型定义(Actions 与 Subjects)。

03权限字符串

角色在配置层以权限字符串保存,格式为「动作 : 资源」,资源键为小写。 能力判定使用 PascalCase 资源类型,两者之间的映射由 SUBJECT_KEY_MAP 维护。

权限字符串与能力判定
"manage:equipment"  →  can("manage", "Equipment")
"read:workorder"  →  can("read", "WorkOrder")
"use:aichat"  →  can("use", "AiChat")
"grab:workorder"  →  can("grab", "WorkOrder")

左侧为配置层存储形式,右侧为构建能力对象时产生的规则。 两者的对应关系集中在单一映射表中,新增资源类别只需在该表登记一次。

解析由 resolvePermission 完成:以冒号切分字符串取出动作与资源键,再经 SUBJECT_KEY_MAP 映射为资源类型;映射失败的权限字符串返回空值,在构建阶段被丢弃。

这一处理方式决定了配置层的安全性:写错的权限字符串会失效,而不会因无法识别被放宽为通配。

依据:resolvePermission 与 SUBJECT_KEY_MAP 的实现。

04能力构建

运行时由 buildAbilityFromPermissions 把权限列表构建为能力对象, 入参为权限列表与可选项:调用方是否为平台超管,以及权限对应的数据条件。

  1. 平台超管直接授予全部权限——判定为超管时授予 can("manage", "all"),不再逐条解析权限列表。
  2. 逐条解析权限字符串——每一条经 resolvePermission 得到动作与资源类型。
  3. 判断是否存在数据条件——该权限在 permissionConditions 中有对应条目时,以带条件的形式构建规则;无对应条目时以无条件形式构建。
  4. 构建能力对象——AbilityBuilder 汇总全部规则后返回 AppAbility。

该文件的长度为 132 行,承担两件事:类型定义决定判定可用的动作与资源范围, 构建过程决定请求上下文中的实际规则集合。同一份权限列表在三处消费时得到同一结果, 因此界面显示与接口放行之间不存在配置差。

同构带来的一个直接结果

角色在系统内的授权记录只有一份。 界面、接口与工具清单由同一份记录生成,三者之间的差异只可能来自数据条件的取值,不可能来自判定口径。

05五个判定维度

能力判定的依据为五个维度:组织、角色、资源类型、动作类型、数据范围。 同一套判定在三条通道上适用,判定结果不因请求来自界面、内嵌助手或外部 Agent 而不同。

此处需要说明一处口径差异。源文以「三维数据范围」描述平台范围、部门范围与本人范围三档, 指的是「数据范围」这一维度的三种取值。本文按站内其余页面的口径,把五个判定维度与数据范围的三档取值分开表述: 前者是判定的依据,后者是其中一项依据的取值。两种说法描述的是同一套设计,不构成冲突。

表 2 · 数据范围的三档取值
取值可见范围规则形式典型角色
all平台范围内的全部数据can("manage", "all")平台超管
department本部门范围内的数据can("read", "WorkOrder", { departmentId })部门管理员
self本人负责的数据can("read", "WorkOrder", { responsibleUserId })普通维修工

数据范围以 CASL 的条件权限实现:授予以数据字段为条件的规则,判定时以记录自身的字段值与条件比对。 部门管理员的规则以本部门标识为条件,普通维修工的规则以本人标识为条件, 由此同一动作对不同角色的可见数据集自然不同,无需为每类角色单独编写查询分支。

该机制带来一处需要留意的实现差别:在缺少数据上下文的纯前端环境中,带条件的判定不成立; 条件本身在后端被取出并注入数据库查询,形成 SQL 的 WHERE 子句。 前端由此只承担显隐,实际放行以后端注入条件后的查询结果为准。规则来源相同,两端承担的角色不同。

依据:rulesFor 的返回结构与后端查询注入的实现记录;三档取值分别对应平台超管、部门管理员与普通员工。

06同构的含义

以上结构得出一个可以直接陈述的结论:权限判定在统一执行管道内部完成。 executeAction 是唯一的写入口,参数校验、权限裁决、审批校验与审计写入均为该入口内部的环节, 与调用方是 Web 控制台还是外部 Agent 无关。这是「同构」一词在本系统中的确切含义。

由此,「Agent 拥有特权」与「Agent 可绕过审批」两种情况在结构上不成立: 外部 Agent 没有独立的判定路径,也没有可以跳过的环节。它进入的是与人工操作相同的管道, 适用相同的能力对象与相同的判定维度。

表 3 · 三条通道的身份来源与判定口径
通道使用者身份来源权限判定
Web 控制台业务人员cookie JWT同一套能力对象,五维度判定
内嵌 AI 助手系统内的对话式操作请求级上下文同一套能力对象,五维度判定
MCP Server外部 AgentAPI Key同一套能力对象,五维度判定

三条通道的身份来源不同,进入管道后适用同一套规则。身份来源的差别决定「以谁的名义执行」, 不决定「可以执行什么」。API Key 在系统内按角色签发,权限随该角色确定,集团与各单位的可见范围按上述维度分别计算。

本文的核心判断

「Agent 不绕过审批」在本系统中并非一项需要事先约定的承诺,而是架构结果:不存在可绕过的路径。 权限即契约,系统内没有第二套判定口径。

依据:executeAction 管道的环节划分与 AppAbility 的三处共用方式。通道与接入方式的完整说明见 AI 原生与 Agent 接入。

07三层消费

同一份能力对象在三处消费。消费方式各有差别,判定依据相同。

表 4 · 同一能力对象的三处消费
层级消费方式实现位置
Web 控制台ability.can(action, subject) 决定按钮与菜单的显隐共享的 AppAbility 实例
后端接口中间件以同一能力对象裁决,并按规则注入数据条件API Server
工具清单getAuthorized(ability) 按权限裁剪工具清单Tool Factory

工具清单的裁剪方式值得单独说明。工具注册表提供按能力过滤的方法: 工具在注册时标注所需的动作与资源,取清单时逐条比对; 未标注权限要求的工具默认向全部调用方开放。

因此工具清单在服务端按账号权限生成:调用方拿到的清单即为服务端的授权结果。 生成时未列入的动作不会出现在调用方的可调用集合中,也就不存在调用时的拒绝。 这一差别决定了权限边界的位置:界面隐藏入口属表现层处理,绕过界面仍有试探空间; 清单裁剪属结构性限制,客户端没有可试探的对象。

口径:截至本文发布,动作契约共 247 条,覆盖 35 个业务域;演示账号可见的工具由端点实时返回。该清单可由演示环境实时导出并核对。

08边界与不承诺

说明上述结构之后,需同时说明本文的范围。以下三项属系统自身的约束与不作出的承诺, 在能力说明之前列出。

表 5 · 应当在能力说明之前列出的三项边界
事项说明
哪些动作不得自主执行 改账、报废、权限变更等高风险动作在动作定义上标注需人工确认,未携带确认的调用一律拒绝执行
只读角色不可见什么 写入类动作不在该角色的清单内。边界由清单生成时的裁剪划定,不依靠调用时的拦截
关于标准与认证 本页所述为系统自身的设计约束,不构成对任何标准或认证的符合性认定。认证对象是组织,而非软件

另有一项属性能范畴,本文不下结论:识别与判断的准确率,以及无人值守的程度。 本文所述内容集中于权限判定的结构与边界,与上述两项指标无关。

09作者与依据

作者
EAMX 产品团队 · 平台工程
依据
能力定义文件 packages/core/src/ability.ts(132 行)中的类型定义与构建过程;本系统的权限与审计设计实现记录
数据来源
动作契约清单(可实时导出)、演示环境(无需申请公开)
引用标准
本页不涉及标准条款对照;ISO 55000 系列为本方的方法论依据,不构成认证
更新日期
2026-09-28
01相关产品能力

本文所述的判定口径,可在这些页面核对

02相关文章

同专题与跨专题的延伸

本技术系列共 11 篇,总纲见 技术系列专题;各篇为独立长文,亦可单独查阅。

本文所述的判定结构可由贵方自行核对

五个判定维度、工具清单的裁剪方式、审计口径的同一性——上述各项均无需采信本文陈述, 可由演示环境当场核对,或由贵方自有客户端报告可见工具数量。

信息中心 / 技术评估
要接入方式与判定口径的完整说明
业务与执行层
关注权限边界在业务执行中的表现