@mhome/app-facade-protocol 1.34.1 → 1.36.0
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/contract/host-provisioning-v1.md +3 -5
- package/contract/pod-commissioning-v1.md +34 -45
- package/manifest/app-facade.v1.json +1 -1
- package/manifest/host-provision-targets.v1.json +1 -3
- package/manifest/hub-targets.v1.json +1 -1
- package/manifest/pod-targets.v1.json +1 -6
- package/manifest/routing.v1.json +1 -1
- package/manifest/targets.v1.json +1 -1
- package/package.json +1 -1
- package/protocol.json +1 -1
- package/schema/host-provision.v1.schema.json +0 -1
- package/schema/pod-commission.v1.schema.json +0 -1
|
@@ -119,20 +119,18 @@ Candidates come from the shared discovery (`/local/pod/discovery/*`) with
|
|
|
119
119
|
| `/local/host/provision/code` | `{"sessionId","code"}` | session snapshot |
|
|
120
120
|
| `/local/host/provision/wifi` | `{"sessionId","ssid","password"?}` | session snapshot |
|
|
121
121
|
| `/local/host/provision/wifi/scan` | `{"sessionId"}` | session snapshot |
|
|
122
|
-
| `/local/host/provision/cancel` | `{"sessionId"}` | session snapshot |
|
|
123
|
-
| `/local/host/provision/renew` | `{"sessionId"}` | session snapshot |
|
|
124
122
|
| `/local/host/provision/status` | `{}` | `{"session": snapshot or null}` |
|
|
125
123
|
|
|
126
124
|
Event `/local/host/provision/changed` carries a session snapshot. One session
|
|
127
125
|
per native Client, and none while a pod session is active; discovery scanning
|
|
128
126
|
pauses during either. Rejected requests use the error envelope and the stable
|
|
129
127
|
`details.reason` values of `pod-commissioning-v1.md` section 7. The session is
|
|
130
|
-
owned
|
|
131
|
-
|
|
128
|
+
owned by the native core until success, failure or the session deadline.
|
|
129
|
+
There is no cancellation or renewal endpoint; leaving the UI does not end it.
|
|
132
130
|
|
|
133
131
|
Session states, in order: `connecting`, `awaiting_code`, `securing`,
|
|
134
132
|
`reading_info`, `awaiting_wifi`, `joining_wifi`, `completed`; terminal `failed`,
|
|
135
|
-
`
|
|
133
|
+
`timed_out`. `completed` carries `host`, the reported `addresses`
|
|
136
134
|
(IPv4 only, possibly empty) and `claimToken` from the `finish` response; the
|
|
137
135
|
commissioner sends `finish` (up to 3 times while the secure session lasts)
|
|
138
136
|
before reporting it. `claimToken` is absent when `finish` could not be
|
|
@@ -8,7 +8,8 @@ call the `/local/pod/*` targets of their native Client.
|
|
|
8
8
|
|
|
9
9
|
Commissioning order is fixed: secure BLE session, Wi-Fi joined, user
|
|
10
10
|
authorization, credential issue, delivery, activation. A credential is issued only
|
|
11
|
-
after the pod reports a joined network.
|
|
11
|
+
after the pod reports a joined network. Failed setup releases the connection;
|
|
12
|
+
pending cloud credentials expire, and a fresh successful claim cleans up old credentials.
|
|
12
13
|
|
|
13
14
|
## 1. Device identity
|
|
14
15
|
|
|
@@ -24,7 +25,7 @@ after the pod reports a joined network. Any failure after issue revokes it.
|
|
|
24
25
|
## 2. BLE advertising
|
|
25
26
|
|
|
26
27
|
Pods advertise only while unprovisioned, while re-commissioning after logout or
|
|
27
|
-
|
|
28
|
+
credential invalidation, or inside a re-provision window. A commissioned pod does not advertise.
|
|
28
29
|
|
|
29
30
|
- Service UUID (128-bit, shared by every MeowLink commissionable device):
|
|
30
31
|
`a17a7ad5-9b2f-4010-9cf0-aa15ac54c40e`.
|
|
@@ -157,7 +158,7 @@ unprovisioned ──connect──▶ session_open ──handshake──▶ secur
|
|
|
157
158
|
secured ──prov-config apply──▶ wifi_joining ──▶ wifi_connected | wifi_failed
|
|
158
159
|
wifi_failed ──retry──▶ wifi_joining
|
|
159
160
|
wifi_connected ──deliver──▶ activating ──time sync, refresh, commit──▶ commissioned | failed
|
|
160
|
-
any pre-commit state ──timeout/disconnect
|
|
161
|
+
any pre-commit state ──timeout/disconnect──▶ unprovisioned
|
|
161
162
|
```
|
|
162
163
|
|
|
163
164
|
Runtime states after commit:
|
|
@@ -176,8 +177,9 @@ Runtime states after commit:
|
|
|
176
177
|
- `needs_recommission`: logout, or refresh rejected because the credential was
|
|
177
178
|
revoked or the user no longer exists. Credential and local JWTs are erased,
|
|
178
179
|
Wi-Fi is kept, advertising resumes with the Wi-Fi-configured flag.
|
|
179
|
-
- `factory_resetting`:
|
|
180
|
-
|
|
180
|
+
- `factory_resetting`: purely offline, erase all persisted data including the
|
|
181
|
+
identity key and cached Hub tokens, reboot to `unprovisioned`. No cloud
|
|
182
|
+
request is needed. Logout also clears local credentials without cloud revocation.
|
|
181
183
|
|
|
182
184
|
Time sync uses SNTP; if NTP is unreachable the pod may use the `Date` header of a
|
|
183
185
|
Lion HTTPS response. Activation proofs require a synced clock.
|
|
@@ -227,7 +229,7 @@ claims `iss` and `sub` = `podId`, a single-valued `aud` = `pod-token-refresh`,
|
|
|
227
229
|
proof can be accepted; a reused `jti` in that window fails with
|
|
228
230
|
`pod_proof_replayed`.
|
|
229
231
|
|
|
230
|
-
|
|
232
|
+
Before the first successful refresh moves `pending` to `active`, Lion deletes every other
|
|
231
233
|
credential with the same `identity.keyId` (whichever user holds it) and the same
|
|
232
234
|
user's other credentials with the same `deviceId`. A `pending` credential past
|
|
233
235
|
`activateBefore` is rejected and deleted. Revoked credentials are deleted, so a
|
|
@@ -241,17 +243,16 @@ later refresh fails with `pod_credential_invalid`. Response
|
|
|
241
243
|
`absent` (schema `schema/pod-credential-status.v1.schema.json`). `absent`
|
|
242
244
|
covers no such credential, revoked, pending past `activateBefore`, and a
|
|
243
245
|
credential owned by another user, so the answer never reveals other users'
|
|
244
|
-
pods. `activatedAt` (epoch ms) is present when `active`.
|
|
245
|
-
|
|
246
|
+
pods. `activatedAt` (epoch ms) is present when `active`. It is informational;
|
|
247
|
+
commissioning success requires the device confirmation described in section 7.
|
|
246
248
|
|
|
247
|
-
###
|
|
249
|
+
### Reset and cleanup
|
|
248
250
|
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
Response `{"ok":true}`.
|
|
251
|
+
There is no public Pod credential revocation endpoint and no App action that
|
|
252
|
+
withdraws a Pod's access without contacting the device. Factory reset executes
|
|
253
|
+
on the Pod itself. Remote reset, when provided, must reach an online Pod; a
|
|
254
|
+
cloud-side deletion is not a successful reset. This contract currently exposes
|
|
255
|
+
no remote reset target. Each setup creates a new Pod credential.
|
|
255
256
|
|
|
256
257
|
### List and rename
|
|
257
258
|
|
|
@@ -284,15 +285,9 @@ and unexpired pending pods, each
|
|
|
284
285
|
- `/api/v1/hub/token/exchange` with a pod access token returns a Hub JWT with
|
|
285
286
|
`clientKind` = `pod` and `podId` claims and the same lifetime as a Hub JWT
|
|
286
287
|
for a user token.
|
|
287
|
-
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
notifies the Hub through the pull-sync contract. A Hub that is offline pulls
|
|
291
|
-
the marker when its bridge reconnects. `scope.pods` is a snapshot
|
|
292
|
-
`{"podIds":[…]}` of the active pods of the Space's members. The Hub revokes
|
|
293
|
-
the local tokens it issued to any other pod before the pull, disables the
|
|
294
|
-
local auth of that pod's app client once no active token is left, and refuses
|
|
295
|
-
and stops renewing that pod's local connections.
|
|
288
|
+
- Pod and ordinary Client local Hub JWTs have the same 100-year lifetime
|
|
289
|
+
(100 * 365 days). There is no per-Pod Hub revocation list or cloud-to-Hub
|
|
290
|
+
revocation sync. Local tokens are cleared on the Pod by reset/logout.
|
|
296
291
|
|
|
297
292
|
## 6. Pod runtime authentication
|
|
298
293
|
|
|
@@ -358,8 +353,6 @@ never show these values or `message` verbatim.
|
|
|
358
353
|
| `/local/pod/commission/wifi` | `{"sessionId","ssid","password"?}` | session snapshot |
|
|
359
354
|
| `/local/pod/commission/wifi/scan` | `{"sessionId"}` | session snapshot |
|
|
360
355
|
| `/local/pod/commission/authorize` | `{"sessionId","scopeId"}` | session snapshot |
|
|
361
|
-
| `/local/pod/commission/cancel` | `{"sessionId"}` | session snapshot |
|
|
362
|
-
| `/local/pod/commission/renew` | `{"sessionId"}` | session snapshot |
|
|
363
356
|
| `/local/pod/commission/status` | `{}` | `{"session": snapshot or null}` |
|
|
364
357
|
| `/local/pod/bluetooth/settings` | `{}` | `{"opened"}` |
|
|
365
358
|
|
|
@@ -381,10 +374,10 @@ UIs reconcile with `status` and discovery `list` on start, resume, reconnect and
|
|
|
381
374
|
when they become visible, and a snapshot with a lower `revision` than one
|
|
382
375
|
already seen for the same session is stale.
|
|
383
376
|
|
|
384
|
-
The
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
377
|
+
The native core owns the session until success or failure, bounded by
|
|
378
|
+
`expiresAtMs`. There is no user cancellation or session renewal. Leaving the
|
|
379
|
+
page does not end setup; returning to it reads `status`. Waiting for user input
|
|
380
|
+
also counts toward the deadline. Discovery leases still control scanning.
|
|
388
381
|
|
|
389
382
|
Sign-in and Spaces are checked at `start` (`not_signed_in`,
|
|
390
383
|
`scope_not_offered`) and again when the authorization prompt is built.
|
|
@@ -403,7 +396,7 @@ pod's Wi-Fi rather than adding a pod.
|
|
|
403
396
|
Session states, in order: `connecting`, `awaiting_code`, `securing`,
|
|
404
397
|
`reading_info`, `awaiting_wifi`, `joining_wifi`, `awaiting_authorization`,
|
|
405
398
|
`issuing`, `delivering`, `activating`, `completed`; terminal `failed`,
|
|
406
|
-
`
|
|
399
|
+
`timed_out`. Wi-Fi states are skipped when the pod reports a
|
|
407
400
|
configured network and `prov-config` status reports it connected; while that
|
|
408
401
|
status is `connecting` the commissioner keeps polling, and only after a failure
|
|
409
402
|
does it reset Wi-Fi (`prov-ctrl`) and offer new credentials. The commissioner
|
|
@@ -413,18 +406,15 @@ scan runs waits for it. `revision` increases on every observable change.
|
|
|
413
406
|
`expiresAtMs` is 10 minutes after `start` until delivery starts; from
|
|
414
407
|
`delivering` on it is `activateBefore` plus 30 seconds.
|
|
415
408
|
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
- `pending`: ask again every 5 seconds until `activateBefore` plus 30 seconds,
|
|
422
|
-
then revoke and fail with `activation_failed`.
|
|
423
|
-
- `absent`: fail with `activation_failed`.
|
|
409
|
+
Only the device's durable `commissioned` response confirms successful setup.
|
|
410
|
+
Lost BLE delivery confirmation or activation status fails the attempt, even
|
|
411
|
+
when Lion has already activated its credential. Expiry fails or times out the
|
|
412
|
+
attempt. The commissioner does not recover interrupted setup through Lion's
|
|
413
|
+
credential status. The user resets the device and starts a fresh attempt.
|
|
424
414
|
|
|
425
415
|
A refused `deliver` fails with `delivery_failed` carrying the pod's `reason`
|
|
426
|
-
(`invalid_payload` or `wrong_state`) in `detail
|
|
427
|
-
itself reports `failed`, the commissioner
|
|
416
|
+
(`invalid_payload` or `wrong_state`) in `detail`. When the pod
|
|
417
|
+
itself reports `failed`, the commissioner fails with
|
|
428
418
|
`activation_failed` carrying the pod's code. `activation_failed` without a pod
|
|
429
419
|
code carries `not_activated`. The commissioner records `completed` before
|
|
430
420
|
sending `finish`. Native Clients keep a non-terminal session running while the
|
|
@@ -438,10 +428,9 @@ Session error codes: `bluetooth_unavailable`, `device_busy`, `disconnected`,
|
|
|
438
428
|
`detail`), `session_timeout`. `code_locked` is terminal: the device shows a new
|
|
439
429
|
code once it accepts handshakes again. `failed` and `timed_out` always carry `error`. A rejected
|
|
440
430
|
code returns to `awaiting_code` with `code_rejected`; a failed join returns to
|
|
441
|
-
`awaiting_wifi` with the `wifi_*` code. No other state carries `error`.
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
credential.
|
|
431
|
+
`awaiting_wifi` with the `wifi_*` code. No other state carries `error`. Terminal states release the link and radio
|
|
432
|
+
without revoking credentials. Reset the Pod and start over after an uncertain
|
|
433
|
+
activation outcome; unused pending cloud credentials expire automatically.
|
|
445
434
|
|
|
446
435
|
The schemas are `schema/pod-discovery.v1.schema.json` and
|
|
447
436
|
`schema/pod-commission.v1.schema.json`.
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": "mhome.host-provision.targets.v1",
|
|
3
|
-
"contractVersion": "1.
|
|
3
|
+
"contractVersion": "1.36.0",
|
|
4
4
|
"contract": "contract/host-provisioning-v1.md",
|
|
5
5
|
"localTargets": [
|
|
6
6
|
"/local/host/provision/start",
|
|
7
7
|
"/local/host/provision/code",
|
|
8
8
|
"/local/host/provision/wifi",
|
|
9
9
|
"/local/host/provision/wifi/scan",
|
|
10
|
-
"/local/host/provision/cancel",
|
|
11
|
-
"/local/host/provision/renew",
|
|
12
10
|
"/local/host/provision/status"
|
|
13
11
|
],
|
|
14
12
|
"eventTargets": [
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": "mhome.pod.targets.v1",
|
|
3
|
-
"contractVersion": "1.
|
|
3
|
+
"contractVersion": "1.36.0",
|
|
4
4
|
"contract": "contract/pod-commissioning-v1.md",
|
|
5
5
|
"localTargets": [
|
|
6
6
|
"/local/pod/discovery/start",
|
|
@@ -12,8 +12,6 @@
|
|
|
12
12
|
"/local/pod/commission/wifi",
|
|
13
13
|
"/local/pod/commission/wifi/scan",
|
|
14
14
|
"/local/pod/commission/authorize",
|
|
15
|
-
"/local/pod/commission/cancel",
|
|
16
|
-
"/local/pod/commission/renew",
|
|
17
15
|
"/local/pod/commission/status",
|
|
18
16
|
"/local/pod/bluetooth/settings"
|
|
19
17
|
],
|
|
@@ -63,15 +61,12 @@
|
|
|
63
61
|
},
|
|
64
62
|
"session": {
|
|
65
63
|
"lifetimeMs": 600000,
|
|
66
|
-
"leaseMs": 30000,
|
|
67
|
-
"renewIntervalMs": 10000,
|
|
68
64
|
"activationGraceMs": 30000,
|
|
69
65
|
"credentialStatusPollMs": 5000
|
|
70
66
|
},
|
|
71
67
|
"cloud": {
|
|
72
68
|
"issue": "pod/credential/issue",
|
|
73
69
|
"status": "pod/credential/status",
|
|
74
|
-
"revoke": "pod/credential/revoke",
|
|
75
70
|
"statusSchema": "schema/pod-credential-status.v1.schema.json"
|
|
76
71
|
},
|
|
77
72
|
"activationErrorCodes": [
|
package/manifest/routing.v1.json
CHANGED
package/manifest/targets.v1.json
CHANGED
package/package.json
CHANGED
package/protocol.json
CHANGED