package runtimeidentity

import (
	"context"
	"errors"
	"testing"
	"time"

	"github.com/golang-jwt/jwt/v5"
	featureauth "github.com/nexuscrm/auth"
	"github.com/nexuscrm/backend/internal/runtimeapi"
	kernelauth "github.com/nexuscrm/kernel/pkg/auth"
	"github.com/nexuscrm/shared/pkg/models"
	"github.com/pingcap-inc/nexuscrm-api-host/runtimegrpc"
	semantic "github.com/pingcap-inc/nexuscrm-contract/pkg/runtime/sessionv1"
)

type sessionAuthStub struct {
	loginResult        *featureauth.LoginResult
	loginErr           error
	loginCalls         int
	loginIdentity      string
	loginSecret        string
	loginSourceAddress string
	loginUserAgent     string
	loginOptions       *featureauth.SessionOptions
	logoutCalls        int
	browserLogoutCalls int
	admitCalls         int
	renewCalls         int
	controlCalls       int
	validation         *featureauth.AuthorizingSessionValidation
	replacement        string
	proofExpiry        time.Time
	createdToken       *models.SessionToken
	controlledToken    *featureauth.SessionTokenResult
	createdOptions     *featureauth.SessionOptions
	controlledOptions  *featureauth.SessionOptions
}

func (*sessionAuthStub) AuthorizingSessionAdmissionReady() bool { return true }
func (s *sessionAuthStub) Login(_ context.Context, identity, secret, sourceAddress, userAgent string, options *featureauth.SessionOptions) (*featureauth.LoginResult, error) {
	s.loginCalls++
	s.loginIdentity = identity
	s.loginSecret = secret
	s.loginSourceAddress = sourceAddress
	s.loginUserAgent = userAgent
	if options != nil {
		copy := *options
		s.loginOptions = &copy
	}
	return s.loginResult, s.loginErr
}
func (s *sessionAuthStub) CreateSessionForUser(_ context.Context, _, _, _ string, options *featureauth.SessionOptions) (*models.SessionToken, error) {
	if options != nil {
		copy := *options
		s.createdOptions = &copy
	}
	return s.createdToken, s.loginErr
}
func (s *sessionAuthStub) CreateControlledSessionForUser(_ context.Context, _, _, _ string, options *featureauth.SessionOptions) (*featureauth.SessionTokenResult, error) {
	if options != nil {
		copy := *options
		s.controlledOptions = &copy
	}
	return s.controlledToken, s.loginErr
}
func (s *sessionAuthStub) AdmitAuthorizingSession(context.Context, string) (*featureauth.AuthorizingSessionValidation, error) {
	s.admitCalls++
	return s.validation, s.loginErr
}
func (s *sessionAuthStub) AdmitAuthorizingSessionWithRenewal(context.Context, string) (*featureauth.AuthorizingSessionValidation, string, error) {
	s.renewCalls++
	return s.validation, s.replacement, s.loginErr
}
func (s *sessionAuthStub) AdmitAuthorizingSessionWithControl(context.Context, string, string) (*featureauth.AuthorizingSessionValidation, string, time.Time, error) {
	s.controlCalls++
	return s.validation, s.replacement, s.proofExpiry, s.loginErr
}
func (s *sessionAuthStub) AdmitAuthorizingSessionWithRenewalPreparation(ctx context.Context, token string, prepare func(*featureauth.AuthorizingSessionValidation) error) (*featureauth.AuthorizingSessionValidation, string, error) {
	if s.loginErr != nil {
		return nil, "", s.loginErr
	}
	if err := prepare(s.validation); err != nil {
		return nil, "", err
	}
	return s.AdmitAuthorizingSessionWithRenewal(ctx, token)
}
func (s *sessionAuthStub) AdmitAuthorizingSessionWithControlPreparation(ctx context.Context, token, proof string, prepare func(*featureauth.AuthorizingSessionValidation) error) (*featureauth.AuthorizingSessionValidation, string, time.Time, error) {
	if s.loginErr != nil {
		return nil, "", time.Time{}, s.loginErr
	}
	if err := prepare(s.validation); err != nil {
		return nil, "", time.Time{}, err
	}
	return s.AdmitAuthorizingSessionWithControl(ctx, token, proof)
}
func (s *sessionAuthStub) Logout(context.Context, string) error {
	s.logoutCalls++
	return s.loginErr
}
func (s *sessionAuthStub) BrowserLogout(context.Context, string, string) error {
	s.browserLogoutCalls++
	return s.loginErr
}

