Skip to content

Commit b4307f2

Browse files
author
developerworks
committed
Harden dashboard protocol handling
- Reject legacy protocol messages in dashboard IPC flows - Add registration heartbeat coverage and fixture boundaries - Align dashboard contracts, docs, configuration, and tests
1 parent fbd9f42 commit b4307f2

28 files changed

Lines changed: 431 additions & 98 deletions

ASSUMPTIONS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
- target IPC(目标进程进程间通信) 使用 Unix domain socket(Unix 域套接字) 和 newline-delimited JSON(按行分隔的 JSON 数据).
2626
- `ipc.enabled=false` 或缺少 `ipc` section(配置节) 时, target process(目标进程) 不打开 IPC(进程间通信).
2727
- `ipc.enabled=true` 时, `ipc.path``registration.relay_registration_path` 必须是 absolute path(绝对路径).
28-
- dynamic registration(动态注册) 只上报 `target_id`, `display_name`, `ipc_path`, `authorization_scope``lease_seconds`.
28+
- dynamic registration(动态注册) 只上报 `target_id`, `display_name`, `ipc_path`, `lease_seconds``supported_commands`.
2929
- event(事件) 和 log(日志) subscription(订阅) 必须由 established dashboard session(已建立看板会话) 触发, registration(注册) 本身不触发主动推送.
3030
- 本次 UI(用户界面) browser test(浏览器测试) 使用 `wss://` relay(中继) URL(统一资源定位符) 和本地 TLS(传输层安全协议) WebSocket(网络套接字协议) 协议测试服务验证交互. 浏览器测试不证明真实 mTLS(双向传输层安全协议认证) 证书链有效.
3131
- 当前仓库的 target-side IPC server(目标侧进程间通信服务端) 提供可测试 dispatcher(分发器), Unix listener(Unix 监听器) bind(绑定) 和命令映射边界. relay(中继) 测试使用真实 Unix domain socket IPC(Unix 域套接字进程间通信) 测试目标覆盖会话门控和转发顺序.

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,8 +56,8 @@ ipc:
5656
enabled: true
5757
relay_registration_path: /run/rust-supervisor/dashboard-relay-registration.sock
5858
display_name: "payments worker a"
59-
authorization_scope: "payments:operate"
6059
lease_seconds: 30
60+
registration_heartbeat_interval_seconds: 15
6161
```
6262
6363
When `ipc.enabled=true`, `ipc.path` and `ipc.registration.relay_registration_path` must be absolute local paths. Registration uses dynamic registration. The relay configuration must not hard-code target lists.

README.zh.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,8 +49,8 @@ ipc:
4949
enabled: true
5050
relay_registration_path: /run/rust-supervisor/dashboard-relay-registration.sock
5151
display_name: "payments worker a"
52-
authorization_scope: "payments:operate"
5352
lease_seconds: 30
53+
registration_heartbeat_interval_seconds: 15
5454
```
5555
5656
`ipc.enabled=true` 时, `ipc.path` 和 `ipc.registration.relay_registration_path` 必须是 absolute path(绝对路径). registration(注册) 使用 dynamic registration(动态注册). relay config(中继配置) 不允许写死 target list(目标列表).

examples/config/supervisor.template.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ ipc:
2727
enabled: false
2828
relay_registration_path: /run/rust-supervisor/dashboard-relay-registration.sock
2929
display_name: "example target"
30-
authorization_scope: "example:operate"
3130
lease_seconds: 30
31+
registration_heartbeat_interval_seconds: 15

examples/config/supervisor.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,5 +27,5 @@ ipc:
2727
enabled: true
2828
relay_registration_path: /run/rust-supervisor/dashboard-relay-registration.sock
2929
display_name: "payments worker a"
30-
authorization_scope: "payments:operate"
3130
lease_seconds: 30
31+
registration_heartbeat_interval_seconds: 15

fixtures/legacy_protocol/.gitkeep

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

