Give claude-code's runtime its forge credential file, and say a credential it cannot place as a condition (issue 774)

The file gitea-read.secret was declared with no owner, so it was root's at 0600; claude-code's tools run in the
node's runtime as the operator's account and could not read it ("permission denied", ~870 times a machine), said
only in the journal. A file a bundle reads is the runtime account's only when a word of the bundle names it
(catalogue givenTo); this one was found through MESH_CLAUDE_CODE_STATE alone.

Quick fix: name the file with the bundle word MESH_CLAUDE_CODE_FORGE, which the reader now uses. Thorough fix: the
same, plus a failure to place the credential raises a warning condition of the module on the operator-channel seat,
once per reason, cleared when it places again. Chose thorough: the fault ran unseen for days. A change of the
credential now restarts the node's runtime, as for every file a bundle word names.
claude-code's mesh-sdk pin moves to 2da0de75 (main's), the first with asks.Condition.
This commit is contained in:
2026-10-30 18:13:44 +01:00
parent aec2ed3c24
commit 7531c3257d
7 changed files with 162 additions and 15 deletions
+24 -1
View File
@@ -22,6 +22,7 @@ import (
"time"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-sdk/go/asks"
)
func say(format string, args ...any) {
@@ -177,6 +178,19 @@ func (s memoryStateOf) Delete(key string) error { return s.s.Delete(key) }
// memoryCarrier carries this node's memory folders (ADR 0343); nil until the long-running half starts it.
var memoryCarrier *MemoryCarrier
// sayCondition says a condition on the operator-channel seat under this module's name (novox/hq ADR 0437 §9).
func sayCondition(c asks.Condition) error {
subject, err := asks.ConditionSubject("claude-code")
if err != nil {
return err
}
raw, err := asks.EncodeCondition(c)
if err != nil {
return err
}
return stdio.SeatPublish(subject, json.RawMessage(raw), "")
}
// notifyOperator tells the operator through the operator channel's notify verb (ADR 0253).
func notifyOperator(args map[string]any) error {
_, err := ask("seat:operator-channel.notify", args)
@@ -599,12 +613,21 @@ func run(p Paths, view *ServerView, configView *ConfigView) {
// The forge's read credential (forge.go, ADR 0365 §4): placed as held, and put back when git or a person changed
// it; the sessions' environment names it only while one is held.
forgeHeld := ForgeCredentialHeld(p)
forgeHealth := &ForgeHealth{Node: p.Node}
placeForge := func() {
if line, err := PlaceForgeCredential(p); err != nil {
line, err := PlaceForgeCredential(p)
if err != nil {
say("%v", err)
} else if line != "" {
say("%s", line)
}
// Said to the operator as a condition, raised once per reason and cleared when it places again.
if c := forgeHealth.Look(err); c != nil {
if serr := sayCondition(*c); serr != nil {
say("the forge credential's condition could not be said (%s): %v", c.State, serr)
forgeHealth = &ForgeHealth{Node: p.Node} // said again at the next look
}
}
if held := ForgeCredentialHeld(p); held != forgeHeld {
forgeHeld = held
if _, err := RenderNow(p, writeManaged); err != nil {