查看 Markdown

DeveloperSemantic · 治理与运营

访问与安全

这一页讲应用怎样确认访客,以及资源怎样分享。应用不需要自己写登录页,也不需要自己保存用户。

说明

前提:读取自己的身份不需要特别的角色。分享资源要是资源的 Owner。管理成员、组和 Markings 要组织(命名空间 cell-demo)的 developer。命令行要先运行 aidc login。

快速上手

先看自己是谁。再在应用里读取当前用户,判断能不能显示某个按钮。

看自己是谁
$ aidc semantic admin whoami
张三(zhang.san)· Demo Company(cell-demo)· developer · Key aidc-dk-xxxxxxxx… · 可发布到 cell-demo
import { semantic } from "/developer/sdk/v1/aidc.js";

const me = await semantic.admin.getCurrentUser();
if (!me.signedIn) semantic.admin.signIn();
if (semantic.admin.can(me, { action: "production.flag_issue" })) showFlagButton();

登录与身份

打开 Nexus 应用前,平台先检查登录和成员身份。没有登录的人会去 AIDC 登录页,登录后回到应用。不是组织成员,并且没有被分享的人,会看到 403。

应用不能伪造身份。访客的身份随应用票据下发。服务端按这个身份判断每一次读写。

semantic.admin.getCurrentUser() 返回的主要字段:

字段 说明
signedIn 是否已登录
member 是否是应用所在组织的人(developer 或 member)
role 角色:developer、member、editor、viewer 或 anonymous
shared 是否通过分享打开
permissions read、actions、write 是名称数组。share 是是否允许分享的布尔值

semantic.admin.can(me, { action: "…" }) 只在页面里判断,用来决定显示或隐藏按钮。服务端仍然独立判断每一次操作。

semantic.admin.viewer() 同步返回页面里的访客信息,不发请求。它只在 Nexus 应用里有值。

公开链接也要登录

公开链接的访客也要先登录 AIDC 账号。登录后,应用知道访客是谁。清单里的 auth.publicLink 决定公开链接的访客能做什么:

值 持公开链接的访客
signin(缺省) 先登录再打开。组织成员按组织角色访问。指定账号分享的访客按分享角色访问。其他人只读
members 登录后,组织成员和已获指定账号分享的组织外账号能打开。其他人看到 403
{ "auth": { "access": "company", "publicLink": "members" } }
const me = await semantic.admin.getCurrentUser();
if (!me.signedIn) semantic.admin.signIn();                // 整页跳到登录页,登录后回到当前链接
else if (!me.member) ui.toast("仅限本组织成员使用");        // 已登录,但不是组织的人

signIn() 是整页跳转。登录后回到当前链接。

角色

组织里有两种角色:developer 和 member。资源上有三种角色:Owner、Editor 和 Viewer。

角色 谁 能做什么
developer 组织的开发者,包括持 developer 授权码的账号、组织管理员和 AIDC 平台员工 看全部,定义本体,直接改数据,分享,使用 test 通道
member 组织的成员,持 member 授权码的账号 看清单登记的类型,执行 Action
editor 通过指定账号分享获得 editor 角色的人。可以是别的组织的人 同 member
viewer 只读分享或公开链接的访客 只看
developer / member 官方应用的访客。需要登录,且至少属于一个组织 按角色访问

资源上的角色:

角色 能做什么
Owner 改分享和访问设置,添加其他 Owner。资源的创建人也是 Owner
Editor 改内容。例如在本体里执行 Action 改数据,或编辑文件。不能改分享
Viewer 查看和使用

只有 Owner 能改分享。组织的开发者也是资源的 Owner。Space 中不属于 Project 的个人条目不授予组织开发者隐式 Owner 角色。

应用清单可以把访问收紧到只有开发者和被分享的人:

{ "auth": { "access": "restricted" } }

缺省是 company。组织的成员都能打开。Action 也可以用 roles 限定能执行它的角色。

开放程度

资源的开放程度分四档。每一档比上一档更开。

Object Type、媒体集、Applications、应用及 Project 内的 Space 条目继承父资源的访问权限。你不能把这些资源单独设为 private。应用和 Applications 只支持 group、internet。

档位 谁能看 API 中的值
Private 只有 Owner。Owner 可以有多个 private
Group 指定的人、组、整个组织,以及拿到邀请链接的人 group
Public 所有登录的 AIDC 账号,包括别的组织的人。只读,不含匿名访客 public
Open to Internet 任何人,不用登录。只读 internet