manual/dashboard.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,11 @@ ipc:
1919
enabled: true
2020
relay_registration_path: /run/rust-supervisor/dashboard-relay-registration.sock
2121
display_name: "payments worker a"
22-
authorization_scope: "payments:operate"
2322
lease_seconds: 30
23+
registration_heartbeat_interval_seconds: 15
2424
```
2525
26-
`ipc.path` 必须是 absolute path(绝对路径). `registration.authorization_scope` 必须非空. `registration.lease_seconds` 必须大于 0.
26+
`ipc.path` 必须是 absolute path(绝对路径). `registration.lease_seconds` 必须大于 0. `registration.registration_heartbeat_interval_seconds` 必须小于 `registration.lease_seconds`.
2727

2828
## Protocol(协议)
2929

specs/003-supervisor-dashboard/analysis.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ To execute(执行方式): `/speckit.git.commit`
3737
| FR-016 | Yes(是) | T009, T053, T057, T058 | 覆盖 requested by(请求者) 派生和覆盖保护. |
3838
| FR-017 | Yes(是) | T009, T054, T057, T062 | 覆盖危险命令二次确认和 reason(原因) 非空. |
3939
| FR-018 | Yes(是) | T009, T054, T058, T050 | 覆盖 command audit(命令审计) 生成和展示. |
40-
| FR-019 | Yes(是) | T053, T059 | 覆盖未认证, 未授权和未建立控制会话拒绝路径. |
40+
| FR-019 | Yes(是) | T053, T059 | 覆盖未认证和未建立控制会话拒绝路径. |
4141
| FR-020 | Yes(是) | T043, T049, T051, T052 | 覆盖事件日志过滤条件和 UI(用户界面) 集成. |
4242
| FR-021 | Yes(是) | T043, T048, T050, T063 | 覆盖连接, 认证, 命令失败和事件丢失诊断. |
4343
| FR-022 | Yes(是) | T002, T009, T012, T017, T054 | 覆盖 no compatibility export(无兼容导出), 旧协议别名和历史命令别名拒绝. |

specs/003-supervisor-dashboard/contracts/config-schema.md

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,8 +17,8 @@ ipc:
1717
enabled: true
1818
relay_registration_path: /run/rust-supervisor/dashboard-relay-registration.sock
1919
display_name: "payments worker a"
20-
authorization_scope: "payments:operate"
2120
lease_seconds: 30
21+
registration_heartbeat_interval_seconds: 15
2222
```
2323
2424
### Rules(规则)
@@ -30,12 +30,12 @@ ipc:
3030
- `bind_mode=create_new` 时, path(路径) 已存在必须失败并返回结构化配置错误.
3131
- `ipc.registration.enabled=true` 时, 目标进程必须在 IPC(进程间通信) 就绪后向 relay(中继) 提交 dynamic registration(动态注册).
3232
- `ipc.registration.relay_registration_path` 必须是本机绝对 path(路径).
33-
- `ipc.registration.authorization_scope` 必须非空.
3433
- `ipc.registration.lease_seconds` 必须大于 0.
34+
- `ipc.registration.registration_heartbeat_interval_seconds` 必须大于 0, 并且必须小于 `ipc.registration.lease_seconds`.
3535

3636
## Relay config(中继配置)
3737

38-
relay(中继) 使用独立 YAML(配置文件格式) 配置 `wss://` 监听地址, mTLS(双向传输层安全协议认证), trusted proxy(可信代理), registration(注册) 入口和授权默认规则. 目标进程列表不得写死在 relay(中继) 配置中. 该配置文件必须放在 `/Users/0x00/Documents/rust-supervisor-relay`.
38+
relay(中继) 使用独立 YAML(配置文件格式) 配置 `wss://` 监听地址, mTLS(双向传输层安全协议认证), trusted proxy(可信代理), registration(注册) 入口和租约规则. 目标进程列表不得写死在 relay(中继) 配置中. 该配置文件必须放在 `/Users/0x00/Documents/rust-supervisor-relay`.
3939

4040
```yaml
4141
listen:
@@ -56,8 +56,6 @@ registration:
5656
- /run/rust-supervisor/
5757
default_lease_seconds: 30
5858
max_lease_seconds: 120
59-
authorization_defaults:
60-
unknown_scope_policy: reject
6159
```
6260

6361
### Rules(规则)
@@ -66,6 +64,6 @@ authorization_defaults:
6664
- `tls.client_ca_path` 必须存在, 除非 `trusted_proxy.enabled=true` 且 relay(中继) 只接受可信代理地址.
6765
- `registration.listen_path` 必须是本机绝对 path(路径), 且不得暴露到外网.
6866
- `registration.allowed_ipc_path_prefixes` 为空时必须拒绝目标进程注册.
69-
- relay(中继) 必须在运行时拒绝重复 target id(目标标识), 重复 IPC path(进程间通信路径), 非绝对 IPC path(进程间通信路径), 空授权范围和无效租约.
67+
- relay(中继) 必须在运行时拒绝不同 owner identity(所有者身份) 覆盖相同 target id(目标标识), 重复 IPC path(进程间通信路径), 非绝对 IPC path(进程间通信路径), supported_commands(支持的命令) 结构无效和无效租约.
7068
- 注册冲突必须返回结构化错误, 并指出冲突 target id(目标标识) 或 IPC path(进程间通信路径).
7169
- 目标进程只完成注册时不得触发事件日志主动推送. 已认证客户端会话建立并绑定目标后, relay(中继) 才能连接目标进程 IPC(进程间通信) 并建立 subscription(订阅).

