From d83ce2dd427244f088e3b31a7aedae330c260858 Mon Sep 17 00:00:00 2001 From: William Webster Date: Mon, 29 Jun 2026 11:33:05 -0400 Subject: [PATCH 1/2] fix(schema): add case management kinds to envelope.schema.json kind enum validate_authored_envelope() rejected CaseNotificationGroup, CaseSla, and CaseTemplate because the JSON Schema kind enum was never updated when those kinds were added to KIND_TO_TYPE in v0.5.8. The Python provider registry and template discovery were correct; only the schema validator was stale. Adds a drift-guard test (test_schema_kind_enum_matches_kind_to_type) that asserts schema enum == KIND_TO_TYPE.keys() so the two cannot diverge again. --- CHANGELOG.md | 15 ++++++++++++++ src/talonctl/schemas/envelope.schema.json | 2 +- tests/unit/test_envelope_validation.py | 24 +++++++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 32ce78c..deacaad 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,21 @@ ## [Unreleased] +## v0.5.9 — hotfix: accept case management kinds in schema validator + +### Fixed + +- **`talonctl validate` now accepts `CaseNotificationGroup`, `CaseSla`, and + `CaseTemplate` envelopes.** The JSON Schema enum in + `schemas/envelope.schema.json` was never updated when the three case kinds + were added to `KIND_TO_TYPE`, causing `validate_authored_envelope()` to + reject all case management templates with an "is not one of" error. The + Python code (provider registry, template discovery, `VALID_KINDS`) was + correct; only the JSON Schema enum was stale. +- **Drift-guard test added** (`test_schema_kind_enum_matches_kind_to_type`) + that asserts the schema's kind enum exactly matches `KIND_TO_TYPE.keys()`, + so the two sources of truth cannot diverge again. + ## v0.5.8 — case management resources (notification groups, SLAs, templates) ### Added diff --git a/src/talonctl/schemas/envelope.schema.json b/src/talonctl/schemas/envelope.schema.json index c857383..2b80991 100644 --- a/src/talonctl/schemas/envelope.schema.json +++ b/src/talonctl/schemas/envelope.schema.json @@ -9,7 +9,7 @@ "apiVersion": { "const": "talon/v2" }, "kind": { "type": "string", - "enum": ["Detection", "SavedSearch", "LookupFile", "Workflow", "Dashboard", "RtrScript", "RtrPutFile"] + "enum": ["Detection", "SavedSearch", "LookupFile", "Workflow", "Dashboard", "RtrScript", "RtrPutFile", "CaseNotificationGroup", "CaseSla", "CaseTemplate"] }, "metadata": { "type": "object", diff --git a/tests/unit/test_envelope_validation.py b/tests/unit/test_envelope_validation.py index 923384c..3eec377 100644 --- a/tests/unit/test_envelope_validation.py +++ b/tests/unit/test_envelope_validation.py @@ -87,3 +87,27 @@ def test_whitespace_hygiene_checks_metadata_and_nested(): env = Envelope("talon/v2", "Dashboard", {"resource_id": "d"}, {"widgets": {"w1": {"queryString": "#a\n| b \n"}}}) errs = check_whitespace_hygiene(env) assert any("trailing whitespace" in e and "widgets.w1.queryString" in e for e in errs) + + +def test_validate_authored_envelope_accepts_case_kinds(): + """Schema kind enum must include all three case management kinds.""" + for kind in ("CaseNotificationGroup", "CaseSla", "CaseTemplate"): + env = Envelope( + "talon/v2", kind, + {"resource_id": "test_resource", "name": "Test"}, + {"name": "Test"}, + ) + errors = validate_authored_envelope(env) + assert errors == [], f"{kind} rejected by schema: {errors}" + + +def test_schema_kind_enum_matches_kind_to_type(): + """Schema kind enum must stay in sync with KIND_TO_TYPE (drift guard).""" + import json + from importlib import resources as importlib_resources + from talonctl.core.envelope import KIND_TO_TYPE + + text = importlib_resources.files("talonctl.schemas").joinpath("envelope.schema.json").read_text() + schema = json.loads(text) + schema_kinds = set(schema["properties"]["kind"]["enum"]) + assert schema_kinds == set(KIND_TO_TYPE.keys()) From 8c2a728b0027ecd94e0f801f8de95e4d6199eff5 Mon Sep 17 00:00:00 2001 From: William Webster Date: Mon, 29 Jun 2026 11:54:45 -0400 Subject: [PATCH 2/2] style: ruff format test_envelope_validation.py --- tests/unit/test_envelope_validation.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/unit/test_envelope_validation.py b/tests/unit/test_envelope_validation.py index 3eec377..1e516de 100644 --- a/tests/unit/test_envelope_validation.py +++ b/tests/unit/test_envelope_validation.py @@ -93,7 +93,8 @@ def test_validate_authored_envelope_accepts_case_kinds(): """Schema kind enum must include all three case management kinds.""" for kind in ("CaseNotificationGroup", "CaseSla", "CaseTemplate"): env = Envelope( - "talon/v2", kind, + "talon/v2", + kind, {"resource_id": "test_resource", "name": "Test"}, {"name": "Test"}, )