fix(access): verify subscription readiness with real user keys
When subscription access is requested with an explicit access_api_key, assign the subscription to the real target user, bind that user's API key to the subscription group, and probe readiness with the same key instead of falling back to a managed synthetic user. Update the runtime/reconcile flows, adapter tests, and source-of-truth docs so subscription_ready now reflects user-visible host access rather than managed-key-only closure success.
This commit is contained in:
@@ -78,12 +78,12 @@ func TestServiceCloseAssignsSubscriptionsAndProbesGateway(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestServiceCloseSubscriptionManagedKeyOverridesExplicitProbeAPIKey(t *testing.T) {
|
||||
func TestServiceCloseSubscriptionExplicitProbeAPIKeyUsesRequestedUserKey(t *testing.T) {
|
||||
host := &fakeClosureHost{
|
||||
gatewayResult: sub2api.GatewayAccessResult{OK: true, StatusCode: 200, HasExpectedModel: true, Models: []string{"deepseek-chat"}},
|
||||
completionResult: sub2api.GatewayCompletionResult{OK: true, StatusCode: 200},
|
||||
managedAccess: map[string]sub2api.SubscriptionAccessRef{
|
||||
"user-1": {UserID: "host-user-1", APIKey: "managed-user-key"},
|
||||
"user-1": {UserID: "user-1", APIKey: "caller-supplied-key"},
|
||||
},
|
||||
}
|
||||
service := NewService(host)
|
||||
@@ -97,14 +97,20 @@ func TestServiceCloseSubscriptionManagedKeyOverridesExplicitProbeAPIKey(t *testi
|
||||
if err != nil {
|
||||
t.Fatalf("Close() error = %v", err)
|
||||
}
|
||||
if host.gatewayProbe.APIKey != "managed-user-key" {
|
||||
t.Fatalf("gateway probe api key = %q, want managed-user-key override", host.gatewayProbe.APIKey)
|
||||
if len(host.assigned) != 1 || host.assigned[0].UserID != "user-1" {
|
||||
t.Fatalf("assigned subscriptions = %+v, want requested user assignment", host.assigned)
|
||||
}
|
||||
if result.EffectiveProbeAPIKey != "managed-user-key" {
|
||||
t.Fatalf("effective probe api key = %q, want managed-user-key", result.EffectiveProbeAPIKey)
|
||||
if host.gatewayProbe.APIKey != "caller-supplied-key" {
|
||||
t.Fatalf("gateway probe api key = %q, want caller-supplied-key", host.gatewayProbe.APIKey)
|
||||
}
|
||||
if result.EffectiveProbeKeySource != ProbeKeySourceManagedSubscription {
|
||||
t.Fatalf("effective probe key source = %q, want %q", result.EffectiveProbeKeySource, ProbeKeySourceManagedSubscription)
|
||||
if len(host.ensureRequests) != 1 || host.ensureRequests[0].ProbeAPIKey != "caller-supplied-key" {
|
||||
t.Fatalf("ensure requests = %+v, want probe api key forwarded", host.ensureRequests)
|
||||
}
|
||||
if result.EffectiveProbeAPIKey != "caller-supplied-key" {
|
||||
t.Fatalf("effective probe api key = %q, want caller-supplied-key", result.EffectiveProbeAPIKey)
|
||||
}
|
||||
if result.EffectiveProbeKeySource != ProbeKeySourceRequestedProbeAPIKey {
|
||||
t.Fatalf("effective probe key source = %q, want %q", result.EffectiveProbeKeySource, ProbeKeySourceRequestedProbeAPIKey)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,6 +203,7 @@ func TestServiceCloseRepairsOpenAIResponsesCapabilityMismatch(t *testing.T) {
|
||||
|
||||
type fakeClosureHost struct {
|
||||
assigned []sub2api.AssignSubscriptionRequest
|
||||
ensureRequests []sub2api.EnsureSubscriptionAccessRequest
|
||||
managedAccess map[string]sub2api.SubscriptionAccessRef
|
||||
assignErr error
|
||||
gatewayProbe sub2api.GatewayAccessCheckRequest
|
||||
@@ -215,6 +222,7 @@ type fakeClosureHost struct {
|
||||
}
|
||||
|
||||
func (f *fakeClosureHost) EnsureSubscriptionAccess(_ context.Context, req sub2api.EnsureSubscriptionAccessRequest) (sub2api.SubscriptionAccessRef, error) {
|
||||
f.ensureRequests = append(f.ensureRequests, req)
|
||||
if ref, ok := f.managedAccess[req.UserSelector]; ok {
|
||||
return ref, nil
|
||||
}
|
||||
|
||||
@@ -9,8 +9,31 @@ import (
|
||||
)
|
||||
|
||||
func (s *Service) prepareSubscriptionPlan(ctx context.Context, req ClosureRequest, plan closurePlan) (closurePlan, error) {
|
||||
requestedProbeAPIKey := strings.TrimSpace(req.ProbeAPIKey)
|
||||
for _, target := range req.Subscriptions {
|
||||
resolvedTarget := target.UserID
|
||||
if requestedProbeAPIKey != "" {
|
||||
if _, err := s.host.AssignSubscription(ctx, sub2api.AssignSubscriptionRequest{
|
||||
UserID: resolvedTarget,
|
||||
GroupID: req.GroupID,
|
||||
DurationDays: target.DurationDays,
|
||||
}); err != nil {
|
||||
return closurePlan{}, fmt.Errorf("assign subscription for %s: %w", target.UserID, err)
|
||||
}
|
||||
accessRef, err := s.host.EnsureSubscriptionAccess(ctx, sub2api.EnsureSubscriptionAccessRequest{
|
||||
UserSelector: target.UserID,
|
||||
GroupID: req.GroupID,
|
||||
ProbeAPIKey: requestedProbeAPIKey,
|
||||
})
|
||||
if err != nil {
|
||||
return closurePlan{}, fmt.Errorf("ensure subscription access for %s: %w", target.UserID, err)
|
||||
}
|
||||
if strings.TrimSpace(accessRef.APIKey) != "" {
|
||||
plan.effectiveProbeAPIKey = strings.TrimSpace(accessRef.APIKey)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
accessRef, err := s.host.EnsureSubscriptionAccess(ctx, sub2api.EnsureSubscriptionAccessRequest{
|
||||
UserSelector: target.UserID,
|
||||
GroupID: req.GroupID,
|
||||
|
||||
Reference in New Issue
Block a user