| index 078f10ed4..72513ef18 100644 |
| --- a/internal/domains/claims_test.go |
| +++ b/internal/domains/claims_test.go |
| @@ -235,6 +235,66 @@ func TestNormalizeAliasHost(t *testing.T) { |
| } |
| } |
| |
| +func TestSetClaimCapabilities(t *testing.T) { |
| + ctx := context.Background() |
| + s := release.NewDirStore(t.TempDir()) |
| + if _, _, err := AttachClaim(ctx, s, Claim{Host: "woodstar.app", Account: "bab", App: "woodstar-relay", Route: "woodstar-relay.bab.oncarlos.com", CreatedAt: "2026-08-13T00:00:00Z"}); err != nil { |
| + t.Fatal(err) |
| + } |
| + |
| + // Set both capabilities. |
| + changed, err := SetClaimCapabilities(ctx, s, "woodstar.app", "bab", "woodstar-relay", true, true) |
| + if err != nil || !changed { |
| + t.Fatalf("set: changed=%v err=%v", changed, err) |
| + } |
| + got, err := GetClaim(ctx, s, "woodstar.app") |
| + if err != nil || !got.Wildcard || !got.Catchall { |
| + t.Fatalf("stored claim: %+v err=%v", got, err) |
| + } |
| + // Route, CreatedAt survive the capability write. |
| + if got.Route != "woodstar-relay.bab.oncarlos.com" || got.CreatedAt != "2026-08-13T00:00:00Z" { |
| + t.Fatalf("capability write must preserve Route+CreatedAt: %+v", got) |
| + } |
| + |
| + // Idempotent: same values = no write. |
| + changed, err = SetClaimCapabilities(ctx, s, "woodstar.app", "bab", "woodstar-relay", true, true) |
| + if err != nil || changed { |
| + t.Fatalf("no-op set: changed=%v err=%v", changed, err) |
| + } |
| + |
| + // Turning both off works and reports changed. |
| + changed, err = SetClaimCapabilities(ctx, s, "woodstar.app", "bab", "woodstar-relay", false, false) |
| + if err != nil || !changed { |
| + t.Fatalf("unset: changed=%v err=%v", changed, err) |
| + } |
| +} |
| + |
| +func TestSetClaimCapabilitiesRefusals(t *testing.T) { |
| + ctx := context.Background() |
| + s := release.NewDirStore(t.TempDir()) |
| + if _, _, err := AttachClaim(ctx, s, Claim{Host: "woodstar.app", Account: "bab", App: "woodstar-relay", CreatedAt: "2026-08-13T00:00:00Z"}); err != nil { |
| + t.Fatal(err) |
| + } |
| + |
| + // Catchall without wildcard: refused, never stored. |
| + if _, err := SetClaimCapabilities(ctx, s, "woodstar.app", "bab", "woodstar-relay", false, true); !errors.Is(err, ErrCatchallNeedsWildcard) { |
| + t.Fatalf("want ErrCatchallNeedsWildcard, got %v", err) |
| + } |
| + if got, _ := GetClaim(ctx, s, "woodstar.app"); got.Catchall { |
| + t.Fatal("refused catchall must not be stored") |
| + } |
| + |
| + // Wrong owner: neutral refusal, same error the attach door uses. |
| + if _, err := SetClaimCapabilities(ctx, s, "woodstar.app", "bad", "other-app", true, false); !errors.Is(err, ErrHostUnavailable) { |
| + t.Fatalf("want ErrHostUnavailable, got %v", err) |
| + } |
| + |
| + // No claim at all: neutral, not a bare not-found (no existence oracle). |
| + if _, err := SetClaimCapabilities(ctx, s, "unclaimed.example", "bab", "woodstar-relay", true, false); !errors.Is(err, ErrHostUnavailable) { |
| + t.Fatalf("want ErrHostUnavailable for missing claim, got %v", err) |
| + } |
| +} |
| + |
| func TestHostDenied(t *testing.T) { |
| deny := []string{"oncarlos.com"} |
| cases := []struct { |