开发

组织、团队与文件夹权限

把一家工作室的人、团队和空间放在一起:按团队给空间授权,限制谁能改某个文件夹,用公司的身份提供方登录,导出审计记录。

查看 Markdown

组织(organization)装着一家公司的人和它的团队。一个空间可以属于一个组织,之后组织的团队就能在空间里有角色:有人加入剪辑组,就一次性拿到剪辑组在所有项目里的权限,离开时也一起收回。不属于组织的空间和以前完全一样。

组织角色能做什么
owner(所有者)管理员能做的都能做,另外能任命所有者、设置单点登录。最后一个所有者不能离开。
admin(管理员)加人、移人、建团队,把自己管理的空间放进组织,导出审计记录。
member(成员)查看组织的成员、团队和自己所在的空间。

成员和团队

sidespace org create "Harbor Pictures"
sidespace org members "Harbor Pictures" --add [email protected] --role admin
sidespace team create "Harbor Pictures" 剪辑组
sidespace team add "Harbor Pictures" 剪辑组 [email protected] [email protected]
sidespace org attach "Film A" "Harbor Pictures"     # 你管理 Film A,并且是组织管理员
sidespace team grant "Film A" 剪辑组 editor

把人加进团队时,如果他还不在组织里,会以成员身份加入。新建组织只能由人来做(令牌需要 admin 权限范围);给团队空间角色要空间管理员(令牌需要 members:manage)。

成员在空间里的角色

一个人在空间里的角色,取他自己的授权和他所在团队在这个空间的角色中最高的那个。GET /v1/spaces/{sid}/members 三样都给出:

JSON
{ "user": { "email": "[email protected]" }, "role": "editor", "direct_role": "viewer",
  "teams": [{ "id": "team_…", "name": "剪辑组", "role": "editor" }] }

只通过团队进入空间的人,direct_role 是 null。加入或离开团队,角色立刻跟着变。如果某人还通过团队有权限,从空间移除他会被拒绝(409,并说明是哪个团队),因为“移除”就该是真的不在了:先把他移出团队,或取消团队的角色。

文件夹权限

文件夹可以有规则,限制或放宽在里面能改什么。规则从不限制能看到什么。

  • default_role:没有单独授权的人在里面最多能做什么(viewer、commenter 或 editor;null 表示按各自在空间里的角色)。
  • grants:给空间成员(按邮箱)或组织的团队(按名字)单独的角色,可以高于他们在空间里的角色。比如让查看者能往某个交付文件夹上传。
  • 离得最近的、有规则的文件夹说了算。上下层的规则不叠加,所以一个文件夹的规则在一个地方就能看清。
  • 空间管理员不受限制,没人能把空间所有者锁在外面。
# 剪辑室能看 /final,只有交付组能改
sidespace access "Film A" /final --default viewer --grant team:交付组=editor
sidespace access "Film A" /final          # 你在那里是什么角色,由哪个文件夹决定
sidespace access "Film A" --list          # 所有有规则的文件夹
sidespace access "Film A" /final --clear

每次写入都按所在位置检查角色:新建(看父文件夹)、保存新版本、改名和移动(看原位置和新的父文件夹)、删除、恢复、附加信息、预览文件、评论(评论者)、分享链接和 AI 运行。被拒绝的写入返回 403,消息里写明这个文件夹需要什么角色。GET /v1/spaces/{sid}/nodes/{nid}/access 返回你在那里的 role、你的 space_role 和决定它的规则(governed_by),应用可以在别人动手之前就说清楚;网页版会在这种文件夹上显示“这里你是查看者”,并收起你做不了的操作。

单点登录

组织可以通过 OpenID Connect 让成员用公司的身份提供方登录:Okta、Microsoft Entra ID、Google Workspace、Keycloak、Authing,以及任何提供 /.well-known/openid-configuration 的服务。所有者设置,管理员可以查看。

  1. 在身份提供方登记回调地址。GET /v1/orgs/{oid}/sso 会给出它;还没设置单点登录时,它返回的 404 里也写着。
  2. 为每个邮箱域名添加 DNS TXT 记录 _sidespace.<域名>,值是同一个调用给出的 domain_proof(sidespace-verify=…),证明域名是你们的。否则谁都能声称 gmail.com。
  3. 为这些域名接入身份提供方:
sidespace org sso "Harbor Pictures" --issuer https://harbor.okta.com --client-id 0oa… \
  --client-secret - --domain harbor.example --required < secret.txt
sidespace org sso "Harbor Pictures"          # 查看(不会显示密钥)
sidespace org sso "Harbor Pictures" --off

没有 TXT 记录的域名会被拒绝(422,code 为 domain_unproven)。Client secret 用服务器的密钥封存,从不返回;之后再 PUT 时不传它就保持不变。开启 required 后,这些域名不能再用邮箱验证码登录。通过单点登录进来的人会以成员身份加入组织。

在应用里登录

应用不接触身份提供方的令牌。用对方的邮箱开始登录,在浏览器里打开返回的 url,再用 handle 轮询,直到有结果:

Shell
curl -X POST https://side.example.com/v1/auth/sso/start -H "Content-Type: application/json" \
  -d '{"email": "[email protected]", "device_name": "Ben 的笔记本"}'
# → {"url": "https://harbor.okta.com/…", "handle": "sso_…", "expires_at": "…"}
curl -X POST https://side.example.com/v1/auth/sso/poll -H "Content-Type: application/json" -d '{"handle": "sso_…"}'
# 等待中返回 202;成功返回 200,令牌和邮箱登录的一样;过期或已取走返回 410

没有组织为这个域名设置单点登录时,start 返回 404。POST /v1/auth/email/start(或 verify)返回 403、code 为 sso_required 时,就改走这个流程。sidespace login EMAIL --sso 和网页版的登录页都是这样做的。

审计导出

管理员可以导出组织里发生过的事,按时间从早到晚。令牌需要 admin 权限范围。

sidespace org audit "Harbor Pictures" --since 2026-10-01 --format csv -o audit.csv

每条记录有 at、source、kind、actor_id、actor_email,适用时还有 actor_kind(人、AI agent 或插件)、via(令牌或 AI 动作)、space_id、space_name、target、path 和 detail。记录来自两处:

  • org:组织的变化(成员、团队、空间角色、文件夹规则、单点登录设置)和每一次单点登录。
  • space:组织里各个空间的每次文件改动,取自空间的变更日志,带着当时的文件名。空间放进组织时,它之前的历史也一起带进来。

since 和 until 接受 RFC 3339 时间或日期,默认是最近 30 天。一次最多返回 20 万条;更多时从最后一条的时间开始再导出。网页版里,管理员在组织的审计导出页下载。