type sessionOAuthStub struct {
	decision  *featureauth.OAuthPolicyDecision
	err       error
	permitted bool
	request   featureauth.OAuthPolicyRequest
}

func (s *sessionOAuthStub) ResolveOAuthPolicy(_ context.Context, request featureauth.OAuthPolicyRequest) (*featureauth.OAuthPolicyDecision, error) {
	s.request = request
	return s.decision, s.err
}
func (s *sessionOAuthStub) IsUserPermittedForApp(context.Context, *models.SystemConnectedApp, string) (bool, error) {
	return s.permitted, s.err
}

func sessionTestContext(t *testing.T) context.Context {
	t.Helper()
	ctx, cancel := context.WithTimeout(context.Background(), time.Second)
	t.Cleanup(cancel)
	return ctx
}

func sessionTestUser() kernelauth.UserSession {
	roleID, roleName := "role-1", "Sales"
	return kernelauth.UserSession{
		ID: "user-1", Name: "Ada Lovelace", Email: "ada@example.test",
		ProfileId: "profile-1", ProfileName: "Standard",
		RoleId: &roleID, RoleName: &roleName,
	}
}

func sessionTestValidation(now time.Time) *featureauth.AuthorizingSessionValidation {
	return &featureauth.AuthorizingSessionValidation{Claims: &kernelauth.Claims{
		User: sessionTestUser(), RegisteredClaims: jwt.RegisteredClaims{
			ExpiresAt: jwt.NewNumericDate(now.Add(time.Hour)),
		},
	}}
}

func sessionTestAuthority() runtimeapi.RuntimeWorkloadCall {
	return runtimeapi.RuntimeWorkloadCall{
		OrgID: "org-1", CallerWorkloadID: "sfcrm", Capability: semantic.CapabilityName,
		SecurityEpoch: 7,
	}
}

func sessionTestSecurity(now time.Time) IssuanceSecuritySource {
	return func(context.Context, string, string) (IssuanceSecurityState, error) {
		return IssuanceSecurityState{
			StateFound: true, BindingFound: true, BindingActive: true,
			OrgID: "org-1", Capabilities: []string{semantic.CapabilityName},
			SecurityEpoch: 7, LeaseFound: true, LeaseSecurityEpoch: 7,
			LeaseExpiresAt: now.Add(time.Minute),
		}, nil
	}
}

func newSessionLifecycleTest(t *testing.T, auth *sessionAuthStub, oauth *sessionOAuthStub, now time.Time) *SessionLifecycle {
	t.Helper()
	owner, err := NewSessionLifecycle(SessionLifecycleConfig{
		Auth: auth, OAuth: oauth, Security: sessionTestSecurity(now),
		AppInstallationID: "installation-1", AuthorizedWorkloadID: "sfcrm",
		Now: func() time.Time { return now },
	})
	if err != nil {
		t.Fatal(err)
	}
	return owner
}

