mesh/merge-gate pass: builds mesh-sdk, sent nowhere; no bus step; every machine composes with the change as it did without (4 of 4 compose)
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery-group group feat/asks-answered-on-any-channel rejected: a member's own check failed
mesh/delivery superseded: a newer head of the same pull request
A warrant named the ask by id and the option by id, and the asker acted on whatever its record held for them. Now the ask carries, for every option above acknowledge, the digest of exactly what it performs (Option.Binds, ActDigest), the router puts the digest of the ask it took in the warrant (Warrant.AskDigest), For refuses a warrant whose digest is not that of the ask the asker keeps, and Option.Performs refuses an act the option did not bind. A warrant then authorises one act, as the person was shown it, once.
166 lines
6.6 KiB
Go
166 lines
6.6 KiB
Go
package asks
|
|
|
|
import (
|
|
"encoding/json"
|
|
"strings"
|
|
"testing"
|
|
"time"
|
|
)
|
|
|
|
var now = time.Date(2026, 10, 8, 14, 0, 0, 0, time.UTC)
|
|
|
|
func held() Ask {
|
|
return Ask{ID: "d-1", Headline: "openrazer delivery held", Explanation: "Needs you: release it, or stop it.",
|
|
Who: Operator, Expires: now.Add(time.Hour), OnExpiry: "the delivery stays held", About: "delivery.openrazer",
|
|
Options: []Option{
|
|
{ID: "release", Label: "Release", Does: "the delivery goes on", Level: Approve, Binds: bind("release", "openrazer")},
|
|
{ID: "stop", Label: "Stop", Does: "the delivery ends", Level: Approve, Binds: bind("stop", "openrazer")},
|
|
{ID: "silence", Label: "Silence for a week", Does: "nothing more is said for a week", Level: Acknowledge},
|
|
}}
|
|
}
|
|
|
|
func bind(verb, what string) string {
|
|
d, err := ActDigest(map[string]string{"verb": verb, "delivery": what})
|
|
if err != nil {
|
|
panic(err)
|
|
}
|
|
return d
|
|
}
|
|
|
|
func TestASoundAskPasses(t *testing.T) {
|
|
if err := held().Check(now); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
}
|
|
|
|
func TestAnAskIsRefusedInWordsForEachFault(t *testing.T) {
|
|
for want, change := range map[string]func(*Ask){
|
|
"is not letters": func(a *Ask) { a.ID = "a.b" },
|
|
"headline is empty": func(a *Ask) { a.Headline = "" },
|
|
"explains nothing": func(a *Ask) { a.Explanation = " " },
|
|
"only the operator answers": func(a *Ask) { a.Who = "agent" },
|
|
"offers 0 options": func(a *Ask) { a.Options = nil },
|
|
"offers 5 options": func(a *Ask) { a.Options = append(a.Options, a.Options[0], a.Options[1]) },
|
|
"is offered twice": func(a *Ask) { a.Options[1].ID = "release" },
|
|
"does not say what it does": func(a *Ask) { a.Options[0].Does = "" },
|
|
"none of acknowledge": func(a *Ask) { a.Options[0].Level = "admin" },
|
|
"expires before it is asked": func(a *Ask) { a.Expires = now },
|
|
"approves lasts at most": func(a *Ask) { a.Expires = now.Add(25 * time.Hour) },
|
|
"destroys lasts at most": func(a *Ask) { a.Options[0].Level = Destroy },
|
|
"never defaults": func(a *Ask) { a.OnExpiry = "" },
|
|
"is a key, without spaces": func(a *Ask) { a.About = "a b" },
|
|
"does not bind what it": func(a *Ask) { a.Options[0].Binds = "" },
|
|
} {
|
|
a := held()
|
|
change(&a)
|
|
if err := a.Check(now); err == nil || !strings.Contains(err.Error(), want) {
|
|
t.Errorf("want a refusal saying %q, got %v", want, err)
|
|
}
|
|
}
|
|
ack := held()
|
|
ack.Options = ack.Options[2:]
|
|
ack.OnExpiry = ""
|
|
ack.Expires = now.Add(7 * 24 * time.Hour)
|
|
if err := ack.Check(now); err != nil {
|
|
t.Errorf("an ask that only acknowledges needs no expiry words and may last a week: %v", err)
|
|
}
|
|
}
|
|
|
|
func TestAnAskerActsOnlyOnAWarrantForItsOwnAskAndOption(t *testing.T) {
|
|
w := Warrant{Ask: "d-1", Asker: "mesh-delivery", Outcome: OutcomeChosen, Option: "release", Label: "Release",
|
|
Level: Approve, By: &Person{Who: Operator, Kind: "telegram", Identity: "42", Verified: "user id verified"},
|
|
AskDigest: held().Digest()}
|
|
if o, err := w.For("mesh-delivery", held()); err != nil || o.ID != "release" {
|
|
t.Fatalf("a sound warrant was refused: %v", err)
|
|
}
|
|
if got := w.Says(); got != "the operator, via telegram (user id verified), chose Release" {
|
|
t.Errorf("the warrant says %q", got)
|
|
}
|
|
for why, change := range map[string]func(*Warrant){
|
|
"another asker": func(w *Warrant) { w.Asker = "mesh-controller" },
|
|
"another ask": func(w *Warrant) { w.Ask = "d-2" },
|
|
"no choice": func(w *Warrant) { w.Outcome = OutcomeExpired },
|
|
"nobody": func(w *Warrant) { w.By = nil },
|
|
"not offered": func(w *Warrant) { w.Option = "delete" },
|
|
"a lower level": func(w *Warrant) { w.Level = Acknowledge },
|
|
"another role": func(w *Warrant) { w.By = &Person{Who: "agent"} },
|
|
"no digest": func(w *Warrant) { w.AskDigest = "" },
|
|
"another ask's digest": func(w *Warrant) {
|
|
other := held()
|
|
other.Options[0].Binds = bind("release", "another")
|
|
w.AskDigest = other.Digest()
|
|
},
|
|
} {
|
|
c := w
|
|
by := *w.By
|
|
c.By = &by
|
|
change(&c)
|
|
if _, err := c.For("mesh-delivery", held()); err == nil {
|
|
t.Errorf("a warrant with %s was acted on", why)
|
|
}
|
|
}
|
|
}
|
|
|
|
func TestTheSubjectsNameTheirPublisher(t *testing.T) {
|
|
for got, want := range map[string]string{
|
|
AskSubject("mesh-delivery"): "mesh.seat.operator-channel.accept.ask.mesh-delivery",
|
|
DecidedSubject("mesh-delivery"): "mesh.seat.operator-channel.event.decided.mesh-delivery",
|
|
ChannelSubject(Show, "telegram"): "mesh.seat.channel.accept.show.telegram",
|
|
IntakeSubject(Chosen, "desktop"): "mesh.seat.intake.event.choice.desktop",
|
|
ProofSubject(CodeProof, "telegram"): "mesh.seat.intake.proof.code.telegram",
|
|
} {
|
|
if got != want {
|
|
t.Errorf("%s, want %s", got, want)
|
|
}
|
|
}
|
|
}
|
|
|
|
// A warrant answers one ask as it was shown, and authorises the act its option bound and no other
|
|
// (novox/hq ADR 0259 §6: the warrant is bound to the exact ask and its arguments).
|
|
func TestAWarrantAuthorisesOnlyTheActItsOptionBound(t *testing.T) {
|
|
a := held()
|
|
// The digest survives the trip through the bus: what the router decodes and digests is what was sent.
|
|
raw, err := json.Marshal(a)
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
var decoded Ask
|
|
if err := json.Unmarshal(raw, &decoded); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
if decoded.Digest() != a.Digest() {
|
|
t.Fatalf("the ask's digest changed on the way: %s, %s", decoded.Digest(), a.Digest())
|
|
}
|
|
local := a
|
|
local.Expires = a.Expires.In(time.FixedZone("CEST", 2*3600))
|
|
if local.Digest() != a.Digest() {
|
|
t.Error("the same instant in another zone digests differently")
|
|
}
|
|
// Changing anything the person was shown, or what an option binds, changes the digest.
|
|
for what, change := range map[string]func(*Ask){
|
|
"the headline": func(a *Ask) { a.Headline += "!" },
|
|
"the explanation": func(a *Ask) { a.Explanation += " " },
|
|
"a label": func(a *Ask) { a.Options[0].Label = "Go" },
|
|
"what it binds": func(a *Ask) { a.Options[0].Binds = bind("release", "another") },
|
|
"the expiry": func(a *Ask) { a.Expires = a.Expires.Add(time.Second) },
|
|
"what it is about": func(a *Ask) { a.About = "delivery.other" },
|
|
} {
|
|
c := held()
|
|
change(&c)
|
|
if c.Digest() == a.Digest() {
|
|
t.Errorf("changing %s leaves the digest", what)
|
|
}
|
|
}
|
|
o, _ := a.Option("release")
|
|
if err := o.Performs(map[string]string{"verb": "release", "delivery": "openrazer"}); err != nil {
|
|
t.Errorf("the bound act was refused: %v", err)
|
|
}
|
|
if err := o.Performs(map[string]string{"verb": "release", "delivery": "another"}); err == nil {
|
|
t.Error("an act the option did not bind was let through")
|
|
}
|
|
ack, _ := a.Option("silence")
|
|
if err := ack.Performs(map[string]string{"anything": "x"}); err != nil {
|
|
t.Errorf("an acknowledgement that bound nothing: %v", err)
|
|
}
|
|
}
|