跳转至

环境认证

环境颁发自己的会话并强制执行其能力。云身份与中继凭据属于单独的信任边界,详见 T3 Connect。中继令牌绝不是环境登录。

权限在传输变更后依然有效

配对会委托一组范围。交换引导凭据可以缩小该授权,但不能扩大它。默认授权包括访问和中继管理:terminal:operate 是以服务器用户身份运行的 shell,orchestration:operate 可以启动完全访问的代理,并且任一权限都可以通过 t3 auth session issue 铸造一个具有所有范围的会话,因此从默认授权中扣留管理权并不能构成边界。范围较窄的客户端会获得明确的权限范围。创建另一个配对链接需要同时具备 access:write 和被委托的每个范围。认证处理程序 在颁发时强制执行这一点;客户端标签和设备元数据没有授权角色。

访问读取模型包含配对元数据,绝不包含可恢复的配对机密。只有创建响应会返回原始凭据。否则,对连接列表的读取访问将成为获取另一个客户端权限的途径。

浏览器 Cookie、Bearer 令牌和 DPoP 令牌适配了相同的范围会话模型。DPoP 将令牌绑定到客户端的证明密钥;无效证明必须失败,而不是回退到 Bearer 认证。OAuth 令牌交换词汇表为这些授权赋予了熟悉的含义。

访客链接 给予一个浏览器对单个线程的读取访问权限,并提供一种提议消息的方式。其令牌是线程和共享 ID 在服务器密钥下的 HMAC(GuestShareService),因此不会存储任何机密。线程投影中的共享是唯一状态:替换、关闭或归档它会撤销所有令牌,而编排器的串行命令使兑换和发送只发生一次。Guest 令牌永远不会进入 SessionStore,因此任何 RPC、WebSocket 或 MCP 路径都无法接受它。Guest 路由还要求 T3 Connect 仍然服务于链接的主机名;请求的 Host 头不会被检查,因为 LAN 客户端可以伪造它。

MCP 客户端是另一类受众

并非由 T3 Code 启动的代理通过一个窄范围 OAuth 授权码服务器登录 /mcp(McpOAuth)。它接受用户机器上代理的回环重定向 URI,以及托管代理(ChatGPT、机器人)的任何 HTTPS 重定向。HTTPS 重定向意味着别人发送给所有者的链接可以将访问权传递给那个人,因此审批页面会指明访问指向的主机,而是否批准仍由所有者决定。每个客户端都是公开的,并通过 PKCE 证明自身;请求机密的客户端也会在未注册机密的情况下完成注册。客户端注册是无状态的,因此未经认证的调用者无法增加服务器状态。审批会消耗一次性配对码,或使用具有 access:write 的浏览器会话;绑定证明的 T3 Connect 代码会被拒绝,且不会被消耗。

用户授予的是只读访问权或运行时模式上限,而不是范围列表:MCP 工具全部属于编排范畴,而单独的 orchestration:operate 会让代理以完全访问模式启动线程并借此行事。结果是一个主题为 mcp-client 的普通会话。只读授权仅持有 orchestration:read。在 /mcp 上,它只传递在 McpToolAccess 中声明为读取的工具,而每个工具都必须声明谁可以调用它才能编译。任何其他授权都会添加 orchestration:operate 和一个带签名的上限。只有 /mcp 接受这些会话。所有其他 HTTP 和 WebSocket 路径都会拒绝该主题,因为 RPC 接口会让代理超出其上限行事。在 MCP 内部,凭据设定限制,工具参数只选择目标;参见 threadAccess。

颁发者和资源 URL 来自请求的 Host 和 X-Forwarded-Proto,因此一个服务器可以同时响应回环、Tailscale Serve 和 T3 Connect 隧道。重写 Host 或丢弃协议头的代理会破坏登录。

