LinkCattle

开发者指南

已有 HTTP、SSE、WebSocket 服务可以保留业务路径和数据格式。LinkCattle 增加带认证的入口,客户端应用可选。各仓库通过 python3 scripts/release.py 统一构建、签名并验收本地制品。

仓库边界

linkcattle-gateway 负责平台和官网,linkcattle-sdk 负责版本化契约与库,linkcattle-client 负责 CLI、Android、iOS 与电脑执行。linkcattle-app 负责业务应用,linkcattle-skills 负责精选 Skill,linkcattle-plugins 负责 Agent Plugin 包与市场制品。各仓库仅基于固定依赖构建自己的生成物。

接入 API

让服务监听固定 loopback HTTP 地址,编写路由文件:

{
  "business_api": {"id": "example.notes.api", "version": "1.0.0"},
  "routes": [
    {"methods": ["GET"], "path": "/notes/**", "requires": ["notes.read"]},
    {"methods": ["POST"], "path": "/notes", "requires": ["notes.write"]},
    {"methods": ["GET"], "path": "/events", "requires": ["notes.read"]},
    {"methods": ["GET"], "path": "/ws", "requires": ["notes.read"], "websocket": true}
  ]
}
linkcattle connect api 127.0.0.1:8080 --routes /absolute/notes-routes.json
linkcattle list
linkcattle access INSTANCE_ID --capabilities notes.read --output /absolute/private/access.json

导出的 600 权限文件含短期 endpoint 和 access_token。客户端在 endpoint 后追加原路径,使用 Relay-Authorization: Bearer <access_token>。该头在转发前移除,原业务 Authorization 保留。文件放在源码和构建目录之外,不打印内容。

