Make the controller checks strict: nothing names the placed-nowhere controller

controllerdeps refuses any manifest naming the controller's seat, states or
buckets, the lease and the entries once kept to its write among them, and
any module file naming one of its buckets (ADR 0590 §5). The words check
refuses a controller address in any text a module shows. The handacts check
and noplacement's list of assignments readers are folded into it (issue 1126 B10).

Claude-Session: https://claude.ai/code/session_01NcbgfJ9Gum47zkFKWRaovL
This commit is contained in:
2026-11-02 12:29:56 +01:00
parent 32c4c52261
commit 0bfc72d230
21 changed files with 215 additions and 367 deletions
+2 -2
View File
@@ -19,8 +19,8 @@ alone writes the log.
`hand-act drill` for a drill, whose cause is always `drill`). Who did it is the caller the runtime proves.
- `mesh-hand-acts.warranted`: asker and ask. Read from the router's own record of that ask (`messenger.asks`), never
from the caller, and recorded once per ask; an ask still open, ended without a choice or another asker's is refused.
- `mesh-hand-acts.hand-acts`: both logs, this one and the controller's `mesh-controller_hand-acts` until its lease
ends, newest first, with the causes repaired by hand twice within a fortnight; `warrants=true` lists the warrants.
- `mesh-hand-acts.hand-acts`: this log (the controller's acts were copied into it once), newest first, with the
causes repaired by hand twice within a fortnight; `warrants=true` lists the warrants.
- `hand_acts_copied` and `hand_acts_copy` (research 072 row 26): the controller's hand acts are copied once into this
seat's log, each with its own key, time and author. It runs at the module's start while the old bucket is readable
@@ -9,8 +9,8 @@ package main
//
// **Who did it is the runtime's word, never the caller's**: `by` is the bus user the runtime proved. A warrant is the
// router's word, never the caller's: `warranted` reads the router's own record of the asker's ask and records who
// chose, through which channel, with which proofs and which answer, once per ask. The controller's bucket
// `mesh-controller_hand-acts` is no longer read (issue 774, ADR 0571 §13): its acts were copied into this log once, and
// chose, through which channel, with which proofs and which answer, once per ask. The controller's hand-act
// bucket is no longer read (issue 774, ADR 0571 §13): its acts were copied into this log once, and
// `hand-acts` answers from this log alone.
import (
@@ -1,7 +1,7 @@
package main
// The one-time copy of the controller's hand-act log into this seat's log is over (novox/hq research 072 row 26, ADR 0571
// §13, issue 774). The controller kept every act of its life in its bucket `mesh-controller_hand-acts`; they were copied
// §13, issue 774). The controller kept every act of its life in a bucket of its own; they were copied
// once into `acts`, each as the controller wrote it, by the earlier builds of this module, which left the marker
// `controller-hand-acts` of the state `copied`. This module no longer reads that bucket, so the copy cannot run: the
// tools `hand_acts_copy` and `hand_acts_copied` stay and say so, with the marker's figures when it exists.
@@ -79,7 +79,7 @@ func Tools(l *Log) []stdio.Tool {
Input: obj(map[string]any{}),
Run: func(map[string]any) (any, error) { return l.Copied() }},
{Name: CopyTool,
Description: "Answers that the copy is over (the controller's hand-act log, its bucket mesh-controller_hand-acts, " +
Description: "Answers that the copy is over (the controller's hand-act log " +
"is no longer read, novox/hq ADR 0571 §13) with the marker of the copy that was made; copies nothing.",
Input: obj(map[string]any{"top_up": str("\"true\": after the copy is done, append the acts written since")}),
Run: func(a map[string]any) (any, error) {
+2 -2
View File
@@ -148,8 +148,8 @@ func SetBucketExpiry(ctx context.Context, bus Bus, said Said, record Recorded, a
// expiryTools is the module's tool that sets a bucket's expiry.
func expiryTools(bus Bus, said Said, record Recorded) []stdio.Tool {
return []stdio.Tool{{Name: "nats_bucket_expiry",
Description: "Sets or restores the expiry of one key-value bucket: `max_age` is a duration such as 15s, or `none` to keep keys with no expiry (e.g. the lease bucket of mesh-controller at the lease write, back to 15s at the hand-back; novox/hq ADR 0582). Needs `why`, kept in the audit trail and recorded as a hand act through mesh-hand-acts (`warrant` names the operator's ask when there is one); refuses a name that is no key-value bucket; reads the expiry first and back after, and a bucket already at that expiry is answered as such. `dry_run` only reads. The bus refuses any bucket the module's credential is not granted.",
Input: map[string]any{"bucket": str("the bucket as nats_buckets lists it, e.g. mesh-controller_lease"), "max_age": str("a duration such as 15s, or none to remove the expiry"),
Description: "Sets or restores the expiry of one key-value bucket: `max_age` is a duration such as 15s, or `none` to keep keys with no expiry (e.g. a bucket whose keys must outlive their usual age while a person works on them, then back). Needs `why`, kept in the audit trail and recorded as a hand act through mesh-hand-acts (`warrant` names the operator's ask when there is one); refuses a name that is no key-value bucket; reads the expiry first and back after, and a bucket already at that expiry is answered as such. `dry_run` only reads. The bus refuses any bucket the module's credential is not granted.",
Input: map[string]any{"bucket": str("the bucket as nats_buckets lists it, e.g. mesh-config_resolved"), "max_age": str("a duration such as 15s, or none to remove the expiry"),
"why": str("why it is changed, for the audit trail (required)"), "warrant": str("the operator's ask this follows, when there is one"),
"dry_run": map[string]any{"type": "boolean", "description": "read the expiry, change nothing"}},
Run: func(a map[string]any) (any, error) {