# d::Gois — Site institucional de 10 anos

Novo site institucional multipágina da **d::Gois Inteligência Empresarial**, construído em PHP com MVC próprio, sem banco de dados e preparado para Apache 2.

## Requisitos

- PHP 8.2 ou superior com sessões, OpenSSL e `allow_url_fopen` habilitados (`mbstring` é recomendada para contagem Unicode precisa, mas há fallback seguro);
- Apache 2.4 com `mod_rewrite`, `mod_headers` e, opcionalmente, `mod_deflate`;
- Composer 2 (recomendado para gerar o autoload otimizado; o projeto inclui um autoloader PSR-4 de contingência para desenvolvimento).

## Instalação local

```bash
cp .env.example .env
composer install
composer serve
```

Sem Composer instalado, use:

```bash
cp .env.example .env
php -S 127.0.0.1:8000 -t public public/router.php
```

Acesse `http://localhost:8000`. Ajuste `APP_URL` no `.env` para corresponder ao endereço utilizado.

## Estrutura

- `app/Controllers`: entrada das ações web;
- `app/Core`: roteamento, requisição, resposta, views, CSRF e segurança;
- `app/Repositories`: contratos e implementação baseada em arquivos;
- `app/Services`: casos de uso e adaptadores;
- `app/Views`: layouts, componentes e páginas;
- `content`: conteúdo institucional fora da pasta pública;
- `public`: único diretório que deve ser exposto pelo servidor;
- `config`: exemplos para Apache e Nginx;
- `storage`: cache de rate limit e logs não públicos;
- `tests`: suíte leve, sem dependências externas.

## Editando conteúdo e serviços

Os quatro serviços ficam em `content/services.php`. Dados institucionais e canais oficiais ficam em `content/site.php`. Controllers e templates não precisam ser modificados para atualizar esses textos.

O contrato `ServiceRepositoryInterface` desacopla o conteúdo da apresentação. Uma futura implementação via PDO pode cumprir a mesma interface e ser injetada no bootstrap sem reescrever controllers.

## Logo e imagens

O logo comemorativo utilizado está em `public/assets/images/dgois-10-anos.png`. Para produção, substitua esse arquivo pelo PNG/SVG master oficial, mantendo o mesmo nome ou atualizando as referências. Preserve área de respiro, proporções e contraste.

## Formulário de contato

O formulário possui validação no servidor, CSRF, honeypot, limite de cinco tentativas por IP a cada quinze minutos e consentimento de privacidade.

O adaptador local `LogContactSender` **não grava nome, mensagem, telefone ou e-mail em texto aberto**. Ele registra apenas data, identificador técnico e uma impressão irreversível do e-mail.

Em produção, o adaptador `MicrosoftGraphContactSender` envia o contato pelo Microsoft Graph usando OAuth 2.0 `client_credentials`. O visitante é configurado como `Reply-To`, permitindo responder diretamente pelo Outlook, e todos os valores inseridos no corpo HTML são escapados.

### Configuração do Microsoft 365

1. No Microsoft Entra, registre um aplicativo para o site;
2. Em **API permissions**, adicione Microsoft Graph → **Application permissions** → `Mail.Send`;
3. Conceda o consentimento administrativo;
4. Crie um segredo do cliente e guarde somente o **valor** do segredo no `.env`;
5. Recomenda-se restringir o aplicativo à caixa remetente com **RBAC for Applications** no Exchange Online, pois `Mail.Send` de aplicação sem escopo permite enviar como qualquer usuário da organização;
6. Configure o `.env`:

```dotenv
MAIL_DRIVER=graph
CONTACT_RECIPIENT=contato@dgois.com.br
MS_GRAPH_TENANT_ID=<directory-tenant-id>
MS_GRAPH_CLIENT_ID=<application-client-id>
MS_GRAPH_CLIENT_SECRET=<client-secret-value>
MS_GRAPH_SENDER=contato@dgois.com.br
MS_GRAPH_TIMEOUT=10
```

`MS_GRAPH_SENDER` deve identificar uma caixa existente no Exchange Online. `CONTACT_RECIPIENT` é o endereço que receberá os contatos e pode ser diferente. O segredo nunca deve ser incluído no `.env.example` nem no Git.

O envio usa `POST /users/{remetente}/sendMail`; uma resposta HTTP `202 Accepted` é considerada sucesso de submissão pelo Graph. Falhas registram somente etapa, status HTTP, código seguro e `request-id`, sem token nem conteúdo da mensagem. Mantenha `MAIL_DRIVER=log` no desenvolvimento para não realizar envios reais.

Documentação oficial: [fluxo client credentials](https://learn.microsoft.com/entra/identity-platform/v2-oauth2-client-creds-grant-flow), [ação sendMail](https://learn.microsoft.com/graph/api/user-sendmail?view=graph-rest-1.0) e [RBAC para aplicações no Exchange Online](https://learn.microsoft.com/exchange/permissions-exo/application-rbac).

## Testes

```bash
php tests/run.php
find app bootstrap config content public routes tests -name '*.php' -print0 | xargs -0 -n1 php -l
```

Os testes cobrem repositório, contratos, validação do formulário, CSRF, roteamento, renderização das páginas e 404.

## Publicação no Apache

1. Envie o projeto para, por exemplo, `/var/www/dgois`;
2. Mantenha `.env`, `app`, `content`, `storage` e `vendor` fora do DocumentRoot;
3. Use **`/var/www/dgois/public`** como `DocumentRoot`;
4. Adapte `config/apache-vhost.conf.example` ao servidor;
5. Habilite módulos: `a2enmod rewrite headers deflate ssl`;
6. Garanta escrita do usuário do PHP em `storage/cache` e `storage/logs`, sem permissões abertas;
7. Configure HTTPS e defina `APP_ENV=production`, `APP_DEBUG=false` e `APP_URL=https://www.dgois.com.br`;
8. Crie um `APP_KEY` longo e aleatório e configure as credenciais de e-mail somente no `.env`;
9. Recarregue o Apache após validar a configuração.

Se a hospedagem compartilhada não permitir alterar o DocumentRoot, solicite ao provedor que aponte o domínio para `/public`. Não mova o `.env` nem diretórios internos para dentro da pasta pública.

## Integração futura com banco

1. Crie uma implementação PDO de `ServiceRepositoryInterface`;
2. Centralize a conexão em um pequeno `ConnectionFactory` usando as variáveis `DB_*`;
3. Injete a nova implementação no bootstrap;
4. Mantenha consultas fora dos controllers e use statements preparados;
5. Adicione migrações versionadas e testes de integração.

Nenhuma conexão com banco é realizada na versão atual.

## Limpeza e produção

- Remova arquivos de `storage/cache/contact` para limpar somente os limites expirados;
- Rotacione `storage/logs/contact.log` no servidor;
- Execute `composer install --no-dev --optimize-autoloader`;
- Mantenha `display_errors=Off` e registre erros fora da área pública;
- Restrinja permissões de arquivo e nunca versione `.env`;
- Revise a política de privacidade com responsável jurídico antes da publicação;
- Configure o Microsoft Graph, restrinja o aplicativo à caixa remetente, faça um teste real de entrega e monitore SPF, DKIM e DMARC.