规则:

  • Public 和 Open to Internet 只能授予 Viewer。
  • Open to Internet 只用于有匿名只读入口的资源:文件、应用、组织的 Applications 和 Space 条目。
  • Open to Internet 只管读。匿名访客只能通过应用嵌入的 Custom widget 调用允许的 Semantic 读接口。应用必须设为 Open to Internet。匿名访客不能执行 Action,也不能查 SQL。
  • 本体上的角色继承到它的 Object Type。Object Type 自己的授予只能加,不能减。
  • 页面上显示的开放程度由授予算出。有 Open to Internet 的授予,就是 internet。有 Public 的授予,就是 public。有给人、组或邀请链接的非 Owner 授予,就是 group。只有 Owner 授予或没有授予,就是 private。

资源包括本体、Object Type、数字员工、文件和 Applications。资源的 RID 形状如下:

  • 本体:ri.ontology.aidc.ontology.<组织>
  • Object Type:ri.ontology.aidc.object-type.<entityId>
  • 数字员工:ri.agents.aidc.agent.<id>
  • 文件:ri.compass.aidc.file.<id>

一步设到一档,用 setResourceAccess:

以下 SDK 示例需要开发者 Key 和资源的 Owner 角色。应用票据不能调用这个接口。

await semantic.filesystem.setResourceAccess(rid, "group");   // 需要 Owner 角色
aidc semantic filesystem access <rid> --tier group

四档的效果如下:

  • private:撤掉所有分享,只剩 Owner。继承父资源的资源不支持这一档。
  • group:撤销 Public 和 Open to Internet。资源不继承父资源且没有其他分享时,授予整个组织 Viewer。
  • public:撤销 Open to Internet,添加 Public 的 Viewer 授予。
  • internet:加上 Open to Internet 的 Viewer 授予。

命令的全部参数见 aidc semantic filesystem access。

分享资源与应用

资源用 semantic.filesystem 分享。应用用 shareApplication 分享。

下面的资源分享和邀请链接示例需要开发者 Key。应用票据不能调用这些接口。

import { semantic } from "/developer/sdk/v1/aidc.js";

await semantic.filesystem.shareResource(rid, { group: "<组 id>", role: "viewer" });   // 分享给一个组(部门就是组)
await semantic.filesystem.shareResource(rid, { user: "<账号 id>", role: "editor" });  // 分享给一个账号
const { url } = await semantic.filesystem.resourceLink(rid, { expiresInDays: 7 });   // 邀请链接

资源可以分享给这些对象:

对象 写法
一个人 账号 id(user)
一个组 组 id(group)。部门就是组
整个组织 cell-<命名空间>,例如 cell-demo
组织的开发者 cell-<命名空间>:developers

别的组织的组,只能按 cellId 精确找。

应用的分享,用 shareApplication:

// 应用分享给组织的全员,只读
await semantic.filesystem.shareApplication({ audience: "company", role: "viewer" });
// 指定账号,30 天后失效
await semantic.filesystem.shareApplication({ audience: "users", account: "li.si@example.com", role: "editor", expiresInDays: 30 });
// 公开链接:持链接、登录了的人只读。完整地址只返回一次
const { url } = await semantic.filesystem.shareApplication({ audience: "public" });
audience 谁能打开 角色
company 组织的全员 viewer 或 editor
users 指定的账号。可以是别的组织的人 viewer 或 editor
public 持链接、登录了的人。只读 viewer
分享给全组织
$ aidc share inspector --company
已分享:inspector → company(viewer)
公开链接
$ aidc share inspector --public --days 7
已分享:inspector → public(viewer)
链接(只显示这一次):https://www.ai-dc.ai/nexus/s/…

分享的规则:

  • 再次分享给同一个对象,会改角色和有效期。company 和 users 的分享是幂等的。
  • 每次 public 分享都新建一条公开链接。
  • 每次分享和撤销都写进审计日志和应用日志。
  • 分享的是真实数据。发出前,确认数据可以对外。
  • 邀请链接:持链接的人先登录 AIDC 账号。打开 /share/<令牌> 后,得到一条 Viewer 授予。链接可以撤销。缺省 30 天有效。

应用的分享用 aidc share。资源的分享用 aidc semantic filesystem share:

aidc share list inspector                                              # 列出应用的分享
aidc share revoke <分享 id>                                            # 撤销
aidc semantic filesystem share <rid> --group <组 id> --role viewer     # 分享资源给一个组
aidc semantic filesystem link <rid> --days 7                           # 建邀请链接

