Skip to the content.

GNAT Architecture Decision Records

A single reference for every design decision made during development, including tradeoffs, alternatives considered, and implementation notes. Use this when testing, implementing new connectors, or extending existing subsystems.

Table of Contents

  1. ADR-0001: HTTP Client Layer
  2. ADR-0002: ORM / STIX Compatibility
  3. ADR-0003: Connector Architecture
  4. ADR-0004: Ingestion Framework
  5. ADR-0005: Context System — Global and Local
  6. ADR-0006: Workspace Persistence
  7. ADR-0007: Async Client
  8. ADR-0008: Visualization — Tabular
  9. ADR-0009: Visualization — Graph
  10. ADR-0010: Visualization — Grafana vs Power BI
  11. ADR-0011: CLI Design
  12. ADR-0012: Code Generation
  13. ADR-0013: Configuration
  14. ADR-0014: Testing Strategy
  15. ADR-0015: Packaging and Extras
  16. ADR-0016: Feed Scheduling
  17. ADR-0017: Export / Integration Pipeline
  18. ADR-0018: AI Agent Layer
  19. ADR-0019: Shared Research Library
  20. ADR-0020: NLP Query Layer
  21. ADR-0021: Rust Native Extension (gnat-core)
  22. ADR-0022: Web Dashboard (gnat/serve/)
  23. ADR-0023: Terminal UI — Textual
  24. ADR-0024: XSOAR Content Pack Generator
  25. ADR-0025: Upstream Contribution Pipeline
  26. ADR-0026: Connector Health Monitor
  27. ADR-0027: Multi-Tenant Workspace Isolation
  28. ADR-0028: TAXII 2.1 Server
  29. ADR-0029: Docker Containerization
  30. ADR-0030: Use Diátaxis and ADRs
  31. ADR-0031: Analysis Layer Architecture
  32. ADR-0032: STIX Custom Objects
  33. ADR-0033: Confidence Scoring
  34. ADR-0034: Report Lifecycle
  35. ADR-0035: Quality Agents
  36. ADR-0036: Security Agents Phase B
  37. ADR-0037: Adopt Responsible Disclosure, DCO, and Apache 2.0 Compliance
  38. ADR-0038: Data Lineage Tracking

Phase 4 — Control, Reasoning, Safety

  1. ADR-0039: Unified Execution Context
  2. ADR-0040: Connector Trust Model
  3. ADR-0041: Idempotency and Schema Evolution
  4. ADR-0042: Hypothesis Engine
  5. ADR-0043: Negative Evidence Tracking
  6. ADR-0044: Reasoning Engine
  7. ADR-0045: Agent Governance
  8. ADR-0046: HITL Gateway
  9. ADR-0047: Workspace Isolation and Trust Boundaries
  10. ADR-0048: Query Budget and Cost Model
  11. ADR-0049: Testing Framework — Simulation and Replay

Detection, Attribution & Telemetry

  1. ADR-0050: HuntGNAT — Detection Rule Translation
  2. ADR-0051: Attribution & Campaign Tracking
  3. ADR-0052: Telemetry Ingestion
  4. ADR-0053: Infrastructure Graph Labels
  5. ADR-0054: Analysis Rule Engine

Cross-Tool Integration

  1. ADR-0055: Cross-Tool Investigation Context
  2. ADR-0056: Unified API Key Authentication

GUI Foundation

  1. ADR-0057: Pydantic Schema Exports
  2. ADR-0058: Analyst Service Wrappers

Quick Reference: Adding a New Connector

# 1. Generate scaffold
gnat-codegen --spec platform-openapi.json --name myplatform --auth oauth2

# 2. Implement in gnat/connectors/myplatform/client.py
#    - authenticate()
#    - to_stix(native) → dict with type, id, created, modified
#    - from_stix(stix_dict) → platform-native payload
#    - health_check()
#    - get_object(), list_objects(), upsert_object(), delete_object()

# 3. Register sync connector
# gnat/clients/__init__.py:
CLIENT_REGISTRY["myplatform"] = MyplatformClient

# 4. Add async mirror
# gnat/async_client/connectors.py: add AsyncMyplatformClient
# gnat/async_client/client.py: add to _build_async_registry()

# 5. Add INI section to config/config.ini.example

# 6. Add [global.myplatform] block to ADR-0013 (0013-ADR-configuration.md)

# 7. Run tests
pytest tests/unit/connectors/ -v

Quick Reference: Adding a New Ingest Source

# SourceReader subclass
class MyReader(SourceReader):
    def _iter_records(self) -> Iterator[RawRecord]:
        # yield plain dicts

# RecordMapper subclass
class MyMapper(RecordMapper):
    def map(self, record: RawRecord) -> Iterator[STIXBase]:
        # yield STIXBase objects using self._client, self.tlp_marking, self.confidence

# Register in:
# gnat/ingest/sources/__init__.py
# gnat/ingest/mappers/__init__.py
# gnat/__init__.py (both __all__ and import)

Quick Reference: Workspace Investigation Workflow

from gnat import GNATClient
from gnat.context import WorkspaceManager, GlobalContextRegistry

# Setup (once per session)
tq = GNATClient().connect("threatq")
rf = GNATClient().connect("recordedfuture")  # read-only
cs = GNATClient().connect("crowdstrike")

manager = WorkspaceManager.from_clients(
    {"threatq": tq, "rf": rf, "crowdstrike": cs},
    default="threatq",
    read_only=["rf"],
)

# Investigation
ws = manager.get_or_create("campaign-name")
ws.load("indicator", filters={"tags": "apt28"})

ws.enrich(
    sources=["rf", "crowdstrike"],
    strategy="create_relationships",  # preserves provenance
    confidence_floor=60,
)

print(ws.diff())            # what changed
result = ws.commit()        # write back to ThreatQ
print(result)

# Visualize
from gnat.viz import TabularView, GraphView
TabularView(ws).show()
GraphView(ws).to_html("graph.html")  # auto-selects sigma.js at scale

Licensed under the Apache License, Version 2.0