路由默认精确匹配,只有显式尾部 /** 允许子路径。未知路由、歧义路径和缺失能力均拒绝。调用者不能指定任意上游。资源和字段级鉴权继续由业务服务执行,SDK 不提供后端沙箱。

底层 rg-connector CONFIG.json 支持自定义应用身份与 proxy 路由,配置见 linkcattle-sdk/crates/gateway-sdk/src/bin/rg-connector.rs。trusted_gateway: true 表示接受平台终止 TLS;TLS 透传改用受保护的 endpoint_config,包含主机名、证书路径和私钥路径。两种模式都保持证书校验。

流与失败处理

浏览器凭据绑定精确允许的来源。SSE 使用 fetch 流,因为浏览器 EventSource 不能添加所需认证头。原生 WebSocket 可直接携带该头;浏览器先向 POST /__linkcattle/ws-tickets 发送 {"path":"/ws"},再以 ?__relay_ticket=... 连接该确切路径。票据有效 30 秒且只能用一次,长期访问令牌不得进入 URL。

写入转发后断线可能返回 409 outcome_unknown。应查询业务结果或使用业务幂等键,不自动重试写操作或收费模型任务。流重连不表示原操作已取消或可以重放。

构建应用

宿主 API 1.5 为兼容范围排除 API 1.4 的应用提供异步上下文:已校验的本地页面可先于实时授权和直连探测显示。待授权的 #relay-context 含 authorization_pending: true,不含 API 凭据;前端通过携带 X-LinkCattle-Runtime 的 GET /__linkcattle/context 等待完整上下文后才发业务请求。实时市场资格、授权、路由和有效期校验仍然执行;兼容旧宿主的应用保留同步上下文。 本地快速打开也必须匹配所选实例编号、应用类型及缓存的业务 API 契约;元数据缺失或不兼容时,先按正常流程选择兼容版本,再打开页面。

应用位于独立 linkcattle-app 仓库。包包含 manifest.json、本地 Web 资源、来源和许可证声明。清单声明应用类型、业务与宿主 API 兼容范围、路由、必需/可选能力、存储版本和安全修订号。版本范围采用 Rust SemVer 语法,例如 >=1.0.0, <2.0.0。

宿主在受限 Web 容器加载已校验的本地资源。禁止外部脚本、Worker、Service Worker、任意原生程序和安装脚本。存储按平台、账号、实例、应用、schema 版本隔离。宿主未实现的必需原生权限会被拒绝。各操作系统须单独声明和验证,签名不代表运行兼容。

公开外部依赖在当前客户端调用,不经所连接的电脑。宿主 API 1.7 的应用可声明 external_network: "allowlist"、external_origins: ["https://api.github.com"],并要求宿主至少 1.7。来源必须是精确的公网 HTTPS 来源,不含端口、路径、凭据、通配符或私网主机。宿主仅把这些来源加入 CSP connect-src 和原生资源白名单;导航和外部代码限制保留,来源变化后重新确认。#relay-context.external_http 在等待电脑授权时也提供客户端本地端点及允许来源。不支持 CORS 的 API 可 GET 此端点,以 url 和可选 timeout_ms(250–12000)为参数,仅携带本地 X-LinkCattle-Runtime 证明。JSON 回执保留上游 status 和原始 UTF-8 body,传输错误另列 transport_error;正文最多 1MiB、并发最多六个读取、拒绝重定向,不转发应用、账号或 Cookie 凭据。电脑安装和执行仍使用既有授权路由。

宿主 API 1.4.0 新增 summary.share 和 file.download。声明其中任一权限(包括可选权限)的应用须设置 host_api_range: ">=1.4.0, <2.0.0",因为旧宿主会拒绝未知权限名称。目录选择会保留较早的兼容版本,不强制使用最新版应用。不使用这些新权限的既有 WebSocket 应用仍可保留 1.3.0 下限。

file.download 仅在完整文件保存成功且未覆盖既有下载后返回成功。当前 App 提供短暂完成提示及本账号下载列表入口;宿主读取自己的保存结果,不接受应用自报成功。打开下载列表和下载文件是两个独立操作。没有宿主保存能力的普通浏览器应提示已交给浏览器下载,不冒称文件进入 LinkCattle 列表。通过能力协商调用界面操作不会增加文件路由授权,也不会暴露账号凭据。

Flutter Web 使用 --csp --no-web-resources-cdn --no-source-maps,渲染器与字体本地化。不通过开放任意 CDN 或 unsafe-eval 修复构建。新增清单字段前阅读linkcattle-sdk/crates/gateway-market/src/lib.rs和 linkcattle-app 的现有清单。

声明 external.open 的应用可通过 postMessage({type: 'relay-host-open-link', request_id, url, external: true}, '*') 请求在系统浏览器授权。宿主检查 HTTPS、当前市场资格,并单独请求用户确认;不会向系统浏览器注入应用上下文。

电脑组件由受信任 App 在 Web 容器之外编排拥有者确认的通用执行计划。install_web_pinned 的 package_receipt: true 仅返回已校验包的公开路径、manifest、摘要与当前用户/电脑标识,不返回账号凭据。客户端固定用户核对的版本,结果未知时查询原操作ID;安装包本身不执行组件代码、不授予执行权。

发布

已登录 App 通过短期、仅市场权限的会话打开开发者控制台。登记发布者与应用类型,创建不可变签名版本,上传文件,提交独立审核后发布。市场会话不授予业务实例使用权;尚未实现付费分发。

python3 scripts/release.py --product all --plan
python3 scripts/release.py --product all --signing-config /absolute/private/app-signing.json --market-bin /absolute/tools/rg-market

打包生成软件包及签名 .release.json。私钥放在受保护存储中。内容变化必须新建版本,同一应用 ID/版本不可替换为不同字节。审核员不能审核自己的发布者或包。私有渠道成员权与服务授权分开。

发布是异步操作:签名进程上传并核验包和 TUF 对象后,publishing 才变为 published。宿主验证固定市场根、TUF 期限/版本/摘要及发布者签名。撤回阻止新的运行租约,不能擦除已经下载的代码。

TUF 根私钥离线保管,在线角色私钥只供独立签名进程使用。rg-market rotate-prepare / rotate-apply 用于双签根轮换;publisher-rotation 用于正常发布者换钥;publisher-recovery / publisher-recovery-sql 要求原拥有者、独立审核员和新钥证明。参数见linkcattle-sdk/crates/gateway-market/src/main.rs,不得用重新初始化已有信任根代替恢复。

Agent Plugins

Agent Plugin 与业务应用独立。linkcattle-plugins 维护标准根目录 plugin.json、可选的 mcp.json 和 skills/,以及 .agents/plugins/marketplace.json。平台托管构建好的市场制品,不编译插件源码;LinkCattle Client 在所选电脑安装和执行已授权的包。手机通过系统浏览器发起人工 OAuth,具体授权方式和回调由电脑侧插件宿主管理,服务商凭据留在该电脑。服务商注册及真实账号验收与离线包检查分别完成。

运行平台

配置示例见 linkcattle-gateway/config/,部署模板见 linkcattle-gateway/deploy/。准备独立 MySQL、Redis、S3 兼容存储、持久公共市场元数据、受保护平台身份和独立市场签名进程。市场对象保持私有,与公开应用下载分开。升级沿用既有身份,应用模板前先核对自身基础设施。

已验证的本地界面可在当前应用资格与实例授权核对期间先显示。此时尚未授予特权运行租约:私有存储、宿主操作、点对点传输和业务请求仍须等待线上资格核对成功;API 凭据还须通过实时授权、路由和用户已确认的传输信任检查。缓存服务元数据仅用于选择界面版本,不是授权。发布性能验收必须覆盖完整宿主调用与页面可见、可编辑的时点,并为资格及授权请求注入延迟,不能只测内部渲染构造函数。