josequembi / angola-geoguard
Pacote PHP e Laravel para geolocalização, geofencing, controlo territorial, restrição de acesso e segurança geoespacial em Angola.
Requires
- php: ^8.3
- ext-json: *
- ramsey/uuid: ^4.7
Requires (Dev)
- laravel/pint: ^1.16
- orchestra/testbench: ^9.0|^10.0
- phpstan/phpstan: ^2.2
- phpunit/phpunit: ^11.0
- rector/rector: ^2.0
Suggests
- geoip2/geoip2: Necessario para o provedor MaxMind GeoLite2/GeoIP2
- illuminate/database: Requerido para migrations, models e query builder Laravel
- illuminate/http: Requerido para middleware e resolucao de pedidos Laravel
- illuminate/support: Requerido para a integracao Laravel (^10.0|^11.0|^12.0)
- predis/predis: Recomendado para cache distribuido em producao
This package is auto-updated.
Last update: 2026-07-29 06:34:54 UTC
README
Angola GeoGuard é um pacote PHP/Laravel para geolocalização, geofencing, controlo territorial, restrição de acesso e segurança geoespacial em Angola. Ele permite proteger rotas, APIs e fluxos internos por país, província, geofence personalizado, listas de permissão/bloqueio e políticas híbridas.
O pacote foi desenhado para aplicações que precisam de decisões territoriais auditáveis: SaaS multi-tenant, portais institucionais, plataformas privadas, operações com restrições provinciais e sistemas que exigem defesa contra VPN, proxy, Tor, datacenters e padrões de tráfego suspeitos.
Estado do projeto: núcleo, modelos, migrations, seed das 21 províncias, motor de políticas, middleware, auditoria, importação GeoJSON e deteção comportamental estão implementados. As geometrias oficiais de fronteiras provinciais não são incluídas no pacote; devem ser importadas de uma fonte oficial ou verificável.
Destaques
- Suporte às 21 províncias de Angola, incluindo a reorganização de 2024.
- API fluida via
GeoGuard::request($request)->province(...)->evaluate(). - Middleware Laravel:
geo.angola,geo.province,geo.provinces,geo.policy,geo.global,geo.no-vpn,geo.no-proxyegeo.verified. - Motor espacial em memória, PostGIS ou MySQL/MariaDB Spatial.
- Tokens de localização assinados por HMAC, com expiração e proteção contra replay.
- Resolução segura de IP real atrás de proxies confiáveis.
- Auditoria de decisões e comandos Artisan para diagnóstico, importação e limpeza.
- Deteção comportamental heurística com contramedidas progressivas.
- Comando
geoguard:calibratepara sugerir limiares a partir do histórico real. - Testes automatizados com PHPUnit, PHPStan 2 e Laravel Pint.
Índice
- Requisitos
- Instalação
- Publicação da configuração e migrations
- Configuração básica
- Seed das províncias
- Uso rápido
- Middleware
- Políticas e modos de acesso
- Geofences personalizados
- Dados geográficos e fronteiras
- Provedores de geolocalização
- Segurança
- Deteção comportamental
- Calibração por tráfego real
- Comandos Artisan
- Qualidade e testes
- Publicação no Packagist
- Segurança e licença
Requisitos
- PHP 8.3 ou superior.
- Laravel 10, 11 ou 12 para integração completa.
- Extensão PHP
json.
O núcleo em Core/, DTOs/, Enums/, Security/, Spatial/ e
ValueObjects/ é framework-agnostic e pode ser testado sem Laravel.
Instalação
composer require josequembi/angola-geoguard
Publicação da configuração e migrations
php artisan vendor:publish \
--provider="JoseQuembi\AngolaGeoGuard\AngolaGeoGuardServiceProvider"
php artisan migrate
Também pode publicar apenas grupos específicos:
php artisan vendor:publish --tag=angola-geoguard-config php artisan vendor:publish --tag=angola-geoguard-migrations
Configuração básica
Todas as opções ficam em config/angola-geoguard.php e podem ser
controladas por variáveis de ambiente:
ANGOLA_GEOGUARD_ENABLED=true ANGOLA_GEOGUARD_DEFAULT_MODE=angola_only ANGOLA_GEOGUARD_FAILURE_MODE=deny ANGOLA_GEOGUARD_BLOCK_VPN=false ANGOLA_GEOGUARD_BLOCK_PROXY=false ANGOLA_GEOGUARD_BLOCK_TOR=true ANGOLA_GEOGUARD_BLOCK_DATACENTER=false ANGOLA_GEOGUARD_TRUSTED_PROXIES=173.245.48.0/20,10.0.0.0/8 ANGOLA_GEOGUARD_TOKEN_KEY=troque-esta-chave-em-producao ANGOLA_GEOGUARD_SPATIAL_ENGINE=memory
ANGOLA_GEOGUARD_FAILURE_MODE define o que acontece quando a localização
não pode ser resolvida:
deny: nega por padrão, recomendado para sistemas privados.allow: permite por padrão, útil apenas em cenários de baixo risco.challenge: exige verificação adicional.observe: não bloqueia, apenas regista a decisão.
Seed das províncias
php artisan geoguard:seed-angola
Ou diretamente pelo seeder:
php artisan db:seed --class="JoseQuembi\AngolaGeoGuard\Database\Seeders\AngolaProvincesSeeder"
O seed cria Angola e as 21 províncias com nome oficial, capital e código interno estável. As colunas de geometria ficam vazias até importar dados oficiais ou verificáveis.
Uso rápido
use JoseQuembi\AngolaGeoGuard\Facades\GeoGuard; $decision = GeoGuard::request($request) ->country('AO') ->minimumConfidence('medium') ->denyVpn() ->evaluate(); if ($decision->denied()) { abort(403, $decision->publicMessage()); }
Restringir a uma província:
GeoGuard::request($request) ->province('huila') ->evaluate();
Permitir várias províncias:
GeoGuard::request($request) ->provinces(['huila', 'benguela', 'namibe']) ->evaluate();
Usar uma política persistida e exceções temporárias por utilizador:
GeoGuard::request($request) ->forUser($user->id) ->usingPolicy('acesso-interno-governo') ->evaluate();
Middleware
Route::middleware(['auth', 'geo.angola'])->group(function () { Route::get('/dashboard', DashboardController::class); }); Route::middleware(['geo.province:huila'])->group(function () { Route::get('/sistema-provincial', ProvincialController::class); }); Route::middleware(['geo.provinces:huila,benguela,namibe'])->group(function () { Route::get('/regiao-sul', SouthernRegionController::class); }); Route::middleware(['geo.policy:acesso-interno-governo'])->group(function () { Route::get('/sistema-interno', InternalSystemController::class); }); Route::middleware(['geo.global', 'geo.no-vpn'])->group(function () { Route::get('/global', GlobalController::class); });
A decisão fica disponível em:
$request->attributes->get('geo_access_decision');
Não existe bypass por parâmetro público, como ?bypass=true. Essa decisão é
intencional para evitar evasão trivial.
Políticas e modos de acesso
| Modo | Enum | Descrição |
|---|---|---|
| Global | GLOBAL |
Permite qualquer país; regras de segurança continuam ativas |
| Apenas Angola | ANGOLA_ONLY |
Permite apenas country_code === 'AO' |
| Uma província | PROVINCE_ONLY |
Permite uma única província |
| Várias províncias | MULTIPLE_PROVINCES |
Permite uma lista de províncias |
| Geofence personalizado | CUSTOM_GEOFENCE |
Avalia polígonos ou multipolígonos GeoJSON |
| Lista de bloqueio | BLOCKLIST |
Bloqueia províncias específicas |
| Lista de permissão | ALLOWLIST |
Permite apenas províncias listadas |
| Híbrido | HYBRID |
Combina lista de bloqueio e permissão; bloqueio tem prioridade |
Geofences personalizados
use JoseQuembi\AngolaGeoGuard\DTOs\GeoAccessPolicyConfig; use JoseQuembi\AngolaGeoGuard\Enums\AccessMode; use JoseQuembi\AngolaGeoGuard\Services\GeoAccessPolicyEngine; $policy = GeoAccessPolicyConfig::fromArray([ 'mode' => AccessMode::CUSTOM_GEOFENCE, 'allowed_geofences' => ['sede-luanda'], ]); $geometries = [ 'sede-luanda' => $geofenceModel->geometry, ]; $decision = app(GeoAccessPolicyEngine::class) ->evaluate($location, $policy, $geometries);
O motor em memória aceita Polygon e MultiPolygon no formato GeoJSON,
incluindo polígonos com buracos.
Dados geográficos e fronteiras
O pacote inclui dados administrativos das províncias, mas não inclui fronteiras oficiais. Isso evita publicar limites territoriais inventados, desatualizados ou sem licença clara.
Para importar geometrias:
php artisan geoguard:import \
--file=/caminho/fronteiras-ago-adm1.geojson \
--source="Fonte oficial ou verificável" \
--version=2026.1
O importador valida FeatureCollection, Polygon e MultiPolygon, cria
uma nova versão em geo_data_versions e associa as geometrias às províncias
existentes por código interno, slug ou alias documentado.
Provedores de geolocalização
O pacote não força nenhum serviço comercial. Por padrão, usa
NullGeolocationProvider para nunca inventar localização.
Para ativar resolução por IP, registe um adaptador que implemente
GeolocationProviderInterface:
$this->app->bind( \JoseQuembi\AngolaGeoGuard\Contracts\GeolocationProviderInterface::class, fn () => new MyMaxMindAdapter(config('angola-geoguard.providers.maxmind.database_path')), );
Segurança
Proxies confiáveis
Cabeçalhos como X-Forwarded-For, CF-Connecting-IP, True-Client-IP e
X-Real-IP só são considerados quando o IP de origem pertence a um CIDR
configurado em ANGOLA_GEOGUARD_TRUSTED_PROXIES.
Nunca use:
ANGOLA_GEOGUARD_TRUSTED_PROXIES=0.0.0.0/0
Tokens de localização assinados
Para rotas de alto risco, pode exigir um token assinado:
use JoseQuembi\AngolaGeoGuard\Security\LocationToken; use JoseQuembi\AngolaGeoGuard\ValueObjects\Coordinates; $token = LocationToken::issue( userId: (string) $user->id, coordinates: new Coordinates($lat, $lng), signingKey: config('angola-geoguard.security.location_token.key'), ttlSeconds: 300, );
O cliente envia o token no cabeçalho X-Location-Token. O middleware
geo.verified valida assinatura HMAC, expiração, coordenadas e replay.
Deteção comportamental
Além da decisão por pedido, o pacote observa padrões por sujeito ao longo do tempo. Essa camada é heurística e estatística; não é um modelo de machine learning treinado.
Sinais avaliados:
| Sinal | Padrão detetado |
|---|---|
impossible_travel |
Velocidade implícita fisicamente improvável entre duas localizações |
high_denial_ratio |
Muitos pedidos negados numa janela curta |
rapid_fire |
Intervalo entre pedidos muito abaixo da linha de base aprendida |
province_enumeration |
Muitas províncias distintas tentadas numa janela curta |
country_hopping |
Mudanças frequentes de país |
evasion_signal_cycling |
Alternância repetida de VPN, proxy ou Tor |
Contramedidas possíveis:
NONE -> LOG_ONLY -> CHALLENGE -> THROTTLE -> QUARANTINE
A quarentena é escalonada por reincidência, no estilo fail2ban.
Calibração por tráfego real
Depois de acumular histórico em geo_access_decisions, use:
php artisan geoguard:calibrate --days=30 php artisan geoguard:calibrate --days=30 --env
O comando sugere limiares para threat_detection.thresholds com base em
percentis reais: taxa de negação, enumeração territorial, alternância de
sinais de evasão, rajadas de pedidos e viagem impossível.
O comando é somente leitura; ele não altera configuração automaticamente.
Comandos Artisan
php artisan geoguard:install
php artisan geoguard:publish
php artisan geoguard:seed-angola
php artisan geoguard:import --file=fronteiras.geojson --source="Fonte" --version=2026.1
php artisan geoguard:validate
php artisan geoguard:diagnose
php artisan geoguard:audit --days=7
php artisan geoguard:calibrate --days=30 --env
php artisan geoguard:threats
php artisan geoguard:clear-cache
php artisan geoguard:prune
php artisan geoguard:rollback-data 2026.1
Qualidade e testes
composer install composer quality
composer quality executa:
- Laravel Pint.
- PHPStan 2 no nível 8.
- PHPUnit.
Também pode executar separadamente:
composer pint:test
composer stan
composer test
Publicação no Packagist
Para boa apresentação no Packagist:
-
Garanta que
composer.jsonestá validado:composer validate --strict
-
Publique o repositório no GitHub com uma tag semântica:
git tag v0.1.0 git push origin main --tags
-
Registe o pacote em packagist.org.
-
Ative o hook GitHub/Packagist para atualizar releases automaticamente.
-
Mantenha o README em português claro, com exemplos executáveis e changelog.
Segurança e licença
Vulnerabilidades devem ser reportadas de forma privada. Consulte SECURITY.md.
O pacote usa licença proprietária por padrão. Consulte LICENSE e ajuste a licença antes de publicação pública caso deseje distribuição open source.