feat(connect): add device identity store and registration proof (#6267)

This commit is contained in:
Zhengchao An
2026-08-20 03:32:59 +08:00
committed by GitHub
parent 898aa4db95
commit c10d74c78b
49 changed files with 7372 additions and 0 deletions
@@ -0,0 +1,3 @@
610eeaf44cb7a9a4ed2e4f076c2aec6050a5b81e873fa5c97845155b7ee727a2 additive-compatibility.json
3c9453cdbb34557d08ac63a1e2d7024870c8794e7d0cdc48c3a7fdfd2fa8b15f field-registry.json
3c7fe86634b7c85da87865498a6677968a78fad1be6d69ed5b3607c29d47430e negotiation-vectors.json
@@ -0,0 +1,104 @@
{
"protocolVersion": "v1",
"fixtureSet": "version",
"fixture": "additive-compatibility",
"description": "Release skew in both directions. v1 grows by optional fields only, so an unknown field is discarded and an absent one takes its documented default.",
"vectors": [
{
"name": "new agent sends a v1 field this Connect does not know",
"direction": "new-agent-to-old-connect",
"payload": {
"protocolVersion": "v1",
"agentVersion": "1.9.0",
"capabilities": ["heartbeat"],
"telemetryProfile": "extended"
},
"expected": {
"decision": "ACCEPT",
"retained": ["protocolVersion", "agentVersion", "capabilities"],
"discarded": ["telemetryProfile"],
"defaultsApplied": {},
"echoedBack": [],
"stored": []
}
},
{
"name": "new agent sends several unknown optional fields at once",
"direction": "new-agent-to-old-connect",
"payload": {
"protocolVersion": "v1",
"capabilities": ["heartbeat", "inventory", "bundle.upload"],
"telemetryProfile": "extended",
"regionHint": "eu-west",
"experimentalFlags": {
"fastHeartbeat": true
}
},
"expected": {
"decision": "ACCEPT",
"retained": ["protocolVersion", "capabilities"],
"discarded": ["telemetryProfile", "regionHint", "experimentalFlags"],
"defaultsApplied": {
"agentVersion": null
},
"echoedBack": [],
"stored": []
}
},
{
"name": "old agent omits every optional field",
"direction": "old-agent-to-new-connect",
"payload": {
"protocolVersion": "v1"
},
"expected": {
"decision": "ACCEPT",
"retained": ["protocolVersion"],
"discarded": [],
"defaultsApplied": {
"agentVersion": null,
"capabilities": []
},
"echoedBack": [],
"stored": []
}
},
{
"name": "old agent reports no capabilities but names itself",
"direction": "old-agent-to-new-connect",
"payload": {
"protocolVersion": "v1",
"agentVersion": "1.0.0"
},
"expected": {
"decision": "ACCEPT",
"retained": ["protocolVersion", "agentVersion"],
"discarded": [],
"defaultsApplied": {
"capabilities": []
},
"echoedBack": [],
"stored": []
}
},
{
"name": "unknown fields do not rescue an unsupported major version",
"direction": "new-agent-to-old-connect",
"payload": {
"protocolVersion": "v2",
"agentVersion": "2.0.0",
"compatibilityShim": "v1"
},
"expected": {
"decision": "REJECT",
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400,
"retained": [],
"discarded": [],
"defaultsApplied": {},
"echoedBack": [],
"stored": []
}
}
]
}
@@ -0,0 +1,34 @@
{
"protocolVersion": "v1",
"fixtureSet": "version",
"fixture": "field-registry",
"description": "The frozen v1 negotiation envelope. Registration and heartbeat both carry it. Any top-level field not listed here is unknown and is discarded after acceptance.",
"envelope": "AgentProtocolNegotiation",
"supportedMajorVersions": [1],
"protocolVersionPattern": "^v[1-9][0-9]{0,3}$",
"unknownFieldPolicy": "accept-and-discard",
"unknownCapabilityPolicy": "discard",
"fields": [
{
"name": "protocolVersion",
"requiredness": "required",
"type": "string",
"default": null,
"note": "Major version only. The minor and patch level of an agent is not negotiated."
},
{
"name": "agentVersion",
"requiredness": "optional",
"type": "string",
"default": null,
"note": "Informational. Connect never compares it for equality with its own version and never gates behavior on it."
},
{
"name": "capabilities",
"requiredness": "optional",
"type": "array",
"default": [],
"note": "Unordered token set. A capability an operation requires but the device did not report fails that operation with a structured result, not the connection."
}
]
}
@@ -0,0 +1,132 @@
{
"protocolVersion": "v1",
"fixtureSet": "version",
"fixture": "negotiation-vectors",
"description": "Protocol version decisions. A rejected version fails closed: nothing in the payload is processed, stored, or echoed.",
"vectors": [
{
"name": "supported major version",
"request": {
"protocolVersion": "v1",
"agentVersion": "1.4.0",
"capabilities": ["heartbeat", "inventory"]
},
"expected": {
"decision": "ACCEPT",
"negotiatedProtocolVersion": "v1",
"reason": null,
"httpStatus": null
}
},
{
"name": "supported major version reported by an agent that sends nothing else",
"request": {
"protocolVersion": "v1"
},
"expected": {
"decision": "ACCEPT",
"negotiatedProtocolVersion": "v1",
"reason": null,
"httpStatus": null
}
},
{
"name": "next major version from a future agent",
"request": {
"protocolVersion": "v2",
"agentVersion": "2.0.0",
"capabilities": ["heartbeat"]
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
},
{
"name": "far future major version",
"request": {
"protocolVersion": "v9999"
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
},
{
"name": "missing protocol version",
"request": {
"agentVersion": "1.4.0"
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
},
{
"name": "version without its prefix",
"request": {
"protocolVersion": "1"
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
},
{
"name": "uppercase prefix",
"request": {
"protocolVersion": "V1"
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
},
{
"name": "dotted version",
"request": {
"protocolVersion": "v1.2"
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
},
{
"name": "zero major version",
"request": {
"protocolVersion": "v0"
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
},
{
"name": "empty protocol version",
"request": {
"protocolVersion": ""
},
"expected": {
"decision": "REJECT",
"negotiatedProtocolVersion": null,
"reason": "UNSUPPORTED_PROTOCOL",
"httpStatus": 400
}
}
]
}