Registry.ClaimExternal now enforces the plan gate itself via an injected domains.ExternalClaimGate (pre-lock, typed refusals), so every entry point — and any future consumer — inherits it from the allocation API. One constructor in internal/server builds the gate from the entitlements querier and connect target; it is injected into the member-facing registry constructions in server.go and fedwiki.go and drives affordance rendering on both surfaces. The duplicated helpers and resource-key constants in fedwiki web and member_domains are gone; fedwiki no longer reads entitlement tables for this gate at all. Archives the change with the domains-registry spec delta (enforcement location is now requirement-level: registry-inherited, surfaces derive). Closes the entitlement-gate placement debt in issues.md; files the separately-discovered operator force-release dead-end affordance bug that a placed claim exposed in the domains walkthrough.
39 lines
1.4 KiB
Go
39 lines
1.4 KiB
Go
package domains
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"testing"
|
|
)
|
|
|
|
// TestClaimExternalGateRefusesBeforeAllocating pins the enforcement point
|
|
// (centralize-external-claim-gate): a refusing gate stops ClaimExternal
|
|
// before ANY registry work. The registry here has a nil database — reaching
|
|
// the lock or the queries would panic — so the clean typed refusal is proof
|
|
// nothing was allocated, no token minted, no lock taken.
|
|
func TestClaimExternalGateRefusesBeforeAllocating(t *testing.T) {
|
|
for _, refusal := range []error{ErrExternalClaimsNotEntitled, ErrNoConnectTarget} {
|
|
r := NewRegistry(nil, WithExternalClaimGate(func(ctx context.Context, workspaceID string) error {
|
|
return refusal
|
|
}))
|
|
_, err := r.ClaimExternal(context.Background(), "ws-1", "example.org")
|
|
if !errors.Is(err, refusal) {
|
|
t.Errorf("ClaimExternal with refusing gate: got %v, want %v", err, refusal)
|
|
}
|
|
}
|
|
}
|
|
|
|
// TestClaimExternalGateReceivesWorkspace pins that the gate is consulted
|
|
// with the requesting workspace — the input the entitlement lookup keys on.
|
|
func TestClaimExternalGateReceivesWorkspace(t *testing.T) {
|
|
var saw string
|
|
r := NewRegistry(nil, WithExternalClaimGate(func(ctx context.Context, workspaceID string) error {
|
|
saw = workspaceID
|
|
return ErrExternalClaimsNotEntitled // refuse so the nil DB is never touched
|
|
}))
|
|
_, _ = r.ClaimExternal(context.Background(), "ws-42", "example.org")
|
|
if saw != "ws-42" {
|
|
t.Errorf("gate saw workspace %q, want ws-42", saw)
|
|
}
|
|
}
|