Centralize STIX spec version in gnat/stix/version.py#113
Conversation
Before this change, the string literal "2.1" was inlined in 371+
places across 138 files — 120 connector to_stix() methods, ORM
defaults, helper functions, custom SDOs, the TAXII media types, the
validator's closed vocabulary, and the HITL agent workflow. A minor
STIX version bump (e.g. 2.1 → 2.2) would have required a sed pass
across the entire codebase.
This refactor introduces a single source of truth at
gnat/stix/version.py with four exported constants:
- CURRENT_SPEC_VERSION (the version emitted everywhere)
- SUPPORTED_SPEC_VERSIONS (closed vocab for the validator)
- STIX_MEDIA_TYPE (derived from CURRENT_SPEC_VERSION)
- TAXII_MEDIA_TYPE (derived from CURRENT_SPEC_VERSION)
All downstream surfaces now import from this module:
Core:
- gnat/orm/base.py STIXBase default + to_stix_bundle()
- gnat/utils/stix_helpers.py make_bundle(), make_observed_data_
envelope(), osv_to_stix_vulnerability()
- gnat/stix/object_validator.py _CLOSED_VOCAB['spec_version']
- gnat/stix/pattern_validator.py stix_version argument forwarded
to the stix2-patterns library
- gnat/stix/sdos/hypothesis.py, negative_evidence.py from_dict
fallbacks
- gnat/taxii/_protocol.py STIX_MEDIA_TYPE + TAXII_MEDIA_TYPE
re-exported from gnat.stix.version
for a single source of truth
- gnat/agents/hitl.py _action_to_stix(), _notify_xsoar()
Connectors: 120 files touched. Every `"spec_version": "2.1",` literal
was replaced with `"spec_version": CURRENT_SPEC_VERSION,` via a
one-shot mass-migration script that also inserted the required
`from gnat.stix.version import CURRENT_SPEC_VERSION` import at the
correct alphabetical position in each file's gnat-import block.
Verification:
- Full unit suite: 4,621 passed, 198 skipped, 0 failures, 0 errors.
No regressions from the refactor.
- Stress test: edited gnat/stix/version.py on disk to "2.2",
spawned a fresh subprocess, and verified that the CISA,
Dataminr, and HackerOne connectors — plus the make_bundle()
helper and the STIXBase ORM default — all emitted "2.2"
without any additional code changes. Reverted immediately.
- Ruff: error count dropped from 25 → 19 on the refactor paths
(net improvement due to the I001 auto-fixes that ran as a
side effect of the import-insertion sweep).
Future minor STIX version bumps (2.1 → 2.2 → 2.3 …) are now a
literal one-line change in gnat/stix/version.py — no sed across
138 files required. Major bumps (3.0) still need per-connector
to_stix() review for any renamed fields / pattern-grammar changes,
but this refactor is a prerequisite that removes the mechanical
toil and leaves only the meaningful audit work.
Side effect: 4 pre-existing `I001` import-sort issues in
gnat/agents/{embeddings,parsing,steps,workflows/__init__}.py were
auto-corrected by the ruff --fix pass and are included in this
commit. They're unrelated to STIX versioning but are harmless
improvements.
There was a problem hiding this comment.
Pull request overview
This PR centralizes the STIX spec_version and related media-type strings into a single module (gnat/stix/version.py) and replaces widespread "2.1" literals across the codebase with imports of shared constants, reducing future mechanical churn for STIX minor version bumps.
Changes:
- Introduces
gnat.stix.versionas the single source of truth for STIX spec version and derived media types. - Updates core helpers/validators/ORM defaults and a large set of connectors/mappers/tests to emit
spec_versionviaCURRENT_SPEC_VERSION. - Includes a few incidental import-sorting/formatting adjustments from automated tooling.
Reviewed changes
Copilot reviewed 134 out of 134 changed files in this pull request and generated 13 comments.
Show a summary per file
| File | Description |
|---|---|
| gnat/utils/stix_helpers.py | Bundles/envelopes now emit spec_version via CURRENT_SPEC_VERSION. |
| gnat/taxii/_protocol.py | Re-exports media-type constants and uses CURRENT_SPEC_VERSION in bundle creation. |
| gnat/stix/version.py | New centralized STIX version + supported versions + derived media types. |
| gnat/stix/sdos/negative_evidence.py | Uses CURRENT_SPEC_VERSION fallback when spec_version absent. |
| gnat/stix/sdos/hypothesis.py | Uses CURRENT_SPEC_VERSION fallback when spec_version absent. |
| gnat/stix/pattern_validator.py | Forwards CURRENT_SPEC_VERSION into strict pattern validation. |
| gnat/stix/object_validator.py | Uses SUPPORTED_SPEC_VERSIONS for closed vocabulary validation. |
| gnat/stix/init.py | Exposes version/media-type constants from the gnat.stix package surface. |
| gnat/orm/base.py | ORM defaults and bundle emission now use CURRENT_SPEC_VERSION. |
| gnat/connectors/zerofox/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/zeek/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/zeek/init.py | Bundle/object emission uses CURRENT_SPEC_VERSION. |
| gnat/connectors/xm_cyber/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/wiz/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/wazuh/stix_mapper.py | Mapper emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/connectors/vulncheck/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/vmray/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/velociraptor/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/vectra/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/upguard/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/trm_labs/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/trellix/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/tenable_one/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/talos/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/suricata/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/suricata/init.py | Bundle/object emission uses CURRENT_SPEC_VERSION. |
| gnat/connectors/splunk/stix_mapper.py | Mapper emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/connectors/sophos/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/snort/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/snort/init.py | Bundle/object emission uses CURRENT_SPEC_VERSION. |
| gnat/connectors/silverfort/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/silent_push/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/shodan/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/servicenow_secops/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/sentinelone/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/sentinel/tests/test_sentinel.py | Tests use CURRENT_SPEC_VERSION for bundle fixtures. |
| gnat/connectors/sentinel/stix_mapper.py | Mapper emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/connectors/semperis/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/securonix/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/securitytrails/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/security_onion/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/security_onion/init.py | Bundle/object emission uses CURRENT_SPEC_VERSION. |
| gnat/connectors/samdesk/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/safebreach/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/runzero/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/red_canary/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/qualys/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/qradar/tests/test_qradar.py | Tests use CURRENT_SPEC_VERSION for bundle fixtures. |
| gnat/connectors/qradar/stix_mapper.py | Mapper emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/connectors/project_honey_pot/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/ping_identity/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/picus/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/pentera/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/ossim/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/ossim/init.py | Bundle/object emission uses CURRENT_SPEC_VERSION. |
| gnat/connectors/orca/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/opencti/client.py | Wraps payloads in bundles with CURRENT_SPEC_VERSION. |
| gnat/connectors/okta/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/misp/tests/test_misp.py | Tests use CURRENT_SPEC_VERSION for bundle fixtures. |
| gnat/connectors/misp/stix_mapper.py | Mapper emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/connectors/mimecast/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/magnet_axiom/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/lansweeper/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/kaspersky_opentip/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/joe_sandbox/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/ironscales/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/ip_api/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/intezer/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/intel471/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/hybrid_analysis/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/huntress/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/human_security/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/hudsonrock/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/hackerone/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/gurucul/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/group_ib/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/grok/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/greynoise/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/greenbone/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/graylog/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/graylog/init.py | Bundle/object emission uses CURRENT_SPEC_VERSION. |
| gnat/connectors/google_ct/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/google_chronicle/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/gnat_remote/connector.py | Uses CURRENT_SPEC_VERSION for bundle spec_version. |
| gnat/connectors/gemini/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/fortisiem/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/fortiguard/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/fortiedr/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/flashpoint/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/factal/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/extrahop/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/exabeam/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/eset_ti/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/entra_id/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/elastic/test_elastic.py | Tests use CURRENT_SPEC_VERSION for bundle fixtures. |
| gnat/connectors/elastic/stix_mapper.py | Mapper emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/connectors/dynatrace/stix_mapper.py | Mapper emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/connectors/dtex/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/domaintools/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/discord/connector.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/defectdojo/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/dataminr/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/darktrace/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/cymulate/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/cycognito/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/cyble_vision/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/crtsh/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/cortex_xpanse/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/copilot/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/cofense_intel/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/code42/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/cloudflare_intel/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/claroty/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/cisco_umbrella/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/CISA/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/chatgpt/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/censys/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/bugcrowd/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/bitsight/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/bitdefender_iz/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/axonius/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/attackiq/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/armis/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/arctic_wolf/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/any_run/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/alienvault/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/alienvault/init.py | Bundle/object emission uses CURRENT_SPEC_VERSION. |
| gnat/connectors/abuseipdb/client.py | Connector STIX output uses CURRENT_SPEC_VERSION. |
| gnat/connectors/abusech/client.py | Base indicator skeleton emits spec_version via CURRENT_SPEC_VERSION. |
| gnat/agents/workflows/init.py | Import order adjusted (tooling side effect). |
| gnat/agents/steps.py | Whitespace cleanup (tooling side effect). |
| gnat/agents/parsing.py | Import ordering adjusted (tooling side effect). |
| gnat/agents/hitl.py | Agent action/note emission uses CURRENT_SPEC_VERSION. |
| gnat/agents/embeddings.py | Import ordering adjusted (tooling side effect). |
Comments suppressed due to low confidence (1)
gnat/connectors/gnat_remote/connector.py:44
- This connector still hardcodes
_TAXII_MEDIA_TYPE/_STIX_MEDIA_TYPEeven though the PR is centralizing version/media-type constants. To avoid drift (especially if the STIX media type version parameter changes), import and use the sharedTAXII_MEDIA_TYPEandSTIX_MEDIA_TYPEconstants instead of duplicating the strings here.
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| #: MIME type served by the GNAT TAXII 2.1 server and expected from | ||
| #: upstream TAXII sources. Derived from :data:`CURRENT_SPEC_VERSION` | ||
| #: so a minor version bump automatically updates the media-type | ||
| #: version parameter. | ||
| TAXII_MEDIA_TYPE: str = f"application/taxii+json;version={CURRENT_SPEC_VERSION}" | ||
|
|
||
| #: MIME type for STIX-JSON envelopes as defined by the TAXII 2.1 spec. | ||
| #: Derived from :data:`CURRENT_SPEC_VERSION` for the same reason as | ||
| #: :data:`TAXII_MEDIA_TYPE`. | ||
| STIX_MEDIA_TYPE: str = f"application/stix+json;version={CURRENT_SPEC_VERSION}" |
There was a problem hiding this comment.
TAXII_MEDIA_TYPE is currently derived from CURRENT_SPEC_VERSION, but the application/taxii+json;version=... parameter is the TAXII protocol version (TAXII 2.1), not the STIX spec version. If CURRENT_SPEC_VERSION is bumped to 2.2 (as suggested by the module docstring), this would generate an invalid TAXII media type and break TAXII content negotiation. Consider introducing a separate constant for the TAXII protocol version (kept at "2.1") and derive TAXII_MEDIA_TYPE from that, while keeping STIX_MEDIA_TYPE derived from the STIX spec version.
| # Media-type constants (spec §3.1) — re-exported from gnat.stix.version so | ||
| # there is a single source of truth for the STIX version number. Bumping | ||
| # ``CURRENT_SPEC_VERSION`` automatically updates the ``;version=...`` | ||
| # parameter on both media types. | ||
| # --------------------------------------------------------------------------- |
There was a problem hiding this comment.
This comment states that bumping CURRENT_SPEC_VERSION will update the ;version=... parameter on both STIX and TAXII media types. The TAXII media type version parameter is the TAXII protocol version (2.1) and should not track the STIX spec version; updating it on a STIX minor bump would be incorrect and could break clients. Update the comment (and the underlying constant in gnat.stix.version, if needed) to keep TAXII and STIX versioning distinct.
| return { | ||
| "type": "ipv4-addr", | ||
| "id": f"ipv4-addr-{_det_uuid('ipv4-addr', value)}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "value": value, | ||
| } |
There was a problem hiding this comment.
STIX IDs should use the <type>--<uuid> format. This helper builds an ipv4-addr with an ID like ipv4-addr-<uuid>, which is not a valid STIX identifier and may fail validation/downstream ingestion. Update the ID format to include the required -- separator (consistent with other mappers in this repo).
| return { | ||
| "type": "domain-name", | ||
| "id": f"domain-name-{_det_uuid('domain-name', value)}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "value": value, | ||
| } |
There was a problem hiding this comment.
STIX IDs should use the <type>--<uuid> format. This helper currently returns domain-name-<uuid> (single hyphen) which is not a valid STIX identifier; use domain-name--<uuid> instead.
| return { | ||
| "type": "url", | ||
| "id": f"url-{_det_uuid('url', value)}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "value": value, | ||
| } |
There was a problem hiding this comment.
STIX IDs should use the <type>--<uuid> format. This helper currently returns url-<uuid> (single hyphen) which is not a valid STIX identifier; use url--<uuid> instead.
| def _make_ipv4(value: str) -> dict: | ||
| """Internal helper for make ipv4.""" | ||
| return { | ||
| "type": "ipv4-addr", | ||
| "id": f"ipv4-addr-{_det_uuid('ipv4-addr', value)}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "value": value, | ||
| } |
There was a problem hiding this comment.
STIX IDs should use the <type>--<uuid> format. This helper builds an ipv4-addr with an ID like ipv4-addr-<uuid>, which is not a valid STIX identifier and may fail validation/downstream ingestion. Update the ID format to include the required -- separator.
| def _make_user_account(user_id: str) -> dict: | ||
| """Internal helper for make user account.""" | ||
| return { | ||
| "type": "user-account", | ||
| "id": f"user-account-{_det_uuid('user-account', user_id)}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "user_id": user_id, | ||
| } |
There was a problem hiding this comment.
STIX IDs should use the <type>--<uuid> format. This helper currently returns user-account-<uuid> (single hyphen) which is not a valid STIX identifier; use user-account--<uuid> instead.
| def _make_process(name: str) -> dict: | ||
| """Internal helper for make process.""" | ||
| return { | ||
| "type": "process", | ||
| "id": f"process-{_det_uuid('process', name)}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "name": name, | ||
| } |
There was a problem hiding this comment.
STIX IDs should use the <type>--<uuid> format. This helper currently returns process-<uuid> (single hyphen) which is not a valid STIX identifier; use process--<uuid> instead.
| def _make_domain(value: str) -> dict: | ||
| """Internal helper for make domain.""" | ||
| return { | ||
| "type": "domain-name", | ||
| "id": f"domain-name-{_det_uuid('domain-name', value)}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "value": value, | ||
| } |
There was a problem hiding this comment.
STIX IDs should use the <type>--<uuid> format. This helper currently returns domain-name-<uuid> (single hyphen) which is not a valid STIX identifier; use domain-name--<uuid> instead.
| def _make_bundle(objects: list[dict]) -> dict: | ||
| """Internal helper for make bundle.""" | ||
| return { | ||
| "type": "bundle", | ||
| "id": f"bundle-{uuid.uuid4()}", | ||
| "spec_version": "2.1", | ||
| "spec_version": CURRENT_SPEC_VERSION, | ||
| "objects": objects, | ||
| } |
There was a problem hiding this comment.
STIX Bundle IDs should use the bundle--<uuid> format. This helper currently produces bundle-<uuid> (single hyphen), which is not a valid STIX bundle identifier. Align with the standard bundle--... form used elsewhere in the codebase.
Before this change, the string literal "2.1" was inlined in 371+ places across 138 files — 120 connector to_stix() methods, ORM defaults, helper functions, custom SDOs, the TAXII media types, the validator's closed vocabulary, and the HITL agent workflow. A minor STIX version bump (e.g. 2.1 → 2.2) would have required a sed pass across the entire codebase.
This refactor introduces a single source of truth at gnat/stix/version.py with four exported constants:
All downstream surfaces now import from this module:
Core:
envelope(), osv_to_stix_vulnerability()
to the stix2-patterns library
fallbacks
re-exported from gnat.stix.version
for a single source of truth
Connectors: 120 files touched. Every
"spec_version": "2.1",literal was replaced with"spec_version": CURRENT_SPEC_VERSION,via a one-shot mass-migration script that also inserted the requiredfrom gnat.stix.version import CURRENT_SPEC_VERSIONimport at the correct alphabetical position in each file's gnat-import block.Verification:
Future minor STIX version bumps (2.1 → 2.2 → 2.3 …) are now a literal one-line change in gnat/stix/version.py — no sed across 138 files required. Major bumps (3.0) still need per-connector to_stix() review for any renamed fields / pattern-grammar changes, but this refactor is a prerequisite that removes the mechanical toil and leaves only the meaningful audit work.
Side effect: 4 pre-existing
I001import-sort issues in gnat/agents/{embeddings,parsing,steps,workflows/init}.py were auto-corrected by the ruff --fix pass and are included in this commit. They're unrelated to STIX versioning but are harmless improvements.