fix: a require-only consumer of a parameterless provision still asks (mint gap) #12

Merged
jschoubben merged 1 commits from fix/require-only-mint into main 2026-09-06 21:21:25 +00:00
2 changed files with 39 additions and 0 deletions
Showing only changes of commit d0ef659824 - Show all commits
+24
View File
@@ -333,6 +333,30 @@ func TestAConsumersOwnContributionsAreStillThere(t *testing.T) {
}
}
func TestARequireOnlyConsumerOfAParameterlessProvisionStillAsks(t *testing.T) {
// A consumer that requires a parameterless provision (one whose serves names no consumer key —
// redis-cache, amqp) contributes no payload, but it still ASKS for the provision and must be
// granted a credential. Keying "asks" on contributions alone gave its grant From="" — read as
// withdrawn — so the provider never created the account and the consumer authenticated nowhere.
r := Resolution{
Node: "laptop",
Modules: []Manifest{{
Module: "amqp-ping",
Requires: []string{"amqp"},
}},
}
values, asks, err := r.ContributionsFrom("amqp", "amqp-ping", SettingsBy{})
if err != nil {
t.Fatal(err)
}
if !asks {
t.Fatal("a require-only consumer was treated as not asking; its grant would be withdrawn and it would never be provisioned")
}
if values == nil {
t.Fatalf("asks is true but values is nil; expected an empty contribution, got %v", values)
}
}
func TestAConsumerThatStoppedAskingIsWithdrawn(t *testing.T) {
// Withdrawal is how a credential is taken away. The provisioner removes what nobody asks for,
// and it can only do that if the mesh stops asking — a consumer that was unassigned would
+15
View File
@@ -637,6 +637,21 @@ func (r Resolution) ContributionsFrom(requirement, module string, settings Setti
return g.Values, true, nil
}
}
// It contributes no payload — but a require-only consumer of a parameterless provision (one whose
// `serves` names no consumer-supplied key: `redis-cache`, `amqp`) still ASKS for it and must be
// granted a credential. Keying "asks" on contributions alone marked those grants withdrawn
// (From=""), so the provider never created the account and the consumer authenticated nowhere. A
// module asks iff it still requires the provision, whether or not it hands anything up with it.
for _, m := range r.Modules {
if m.Module != module {
continue
}
for _, req := range m.Requires {
if req == requirement {
return map[string]any{}, true, nil
}
}
}
// Nothing on that machine asks for this any more. Said as "not found" rather than as an
// error: it is how a credential is withdrawn, and the provider removes what nobody asks for.
return nil, false, nil