Skip to content

test: pin the GNAT SandGNAT-connector read contract - #25

Merged
wrhalpin merged 1 commit into
mainfrom
claude/intake-service-vm-manager-Azqfw
Jul 5, 2026
Merged

test: pin the GNAT SandGNAT-connector read contract#25
wrhalpin merged 1 commit into
mainfrom
claude/intake-service-vm-manager-Azqfw

Conversation

@wrhalpin

@wrhalpin wrhalpin commented Jul 5, 2026

Copy link
Copy Markdown
Owner

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.

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
Copilot AI review requested due to automatic review settings July 5, 2026 20:47
@wrhalpin
wrhalpin merged commit f932f00 into main Jul 5, 2026
7 of 12 checks passed

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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 /analyses responses.
  • 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()

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants