export interface PlatformBinding { /** 平台对外地址 */ platformUrl: string; /** 本机稳定标识(重绑保持不变) */ machineId: string; /** 隧道凭证(自包含签名,平台验签) */ machineToken: string; /** 机器展示名(默认机器名) */ name?: string; /** 本机所属的平台团队(成员关系下沉到部署本地,平台零存储靠各机上报重组) */ teams?: PlatformTeam[]; /** @deprecated 遗留字段:仅为兼容旧 platform.json 而保留解析,运行期已不再读取。 * 隧道与所有平台连接现在都不传 family,交给 Node happy-eyeballs 自动选族; * bind 也不再把兜底成功的协议族落盘。 */ ipFamily?: 4 | 6; } export interface PlatformTeam { teamId: string; teamName: string; } export declare const PLATFORM_BINDING_PATH: string; export declare function readPlatformBinding(): PlatformBinding | null; export declare function writePlatformBinding(b: PlatformBinding): void; /** * 解绑:删除本地平台绑定文件(~/.botmux/platform.json)。 * 平台侧 owner 点了「解绑」并吊销了 machine token 后,daemon 收到 unbound 消息时调用, * 把本地凭证清干净——下次 `botmux bind` 重新写入即可重新绑定。文件不存在视为已清理。 */ export declare function clearPlatformBinding(): void; /** * 绑定平台后,本机对外可达的「机器子域」基址 `https://m-.<平台域名>`, * 平台会把该子域经隧道反代回本机 dashboard。域名从 binding.platformUrl 运行时推导 * (公开仓库不写死平台域名);前缀 `m-` 是平台约定。未绑定返回 null。 */ export declare function platformMachineBaseUrl(): string | null; /** * 平台面向浏览器的、本机可信子域 authority 列表(`host` 形式,不含 scheme)。 * * 中心平台把本机放在 `<前缀>-.<平台域名>` 子域下,再经隧道反代回本机 * dashboard——反代时把 `Host` 改写成回环上游、且**不带 `X-Forwarded-Host`**,于是 * 浏览器发的管理类 WS/请求携带的 `Origin: https://<前缀>-.<平台域名>` * 在 dashboard 的同源校验里找不到匹配的候选 authority(见 dashboard/control-csrf.ts * 的 `requestAuthorities`),被判跨站拒掉——平台浏览器终端 disconnected。 * * 这里由本机 `platform.json`(0600 host-authority,machineId 平台签发、跨站页面 * **伪造不进**)派生出**精确前缀**的可信 authority,交给 `requestAuthorities` 并入 * 候选。为什么**枚举** `m-`/`t-` 精确前缀而非通配 `<任意前缀>-`: * • 安全门须 fail-closed。枚举只依赖「这 2 个前缀反代到本机」这条弱不变量;通配 * `*-` 依赖「**任何**前缀标签都不会落到攻击者可控源」——强得多、且 * 本进程无从验证(平台路由表不在部署机上)。 * • 失败方向相反:枚举漏一个前缀 = 那种终端连不上(响、加一行前缀即修);通配一旦 * 平台某天把某 `