@mhome/core-protocol 1.15.6 → 1.15.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -5,6 +5,12 @@ provider runtimes. Public `/app/*` contracts belong to
5
5
  `mhome-app-facade-api`; this crate owns internal MWS, authentication, LLM,
6
6
  Messaging normalization, Node runtime, and Storage contracts.
7
7
 
8
+ MWS uses standard WebSocket Ping/Pong control frames for connection liveness.
9
+ There are no application `pi`/`po` messages or auth `heartbeatInterval` field.
10
+ The transport owns heartbeat timing and reports authenticated local connection
11
+ activity through `RefreshLocalAppClient`; closing the transport removes that
12
+ connection through `CleanupLocalAppClient`.
13
+
8
14
  `interaction_flow` defines the serializable Core-to-Node flow definition and
9
15
  handler protocol. Definitions name logical operations only; MeowCore chooses
10
16
  and pins the Node instance and fixed transport routes for each session.
@@ -13,6 +13,11 @@
13
13
  "nativeMethod": "hostRuntime",
14
14
  "desktopCommand": "host_runtime",
15
15
  "ipcMethod": "host.runtime"
16
+ },
17
+ "claim": {
18
+ "nativeMethod": "hostClaim",
19
+ "desktopCommand": "host_claim",
20
+ "ipcMethod": "host.claim"
16
21
  }
17
22
  },
18
23
  "actions": {
@@ -59,7 +64,9 @@
59
64
  "reachable"
60
65
  ],
61
66
  "info": "HostInfo or null",
62
- "infoError": "string or null"
67
+ "infoError": "string or null",
68
+ "claimable": "boolean; verified empty-ACL challenge, not a permission result",
69
+ "identityUnverified": "boolean; blocks TOFU and management after verification failure"
63
70
  },
64
71
  "runtimeResponse": {
65
72
  "metrics": "HostMetrics",
@@ -69,5 +76,12 @@
69
76
  "requiresLocalNetwork": true,
70
77
  "invalidateOnNetworkChange": true,
71
78
  "mutationsAutomaticallyRetried": false
79
+ },
80
+ "claimRequest": {
81
+ "hostId": "non-empty string; no scope or endpoint accepted"
82
+ },
83
+ "claimResponse": {
84
+ "claimed": "true only after Host persistence and cloud receipt commit",
85
+ "hostId": "requested Host identity when supplied"
72
86
  }
73
87
  }
