fix(protocol): align quality ack schema
Verify Protocol / module (push) Successful in 1m21s
Verify Protocol / verify (push) Successful in 1m2s

This commit is contained in:
sechmachine
2026-08-13 07:53:35 +07:00
parent 6e18bc9ee6
commit c3ea2f35c6
7 changed files with 51 additions and 7 deletions
+40 -2
View File
@@ -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