账户与访问权限
一个账户包含你的项目、团队成员以及一种访问模型。
账户包含你的项目以及在其中工作的人员。注册时,Beeuni 会为你创建个人账户。邀请一位团队成员后,账户就会变为团队账户。个人账户和团队账户使用相同的角色、账单和限额。
一种访问模型
Beeuni 只有一种授权记录:分配。每项分配都会在特定范围内,将一个主体与一个角色绑定。
| 术语 | 含义 |
|---|---|
| 主体 | 获得访问权限的人或对象。可以是user、group、service_account(代理的身份),或pending受邀者的电子邮件地址。 |
| 角色 | 一组有名称的权限。Beeuni 提供以下内置角色。账户可以添加自定义角色。 |
| 权限 | 一项操作,例如project.secret.read或member.update。 |
| 范围 | 角色的适用位置:整个account,或一个project。 |
| 对象 | 可选。将分配范围缩小到范围内的一个agent、skill、secret、app或trigger。 |
| 到期时间 | 可选。分配在expires_at停止授予权限。 |
不存在第二种授权存储。群组访问、针对单个资源的授权以及自定义角色绑定,都是分配。它们的区别仅在于主体、对象和角色。
账户角色
账户中的每个人都持有一个账户角色:
- 所有者 — 完全控制账户,包括成员和账单。
- 管理员 — 管理项目、成员、群组、角色和令牌。
- 成员 — 只能在自己拥有项目分配的项目中工作。
所有者和管理员在账户中的每个项目上都拥有相当于经理的访问权限。项目分配无法降低此权限。若要限制所有者或管理员对某个项目的访问,请先将其账户角色更改为成员。
相当于经理的访问权限不包括成员的私人会话。账户所有者可以在Settings → Security下启用Admins can open every session,让所有者和管理员访问这些会话。只有所有者可以更改此设置,且每次使用都会记录在审计日志中。请参阅会话访问。
从账户的成员页面通过电子邮件邀请团队成员。邀请是分配给pending主体的一项分配。对方接受后,它会变为user分配。
项目角色
在项目中,一个主体持有以下两个角色之一:
- 成员 — 查看项目、启动和停止项目会话、触发项目触发器。不能编辑或配置。
- 经理 — 拥有所有项目权限:编辑项目、管理触发器、连接器、技能、机密和访问权限、持有网关密钥,以及删除项目。
项目没有第三种角色。
经理拥有完整的项目权限。自定义角色只能添加权限,因此没有任何角色能从经理那里收回某项权限。对象分配是另一种机制,用于缩小权限可触及的对象范围。
可在项目的访问设置中配置项目访问权限,也可使用beeuni access——请参阅CLI。
群组
群组是一种主体,与个人完全相同。在某个范围内为群组分配角色后,该群组的每位成员都会持有该角色。群组会增加访问权限,但不会移除个人已有的访问权限。通过 SCIM 配置的群组与手动创建的群组属于同一种主体类型。
对象分配
分配可以指定项目中的一个对象:agent、skill、secret、app或trigger。目前,Beeuni 会对代理和技能强制执行对象分配。
- 代理默认关闭访问。 只有在分配中指定成员本人、该成员所属的某个群组,或项目中的所有人时,成员才能访问代理。
- 其他所有对象类型默认开放访问。 对象没有分配时,成员即可访问。带有分配的共享连接器账户只能由分配中指定的人员使用——请参阅选择谁可以使用共享账户。
- 项目中的所有人也是一种主体。 在Grant access对话框中,选择Everyone in,然后选择项目名称,即可一次性将代理授予所有成员(
principal_type: "project"、principal_id= 项目 ID)。它只持有对象分配,不持有角色,因此每个人仍保留自己的项目角色。 - 对象分配也会限制项目经理。 只有这样,“将此代理限定给财务组”才有实际意义。经理角色带来的是未指定对象时的默认访问权限,而不是豁免。
- 账户所有者和管理员不受对象分配限制,独立执行自身分配的服务账户也不受限制。
对象分配本身不包含任何权限。它回答的是“哪些对象”,而不是“哪些操作”。
到期时间
为分配设置expires_at后,它会在该时刻停止授予权限。引擎会忽略已过期的分配。记录仍会保留,以供审计。
一套术语,两种绑定
个人、群组或代理通过 Beeuni 以角色的形式获得访问权限,即上述分配。代理还带有第二种独立绑定:其清单在agents.<name>.beeuni_permissions下的beeuni.yaml中声明的 Beeuni 权限。会话只能执行两者都允许的操作;两者不会相互扩大权限。即使代理的清单列出了project.secret.read,只要角色判定拒绝访问,它仍无法读取任何内容;即使由所有者启动代理的会话,只要其清单未列出该操作,代理仍无法读取任何内容。角色属于账户状态;Beeuni 权限则是清单中的存储库状态。请参阅清单参考。
代理会话所适用的角色,是绑定到代理自身服务账户的角色,即其权限上限;如果没有绑定角色,则使用默认代理权限上限。启动会话的人员所持角色不适用。有一项权限project.credentials.issue仅供人类使用,代理永远无法获得。代理只能授予自身持有的权限。管理员可在 Access hub 的Agents下,将代理选为项目角色的主体。请参阅代理权限。
自定义角色
自定义角色是由账户拥有、包含你所选权限的角色。分配自定义角色时只会写入一项分配,其下没有内置基线记录。自定义角色可以在完全没有内置项目角色的情况下授予项目访问权限,这就是部门类角色的实现方式。
自定义角色只能添加权限。Beeuni 没有拒绝规则。
自定义角色需要企业版rbac权益。没有此权益时,分配自定义角色会以code: "entitlement_required"响应402。
超级管理员
超级管理员不是一种角色,而是账户成员身份上的一个标记。它会绕过所有权限检查,每次绕过都会写入审计日志。普通访问使用角色机制;超级管理员则是经过审计的应急通道。
账户创建者最初是所有者和超级管理员。当所有者被降级时,所有者角色和超级管理员标记会一并变更:此操作会清除标记并记录iam.member.super_admin.revoke。如果超级管理员标记授予了非所有者,该标记会一直保留,直到所有者撤销为止。
单点登录域名
SAML 身份提供商会断言每个人的电子邮件地址。对于账户已验证的域名,Beeuni 才会在账户之外信任该地址。验证完成前:
- 通过身份提供商登录的人员仍会加入你的账户并获得其所属群组;
- 其 SSO 身份无法匹配来自其他账户的邀请,其他账户通过“按电子邮件添加成员”也无法找到该身份;
- SSO 登录永远不会将已有身份合并到 SSO 身份中;
- Enforce SSO 不会生效,该域名仍可使用密码登录。
若要验证域名,请打开账户设置中的Identity。SSO 卡片会显示一条 DNS TXT 记录:名称为_beeuni-verification.<your-domain>,值为beeuni-verification=<token>。在 DNS 提供商处发布该记录,然后选择Verify domain(POST /v1/accounts/:accountId/iam/sso/provider/verify-domain)。一个域名只能归属一个账户:已由其他账户验证的域名无法再次验证。更改主域名会开始一项新的、未经验证的声明。
域名验证成功且启用Enforce SSO后,网页登录表单、/v1/access/check-email以及无头/v1/auth/sign-in/password、/v1/auth/sign-in/magic-link和/v1/auth/verify-otp路由都会拒绝该域名的密码和电子邮件验证码登录方式(403 sso_required)。
即使域名已验证,SSO 登录也永远不会将所有者或超级管理员合并到 SSO 身份中。他们会保留原有身份,SSO 身份则作为独立成员加入。
按功能设置访问权限
有些功能会在角色模型之外,额外设置自身的可见性:
| 设置 | 决定内容 |
|---|---|
| 应用访问模式 | 谁可以打开某个已部署的应用 |
| 触发器会话访问 | 谁可以打开某个触发器创建的会话 |
| Slack 频道策略 | 谁可以从某个频道启动会话 |
| 计算机能力 | 已连接的计算机接受哪些文件系统、shell 和桌面调用 |
每项设置都会缩小对单个资源的访问范围。它们都不会授予被角色判定拒绝的权限。
访问 API
| 方法 + 路径 | 功能 |
|---|---|
GET /v1/accounts/{accountId}/iam/assignments |
列出分配。可按主体、范围、对象或角色筛选。 |
POST /v1/accounts/{accountId}/iam/assignments |
创建一项分配。 |
DELETE /v1/accounts/{accountId}/iam/assignments/{assignmentId} |
撤销一项分配。 |
GET /v1/accounts/{accountId}/iam/permissions |
以数据形式提供权限目录。 |
GET /v1/accounts/{accountId}/iam/roles |
列出内置和自定义角色。 |
GET /v1/accounts/{accountId}/iam/roles/{roleId}/permissions |
列出某个角色的权限。 |
权限目录是数据,而不是硬编码列表。每项权限都包含其action、scope_type、resource_type、delegable标记、description、area、level和implies。请读取目录,而不要硬编码操作字符串。
写入路由会根据你所授予的内容选择所需权限:项目角色或对象分配需要project.members.manage,connection分配需要project.connector.connections.manage,账户角色需要member.update,自定义角色需要policy.create。你不能通过选择其他路由绕过权限上限。
品牌
企业版账户可以为所有成员设置应用品牌:横版徽标、方形图标和网站图标,每种都可选配深色模式版本;还可以设置产品名称,以替换浏览器标签标题中的“Beeuni”。打开Account → Branding(/accounts/{accountId}?tab=branding)。上传图片支持 PNG、JPEG、WebP、SVG 和 ICO,大小上限为 1 MB;如果没有徽标,则使用图标;如果没有网站图标,则使用图标;如果没有深色版本,则使用浅色图片。应用内标识会遵循应用主题;网站图标会遵循操作系统的配色方案。
品牌设置跟随账户,而不是浏览器:在项目中,成员看到的是拥有该项目的账户品牌。登录页面、电子邮件和公开分享页面仍显示 Beeuni,因为用户登录前还没有可供设置品牌的账户。企业版权益失效后,成员会重新看到 Beeuni——不会删除任何内容,账户也可以随时移除自己上传的内容。
| 方法 + 路径 | 功能 |
|---|---|
GET /v1/accounts/{accountId}/branding |
返回已存储记录,以及方案是否允许使用品牌设置。 |
PUT /v1/accounts/{accountId}/branding |
设置或清除app_name。需要account.write和branding权益(否则返回402 entitlement_required)。 |
POST /v1/accounts/{accountId}/branding/assets/{kind} |
以 multipart file格式上传一张图片。kind可以是logo、icon、favicon或对应的_dark版本。权限门槛与PUT相同。 |
DELETE /v1/accounts/{accountId}/branding/assets/{kind} |
移除一张图片。仅限account.write。 |
DELETE /v1/accounts/{accountId}/branding |
将所有内容重置为 Beeuni。仅限account.write。 |
GET /v1/accounts会携带每个账户的有效branding——有权益时返回记录,否则返回null——因此客户端只需从已有的一次请求中获取信息即可完成渲染。在 SDK 中:beeuni.accounts.branding.{get, update, uploadAsset, removeAsset, reset}。
切换账户
如果你属于多个账户,可以通过账户切换器在账户之间切换。每个账户都有各自的项目、成员和设置。
已登录设备
Settings → Security → Devices会列出你登录过的所有位置:浏览器、桌面应用和移动应用。
- 在某台设备上选择Sign out会立即结束该设备上的登录状态。该设备无法刷新令牌,令牌不再适用于账户路由,手机也会停止接收推送通知。
- 选择Sign out other devices会结束其他所有设备上的登录状态。这些设备都无法刷新令牌,其手机也会立即停止接收推送通知。
手机重新登录后会再次收到推送通知。
令牌
Beeuni 使用个人访问令牌(beeuni_pat_...)为你登录。该令牌以创建者的身份运行,并且恰好持有该用户的所有分配。服务账户(beeuni_sa_...)是独立主体,不是某个人的凭据;只有通过分配授予权限后,它才会获得项目访问权限。
这两类令牌位于不同页面,因为它们分别属于不同所有者。你自己的 API 密钥位于个人设置中的Settings → API keys(/settings/tokens)——只有你能看到这些密钥,且你的成员身份失效时,密钥也会停止工作。服务账户令牌属于账户配置,位于Account → Tokens,与管理令牌到期时间的密钥规则放在一起。
完整的令牌模型请参阅 SDK 身份验证。
审计日志
审计日志会记录所有到达 API 的请求,无论请求是否表明了调用者身份。服务器会为每个 HTTP 请求、WebSocket 升级、预览请求、Git 传输和 SCIM 调用写入一条记录。日志覆盖范围不受路由影响。
每条记录都会注明请求所证明的调用者:
actor_type |
调用者 |
|---|---|
human |
已登录的个人用户,或该用户的令牌(source: api_key)。 |
agent |
会话的代理凭据。记录还会注明代理代表其执行操作的人类用户。 |
service_account |
服务账户令牌。 |
system |
账户 API 密钥、SCIM 目录令牌、使用已验证签名的集成 webhook,或 Beeuni 后台任务(source: worker)。 |
anonymous |
没有凭据的请求,或带有无效、伪造凭据的请求。 |
每条记录还会在credential_kind和credential_id中记录 API 验证过的凭据。ID 标识凭据,而不是密钥本身。Web 应用会将其显示为Via,并在存在令牌或应用名称时一并显示。
credential_kind |
凭据 | credential_id |
|---|---|---|
browser_session |
Beeuni 登录会话(Web 应用,或持有登录 JWT 的客户端)。 | 登录会话 ID。 |
personal_access_token |
个人访问令牌,例如 CLI 的令牌。 | 令牌 ID。 |
oauth_app |
已连接应用的 beeuni_oat_ 令牌,例如 MCP 客户端。 |
OAuth 客户端 ID。 |
session_token |
Agent 会话自己的令牌。 | 会话 ID。 |
api_key |
账户 API 密钥。 | 密钥 ID。 |
service_account |
服务账户令牌。 | 服务账户 ID。 |
scim_token |
SCIM 目录令牌。 | 令牌 ID。 |
API 从不读取 X-Beeuni-Client。CLI、MCP 服务器和 Web 应用都调用同一个 API,而任何客户端都能发送任意标头值,因此日志只记录 API 能够验证的信息。2026-09-30 之前写入的记录可能包含自报的 client_reported_source。新记录会将其留空。使用 ?credential_kind=oauth_app 在 GET /v1/accounts/:accountId/audit 上按凭据筛选,或使用 beeuni audit ls --credential-kind oauth_app。
2026-10 之前写入的记录包含 session_sequence、integrity_previous_hash 和 integrity_hash:每会话计数器和哈希链。新记录会将这三项全部留空,这些字段也已弃用。哈希链从未经过验证,而维护它会导致同一会话的所有写入操作串行执行。会话日志按创建时间排序:带有 session_sequence 的记录排在前面,并按该字段排序;之后是 API 创建的新记录,按创建顺序排列。
被拒绝的请求会生成一条带有 outcome: denied 的记录。metadata.auth 记录调用方的身份验证方式:只记录令牌 ID,不记录密钥。Git 克隆对应操作 git.clone。推送对应 git.push,而 metadata.refs 列出其创建、更新或删除的每个 ref。
保留期限
| 事件时长 | 存储位置 | 读取方式 |
|---|---|---|
| 0 至 90 天 | PostgreSQL,每周一个分区 | Web 应用中的审计日志、GET /v1/accounts/:accountId/audit、beeuni audit ls、审计 Webhook 和导出 |
| 90 至 365 天 | 启用了对象锁定(合规模式)的 S3 存档 | 仅支持导出:GET /v1/accounts/:accountId/audit/export 或 beeuni audit export |
| 超过 365 天 | 已删除 | 不可用 |
每周从周一 00 UTC 到下周一 00 UTC。某周最后一刻满 90 天后,该周的数据就会移入存档,因此事件发生 90 至 97 天后会变为仅可导出。存档会保留事件,直到该周结束后 365 天,因此事件总共保留 365 至 372 天;在此之前,保留锁意味着包括 Beeuni 员工在内的任何人都无法缩短保留期限或删除事件。隐私政策也规定了相同的上限:应用日志最多保留 365 天。
导出会将存档和 PostgreSQL 中的数据合并为一个列表,按时间从旧到新排列,并使用相同的筛选条件、字段和 X-Audit-Next-Cursor 分页方式。两种读取方式都需要 auditAccess 权限。存档事件包含与实时事件相同的字段;2026-10 之后写入的事件中,session_sequence 和完整性哈希为空(见上文)。
操作
每条记录都有一个名为 domain.resource.verb 的 action,以及 Web 应用和 beeuni audit ls 显示的标题:
| 操作 | 标题 | 写入方 |
|---|---|---|
gateway.key.revoke |
已撤销 LLM 网关密钥 | 对 DELETE /v1/projects/:projectId/gateway/keys/:keyId 的请求。 |
iam.group.create |
已创建群组 | 创建群组的请求。记录在 after 中包含新群组。 |
secret.consumer.used |
已使用密钥 | 读取了密钥的沙盒。 |
api.rate_limit.exceeded |
达到 API 速率限制 | 拒绝请求的限流器。metadata.limiter 标明了限流器。 |
每个 API 路由恰好对应一个操作。请求记录会在 metadata.http 中保留路由模板,而不会记录可能包含令牌的原始路径。当处理程序为请求记录自己的事件,并包含前后状态时,该事件就是请求唯一的记录。未匹配任何路由的请求对应 api.route.unmatched。
按操作前缀筛选:在 GET /v1/accounts/:accountId/audit 上使用 ?action=iam.、beeuni audit ls --action iam.,或使用审计 Webhook 的 --action-prefix。审计日志操作 列出了所有操作及其标题。2026-09-24 之前写入的记录会将 METHOD /template 作为操作,并显示相同的标题。
Beeuni 后台作业无需请求即可执行操作:它们会使授权和隧道权限过期、删除过期的会话分支、激活 App 部署,以及在沙盒提供商之间迁移项目。此类记录带有 source: worker,而 metadata.auth.worker 会标明作业名称,例如 tunnel-cleanup 或 app-deployments。App 部署记录还会将发起部署的成员标为发起者。
匿名请求如果指向你的某个项目,也会写入你的日志。使用 actor_type=anonymous 选择这些记录。每个 API 进程都会对匿名记录限流,因此大量此类记录不会挤占可识别来源的记录。健康探测、CORS 预检请求以及发往已部署 App 的匿名流量不会被记录。
计费
免费版包含 1 个项目和 $20 首次赠送额度,领取后 30 天有效。下一周期起每月赠送 $2,当期有效、不累积。额度可用于电脑运行和官方模型。
首次赠送每个个人账户仅领取一次。之前领过 $2 首次额度的用户补发 $18;未领过的用户获得 $20。创建其他团队或项目不会重复领取。充值额度独立保存,不会因赠送额度到期或月度重置而清空。
计费按账户进行,涵盖账户中的所有项目。Beeuni 提供免费版、专业版和按席位计费的团队版,每个版本都有各自的模型访问权限和额度。使用自己的模型密钥并不意味着使用免费:除免费版外,Beeuni 仍会在其基础上收取平台费用。