package service import ( "baron-sso-backend/internal/domain" "context" "encoding/json" "testing" "time" "github.com/stretchr/testify/mock" "github.com/stretchr/testify/require" ) type identityWriteRedisStub struct { values map[string]string } func (s *identityWriteRedisStub) Set(key string, value string, expiration time.Duration) error { if s.values == nil { s.values = map[string]string{} } s.values[key] = value return nil } func (s *identityWriteRedisStub) Get(key string) (string, error) { return s.values[key], nil } func (s *identityWriteRedisStub) Delete(key string) error { delete(s.values, key) return nil } func (s *identityWriteRedisStub) StoreVerificationCode(phone, code string) error { return nil } func (s *identityWriteRedisStub) GetVerificationCode(phone string) (string, error) { return "", nil } func (s *identityWriteRedisStub) DeleteVerificationCode(phone string) error { return nil } func TestIdentityWriteServiceUpdateIdentityMarksMirrorStale(t *testing.T) { kratos := new(MockKratosAdminServiceShared) redis := &identityWriteRedisStub{} traits := map[string]any{"email": "user@example.com"} kratos.On("UpdateIdentity", mock.Anything, "user-1", traits, "active").Return(&KratosIdentity{ ID: "user-1", State: "active", Traits: traits, }, nil).Once() writer := NewIdentityWriteService(kratos, redis) updated, err := writer.UpdateIdentity(context.Background(), IdentityUpdateRequest{ IdentityID: "user-1", Traits: traits, State: "active", Reason: "rp_custom_claims_sync", Source: "dev_handler", }) require.NoError(t, err) require.Equal(t, "user-1", updated.ID) rawState := redis.values["identity:mirror:state"] require.NotEmpty(t, rawState) var state domain.IdentityCacheStatus require.NoError(t, json.Unmarshal([]byte(rawState), &state)) require.Equal(t, "stale", state.Status) require.Contains(t, state.LastError, "rp_custom_claims_sync") kratos.AssertExpectations(t) }