opentide

Detection-as-code

The day-to-day loop for authoring, reviewing, promoting, and deploying detection objects.

This is the workflow you live in after onboarding: author objects, validate, review, promote, deploy. If you have not built a chain yet, do the Tutorial first — this page assumes you understand the object model.

The daily loop

flowchart LR
  edit["Edit YAML"] --> gen["generate<br/>(if schemas changed)"]
  gen --> val["validate --strict"]
  val --> lint["lint --strict"]
  lint --> q["validate query"]
  q --> pr["Open PR → CI gate"]
  pr --> deploy["deploy staging"]
  deploy --> promote["promote → production"]
opentide generate                          # only when schemas/templates changed
opentide validate --strict                 # schema, UUID, uniqueness, chaining
opentide lint --strict                     # filename slugs and recommended metadata
opentide validate query --platform sentinel --live
opentide deploy --platform sentinel --dry-run --strategy PREVIEW --all
opentide generate docs                          # refresh wiki pages

While iterating on a single file, keep the loop tight:

opentide validate --file objects/rules/my-rule.yaml

For large repos, narrow with --uuid or --type so you validate only what you touched.

Authoring a good object

Beyond passing validation, good objects are reviewable and chained.

Start from a template

New objects should start from the generated templates so required fields and structure are correct:

cp .opentide/templates/rule.1.0.template.yaml objects/rules/my-rule.yaml

Fill fields with meaning, not placeholders

  • metadata.schema — the correct revision (rule::1.0). See Schema revision.
  • metadata.uuid — a freshly generated UUID, never copied.
  • description — what the detection catches and why, in a sentence a reviewer can judge.
  • severity / response.alert_severity — drawn from the severity vocabulary.
  • techniques / att&ck — the ATT&CK techniques this addresses; these power coverage reporting.

Chain it

A rule that references no objective is an orphan. Point detection_model at the objective it implements, and make sure that objective references the threat it covers under objective.threats. Verify:

opentide info
opentide --json info --technique T1059 coverage

Map fields to vocabularies

Fields like severity, impact, surface, methodology, and att&ck draw their allowed values from published vocabularies. (terrain is free-form prose, not a vocabulary.) Using a value outside the vocabulary fails validation — check the catalog when unsure.

Status and deployment strategy

Every rule has a status, and each status maps to a strategy that drives whether and how the rule deploys. Statuses are configurable; the table below is the bundled set:

IntentBundled statusesDeploys?
DesignDESIGNNo (INERT)
Build & refineDEVELOPMENT, IMPROVING, STAGING, ACCEPTANCEFrom pull requests (PREVIEW)
LivePRODUCTIONFrom the default branch (RELEASE)
RetireDISABLED, REMOVEDDisable / delete

The pull request job runs opentide deploy --strategy PREVIEW and deploys the changed PREVIEW rules; the default-branch job runs --strategy RELEASE and deploys the changed RELEASE rules, disabling or deleting retired ones. Each goes to the tenants whose strategies accept it. Runs select by strategy, so they work whatever your statuses are called. See Statuses, strategies and tenants.

opentide validates only that a rule's status exists in your merged deployment.toml — it does not enforce any ordering between statuses, so you can set any configured status directly. If you override deployment.toml, these names may not exist at all in your repo. See Configuration → deployment statuses.

Promotion

Edit the rule's status in YAML (and commit it) for deliberate changes, then deploy. When [promotion] is enabled in deployment.toml, the default-branch opentide deploy --strategy RELEASE rewrites the promotable statuses of the changed rules directly to the configured promotion_target — it does not walk them one step at a time. Statuses whose strategy is RELEASE, DISABLEMENT, or DELETION are left untouched. There is no separate mutate promote command.

# after committing the status change: deploy what the last commit changed
opentide deploy --platform sentinel --dry-run --strategy RELEASE
opentide deploy --platform sentinel --strategy RELEASE

See deploy and Configuration → promotion.

Platform queries

Each rule carries per-platform query blocks under configurations. Six platforms support query syntax validation; two are deploy-only:

PlatformQuery languageQuery validate
SentinelKQLyes
Defender for EndpointKQLyes
ElasticKuery / Lucene / EQL / ES|QLyes
SplunkSPLyes
SentinelOneS1QLyes
Carbon Black CloudLuceneyes
CrowdStrike—no (deploy only)
HarfangLab—no (deploy only)

Always run opentide validate query --platform <name> --live for supporting platforms before deploy. A bare command refuses. opentide reports supported: false for CrowdStrike/HarfangLab rather than faking a pass — see Platforms.

Review checklist

Use this in pull-request reviews:

  1. Does validate --strict pass? (CI enforces it — see CI/CD.)
  2. Is the rule chained to an objective, and the objective to a threat?
  3. Are severity, att&ck, and vocabulary fields meaningful and valid?
  4. Is status appropriate for the change (not accidentally PRODUCTION)?
  5. For supported platforms, does query validation pass?
  6. Is metadata.version bumped if the detection logic changed?

Exports and coverage

opentide generate exports navigator
opentide generate exports revisions
opentide --json info --technique T1059 coverage

See generate exports.

Agent-assisted authoring

Agents can run the same loop through MCP. Configure once:

opentide setup mcp --cursor --yes
opentide setup skills --yes --generic

Then see Agentic setup for a safe agent workflow and its limits.

On this page