@mhome/app-facade-protocol 1.47.0 → 1.49.1
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 +7 -0
- package/contract/pod-commissioning-v1.md +54 -12
- package/manifest/app-facade.v1.json +9 -3
- package/manifest/host-provision-targets.v1.json +1 -1
- package/manifest/hub-targets.v1.json +1 -1
- package/manifest/pod-targets.v1.json +1 -1
- package/manifest/routing.v1.json +7 -3
- package/manifest/targets.v1.json +1 -1
- package/package.json +1 -1
- package/protocol.json +1 -1
package/README.md
CHANGED
|
@@ -49,6 +49,13 @@ timings and request reasons are in `manifest/pod-targets.v1.json`; snapshots use
|
|
|
49
49
|
`schema/pod-discovery.v1.schema.json` and `schema/pod-commission.v1.schema.json`;
|
|
50
50
|
User Pod enrollment uses a one-time login approval; activation is confirmed on the paired device.
|
|
51
51
|
|
|
52
|
+
`/app/pod/list` reads registered Pod Clients in the active Space, including
|
|
53
|
+
connections that are currently absent. `/app/host/list` reads historical Host
|
|
54
|
+
registrations without granting management access; see the
|
|
55
|
+
[Host directory contract](contract/host-directory-v1.md). Native commissioning
|
|
56
|
+
uses the existing device protocols; the Agent resumes only after verifying the
|
|
57
|
+
resulting registration. Host completion identifies both `hostId` and `env`.
|
|
58
|
+
|
|
52
59
|
`host_provision` (1.34.0) defines BLE Wi-Fi provisioning of embedded Hosts
|
|
53
60
|
(`/local/host/provision/*`) on the same BLE layer; discovery candidates carry
|
|
54
61
|
`kind`. A completed session carries the one-time `claimToken` that the first
|
|
@@ -247,8 +247,15 @@ stores the resulting refresh token, and refresh uses the standard User login
|
|
|
247
247
|
endpoint. A failed attempt is retried with a new approval; no old protocol is
|
|
248
248
|
accepted.
|
|
249
249
|
|
|
250
|
-
`podId` identifies
|
|
251
|
-
|
|
250
|
+
`podId` identifies a single approval attempt, not the durable device or authenticated
|
|
251
|
+
User. The durable `registrationId` derives from the business User and the validated
|
|
252
|
+
persistent device-key fingerprint. `POST /api/v1/pod/list` returns that ID;
|
|
253
|
+
`/api/v1/pod/rename` accepts `{registrationId, name}` with ordinary User login.
|
|
254
|
+
Successful authentication atomically creates the registration if absent and records
|
|
255
|
+
completion on the consumed approval. Retries preserve the initial registration and
|
|
256
|
+
current display name. Unauthenticated attempts create no device-list entry.
|
|
257
|
+
The attempt receipt remains readable for one day after the approval's expiry;
|
|
258
|
+
`expiresAt` still controls its ten-minute, single-use authentication window.
|
|
252
259
|
There is no cloud credential-status polling or server-side Pod revocation flow.
|
|
253
260
|
Factory reset clears device credentials and rotates the pairing identity.
|
|
254
261
|
|
|
@@ -359,7 +366,9 @@ scans for networks once on entering `awaiting_wifi`; a scan request while that
|
|
|
359
366
|
scan runs waits for it. `revision` increases on every observable change.
|
|
360
367
|
|
|
361
368
|
`expiresAtMs` is 10 minutes after `start` until delivery starts; from
|
|
362
|
-
`delivering` on
|
|
369
|
+
`delivering` on, User approval uses `activateBefore` plus 30 seconds; Space delivery
|
|
370
|
+
gets a separate two-minute confirmation deadline. An active Space credential has no
|
|
371
|
+
first-use deadline and never causes immediate completion or an expired attempt.
|
|
363
372
|
|
|
364
373
|
Only the device's durable `commissioned` response confirms successful setup.
|
|
365
374
|
Lost LAN confirmation triggers at most three reconnections to this attempt's
|
|
@@ -398,8 +407,10 @@ The schemas are `schema/pod-discovery.v1.schema.json` and
|
|
|
398
407
|
`Authorization` and `ScopeId`, with the same device identity request as personal
|
|
399
408
|
issuance. Only the current Space owner may assist. The Space must be local and have one
|
|
400
409
|
published Hub with business and Host TLS identities. Cloud Spaces must complete
|
|
401
|
-
Hub setup first. The issuer
|
|
402
|
-
|
|
410
|
+
Hub setup first. The issuer derives `appClientId` from tenant, Space and the validated
|
|
411
|
+
persistent device-key fingerprint. The same device in the same Space retains this
|
|
412
|
+
ID across retries; a factory reset rotates its key. Candidate local JWTs use the
|
|
413
|
+
existing Space signing key and local-client audience.
|
|
403
414
|
|
|
404
415
|
Claims are `token_type: local_space_client_access`, `sub: <scopeId>`,
|
|
405
416
|
`tenant_id`, `scope_id`, `hub_id`, `app_client_id`, `jti`, `iat`, `exp`, `is_test`.
|
|
@@ -410,11 +421,17 @@ Personal Pod issuance no longer stores `issuedScopeId`.
|
|
|
410
421
|
|
|
411
422
|
Lion sends `{jwtToken, clientSource:"pod"}` to the authenticated Hub Bridge
|
|
412
423
|
`/hub/client/space/register`. Core verifies signature, audience, issuer, current
|
|
413
|
-
Hub, environment, Space and canonical installation ID
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
424
|
+
Hub, environment, Space and canonical installation ID. It reuses a valid current
|
|
425
|
+
pending or active credential, or atomically selects a replacement after fresh owner
|
|
426
|
+
authorization. Concurrent issuers receive the selected credential; a stale replacement
|
|
427
|
+
cannot overwrite activation or revocation. Pending reuse retains its original
|
|
428
|
+
first-authentication deadline, ten minutes after JWT issuance. Invalid, revoked,
|
|
429
|
+
expired or differently bound credentials are not reused. Signature/key infrastructure
|
|
430
|
+
failures propagate instead of being interpreted as absence.
|
|
431
|
+
The Bridge returns `{credentialId, appClientId, jwtToken, status, activateBefore}`.
|
|
432
|
+
Lion returns `{credentialId, appClientId, jwtToken, credentialState, activateBefore,
|
|
433
|
+
hubIdentity}`. State is `pending` with its epoch-millisecond first-use deadline, or
|
|
434
|
+
`active` with `activateBefore:null`. Issuance alone does not publish a device-list entry. The Hub identity includes its business P-256 key and
|
|
418
435
|
Host TLS public key, bound to `tenantId`, `scopeId`, `hubId` and `hostId`.
|
|
419
436
|
|
|
420
437
|
The secured LAN `pod-credential` delivery is:
|
|
@@ -430,8 +447,10 @@ bounded to 8192 bytes; BLE credential delivery remains disabled.
|
|
|
430
447
|
|
|
431
448
|
The Pod discovers the matching runtime environment and Space's Hub, pins TLS,
|
|
432
449
|
verifies the signed Hub proof, and authenticates with the local JWT and signed
|
|
433
|
-
`appClientId`. Core atomically activates the
|
|
434
|
-
|
|
450
|
+
`appClientId`. After authentication checks succeed, Core atomically activates the
|
|
451
|
+
credential and publishes the durable AppClient registration. Repeated authentication
|
|
452
|
+
preserves the first activation; later offline or revoked credentials do not erase the
|
|
453
|
+
registration. The Pod requires a Space principal for the same Space, installation and
|
|
435
454
|
credential in the authenticated response, then durably saves the profile. Only
|
|
436
455
|
then does LAN setup report completion. The LAN status field named `podId` is an
|
|
437
456
|
enrollment correlation ID: for Space mode it carries `credentialId`, never the
|
|
@@ -450,3 +469,26 @@ MANAGE, personal resources and Host user administration are rejected. It joins
|
|
|
450
469
|
the canonical Space-client conversation group, never an initializer's threads.
|
|
451
470
|
The billing owner fallback is not an acting identity. Host management tokens are
|
|
452
471
|
independent and are never issued by this flow.
|
|
472
|
+
|
|
473
|
+
## Registered Pod list
|
|
474
|
+
|
|
475
|
+
`/app/pod/list` takes empty input and lists persisted Pod Clients in the current
|
|
476
|
+
Space, including disconnected registrations. A personal caller sees their own
|
|
477
|
+
User Pods and Space-owned Pods. Rows contain `appClientId`, `clientMode`,
|
|
478
|
+
`scopeId`, `registered`, `connected` and `observationSource` (`hub` or `cloud`);
|
|
479
|
+
the envelope includes `observedAtMs`. Connection status is observed from that
|
|
480
|
+
execution endpoint, not a statement about physical power or LAN reachability.
|
|
481
|
+
Native clients combine this result with their own discovery observations.
|
|
482
|
+
Never merge a Bluetooth short ID with a registered identity without proof.
|
|
483
|
+
This read does not issue credentials or change Pod identity.
|
|
484
|
+
|
|
485
|
+
|
|
486
|
+
`appClientId` identifies a registered application client; it is not the enrollment
|
|
487
|
+
`podId` used by native commissioning. The list does not invent that association.
|
|
488
|
+
`/app/pod/enrollment/get` takes `{podId}` and returns `{podId, clientMode: "user",
|
|
489
|
+
registered}` from the authenticated user's successful receipt for that exact attempt.
|
|
490
|
+
An older registration for the same device cannot complete a different attempt.
|
|
491
|
+
`/app/pod/space/enrollment/get` takes the same input and checks the current Space's
|
|
492
|
+
active local credential, returning `clientMode: "space"`; this read requires Space
|
|
493
|
+
MANAGE. A cloud Space has no such local enrollment and returns `registered:false`.
|
|
494
|
+
Both checks are read-only completion hooks. They do not issue or renew credentials.
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": "mhome.app-facade.v1",
|
|
3
|
-
"contractVersion": "1.
|
|
3
|
+
"contractVersion": "1.49.1",
|
|
4
4
|
"callSchema": "schema/facade-call.v1.schema.json",
|
|
5
5
|
"routing": "manifest/routing.v1.json",
|
|
6
6
|
"routingSchema": "schema/routing.v1.schema.json",
|
|
@@ -27,7 +27,12 @@
|
|
|
27
27
|
},
|
|
28
28
|
"pod": {
|
|
29
29
|
"targets": "manifest/pod-targets.v1.json",
|
|
30
|
-
"contract": "contract/pod-commissioning-v1.md"
|
|
30
|
+
"contract": "contract/pod-commissioning-v1.md",
|
|
31
|
+
"listTarget": "/app/pod/list",
|
|
32
|
+
"enrollmentTargets": [
|
|
33
|
+
"/app/pod/enrollment/get",
|
|
34
|
+
"/app/pod/space/enrollment/get"
|
|
35
|
+
]
|
|
31
36
|
},
|
|
32
37
|
"hostProvision": {
|
|
33
38
|
"targets": "manifest/host-provision-targets.v1.json",
|
|
@@ -150,7 +155,8 @@
|
|
|
150
155
|
"issuer": "cloud",
|
|
151
156
|
"firstClaimTransport": "directLanOnly",
|
|
152
157
|
"authorizationTarget": "/app/host/authorization",
|
|
153
|
-
"authorizationSchema": "schema/host-authorization.v1.schema.json"
|
|
158
|
+
"authorizationSchema": "schema/host-authorization.v1.schema.json",
|
|
159
|
+
"listTarget": "/app/host/list"
|
|
154
160
|
},
|
|
155
161
|
"clientAppearance": {
|
|
156
162
|
"schema": "schema/client-appearance.v1.schema.json",
|
package/manifest/routing.v1.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"manifest": "mhome.app-facade.routing.v1",
|
|
3
|
-
"contractVersion": "1.
|
|
3
|
+
"contractVersion": "1.49.1",
|
|
4
4
|
"targetPrefix": "/app/",
|
|
5
5
|
"default": {
|
|
6
6
|
"execution": "scopeMode"
|
|
@@ -31,7 +31,9 @@
|
|
|
31
31
|
"/app/messaging/code/status",
|
|
32
32
|
"/app/messaging/binding/list",
|
|
33
33
|
"/app/messaging/bind/code/create",
|
|
34
|
-
"/app/messaging/unbind"
|
|
34
|
+
"/app/messaging/unbind",
|
|
35
|
+
"/app/host/list",
|
|
36
|
+
"/app/pod/enrollment/get"
|
|
35
37
|
],
|
|
36
38
|
"scopeModeTargets": [
|
|
37
39
|
"/app/artifact/resolve",
|
|
@@ -43,7 +45,9 @@
|
|
|
43
45
|
"/app/artifact/upload/complete",
|
|
44
46
|
"/app/artifact/upload/cancel",
|
|
45
47
|
"/app/system/instances/get",
|
|
46
|
-
"/app/system/clients/get"
|
|
48
|
+
"/app/system/clients/get",
|
|
49
|
+
"/app/pod/list",
|
|
50
|
+
"/app/pod/space/enrollment/get"
|
|
47
51
|
],
|
|
48
52
|
"hubPrefixes": [
|
|
49
53
|
"/app/plugin/",
|
package/manifest/targets.v1.json
CHANGED
package/package.json
CHANGED