# Guia Avançado do Sistema Guard - OfficeGest

Este guia detalha implementações avançadas do sistema Guard, incluindo casos de uso complexos, padrões de integração e implementações futuras.

## 📋 Índice

1. [Arquitetura Interna do Guard](#arquitetura-interna-do-guard)
2. [Implementações Avançadas](#implementações-avançadas)
3. [Padrões de Integração](#padrões-de-integração)
4. [Casos de Uso Empresariais](#casos-de-uso-empresariais)
5. [Implementações Futuras](#implementações-futuras)
6. [Performance e Otimização](#performance-e-otimização)

## 🏗️ Arquitetura Interna do Guard

### Fluxo de Autenticação

```
Request → Token Extraction → Token Validation → User Resolution → Permissions Check → Context Creation
```

### Componentes Principais

#### 1. GuardManager - Orquestrador Principal

```php
class GuardManager
{
    private array $config;
    private $db;
    private TokenManager $tokenManager;
    private ?array $currentUser = null;
    private ?PersonalAccessToken $currentToken = null;
    private array $authenticators = [];
    private array $guards = [];
    
    public function authenticate(): ?array
    {
        // Tentar diferentes métodos de autenticação
        foreach ($this->authenticators as $authenticator) {
            $result = $authenticator->attempt();
            if ($result) {
                return $this->setAuthenticatedUser($result);
            }
        }
        
        return null;
    }
    
    public function addAuthenticator(AuthenticatorInterface $authenticator): void
    {
        $this->authenticators[] = $authenticator;
    }
    
    public function addGuard(string $name, GuardInterface $guard): void
    {
        $this->guards[$name] = $guard;
    }
    
    public function guard(string $name = 'default'): GuardInterface
    {
        return $this->guards[$name] ?? $this->guards['default'];
    }
}
```

#### 2. TokenManager - Gestão de Tokens

```php
class TokenManager
{
    private array $tokenTypes = [];
    private array $tokenStrategies = [];
    
    public function createToken(int $userId, string $name, array $abilities = ['*'], ?int $expiresIn = null): PersonalAccessToken
    {
        $strategy = $this->getTokenStrategy($name);
        return $strategy->create($userId, $name, $abilities, $expiresIn);
    }
    
    public function registerTokenType(string $type, TokenTypeConfig $config): void
    {
        $this->tokenTypes[$type] = $config;
    }
    
    public function registerTokenStrategy(string $name, TokenStrategyInterface $strategy): void
    {
        $this->tokenStrategies[$name] = $strategy;
    }
}
```

## 🚀 Implementações Avançadas

### 1. Multi-Guard com Diferentes Provedores

```php
<?php
namespace Og\Modules\Common\Guard\Advanced;

use Og\Modules\Common\Guard\GuardManager;

class MultiGuardManager extends GuardManager
{
    private array $providers = [];
    private array $guards = [];
    
    public function __construct(array $config, $database)
    {
        parent::__construct($config, $database);
        $this->initializeProviders();
        $this->initializeGuards();
    }
    
    private function initializeProviders(): void
    {
        $this->providers = [
            'database' => new DatabaseUserProvider($this->db, $this->config['providers']['database']),
            'ldap' => new LdapUserProvider($this->config['providers']['ldap']),
            'api' => new ApiUserProvider($this->config['providers']['api']),
            'saml' => new SamlUserProvider($this->config['providers']['saml'])
        ];
    }
    
    private function initializeGuards(): void
    {
        foreach ($this->config['guards'] as $name => $guardConfig) {
            $this->guards[$name] = $this->createGuard($guardConfig);
        }
    }
    
    public function guard(string $name = null): GuardInterface
    {
        $name = $name ?: $this->getDefaultGuard();
        
        if (!isset($this->guards[$name])) {
            throw new \InvalidArgumentException("Guard [{$name}] not found.");
        }
        
        return $this->guards[$name];
    }
    
    public function authenticateWithProvider(string $provider, array $credentials): ?array
    {
        if (!isset($this->providers[$provider])) {
            throw new \InvalidArgumentException("Provider [{$provider}] not found.");
        }
        
        return $this->providers[$provider]->authenticate($credentials);
    }
    
    private function createGuard(array $config): GuardInterface
    {
        $driver = $config['driver'];
        $provider = $this->providers[$config['provider']];
        
        switch ($driver) {
            case 'token':
                return new TokenGuard($provider, $this->tokenManager);
            case 'session':
                return new SessionGuard($provider, app('session'));
            case 'jwt':
                return new JwtGuard($provider, $config['jwt']);
            default:
                throw new \InvalidArgumentException("Guard driver [{$driver}] not supported.");
        }
    }
}
```

### 2. Token com Scopes Hierárquicos

```php
<?php
namespace Og\Modules\Common\Guard\Advanced;

class HierarchicalScopeManager
{
    private array $scopeHierarchy = [
        'admin' => ['*'],
        'manager' => [
            'vendas.*',
            'stocks.read',
            'stocks.move',
            'reports.read',
            'users.read'
        ],
        'operator' => [
            'vendas.read',
            'vendas.create',
            'stocks.read',
            'reports.basic'
        ],
        'readonly' => [
            '*.read',
            'reports.basic'
        ]
    ];
    
    private array $scopeImplications = [
        'vendas.*' => ['vendas.read', 'vendas.create', 'vendas.update', 'vendas.delete'],
        'stocks.*' => ['stocks.read', 'stocks.create', 'stocks.update', 'stocks.delete', 'stocks.move'],
        '*.read' => ['vendas.read', 'stocks.read', 'users.read', 'reports.read']
    ];
    
    public function expandScopes(array $scopes): array
    {
        $expanded = [];
        
        foreach ($scopes as $scope) {
            // Verificar hierarquia
            if (isset($this->scopeHierarchy[$scope])) {
                $expanded = array_merge($expanded, $this->scopeHierarchy[$scope]);
            } else {
                $expanded[] = $scope;
            }
        }
        
        // Expandir implicações (wildcards)
        $final = [];
        foreach ($expanded as $scope) {
            if (isset($this->scopeImplications[$scope])) {
                $final = array_merge($final, $this->scopeImplications[$scope]);
            } elseif (str_contains($scope, '*')) {
                $final = array_merge($final, $this->expandWildcard($scope));
            } else {
                $final[] = $scope;
            }
        }
        
        return array_unique($final);
    }
    
    public function hasScope(array $userScopes, string $requiredScope): bool
    {
        $expandedScopes = $this->expandScopes($userScopes);
        
        // Verificar scope exato
        if (in_array($requiredScope, $expandedScopes)) {
            return true;
        }
        
        // Verificar wildcard universal
        if (in_array('*', $expandedScopes)) {
            return true;
        }
        
        // Verificar wildcards específicos
        foreach ($expandedScopes as $scope) {
            if ($this->matchesWildcard($scope, $requiredScope)) {
                return true;
            }
        }
        
        return false;
    }
    
    private function expandWildcard(string $wildcard): array
    {
        $expanded = [];
        $pattern = str_replace('*', '.*', preg_quote($wildcard, '/'));
        
        foreach ($this->getAllDefinedScopes() as $scope) {
            if (preg_match("/^{$pattern}$/", $scope)) {
                $expanded[] = $scope;
            }
        }
        
        return $expanded;
    }
    
    private function matchesWildcard(string $pattern, string $scope): bool
    {
        if (!str_contains($pattern, '*')) {
            return false;
        }
        
        $regex = '/^' . str_replace('*', '.*', preg_quote($pattern, '/')) . '$/';
        return preg_match($regex, $scope);
    }
    
    private function getAllDefinedScopes(): array
    {
        return [
            'vendas.read', 'vendas.create', 'vendas.update', 'vendas.delete',
            'stocks.read', 'stocks.create', 'stocks.update', 'stocks.delete', 'stocks.move',
            'users.read', 'users.create', 'users.update', 'users.delete',
            'reports.read', 'reports.create', 'reports.basic', 'reports.advanced',
            'admin.settings', 'admin.users', 'admin.system'
        ];
    }
}
```

### 3. Context-Aware Authentication

```php
<?php
namespace Og\Modules\Common\Guard\Advanced;

class ContextAwareGuard extends GuardManager
{
    private array $contextProviders = [];
    
    public function authenticateWithContext(array $context = []): ?AuthenticationResult
    {
        $token = $this->extractTokenFromRequest();
        if (!$token) {
            return null;
        }
        
        $personalAccessToken = $this->tokenManager->findToken($token);
        if (!$personalAccessToken || !$personalAccessToken->isValid()) {
            return null;
        }
        
        $user = $this->findUser($personalAccessToken->getTokenableId());
        if (!$user) {
            return null;
        }
        
        // Enriquecer com contexto
        $enrichedContext = $this->enrichContext($user, $context);
        
        // Validar contexto
        if (!$this->validateContext($user, $personalAccessToken, $enrichedContext)) {
            return null;
        }
        
        return new AuthenticationResult($user, $personalAccessToken, $enrichedContext);
    }
    
    private function enrichContext(array $user, array $baseContext): array
    {
        $context = array_merge($baseContext, [
            'user_id' => $user['id'],
            'company_id' => $user['empresa'] ?? null,
            'branch_id' => $user['filial'] ?? null,
            'timestamp' => time(),
            'ip_address' => $_SERVER['REMOTE_ADDR'] ?? null,
            'user_agent' => $_SERVER['HTTP_USER_AGENT'] ?? null
        ]);
        
        // Executar provedores de contexto
        foreach ($this->contextProviders as $provider) {
            $context = $provider->enrich($user, $context);
        }
        
        return $context;
    }
    
    private function validateContext(array $user, PersonalAccessToken $token, array $context): bool
    {
        $validators = [
            new IpContextValidator($this->config['security']['allowed_ips'] ?? []),
            new TimeContextValidator($this->config['security']['time_restrictions'] ?? []),
            new CompanyContextValidator(),
            new DeviceContextValidator()
        ];
        
        foreach ($validators as $validator) {
            if (!$validator->validate($user, $token, $context)) {
                $this->logContextValidationFailure($validator, $context);
                return false;
            }
        }
        
        return true;
    }
    
    public function addContextProvider(ContextProviderInterface $provider): void
    {
        $this->contextProviders[] = $provider;
    }
}

class AuthenticationResult
{
    public function __construct(
        private array $user,
        private PersonalAccessToken $token,
        private array $context
    ) {}
    
    public function getUser(): array { return $this->user; }
    public function getToken(): PersonalAccessToken { return $this->token; }
    public function getContext(): array { return $this->context; }
    
    public function hasContextValue(string $key): bool
    {
        return isset($this->context[$key]);
    }
    
    public function getContextValue(string $key, $default = null)
    {
        return $this->context[$key] ?? $default;
    }
}
```

## 🔄 Padrões de Integração

### 1. Guard com Event System

```php
<?php
namespace Og\Modules\Common\Guard\Events;

class GuardEventManager
{
    private array $listeners = [];
    
    public function listen(string $event, callable $listener): void
    {
        if (!isset($this->listeners[$event])) {
            $this->listeners[$event] = [];
        }
        
        $this->listeners[$event][] = $listener;
    }
    
    public function fire(string $event, array $data = []): void
    {
        if (!isset($this->listeners[$event])) {
            return;
        }
        
        foreach ($this->listeners[$event] as $listener) {
            call_user_func($listener, $data);
        }
    }
}

// Integração no GuardManager
class EventAwareGuardManager extends GuardManager
{
    private GuardEventManager $events;
    
    public function __construct(array $config, $database, GuardEventManager $events)
    {
        parent::__construct($config, $database);
        $this->events = $events;
    }
    
    public function authenticate(): ?array
    {
        $this->events->fire('guard.authenticating', ['timestamp' => time()]);
        
        $result = parent::authenticate();
        
        if ($result) {
            $this->events->fire('guard.authenticated', [
                'user' => $result,
                'timestamp' => time()
            ]);
        } else {
            $this->events->fire('guard.authentication_failed', [
                'timestamp' => time(),
                'ip' => $_SERVER['REMOTE_ADDR'] ?? null
            ]);
        }
        
        return $result;
    }
    
    public function logout(): bool
    {
        $user = $this->user();
        $result = parent::logout();
        
        if ($result && $user) {
            $this->events->fire('guard.logged_out', [
                'user' => $user,
                'timestamp' => time()
            ]);
        }
        
        return $result;
    }
}

// Registrar listeners
$events = new GuardEventManager();

$events->listen('guard.authenticated', function($data) {
    error_log("User {$data['user']['id']} authenticated at " . date('c', $data['timestamp']));
});

$events->listen('guard.authentication_failed', function($data) {
    error_log("Authentication failed from IP {$data['ip']} at " . date('c', $data['timestamp']));
    
    // Implementar bloqueio por IP após X tentativas
    $this->handleFailedAttempt($data['ip']);
});
```

### 2. Guard com Cache Distribuído

```php
<?php
namespace Og\Modules\Common\Guard\Cache;

class DistributedGuardCache
{
    private array $cacheDrivers = [];
    private array $config;
    
    public function __construct(array $config)
    {
        $this->config = $config;
        $this->initializeCacheDrivers();
    }
    
    private function initializeCacheDrivers(): void
    {
        foreach ($this->config['cache']['drivers'] as $name => $config) {
            $this->cacheDrivers[$name] = $this->createCacheDriver($config);
        }
    }
    
    public function cacheUser(string $key, array $user, int $ttl = 3600): void
    {
        $strategy = $this->config['cache']['strategy'] ?? 'write_through';
        
        switch ($strategy) {
            case 'write_through':
                $this->writeToAllCaches($key, $user, $ttl);
                break;
            case 'write_behind':
                $this->writeToMainCache($key, $user, $ttl);
                $this->scheduleBackgroundWrite($key, $user, $ttl);
                break;
        }
    }
    
    public function getCachedUser(string $key): ?array
    {
        $strategy = $this->config['cache']['read_strategy'] ?? 'primary_first';
        
        switch ($strategy) {
            case 'primary_first':
                return $this->readPrimaryFirst($key);
            case 'fastest_first':
                return $this->readFastestFirst($key);
            case 'majority_vote':
                return $this->readWithMajorityVote($key);
        }
        
        return null;
    }
    
    private function readPrimaryFirst(string $key): ?array
    {
        foreach ($this->cacheDrivers as $driver) {
            $result = $driver->get($key);
            if ($result) {
                return json_decode($result, true);
            }
        }
        
        return null;
    }
    
    private function readFastestFirst(string $key): ?array
    {
        $promises = [];
        
        foreach ($this->cacheDrivers as $name => $driver) {
            $promises[$name] = $this->asyncGet($driver, $key);
        }
        
        // Retorna o primeiro resultado que chegar
        $result = $this->waitForFirstResult($promises);
        return $result ? json_decode($result, true) : null;
    }
    
    private function writeToAllCaches(string $key, array $user, int $ttl): void
    {
        $serialized = json_encode($user);
        
        foreach ($this->cacheDrivers as $driver) {
            try {
                $driver->put($key, $serialized, $ttl);
            } catch (\Exception $e) {
                error_log("Cache write failed: " . $e->getMessage());
            }
        }
    }
    
    public function invalidateUser(string $key): void
    {
        foreach ($this->cacheDrivers as $driver) {
            try {
                $driver->forget($key);
            } catch (\Exception $e) {
                error_log("Cache invalidation failed: " . $e->getMessage());
            }
        }
    }
}

// Integração com GuardManager
class CachedGuardManager extends GuardManager
{
    private DistributedGuardCache $cache;
    
    public function findUser(int $userId): ?array
    {
        $cacheKey = "guard_user:{$userId}";
        
        // Tentar cache primeiro
        $cached = $this->cache->getCachedUser($cacheKey);
        if ($cached) {
            return $cached;
        }
        
        // Buscar no banco de dados
        $user = parent::findUser($userId);
        
        if ($user) {
            // Cachear para próximas consultas
            $this->cache->cacheUser($cacheKey, $user, 1800); // 30 minutos
        }
        
        return $user;
    }
    
    public function logout(): bool
    {
        $user = $this->user();
        $result = parent::logout();
        
        if ($result && $user) {
            // Invalidar cache do usuário
            $this->cache->invalidateUser("guard_user:{$user['id']}");
        }
        
        return $result;
    }
}
```

## 🏢 Casos de Uso Empresariais

### 1. Multi-Tenant SaaS Authentication

```php
<?php
namespace Og\Modules\Common\Guard\MultiTenant;

class TenantAwareGuard extends GuardManager
{
    private TenantResolver $tenantResolver;
    
    public function __construct(array $config, $database, TenantResolver $tenantResolver)
    {
        parent::__construct($config, $database);
        $this->tenantResolver = $tenantResolver;
    }
    
    public function authenticate(): ?array
    {
        $tenant = $this->tenantResolver->resolve();
        
        if (!$tenant || !$tenant->isActive()) {
            return null;
        }
        
        // Configurar conexão do banco específica do tenant
        $this->switchTenantDatabase($tenant);
        
        $user = parent::authenticate();
        
        if ($user) {
            // Verificar se usuário pertence ao tenant
            if (!$this->userBelongsToTenant($user, $tenant)) {
                return null;
            }
            
            // Adicionar informações do tenant ao contexto
            $user['tenant'] = $tenant->toArray();
        }
        
        return $user;
    }
    
    private function switchTenantDatabase(Tenant $tenant): void
    {
        $tenantDbConfig = [
            'host' => $tenant->getDatabaseHost(),
            'database' => $tenant->getDatabaseName(),
            'username' => $tenant->getDatabaseUser(),
            'password' => $tenant->getDatabasePassword()
        ];
        
        $this->db = new DatabaseConnector($tenantDbConfig);
    }
    
    private function userBelongsToTenant(array $user, Tenant $tenant): bool
    {
        return $user['tenant_id'] === $tenant->getId();
    }
    
    public function createTenantToken(int $userId, Tenant $tenant, string $name, array $abilities = ['*']): PersonalAccessToken
    {
        $token = parent::createToken($userId, $name, $abilities);
        
        // Adicionar metadata do tenant ao token
        $this->addTenantMetadataToToken($token, $tenant);
        
        return $token;
    }
    
    private function addTenantMetadataToToken(PersonalAccessToken $token, Tenant $tenant): void
    {
        $metadata = [
            'tenant_id' => $tenant->getId(),
            'tenant_slug' => $tenant->getSlug(),
            'tenant_features' => $tenant->getActiveFeatures()
        ];
        
        $this->database
            ->where('id', $token->getId())
            ->update('personal_access_tokens', ['metadata' => json_encode($metadata)]);
    }
}

class TenantResolver
{
    public function resolve(): ?Tenant
    {
        // Resolver por subdomain
        if ($tenant = $this->resolveBySubdomain()) {
            return $tenant;
        }
        
        // Resolver por header
        if ($tenant = $this->resolveByHeader()) {
            return $tenant;
        }
        
        // Resolver por token
        if ($tenant = $this->resolveByToken()) {
            return $tenant;
        }
        
        return null;
    }
    
    private function resolveBySubdomain(): ?Tenant
    {
        $host = $_SERVER['HTTP_HOST'] ?? '';
        $subdomain = explode('.', $host)[0];
        
        return Tenant::where('slug', $subdomain)->first();
    }
    
    private function resolveByHeader(): ?Tenant
    {
        $tenantId = $_SERVER['HTTP_X_TENANT_ID'] ?? null;
        
        if ($tenantId) {
            return Tenant::find($tenantId);
        }
        
        return null;
    }
    
    private function resolveByToken(): ?Tenant
    {
        // Extrair tenant do token JWT ou similar
        $token = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
        
        if (str_starts_with($token, 'Bearer ')) {
            $tokenData = $this->decodeToken(substr($token, 7));
            
            if (isset($tokenData['tenant_id'])) {
                return Tenant::find($tokenData['tenant_id']);
            }
        }
        
        return null;
    }
}
```

### 2. Role-Based Access Control (RBAC) Avançado

```php
<?php
namespace Og\Modules\Common\Guard\RBAC;

class RoleBasedGuard extends GuardManager
{
    private RoleManager $roleManager;
    private PermissionManager $permissionManager;
    
    public function __construct(array $config, $database, RoleManager $roleManager, PermissionManager $permissionManager)
    {
        parent::__construct($config, $database);
        $this->roleManager = $roleManager;
        $this->permissionManager = $permissionManager;
    }
    
    public function userCan(string $permission, array $context = []): bool
    {
        $user = $this->user();
        if (!$user) {
            return false;
        }
        
        // Verificar permissões diretas do usuário
        if ($this->userHasDirectPermission($user, $permission, $context)) {
            return true;
        }
        
        // Verificar permissões através de roles
        $roles = $this->roleManager->getUserRoles($user['id']);
        
        foreach ($roles as $role) {
            if ($this->roleHasPermission($role, $permission, $context)) {
                return true;
            }
        }
        
        return false;
    }
    
    public function userHasRole(string $roleName): bool
    {
        $user = $this->user();
        if (!$user) {
            return false;
        }
        
        return $this->roleManager->userHasRole($user['id'], $roleName);
    }
    
    public function userCanAny(array $permissions, array $context = []): bool
    {
        foreach ($permissions as $permission) {
            if ($this->userCan($permission, $context)) {
                return true;
            }
        }
        
        return false;
    }
    
    public function userCanAll(array $permissions, array $context = []): bool
    {
        foreach ($permissions as $permission) {
            if (!$this->userCan($permission, $context)) {
                return false;
            }
        }
        
        return true;
    }
    
    private function userHasDirectPermission(array $user, string $permission, array $context): bool
    {
        $userPermissions = $this->permissionManager->getUserDirectPermissions($user['id']);
        
        foreach ($userPermissions as $userPermission) {
            if ($this->permissionMatches($userPermission, $permission, $context)) {
                return true;
            }
        }
        
        return false;
    }
    
    private function roleHasPermission(Role $role, string $permission, array $context): bool
    {
        $rolePermissions = $this->permissionManager->getRolePermissions($role->getId());
        
        foreach ($rolePermissions as $rolePermission) {
            if ($this->permissionMatches($rolePermission, $permission, $context)) {
                return true;
            }
        }
        
        return false;
    }
    
    private function permissionMatches(Permission $userPermission, string $requiredPermission, array $context): bool
    {
        // Verificar nome da permissão
        if (!$this->permissionNameMatches($userPermission->getName(), $requiredPermission)) {
            return false;
        }
        
        // Verificar contexto (ex: empresa, filial)
        if (!$this->contextMatches($userPermission->getContext(), $context)) {
            return false;
        }
        
        // Verificar condições temporais
        if (!$this->temporalConditionsMatch($userPermission)) {
            return false;
        }
        
        return true;
    }
    
    private function permissionNameMatches(string $userPermission, string $requiredPermission): bool
    {
        // Suporte a wildcards
        if ($userPermission === '*') {
            return true;
        }
        
        if (str_contains($userPermission, '*')) {
            $pattern = str_replace('*', '.*', preg_quote($userPermission, '/'));
            return preg_match("/^{$pattern}$/", $requiredPermission);
        }
        
        return $userPermission === $requiredPermission;
    }
    
    private function contextMatches(array $permissionContext, array $requestContext): bool
    {
        foreach ($permissionContext as $key => $value) {
            if (isset($requestContext[$key]) && $requestContext[$key] !== $value) {
                return false;
            }
        }
        
        return true;
    }
    
    private function temporalConditionsMatch(Permission $permission): bool
    {
        $now = time();
        
        if ($permission->getValidFrom() && $now < $permission->getValidFrom()) {
            return false;
        }
        
        if ($permission->getValidUntil() && $now > $permission->getValidUntil()) {
            return false;
        }
        
        // Verificar horários permitidos
        if ($timeRestrictions = $permission->getTimeRestrictions()) {
            if (!$this->isWithinTimeRestrictions($timeRestrictions)) {
                return false;
            }
        }
        
        return true;
    }
}

class RoleManager
{
    private $database;
    private array $roleCache = [];
    
    public function getUserRoles(int $userId): array
    {
        if (!isset($this->roleCache[$userId])) {
            $this->roleCache[$userId] = $this->database
                ->select('r.*')
                ->from('roles r')
                ->join('user_roles ur', 'r.id = ur.role_id')
                ->where('ur.user_id', $userId)
                ->where('r.active', 1)
                ->get()
                ->result();
        }
        
        return array_map(fn($role) => new Role($role), $this->roleCache[$userId]);
    }
    
    public function assignRole(int $userId, string $roleName, array $context = []): bool
    {
        $role = $this->findRoleByName($roleName);
        if (!$role) {
            return false;
        }
        
        $data = [
            'user_id' => $userId,
            'role_id' => $role->getId(),
            'context' => json_encode($context),
            'assigned_at' => date('Y-m-d H:i:s')
        ];
        
        $this->database->insert('user_roles', $data);
        
        // Limpar cache
        unset($this->roleCache[$userId]);
        
        return true;
    }
}
```

## 🔮 Implementações Futuras

### 1. ApplicationGuard - Autenticação por Aplicação

```php
<?php
namespace Og\Modules\Common\Guard\Future;

class ApplicationGuard implements GuardInterface
{
    private ApplicationManager $applicationManager;
    private ModuleManager $moduleManager;
    private LicenseManager $licenseManager;
    
    public function authenticate(Request $request): ?ApplicationContext
    {
        $appToken = $request->header('X-Application-Token');
        $userToken = $request->header('Authorization');
        
        // 1. Validar token de aplicação
        $application = $this->applicationManager->validateToken($appToken);
        if (!$application) {
            throw new InvalidApplicationTokenException();
        }
        
        // 2. Verificar licença da aplicação
        if (!$this->licenseManager->isApplicationLicenseValid($application)) {
            throw new ApplicationLicenseExpiredException();
        }
        
        // 3. Autenticar usuário no contexto da aplicação
        $user = null;
        if ($userToken) {
            $user = $this->authenticateUserInApplication($userToken, $application);
        }
        
        // 4. Carregar módulos ativos
        $activeModules = $this->moduleManager->getActiveModules($application);
        
        // 5. Criar contexto de aplicação
        return new ApplicationContext([
            'application' => $application,
            'user' => $user,
            'modules' => $activeModules,
            'permissions' => $this->resolvePermissions($application, $user),
            'features' => $this->resolveFeatures($application, $user)
        ]);
    }
    
    private function authenticateUserInApplication(string $token, Application $application): ?User
    {
        $tokenData = $this->parseToken($token);
        
        // Verificar se o token pertence à aplicação
        if ($tokenData['app_id'] !== $application->getId()) {
            return null;
        }
        
        // Buscar usuário
        $user = $this->findUser($tokenData['user_id']);
        
        // Verificar se usuário tem acesso à aplicação
        if (!$this->userHasApplicationAccess($user, $application)) {
            return null;
        }
        
        return $user;
    }
    
    private function resolvePermissions(Application $application, ?User $user): array
    {
        $permissions = [];
        
        // Permissões da aplicação
        $permissions = array_merge($permissions, $application->getPermissions());
        
        // Permissões do usuário (se autenticado)
        if ($user) {
            $userPermissions = $user->getPermissionsInApplication($application->getId());
            $permissions = array_merge($permissions, $userPermissions);
        }
        
        return array_unique($permissions);
    }
}

class ApplicationContext
{
    private array $data;
    
    public function __construct(array $data)
    {
        $this->data = $data;
    }
    
    public function getApplication(): Application
    {
        return $this->data['application'];
    }
    
    public function getUser(): ?User
    {
        return $this->data['user'] ?? null;
    }
    
    public function hasModule(string $module): bool
    {
        return in_array(strtolower($module), array_map('strtolower', $this->data['modules']));
    }
    
    public function hasPermission(string $permission): bool
    {
        return in_array($permission, $this->data['permissions']);
    }
    
    public function hasFeature(string $feature): bool
    {
        return in_array($feature, $this->data['features']);
    }
    
    public function isUserAuthenticated(): bool
    {
        return $this->data['user'] !== null;
    }
}

// Middleware correspondente
class ApplicationGuardMiddleware implements MiddlewareInterface
{
    private ApplicationGuard $applicationGuard;
    
    public function handle(Request $request, Closure $next, string $requiredModule = null): mixed
    {
        try {
            $context = $this->applicationGuard->authenticate($request);
            
            // Verificar módulo requerido
            if ($requiredModule && !$context->hasModule($requiredModule)) {
                return Response::json([
                    'error' => 'Module Not Available',
                    'message' => "Application doesn't have access to module: {$requiredModule}",
                    'available_modules' => $context->getApplication()->getActiveModules()
                ], 403);
            }
            
            // Adicionar contexto ao request
            $request->attributes->set('app_context', $context);
            
            return $next($request);
            
        } catch (ApplicationGuardException $e) {
            return Response::json([
                'error' => 'Application Authentication Failed',
                'message' => $e->getMessage()
            ], 401);
        }
    }
}
```

### 2. Biometric Authentication Guard

```php
<?php
namespace Og\Modules\Common\Guard\Future;

class BiometricGuard extends GuardManager
{
    private BiometricProcessor $biometricProcessor;
    private array $supportedBiometrics = ['fingerprint', 'face', 'voice', 'iris'];
    
    public function authenticateWithBiometric(string $biometricType, string $biometricData, array $metadata = []): ?array
    {
        if (!in_array($biometricType, $this->supportedBiometrics)) {
            throw new UnsupportedBiometricException("Biometric type '{$biometricType}' not supported");
        }
        
        // Processar dados biométricos
        $processedData = $this->biometricProcessor->process($biometricType, $biometricData, $metadata);
        
        // Buscar usuário por biometria
        $user = $this->findUserByBiometric($biometricType, $processedData);
        
        if (!$user) {
            $this->logBiometricFailure($biometricType, $metadata);
            return null;
        }
        
        // Verificar qualidade da biometria
        if ($processedData['confidence'] < $this->getMinimumConfidence($biometricType)) {
            $this->logLowConfidenceBiometric($user, $processedData['confidence']);
            return null;
        }
        
        // Criar token específico para autenticação biométrica
        $token = $this->createBiometricToken($user, $biometricType, $processedData['confidence']);
        
        $this->logBiometricSuccess($user, $biometricType, $processedData['confidence']);
        
        return [
            'user' => $user,
            'token' => $token,
            'biometric_confidence' => $processedData['confidence'],
            'authentication_method' => 'biometric_' . $biometricType
        ];
    }
    
    public function registerBiometric(int $userId, string $biometricType, string $biometricData): bool
    {
        $processedData = $this->biometricProcessor->process($biometricType, $biometricData);
        
        $biometricRecord = [
            'user_id' => $userId,
            'biometric_type' => $biometricType,
            'biometric_hash' => $processedData['hash'],
            'biometric_template' => $processedData['template'],
            'quality_score' => $processedData['quality'],
            'registered_at' => date('Y-m-d H:i:s'),
            'device_info' => json_encode($_SERVER['HTTP_USER_AGENT'] ?? 'unknown')
        ];
        
        return $this->database->insert('user_biometrics', $biometricRecord);
    }
    
    private function createBiometricToken(array $user, string $biometricType, float $confidence): PersonalAccessToken
    {
        $abilities = $this->getBiometricAbilities($biometricType, $confidence);
        $expiresIn = $this->getBiometricTokenExpiry($biometricType, $confidence);
        
        $token = $this->createToken($user['id'], "biometric_{$biometricType}", $abilities, $expiresIn);
        
        // Adicionar metadata específica
        $this->addBiometricMetadata($token, $biometricType, $confidence);
        
        return $token;
    }
    
    private function getBiometricAbilities(string $biometricType, float $confidence): array
    {
        // Permissões baseadas no tipo de biometria e confiança
        $baseAbilities = ['biometric:authenticated'];
        
        if ($confidence >= 0.95) {
            $baseAbilities[] = 'high_security:access';
        } elseif ($confidence >= 0.85) {
            $baseAbilities[] = 'medium_security:access';
        } else {
            $baseAbilities[] = 'basic_security:access';
        }
        
        // Abilities específicas por tipo
        switch ($biometricType) {
            case 'fingerprint':
                $baseAbilities[] = 'fingerprint:verified';
                break;
            case 'face':
                $baseAbilities[] = 'face:verified';
                if ($confidence >= 0.90) {
                    $baseAbilities[] = 'face:high_confidence';
                }
                break;
        }
        
        return $baseAbilities;
    }
}

class BiometricProcessor
{
    private array $processors = [];
    
    public function process(string $type, string $data, array $metadata = []): array
    {
        if (!isset($this->processors[$type])) {
            throw new BiometricProcessorNotFoundException("Processor for '{$type}' not found");
        }
        
        return $this->processors[$type]->process($data, $metadata);
    }
    
    public function registerProcessor(string $type, BiometricProcessorInterface $processor): void
    {
        $this->processors[$type] = $processor;
    }
}
```

## ⚡ Performance e Otimização

### 1. Connection Pooling para Database

```php
<?php
namespace Og\Modules\Common\Guard\Performance;

class ConnectionPoolManager
{
    private array $pools = [];
    private array $config;
    
    public function __construct(array $config)
    {
        $this->config = $config;
        $this->initializePools();
    }
    
    private function initializePools(): void
    {
        foreach ($this->config['pools'] as $name => $poolConfig) {
            $this->pools[$name] = new ConnectionPool($poolConfig);
        }
    }
    
    public function getConnection(string $poolName = 'default'): DatabaseConnection
    {
        return $this->pools[$poolName]->getConnection();
    }
    
    public function releaseConnection(string $poolName, DatabaseConnection $connection): void
    {
        $this->pools[$poolName]->releaseConnection($connection);
    }
}

class ConnectionPool
{
    private \SplQueue $available;
    private \SplObjectStorage $inUse;
    private array $config;
    private int $currentSize = 0;
    
    public function __construct(array $config)
    {
        $this->config = $config;
        $this->available = new \SplQueue();
        $this->inUse = new \SplObjectStorage();
        
        // Criar conexões iniciais
        $this->createInitialConnections();
    }
    
    public function getConnection(): DatabaseConnection
    {
        if ($this->available->isEmpty() && $this->canCreateMore()) {
            $this->createConnection();
        }
        
        if ($this->available->isEmpty()) {
            throw new NoAvailableConnectionsException();
        }
        
        $connection = $this->available->dequeue();
        $this->inUse->attach($connection);
        
        return $connection;
    }
    
    public function releaseConnection(DatabaseConnection $connection): void
    {
        if ($this->inUse->contains($connection)) {
            $this->inUse->detach($connection);
            
            // Verificar se conexão ainda é válida
            if ($connection->isValid()) {
                $this->available->enqueue($connection);
            } else {
                $this->currentSize--;
            }
        }
    }
}
```

### 2. Query Optimization

```php
<?php
namespace Og\Modules\Common\Guard\Performance;

class OptimizedGuardManager extends GuardManager
{
    private QueryCache $queryCache;
    private array $batchQueries = [];
    
    public function __construct(array $config, $database, QueryCache $queryCache)
    {
        parent::__construct($config, $database);
        $this->queryCache = $queryCache;
    }
    
    public function findUser(int $userId): ?array
    {
        $cacheKey = "user:{$userId}";
        
        // Verificar cache first-level (em memória)
        if ($cached = $this->queryCache->getFromMemory($cacheKey)) {
            return $cached;
        }
        
        // Verificar cache second-level (Redis/Memcached)
        if ($cached = $this->queryCache->getFromDistributed($cacheKey)) {
            $this->queryCache->setInMemory($cacheKey, $cached, 300); // 5 min
            return $cached;
        }
        
        // Batch query se possível
        if ($this->shouldBatchQuery()) {
            return $this->addToBatchQuery('user', $userId);
        }
        
        // Query individual
        $user = $this->executeUserQuery($userId);
        
        if ($user) {
            // Cache em ambos os níveis
            $this->queryCache->setInMemory($cacheKey, $user, 300);
            $this->queryCache->setInDistributed($cacheKey, $user, 1800); // 30 min
        }
        
        return $user;
    }
    
    private function shouldBatchQuery(): bool
    {
        return count($this->batchQueries) > 0 || $this->isInBatchContext();
    }
    
    private function addToBatchQuery(string $type, int $id): ?array
    {
        if (!isset($this->batchQueries[$type])) {
            $this->batchQueries[$type] = [];
        }
        
        $this->batchQueries[$type][] = $id;
        
        // Executar batch quando atingir limite ou timeout
        if (count($this->batchQueries[$type]) >= 10) {
            return $this->executeBatchQuery($type);
        }
        
        // Defer para próxima iteração
        return null;
    }
    
    private function executeBatchQuery(string $type): array
    {
        $ids = $this->batchQueries[$type];
        $this->batchQueries[$type] = [];
        
        switch ($type) {
            case 'user':
                return $this->batchLoadUsers($ids);
            case 'permission':
                return $this->batchLoadPermissions($ids);
        }
        
        return [];
    }
    
    private function batchLoadUsers(array $userIds): array
    {
        $users = $this->database
            ->select('*')
            ->from($this->config['user']['table'])
            ->where_in($this->config['user']['id_column'], $userIds)
            ->get()
            ->result_array();
        
        // Cache todos os usuários carregados
        foreach ($users as $user) {
            $cacheKey = "user:{$user[$this->config['user']['id_column']]}";
            $this->queryCache->setInMemory($cacheKey, $user, 300);
            $this->queryCache->setInDistributed($cacheKey, $user, 1800);
        }
        
        return $users;
    }
}

class QueryCache
{
    private array $memoryCache = [];
    private $distributedCache;
    private int $maxMemoryItems = 1000;
    
    public function getFromMemory(string $key)
    {
        return $this->memoryCache[$key]['data'] ?? null;
    }
    
    public function setInMemory(string $key, $data, int $ttl): void
    {
        if (count($this->memoryCache) >= $this->maxMemoryItems) {
            $this->evictOldestMemoryItems();
        }
        
        $this->memoryCache[$key] = [
            'data' => $data,
            'expires' => time() + $ttl,
            'accessed' => time()
        ];
    }
    
    public function getFromDistributed(string $key)
    {
        return $this->distributedCache?->get($key);
    }
    
    public function setInDistributed(string $key, $data, int $ttl): void
    {
        $this->distributedCache?->put($key, $data, $ttl);
    }
    
    private function evictOldestMemoryItems(): void
    {
        // Remover itens expirados primeiro
        $now = time();
        foreach ($this->memoryCache as $key => $item) {
            if ($item['expires'] < $now) {
                unset($this->memoryCache[$key]);
            }
        }
        
        // Se ainda está cheio, remover os menos recentemente acessados
        if (count($this->memoryCache) >= $this->maxMemoryItems) {
            uasort($this->memoryCache, fn($a, $b) => $a['accessed'] <=> $b['accessed']);
            $this->memoryCache = array_slice($this->memoryCache, -($this->maxMemoryItems - 100), null, true);
        }
    }
}
```

Esta documentação abrange implementações avançadas do sistema Guard, desde padrões de integração complexos até otimizações de performance, fornecendo uma base sólida para desenvolver sistemas de autenticação robustos e escaláveis no contexto do OfficeGest ERP.