# Infra Protocol

一组面向个人基础设施的本机协议；首个稳定协议 Infra Discovery 让服务声明具体协议版本与连接方式，供兼容消费者精确发现并直接连接。

## Metadata

- HTML: https://glenzli.com/projects/infra-protocol/
- Markdown: https://glenzli.com/projects/infra-protocol.md
- Collection: Projects
- Language: zh-CN
- Published: 2026-08-11
- Status: active
- Tags: personal-infra, protocol, discovery, local-services, interoperability

## Content

Infra Protocol 面向个人基础设施提供一组中立、统一登记且可以独立演进的本机协议。当前正式包含的第一个协议是 **Infra Discovery**：服务声明自己实现了哪些具体协议版本，以及可以通过哪些 binding 访问；消费者找到自己确实理解的组合后，直接连接服务。

它解决的是“本机有哪些兼容服务、它们在哪里”这一件事。发现结束以后，请求、响应、指标、状态机、错误与权限仍由被选中的应用协议定义。

## 项目概念

  ![多个本机服务发布短时登记，消费者精确匹配协议版本与 binding 后直接连接服务](/images/projects/infra-protocol-banner.webp)

```text
Publisher -> short-lived registration
Consumer  -> exact protocol version + binding match
Consumer  --------------------------------> Provider
              discovery ends; application protocol begins
```

## 三份合同彼此独立

    **Discovery document**
    只定义登记 JSON 的结构。当前稳定版本是 <code>infra.discovery.registration@20260810.1</code>。

    **Application protocol**
    协议 ID 与精确版本决定服务实际提供什么。Discovery 不解释内容，也不把相似功能视为兼容。

    **Binding**
    Binding 规定 endpoint 怎样解释，以及连接层必须满足哪些安全条件；它不定义应用消息格式。

    **未知就忽略**
    消费者忽略自己不认识的协议、版本和 binding，不按名称、字段相似度或版本大小猜测兼容性。

一项应用协议升级，不要求 Discovery 文档随之升级；新增 binding 也不需要改变应用协议。把这三层拆开，是为了让本机设施可以互相发现，而不被迫共享同一套 RPC 或数据模型。

## 注册清单里有什么

每个服务以 `service.kind + service.instance_id` 形成稳定身份，并在每次进程启动时生成新的 `generation`。注册清单只保留最小的发现信息：

| 字段 | 作用 |
| --- | --- |
| Service identity | 标识同一个长期服务实例。 |
| Generation | 区分每次启动，防止旧 endpoint 被误用。 |
| Lease | 让退出或失联的发布者自然过期。 |
| Offer | 声明 `(protocol, exact versions, binding, endpoint)`。 |

同一个稳定服务身份同时只能有一个发布者续租；需要并行存在的实例必须使用不同的 `instance_id`。发布者通常每 15 秒续租一次，lease 为 45 秒。消费者只读取和验证清单，不替发布者修复、更新或删除它。

## 从发现到直连

      **发布具体 offer**
      一个服务可以发布多个协议或 binding，但每个 offer 都明确绑定协议、版本和 endpoint。

```json
{
  "protocol": "pcp.runtime.observer",
  "protocol_versions": ["20260810.1"],
  "binding": "infra.local.unix-socket",
  "endpoint": "sockets/a83f2d9c.sock"
}
```

协议版本对 Discovery 来说是不透明字符串，只按精确相等匹配，不按数字或时间推断兼容范围。

      **消费者按自己的能力选择**
      消费者带着支持的协议版本和 binding 扫描仍在租约内的登记，再按自己的偏好选择。

```text
live registration
  -> known protocol
  -> exact version intersection
  -> supported binding
  -> direct connection
```

存在多个兼容服务时，选择、排序、回退或负载均衡仍是消费者策略，Discovery 不提供全局评分。

      **连接后退出发现层**
      连接建立后，双方只按照选中的应用协议和 binding 通信。

```text
Discovery: location + exact compatibility
Application protocol: requests + responses + semantics + authorization
```

注册清单不携带指标、Console URL、凭据、控制能力或通用请求 envelope。

## 本机边界

默认运行根按平台选择当前用户专属的位置：macOS 使用 Darwin user temp root，Linux 使用经过验证的 `$XDG_RUNTIME_DIR`，Windows 非 packaged 进程使用 Local App Data。沙箱或隔离环境必须显式提供所有参与者共同可访问的安全目录；无法取得共同根时，Discovery 直接不可用，不回退到不受控的 `/tmp`。

当前定义两种本机 binding：Unix socket 与 Windows named pipe。它们都要求当前用户边界和最终 endpoint 校验。Unix socket 使用 owner-only 目录与 `0600` 文件，并校验 peer UID；Windows named pipe 校验连接者 SID。它们防止意外的跨用户访问，但不声称能抵御已经以同一 OS 用户运行的恶意进程。

## 它刻意不做什么

Infra Discovery 不是 daemon、代理、RPC 框架、服务网格或通用能力模型。当前版本不定义 `observe`、`events`、`control`、健康状态、指标、凭据、Console 链接、远程网络或统一请求格式。

这些能力如果有真实需要，应当成为各自可版本化的协议，而不是继续膨胀 Discovery。PCP Runtime 用它发布 enrollment 与 observer 协议，Infra Sentinel 用它定位设施；两边共享的是发现方式，不是业务数据模型。

规范、JSON Schema、有效与无效 fixtures，以及 Schema 之外的租约、选择和文件系统语义检查都保存在仓库中。当前实现以 Python 测试验证 Draft 2020-12 Schema 与 conformance 规则：

```sh
python3 -m unittest discover -s tests -v
```