aidc share 的全部参数见 aidc share。资源分享的参数见 aidc semantic filesystem share。

组织、用户与组

组织是一家公司。数据按组织隔离。组织里有用户,用户可以放进组。部门就是组,组可以嵌套。组织的架构由平台提供,不需要在本体里另建。

  • 组织:一家公司。命名空间是 cell-…,例如 cell-demo。
  • 用户:主组织只有一个。在别的组织持有授权码的人,是那个组织的访客。
  • 组:用户和其他组的集合。组可以嵌套,但不能成环。上下级就是组的嵌套。
  • 用户属性:岗位和部门名是用户属性,例如 department 和 jobTitle。一个键可以有多个值。
  • 智能体:智能体是资源,不是组织成员。给智能体设可见范围,用分享。

组织的开发者运行这些命令,管理组和用户:

aidc semantic admin groups create --name 财务 --description 财务部的人
aidc semantic admin groups add-members <财务组 id> <账号 id> <应付组 id>
aidc semantic admin groups add-members <财务组 id> <外部审计账号 id> --expires 2026-12-31
aidc semantic admin groups members <财务组 id> --transitive
aidc semantic admin users set-attributes <账号 id> department=财务 jobTitle=会计
aidc semantic filesystem share <智能体 rid> --group <财务组 id>

同样的操作,在应用里用 SDK:

const group = await semantic.admin.createGroup({ name: "财务", organizations: ["cell-demo"], description: "财务部的人" });
await semantic.admin.addGroupMembers(group.id, ["<账号 id>"]);
  • 组的 organizations 决定哪些组织能看见这个组。组名在主组织里不能重复。
  • 资源分享、Markings 成员和对象安全策略的 group 条件,都可以用组。
  • aidc semantic admin groups expiration 设定新成员最长多久后到期。
  • 临时成员用 --expires,到期后自动失效。

导入已有名单

组织已经有员工账号时,可以把名单导进 AIDC。导入的人都成为组织的 member。先用 --dry-run 看每个人会怎么处理。

先预演导入
$ aidc semantic admin members import users.json --source old-portal --dry-run
预演(没有写入):Demo Company(cell-demo)· 来源 old-portal · 3 人
  新建待激活账号 + member:2
  已是 member,不动:1
  席位:41 → 43 / 50
确认无误后去掉 --dry-run 再跑一次;重复导入不会重复建号。
情况 处理
邮箱在 AIDC 里没有账号 新建待激活账号,并加上 member 授权码
账号存在,但还不是组织的人 补一张 member 授权码
已经是组织的 member 不动
已经是组织的 developer 不动。不降级
账号已停用 不动
冲突 不处理。结果里计入「冲突,未处理」

导入的规则:

  • 文件可以是 JSON 或 CSV。JSON 是 [{ "email": "…", "name": "…", "externalId": "…" }],或 { "members": [...] }。CSV 的表头要有 email,可以有 name 和 externalId。
  • 一次最多导入 1,000 人。
  • 每人占一个席位。席位不够时,整批拒绝。错误码是 license_quota_exceeded。
  • externalId 记下来源系统里的 id。同一个人重复导入,不会重复建号。整个导入是幂等的。
  • 本人第一次用这个邮箱登录(收到验证码)时,账号即激活。导入不替本人验证邮箱,也不迁移原系统的口令。

SDK 的写法:

const plan = await semantic.admin.importMembers({
  source: "old-portal",
  members: [{ email: "zhang.san@example.com", name: "张三", externalId: "user_2x" }],
  dryRun: true,
});
console.log(plan.summary, plan.seats);

命令的全部参数见 aidc semantic admin members import。

数据安全:Markings 与安全策略

财务、薪资和配方这类数据也放进本体。三种控制管住这些数据。开放程度和角色决定能不能打开资源。下面的控制再管到每一行和每一列。

控制 挂在哪 怎么判断
Markings(强制控制) 本体、Object Type、数据流、表导入;或者写在行上(marking 属性) 挂着的 Marking 都要满足,才能看见。不看角色,Owner 和 developer 也一样。只能收紧,不能放宽
对象安全策略(行) Object Type 定义里的 objectSecurityPolicy 按对象的属性和读的人,判断每一行能不能看
属性安全策略(列) Object Type 定义里的 propertySecurityGroups 一组属性另外要满足的条件或 Marking。不满足的人读到 null,也不能用它筛选、排序或求和

Marking 属于一个类别。同一个类别里,默认要全部满足。用 --disjunctive 建的类别,满足其中一个即可。

