@mhome/core-protocol 1.51.0 → 1.52.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.
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Node release metadata
|
|
2
|
+
|
|
3
|
+
`POST /node/metadata` with `{}` is available over commissioning HTTPS and the
|
|
4
|
+
existing authenticated Node request transport. It returns `NodeMetadata` under
|
|
5
|
+
`schema/node-metadata.v1.schema.json`. It does not start a business runtime.
|
|
6
|
+
|
|
7
|
+
Delivery describes ownership, independently of `kind` (`core` or `extension`):
|
|
8
|
+
|
|
9
|
+
- `host`: the SDK asks its local Host for the actual installed release manifest.
|
|
10
|
+
The Host returns persisted installation evidence, never the latest catalog.
|
|
11
|
+
The SDK checks node type, service ID and version against its running process.
|
|
12
|
+
- `firmware`: a dedicated implementation embeds its publisher-signed definition
|
|
13
|
+
and version in the binary. Updates replace it with the firmware/application.
|
|
14
|
+
A single-service firmware can use its firmware version as `serviceVersion`.
|
|
15
|
+
This requires no Host installation or separately incremented version counter.
|
|
16
|
+
|
|
17
|
+
An Android Node bundled through an AAR uses `firmware` delivery even on a
|
|
18
|
+
general-purpose phone: the AAR is an App build dependency, and the running Node
|
|
19
|
+
reports its embedded AAR release version. Publishing a new AAR does not update an
|
|
20
|
+
installed App. This classification describes the update owner, not the hardware
|
|
21
|
+
category or whether the Plugin is `core` or `extension`.
|
|
22
|
+
|
|
23
|
+
The response carries exact signed manifest bytes and the detached Minisign
|
|
24
|
+
signature. Host manifests use `meow.plugin.manifest[-bundle]`; embedded releases
|
|
25
|
+
use `meow.node.firmware-manifest[-bundle]`, with `platform`, `pluginId`,
|
|
26
|
+
`componentId`, `version`, `nodeMetadata.plugin` and `compatibility` at the payload
|
|
27
|
+
root. Host release components retain their normal package manifest structure.
|
|
28
|
+
|
|
29
|
+
Core verifies environment-scoped publisher trust, schema, definition, runtime
|
|
30
|
+
identity and version. A Node cannot choose its own trust key. `core` definitions
|
|
31
|
+
must match Core's private protocol revision; `extension` has no private protocol.
|
|
32
|
+
The immutable identity consists of id, nodeType, serviceId, componentId, kind and
|
|
33
|
+
bindingCardinality, consistent across versions, platforms and delivery forms.
|
|
34
|
+
Display strings can change. The catalog is not a binding authority.
|
|
35
|
+
|
|
36
|
+
The signed onboarding challenge includes `serviceVersion` and `manifestSha256`
|
|
37
|
+
(SHA-256 of the exact signed manifest UTF-8 bytes). The token-issue request carries
|
|
38
|
+
`metadata`; Core compares its verified version/hash to the challenge. Fetching
|
|
39
|
+
metadata before a challenge is a browsing hint only. Token-bearing commissioning
|
|
40
|
+
requests still require the challenge-proven TLS key.
|
|
41
|
+
|
|
42
|
+
Core persists `NodeBindingMetadata` with each binding for offline management.
|
|
43
|
+
Every `/node/auth` request includes required `metadata` for the running release.
|
|
44
|
+
Core authenticates the token and binding first, then verifies the publisher
|
|
45
|
+
signature, stable identity, runtime version and private protocol compatibility.
|
|
46
|
+
Only then may it activate the token and return `ok: true`. Release validation
|
|
47
|
+
failure rejects the connection without revoking the binding or requesting
|
|
48
|
+
`CLEAR_LOCAL_IDENTITY`. No catalog/network lookup is part of authentication.
|
|
49
|
+
|
|
50
|
+
A successful auth response includes `bindingMetadata` and the accepted optional
|
|
51
|
+
`coreProtocolVersion`. Transports check this acknowledgement against the requested
|
|
52
|
+
release (including its manifest hash), then carry that exact snapshot into
|
|
53
|
+
connection registration. Each connection retains its own immutable snapshot;
|
|
54
|
+
a concurrent reconnect changing persisted metadata cannot change an existing
|
|
55
|
+
connection's admitted version. Persisted metadata is written only when changed.
|
|
56
|
+
There is no fingerprint negotiation, signature cache or second readiness handshake.
|
|
57
|
+
|
|
58
|
+
After authentication Core loads `/<nodeType>/describe` for that connection's App
|
|
59
|
+
access policy. Its schema, node type, service ID and version must agree with the
|
|
60
|
+
admitted release. App operations wait for a valid policy; normal Node operations
|
|
61
|
+
can start after auth. A failed description closes the connection. Core does not
|
|
62
|
+
pull `/node/metadata` again after auth. The metadata endpoint remains available
|
|
63
|
+
for commissioning. No legacy static registry or inferred cardinality is permitted.
|
|
64
|
+
|
|
65
|
+
The complete serialized authentication envelope must fit the peer's transport
|
|
66
|
+
limit, including JSON escaping of the nested manifest and MWS payload. Native
|
|
67
|
+
MWS allows 2 MiB; firmware may impose a smaller limit (ESP uses 32 KiB). SDK and
|
|
68
|
+
firmware reject oversized auth frames before sending them. Publisher metadata
|
|
69
|
+
proves release identity and compatibility, not remote binary attestation;
|
|
70
|
+
installed package integrity remains the installation chain's responsibility.
|
|
71
|
+
|
|
72
|
+
Manifest bytes are bounded to 1 MiB, signatures to 4 KiB. No publisher secret or
|
|
73
|
+
account credential is included. Existing databases require explicit rebuilding
|
|
74
|
+
when the baseline binding snapshot column is introduced; startup does not migrate
|
|
75
|
+
or erase data.
|
|
@@ -1,19 +1,20 @@
|
|
|
1
1
|
[
|
|
2
2
|
{"target":"/app/widget/list","payload":{},"operation":"coreRequest","totalMs":60000},
|
|
3
3
|
{"target":"/harness/test/session/open","payload":{},"operation":"harnessSessionOpen","totalMs":150000},
|
|
4
|
-
{"target":"/app/automation/save","payload":{"input":{"script":{"scripts":{"lighting":"source"}}}},"operation":"scriptSave","totalMs":
|
|
4
|
+
{"target":"/app/automation/save","payload":{"input":{"script":{"scripts":{"lighting":"source"}}}},"operation":"scriptSave","totalMs":60000,"lionWaitMs":90000},
|
|
5
5
|
{"target":"/app/automation/verify","payload":{"input":{"script":{"scripts":{"lighting":"source"}}}},"operation":"scriptValidation","totalMs":205000,"lionWaitMs":230000},
|
|
6
|
-
{"target":"/automation/save","payload":{"script":{"scripts":{"lighting":"source"}}},"operation":"scriptSave","totalMs":
|
|
7
|
-
{"target":"/invoke/app/automation/save","payload":{"call":{"input":{"script":{"scripts":{"lighting":"source"}}}}},"operation":"scriptSave","totalMs":
|
|
6
|
+
{"target":"/automation/save","payload":{"script":{"scripts":{"lighting":"source"}}},"operation":"scriptSave","totalMs":60000},
|
|
7
|
+
{"target":"/invoke/app/automation/save","payload":{"call":{"input":{"script":{"scripts":{"lighting":"source"}}}}},"operation":"scriptSave","totalMs":60000},
|
|
8
8
|
{"target":"/dispatch/agent/app/automation/verify","payload":{"call":{"input":{"script":{"scripts":{"lighting":"source"}}}}},"operation":"scriptValidation","totalMs":205000},
|
|
9
|
-
{"target":"/dispatch/app/automation/save","payload":{"call":{"input":{"script":{"scripts":{"lighting":"source"}}}}},"operation":"scriptSave","totalMs":
|
|
9
|
+
{"target":"/dispatch/app/automation/save","payload":{"call":{"input":{"script":{"scripts":{"lighting":"source"}}}}},"operation":"scriptSave","totalMs":60000},
|
|
10
10
|
{"target":"/app/automation/save","payload":{"input":{"script":{"scripts":{}}}},"operation":"coreRequest","totalMs":60000},
|
|
11
11
|
{"target":"/app/automation/save","payload":{"script":{"scripts":{"lighting":"source"}}},"operation":"coreRequest","totalMs":60000},
|
|
12
12
|
{"target":"/app/automation/save","payload":{"input":{"script":{"scripts":[]}}},"operation":"coreRequest","totalMs":60000},
|
|
13
|
-
{"target":"/
|
|
14
|
-
{"target":"/automation/
|
|
15
|
-
{"target":"/automation/
|
|
16
|
-
{"target":"/automation/
|
|
13
|
+
{"target":"/automation/snapshot/rollback","payload":{},"operation":"scriptSave","totalMs":60000},
|
|
14
|
+
{"target":"/app/automation/snapshot/rollback","payload":{},"operation":"scriptSave","totalMs":60000},
|
|
15
|
+
{"target":"/automation/copy","payload":{},"operation":"scriptSave","totalMs":60000},
|
|
16
|
+
{"target":"/automation/enroll","payload":{},"operation":"scriptSave","totalMs":60000},
|
|
17
|
+
{"target":"/automation/overview/save","payload":{},"operation":"scriptSave","totalMs":60000},
|
|
17
18
|
{"target":"/bridge/automation/compile","payload":{"script":{"scripts":{"lighting":"source"}}},"operation":"scriptValidation","totalMs":205000},
|
|
18
19
|
{"target":"/app/integration/entity/refresh","payload":{},"operation":"entityRefresh","totalMs":85000,"lionWaitMs":90000},
|
|
19
20
|
{"target":"/invoke/app/integration/entity/refresh","payload":{},"operation":"entityRefresh","totalMs":85000,"lionWaitMs":90000},
|
package/manifest/core.v1.json
CHANGED
|
@@ -2,10 +2,11 @@
|
|
|
2
2
|
"manifest": "mhome.operation-timeouts.v1",
|
|
3
3
|
"operations": {
|
|
4
4
|
"coreRequest": { "totalMs": 60000, "description": "Default Core request execution." },
|
|
5
|
+
"eventProcessing": { "totalMs": 60000, "description": "One Automation event delivery and its execution slice, including admission and preparation; durable waits are separate." },
|
|
5
6
|
"entityRefresh": { "totalMs": 85000, "description": "Integration entity refresh including source loading and response preparation." },
|
|
6
7
|
"harnessSessionOpen": { "totalMs": 150000, "description": "Harness session initialization." },
|
|
7
8
|
"scriptValidation": { "totalMs": 205000, "description": "Companion Rust build and validation." },
|
|
8
|
-
"scriptSave": { "totalMs":
|
|
9
|
+
"scriptSave": { "totalMs": 60000, "description": "Automation save or rollback, including companion Rust build and installation." },
|
|
9
10
|
"coreBridgeRequest": { "totalMs": 35000, "description": "Core outgoing cloud request, including sending." },
|
|
10
11
|
"coreBridgeInbound": { "totalMs": 55000, "description": "Ordinary incoming Core Bridge request, including queueing." },
|
|
11
12
|
"nodeRequest": { "totalMs": 60000, "description": "Core outgoing Node request, including sending." },
|
package/package.json
CHANGED
package/protocol.json
CHANGED
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://json-schema.org/draft/2020-12/schema",
|
|
3
|
+
"type": "object",
|
|
4
|
+
"additionalProperties": false,
|
|
5
|
+
"required": [
|
|
6
|
+
"schemaVersion",
|
|
7
|
+
"delivery",
|
|
8
|
+
"nodeType",
|
|
9
|
+
"serviceId",
|
|
10
|
+
"serviceVersion",
|
|
11
|
+
"releaseManifest"
|
|
12
|
+
],
|
|
13
|
+
"properties": {
|
|
14
|
+
"schemaVersion": {
|
|
15
|
+
"const": "meow.node.metadata.v1"
|
|
16
|
+
},
|
|
17
|
+
"delivery": {
|
|
18
|
+
"enum": [
|
|
19
|
+
"host",
|
|
20
|
+
"firmware"
|
|
21
|
+
]
|
|
22
|
+
},
|
|
23
|
+
"nodeType": {
|
|
24
|
+
"type": "string",
|
|
25
|
+
"minLength": 1
|
|
26
|
+
},
|
|
27
|
+
"serviceId": {
|
|
28
|
+
"type": "string",
|
|
29
|
+
"minLength": 1
|
|
30
|
+
},
|
|
31
|
+
"serviceVersion": {
|
|
32
|
+
"type": "string",
|
|
33
|
+
"minLength": 1
|
|
34
|
+
},
|
|
35
|
+
"releaseManifest": {
|
|
36
|
+
"type": "object",
|
|
37
|
+
"additionalProperties": false,
|
|
38
|
+
"required": [
|
|
39
|
+
"schemaVersion",
|
|
40
|
+
"kind",
|
|
41
|
+
"manifest",
|
|
42
|
+
"signature"
|
|
43
|
+
],
|
|
44
|
+
"properties": {
|
|
45
|
+
"schemaVersion": {
|
|
46
|
+
"const": 1
|
|
47
|
+
},
|
|
48
|
+
"kind": {
|
|
49
|
+
"enum": [
|
|
50
|
+
"meow.plugin.manifest-bundle",
|
|
51
|
+
"meow.node.firmware-manifest-bundle"
|
|
52
|
+
]
|
|
53
|
+
},
|
|
54
|
+
"manifest": {
|
|
55
|
+
"type": "string",
|
|
56
|
+
"minLength": 1
|
|
57
|
+
},
|
|
58
|
+
"signature": {
|
|
59
|
+
"type": "string",
|
|
60
|
+
"minLength": 1
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
}
|