6.5 KiB
Row 60, bus read: credential status on the broker, round 1 review (Darkwing)
Issue #1549, request comment 27383, packet agents/filbert/work/queue-60/.
Brief: docs/plans/2026-10-10_design-implementation.md, "Bus read:
credential status on the broker". Base 4100fa68. Candidate manifest sha256
99d67e44e226fdf15aeb850bfa2f36a61f3b7f940fad36249ff4bd101f24eedc, 9
files, matching the request.
Verdict: approve. The read gives human and reader sessions service,
account, role, date kind, date and state for their own business, and nothing
that names a token, file or variable. A role session gets human-required,
and any argument gets invalid-request. The broker gets a status function,
never the Credentials object, so it has no path to use(). The read asks
the status on every request, so a date that crosses a boundary while the host
runs shows up without a restart. Nothing blocks. Two notes and the answers to
Filbert's two questions are below.
Method
- I read the whole patch: the
credentialscase and the constructor option inbroker.mjs, the runtime wiring,views.mjs, the WebUI route, both READMEs and the tests. - A detached worktree at
4100fa68withbuild.patchapplied, thensha256sum -con the manifest: 9 OK. - I checked the account rule against the business file loader
(
packages/business/src/business.mjslines 91 to 101): a role whose definition uses Vikunja must havetracker.bot, and a role without Vikunja can't havetracker. - 16 mutants of my own (
r1/mutants.sh, usingagents/darkwing/work/queue-59-review/r1/mut.mjs), each run against one test file and restored from the worktree index. I aimed some at sites Filbert's 16 name, to check the tests kill them for the right reason, and the rest at sites they don't.
Node v26.8.1, TMPDIR=~/darkwing-scratch/rv60/tmp.
Suites
On the candidate, one at a time (r1/tests.sh, r1/gate.sh), from
23:48Z to 23:53:59Z on 2026-10-11:
| Suite | Result |
|---|---|
| packages/bus | 84 pass, 0 fail |
| packages/webui | 41 pass, 0 fail |
| test-auth | 15 passed |
| test-conductor | 17 passed |
| test-config | 24 passed |
| test-discord | 66 passed |
| test-extension-package | 18 passed |
| test-foundation | 44 passed |
| test-queue | 27 passed |
| test-release | 14 passed |
| test-task | 26 passed |
test-task ran with DOCKER_HOST set to a missing socket and skipped its
Docker cases. I didn't run packages/control-board or packages/cli;
Filbert's run has them green, and Sage's gate rerun covers landing.
test-discord passed first time for me, so I didn't see Filbert's timing
failure.
Mutants
13 of 16 fail on the first run (r1/mutants.txt). Each kill failed the test
meant for it.
| Mutant | Fails |
|---|---|
reader-refused: credentials left off the reader list |
all 4 credential tests |
role-allowed: no human-or-reader check |
the role and argument test, the process test |
args-accepted: keys(a, [], []) removed |
the role and argument test |
prefix-no-slash |
the shape test (demo sees demox), the process test |
no-filter |
the shape test, the process test |
sync-label-raw: role @sync |
the shape test, the process test |
sync-no-bot: the sync account null |
the shape test, the process test |
gitea-gets-bot: Gitea takes tracker.bot |
the shape test, the process test |
datekind-fixed: always expires |
the shape test, the process test |
leak-instance: instance kept in the row |
the shape test, the process test |
status-cached: status read once at construction |
the per-request test |
runtime-no-status: the runtime passes no status |
the process test |
serve-no-verb: credentials off BUS_VERBS |
2 WebUI bus tests |
views-no-verb: credentials() removed from views |
2 WebUI bus tests, on a rerun |
account-undefined: bot for bot ?? null |
survives, equivalent |
no-result-check: no #secretCheck(result) |
survives, base code |
views-no-verb survived the first run because I pointed it at the bus suite.
The WebUI is the only caller of views().credentials, and the rerun against
packages/webui/tests/bus.test.mjs kills it. That was my mistake in the
script, not a gap in the tests.
account-undefined is equivalent under a loaded business file. The only
row where bot could be undefined is a Vikunja credential on a role with
no tracker.bot, and the loader refuses that file. The broker tests build
their businesses by hand, so they'd accept one, but the runtime gets its
businesses from the loader.
no-result-check removes a line the base already has for every read, so it
isn't this row's code. No credential row in the fixtures holds a known
token, so nothing reaches it. The process test covers the same leak from the
outside: it seeds a token in a file and in the environment and greps the
output, the log and every bus.sqlite* file.
Notes
1. The re-round meets two rows on four of these paths. Row 74
(351464ce) changed packages/webui/README.md and
packages/webui/src/serve.mjs after 4100fa68. Row 59 edits
broker.mjs and the bus README, and Filbert's overlap note already shows
git apply --3way merging it cleanly. Row 58 touches the webui README too.
When this row re-rounds after 58, the serve.mjs merge is the one to read by
hand: row 74 put its preview checks ahead of routing in the same request
handler that reads BUS_VERBS. Nothing in this review depends on those
lines, so my findings carry over, and on the re-round I'll check the digest,
the merged handler and the WebUI bus and preview tests.
2. test-release is 14, not 4. The gate table in build.md says
"release 4". My run has 14 passed, the same as the other runs today. A typo
in the packet; it doesn't touch the candidate.
Questions
- The Business view. Leave it alone in this row. The brief asks for the endpoint, and the Business view working without a bus host is worth keeping. The reason this read exists is the case the view can't show: a token file rotated after startup, which the host doesn't reread until restart. That only helps Jason if a page puts the two side by side. A later row, after the cutover, could add a "host loaded" column to the Business view when the bus answers and flag a row whose date or state differs from the file's, with the file metadata alone when it doesn't.
- The missing
decisionsrow. Yes, add it. Since this row re-rounds anyway and already edits that table, I'd put the one line in the re-round rather than open a docs row for it. If Sage would rather keep the re-round to the digest, a docs follow-up is fine.