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:
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user