func TestSessionLifecyclePasswordUsesExistingPolicyAndDurableAuthOwner(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	user := sessionTestUser()
	app := &models.SystemConnectedApp{ID: "app-1", ConsumerKey: featureauth.BuiltInBrowserClientID}
	auth := &sessionAuthStub{loginResult: &featureauth.LoginResult{
		Token: "access-token", User: user, ExpiresAt: now.Add(time.Hour), ControlProof: "control-proof",
	}}
	oauth := &sessionOAuthStub{decision: &featureauth.OAuthPolicyDecision{App: app}, permitted: true}
	owner := newSessionLifecycleTest(t, auth, oauth, now)
	response, issued, err := owner.CreateSession(
		sessionTestContext(t), sessionTestAuthority(),
		runtimegrpc.SessionCreateCredentials{Identity: user.Email, Secret: " password ", ClientSecret: " client-secret "},
		semantic.CreateRequest{
			AppInstallationID: "installation-1", Method: semantic.AuthenticationMethodPassword,
			ApplicationClientID: featureauth.BuiltInBrowserClientID, RequestedScope: "api refresh_token",
			SourceAddress: "192.0.2.1", UserAgent: "browser", IssueControlProof: true,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	if issued.AccessToken != "access-token" || issued.ControlProof != "control-proof" ||
		response.Session.Principal.PrincipalID != user.ID || !response.ControlProofIssued {
		t.Fatalf("response = %#v, issued = %#v", response, issued)
	}
	if auth.loginOptions == nil || auth.loginOptions.SessionClass != featureauth.OAuthSessionClassPlatformBrowser ||
		!auth.loginOptions.IssueControlProof || auth.loginOptions.ConnectedAppId != app.ID {
		t.Fatalf("login options = %#v", auth.loginOptions)
	}
	if auth.loginCalls != 1 || auth.loginIdentity != user.Email || auth.loginSecret != " password " ||
		auth.loginSourceAddress != "192.0.2.1" || auth.loginUserAgent != "browser" ||
		oauth.request.ClientID != featureauth.BuiltInBrowserClientID ||
		oauth.request.RequestedScope != "api refresh_token" ||
		oauth.request.PresentedSecret != " client-secret " {
		t.Fatalf("login input = (%d, %q, %q, %q, %q), policy = %#v",
			auth.loginCalls, auth.loginIdentity, auth.loginSecret,
			auth.loginSourceAddress, auth.loginUserAgent, oauth.request)
	}
}

func TestSessionLifecyclePermissionDenialRevokesIssuedSession(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	auth := &sessionAuthStub{loginResult: &featureauth.LoginResult{
		Token: "access-token", User: sessionTestUser(), ExpiresAt: now.Add(time.Hour),
	}}
	oauth := &sessionOAuthStub{
		decision:  &featureauth.OAuthPolicyDecision{App: &models.SystemConnectedApp{ID: "app-1", ConsumerKey: "client-1"}},
		permitted: false,
	}
	owner := newSessionLifecycleTest(t, auth, oauth, now)
	_, _, err := owner.CreateSession(
		sessionTestContext(t), sessionTestAuthority(),
		runtimegrpc.SessionCreateCredentials{Identity: "ada@example.test", Secret: "password"},
		semantic.CreateRequest{
			AppInstallationID: "installation-1", Method: semantic.AuthenticationMethodPassword,
			ApplicationClientID: "client-1",
		},
	)
	var failure *semantic.Failure
	if !errors.As(err, &failure) || failure.Category != semantic.FailureForbidden || auth.logoutCalls != 1 {
		t.Fatalf("error = %#v, logout calls = %d", failure, auth.logoutCalls)
	}
}

func TestSessionLifecycleStaleSecurityStopsBeforeIdentityOwner(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	auth := &sessionAuthStub{}
	oauth := &sessionOAuthStub{}
	owner := newSessionLifecycleTest(t, auth, oauth, now)
	authority := sessionTestAuthority()
	authority.SecurityEpoch = 6
	_, _, err := owner.CreateSession(
		sessionTestContext(t), authority,
		runtimegrpc.SessionCreateCredentials{Identity: "ada@example.test", Secret: "password"},
		semantic.CreateRequest{
			AppInstallationID: "installation-1", Method: semantic.AuthenticationMethodPassword,
			ApplicationClientID: "client-1",
		},
	)
	var failure *semantic.Failure
	if !errors.As(err, &failure) || failure.Category != semantic.FailureStaleState || auth.loginCalls != 0 {
		t.Fatalf("error = %#v, login calls = %d", failure, auth.loginCalls)
	}
}

func TestSessionLifecycleAdmissionFailsClosedBeforeAuth(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	for _, test := range []struct {
		name  string
		state IssuanceSecurityState
		err   error
		want  semantic.FailureCategory
	}{
		{name: "missing authority", want: semantic.FailureUnavailable},
		{
			name: "inactive binding", want: semantic.FailureForbidden,
			state: IssuanceSecurityState{StateFound: true, BindingFound: true, OrgID: "org-1"},
		},
		{
			name: "capability not granted", want: semantic.FailureForbidden,
			state: IssuanceSecurityState{
				StateFound: true, BindingFound: true, BindingActive: true, OrgID: "org-1",
				Capabilities: []string{"runtime.other.v1"}, SecurityEpoch: 7,
				LeaseFound: true, LeaseSecurityEpoch: 7, LeaseExpiresAt: now.Add(time.Minute),
			},
		},
		{
			name: "expired lease", want: semantic.FailureStaleState,
			state: IssuanceSecurityState{
				StateFound: true, BindingFound: true, BindingActive: true, OrgID: "org-1",
				Capabilities: []string{semantic.CapabilityName}, SecurityEpoch: 7,
				LeaseFound: true, LeaseSecurityEpoch: 7, LeaseExpiresAt: now,
			},
		},
		{name: "authority unavailable", err: errors.New("database unavailable"), want: semantic.FailureUnavailable},
	} {
		t.Run(test.name, func(t *testing.T) {
			auth := &sessionAuthStub{}
			owner, err := NewSessionLifecycle(SessionLifecycleConfig{
				Auth: auth, OAuth: &sessionOAuthStub{}, Now: func() time.Time { return now },
				AppInstallationID: "installation-1", AuthorizedWorkloadID: "sfcrm",
				Security: func(context.Context, string, string) (IssuanceSecurityState, error) {
					return test.state, test.err
				},
			})
			if err != nil {
				t.Fatal(err)
			}
			_, _, err = owner.CreateSession(
				sessionTestContext(t), sessionTestAuthority(),
				runtimegrpc.SessionCreateCredentials{Identity: "user@example.test", Secret: "password"},
				semantic.CreateRequest{
					AppInstallationID: "installation-1", Method: semantic.AuthenticationMethodPassword,
					ApplicationClientID: "client-1",
				},
			)
			var failure *semantic.Failure
			if !errors.As(err, &failure) || failure.Category != test.want || auth.loginCalls != 0 {
				t.Fatalf("error = %#v, login calls = %d", err, auth.loginCalls)
			}
		})
	}
}

func TestSessionLifecycleDeploymentScopeFailsBeforeSecurityOrAuth(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	for _, test := range []struct {
		name         string
		authority    runtimeapi.RuntimeWorkloadCall
		installation string
	}{
		{name: "wrong workload", authority: func() runtimeapi.RuntimeWorkloadCall {
			value := sessionTestAuthority()
			value.CallerWorkloadID = "integration-service"
			return value
		}(), installation: "installation-1"},
		{name: "wrong installation", authority: sessionTestAuthority(), installation: "installation-2"},
	} {
		t.Run(test.name, func(t *testing.T) {
			securityCalls := 0
			auth := &sessionAuthStub{}
			owner, err := NewSessionLifecycle(SessionLifecycleConfig{
				Auth: auth, OAuth: &sessionOAuthStub{},
				AppInstallationID: "installation-1", AuthorizedWorkloadID: "sfcrm",
				Security: func(context.Context, string, string) (IssuanceSecurityState, error) {
					securityCalls++
					return sessionTestSecurity(now)(context.Background(), "installation-1", "sfcrm")
				},
				Now: func() time.Time { return now },
			})
			if err != nil {
				t.Fatal(err)
			}
			_, _, err = owner.CreateSession(
				sessionTestContext(t), test.authority,
				runtimegrpc.SessionCreateCredentials{Identity: "user@example.test", Secret: "password"},
				semantic.CreateRequest{
					AppInstallationID: test.installation, Method: semantic.AuthenticationMethodPassword,
					ApplicationClientID: "client-1",
				},
			)
			var failure *semantic.Failure
			if !errors.As(err, &failure) || failure.Category != semantic.FailureForbidden ||
				securityCalls != 0 || auth.loginCalls != 0 {
				t.Fatalf("error = %#v, security calls = %d, login calls = %d", err, securityCalls, auth.loginCalls)
			}
		})
	}
}

func TestSessionLifecycleReadAndRevokePreserveRenewalAndControlProfiles(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	auth := &sessionAuthStub{
		validation: sessionTestValidation(now), replacement: "replacement-token",
		proofExpiry: now.Add(time.Hour),
	}
	owner := newSessionLifecycleTest(t, auth, &sessionOAuthStub{}, now)
	response, issued, err := owner.ReadSession(
		sessionTestContext(t), sessionTestAuthority(),
		runtimegrpc.SessionPresentedCredentials{AccessToken: "old-token", ControlProof: "proof"},
		semantic.ReadRequest{AppInstallationID: "installation-1", AllowRenewal: true, UseControlProof: true},
	)
	if err != nil {
		t.Fatal(err)
	}
	if issued.AccessToken != "replacement-token" || !response.ReplacementAccessTokenIssued ||
		response.ControlProofExpiresAtUnixSecond != now.Add(time.Hour).Unix() {
		t.Fatalf("response = %#v, issued = %#v", response, issued)
	}
	if auth.controlCalls != 1 || auth.renewCalls != 0 || auth.admitCalls != 0 {
		t.Fatalf("admission calls = strict:%d renewal:%d control:%d", auth.admitCalls, auth.renewCalls, auth.controlCalls)
	}
	if err := owner.RevokeSession(
		sessionTestContext(t), sessionTestAuthority(),
		runtimegrpc.SessionPresentedCredentials{AccessToken: "old-token", ControlProof: "proof"},
		semantic.RevokeRequest{AppInstallationID: "installation-1", UseControlProof: true},
	); err != nil {
		t.Fatal(err)
	}
	if auth.browserLogoutCalls != 1 || auth.logoutCalls != 0 {
		t.Fatalf("browser logout = %d, bearer logout = %d", auth.browserLogoutCalls, auth.logoutCalls)
	}
}

func TestSessionLifecycleFederatedTokenIsVerifiedBeforePrincipalResolution(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	auth := &sessionAuthStub{
		validation: sessionTestValidation(now),
		controlledToken: &featureauth.SessionTokenResult{
			SessionToken: &models.SessionToken{AccessToken: "federated-token"},
			ExpiresAt:    now.Add(time.Hour), ControlProof: "control-proof",
		},
	}
	oauth := &sessionOAuthStub{}
	verifiedRaw, resolvedIdentifier := "", ""
	owner, err := NewSessionLifecycle(SessionLifecycleConfig{
		Auth: auth, OAuth: oauth, Security: sessionTestSecurity(now),
		AppInstallationID: "installation-1", AuthorizedWorkloadID: "sfcrm",
		Now: func() time.Time { return now },
		FederatedVerifiers: map[string]FederatedIDTokenVerifier{
			"google": func(_ context.Context, raw string) (FederatedIdentity, error) {
				verifiedRaw = raw
				return FederatedIdentity{LoginIdentifier: "ada@example.test"}, nil
			},
		},
		FederatedScopes: map[string]string{"google": "api"},
		FederatedPrincipals: func(_ context.Context, identifier string) (string, error) {
			resolvedIdentifier = identifier
			return "user-1", nil
		},
	})
	if err != nil {
		t.Fatal(err)
	}
	_, issued, err := owner.CreateSession(
		sessionTestContext(t), sessionTestAuthority(),
		runtimegrpc.SessionCreateCredentials{Secret: "signed-id-token"},
		semantic.CreateRequest{
			AppInstallationID: "installation-1", Method: semantic.AuthenticationMethodFederatedIDToken,
			FederatedProviderID: "google", IssueControlProof: true,
		},
	)
	if err != nil {
		t.Fatal(err)
	}
	if verifiedRaw != "signed-id-token" || resolvedIdentifier != "ada@example.test" ||
		issued.AccessToken != "federated-token" || issued.ControlProof != "control-proof" {
		t.Fatalf("verified = %q, resolved = %q, issued = %#v", verifiedRaw, resolvedIdentifier, issued)
	}
	if auth.controlledOptions == nil || auth.controlledOptions.Scope != "api" ||
		auth.controlledOptions.GrantType != "federated_id_token" ||
		auth.controlledOptions.SessionClass != featureauth.OAuthSessionClassPlatformBrowser {
		t.Fatalf("federated session options = %#v", auth.controlledOptions)
	}
	capabilityPolicy, err := NewSessionCapabilityPolicy(map[string][]string{
		"api": {"runtime.records.query.v1"},
	})
	if err != nil {
		t.Fatal(err)
	}
	capabilities, err := capabilityPolicy(t.Context(), runtimeapi.RuntimeSessionState{
		User: models.UserSession{Scope: auth.controlledOptions.Scope},
	})
	if err != nil || len(capabilities) != 1 || capabilities[0] != "runtime.records.query.v1" {
		t.Fatalf("federated session capabilities = %v, %v", capabilities, err)
	}
}

func TestSessionLifecycleFederatedProviderRequiresExplicitSessionScope(t *testing.T) {
	_, err := NewSessionLifecycle(SessionLifecycleConfig{
		Auth: &sessionAuthStub{}, OAuth: &sessionOAuthStub{}, Security: sessionTestSecurity(time.Now()),
		AppInstallationID: "installation-1", AuthorizedWorkloadID: "sfcrm",
		FederatedVerifiers: map[string]FederatedIDTokenVerifier{
			"provider-a": func(context.Context, string) (FederatedIdentity, error) {
				return FederatedIdentity{}, nil
			},
		},
		FederatedPrincipals: func(context.Context, string) (string, error) { return "user-1", nil },
	})
	if err == nil {
		t.Fatal("federated provider without an explicit session scope was accepted")
	}
}

func TestSessionDocumentPolicyUsesAdmittedClaimsAndFailsClosed(t *testing.T) {
	now := time.Unix(1_800_000_000, 0)
	auth := &sessionAuthStub{validation: sessionTestValidation(now)}
	owner := newSessionLifecycleTest(t, auth, &sessionOAuthStub{}, now)
	request := semantic.ReadRequest{AppInstallationID: "installation-1", DocumentPolicy: &semantic.DocumentPolicyRequest{RouteFamilyPrefix: "/extensions/data/"}}
	read := func() (semantic.ReadResponse, error) {
		response, _, err := owner.ReadSession(sessionTestContext(t), sessionTestAuthority(), runtimegrpc.SessionPresentedCredentials{AccessToken: "old-token"}, request)
		return response, err
	}
	if _, err := read(); err == nil {
		t.Fatal("missing policy owner accepted")
	}
	calls := 0
	owner.documentPolicy = func(ctx context.Context, claims *kernelauth.Claims, facts semantic.DocumentPolicyRequest) (*semantic.DocumentPolicy, error) {
		calls++
		if claims != auth.validation.Claims || facts.RouteFamilyPrefix != "/extensions/data/" {
			t.Fatal("policy did not receive admitted identity and request facts")
		}
		return &semantic.DocumentPolicy{Restricted: true, AllowedLinks: []string{"records"}, HourlyLimit: 123, DailyLimit: 456}, nil
	}
	response, err := read()
	if err != nil || response.DocumentPolicy == nil || !response.DocumentPolicy.Restricted || response.DocumentPolicy.HourlyLimit != 123 || calls != 1 {
		t.Fatalf("response %+v, error %v, calls %d", response, err, calls)
	}
	auth.loginErr = errors.New("admission rejected")
	if _, err := read(); err == nil || calls != 1 {
		t.Fatalf("policy read before successful admission: %v calls=%d", err, calls)
	}
}

func TestDocumentPolicyFailureDoesNotCommitSessionRenewal(t *testing.T) {
	for _, controlled := range []bool{false, true} {
		for _, failure := range []string{"missing owner", "unavailable", "missing decision", "invalid decision"} {
			t.Run(failure+map[bool]string{false: "/bearer", true: "/controlled"}[controlled], func(t *testing.T) {
				now := time.Now()
				auth := &sessionAuthStub{validation: sessionTestValidation(now), replacement: "replacement", proofExpiry: now.Add(time.Hour)}
				owner := newSessionLifecycleTest(t, auth, &sessionOAuthStub{}, now)
				if failure != "missing owner" {
					owner.documentPolicy = func(context.Context, *kernelauth.Claims, semantic.DocumentPolicyRequest) (*semantic.DocumentPolicy, error) {
						switch failure {
						case "unavailable":
							return nil, errors.New("policy store unavailable")
						case "invalid decision":
							return &semantic.DocumentPolicy{HourlyLimit: -1}, nil
						default:
							return nil, nil
						}
					}
				}
				request := semantic.ReadRequest{AppInstallationID: "installation-1", AllowRenewal: true, UseControlProof: controlled, DocumentPolicy: &semantic.DocumentPolicyRequest{RouteFamilyPrefix: "/extensions/data/"}}
				_, issued, err := owner.ReadSession(sessionTestContext(t), sessionTestAuthority(), runtimegrpc.SessionPresentedCredentials{AccessToken: "old-token", ControlProof: "proof"}, request)
				if err == nil || issued.AccessToken != "" {
					t.Fatalf("failed policy returned success/credentials: %+v %v", issued, err)
				}
				if auth.renewCalls != 0 || auth.controlCalls != 0 {
					t.Fatalf("policy failure reached renewal: bearer=%d controlled=%d", auth.renewCalls, auth.controlCalls)
				}
			})
		}
	}
}
