mesh-sdk holds no go/asks, go/asker, vault answers or compose-candidate types (A1d, J1): each module now names the operator-channel contract and client, the channel benches (mesh-sdk/go/channel), mesh-vault's contract, and node-engine's contract and client (a1-progress.md, the A1d and J1 rewrite maps). - assigner, teller, view: delivery.Ask.Ask and AssignerAsk.Ask are the router's ask as JSON; the refusals mesh-sdk dropped (an id other than AskingID(key, asking), no option) are each reader's and writer's: assign.EncodeAsk/DecodeAsk (askjson.go), the teller's routerAskOf (teller.go) and the view's routerAsk (view.go); the teller refuses an option the asking does not offer and one whose level is not acknowledge (viewanswers.go), the two refusals ViewAnswerFits gave. Row: subtest of TestTheHoldAskIsValid (another id, no option, no ask; each written before). - enrolment, grants: the vault's verbs and answers from meshvault; asks' conditions from the contract and client. - checker, assigner's judge: compose-candidate from nodeengine/nodeengineclient (nec.Own for "node"). - mesh-grants' user-lists golden: the node-engine's users now subscribe to mesh-delivery-view's settled (mesh-sdk's NodeAgentHears, A7's ENG-8 retry). go.mod: each module requires the mesh-contracts modules it imports (and nodeengineclient, which mesh-sdk imports) at the zero version, for the group pin. Claude-Session: https://claude.ai/code/session_01JG73KJNrH5EgFXMKKYSrig
75 lines
2.4 KiB
Go
75 lines
2.4 KiB
Go
package assign
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"time"
|
|
|
|
occ "git.novox.be/novox/mesh-contracts/go/clients/operatorchannelclient"
|
|
oc "git.novox.be/novox/mesh-contracts/go/seats/operatorchannel"
|
|
"git.novox.be/novox/mesh-sdk/go/delivery"
|
|
)
|
|
|
|
// assignerAsk is the asking-th ask a, as the asks state holds it: the router's ask as JSON (delivery.AssignerAsk.Ask).
|
|
func assignerAsk(asking int, a oc.Ask) delivery.AssignerAsk {
|
|
raw, err := json.Marshal(a)
|
|
if err != nil { // an oc.Ask holds only strings, bools and a slice of them: it cannot fail
|
|
panic(fmt.Sprintf("assign: the ask %q does not marshal: %v", a.ID, err))
|
|
}
|
|
return delivery.AssignerAsk{Asking: asking, Ask: raw}
|
|
}
|
|
|
|
// AskOf is the router's ask an asks-state value carries.
|
|
func AskOf(a delivery.AssignerAsk) (oc.Ask, error) {
|
|
var ask oc.Ask
|
|
if err := json.Unmarshal(a.Ask, &ask); err != nil {
|
|
return oc.Ask{}, fmt.Errorf("assign: the value carries no router's ask: %w", err)
|
|
}
|
|
return ask, nil
|
|
}
|
|
|
|
// EncodeAsk is delivery.EncodeAssignerAsk at key, after the checks mesh-sdk no longer makes, since it cannot name the
|
|
// router's ask (ADR 0627 §4): the ask's id is delivery.AskingID(key, asking), and it offers at least one option.
|
|
func EncodeAsk(key string, a delivery.AssignerAsk) ([]byte, error) {
|
|
if _, err := checkedAsk(key, a); err != nil {
|
|
return nil, err
|
|
}
|
|
return delivery.EncodeAssignerAsk(key, a)
|
|
}
|
|
|
|
func checkedAsk(key string, a delivery.AssignerAsk) (oc.Ask, error) {
|
|
ask, err := AskOf(a)
|
|
if err != nil {
|
|
return oc.Ask{}, err
|
|
}
|
|
if want := delivery.AskingID(key, a.Asking); ask.ID != want {
|
|
return oc.Ask{}, fmt.Errorf("assign: the ask's id %q is not the asking's %q", ask.ID, want)
|
|
}
|
|
if len(ask.Options) == 0 {
|
|
return oc.Ask{}, fmt.Errorf("assign: the ask %q offers no option", ask.ID)
|
|
}
|
|
return ask, nil
|
|
}
|
|
|
|
// DecodeAsk reads the ask at key (delivery.DecodeAssignerAsk) with the router's ask it carries.
|
|
func DecodeAsk(key string, data []byte) (delivery.AssignerAsk, oc.Ask, error) {
|
|
a, err := delivery.DecodeAssignerAsk(key, data)
|
|
if err != nil {
|
|
return delivery.AssignerAsk{}, oc.Ask{}, err
|
|
}
|
|
ask, err := checkedAsk(key, a)
|
|
if err != nil {
|
|
return delivery.AssignerAsk{}, oc.Ask{}, err
|
|
}
|
|
return a, ask, nil
|
|
}
|
|
|
|
// ExpiresAt is when the ask ends unanswered; the zero time for an ask that names none.
|
|
func ExpiresAt(a oc.Ask) time.Time {
|
|
t, err := occ.Time(a.Expires)
|
|
if err != nil {
|
|
return time.Time{}
|
|
}
|
|
return t
|
|
}
|