ADR 0274: an agent proposes a shared instruction section, and every node takes it only on the operator's warrant

The operator asked for mesh tools to add shared instructions and context. Issue 340 made that text the
terminal's until a surface of the operator's own exists; the operator channel is that surface. Proposed,
for the operator to accept.
This commit is contained in:
jochen
2026-10-10 12:06:38 +02:00
parent 7c866e7356
commit 891608814e
4 changed files with 302 additions and 2 deletions
+4
View File
@@ -501,6 +501,10 @@ asking, never the act. **Decided by** ADR 0152, 0175, 0234, 0259, 0272.
of them (a path, an address); opened with `detail` only on a `private` channel or through the mesh MCP server.
- **agent** — a coding agent: the operator's, or one the mesh runs. Not the node-engine, and not the
build seat's holder, whose seat name `node-build-agent` is an identifier to rename.
- **instruction section** — one named section of the managed instruction file, which every agent session on the
nodes it is for reads first, as the mesh's word: set at the controller's terminal in the agent module's
settings, or **proposed** by an agent and made active on each node only by the operator's warrant, which that node
proves itself ([ADR 0274](../02-DECISIONS/0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md)). A hand-over between sessions is one.
- **personal rule** — one short text in the operator's own words about how the operator wants their agent
to work with them, registered for the operator (the **operator scope** of the agent module) and rendered
into the agent's home on every node that names an operator account. Not a mesh-wide instruction section,
@@ -0,0 +1,262 @@
---
topic: what runs on it
status: proposed
date: 2026-10-10
deciders: jochen
reconstructed: false
extends: 02-DECISIONS/0273-the-agents-home-is-the-modules-and-the-operators-personal-rules-and-lessons-are-registered-through-it.md
---
# 274. An agent proposes a shared instruction section, and every node takes it only on the operator's warrant, which it proves itself
## Context
[Issue 340](../04-ISSUES/340-an-agent-can-plant-a-hook-in-every-agent-session-on-the-mesh/00-report.md) found that the
agent module's tools cannot tell the operator from an agent: the tool runner acts for any caller of the mesh MCP
server and is not told who called. An instruction section registered for every node lands in the managed instruction
file, which every Claude Code session on those nodes reads first, as the mesh's own word. Anything that could write
one could ask the operator's agent on every node to act for it, at the next session there: a prompt injection that
stays. The operator decided on 2026-10-09 that shared text is set at the controller's terminal, in the module's
settings, "for now", and named the way back: "once we build a UI, we can also update the context through it". A
surface of the operator's own, which can tell the operator from an agent, was the intended way.
That surface exists now. [ADR 0259](0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md)
lets any module ask the operator a question and act on the answer with a **warrant**: the router's record that a
person chose one option of one ask, published on a subject only the router may publish and kept in a record only the
router writes. An option at the level **approve** is carried only by a channel that proves its sender (Telegram,
linked to the operator's account, placed where no agent can become root), so a warrant for it is the operator's
own answer. The controller already acts on warrants, and its `rehearse` command shows the whole path live.
The operator asked on 2026-10-10: "our claude-code module should have mcp-tools to add mesh-shared
instructions/context". Agents keep shared text up as they work: a rule learned, a hand-over from one session to the
next on another node, the state of a piece of work. Today each of those is a trip to the control-node's terminal,
a line typed with the text as a list of lines, which an agent can only hand the operator to type.
The record was searched first ("propose instructions approval warrant", "shared instructions agent hand-over
context"): nothing beside ADR 0273, whose §3 route 2 already puts the operator's personal rules behind a warrant on
an authorising ask, and issue 340.
**Where it would land, measured in the module's code on 2026-10-10.** A registration is a key in the module's
`config` state on the bus. Every node's tool runner that carries the module writes that state, and every node renders
what it finds there. So a record on the bus proves nothing about who put it there: a warrant copied into the bus beside
a text is a string anyone with a tool runner's credential could write. Issue 340 lists the same fact as still open
for text already there ("Text at the mesh or node scope written straight into the bus state still renders").
### Against GENESIS
- **Failure must be loud.** A proposal nothing can carry to the operator is refused at once, in words, never left
waiting for an answer that cannot come.
- **The mesh owns the truth.** The approved text is the mesh's, rendered on every node it is for, not a file an
agent edits.
- **The mesh remembers.** A hand-over written once reaches the next session on every node, so nothing has to be
explained twice.
## Considered Options
### Who may make a shared section active
1. **The tool's caller, as before issue 340.** Rejected in issue 340: the caller may be any agent.
2. **The controller's terminal alone** (issue 340's decision). Safe, and kept as one of two ways. Alone, it makes
every shared text a trip to the control-node, and an agent can only describe what to type.
3. **The operator, on a warrant: an agent proposes, the operator approves on a channel that proves who answered.**
Chosen, beside 2.
### Who proves the warrant, and where the approved text is kept
1. **The instance that hears the warrant writes the text into the module's state on the bus**, as a registration,
and every node renders it. Rejected: the state is written by every tool runner carrying the module, so every node
would render whatever is written there with a warrant's shape beside it. That is issue 340's open item, widened.
2. **The controller verifies the warrant and writes the text into the module's settings**, the terminal's own store.
Weighed. It is durable, and a node that joins later gets it. But it makes the controller write a key it keeps for
the terminal on another module's ask, and lets any asker's warrant write terminal-only settings once that path
exists. It also takes a module's own decision (what its ask says, what its answer does) into the controller.
3. **Every node proves the warrant itself and keeps the approved text in a file of its own.** Each instance reads
the router's own record of the ask under the module's name, composes the ask again from the proposal, holds the
warrant to it, and only then writes the section into its own file, which is what it renders. Chosen. A record
written into the bus by anyone else becomes active nowhere, and a record deleted from the bus removes nothing.
### What "context" is
1. **A separate managed file of shared context** that sessions are told to read. Rejected: a second file, a second
way to reach a session, and a second thing to prove, for text the instruction file already carries.
2. **An instruction section.** Chosen. A hand-over, a rule or the state of a piece of work is a named section, read
first in every session it reaches, approved, replaced and removed like any other. One mechanism.
### Which kinds may be proposed
1. **Every text kind** (sections, output styles, skills, commands, subagents). Rejected for now: a skill is invoked
by the model on its own when its description matches, may carry scripts, and its front matter decides what runs.
Approving one on a phone is a different judgement from reading a paragraph.
2. **Instruction sections only.** Chosen. The other kinds stay the terminal's, as issue 340 left them.
### How the operator reads what they approve
1. **The whole text on the phone, always.** Rejected: the router's content rule refuses a path, an address or a
long unbroken word in any message that leaves the mesh, and a message has a length bound.
2. **A fingerprint only.** Rejected: nobody approves what they cannot read.
3. **The whole text when it is short and every line may leave the mesh; else the first lines, the size and a
fingerprint, and the line that shows all of it at the controller's terminal.** Chosen.
## Decision
### 1. An agent proposes; nothing is active until the operator approves
The agent module (`claude-code`) gains two tools:
- **`claude_code_instructions_propose`** takes a scope (`mesh` for every node, or `node` and a list of nodes), a
name and the text, or `remove` for a section approved before. It refuses what issue 340 refuses and more (§5),
records the **proposal** in the module's `proposals` state (the action, the scope, the nodes, the name, the text,
the text's SHA-256 digest, the node it came from and when), and publishes one ask on the `operator-channel` seat
under the module's own name. It answers with the proposal's id, its fingerprint (the digest's first twelve
hexadecimal digits) and the question the operator was asked. **It changes nothing on any node.**
- **`claude_code_proposals`** lists the proposals, newest first: what each does, where it reaches, its
fingerprint, and what this node made of it (waiting, approved, declined, discarded at expiry, refused). Given an
id it answers that proposal's whole text and digest. It also lists the sections approved on this node.
A proposal that would replace an approved section of the same name and scope says *Replace*. A removal is a
proposal too (§4).
### 2. The ask
One ask per proposal, composed from the proposal alone, so that every node composes the same one:
- **headline**: "Add Claude instructions '<name>'?" ("Replace", "Remove"), shortened to "Add Claude instructions?"
when the name makes it longer than the router allows;
- **explanation**, first line: "Add instructions '<name>' to every Claude session on the mesh?", or "on <the
nodes>"; then the node it was proposed from and when, the text's lines, bytes and fingerprint, and that every new
session there reads it as the mesh's own word until it is removed the same way; then **the whole text** when it is
at most 2000 bytes and 40 lines and every line may leave the mesh, or else **its first lines** (at most 20 lines
and 1200 bytes), each line that may carry a path, an address or a long word replaced by a marker, and the line
that shows it all: `mesh-cli ask claude-code claude_code_proposals '{"id": "<id>"}'` at the controller's
terminal, whose fingerprint must be the one on the phone;
- **two options, Approve and Decline, both at the level approve**, as the controller's rehearsal asks: only a
channel that proves who answered carries either, so a click on a channel that does not prove its sender ends
nothing. Each option binds the digest of its act: the proposal's id, action, scope, nodes, name, the text's
digest, where it came from and when, and the answer;
- **expiry**: a day less ten minutes after it was proposed; at expiry the proposal is discarded and nothing
changes. An ask that authorises never defaults (ADR 0259);
- **about**: the scope, the nodes and the name, so a newer proposal for the same section replaces an older one
still open, and the older one is discarded.
The router caps open asks at three per asker. A fourth proposal is refused by the module, in words, before it is
asked.
### 3. Every node proves the warrant itself
A proposal record on the bus proves nothing, because every tool runner carrying the module writes that state. So
**each node**, for each proposal it has not decided yet, on every word from the router, on every change of the
proposals, and once a minute:
1. reads the router's **own record** of the ask, under the module's name. The bus lets only the router write that
record, and lets the module read only its own asks (ADR 0259 §3). An ask still open is left for the next look;
2. composes the ask again from the proposal, and holds the warrant to it with the SDK's own check: the same asker
and ask, **the ask's digest the router took**, a person's choice, an option the ask offered, at that option's
level, given before the ask expired. Then the chosen option's bound act must be this proposal's act, and the
text's digest must be the digest the proposal names. An ask published under the module's name with other words,
a proposal changed after it was asked, a warrant for another ask, or an answer at another level is refused and
said, and nothing is applied;
3. on **Approve**, writes the section into **its own file** in the module's state directory, if the proposal reaches
this node (the mesh scope, or a node scope naming it), and renders. On **Decline**, an expiry, a cancel, a
replacement or the router's refusal it applies nothing. Either way **it records the proposal as decided and never
decides it again**: a warrant heard twice, or replayed into the bus, changes nothing;
4. takes closed asks oldest warrant first, so two approvals of the same section end with the later one.
The managed instruction file renders the approved sections under their own heading, "Instructions the operator
approved", each with where it was proposed from and when it was approved, after the mesh's own text, the
instructions table and the terminal's sections.
**What the operator approved and when is the router's record**, kept 30 days after the ask closes. A node that was
away for longer than that, or joins later, cannot prove an approval made before, and **does not render it**: its
`claude_code_proposals` says which approvals it could not prove, and the operator proposes the section again or sets
it at the terminal. That is the cost of option 3 and is accepted: an approval the node cannot prove is the case this
decision exists to refuse.
### 4. A removal needs the same approval
An approved section is removed only by a proposal with `remove`, approved the same way, whose ask names the section,
its scope and nodes, and the fingerprint of the text it removes. A node removes the section only when the approved
removal names the text it holds. A proposal record deleted from the bus removes nothing, because the node's own file
is what renders. A section set at the terminal is changed there, and a proposal of the same name is refused.
### 5. What is refused, before anything is asked
- **What issue 340 refuses, kept**: a shell line (`` !`…` `` or a block opened with ```` ```! ````); front matter of
any kind, naming `hooks`, `mcpServers`, `permissionMode` or `allowed-tools` when it holds one; and an `@`
reference, which the instruction file reads in as a file;
- anything shaped like a secret (a key block, a known token's shape, a value given to a secret's name), because the
text is read by every session and shown on a phone;
- an empty text, one that is not text, or **more than 16 KiB**: every session reads all of it, every time;
- the home scope (an account's own directory keeps its own rules, ADR 0273) and `all` at the node scope (that is the
mesh scope);
- a name the controller's terminal sets;
- **when no channel that proves its sender is on the mesh** (no channel kind promising a choice, an exact rendering
and a verified sender): refused at once, naming the terminal's line instead. The router judges again when it takes
the ask, and refuses an ask none of its ready channels can carry; that refusal reaches every node as the ask's end,
and the proposal is discarded. **Nothing waits for an answer that cannot come, and nothing is active without one.**
### 6. The warrant is recorded in the hand-act log
The controller gains the verb **`warranted`** (asker, ask, what was done). It reads **the router's own record** of
that asker's ask, never the caller's account of it, and records who chose, through which channel, with which proofs
and which answer, under the verb `warrant` that the hand-act log already counts as a person's decision, not a repair.
It records once per ask, under an id the ask decides, however many of the module's instances ask. It refuses an ask
still open, one that ended without a person's choice, and another asker's. Every node that decided an Approve or a
Decline asks it, again every ten minutes for a week while the controller has not taken it, so a node that is away
leaves nothing unrecorded.
### 7. Nothing proposed is logged
The module's log names a proposal by its id, action, scope, name and fingerprint. It never logs the text, and never
the ask's explanation, which carries it.
### 8. What this changes in the earlier records
- **Issue 340, decision 2** ("shared agent text is the terminal's, for now"): instruction sections at the mesh and
node scopes gain a second way, the operator's warrant, beside the terminal. The other kinds stay the terminal's.
The registering tools still refuse every shared kind and now name the proposal tool. The issue's still-open item
about text already on the bus is unchanged: approved sections never come from there.
- **ADR 0273 §3** stands. Its route 2, a warrant for the operator's home, is built the way §3 here proves a warrant:
on every node, from the router's own record, against an ask composed again from what was proposed.
## Consequences
- An agent hands work over to the next session on any node with one tool call and one tap on the operator's
phone. The operator sees the text, or its first lines and a fingerprint, before it reaches a session.
- No agent, and nothing holding a tool runner's credential, can make text active in another session: what it
writes to the bus is a proposal, and every node checks the router's own record against the exact text.
- **What got harder:**
- every shared section is a question to the operator, at most three open at once;
- a long text is read at the controller's terminal before it is approved;
- a node away for more than 30 days, or joining later, does not render a section approved before, and says so;
- each node keeps its own copy of what it approved, so `claude_code_proposals` on one node speaks for that node;
- the module now asks the operator, so it uses the `operator-channel` seat, and its grant on the bus grows by
the asker's subjects and its own records there.
## How it is checked
| Rule | Checked by |
|---|---|
| A proposal changes nothing until the operator answers, and asks at the level approve | the module's test: the proposal's ask is published under `ask.claude-code`, passes the SDK's `Check`, offers Approve and Decline both at the level approve, each binding an act digest; the open ask leaves the rendered instruction file without the text |
| The text becomes active on a node only on a warrant that node proved | the module's test: an approval in the router's record makes a second node render the section; a decline, an expiry, the router's refusal, a text changed after the ask (with or without its digest, and past what the phone shows), another ask's words under the module's name, an answer after expiry, at the level acknowledge, with nobody choosing, or for another ask each render nothing and are recorded as decided |
| A warrant is acted on once | the module's test: the same warrant read again changes nothing and is recorded once; an approval replayed into the bus after its section was removed brings nothing back |
| A removal needs the same approval; a deleted record removes nothing | the module's test: deleting the proposal record leaves the section rendered; proposing the removal leaves it; the approved removal takes it out |
| A node scope reaches only its nodes | the module's test: a section approved for one node renders there and not on another |
| Fail closed when no channel proves its sender, or the bus refuses the ask | the module's test: with no verified-sender channel the proposal is refused naming the terminal's line, and nothing is kept or asked; an ask the bus refuses leaves the proposal never asked and never active |
| Issue 340's refusals hold | the module's test: a shell line, a shell block, front matter (with `hooks` or `allowed-tools`, or any), an `@` reference, a key block, a value given to a token's name, more than 16 KiB, a NUL, the home scope, `all` at the node scope and a name the terminal sets are each refused and nothing is asked |
| A long text is shown in part and read whole at the terminal | the module's test: a line with a path is not on the phone, the explanation names the terminal's line and the fingerprint, and `claude_code_proposals` with the id answers the whole text and digest |
| The text is never logged | the module's test: the module's log over a proposal and its approval holds the id and not a line of the text |
| The tools are served | the module's test through its real tool dispatch: propose, list, and the registering tool's refusal naming the proposal tool |
| The warrant is recorded once, from the router's record | the controller's tests: the entry carries who chose, via which channel and the proofs from the router's warrant; an ask still open, ended without a choice, another asker's or another ask's, or the controller's own is refused; the entry is written once however often it is asked, against a real bus; the verb's line is not taken for a repair and is not the terminal's alone |
| Live, after rollout | an agent proposes a hand-over for every node; the operator's phone shows "Add instructions '…' to every Claude session on the mesh?" with Approve and Decline; after Approve a new session on another node reads the text, and `hand-acts` shows the warrant |
## References
- [Issue 340](../04-ISSUES/340-an-agent-can-plant-a-hook-in-every-agent-session-on-the-mesh/00-report.md) — the
decision this amends
- [ADR 0259](0259-an-ask-is-a-message-on-the-bus-any-channel-answers-it-and-the-asker-acts-on-a-warrant.md) — the ask
and the warrant
- [ADR 0273](0273-the-agents-home-is-the-modules-and-the-operators-personal-rules-and-lessons-are-registered-through-it.md)
— the module owns the agent's home; the operator's rules on a warrant
- [ADR 0216](0216-the-agents-configuration-is-registered-through-its-module-at-three-scopes-and-served-as-one-plugin.md)
— the three scopes
- [to-be 36](../03-DESIGN/01-to-be/36-the-operators-agent-on-a-machine.md) §11 — the design
@@ -2,7 +2,7 @@
layer: to-be
status: in-progress
code: [mesh-catalog modules/claude-code]
updated: 2026-10-09
updated: 2026-10-10
decisions:
- 02-DECISIONS/0273-the-agents-home-is-the-modules-and-the-operators-personal-rules-and-lessons-are-registered-through-it.md
- 02-DECISIONS/0266-on-the-control-node-agents-run-under-an-account-of-their-own-that-cannot-become-root-without-a-person.md
@@ -497,6 +497,30 @@ and the pending requests;
`claude_code_lesson_register`, `_list`, `_accept`, `_decline`. Every tool that writes into the operator's
home goes through the two routes above.
## 11. Shared instruction sections an agent proposes and the operator approves
*Added 2026-10-10 by [ADR 0274](../../02-DECISIONS/0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md) (proposed). This section is built against that
record while it awaits the operator's acceptance; the frontmatter names it once it is accepted, as `records.py` holds
a design to accepted records only.*
An instruction section for every node, or for some, has two ways in: the controller's terminal (issue 340), and **a
proposal an agent makes and the operator approves** on a channel that proves who answered. A hand-over, a rule
learned, the state of a piece of work: each is a named section, read first in every session it reaches.
| Step | What happens |
|---|---|
| propose | `claude_code_instructions_propose` (scope `mesh`, or `node` and the nodes; a name; the text, or `remove`) refuses what issue 340 refuses and a secret's shape, more than 16 KiB, a name the terminal sets, and at once when no channel proves its sender; keeps the proposal in the `proposals` state; publishes one ask under the module's name on `operator-channel` |
| ask | composed from the proposal alone: "Add instructions '<name>' to every Claude session on the mesh?", the text whole when short and sayable, else its first lines, its size and fingerprint and the terminal line that shows all of it; Approve and Decline both at the level approve, each binding the proposal's act; a day to answer |
| prove | every node reads the router's own record of the ask under the module's name, composes the ask again, holds the warrant to it (the ask's digest, the option's bound act, the text's digest, in time), and only then writes the section into its own `approved.json`; decided once per node, oldest warrant first |
| render | the managed instruction file gains "Instructions the operator approved", after the terminal's sections, from the node's own file, never from the bus |
| remove | a proposal with `remove`, approved the same way; a deleted bus record removes nothing |
| record | each node that decided an answer asks the controller's `warranted`, which reads the router's record and writes the hand-act log once per ask |
| list | `claude_code_proposals`: every proposal, where it stands on this node, and with an id the whole text and digest |
A node away for more than the 30 days the router keeps its record, or joining later, cannot prove an earlier
approval and does not render it; the list says so. The module uses the `operator-channel` seat, which grants it the
asker's subjects and its own records there.
## How it is checked
| Check | Defends |
@@ -519,6 +543,9 @@ home goes through the two routes above.
| the module's tests over the lessons register: register, list, accept, decline, expiry; only accepted lessons reach `rules/`; a proposal matching a declined rule is refused with the reason; the session-start hook prints the recent and matching rules; the guard prints a matching rule once per session and refuses nothing for it | ADR 0273 §5 |
| the module's render test: the rendered managed instruction file's `working-on-the-mesh` section holds the paragraph on when a lesson is recorded, that a correction goes to the register and not to the agent's memory, and that existing corrections are proposed first; the test fails when the paragraph is taken out | ADR 0273 §5 |
| live: on the laptop, `~/.claude` holds the rendered configuration and the working state and nothing else; a rule written by hand into `rules/` raises `agent-home-drift` within a minute; a rule set at the terminal is in a new session on every node; a correction given in a session is in the lessons list in that turn, accepted at the terminal, and named at the start of the next session on another node | ADR 0273, the exit of WP7–WP9 |
| the module's tests through its real tool dispatch and with a router's record: a proposal asks at the level approve and changes nothing; an approval proved from the router's record renders on another node; a decline, an expiry, a refusal, a changed text, another ask's words, a late answer, a wrong level or another ask's warrant render nothing; a warrant acts once; a removal needs approval and a deleted record removes nothing; a node scope reaches its nodes only; no verified-sender channel refuses at once; issue 340's refusals hold; the text is never logged | ADR 0274 |
| the controller's tests: `warranted` records who chose from the router's record, once per ask, and refuses an open ask, one without a choice, and another asker's | ADR 0274 §6 |
| live: a proposal for every node shows on the operator's phone with Approve and Decline; after Approve a new session on another node reads it | ADR 0274 |
| live: a skill registered at the mesh scope is offered as `nox-mesh:<name>` in a new session on each machine | ADR 0216 |
| the module's test: the "instead of" table is generated from the controller's answers, ordered and cut; the guard refuses ssh to a mesh machine by name, domain, internal name, address, alias and jump, and the local work-arounds for a mesh name, naming the tool — and lets git to the forge, ssh beyond the mesh and a command merely mentioning ssh through; the override is honoured only from the session's start and only when recorded | ADR 0245 |
| the mesh MCP server's provision resolves by co-location; a machine without the mesh MCP server refuses the module by name | ADR 0027, ADR 0152 |
@@ -537,7 +564,8 @@ home goes through the two routes above.
exist, and nothing here changes for it.
- **The package repository seat** (§7).
- **A per-project lesson, lessons for an agent the mesh runs, and a surface of the operator's own** that can
tell the operator from an agent, which would be a third route into the operator's home (ADR 0273).
tell the operator from an agent, which would be a third route into the operator's home (ADR 0273). For the mesh's
shared instruction sections, the operator channel is that surface since ADR 0274 (§11).
- **How the module's tools are run** is decided: the node's tool runner, host-side
([ADR 0175](../../02-DECISIONS/0175-one-tool-runtime-per-node-serves-every-modules-tools-on-the-host-side.md)).
The managed files and the credential write are tools of this module that runtime serves. Until the
@@ -76,6 +76,12 @@ own settings file. It does not see a tool call that changes the managed files of
operator's own home is not written from the tools (see "How it is checked"). In the operator's words: "once we build a UI, we
can also update the context through it". A surface of the operator's own, which can tell the operator from
an agent, is the intended way back.
> **Amended 2026-10-10 by [ADR 0274](../../02-DECISIONS/0274-an-agent-proposes-a-shared-instruction-section-and-every-node-takes-it-only-on-the-operators-warrant-which-it-proves-itself.md) (proposed).**
> Instruction sections at the mesh and node scopes gain a second way beside the terminal: an agent proposes one
> with `claude_code_instructions_propose`, and every node takes it only on the operator's warrant (an ask at the
> level approve, answered on a channel that proves who answered), which each node proves from the router's own
> record. The other kinds stay the terminal's, and approved sections never render from the bus, so the still-open
> item below is unchanged.
3. **Passwords are not settings.** They come from the key vault and can be rotated. Every module found taking
a password, token or API key through a setting is recorded in
[issue 342](../342-a-password-is-taken-as-a-setting-and-outranks-the-vaults/00-report.md), to move to