0032 — One configuration file, one binary, one chart¶
Status: Accepted; applies 0007, 0018; refined by 0036 Date: 2026-10-02
Context¶
The services read about a hundred environment variables, three binaries are
shipped (access-issuer, github-roster, slack-roster) and the chart is
named after one of them. Environment variables are not validated as a whole, an
unknown one is ignored silently, and a secret and a tuning knob look the same.
The policy rule that only declared secrets travel in the environment
(0002) is broken by the
count alone.
Decision¶
- Configuration is one file, validated against a schema. An unknown key
refuses to start and names its replacement, as 0007 already requires of the
policy. The chart passes
configthrough to the file. - Only declared secrets come from the environment, each named in the schema.
- Telemetry is configured by the OpenTelemetry
OTEL_*variables only, read by the SDK; nothing restates them. A trace carries no personal data in a span or a label. - The hundred environment variables are retired.
- One binary,
sluis, with subcommandsserve(the issuer, console and hub),tick(a reconciler'sTick, for one target or all) andmigrate(0031). One chart,sluis.
This is a breaking change, shipped in a 1.x minor release as 0007 allows and
named **Breaking:** in the CHANGELOG with the migration spelled out: the old
binaries, the old chart name and every retired variable go in one release, and a
retired variable that is still set is refused at start, not ignored.
Consequences¶
An installation rewrites its values once. A removed binary is not kept as an alias. The reference for the file, generated from the schema, replaces the environment tables in reference/configuration.md.
Alternatives considered¶
Keep the environment and add a file beside it. Rejected: two sources of truth, and the old one's silence about unknown names stays.
Keep three binaries with a shared file. Rejected: three images to release
and pin for one product, and tick on Lambda is the same binary as serve.
Accept retired variables with a warning for a release. Rejected for the reason 0007 gives: a warning that no pipeline surfaces is silence.
Implementation note: the command surface¶
Shipped in two changes. The configuration file came first (v1.52.4); the one
binary and the one chart came second, and tick is a third, with the leases
of 0029.
sluis serve --config <file> the issuer, the hub and the console
sluis controller github --config <file> the GitHub reconciler's loop
sluis controller slack --config <file> the Slack reconciler's loop
sluis migrate --from <file> --to <file> 0031: copy the State between storages (two `serve` files)
sluis --version | --help
controller <target> is the loop, tick <target> is one pass. The
Deployments the chart renders today are loops (an interval, a watch, one
replica, no lease), and calling them tick would promise a lease and a single
pass that do not exist yet. They are named for what they are, controller, and
tick <target> will be added beside them when 0029's lease is built, calling
the same reconciler Tick; controller <target> then becomes the loop that
calls it on an interval, and nothing about it is renamed. The ADR's tick for
"one target or all" is the later command; there is no rename to make now.
Each command reads one file with its own schema: serve.schema.json,
controller-github.schema.json and controller-slack.schema.json under
schemas/config/, replacing access-issuer, github-roster and slack-roster
(the Go types are config.Serve, config.ControllerGitHub and
config.ControllerSlack). The chart's values follow: config is serve's,
and controllerGithub.config and controllerSlack.config are the controllers'.
The chart's Deployments run the one image with the command as their first
arguments.
The chart keeps what an installation's objects are named from, so the move is a
rollout and not a re-creation: the controllers' objects are still
<full name>-github-roster and <full name>-slack-roster, the paths the chart
mounts are unchanged, and the telemetry service names are unchanged. The one
change of name an installation must act on is the chart's own, which is part of
every object's name; nameOverride and fullnameOverride keep it, and the
migration is in
reference/configuration.md.
The old binaries, the three images and the access-issuer chart are not
published after this change: as the decision says, no alias is kept.