test: pin the GNAT SandGNAT-connector read contract - #25
Merged
Conversation
Verified my earlier G6-G8 STIX changes against the now-shipped gnat.connectors.sandgnat: the connector treats /analyses/<id>/bundle as an opaque passthrough into GNAT's STIX ORM (so standard child_refs / mitre-attack are compatible), and reads only scalar job-row keys, all of which we emit. No mismatch. Adds tests/test_gnat_connector_contract.py to keep it that way. The connector consumes everything via dict.get(), so a field rename on our side wouldn't crash it — it would silently yield None and quietly drop data. These tests assert the export API keeps emitting exactly the job-row keys the connector reads (id, sample_hash_*, status, vt_*, evasion_observed, yara_matches, investigation_id, imphash, ssdeep, tlsh, started_at), the list/bundle/similar envelope shapes, the healthz shape, the full /analyses filter set, and the investigation-tag endpoint. Rename one of these and the contract test fails, pointing at the GNAT consumer. 9 tests. Suite 241 -> 250. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01EHtr9vrTLgnEyFS4rXpCrw
There was a problem hiding this comment.
Pull request overview
Adds a dedicated contract test suite to lock down the HTTP response shapes and job-row keys relied upon by the gnat.connectors.sandgnat consumer, preventing silent integration breakage from field renames or envelope changes.
Changes:
- Introduces connector-contract tests that assert required job-row keys emitted by
/analysesresponses. - Adds endpoint-shape tests for
/healthz,/analyses(list/get),/analyses/<id>/bundle,/analyses/<id>/similar, and the investigation tagging endpoint.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Comment on lines
+5
to
+8
| These pin the exact HTTP shapes and job-row keys that GNAT's SandGNAT | ||
| connector (gnat/connectors/sandgnat/client.py in wrhalpin/GNAT) reads. | ||
| The connector consumes everything via `.get(...)`, so a field rename on | ||
| our side wouldn't crash it — it would silently yield None. That's the |
Comment on lines
+108
to
+113
| resp = client.get("/analyses", headers=API_KEY) | ||
| assert resp.status_code == 200 | ||
| body = resp.get_json() | ||
| assert "items" in body and isinstance(body["items"], list) | ||
| assert CONNECTOR_JOB_KEYS <= body["items"][0].keys() | ||
|
|
Comment on lines
+157
to
+160
| resp = client.get(f"/analyses/{job.id}/similar", headers=API_KEY) | ||
| assert resp.status_code == 200 | ||
| assert "items" in resp.get_json() | ||
|
|
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Verified my earlier G6-G8 STIX changes against the now-shipped gnat.connectors.sandgnat: the connector treats /analyses//bundle as an opaque passthrough into GNAT's STIX ORM (so standard child_refs / mitre-attack are compatible), and reads only scalar job-row keys, all of which we emit. No mismatch.
Adds tests/test_gnat_connector_contract.py to keep it that way. The connector consumes everything via dict.get(), so a field rename on our side wouldn't crash it — it would silently yield None and quietly drop data. These tests assert the export API keeps emitting exactly the job-row keys the connector reads (id, sample_hash_, status, vt_, evasion_observed, yara_matches, investigation_id, imphash, ssdeep, tlsh, started_at), the list/bundle/similar envelope shapes, the healthz shape, the full /analyses filter set, and the investigation-tag endpoint. Rename one of these and the contract test fails, pointing at the GNAT consumer.
9 tests. Suite 241 -> 250.