Files

66 lines
4.1 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# NekoNest Cloud 状态模型
## 账号、租户与席位
- 一个 Cloud 账号拥有一个 `tenant_instances` 记录。
- 一个 `active``slot_state=active` 的主机占一个席位,在线与否不改变计数。
- 未过期的 waiting pairing 只预留容量;取消、过期或成功 claim 后释放预留。
- pairing 创建与 claim 都在写入 SQL 内复核容量。第 N+1 台返回 `device_capacity_exceeded`
- 账户所有者可以轮询自己创建的配对状态,但不能读取其他账户的请求。
- 等待中的请求可由所有者取消;若 daemon 已先认领,则取消失败,不能撤销已提交的设备凭据。
- 主机撤销将主机标记为 deactivated、撤销所有设备凭证、释放席位,并推进 authorization revision。
- 同一身份恢复复用原 host ID;不能因复制公开指纹而获得第二个身份。
席位允许设备成为租户成员,不自动授权任何手机读取该设备。
## Placement
`tenant_placements` 是共享 Relay 的部署权威:
- `home_region_id` 固定租户主区域;
- `relay_node_id` 指向当前唯一可写节点;
- `generation` 只能单调增加;
- `state` 首版使用 `provisioning|active|quiescing|copying|switching|draining|failed`
客户端只看到稳定 Connect origin。`provisioning` 时在同一地址重试,不得到后端节点 URL。
## 授权 revision
每个租户有一条 `tenant_authorization_state`
- `status=active|suspended`
- `revision` 在成功 claim、主机撤销、手机撤销或租户暂停时单调增加;
- 变更只有在相应设备/主机写入已经成功时才推进,避免未提交操作造成虚假撤销。
Relay 获取最长 5 分钟的签名快照,每 60 秒完整刷新、默认每 5 秒检查 revision(delta 与随后的完整刷新各限制为 3 秒)。控制面不可达时不建立新 principal;现有连接最多存活到快照到期。
## 节点与签名密钥
节点状态为 `provisioning|active|draining|offline|retired`。heartbeat 只接受非回退 generation。节点以 D1 中未撤销、未过期的 SPIFFE ID 与证书 SHA-256 指纹记录为身份。所有内部调用必须先通过受信 mTLS 终止层注入绑定 method/path 的短时 HMAC assertion;控制面不要求共享 bearer。
Ed25519 私钥不进入 D1。`relay_signing_keys` 只保存 public JWK、`private_key_ref``kid`、有效期与状态。签名密钥必须至少有效到新快照的 `expires_at`;轮换重叠必须长于 5 分钟最大快照 TTL,旧 public JWK 也必须保留超过最后一份旧 key 快照的 TTL,保证验证窗口不断裂。
## Phone handoff
`phone_handoff_tickets` 生命周期:`issued → consumed``issued → expired`。ticket
- 随机 256 bit
- D1 只保存 SHA-256 摘要;
- 绑定账号、租户、精确 PWA origin;
- 60 秒有效;
- 条件 UPDATE 原子消费一次。
控制面只允许目标 placement 节点原子消费 ticket,并向该节点返回 tenant 与手机公钥。目标 Relay Engine 创建独立 phone principal/token 后,把 routing-only handle 摘要登记回来。控制面不生成或保存 phone token。该流程不创建 device grantroute handle 只负责解析 tenant placement,不能替代 phone token。
每次 phone WS/REST 入口都必须同时校验 route handle 摘要与 phone token 摘要,并要求两者绑定同一未撤销 phone principal 和 tenant;单独持有 route handle 不构成授权。已消费或已过期 ticket 只短暂保留摘要和公开身份字段用于防重放诊断,24 小时后由维护任务删除;D1 从未保存明文 ticket。
## 数据边界
D1 保存账号、权益、主机身份元数据、凭证摘要、placement、授权 revision、公钥、ticket/route 摘要和审计。新增表不得出现 prompt、session、attachment 明文或私钥。
控制面 `last_used_at` 只证明设备凭证最近成功通过授权,不证明租户 relay、WebSocket、Relay Engine 或本地 Agent 在线。
遗留 `grace_days` 不参与资格、设备认证或页面判断。
加载、离线和页面失败是客户端展示状态,不得改写控制面 placement、授权或主机身份事实。