CB-606: config values are checked against their valid set
One entry for all four fields rather than four entries — they are one defect of shape, and the gotcha worth recording is the shape, not the instances. The auth.mode case is the one to keep: a typo behaved as loopback-trust, and the exposure check only fires on a non-loopback bind, so a loopback bind hid it end to end. The daemon started clean and authenticated nobody.
+44
-3
@@ -1724,9 +1724,9 @@ special-cases the exact string `"claude-code"`. Nothing caught it before the spa
|
||||
|
||||
**Gotcha.** The composite constructor separately refuses two adapters claiming the same profile name
|
||||
("worker profile '…' is claimed by two peer adapters"), so that failure mode has always been loud.
|
||||
Checking for the same shape elsewhere found three more unvalidated fields — `auth.mode`, the
|
||||
per-profile `placement:`, and the top-level `placement:` policy, which is validated but only lazily
|
||||
at first spawn. That is CB-606; until it lands, a typo in those three is still accepted silently.
|
||||
|
||||
Checking for the same shape elsewhere found three more fields, all fixed the same way by **CB-606**
|
||||
(2026-08-16) — see *Every config value is checked against its valid set* below.
|
||||
|
||||
---
|
||||
|
||||
@@ -1772,6 +1772,47 @@ the sourcing gap, and the unit file gives the operator no prompt to look for it.
|
||||
|
||||
---
|
||||
|
||||
## Every config value is checked against its valid set
|
||||
|
||||
**What.** A config value the daemon does not recognize now **refuses to start**, naming the field, the
|
||||
value, the accepted set, and what would otherwise have happened. Four fields carried this defect and
|
||||
all four are covered: a profile's `kind:` (CB-604), `auth.mode`, a profile's `placement:`, and the
|
||||
top-level `placement:` policy (all CB-606).
|
||||
|
||||
```
|
||||
refusing to start: auth.mode=toekn is not recognized — accepted values are loopback-trust,
|
||||
token (case-insensitive); an unrecognized mode would otherwise silently fall back to
|
||||
loopback-trust, which authenticates nobody.
|
||||
```
|
||||
|
||||
**On.** Always on; nothing to configure. Every valid value still works case-insensitively, and every
|
||||
absent value keeps its old default — `kind:` → `claude-code`, `auth.mode` → `loopback-trust`, a
|
||||
profile's `placement:` → `tab`, the policy → `fixed`.
|
||||
|
||||
**Why.** All four fields had the same shape: the value was lower-cased in a compact constructor, then
|
||||
compared against exactly **one** string. Anything else fell through to the other branch silently. So
|
||||
a typo was accepted, did nothing the operator asked for, and reported no error.
|
||||
|
||||
`auth.mode` is why this is a release blocker rather than tidying. A typo of `token` behaved as
|
||||
`loopback-trust`, and `validateAuthExposure()` only fires on a **non-loopback** bind — so on a
|
||||
loopback bind, the common case, the mistake was invisible end to end. The daemon started cleanly and
|
||||
authenticated nobody, while the operator's config said `token` and the operator believed it.
|
||||
|
||||
**Gotcha — the general lesson, not the instances.** CB-604 fixed `kind:` alone. The brief for it also
|
||||
asked the worker to *report* any other field with the same shape and explicitly not to fix them. That
|
||||
one question found the other three. **When you fix a defect of shape, ask what else has that shape**
|
||||
— the instance you noticed is rarely the worst one. Here the field nobody had filed a ticket about
|
||||
was the field that turned authentication off.
|
||||
|
||||
Two implementation notes worth keeping. The top-level policy was already validated, by
|
||||
`PlacementPolicies.fromName` — but **lazily, at first spawn**, through the supplier in
|
||||
`CompositePeerLauncher` that re-reads live config. So a bad name still started a daemon that looked
|
||||
healthy and failed much later. It is now called eagerly at load as well, which also covers
|
||||
`ConfigRef.reload()`. And the check calls `fromName` rather than copying its list, so there is still
|
||||
one source of truth for what a valid policy name is.
|
||||
|
||||
---
|
||||
|
||||
## Backfill status
|
||||
|
||||
This page was started after the fact, so it is **not yet complete**. Entries above are written from
|
||||
|
||||
Reference in New Issue
Block a user