先建 Marking,再挂到资源上:

aidc semantic admin marking-categories create --name 数据分级
aidc semantic admin markings create --name 薪资 --category <类别 id> --member <人事组 id>
aidc semantic admin markings grant <薪资 id> USE <HR 负责人账号 id>
aidc semantic filesystem mark <rid> <薪资 id>

Marking 的角色:

  • ADMINISTER:管理成员和角色。
  • USE:可以把 Marking 挂到资源上。
  • DECLASSIFY:可以去掉 Marking,或停止继承。

挂上 Marking 要有 USE。去掉 Marking 要有 DECLASSIFY 和 USE。两种操作都要是资源的 Owner。管 Marking 的人,不一定能看见它保护的数据。Marking 和类别建好以后,不能删除。

行和列写在 Object Type 的定义里。Marking 用 id 引用。下面是员工薪酬的例子:

{
  "kind": "objectType", "apiName": "employeeCompensation", "title": "员工薪酬",
  "schema": {
    "columns": [
      { "name": "employeeId", "type": "string", "primaryKey": true },
      { "name": "accountId", "type": "string" },
      { "name": "baseSalary", "type": "decimal" },
      { "name": "rowMarkings", "type": "array", "arraySubType": "marking", "notNull": true }
    ],
    "objectSecurityPolicy": {
      "name": "compensation-rows",
      "granularPolicy": { "type": "and", "conditions": [
        { "type": "markingProperty", "property": "rowMarkings" },
        { "type": "or", "conditions": [
          { "type": "group", "name": "<人事组 id>" },
          { "type": "comparison", "comparison": { "operator": "EQUAL",
            "left": { "type": "userProperty", "userProperty": { "type": "userId", "userId": {} } },
            "right": { "type": "property", "property": "accountId" } } }
        ] }
      ] }
    },
    "propertySecurityGroups": [{ "name": "pay", "properties": ["baseSalary"], "appliedMarkings": { "<薪资 id>": "MANDATORY" } }],
    "dataSecurity": { "markingConstraint": { "markingIds": ["<高管薪酬 id>"] } }
  }
}

这个例子的意思如下:

  • 这一行的 rowMarkings 要全部满足。
  • 还要满足下面二者之一:属于 <人事组 id> 对应的组,或者是这一行的本人。
  • baseSalary 属于 pay 组。这一组要有「薪资」Marking。

试一试某个人能看见哪些对象和属性。结果只说明能不能看,不返回属性值:

aidc semantic security test employeeCompensation --user <账号 id> --pk e1,e2

完整参数见 aidc semantic security test。

数据安全的规则:

  • 读:所有读的路径都按读的人判断。包括本体 API、对象集订阅、聚合、编辑历史、工作台和自动化。Agent Key 按持有人或服务用户的 Marking 成员资格判断。有 owner 的智能体还受 owner 权限限制。Ontology SQL 不包含受保护的类型。
  • Action:可以新建自己看不见的对象。改属性要看得见它现在的值。删除要看得见整个对象。链接的两端都要看得见。
  • 自动化:条件和效果按拥有者的权限判断。邮件通知按每个收件人的权限过滤。
  • 只在读的时候判断:函数的结果、Action 写入的值和导出的文件,不继承原数据的安全控制。
  • 修改安全策略:改的人要满足改前和改后涉及的全部 Marking。新加 Marking 要 USE。去掉 Marking 或停止继承,要 DECLASSIFY 和 USE。

权限一览

应用里的访客能做什么,由下表决定:

谁 读 执行 Action 直接写 定义和发布
开发者 Key(CLI 和智能体) 组织里的全部 全部 未声明智能体身份时可以 可以
应用里的 developer 访客 清单 semantic.types 登记的 清单登记的,且角色允许的 清单 semantic.write 登记的 不可以
应用里的 member 或 editor 清单登记的,且对组织全员可见的 清单登记的,且角色允许的 不可以 不可以
viewer(只读分享或公开链接) 同上 不可以 不可以 不可以

开发者 Key 声明 x-aidc-author: agent:… 后,不能直接写数据。智能体必须执行 Action 来改数据。

应用清单里这样登记:

{
  "sdk": ["semantic", "ui"],
  "semantic": {
    "types": ["production.order_line", "production.line"],
    "actions": ["production.flag_issue", "production.resolve_issue"],
    "write": []
  }
}

"*" 表示看得见的全部。数据浏览器这类通用应用会用到它。

