/** * [ref] A10 分段 —— **device lane 的装配件**(device-executor-lane-v2 §4.6/§4.7/§5,车A-4)。 * * 一处建齐三件活对象:**店**(四表双库的 `DeviceStore`)→ **准入链**(`DeviceEnrollment`,含跨副本 * 限速座)→ **WS 汇聚端**(`DeviceWsHub`)。三件的依赖是单向的(hub 吃 store+enrollment),所以它们 * 必须在同一处按序建 —— 拆到三处装配点会让「hub 拿到的是不是同一只店」变成一个要读三个文件才答得出 * 的问题(而答错的后果是 presence 与租约各写各的)。 * * ⚠️ **位置即契约**:必须在 `openStores`(拿 backend)之后、`createExecutionEnv`(第七臂要这三件)之前 * 调用;`attach(server)` 则要等 `createHttpServer` 造出裸 `http.Server` 之后(main.ts 的顺序)。 * * 🔴 本模块**不**做车道选择:`REMOTE_EXEC=device` 与否由调用方判(main.ts)。它只回答一件事 —— * 「这台机器上,device lane 的三件装配得起来吗」。装不起来就返回 `undefined`,由 * {@link assertDeviceLaneWired} 响亮拒启([ref]:执行车道上没有静默降级臂)。 */ import { type DeviceEnrollment } from "../device-enrollment.js"; import type { DeviceStore } from "../device-store.js"; import { type DeviceWsHub } from "../device-ws-hub.js"; import type { ServiceConfig } from "../config.js"; import type { Logger } from "../observability/logger.js"; import type { Metrics } from "../observability/metrics.js"; import type { StoreBackend } from "../plugins/store-backend.js"; export interface DeviceLaneCtx { config: ServiceConfig; logger: Logger; metrics: Metrics; backend: StoreBackend | undefined; /** 本副本 id(写进连接租约行 —— §4.6 的跨副本排障面)。 */ replicaId: string; } export interface DeviceLane { store: DeviceStore; enrollment: DeviceEnrollment; hub: DeviceWsHub; } /** * 注册口(`POST /v1/devices/enroll`,pre-auth)的限速策略 —— **本车道自己的地板,不挂任何运维旋钮**。 * * 🔴 此前这里把全局 RateGate 适配成注册限速器,于是限额**值**也跟着全局 `RATE_LIMIT_RPM` 走;而它缺省是 0, * 0 在那只限速器里是「关断哨兵」⇒ 缺省部署上注册口**完全不限速**(实测同一窗 200 次尝试拒绝 0 次), * 设计 §7-T5 ⑤ 对 enroll token 撞库的那道防线在出厂形上不存在。安全地板挂在一根语义无关的运维旋钮上, * 是「部署级旋钮禁挂派生腿」那条教训的又一形。⇒ 注册限速恒用本策略的固定窗,与 `RATE_LIMIT_RPM` 无关。 * * 诚实边界:窗是**每副本**的。device 车道的部署形是单副本(`docs/DEPLOY-PREREQS.md`),滚动期两个进程 * 短暂重叠时上界 = 限额 × 重叠副本数;不声称跨副本全局上界。 */ export declare const DEVICE_ENROLL_RATE_POLICY: { readonly limit: 10; readonly windowMs: 60000; }; /** * 建齐 device lane 的三件。返回 `undefined` = **建不起来**(没有 SQL 后端 ⇒ 没有四表店)。 * * 只在调用方判定本部署是 device 车道时调用;非 device 车道调用它是纯浪费(会白建一只 WS server)。 */ export declare function createDeviceLane(ctx: DeviceLaneCtx): DeviceLane | undefined; /** * **装配后**的拒启门(car A-1 的 `device-executor-unwired` 换来的真门;先例逐字 = * `boot/leader.ts` 的 `assertLeaderDurableStore`)。 * * config 层的门①判的是「运维配没配 SQL 坐标」——那句话回答的是**意图**。它回答不了「这次启动**真的 * 拿到**了店吗」:`openStoreBackendWithFallback` 在 `SESSION_BACKEND=auto`(默认)下,SQL 连不上 / * 建表失败 ⇒ `backend=undefined` + 一条 warn 就继续启动。那次启动里 device lane 的四表整个不在, * 而 `boot/execution-env.ts` 的第七臂拿不到三件 ⇒ `executionEnvFactory` 落 `undefined` ⇒ core 拿 * `StubExecutionEnv`:**一台自称在员工设备上执行的 worker 实际在自己进程里跑,而且回执同形**。 * 那正是 [ref]「执行车道禁静默降级」点名的样板病,也正是 A-1 那条临时门当初要拦的东西 —— 换执法点, * 不是取消执法。 * * 抛而不是 warn:降级的代价由用户承担(他以为命令跑在自己机器上、看到的却是云上一个空目录的结果)。 */ export declare function assertDeviceLaneWired(isDeviceLane: boolean, lane: DeviceLane | undefined, hasFactory: boolean): void; //# sourceMappingURL=device-lane.d.ts.map