Merge pull request 'Issue 359: a secret given reached the operator as "needs a look", and nothing said why' (#259) from issues/359-a-secret-given-reached-the-operator-as-needs-a-look into main
This commit was merged in pull request #259.
This commit is contained in:
@@ -0,0 +1,44 @@
|
||||
---
|
||||
status: located
|
||||
opened: 2026-10-09
|
||||
located-in: [mesh-controller (cmd/mesh-controller/desk_secret.go, internal/conditions/plain.go)]
|
||||
fixed-by:
|
||||
amended-design:
|
||||
---
|
||||
|
||||
# 359. A secret given reached the operator as "needs a look", and nothing said why
|
||||
|
||||
**Severity: medium.** The one notification meant to tell the operator that a module's own secret changed told
|
||||
them nothing they could act on, and the fall back to borrowed words was silent everywhere.
|
||||
|
||||
## Symptom
|
||||
|
||||
On 2026-10-09 at 23:32 (local) the operator gave a chat module's bot token at the controller's terminal, with
|
||||
the controller's `secret accept` and the value on standard input. The urgent desktop notification that followed
|
||||
read, in full:
|
||||
|
||||
> Novox needs a look — Needs you: read the details to see what to do. The mesh noticed a problem it calls
|
||||
> "secret given" with novox.
|
||||
|
||||
That is the scope's fallback wording ([ADR 0253](../../02-DECISIONS/0253-a-condition-says-itself-to-the-operator-in-plain-words-beside-its-summary.md)),
|
||||
with the verdict kept as [ADR 0258](../../02-DECISIONS/0258-a-desk-click-performs-only-an-acknowledgement-and-an-answer-is-a-one-time-ticket.md)
|
||||
requires. It names neither the module nor what was given, and "read the details" sends the operator elsewhere
|
||||
for the one thing the condition exists to say: a secret changed, and silencing it is the answer when they gave
|
||||
it themselves. The condition was raised on every channel on purpose — the security review of 2026-10-09 wanted
|
||||
a bot token changed by somebody else to be heard of — so the words are the whole of its value.
|
||||
|
||||
## Two faults
|
||||
|
||||
1. **The condition's own words broke the plain rule.** Its producer wrote a headline, an explanation, a needs
|
||||
line and a resolved line of its own; the explanation carried the clock time of the giving. The plain rule
|
||||
refuses a clock time (the channel says when, in the operator's time), so the keeper replaced all of them with
|
||||
the scope's words.
|
||||
2. **The replacement was silent.** The keeper tells a hook of every observation said in borrowed words. A test
|
||||
suite sets that hook and fails on it; the serving controller sets none, so nothing — no log line, no
|
||||
condition — said that a producer's words had been refused, or why. The condition's own unit test built the
|
||||
observation without passing it through a keeper, so the suite's check never saw it either.
|
||||
|
||||
## What is asked
|
||||
|
||||
- The secret-given words pass the plain rule, with a test that holds them to it through a keeper.
|
||||
- Words refused at run time are never silent: the keeper logs the kind and the reason, once per process.
|
||||
@@ -0,0 +1,36 @@
|
||||
# Diagnosis — issue 359
|
||||
|
||||
## 2026-10-09 — the cause, confirmed by a test
|
||||
|
||||
A test in the controller's repository built the secret-given observation as the terminal does (the module, the
|
||||
secret's name, "at the controller's terminal", 23:32) and held its words to the plain rule. The answer was
|
||||
`explanation: a clock time or date (23:32)`. With the time removed and nothing else changed, the same words
|
||||
passed, from the terminal and from a desk. The secret's name, written with a hyphen, is not refused by the rule;
|
||||
the clock time alone was the cause.
|
||||
|
||||
The keeper's fallback (`plainly` in the controller's conditions package) then took the scope's words: "… needs a
|
||||
look", and "a problem it calls" the kind with its hyphens as spaces. Since the producer had a needs line, the
|
||||
verdict stayed "Needs you:" with the fallback needs, "read the details to see what to do."
|
||||
|
||||
## Why nothing said so
|
||||
|
||||
The hook told of borrowed words (`Unworded`) is set only by test suites. In the serving controller it is unset,
|
||||
and the keeper replaced the words without a trace. The suite-wide check in the controller's command package
|
||||
fails any condition a test raises through a keeper with words that are not plain; the secret-given test called
|
||||
the producer directly and asserted on its fields, so that check never ran on it.
|
||||
|
||||
## The fix
|
||||
|
||||
In the controller's repository, on its own pull request, linked to this issue:
|
||||
|
||||
- The words name the module and the machine, say the secret's name as words ("telegram token"), say how it was
|
||||
given, and carry no time: "New secret given for telegram on" the machine; "If you gave it, nothing else is
|
||||
needed. If you did not, somebody else now holds what telegram acts with." The needs line says silencing is the
|
||||
answer when the operator just gave it. Severity (urgent) and the one answer (silence for a week) are unchanged.
|
||||
- A test holds the words to the plain rule and observes them through a keeper, so the suite's check covers them;
|
||||
it fails against the old words with the cause above.
|
||||
- With no hook set, the keeper logs which kind is said in borrowed words and why, once per kind and reason per
|
||||
process, so a refusal in the running controller is visible in its journal.
|
||||
|
||||
Ruled out: the bound on lengths (the old needs line was 102 characters of 120), the outward content rule (no
|
||||
address or secret shape in the words), and the machine name.
|
||||
Reference in New Issue
Block a user