Files
mesh-controller/internal/inventory/issued_test.go
T
jschoubben faf8b76b84
mesh/merge-gate pass: builds build-agent, mesh-controller → ace, g14, novox, shanks; no bus step; every machine composes with the change as it did without …
mesh/repo-check pass: its merge-check.sh passed
mesh/delivery superseded: a newer head of the same pull request
Cite ADR 0305's clauses by their accepted-for-review numbers (issue 526)
2026-10-12 01:09:26 +02:00

125 lines
5.2 KiB
Go

package inventory
import (
"testing"
"github.com/novox/mesh-controller/internal/catalogue"
)
// A value a provider's software issued is sealed to every pair that holds the provision from that provider, under
// one stamp of the value, and the same value given again writes nothing and sends nobody (novox/hq ADR 0305 §4,
// §5, issue 526).
func TestAnIssuedValueIsSealedToEveryHolderOnceAndNotAgain(t *testing.T) {
inv, ctx := twoNodesWithKeys(t)
consumerKey, consumerOpens := aSealingKey(t)
cn, _ := inv.NodeByName(ctx, "consumer")
if err := inv.RecordSealingKey(ctx, cn.ID, consumerKey); err != nil {
t.Fatal(err)
}
for _, m := range []string{"kometa", "tautulli"} {
if err := inv.RegisterModule(ctx, catalogue.Manifest{Module: m, Version: "1", Requires: []string{"plex-api"},
Secrets: map[string]string{"plex-api": "/run/plex-api.secret"}}, Source{}); err != nil {
t.Fatal(err)
}
// What the mesh made before the provider gave its value: a random value per pair (issue 164).
if _, err := inv.SecretFor(ctx, "plex-api", "consumer", m, "provider", ""); err != nil {
t.Fatal(err)
}
}
kept, err := inv.KeepIssuedSecret(ctx, "plex-api", "provider", "the-servers-own-token")
if err != nil {
t.Fatal(err)
}
if !kept.Changed || len(kept.Holders) != 2 {
t.Fatalf("the value was not sealed to both holders: %+v", kept)
}
if len(kept.Machines) != 2 || kept.Machines[0] != "consumer" || kept.Machines[1] != "provider" {
t.Fatalf("the machines to send are the provider's and every holder's: %v", kept.Machines)
}
for _, m := range []string{"kometa", "tautulli"} {
got, err := inv.SecretFor(ctx, "plex-api", "consumer", m, "provider", "")
if err != nil {
t.Fatal(err)
}
if got.Origin != OriginIssued {
t.Fatalf("%s's pair says it came from %q, not the provider's software", m, got.Origin)
}
opened, ok := consumerOpens(got.ForConsumer)
if !ok || string(opened) != "the-servers-own-token" {
t.Fatalf("%s's copy is not the provider's value", m)
}
var generation string
pn, _ := inv.NodeByName(ctx, "provider")
if err := inv.store.Pool().QueryRow(ctx, `select generation from secret where name = 'plex-api' and consumer = $1
and consumer_module = $2 and provider = $3`, cn.ID, m, pn.ID).Scan(&generation); err != nil {
t.Fatal(err)
}
if generation != IssuedStamp("the-servers-own-token") {
t.Fatalf("%s's pair is not stamped with the value's fingerprint: %q", m, generation)
}
}
before, _ := inv.SecretFor(ctx, "plex-api", "consumer", "kometa", "provider", "")
// A consumer that binds later gets a pair of its own, and no holder's value is remade for it: the offer names
// no own secret, so ADR 0158 §6's remaking on a bind does not reach it (ADR 0305 §7).
if err := inv.RegisterModule(ctx, catalogue.Manifest{Module: "overseerr", Version: "1", Requires: []string{"plex-api"},
Secrets: map[string]string{"plex-api": "/run/plex-api.secret"}}, Source{}); err != nil {
t.Fatal(err)
}
late, err := inv.SecretFor(ctx, "plex-api", "consumer", "overseerr", "provider", "")
if err != nil {
t.Fatal(err)
}
if late.Origin == OriginIssued {
t.Fatal("a consumer that bound after the ask holds the issued value without an ask")
}
if held, _ := inv.SecretFor(ctx, "plex-api", "consumer", "kometa", "provider", ""); held.ForConsumer != before.ForConsumer {
t.Fatal("a later bind remade a holder's issued value")
}
// The next ask seals the provider's value to the late consumer alone; the holders that had it are not touched.
again, err := inv.KeepIssuedSecret(ctx, "plex-api", "provider", "the-servers-own-token")
if err != nil {
t.Fatal(err)
}
if !again.Changed || len(again.Sealed) != 1 || again.Sealed[0].ConsumerModule != "overseerr" {
t.Fatalf("the late consumer was not sealed to, or not alone: %+v", again)
}
if held, _ := inv.SecretFor(ctx, "plex-api", "consumer", "kometa", "provider", ""); held.ForConsumer != before.ForConsumer {
t.Fatal("sealing the late consumer changed what a holder already held")
}
if got, _ := inv.SecretFor(ctx, "plex-api", "consumer", "overseerr", "provider", ""); got.Origin != OriginIssued {
t.Fatal("the late consumer does not hold the issued value after the ask")
}
// And once every holder holds it, the same value writes nothing and sends nobody.
still, err := inv.KeepIssuedSecret(ctx, "plex-api", "provider", "the-servers-own-token")
if err != nil {
t.Fatal(err)
}
if still.Changed || len(still.Machines) != 0 {
t.Fatalf("the same value was sealed again, which restarts every consumer for nothing: %+v", still)
}
after, _ := inv.SecretFor(ctx, "plex-api", "consumer", "kometa", "provider", "")
if after.ForConsumer != before.ForConsumer {
t.Fatal("the same value given again changed what the consumer holds")
}
changed, err := inv.KeepIssuedSecret(ctx, "plex-api", "provider", "a-token-plex-changed")
if err != nil {
t.Fatal(err)
}
if !changed.Changed {
t.Fatal("a changed value was not sealed")
}
got, _ := inv.SecretFor(ctx, "plex-api", "consumer", "tautulli", "provider", "")
if opened, ok := consumerOpens(got.ForConsumer); !ok || string(opened) != "a-token-plex-changed" {
t.Fatal("the changed value did not reach the holder")
}
if _, err := inv.KeepIssuedSecret(ctx, "plex-api", "provider", " "); err == nil {
t.Fatal("an empty value was kept")
}
}