Here is detection-as-code as most teams actually practise it. An analyst gets a query working in the SIEM console, pastes it into a YAML template on a wiki page, drops the snippet in chat, and a teammate replies “LGTM”. Six hours later someone runs the export script, the converter quietly rewrites the technique field, a colleague has pushed to the same file in the meantime, and the commit message says “update rules”. Everyone did code review. Nobody reviewed the code that shipped.
TL;DR: A preview is only worth something if the commit is bound to it, so write the rule in HEFAISTOS Rule Hub, press Preview to read the exact OpenTIDE YAML and the diff, and let Publish to Git commit that document only while the rule and the branch are still what you saw.

Git Is Not a Review Process, It Is a Place Where Files Land
“We keep our detections in Git” usually means “a file eventually appears in Git.” What the team approved and what the repository holds drift apart through three gaps, and none of them needs malice. Laziness does fine.
The translation gap. The reviewer saw a console query or a chat snippet. The repository receives the output of a converter. Fields get defaulted, renamed or dropped on the way, and the review never covered the converter’s choices because nobody saw them.
The time gap. The review happened at ten, the push at four. In between, the author “just fixed one thing” and someone else committed to the same path. Last writer wins, and the loser finds out when a rule they tuned last week comes back untuned.
The form gap. Metadata is optional until a coverage report needs it. Someone types T1003.1 instead of T1003.001, the commit goes through, and your ATT&CK map gets a hole that looks like a coverage gap but is really a typo.
Add a fourth problem: if your platform demands a full design ticket before you may write a ten-line rule, analysts route around it, and the console-to-wiki-to-chat pipeline above is what they build instead.
A Worked Example: One Rule, Three Attempts
Rule Hub publishes every rule as one OpenTIDE YAML document and validates it against a strict schema before anything is committed. The schema lives in the public HEFAISTOS repository and is described in the Rule Hub authoring and Git publishing guide. We ran that schema against an example rule (an illustrative LSASS dump via comsvcs, not a production detection) and recorded what came back.
Attempt one, technique typed the way people type it at 17:55 on a Friday:
Value error, Invalid MITRE technique ID: T1003.1. Must match pattern T####[.###] (e.g., T1059 or T1059.001)
Attempt two, the description everyone has written at least once:
String should have at least 10 characters [type=string_too_short, input_value='todo', input_type=str]
Attempt three passes. This is the document that would be committed, byte for byte:
metadata:
title: LSASS dump via comsvcs
description: Rundll32 loading comsvcs.dll MiniDump against LSASS.
author: hunt3r
severity: HIGH
mitre_technique: T1003.001
uuid: 3f2c1d9e-8b7a-4c6d-9e5f-1a2b3c4d5e6f
status: experimental
tlp: amber
tags:
- credential-access
created: '2026-11-13T21:00:00+00:00'
modified: '2026-11-13T21:00:00+00:00'
platforms:
kql:
query: DeviceProcessEvents | where FileName =~ "rundll32.exe" | where ProcessCommandLine
has_all ("comsvcs", "MiniDump")
If the file already exists, the Changes tab shows a unified diff against the destination. Tightening has "MiniDump" to has_all looks like this:
@@ -14,4 +14,4 @@
platforms:
kql:
query: DeviceProcessEvents | where FileName =~ "rundll32.exe" | where ProcessCommandLine
- has "MiniDump"
+ has_all ("comsvcs", "MiniDump")
The reviewer reads the diff Git will receive, not a paraphrase of it. That closes the translation gap.
How to Publish a Rule From Rule Hub
Setup is one step, done once by whoever owns the repository connection:
- Configure the repository. In Configuration → Rules, add your GitHub, GitLab or Gitea repository, including a custom API URL and TLS settings if you self-host. The access token stays on the backend; the browser never sees it.
Then, for every rule:
- Write it. In Rule Hub, press New Rule (beside Refresh). No Workbench, capability abstraction or review section is required. Fill the Metadata tab: title, description, author, MITRE technique, severity, status, tags. Platform tabs cover KQL, Elastic EQL, SPL, Wazuh and QRadar AQL with the same autocomplete, validation, templates and AI generation the Workbench editor uses.
- Save Draft. The rule goes into the internal Rule Repo library, no Git needed. Drafts may be incomplete. Each rule gets a stable UUID that survives edits.
- Publish to Git. The editor saves the latest draft first, then asks for a configured repository, an existing branch, a repository-relative
.yamlor.ymlpath and a commit message. - Preview. Read the Changes tab and the OpenTIDE YAML tab. If the destination already holds this exact content, you get “No changes to publish.” and the publish button stays disabled.
- Publish to Git again to commit. You get the commit SHA and a link to the published file.
The time gap is handled by what the preview remembers. It carries a signed token holding you, the rule, the repository, branch, path, the branch head it was computed against, and a SHA-256 digest of the content. At publish time HEFAISTOS recomputes all of it:

If the provider rejects the commit, your saved draft is preserved. Three boundaries worth knowing: publishing writes one rule document, it does not deploy anything to a detection platform, and it does not touch any Workbench review status. Only the rule’s author or an administrator can edit or publish it, and everything is scoped to your organisation. If a rule deserves a home in an existing Workbench, Add to Workbench links it as an alternative without replacing the primary rule, and it inherits that Workbench’s TLP.
Deployment stays a separate, deliberate step: HEFAISTOS writes to Git, and your platforms take it from there on your terms. And Git publishing is for your own repository; handing rules to another team’s HEFAISTOS instance is a different job, which we covered in how to share detections by pulling like an adult.
Do this Today
- Add your detection repository under Configuration → Rules, and point your first publishes at a test branch so nobody has to trust this post on faith.
- Take one rule that currently lives only in a console or a wiki page, rebuild it with New Rule, Save Draft, and read the Changes tab before you publish.
- Edit the rule after previewing and try to publish anyway, so your team sees the refusal once and stops treating a stale preview as approval.
Ship what you saw.
Featured image generated using Artificial Intelligence (EU AI Act transparency notice).