Files
mesh-controller/internal/licences/submitrefresh_test.go
T
jschoubben c3b88b9148 Rename mesh-control -> mesh-controller, substrate -> foundation
One name per thing, per the HQ glossary: the module/container/image/binary/repo
becomes mesh-controller, the seat the-controller, and the store+broker pair the
foundation (embedded base bundles, default template and example lock renamed with
their go:embed directives). No behaviour change — a pure vocabulary rename.

Claude-Session: https://claude.ai/code/session_01D6qtiYU3P9jk3pnAXyAFyx
2026-09-16 18:40:40 +02:00

154 lines
5.8 KiB
Go

package licences
import (
"strings"
"testing"
"github.com/novox/mesh-controller/internal/secrets"
)
// SubmitRefresh is the boundary a manager NODE crosses to publish a refresh it performed: the control
// plane is given only the access token in the clear and an opaque re-sealed refresh box — never the
// refresh token. These tests defend that the boundary keeps its shape.
// A submitted refresh seals the access token to every CONSUMER holder, exactly as an in-process
// refresh does, and delivers no refresh token to a consumer.
func TestSubmitRefreshSealsTheAccessTokenAndNeverTheRefreshToken(t *testing.T) {
held, ctx := fresh(t)
// No in-process refresher registered: the anthropic production path uses SubmitRefresh, not
// Refresh, precisely so nothing opens the box inside this process.
_, _, _, holders, keys := aRefreshableLicence(t, held, ctx, &fakeRefresher{})
sealed, err := held.SubmitRefresh(ctx, "personal", "at-from-the-manager-node", "", "", keys)
if err != nil {
t.Fatal(err)
}
if sealed != 2 {
t.Fatalf("%d consumer holder(s) were resealed, expected 2", sealed)
}
for node, open := range holders {
blob, err := held.KeyFor(ctx, "personal", node, "assistant")
if err != nil {
t.Fatal(err)
}
got, err := open(blob)
if err != nil {
t.Fatalf("%s cannot open what it was delivered", node)
}
if string(got) != "at-from-the-manager-node" {
t.Fatalf("%s was delivered %q, not the access token", node, got)
}
if string(got) == "rt-the-refresh-token" || strings.Contains(blob, "rt-the-refresh-token") {
t.Fatalf("%s was delivered the refresh token", node)
}
}
}
// The refresh token is untouched by a submit that carried no rotation, and the manager node — and
// only it — still opens it. The submit path never saw the refresh token in the clear.
func TestSubmitRefreshWithoutRotationLeavesTheGrantOpenableByTheManagerAlone(t *testing.T) {
held, ctx := fresh(t)
managerPub, managerPriv, _, _, keys := aRefreshableLicence(t, held, ctx, &fakeRefresher{})
before := grantRow(t, held, ctx)
if _, err := held.SubmitRefresh(ctx, "personal", "at-access", "", "", keys); err != nil {
t.Fatal(err)
}
if grantRow(t, held, ctx) != before {
t.Fatal("a submit with no rotation changed the stored refresh token")
}
sealed, _, ok, err := held.RefreshGrant(ctx, "personal")
if err != nil || !ok {
t.Fatalf("the grant is not stored: ok=%v err=%v", ok, err)
}
got := openAnon(t, sealed, managerPub, managerPriv)
if string(got) != "rt-the-refresh-token" {
t.Fatalf("the manager read back %q", got)
}
// A node that is not the manager cannot: the whole of "the manager node only".
otherPub, otherPriv, _ := managerPair(t)
if _, ok := tryOpenAnon(sealed, otherPub, otherPriv); ok {
t.Fatal("a node that is not the manager opened the refresh token")
}
}
// A submit that carries a rotated box replaces the stored one — and the control plane stored it
// without opening it: only the manager node reads the rotated token back.
func TestSubmitRefreshWithRotationReplacesTheBoxUnopened(t *testing.T) {
held, ctx := fresh(t)
managerPub, managerPriv, _, _, keys := aRefreshableLicence(t, held, ctx, &fakeRefresher{})
before := grantRow(t, held, ctx)
// The manager node re-sealed the rotated refresh token to its own key; the control plane is handed
// only this box.
rotated, err := secrets.Seal(managerPub, []byte("rt-a-rotated-refresh-token"))
if err != nil {
t.Fatal(err)
}
if _, err := held.SubmitRefresh(ctx, "personal", "at-access", rotated, managerPub, keys); err != nil {
t.Fatal(err)
}
if grantRow(t, held, ctx) == before {
t.Fatal("the rotated refresh token did not replace the stored box")
}
sealed, _, ok, err := held.RefreshGrant(ctx, "personal")
if err != nil || !ok {
t.Fatalf("the rotated grant is not stored: ok=%v err=%v", ok, err)
}
got := openAnon(t, sealed, managerPub, managerPriv)
if string(got) != "rt-a-rotated-refresh-token" {
t.Fatalf("the stored grant opened to %q, not the rotated token", got)
}
}
// A submit with an empty access token is refused before anything is sealed: publishing nothing while
// reporting success is the failure this whole design refuses.
func TestSubmitRefreshRefusesAnEmptyAccessToken(t *testing.T) {
held, ctx := fresh(t)
_, _, _, _, keys := aRefreshableLicence(t, held, ctx, &fakeRefresher{})
if _, err := held.SubmitRefresh(ctx, "personal", " ", "", "", keys); err == nil {
t.Fatal("a refresh with no access token was published")
}
}
// A static-key licence cannot have a refresh submitted for it: the carve-out never fires, so the
// machinery that holds a token readably is unreachable.
func TestSubmitRefreshRefusesAStaticKeyLicence(t *testing.T) {
held, ctx := fresh(t)
if err := held.Add(ctx, "plain", "anthropic-api-key", nil); err != nil {
t.Fatal(err)
}
if err := held.Use(ctx, "plain", "workstation", "assistant"); err != nil {
t.Fatal(err)
}
_, err := held.SubmitRefresh(ctx, "plain", "at-access", "", "",
func(string) (string, error) { return ASealingKey(t), nil })
if err == nil {
t.Fatal("a refresh was submitted for a static-key licence")
}
if !strings.Contains(err.Error(), "refreshable-grant") {
t.Fatalf("the refusal does not name the shape: %v", err)
}
}
// A refreshable licence with no manager named refuses a submit and says how to name one: a refresh
// cannot be published for a licence no node is responsible for.
func TestSubmitRefreshRefusesWithoutAManager(t *testing.T) {
held, ctx := fresh(t)
if err := held.Add(ctx, "personal", "anthropic", nil); err != nil {
t.Fatal(err)
}
_, err := held.SubmitRefresh(ctx, "personal", "at-access", "", "",
func(string) (string, error) { return "", nil })
if err == nil {
t.Fatal("a refresh was submitted for a licence with no manager")
}
if !strings.Contains(err.Error(), "manager") {
t.Fatalf("the refusal does not point at the missing manager: %v", err)
}
}