GitOps
Run your workspace governance like infrastructure, with the config file in git, a drift gate on pull requests, and an import on merge.
Config as code gives you one versioned JSON document for your workspace's governance. This page is the operating recipe: the file lives in git, CI keeps the workspace honest, and a merge is the only way governance changes.
The loop
- Export once and commit
axiorank.config.json. Every governance change is now a pull request: edit the file, review the diff, merge. - Gate pull requests with
axiorank config diff --exit-code(or the GitHub Action'sconfig-fileinput): the build fails when the file and the live workspace have drifted apart, so out-of-band dashboard edits surface as red builds instead of silent drift. - Apply on merge with
axiorank config importin the main-branch job.
npm install -g @axiorank/cli
export AXIORANK_API_KEY=axr_live_...
axiorank config export --file axiorank.config.json # once, then commit
axiorank config diff --file axiorank.config.json --exit-code # CI gate
axiorank config import --file axiorank.config.json # on mergeGitHub Actions
# .github/workflows/governance.yml
on:
pull_request:
push: { branches: [main] }
jobs:
governance:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Drift gate (PRs)
if: github.event_name == 'pull_request'
run: npx @axiorank/cli config diff --file axiorank.config.json --exit-code
env: { AXIORANK_API_KEY: "${{ secrets.AXIORANK_READ_KEY }}" }
- name: Apply (main)
if: github.event_name == 'push'
run: npx @axiorank/cli config import --file axiorank.config.json
env: { AXIORANK_API_KEY: "${{ secrets.AXIORANK_WRITE_KEY }}" }Two keys keep the blast radius small: the PR job only needs policies:read,
the merge job needs policies:write. Add
config backtest next to
the drift gate to also block changes that would flip more real decisions than
you budgeted for.
Terraform shim
Some platform teams require every production change to flow through
terraform apply. The config document slots in as a null_resource with a
local-exec provisioner: the file's hash is the trigger, so terraform plan
shows when an apply will run, and the file diff in the pull request is the
substantive review.
variable "axiorank_api_key" {
type = string
sensitive = true
}
resource "null_resource" "axiorank_governance" {
triggers = {
config_sha = filesha256("${path.module}/axiorank.config.json")
}
provisioner "local-exec" {
command = "npx -y @axiorank/cli config import --file ${path.module}/axiorank.config.json"
environment = {
AXIORANK_API_KEY = var.axiorank_api_key
}
}
}This is a shim, not a provider: Terraform tracks the file, AxioRank computes
the real diff at import time, and a re-apply of an unchanged file is a no-op
on both sides. Keep axiorank config diff --exit-code in your plan stage if
you want drift from dashboard edits to fail the pipeline too.
Secrets in the pipeline
Exports never contain secrets, so the committed file is safe by
construction. Going the other way, a webhook channel or endpoint created by
an import gets a server-minted signing secret that CI cannot display: read
or rotate it from the dashboard afterwards, or inject a known channel
secret into the document from your CI secret store at import time. The
details are in
write-only secrets.
Promote between workspaces
The CLI is workspace-scoped by its API key, so staging-to-production promotion is the same loop with two keys:
AXIORANK_API_KEY=$STAGING_KEY axiorank config export --file axiorank.config.json
AXIORANK_API_KEY=$PROD_KEY axiorank config diff --file axiorank.config.json --exit-code
AXIORANK_API_KEY=$PROD_KEY axiorank config import --file axiorank.config.jsonNext steps
- Config as code: the document format, diff semantics, and write-only secrets.
- GitHub Action: MCP preflight and policy fixtures in the same pipeline.