Bearer 和 DPoP 客户端通过经过认证的 HTTP 获取短期 WebSocket 票据,从而使长期令牌不进入 socket URL。票据指定其打开的路由:RPC socket,或媒体路由(设备中心、预览流),后者在 <img>、EventSource 和多个 socket 之间共享一张票据。DPoP 客户端的 RPC 票据绑定到其证明密钥,升级时在 dpop 查询参数中携带新的证明,因为 WebSocket 无法设置请求头;在普通 HTTP LAN 路由上捕获的票据如果没有密钥则毫无用处,证明的 jti 也与其他任何证明一样被消耗。媒体票据保持 Bearer 形式,因为每个媒体请求都需要自己的证明。早于这一机制的客户端会铸造未绑定票据,这些票据可打开任一路由。浏览器会话可以使用其 Cookie 对升级进行认证。成功的握手不会授予额外权限:每个 RPC 都声明所需范围,WebSocket RPC 组的 RpcScopeAuthorization 中间件会在任何处理程序运行之前检查该范围。

范围变更不能阻止旧客户端连接。令牌交换会将已识别请求与配对授权取交集;已停用和未知的名称会被丢弃。没有授权范围的请求会在消耗链接之前失败。存储的凭据在范围拆分时绝不会被扩展。

认证响应将 scopes 保持在原始线上词汇表内,并包含针对确切授权的 permissions。新客户端在 permissions 存在时使用它,即使为空。旧服务器会省略该字段,因此客户端对这些服务器已支持的功能使用旧的父级检查。这些客户端检查绝不会改变服务器授权。权限错误同样保留旧的 requiredScope,并添加确切的 requiredPermission,因此被拒绝的 RPC 仍可被旧客户端解码。未知的响应权限会被忽略;授权输入保持严格。

桌面端重启后会忘记之前的本地 bearer token,因此其可复用的引导授权会替换同一主体和方法的早期会话。撤销和插入共享同一个数据库事务;替换失败时必须保持旧凭据仍可用。配对和浏览器会话不遵循此替换规则。

可复用的开发凭据

Web 开发环境可在同一主机名上跨工作树和端口接受一个 T3CODE_DEV_AUTH_TOKEN。该 token 及包含它的启动 URL 授予管理访问权限。桌面端和非开发服务器会忽略它。配置方式参见开发运行手册。

每个环境都会对该值进行哈希处理,并在启动时写入自己的数据库记录。各环境之间不共享 SQLite 数据、签名密钥、环境 ID、会话记录、配对授权或撤销状态。本地撤销在重启后仍然有效,且不会影响其他工作树。删除或轮换该值并重启后,旧凭据及其 WebSocket 票据将失效。

常规凭据保持优先。被拒绝的常规凭据绝不会回退到可复用凭据。OAuth 交换会创建普通的本地 bearer 或 DPoP 子凭据,并具有正常的过期和撤销机制。可复用 cookie 在 30 天后过期。

环境是文件系统边界

项目是组织边界,而不是文件系统沙箱。filesystem:read 允许读取服务器帐户可读取的文件,包括项目之外绝对路径下的文件。这使客户端能够显示代理在临时目录中写入的产物。相对路径和写入操作仍遵循工作区路径规则。

签名资产 URL 是 bearer 凭据。主机上媒体的 URL 授予对单个规范文件及其设备/inode 标识的访问权限,而不是对其所在目录的访问权限。Asset access 在提供文件时会重新检查已打开文件的标识,因此原子替换需要新的 URL,而就地编辑同一文件则不需要。以此方式获得授权的 HTML 文件无法加载同级资源;目录级工作区预览是一种单独的授权。客户端应共享所编写文件的引用,以免泄露临时 URL 的凭据。filesystem:read 在 URL 生成时检查,而不是在提供时检查:在授权被撤销之前发出的 URL 会一直有效到过期,并且它不绑定于生成它的会话。

主机视频可以在原位更改。它们的 HTTP 响应 省略了缓存验证器,因为文件元数据无法为 If-Range 证明逐字节一致性。添加弱验证器会把原生播放器的进度跳转变成为完整下载。

本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 t3/t3code