specs/003-supervisor-dashboard/contracts/wss-session.md

Lines changed: 26 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -13,23 +13,35 @@
1313

1414
## Session startup(会话启动)
1515

16-
服务端在 control session(控制会话) 建立后必须先发送由 active registration(活动注册) 形成的 target process list(目标进程列表) 和授权范围. 目标进程完成 dynamic registration(动态注册) 只会进入该列表, 不会因为注册本身触发事件日志主动推送.
16+
服务端在 WebSocket(网络套接字) 建立后必须先发送 `server_hello`(服务端握手). 客户端收到 `server_hello` 后发送 `client_hello`(客户端握手). relay(中继) 校验 `client_hello` 后才发送由 active registration(活动注册) 形成的 target process list(目标进程列表). 目标进程完成 dynamic registration(动态注册) 只会进入该列表, 不会因为注册本身触发事件日志主动推送.
1717

1818
```json
1919
{
20-
"type": "session_established",
20+
"type": "server_hello",
2121
"session_id": "01HV0000000000000000000200",
22-
"identity": {
23-
"principal": "operator@example.test",
24-
"source": "mtls"
25-
},
22+
"client_identity": "mtls_cert_fingerprint:test-client",
23+
"log_event_filter_mode": "remote",
24+
"log_event_filter_conditions": {},
25+
"filter_config_version": 1
26+
}
27+
```
28+
29+
```json
30+
{
31+
"type": "target_list",
2632
"targets": [
2733
{
2834
"target_id": "payments-worker-a",
2935
"display_name": "payments worker a",
3036
"registration_state": "active",
3137
"connection_state": "registered",
32-
"authorization_scope": "payments:operate"
38+
"supported_commands": [
39+
{
40+
"name": "restart_child",
41+
"idempotent": false,
42+
"timeout_seconds": 30
43+
}
44+
]
3345
}
3446
]
3547
}
@@ -48,8 +60,8 @@
4860

4961
### Ordering rules(顺序规则)
5062

51-
- `session_established` 必须早于 `state`, `event`, `log`, `state_delta`, `command_result``error`.
52-
- `session_established` 发送后, relay(中继) 才能按授权目标触发 IPC(进程间通信) 绑定和 event/log subscription(事件日志订阅).
63+
- `server_hello` 必须早于 `target_list`, `state`, `event`, `log`, `state_delta`, `command_result``error`.
64+
- `client_hello` 校验成功后, relay(中继) 才能自动绑定 active target(活跃目标), 触发 IPC(进程间通信) 绑定和 event/log subscription(事件日志订阅).
5365
- 同一 target process(目标进程) 内的 `event.sequence` 必须按单调顺序发送给 dashboard(看板).
5466
- IPC(进程间通信) 重连成功后, relay(中继) 必须先发送新的 `state`, 再继续发送新的 event(事件) 和 log(日志).
5567

@@ -69,11 +81,12 @@
6981
}
7082
```
7183

72-
### Authorization rules(授权规则)
84+
### Command rules(命令规则)
7385

7486
- relay(中继) 必须根据 RemoteIdentity(远程身份) 派生 `requested_by`.
7587
- 客户端消息中的 `requested_by` 必须被忽略或拒绝.
76-
- 未认证, 未授权, 证书身份不可解析或 control session(控制会话) 未建立时, relay(中继) 不得连接 IPC(进程间通信), 不得绑定 IPC(进程间通信), 不得转发命令.
88+
- 未认证, 证书身份不可解析或 control session(控制会话) 未建立时, relay(中继) 不得连接 IPC(进程间通信), 不得绑定 IPC(进程间通信), 不得转发命令.
89+
- relay(中继) 转发命令前必须确认 target(目标) 处于 active(活跃) 状态, 并确认 target(目标) 已经在 registration(注册) 中声明支持该命令.
7790
- `shutdown_tree`, `remove_child``add_child` 必须要求 `confirmed=true` 和非空 `reason`.
7891
- 客户端发送旧协议别名或历史控制命令别名时, relay(中继) 必须返回结构化拒绝错误, 不得执行别名对应行为.
7992

@@ -83,13 +96,13 @@ dashboard client(看板客户端) 可以本地过滤, 也可以向 relay(中继)
8396

8497
```json
8598
{
86-
"type": "filter_update",
99+
"type": "log_event_filter_conditions",
87100
"target_ids": ["payments-worker-a"],
88101
"child_paths": ["/root/payment_loop"],
89102
"lifecycle_states": ["failed", "restarting"],
90103
"event_types": ["child_failed", "child_restarted"],
91104
"severities": ["warning", "error"],
92-
"sequence_from": 1000,
105+
"sequence_min": 1000,
93106
"correlation_id": "restart-7"
94107
}
95108
```

0 commit comments

Comments
 (0)