上表之外,Markings 和安全策略对所有人生效,包括开发者 Key。挂了 Marking 的数据,不是成员就读不到。

票据

应用票据是访客在应用里的凭证。浏览器 SDK 自动带上票据。SDK 发请求时检查票据,按剩余有效期尝试续期。

  • 组织应用的票据 8 小时有效。官方公开应用(public)的票据 1 小时有效。
  • 票据剩余有效期不超过 60 秒时,SDK 尝试用当前票据续期。
  • 票据过期后 24 小时内也能续。续票时,服务端会确认账号仍有权访问,分享仍然有效。
  • 超过 24 小时宽限期后,不能凭旧票据续期。

命令行

这一节列出访问、成员和分享的命令。每个命令的参数都在参考页里。

命令 做什么
aidc semantic admin whoami 看自己是谁,以及角色
aidc semantic admin members list 列出组织的成员
aidc semantic admin members import <名单> --source <来源名> 导入已有名单。加 --dry-run 先预演
aidc semantic admin groups … 建组、加减成员、设成员资格的期限
aidc semantic admin users … 查看用户,设置用户属性
aidc semantic admin markings … 建 Marking,授予角色,加成员
aidc semantic filesystem … 看资源,设开放程度,分享,建邀请链接,挂 Marking
aidc share <应用> 分享应用:--company、--user 或 --public
aidc semantic security test 试一试安全策略

全部参数见 参考 · 访问、自动化与用量、参考 · 应用与界面 和 参考 · Semantic 本体与数据。

API

访问、成员和分享的 SDK 与命令调用下面这些端点。Developer 接口接受开发者 Key 或应用票据。Filesystem 接口接受开发者 Key 或网页登录会话。Filesystem 接口拒绝应用票据。

导入名单的预演使用请求头 x-aidc-dry-run: true 或查询参数 dryRun=1。不要把 dryRun 放进 JSON 请求体。

方法 路径 做什么
GET /api/v1/developer/auth/me 查看当前用户和权限
GET / POST /api/v1/developer/shares 列出应用的分享;分享应用
DELETE /api/v1/developer/shares/{id} 撤销分享
GET /api/v1/developer/members 列出组织的成员
POST /api/v1/developer/members/import 导入名单。可以重复导入
GET /api/v1/filesystem/resources?scope=public|organization|shared|mine 列出看得见的资源
GET /api/v1/filesystem/resources/{rid} 读一个资源和我的角色
GET /api/v1/filesystem/resources/{rid}/roles 列出资源上的授予
POST /api/v1/filesystem/resources/{rid}/roles/add 添加授予
POST /api/v1/filesystem/resources/{rid}/roles/remove 撤销授予
POST /api/v1/filesystem/resources/{rid}/access 一步设开放程度。请求体是 {"tier": "group"}
POST / DELETE /api/v1/filesystem/resources/{rid}/links 建邀请链接。撤销时用 /links/{linkId}
POST /api/v1/filesystem/links/redeem 兑换邀请链接
GET /api/v1/filesystem/principals?q= 查找可以分享给的人和组

限制

下表列出访问与安全的上限。

项目 上限
一次导入的人数 1,000 人
组织应用的票据有效期 8 小时
官方公开应用的票据有效期 1 小时
票据过期后续票的宽限 24 小时
对象安全策略的比较数 10 个
安全策略的权重总和 小于 10,000。常量 1,集合 1,000,Marking 条件 3,000
属性安全策略的组数 20 组
一个属性安全策略组的属性数 256 个
每个 appliedMarkings、assumedMarkings 映射的 Marking 数 各 20 个
每个 constantMarkings.markings 数组的 Marking 数 20 个
markingConstraint 的 Marking 数 1 到 50 个

常见错误

按错误码或现象查。

错误或现象 原因 怎么办
页面显示 403 不是组织的成员,也没有被分享 请资源的 Owner 分享给你,或加入组织
页面显示「仅限本组织成员使用」 已登录,但不是组织的成员 用组织的账号登录
forbidden,提示要先改资源自己的设置 目标开放程度比资源自带的设置更窄 先到资源自己的设置里改,再设开放程度
invalid_payload Public 或 Open to Internet 授予了 Viewer 以外的角色 把角色改成 viewer
license_quota_exceeded 导入后的席位超过授权的人数 减少导入的人数,或增加席位后再导入
--role 的值不对,退出码 2 角色不是 owner、editor 或 viewer 改成三者之一

下一步

本页由 developer/docs/auth.md 生成 · Markdown 原文 · llms.txt