Node-engine: logins, signers, enrolment tokens and redeems, and the grants part's sealed user list come from the vault and node-enroller clients and the grants state package; no file imports go/delivery (ADR 0634 §1, §4; issue 1966)

Claude-Session: https://claude.ai/code/session_01NcbgfFSnn24M3GcqttoU7i
This commit is contained in:
2026-11-05 15:47:59 +01:00
parent 4bfa94dfef
commit 13e2fe14aa
22 changed files with 248 additions and 219 deletions
+14 -15
View File
@@ -32,16 +32,15 @@ import (
"encoding/json"
"fmt"
"git.novox.be/novox/mesh-contracts/go/seats/nodeengine"
"git.novox.be/novox/mesh-delivery/modules/mesh-grants/grantsstate"
"git.novox.be/novox/mesh-sdk/go/seal"
"github.com/novox/mesh-host/internal/agent"
engcomp "github.com/novox/mesh-host/internal/compositions"
"regexp"
"sort"
"strings"
"sync"
"time"
"git.novox.be/novox/mesh-sdk/go/delivery"
"git.novox.be/novox/mesh-sdk/go/seal"
"github.com/novox/mesh-host/internal/agent"
)
// ResourceID is the id the composer gives the bus's user list (mesh-sdk catalogue.BusUsersID); in a composition it may
@@ -66,7 +65,7 @@ type Env struct {
Write func(ctx context.Context, module string, resource json.RawMessage, body []byte) (digest string, changed bool, err error)
// Report says what was written, in the module's have.
Report func(ctx context.Context, module string, w Written)
// Grants watches the grants part's state (its key delivery.GrantsUserListKey); nil writes nothing.
// Grants watches the grants part's state (its key grantsstate.GrantsUserListKey); nil writes nothing.
Grants agent.Watcher
// Fetch reads an object of the grants part's bucket by its name; Open opens a box sealed to this node's key; Key is
// this node's sealing key's public half (SPKI PEM), said in the have so the grants part seals to it ("" unknown).
@@ -103,7 +102,7 @@ type Follower struct {
mod string
said map[string]bool
// grants is the grants part's key as last heard (nil when none).
grants *delivery.GrantsUserList
grants *grantsstate.GrantsUserList
grantsRev uint64
// unwatched is why the grants part's key is not watched now; empty while it is, or where it need not be.
unwatched string
@@ -124,7 +123,7 @@ func New(env Env) *Follower {
said: map[string]bool{}}
if env.Grants != nil && env.Kept != nil {
if raw, rev := env.Kept(); raw != nil {
if g, err := delivery.DecodeGrantsUserList(raw); err == nil {
if g, err := grantsstate.DecodeGrantsUserList(raw); err == nil {
f.grants, f.grantsRev = &g, rev
}
}
@@ -180,7 +179,7 @@ func (f *Follower) Run(ctx context.Context) error {
return
}
opened = true
ch, err := f.env.Grants.Watch(ctx, delivery.GrantsUserListKey)
ch, err := f.env.Grants.Watch(ctx, grantsstate.GrantsUserListKey)
if err != nil {
failed(err.Error())
return
@@ -268,7 +267,7 @@ func (f *Follower) takeGrants(u agent.Update) {
f.sayOnceLocked("the grants part's user-list key is deleted, so the list loaded is kept")
return
}
g, err := delivery.DecodeGrantsUserList(u.Value)
g, err := grantsstate.DecodeGrantsUserList(u.Value)
if err != nil {
f.sayOnceLocked("the grants part's user-list key cannot be read, so the list loaded is kept: " + err.Error())
return
@@ -312,7 +311,7 @@ func reportable(prev, w Written) bool {
// says why in the have.
func (f *Follower) settleGrants(ctx context.Context, again bool) {
f.mu.Lock()
var g delivery.GrantsUserList
var g grantsstate.GrantsUserList
heard := f.grants != nil
if heard {
g = *f.grants
@@ -343,8 +342,8 @@ func (f *Follower) settleGrants(ctx context.Context, again bool) {
}
f.mu.Unlock()
w := Written{Source: delivery.GrantsUserListSource, Revision: int64(rev), Wanted: g.Digest, At: f.env.Now().UTC(),
Follows: delivery.FollowGrants, Key: f.key(), Unwatched: f.unwatchedNow()}
w := Written{Source: grantsstate.GrantsUserListSource, Revision: int64(rev), Wanted: g.Digest, At: f.env.Now().UTC(),
Follows: grantsstate.FollowGrants, Key: f.key(), Unwatched: f.unwatchedNow()}
var err error
var changed bool
resource, rerr := mode0600(file.resource)
@@ -357,14 +356,14 @@ func (f *Follower) settleGrants(ctx context.Context, again bool) {
err = fmt.Errorf("the grants part's key names no list yet; the list on the machine is kept")
case f.env.Fetch == nil || f.env.Open == nil:
err = fmt.Errorf("this engine cannot read or open the grants part's list")
case g.SealedTo != "" && w.Key != "" && g.SealedTo != delivery.SealingKeyID(w.Key):
case g.SealedTo != "" && w.Key != "" && g.SealedTo != grantsstate.SealingKeyID(w.Key):
err = fmt.Errorf("the grants part's list is sealed to another key than this node's (%s); the list on the machine is kept until it seals to this one", g.SealedTo)
}
var body []byte
if err == nil {
var object []byte
if object, err = f.env.Fetch(ctx, g.Object); err == nil {
body, err = delivery.OpenUserList(object, g.Digest, f.env.Open)
body, err = grantsstate.OpenUserList(object, g.Digest, f.env.Open)
}
if err != nil {
err = fmt.Errorf("the grants part's list %s could not be had: %w", short(g.Digest), err)
@@ -395,7 +394,7 @@ func (f *Follower) settleGrants(ctx context.Context, again bool) {
f.mod, f.state = file.module, w
f.written = err == nil
f.mu.Unlock()
at := fmt.Sprintf("%s@%d", delivery.GrantsUserListSource, rev)
at := fmt.Sprintf("%s@%d", grantsstate.GrantsUserListSource, rev)
if err != nil {
f.sayOnce(fmt.Sprintf("the bus's user list of %s could not be written: %v", at, err))
} else if changed {