Gaugedocs
Functional alpha v0.1.0-dev GitHub

Guides

From a clone to a failing build.

There is no tagged release. The repository is the install path, and the first useful run takes one command. This page covers the two commands, the flags they accept, a CI job that fails on findings, and the checks a contribution has to pass.

Prerequisites

Go 1.27.3 or newer. No credentials, no wallet, no Stellar SDK and no configuration beyond the command. Gauge reads public Horizon data over HTTPS, so a network that reaches horizon-testnet.stellar.org is enough for the first run.

Shell
git clone https://github.com/posture-sec/guage
cd guage
go build -o stellar-gauge ./cmd/stellar-gauge
./stellar-gauge version

Building once is faster than go run on every invocation, and it gives CI a binary to cache. Both paths run the same code.

check: one account, no policy file

check takes the network, one endpoint and one or more G addresses. It applies the live rules that need no declaration and prints a report. Five of the seven can fire here; flag-drift and id-no-home-domain compare a declared expectation, so only audit can raise them.

Shell
./stellar-gauge check \
  --network testnet \
  --endpoint https://horizon-testnet.stellar.org \
  --fail-on warn \
  GDSX2WUFUT7KCMTUNG3IUQWIUQSC4XNKQ5NTGEZRKLTMLCSJTCUVBEVG
FlagDefaultNotes
--network(required)mainnet, testnet or a full passphrase. There is no default and no discovery.
--endpoint(required)May be repeated by the parser, but exactly one is accepted at v0.1. Must be HTTPS, except loopback.
--formattexttext or json. Any other value exits 2.
--fail-onhighhigh or warn. Sets the severity at which a finding produces exit 1.

Positional arguments are the accounts. Each must be a canonical G address. An M address, a C address, a secret seed or an arbitrary string is refused with a specific message, and the value is never echoed.

audit: the whole policy

audit reads gauge.toml and audits every declared account. It has no positional arguments and no network flag, because both come from the file.

Shell
./stellar-gauge audit --config gauge.toml --fail-on warn
./stellar-gauge audit --config gauge.toml --format json
FlagDefaultNotes
--configgauge.tomlPath to the policy. A missing or rejected file exits 2 before any request.
--formattexttext or json. markdown is refused with "not implemented yet".
--fail-onhighhigh or warn.

Accounts are fetched in policy order through a pool of at most eight requests. A 404 becomes the acct-missing finding and the run continues. Any other read failure cancels the remaining fetches and exits 3, so a partial report is never rendered as a full one.

Reading the result

0 Pass

The run completed and every evaluated rule agreed with the policy.

1 Findings

A finding reached --fail-on. The report is complete and trustworthy.

2 Config or usage

A bad flag, a rejected policy, an unknown key or a secret seed. Fix the input.

3 Source or internal

Unreachable endpoint, malformed or oversized response, or a rule panic. Do not treat it as a pass.

A failing job is the product working. Exit 1 means the chain and the policy disagree in a way you asked to be told about. Exit 3 means Gauge could not form a trustworthy opinion, which is also not a pass. Alerting should distinguish the two: exit 1 is a posture change, exit 3 is an availability or data problem.

Wire it into CI

A scheduled or pull-request job needs no secrets. This example audits on every push and once a day, and keeps the report as an artifact for the run that failed.

.github/workflows/gauge.yml
name: gauge

on:
  push:
    branches: [main]
  schedule:
    - cron: "17 6 * * *"
  workflow_dispatch:

jobs:
  audit:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-go@v7
        with:
          go-version: "1.27.3"
      - run: go build -o stellar-gauge ./cmd/stellar-gauge
      - name: Audit the declared accounts
        run: ./stellar-gauge audit --config gauge.toml --format json > report.json
      - if: always()
        uses: actions/upload-artifact@v7
        with:
          name: gauge-report
          path: report.json

Start on testnet. Moving to mainnet changes network and endpoints in the policy, and nothing in the job. The repository pins its own actions by commit SHA; consumer workflows can use release tags.

For a merge gate, run the audit on the pull request and leave the policy file under review like any other code. An acceptance that changes a red job to green should arrive as a visible policy diff with a reason, not as a CI variable.

Working with JSON

--format json prints one object with tool_version, network, ledger, accounts, exit_code and limits. Each account carries a snapshot and a findings array; findings carry rule_id, severity, account, message, evidence, fingerprint and accepted. The output is indented, stable and HTML-escaped off.

Shell
./stellar-gauge check --network testnet \
  --endpoint https://horizon-testnet.stellar.org \
  --format json G... \
  | jq '{ledger, exit_code, rules: [.accounts[].findings[].rule_id]}'

The report header includes the ledger the endpoint reported at read time, so an archived report can be tied to a point in chain history. The limits footer is part of the JSON, not only the text output.

Advice by account role

Issuer
Declare all four flags explicitly. An issuer's flags decide what it can do to holders. Leaving clawback undeclared is what flag-undeclared-clawback exists to catch.
Treasury
Declare every flag as false unless the account issues. A treasury that has clawback enabled is a fact worth failing a build over, even before role severities land.
Distribution
Start with flags, then add expectations as rules ship. Signer and threshold expectations are validated now, but no live rule compares them yet.
Merchant
Use check for a quick read and a policy once the set of accounts is stable. A merchant account is usually the simplest to describe, so drift stands out.

These are authoring recommendations, not severity profiles. Role-based severity overrides are task 3.4 and are not active.

Working on Gauge

Every contribution starts from the roadmap. Find the task, check its dependencies, write the failing test first, then the smallest change that passes.

Checks before a pull request
gofmt -l .                       # must print nothing
go vet ./...
staticcheck ./...                # v0.8.2
go test ./... -race -count=1
govulncheck ./...                # v1.9.0
scripts/check_roadmap_touched.sh origin/main
scripts/roadmap_progress.sh --check ROADMAP.md
scripts/generate_issues.sh --check

Install the pinned tools with go install honnef.co/go/tools/cmd/staticcheck@v0.8.2 and go install golang.org/x/vuln/cmd/govulncheck@v1.9.0. The fuzz targets run one at a time, because -fuzz refuses multiple packages: go test ./internal/strkey -run '^$' -fuzz=FuzzClassify -fuzztime=10s, then the same against FuzzText and FuzzFenced in internal/sanitize. They are smoke runs a contributor makes locally, not CI jobs.

Adding a rule means a new pure function in internal/rules, a registration entry, a positive and a negative fixture, updated golden files, and matching updates to PRD.md 6.1 and ARCHITECTURE_ESSENTIALS.md 8. The roadmap rule applies to every change, including documentation: ROADMAP.md is updated in the same pull request.

The boundary

A green job means the rules that ran agreed with your policy. It does not mean the account is safe. Gauge documentation

Gauge reads public ledger state, compares it with a file and reports the difference. It cannot see key custody, signer independence, off-chain approvals or who can edit the CI job that runs it.