What it checks
Two analyzers, both on by default; -sxreg and -sxserved select one
explicitly.
These are the shapes of mistake the tool looks for, described so you know what it is for. The tool is early and due a redesign — for the exact diagnostics your version emits, run it.
sxreg — registrations and compositions#
Service ids. An id should be an exported package constant, path-shaped, and rooted in the registering package's import path. That rooting rule is the point: ids are unique by construction when they start with the package that declares them, and it is precisely the guarantee the runtime cannot check — at run time there is no such thing as "the package this registration is written in".
const ID = "example.com/box/serve" // in package example.com/box/serve
Registration chains. Every chain must reach a terminal — .Register()
or fw.Solo — and must declare an alias. A chain that is built and then
dropped compiles perfectly and registers nothing; that is a mistake with
no runtime symptom at all, because the service simply isn't there. Alias
grammar is validated too.
Config struct tags. The engine's rules, mirrored:
conf:/env:/pos:grammar, and the mandatoryjson:name- the dead
arg:tag - the
Versionmandate - positional shape — contiguity, at most one
rest, no required index after an optional one - positionals declared on non-applet services
- separator runs (
a--b) that would forge a boundary in a derived environment name
Migration chains. From-versions contiguous, each step's input type matching the previous step's output, and the final step's output equal to the current config type. A chain that stops one version short is a startup error you would otherwise meet on a machine with an old config file — which is to say, in production.
Compositions. Accept and Order must name registrations that are
actually catalogued, Order must be a subset of Accept, and duplicates
are reported. Ambiguous dependencies — two unranked candidates for one
slot — are caught here rather than at startup.
sxserved — the two-phase front door#
conf.New and conf.NewLoader(...).Load() return a served boolean.
When it is true, the run was already answered — --help printed the
schema, --write-config wrote the file, --upgrade-config migrated it,
--validate-config found nothing wrong — and the program should return.
See the conf front door for the exact set, including
which failures are deliberately not served.
Discard that value and --help prints the help and then the program
runs anyway. Nothing errors; the tool just does its job when the user
asked a question. The analyzer flags the discard.
Where this fits#
These checks exist because the framework already enforces the same rules at startup. What the analyzer changes is when you find out — in an editor or in CI, rather than the first time someone runs the binary with a real config file.
Both back-ends are documented from the other side too: fw for the framework's runtime checks, and conf for the standalone engine's.