Skip to the content.

ADR-0005: Context System — Global and Local

Decision: Multiple global contexts, separate relationship objects for enrichment (not merged scores).

Multiple globals rationale: Different platforms serve different roles — ThreatQ as system of record, Recorded Future as enrichment-only, CrowdStrike as endpoint context. Forcing a single global would either lose platform provenance or require complex merge logic.

GlobalContextRegistry priority: Lower integer = higher priority. Default write target is the lowest-priority non-read-only context. Override with registry.set_default("name").

INI config format for multiple globals:

[global]
default = threatq_prod

[global.threatq_prod]
target        = threatq
host          = https://threatq.example.com
client_id     = ...
client_secret = ...

[global.recorded_future]
target    = recordedfuture
host      = https://api.recordedfuture.com
api_token = ...
read_only = true
priority  = 20

GlobalContextRegistry.from_clients() for programmatic setup:

registry = GlobalContextRegistry.from_clients(
    {"tq": tq_cli, "rf": rf_cli, "cs": cs_cli},
    default="tq",
    read_only=["rf"],
)

Enrichment strategies — choose based on use case:

Strategy Effect Use when
create_relationships New STIX SDO + Relationship added; original untouched Default. Preserves full provenance. Multiple platforms can enrich the same object without collision.
merge_extensions x_ fields merged into original; original marked dirty You want a single enriched indicator rather than a graph of objects. Loses individual platform provenance.
tag_only x_enrichment_tags list updated; nothing else changes Lightweight “was checked” marking. No data persisted.

create_relationships is the correct default for your requirement (“preserve both as separate relationships”). RF risk score and CS endpoint data become separate nodes in the graph, linked to the original indicator. diff() and commit() will pick them up as new objects.


Licensed under the Apache License, Version 2.0