Review of L2, round 2: a refusal at the first compose after a start keeps what the module's have said runs (1); each have of a self-composing node carries the values its composition holds sealed, and the composer reuses them after a restart, so a rotated secret moves no composition at a restart (2); pin mesh-sdk dd9d9d5 (issue 1126, ADR 0547 §3)
mesh/delivery closed: a newer head of the same pull request
mesh/check checking 4476e5808047 on ff9386dcccc2 | novox/mesh-host#149 in group feat/1126-nodes-compose

This commit is contained in:
2026-10-26 20:23:16 +01:00
parent 58de6aa10a
commit 4476e58080
9 changed files with 255 additions and 72 deletions
+14 -3
View File
@@ -60,7 +60,8 @@ func (h sessionHaves) Read(ctx context.Context, module string) (agent.Have, bool
if !ok {
return agent.Have{}, false
}
return agent.Have{Module: module, FP: got.FP, Composed: got.Composed, Phase: string(got.Phase), Detail: got.Detail}, true
return agent.Have{Module: module, FP: got.FP, Composed: got.Composed, Phase: string(got.Phase), Detail: got.Detail,
Sealed: got.Sealed}, true
}
func (h sessionHaves) Write(ctx context.Context, x agent.Have) {
@@ -76,7 +77,8 @@ func (h sessionHaves) Write(ctx context.Context, x agent.Have) {
phase = ""
}
h.session.NoteModule(ctx, link.ModuleFact{Module: x.Module, FP: x.FP, Composed: x.Composed, Phase: phase,
Failed: phase == string(delivery.PhaseFailed), Detail: shorten(x.Detail), Judgement: x.Judgement, Waits: x.Waits})
Failed: phase == string(delivery.PhaseFailed), Detail: shorten(x.Detail), Judgement: x.Judgement, Waits: x.Waits,
Sealed: x.Sealed})
}
func (h sessionHaves) Removed(ctx context.Context, module string) {
@@ -507,6 +509,14 @@ func nodeAgent(ctx context.Context, opts options, signer ed25519.PublicKey, sess
return nil
},
unseal: sealOpener(opts.state),
// And what each module's have says it runs sealed: after a restart the agent has applied nothing yet.
held: func(module string) []string {
got, ok := session.ReadHave(linked, module)
if !ok {
return nil
}
return got.Sealed
},
refused: func(why string) {
if now := current.get(); now != nil {
now.NotComposed(linked, why)
@@ -809,6 +819,7 @@ type composerHooks struct {
running func() []delivery.Composed
unseal func(string) ([]byte, error)
refused func(string)
held func(module string) []string
}
func selfComposer(ctx context.Context, session *link.Session, node string, say func(string), hooks composerHooks) *selfcompose.Composer {
@@ -846,7 +857,7 @@ func selfComposer(ctx context.Context, session *link.Session, node string, say f
},
// And the vault's word that a secret changed, on which it composes again (ADR 0547 §2).
Hear: session.Hear,
Running: hooks.running, Unseal: hooks.unseal, Refused: hooks.refused})
Running: hooks.running, Unseal: hooks.unseal, Refused: hooks.refused, Held: hooks.held})
}
// endWhenPlaced calls stop once this node's placement key appears in the indexer's placement (a value after the watch