fix(protocol): align quality ack schema
This commit is contained in:
+40
-2
@@ -12,6 +12,17 @@ import sys
|
||||
ROOT = pathlib.Path(__file__).resolve().parents[1]
|
||||
|
||||
|
||||
def matches_outcome_branch(instance: dict[str, object], branch: dict[str, object]) -> bool:
|
||||
required = branch.get("required", [])
|
||||
if not all(field in instance for field in required):
|
||||
return False
|
||||
outcome = branch.get("properties", {}).get("outcome", {}).get("const")
|
||||
if instance.get("outcome") != outcome:
|
||||
return False
|
||||
forbidden = branch.get("not", {}).get("required", [])
|
||||
return not all(field in instance for field in forbidden) if forbidden else True
|
||||
|
||||
|
||||
def main() -> int:
|
||||
schema_path = ROOT / "schemas/control-v1.schema.json"
|
||||
schema = json.loads(schema_path.read_text(encoding="utf-8"))
|
||||
@@ -59,8 +70,32 @@ def main() -> int:
|
||||
assert quality_request["properties"]["lease_generation"]["minimum"] == 1
|
||||
assert defs["GatewayStopWorkRequest"]["required"] == ["version", "session_id", "gateway_id", "reconnect_sequence", "acquisition"]
|
||||
assert defs["GatewayQualityWork"]["required"][-3:] == ["lease_generation", "lease_expires_at", "selected_descriptor"]
|
||||
assert defs["GatewayQualityAck"]["required"][-3:] == ["revision", "lease_generation", "outcome"]
|
||||
assert defs["GatewayQualityAck"]["properties"]["outcome"]["enum"] == ["applied", "proven_prior", "unknown"]
|
||||
quality_ack = defs["GatewayQualityAck"]
|
||||
assert quality_ack["required"][-3:] == ["revision", "lease_generation", "outcome"]
|
||||
assert quality_ack["properties"]["outcome"]["enum"] == ["applied", "proven_prior", "unknown"]
|
||||
assert quality_ack["description"] == (
|
||||
"Outcome invariants: applied requires current_applied_revision equal to revision; "
|
||||
"proven_prior requires current_applied_revision strictly less than revision; "
|
||||
"unknown forbids current_applied_revision and makes no applied-revision assertion."
|
||||
)
|
||||
assert quality_ack["oneOf"] == [
|
||||
{"properties": {"outcome": {"const": "applied"}}, "required": ["current_applied_revision"]},
|
||||
{"properties": {"outcome": {"const": "proven_prior"}}, "required": ["current_applied_revision"]},
|
||||
{"properties": {"outcome": {"const": "unknown"}}, "not": {"required": ["current_applied_revision"]}},
|
||||
]
|
||||
ack_branches = quality_ack["oneOf"]
|
||||
for valid_ack in (
|
||||
{"outcome": "applied", "current_applied_revision": 7},
|
||||
{"outcome": "proven_prior", "current_applied_revision": 6},
|
||||
{"outcome": "unknown"},
|
||||
):
|
||||
assert sum(matches_outcome_branch(valid_ack, branch) for branch in ack_branches) == 1, valid_ack
|
||||
for invalid_ack in (
|
||||
{"outcome": "applied"},
|
||||
{"outcome": "proven_prior"},
|
||||
{"outcome": "unknown", "current_applied_revision": 6},
|
||||
):
|
||||
assert not any(matches_outcome_branch(invalid_ack, branch) for branch in ack_branches), invalid_ack
|
||||
|
||||
operation_id_pattern = r"^(?!00000000-0000-0000-0000-000000000000$)[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$"
|
||||
canonical_time_pattern = r"^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}(?:\.[0-9]{0,8}[1-9])?Z$"
|
||||
@@ -235,6 +270,9 @@ def main() -> int:
|
||||
assert "coordinates MUST match exactly" in quality_acquisition
|
||||
quality_acknowledgement = openapi.split(" operationId: acknowledgeGatewayQualityWork\n", 1)[1].split(" responses:\n", 1)[0]
|
||||
assert "Stale lease generations MUST be rejected" in quality_acknowledgement
|
||||
assert "`applied` requires `current_applied_revision == revision`" in quality_acknowledgement
|
||||
assert "`proven_prior` requires `current_applied_revision < revision`" in quality_acknowledgement
|
||||
assert "`unknown` forbids `current_applied_revision`" in quality_acknowledgement
|
||||
for operation_id in ("createSessionQualityChange", "getSessionQualityChange", "createSessionStopOperation", "getSessionStopOperation"):
|
||||
operation = openapi.split(f" operationId: {operation_id}\n", 1)[1].split(" responses:\n", 1)[0]
|
||||
assert "owning principal and active device/key" in operation, operation_id
|
||||
|
||||
Reference in New Issue
Block a user