Monitors, dashboards and detections as code
Tracix takes two kinds of content from Git. Detection rules, value lists and YARA rulesets live as plain files in a detection repository. Monitors, visualizations, dashboards and APM service groups are described in tracix.io/v1 JSON bundles. Both are published the same way: validate, then plan, then apply the plan you reviewed.
What you can automate today
Detection content runs from any CI system with a scoped API key, or your workspace syncs the repository itself. Monitor and dashboard bundles can't be published with an API key yet: publishing one needs a workspace admin, so bundles have no unattended CI path today.
How content managed as code behaves
- Git owns the definition. Each published object gets a stable ID,
code:<package>:<kind>:<uid>, and is marked as managed as code. - The workspace won't edit it. Editing or deleting a managed definition in the workspace is refused, for admins too. To change one for yourself, duplicate it: the copy is an ordinary object you own.
- Operational controls stay yours. You can still enable, disable and snooze a managed monitor and change where it notifies, and enable or disable a managed detection rule or YARA ruleset. These settings survive later publishes.
- A package owns its objects. Everything a repository or bundle publishes belongs to the package it names.
Integration packages from the catalog install their monitors and dashboards the same way, so those are managed as code too.
Validate, plan and apply
| Step | What it does | Changes your workspace |
|---|---|---|
| Validate | Compiles every definition with your workspace's engine and runs the tests that come with them | No |
| Plan | Validates, then compares with what the workspace runs: each object is a create, update, delete, unchanged or conflict, and the plan gets a plan hash | No |
| Apply | Plans again and must reproduce the plan hash you reviewed, then publishes | Yes |
- Apply refuses a stale plan. If anything changed since the review, apply answers
409and you plan again. - Plans survive a merge. The plan hash covers each object's action, definition and live version, not the commit, so a plan reviewed on a pull request still applies at the merge commit when the content is the same.
- Apply isn't a transaction. Each write is safe to repeat, but a failure part way leaves the earlier writes in place. Plan again and apply again.
- Roll back from Git. Revert the commit and apply it. For detection content, only the rules whose definition changes are written.
Detection repositories
A detection repository holds plain files, and its Sigma rules stay readable by sigma-cli and pySigma.
tracix-detections.yaml the manifest: package, defaults, overrides
sigma/**/*.yml|yaml Sigma rules, verbatim (up to 50 documents per file)
native/**/*.yml|yaml native rules: sql, sequence, new_terms, cardinality, watchlist
lists/**/*.yml|yaml value lists: name, description, items
yara/**/*.yar|yara YARA rulesets, one per file
tests/**/*.yml|yaml fixtures: events each rule must or must not matchOther files, such as a README or CI configuration, are ignored. A repository can keep its detections in a subfolder. It can hold up to 5,000 detection files and 50 MB of content, and publish up to 5,000 objects.
The manifest
tracix-detections.yaml at the repository root names the package and tunes the rules. Unknown keys and values that would need converting fail validation, so a typo never becomes a silent default.
package: acme-soc
defaults:
intervalSeconds: 60 # how often each rule's monitor runs
windowMinutes: 5 # how far back each run looks
rbacFloor: editor # who sees the published rules: viewer | editor | admin
license: custom # for Sigma documents that declare no license
overrides:
# One rule, by its Sigma id: tuning lives here, not in the Sigma file.
"0dc16a63-818e-4162-95ea-d8f9e5740ef7":
severity: high
exceptions:
- User: list:service-accounts
suppress:
byFields: [host.name]
windowMinutes: 60
# A glob over repository paths: new network rules start in shadow mode.
"sigma/network/**":
stage: test
prune: true| Key | What it sets |
|---|---|
package | Required. A lowercase name of letters, digits, _, . and -, up to 128 characters |
defaults | stage, enabled, intervalSeconds (15 to 86,400), windowMinutes (1 to 10,080), rbacFloor and license for every rule |
overrides | Tuning per rule ID, uid, path or glob: stage, severity, risk score, threshold, exceptions, suppression, schedule and investigation guide. Glob keys apply first, in order, and exact keys last |
prune | true by default: a file removed from the repository plans a delete. With false, removing a file leaves the published object alone |
logsources | Routes for Sigma log sources the built-in table doesn't know. In this release, validate checks the block and warns that it isn't applied yet |
Stages
Every rule runs at a stage. A rule's stage comes from the manifest; without one, a Sigma rule's status decides: experimental and test start in test, stable in production, and deprecated or unsupported documents are errors.
| Stage | Behavior |
|---|---|
draft | Off, with no monitor |
test | Shadow mode: the rule's monitor runs and records alerts, but nobody is notified or paged and no case is opened |
production | Alerts and notifies as usual |
Promote a rule with a pull request that changes its stage. A rule that doesn't compile is published disabled, with its reasons, never dropped.
Fixtures
Files under tests/ hold events a rule must or must not match. Validate and plan run every case against the compiled rule on one synthetic row: nothing is written and nothing alerts.
rule: 0dc16a63-818e-4162-95ea-d8f9e5740ef7
cases:
- name: whoami run by a person
event:
Image: 'C:\Windows\System32\whoami.exe'
User: alice
expect: match
- name: service account excluded by the exception
event:
Image: 'C:\Windows\System32\whoami.exe'
User: svc_backup
expect: no_match
withExceptions: true- Sigma and SQL rules run fixtures. Sequence, new terms, cardinality and watchlist rules need several events or history, so their cases report
unsupportedand the rules are checked by compiling them. - A file that names a
rulesetholds YARA fixtures: text or base64 samples and the exact set of rules that must match. - A file holds up to 100 cases. A failing case makes validate and plan report
valid: false, so the CLI exits with1before apply.
Conflicts
A repository rule whose rule ID matches a rule created in the UI or installed from the Sigma pack plans a conflict. Apply refuses the whole plan until you confirm the replacement with --replace. The older rule is then disabled and linked to the new one, never taken over in place. Value lists can't be replaced: a list name that another list already uses blocks the plan.
In this release, a repository refuses Sigma correlation and filter documents. Write a correlation as a native sequence or cardinality rule, and a filter as manifest exceptions.
Run the CLI
tracix-detections is a single Node.js 20 or later file with no dependencies. Your workspace serves the build that matches its API.
Point it at your workspace
Set your workspace's address and a CI key with
security.read:bashexport TRACIX_URL=https://production-a7k3p2q9.app.tracix.io export TRACIX_API_KEY=txk_...Download the CLI
bashcurl -fsS -H "X-API-Key: $TRACIX_API_KEY" \ "$TRACIX_URL/api/security/detections/cli" -o tracix-detections.mjsThe response's
X-Tracix-Cli-Sha256header carries the file's SHA-256, so CI can pin a reviewed build.Validate and plan
bashnode tracix-detections.mjs validate . node tracix-detections.mjs plan . plan.jsonThe plan lists what apply would create, update, delete or replace, and is saved for review.
Apply the reviewed plan
With a key that carries
security.manage:bashnode tracix-detections.mjs apply . plan.jsonMore than 200 writes run in the background, and the CLI follows the job to the end.
CLI reference
| Command | What it does |
|---|---|
validate <dir> | Compiles every file and runs the fixtures. Read-only |
plan <dir> <plan.json> | Validates, compares with the workspace and writes the plan for review |
apply <dir> <plan.json> | Applies a reviewed plan. The workspace plans again and must match |
export <package> <outdir> | Writes a package's published rules and lists as repository files |
| Option | What it does |
|---|---|
--replace | plan, apply: confirm replacing rules that share a rule ID with this repository |
--archive | Have the workspace fetch the commit from GitHub or GitLab instead of sending the files |
--revision <sha> | The commit the files were taken at. Defaults to the Git HEAD of the folder, with -dirty when it has changes |
--repo <owner/name> | Archive mode: the repository |
--package <name> | Refuse to run unless the manifest publishes this package |
--no-wait | apply: return once a background apply has started |
--force | export: write into a folder that isn't empty |
--json | Print the workspace's JSON instead of tables |
--verbose | Also list unchanged objects and passing fixtures |
| Environment variable | What it sets |
|---|---|
TRACIX_URL | Your workspace's address. HTTPS, except for localhost |
TRACIX_API_KEY | A CI key: security.read for validate, plan and export, security.manage for apply |
TRACIX_TOKEN | A bearer token, used instead of TRACIX_API_KEY. Set one or the other |
TRACIX_REPO_CREDENTIAL | Archive mode: the ID of a GitHub or GitLab credential stored in your workspace |
TRACIX_REPO | Archive mode: owner/name, when --repo isn't given |
TRACIX_REVISION | The revision to publish, when --revision isn't given |
TRACIX_MAX_REQUEST_BYTES | Request size before the CLI batches or switches to archive mode. Default 1,000,000, at most 10,485,760 |
TRACIX_TIMEOUT_MS | Timeout per request. Default 300,000 |
TRACIX_POLL_MS | How often apply checks a background job. Default 2,000 |
TRACIX_APPLY_WAIT_MS | How long apply follows a background job. Default 1,800,000 |
The CLI exits with 0 on success, 1 for compile errors, failing fixtures, unconfirmed conflicts, a blocked plan or a failed request, and 2 for usage or configuration errors. It sends the key only in a header to TRACIX_URL, refuses redirects and masks the key in everything it prints. A plan is bound to the workspace it was made against, and apply refuses a plan made for another TRACIX_URL.
Sync a repository from your workspace
Your workspace can follow a repository without any CI. An admin connects it under Security › Detection rules › Repositories with Connect repository, or with Keep in sync when importing rules from a Git repository, using a GitHub or GitLab credential stored in the workspace.
| Setting | Options |
|---|---|
| Repository, branch and folder | Where the detections live |
| Mode | Interval checks the branch every 15 minutes by default (5 to 1,440). Webhook plans on every push, checked against a webhook signing secret, and still checks hourly in case a delivery was lost. Manual plans only when you select Sync now or Sync to commit |
| Apply clean plans automatically | Off by default. When on, a plan applies by itself only if it has no compile errors, failing fixtures or conflicts |
Every other plan waits for an admin to review it, with a diff per rule, and apply or discard it. To roll back, Sync to commit pins the repository to an earlier commit and plans it.
Export rules you wrote in the UI
Security › Detection rules › Export, or Export to git on one rule, turns rules authored in the UI into repository files: a download, or one pull request on a connected GitHub repository (GitLab repositories export as files). After the merge, the next plan shows each exported rule as a conflict that replaces its UI rule; confirm it to hand the rule to Git.
To get a published package back as files, run node tracix-detections.mjs export <package> <outdir>. Fixtures aren't stored in the workspace, so they aren't exported.
Monitor and dashboard bundles
A bundle is one JSON file that describes monitors, visualizations, dashboards and APM service groups.
{
"apiVersion": "tracix.io/v1",
"package": "team-operations",
"revision": "1.0.0",
"resources": [
{
"kind": "monitor",
"uid": "service-error-rate",
"attributes": {
"name": "Service error rate",
"description": "Sustained server error ratio above 5 percent.",
"templateId": "apm.error_rate",
"enabled": false,
"condition": "above",
"thresholds": { "alert": 5, "warn": 2 },
"windowMinutes": 15,
"pendingForMinutes": 5,
"noData": "last_known",
"sharing": { "visibility": "team", "rbacFloor": "viewer" }
},
"tests": [
{ "name": "healthy", "value": 1, "expected": "ok" },
{ "name": "warning", "value": 3, "expected": "warn" },
{ "name": "alert", "value": 6, "expected": "alert" }
]
}
]
}| Field | Rules |
|---|---|
apiVersion | tracix.io/v1 |
package | A lowercase name of letters, digits, _, . and -, up to 128 characters, starting with a letter or digit |
revision | Any label up to 128 characters, such as a version or a commit |
resources | 1 to 500 objects |
resources[].kind | monitor, visualization, dashboard or service_group |
resources[].uid | The object's ID within the package, in the same form as package |
resources[].attributes | The object's definition, as the workspace stores it |
resources[].references | Data sources, visualizations or dashboards it depends on. @<uid> refers to an object of that kind in the same bundle |
resources[].tests | Monitors only: threshold fixtures |
resources[].state | present (the default) or absent |
Validation is strict: an unknown field fails, and a monitor value that would have to be converted or clamped fails instead of being adjusted. Detection content can't go in a bundle; it comes from a detection repository.
Tests
A value-threshold monitor can carry tests: a name, a numeric value, an optional currentLevel and the expected level (ok, warn or alert). Validation runs the real threshold logic, including recovery. Tests don't replay queries, pending periods, missing data timing, notifications or anomaly learning, so check those with real telemetry in a staging workspace.
Delete and restore
Leaving an object out of a bundle never deletes it. To delete one, keep it in the bundle with "state": "absent", plan and apply: the plan shows delete. Set it back to present to restore it. Apply writes visualizations before the dashboards that use them and deletes dashboards first, so delete or update the dashboards that reference a visualization in the same change.
Publish a bundle
Workspace admins only, for now
Your workspace validates, plans, applies and exports bundles only for a signed-in workspace admin. API keys can't publish monitor and dashboard bundles yet, so you can't apply them from unattended CI today.
An export captures each object's current definition and operational controls. It isn't a backup of your Git file: tests and comments aren't stored in the workspace.