diff --git a/internal/catalogue/delivery_seat.go b/internal/catalogue/delivery_seat.go index 4c62decf..a4203f45 100644 --- a/internal/catalogue/delivery_seat.go +++ b/internal/catalogue/delivery_seat.go @@ -63,6 +63,18 @@ func deliveryVerbs() []Verb { "past its bound. Refused for any other.", Input: schema(map[string]string{"id": "the delivery's id", "why": "the condition it answers"}, []string{"id", "why"})}, + {Name: "retire-history", Description: "Retire held deliveries that are history, on a person's word, with " + + "why: each made from the forge's word for a merge on the trunk heard long after it happened — replayed " + + "when the holder first held the seat — with no walk of it open. Never released, delivered or put back: " + + "retired, final. One by id, refused when the rule does not take it; or every held one, of one " + + "repository when named, answering how many it retired and naming those it left held. dry \"true\" " + + "answers what it would do and changes nothing.", + Input: schema(map[string]string{"why": "why, kept with every transition", + "id": "one delivery's id; every held one when empty", + "repository": "owner/repository: only its held deliveries", + "dry": "\"true\": what it would retire, changing nothing"}, []string{"why"}, "dry"), + // Added after the seat's holder shipped (novox/hq issue 313): optional until mesh-delivery serves it. + Optional: true}, } } diff --git a/internal/catalogue/delivery_seat_test.go b/internal/catalogue/delivery_seat_test.go index 046b93d4..55fc7afe 100644 --- a/internal/catalogue/delivery_seat_test.go +++ b/internal/catalogue/delivery_seat_test.go @@ -58,3 +58,42 @@ func TestTheDeliverySeatPromisesChecks(t *testing.T) { t.Fatalf("a holder without %s: %v", before[0], err) } } + +// The seat retires history on a person's word (novox/hq issue 313): `retire-history`, with why, one delivery by +// id or every held one, dry to see first. Added after the holder shipped, it is optional, so the holder that +// does not serve it yet still holds the seat, and one that does is not refused for a verb the seat lacks. +func TestTheDeliverySeatPromisesRetireHistoryOptionally(t *testing.T) { + seat, _ := SeatNamed(DeliverySeat) + var retire *Verb + for i := range seat.Serves { + if seat.Serves[i].Name == "retire-history" { + retire = &seat.Serves[i] + } + } + if retire == nil || !retire.Optional { + t.Fatalf("the delivery seat promises %v, retire-history optionally", VerbNames(seat.Serves)) + } + props, _ := retire.Input["properties"].(map[string]any) + for _, arg := range []string{"why", "id", "repository", "dry"} { + if _, has := props[arg]; !has { + t.Errorf("retire-history takes no %q", arg) + } + } + if req, _ := retire.Input["required"].([]string); !reflect.DeepEqual(req, []string{"why"}) { + t.Errorf("retire-history requires %v, wanted only why", req) + } + var without []string + for _, v := range VerbNames(seat.Serves) { + if v != "retire-history" { + without = append(without, v) + } + } + m := Manifest{Module: "mesh-delivery", Claims: []Claim{{Name: DeliverySeat, Scope: ScopeMesh, Serves: without}}} + if err := CanHold(m, seat); err != nil { + t.Fatalf("a holder without retire-history yet: %v", err) + } + m.Claims[0].Serves = VerbNames(seat.Serves) + if err := CanHold(m, seat); err != nil { + t.Fatalf("a holder serving retire-history: %v", err) + } +}