@@ -1,25 +1,161 @@
1
1
  {
2
2
  "valid": [
3
- { "name": "empty request", "value": {} },
4
- { "name": "device request", "value": { "deviceId": "camera-1" } },
5
- { "name": "watch set request", "value": { "deviceId": "camera-1", "enabled": true } },
3
+ {
4
+ "name": "empty request",
5
+ "value": {}
6
+ },
7
+ {
8
+ "name": "device request",
9
+ "value": {
10
+ "deviceId": "camera-1"
11
+ }
12
+ },
13
+ {
14
+ "name": "watch set request",
15
+ "value": {
16
+ "deviceId": "camera-1",
17
+ "enabled": true
18
+ }
19
+ },
6
20
  {
7
21
  "name": "management snapshot",
8
22
  "value": {
9
- "providers": [{ "id": "onvif", "displayName": "ONVIF", "description": "ONVIF cameras", "supportsMultipleCameras": true }],
10
- "devices": [{ "id": "camera-1", "name": "Front Door", "capabilities": ["state.cameraMotion"], "health": "ready" }],
11
- "onlineStates": [{ "id": "camera-1", "state": "online", "observedAt": 1767225600, "source": "onvif" }],
12
- "watchStates": [{ "ok": true, "deviceId": "camera-1", "enabled": false }]
23
+ "providers": [
24
+ {
25
+ "id": "onvif",
26
+ "displayName": "ONVIF",
27
+ "description": "ONVIF cameras",
28
+ "supportsMultipleCameras": true
29
+ }
30
+ ],
31
+ "devices": [
32
+ {
33
+ "id": "camera-1",
34
+ "name": "Front Door",
35
+ "capabilities": [
36
+ "state.cameraMotion"
37
+ ],
38
+ "health": "ready",
39
+ "sourceId": null,
40
+ "resolutionStatus": "ready"
41
+ }
42
+ ],
43
+ "onlineStates": [
44
+ {
45
+ "id": "camera-1",
46
+ "state": "online",
47
+ "observedAt": 1767225600,
48
+ "source": "onvif"
49
+ }
50
+ ],
51
+ "watchStates": [
52
+ {
53
+ "ok": true,
54
+ "deviceId": "camera-1",
55
+ "enabled": false
56
+ }
57
+ ],
58
+ "sources": []
59
+ }
60
+ },
61
+ {
62
+ "name": "device list",
63
+ "value": {
64
+ "devices": [],
65
+ "onlineStates": []
66
+ }
67
+ },
68
+ {
69
+ "name": "device mutation",
70
+ "value": {
71
+ "deviceIds": [
72
+ "camera-1"
73
+ ],
74
+ "changed": true
75
+ }
76
+ },
77
+ {
78
+ "name": "watch response",
79
+ "value": {
80
+ "ok": true,
81
+ "deviceId": "camera-1",
82
+ "enabled": true
13
83
  }
14
84
  },
15
- { "name": "device list", "value": { "devices": [], "onlineStates": [] } },
16
- { "name": "device mutation", "value": { "deviceIds": ["camera-1"], "changed": true } },
17
- { "name": "watch response", "value": { "ok": true, "deviceId": "camera-1", "enabled": true } },
18
- { "name": "operation error", "value": { "ok": false, "reason": "CAMERA_OPERATION_FAILED", "detail": "failed" } }
85
+ {
86
+ "name": "operation error",
87
+ "value": {
88
+ "ok": false,
89
+ "reason": "CAMERA_OPERATION_FAILED",
90
+ "detail": "failed"
91
+ }
92
+ },
93
+ {
94
+ "name": "remove-ha-source",
95
+ "value": {
96
+ "sourceId": "ha-1"
97
+ }
98
+ },
99
+ {
100
+ "name": "connected-empty-ha",
101
+ "value": {
102
+ "providers": [],
103
+ "sources": [
104
+ {
105
+ "id": "ha-1",
106
+ "name": "http://homeassistant.local:8123",
107
+ "deviceCount": 0
108
+ }
109
+ ],
110
+ "devices": [],
111
+ "onlineStates": [],
112
+ "watchStates": []
113
+ }
114
+ }
19
115
  ],
20
116
  "invalid": [
21
- { "name": "watch mutation missing enabled", "value": { "deviceId": "camera-1", "unexpected": true } },
22
- { "name": "unknown health", "value": { "providers": [], "devices": [{ "id": "camera-1", "name": "Front", "capabilities": [], "health": "unknown" }], "onlineStates": [], "watchStates": [] } },
23
- { "name": "device leaks internal field", "value": { "devices": [{ "id": "camera-1", "name": "Front Door", "capabilities": [], "health": "ready", "sourceUid": "secret" }], "onlineStates": [] } }
117
+ {
118
+ "name": "watch mutation missing enabled",
119
+ "value": {
120
+ "deviceId": "camera-1",
121
+ "unexpected": true
122
+ }
123
+ },
124
+ {
125
+ "name": "unknown health",
126
+ "value": {
127
+ "providers": [],
128
+ "devices": [
129
+ {
130
+ "id": "camera-1",
131
+ "name": "Front",
132
+ "capabilities": [],
133
+ "health": "unknown",
134
+ "sourceId": null,
135
+ "resolutionStatus": "ready"
136
+ }
137
+ ],
138
+ "onlineStates": [],
139
+ "watchStates": [],
140
+ "sources": []
141
+ }
142
+ },
143
+ {
144
+ "name": "device leaks internal field",
145
+ "value": {
146
+ "devices": [
147
+ {
148
+ "id": "camera-1",
149
+ "name": "Front Door",
150
+ "capabilities": [],
151
+ "health": "ready",
152
+ "sourceUid": "secret",
153
+ "sourceId": null,
154
+ "resolutionStatus": "ready"
155
+ }
156
+ ],
157
+ "onlineStates": []
158
+ }
159
+ }
24
160
  ]
25
161
  }
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "manifest": "mhome.core.v1",
3
- "contractVersion": "1.15.6",
3
+ "contractVersion": "1.15.7",
4
4
  "protocols": {
5
5
  "agentGateway": {
6
6
  "submitTarget": "/agent/submit",
@@ -29,7 +29,8 @@
29
29
  "managementSnapshot": "management/snapshot",
30
30
  "deviceRemove": "device/remove",
31
31
  "watchStatus": "watch/status",
32
- "watchSet": "watch/set"
32
+ "watchSet": "watch/set",
33
+ "sourceRemove": "source/remove"
33
34
  },
34
35
  "flows": {
35
36
  "deviceAdd": "device.add"
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mhome/core-protocol",
3
- "version": "1.15.6",
3
+ "version": "1.15.7",
4
4
  "description": "Build-time protocol artifacts for mhome.core",
5
5
  "license": "MIT",
6
6
  "repository": {
package/protocol.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "protocol": "mhome.core",
3
- "contractVersion": "1.15.6",
3
+ "contractVersion": "1.15.7",
4
4
  "manifest": "manifest/core.v1.json",
5
5
  "schemas": {
6
6
  "hostManagementRequest": "schema/host-management-request.v1.schema.json",
@@ -3,122 +3,360 @@
3
3
  "$id": "https://mhome.ai/schema/camera-plugin-management.v1.schema.json",
4
4
  "title": "Camera Plugin management values",
5
5
  "oneOf": [
6
- { "$ref": "#/$defs/emptyRequest" },
7
- { "$ref": "#/$defs/deviceIdRequest" },
8
- { "$ref": "#/$defs/watchSetRequest" },
9
- { "$ref": "#/$defs/managementSnapshot" },
10
- { "$ref": "#/$defs/deviceListResponse" },
11
- { "$ref": "#/$defs/deviceMutationResponse" },
12
- { "$ref": "#/$defs/watchControlResponse" },
13
- { "$ref": "#/$defs/errorResponse" }
6
+ {
7
+ "$ref": "#/$defs/emptyRequest"
8
+ },
9
+ {
10
+ "$ref": "#/$defs/deviceIdRequest"
11
+ },
12
+ {
13
+ "$ref": "#/$defs/watchSetRequest"
14
+ },
15
+ {
16
+ "$ref": "#/$defs/managementSnapshot"
17
+ },
18
+ {
19
+ "$ref": "#/$defs/deviceListResponse"
20
+ },
21
+ {
22
+ "$ref": "#/$defs/deviceMutationResponse"
23
+ },
24
+ {
25
+ "$ref": "#/$defs/watchControlResponse"
26
+ },
27
+ {
28
+ "$ref": "#/$defs/errorResponse"
29
+ },
30
+ {
31
+ "$ref": "#/$defs/sourceIdRequest"
32
+ }
14
33
  ],
15
34
  "$defs": {
16
- "emptyRequest": { "type": "object", "additionalProperties": false },
35
+ "emptyRequest": {
36
+ "type": "object",
37
+ "additionalProperties": false
38
+ },
17
39
  "deviceIdRequest": {
18
40
  "type": "object",
19
- "required": ["deviceId"],
20
- "properties": { "deviceId": { "type": "string", "minLength": 1 } },
41
+ "required": [
42
+ "deviceId"
43
+ ],
44
+ "properties": {
45
+ "deviceId": {
46
+ "type": "string",
47
+ "minLength": 1
48
+ }
49
+ },
21
50
  "additionalProperties": false
22
51
  },
23
52
  "watchSetRequest": {
24
53
  "type": "object",
25
- "required": ["deviceId", "enabled"],
54
+ "required": [
55
+ "deviceId",
56
+ "enabled"
57
+ ],
26
58
  "properties": {
27
- "deviceId": { "type": "string", "minLength": 1 },
28
- "enabled": { "type": "boolean" }
59
+ "deviceId": {
60
+ "type": "string",
61
+ "minLength": 1
62
+ },
63
+ "enabled": {
64
+ "type": "boolean"
65
+ }
29
66
  },
30
67
  "additionalProperties": false
31
68
  },
32
69
  "providerCatalogItem": {
33
70
  "type": "object",
34
- "required": ["id", "displayName", "description", "supportsMultipleCameras"],
71
+ "required": [
72
+ "id",
73
+ "displayName",
74
+ "description",
75
+ "supportsMultipleCameras"
76
+ ],
35
77
  "properties": {
36
- "id": { "type": "string", "minLength": 1 },
37
- "displayName": { "type": "string", "minLength": 1 },
38
- "description": { "type": "string" },
39
- "supportsMultipleCameras": { "type": "boolean" }
78
+ "id": {
79
+ "type": "string",
80
+ "minLength": 1
81
+ },
82
+ "displayName": {
83
+ "type": "string",
84
+ "minLength": 1
85
+ },
86
+ "description": {
87
+ "type": "string"
88
+ },
89
+ "supportsMultipleCameras": {
90
+ "type": "boolean"
91
+ }
40
92
  },
41
93
  "additionalProperties": false
42
94
  },
43
95
  "cameraDevice": {
44
96
  "type": "object",
45
- "required": ["id", "name", "capabilities", "health"],
97
+ "required": [
98
+ "id",
99
+ "name",
100
+ "capabilities",
101
+ "health",
102
+ "sourceId",
103
+ "resolutionStatus"
104
+ ],
46
105
  "properties": {
47
- "id": { "type": "string", "minLength": 1 },
48
- "name": { "type": "string", "minLength": 1 },
49
- "manufacturerName": { "type": "string", "minLength": 1 },
106
+ "id": {
107
+ "type": "string",
108
+ "minLength": 1
109
+ },
110
+ "name": {
111
+ "type": "string",
112
+ "minLength": 1
113
+ },
114
+ "manufacturerName": {
115
+ "type": "string",
116
+ "minLength": 1
117
+ },
50
118
  "capabilities": {
51
119
  "type": "array",
52
- "items": { "type": "string", "minLength": 1 },
120
+ "items": {
121
+ "type": "string",
122
+ "minLength": 1
123
+ },
53
124
  "uniqueItems": true
54
125
  },
55
- "health": { "enum": ["applying", "ready", "degraded", "error"] },
56
- "lastError": { "type": "string", "minLength": 1 }
126
+ "health": {
127
+ "enum": [
128
+ "applying",
129
+ "ready",
130
+ "degraded",
131
+ "error"
132
+ ]
133
+ },
134
+ "lastError": {
135
+ "type": "string",
136
+ "minLength": 1
137
+ },
138
+ "sourceId": {
139
+ "type": [
140
+ "string",
141
+ "null"
142
+ ],
143
+ "minLength": 1
144
+ },
145
+ "resolutionStatus": {
146
+ "enum": [
147
+ "unresolved",
148
+ "ready",
149
+ "failed"
150
+ ]
151
+ }
57
152
  },
58
153
  "additionalProperties": false
59
154
  },
60
155
  "onlineStateObservation": {
61
156
  "type": "object",
62
- "required": ["id", "state"],
157
+ "required": [
158
+ "id",
159
+ "state"
160
+ ],
63
161
  "properties": {
64
- "id": { "type": "string", "minLength": 1 },
65
- "state": { "enum": ["online", "offline"] },
66
- "observedAt": { "type": "integer" },
67
- "source": { "type": "string", "minLength": 1 },
68
- "reason": { "type": "string", "minLength": 1 }
162
+ "id": {
163
+ "type": "string",
164
+ "minLength": 1
165
+ },
166
+ "state": {
167
+ "enum": [
168
+ "online",
169
+ "offline"
170
+ ]
171
+ },
172
+ "observedAt": {
173
+ "type": "integer"
174
+ },
175
+ "source": {
176
+ "type": "string",
177
+ "minLength": 1
178
+ },
179
+ "reason": {
180
+ "type": "string",
181
+ "minLength": 1
182
+ }
69
183
  },
70
184
  "additionalProperties": false
71
185
  },
72
186
  "watchControlResponse": {
73
187
  "type": "object",
74
- "required": ["ok", "deviceId", "enabled"],
188
+ "required": [
189
+ "ok",
190
+ "deviceId",
191
+ "enabled"
192
+ ],
75
193
  "properties": {
76
- "ok": { "type": "boolean" },
77
- "deviceId": { "type": "string", "minLength": 1 },
78
- "enabled": { "type": "boolean" }
194
+ "ok": {
195
+ "type": "boolean"
196
+ },
197
+ "deviceId": {
198
+ "type": "string",
199
+ "minLength": 1
200
+ },
201
+ "enabled": {
202
+ "type": "boolean"
203
+ }
79
204
  },
80
205
  "additionalProperties": false
81
206
  },
82
207
  "managementSnapshot": {
83
208
  "type": "object",
84
- "required": ["providers", "devices", "onlineStates", "watchStates"],
209
+ "required": [
210
+ "providers",
211
+ "devices",
212
+ "onlineStates",
213
+ "watchStates",
214
+ "sources"
215
+ ],
85
216
  "properties": {
86
- "providers": { "type": "array", "items": { "$ref": "#/$defs/providerCatalogItem" } },
87
- "devices": { "type": "array", "items": { "$ref": "#/$defs/cameraDevice" } },
88
- "onlineStates": { "type": "array", "items": { "$ref": "#/$defs/onlineStateObservation" } },
89
- "watchStates": { "type": "array", "items": { "$ref": "#/$defs/watchControlResponse" } }
217
+ "providers": {
218
+ "type": "array",
219
+ "items": {
220
+ "$ref": "#/$defs/providerCatalogItem"
221
+ }
222
+ },
223
+ "devices": {
224
+ "type": "array",
225
+ "items": {
226
+ "$ref": "#/$defs/cameraDevice"
227
+ }
228
+ },
229
+ "onlineStates": {
230
+ "type": "array",
231
+ "items": {
232
+ "$ref": "#/$defs/onlineStateObservation"
233
+ }
234
+ },
235
+ "watchStates": {
236
+ "type": "array",
237
+ "items": {
238
+ "$ref": "#/$defs/watchControlResponse"
239
+ }
240
+ },
241
+ "sources": {
242
+ "type": "array",
243
+ "items": {
244
+ "$ref": "#/$defs/homeAssistantSource"
245
+ }
246
+ }
90
247
  },
91
248
  "additionalProperties": false
92
249
  },
93
250
  "deviceListResponse": {
94
251
  "type": "object",
95
- "required": ["devices", "onlineStates"],
252
+ "required": [
253
+ "devices",
254
+ "onlineStates"
255
+ ],
96
256
  "properties": {
97
- "devices": { "type": "array", "items": { "$ref": "#/$defs/cameraDevice" } },
98
- "onlineStates": { "type": "array", "items": { "$ref": "#/$defs/onlineStateObservation" } }
257
+ "devices": {
258
+ "type": "array",
259
+ "items": {
260
+ "$ref": "#/$defs/cameraDevice"
261
+ }
262
+ },
263
+ "onlineStates": {
264
+ "type": "array",
265
+ "items": {
266
+ "$ref": "#/$defs/onlineStateObservation"
267
+ }
268
+ }
99
269
  },
100
270
  "additionalProperties": false
101
271
  },
102
272
  "deviceMutationResponse": {
103
273
  "type": "object",
104
- "required": ["deviceIds", "changed"],
274
+ "required": [
275
+ "deviceIds",
276
+ "changed"
277
+ ],
105
278
  "properties": {
106
279
  "deviceIds": {
107
280
  "type": "array",
108
- "items": { "type": "string", "minLength": 1 },
281
+ "items": {
282
+ "type": "string",
283
+ "minLength": 1
284
+ },
109
285
  "uniqueItems": true
110
286
  },
111
- "changed": { "type": "boolean" }
287
+ "changed": {
288
+ "type": "boolean"
289
+ }
112
290
  },
113
291
  "additionalProperties": false
114
292
  },
115
293
  "errorResponse": {
116
294
  "type": "object",
117
- "required": ["ok", "reason", "detail"],
295
+ "required": [
296
+ "ok",
297
+ "reason",
298
+ "detail"
299
+ ],
118
300
  "properties": {
119
- "ok": { "const": false },
120
- "reason": { "type": "string", "minLength": 1 },
121
- "detail": { "type": "string", "minLength": 1 }
301
+ "ok": {
302
+ "const": false
303
+ },
304
+ "reason": {
305
+ "type": "string",
306
+ "minLength": 1
307
+ },
308
+ "detail": {
309
+ "type": "string",
310
+ "minLength": 1
311
+ }
312
+ },
313
+ "additionalProperties": false
314
+ },
315
+ "sourceIdRequest": {
316
+ "type": "object",
317
+ "required": [
318
+ "sourceId"
319
+ ],
320
+ "properties": {
321
+ "sourceId": {
322
+ "type": "string",
323
+ "minLength": 1
324
+ }
325
+ },
326
+ "additionalProperties": false
327
+ },
328
+ "homeAssistantSource": {
329
+ "type": "object",
330
+ "required": [
331
+ "id",
332
+ "name",
333
+ "deviceCount"
334
+ ],
335
+ "properties": {
336
+ "id": {
337
+ "type": "string",
338
+ "minLength": 1
339
+ },
340
+ "name": {
341
+ "type": "string",
342
+ "minLength": 1
343
+ },
344
+ "deviceCount": {
345
+ "type": "integer",
346
+ "minimum": 0
347
+ },
348
+ "lastError": {
349
+ "type": [
350
+ "string",
351
+ "null"
352
+ ]
353
+ },
354
+ "lastRefreshedAt": {
355
+ "type": [
356
+ "string",
357
+ "null"
358
+ ]
359
+ }
122
360
  },
123
361
  "additionalProperties": false
124
362
  }