7.8 KiB
SuiteCrmClient — contrato implementado
Estado: cliente Laravel implementado e testado com HTTP simulado. Não há SuiteCRM instalado, credenciais criadas, tráfego real ou integração com as manifestações. Não activar apenas por estes testes passarem.
Ficheiros desta entrega
| Ficheiro | Finalidade |
|---|---|
app/Integrations/SuiteCrm/SuiteCrmClient.php |
Cliente OAuth2/JSON:API |
app/Integrations/SuiteCrm/SuiteCrmException.php |
Erro sanitizado e metadados de recuperação |
config/suitecrm.php |
Desactivação por defeito, URLs, módulos e limites |
.env.example |
Variáveis backend sem credenciais reais |
tests/Feature/SuiteCrm/SuiteCrmClientTest.php |
Testes de contrato local, recuperação e segurança |
Sem novas dependências Composer, rotas, migrations ou chamadas desde o frontend. A configuração usa o cache database existente; os testes usam array e não precisam de uma base de dados. Em implantação com vários workers, todos devem partilhar o cache e os locks.
Contrato HTTP
A base configurada é a URL HTTPS da aplicação legacy que contém Api; o prefixo real será confirmado na instalação. Todos os caminhos abaixo são relativos a essa base.
| Método Laravel | HTTP | Caminho | Contrato |
|---|---|---|---|
| Autenticação interna | POST | /Api/access_token |
grant_type=client_credentials, client ID/secret; resposta Bearer com validade |
find |
GET | /Api/V8/module/{module}/{id} |
Registo autorizado |
search |
GET | /Api/V8/module/{module} |
Filtros exactos combinados por AND; página >=1; tamanho 1–100 |
create |
POST | /Api/V8/module |
Envelope data.type e data.attributes |
update |
PATCH | /Api/V8/module |
Envelope com tipo, ID e atributos |
relate |
POST | /Api/V8/module/{module}/{id}/relationships/{linkField} |
Tipo e ID do registo relacionado |
fields |
GET | /Api/V8/meta/fields/{module} |
Metadados para validar o mapeamento |
O cliente devolve o documento JSON, preservando paginação. Não segue links de paginação devolvidos pelo servidor; o consumidor pede explicitamente a página seguinte. Módulos são limitados à allowlist de configuração; nomes e IDs não aceitam separadores de caminho. Métodos não são endpoints públicos e não substituem autorização de negócio, validação dos atributos ou permissões da conta técnica.
Os formatos foram confrontados com public/legacy/Api/V8/Config/routes.php no pacote oficial SuiteCRM 8.10.2 de SHA-256 ac4693d10ea2d6cd20b3256098781d134599d88878fb24e8dc127038d624f5a8. Os testes são contratos do consumidor com respostas simuladas; ainda falta provar compatibilidade contra o servidor.
Tokens e segredos
HTTPS e validação do certificado são obrigatórios; redirects são recusados. A URL não pode conter credenciais, query ou fragmento. Tokens são cifrados com a chave Laravel antes de entrar no cache e expiram antecipadamente. Obtenção e invalidação usam locks. Se outra chamada já renovou o token, um 401 atrasado não deve apagar o token novo.
Client credentials obtém novo token na expiração; não presume refresh token. Um 401 da API permite uma renovação e repetição. O segundo 401 termina a operação. Alterar o segredo muda o namespace do cache; reiniciar workers/reconstruir o cache de configuração durante rotação. Revogar o cliente antigo no CRM; a mudança local não o revoga remotamente.
O segredo deve ser injectado no ambiente do backend por mecanismo privado. Não usar variáveis VITE_. O .env actual não foi alterado. Não imprimir configuração, payloads ou respostas de autenticação no diagnóstico.
Retries, circuit breaker e ambiguidade
- Consultas: até duas repetições para falhas de rede, 429 e 5xx, com backoff exponencial e jitter.
- Retry-After numérico/data é respeitado. Atrasos superiores a cinco segundos são devolvidos ao futuro job, sem bloquear o processo; valor limitado a um dia.
- Criação, actualização e relação: não repetir automaticamente após timeout ou 5xx.
outcomeUnknown=trueexige consultar a identidade externa/reconciliar antes de reenviar. - 403, 404, 409 e 422 são erros permanentes neste nível; a lógica de negócio decide a recuperação.
- Cinco operações com falha transitória abrem o circuito durante 60 segundos. O contador usa lock. Após o intervalo, operações voltam a ser permitidas; ainda não há controlo de uma única sonda half-open.
- Sucesso com JSON inválido é rejeitado; numa escrita, é considerado ambíguo.
retryable indica natureza transitória, não autorização para repetir uma escrita. O futuro processador da outbox deve respeitar também outcomeUnknown e retryAfter. O cliente isolado não implementa idempotência distribuída nem fusão de contactos.
Observabilidade
Cada tentativa produz suitecrm.http com operação, código HTTP e duração em milissegundos. Não inclui URL, IDs, corpos, atributos ou cabeçalhos. Excepções usam razões enumeradas e não encadeiam a excepção HTTP original. Há atributos SensitiveParameter nos argumentos com dados pessoais/segredos.
Esses eventos permitem agregar taxa de falhas/latência; ainda não há exporter, dashboard ou alertas instalados. Instrumentação externa que capture HTTP (debuggers/APM) deve ser configurada para excluir tokens e payloads antes de activar a integração.
Verificação e limites
15 testes, 62 asserções, sem rede real: desactivação, HTTPS, tokens cifrados, reutilização, expiração, rotação, 401 limitado, formato JSON:API, retry de leitura, escrita ambígua, Retry-After, circuito, módulos/IDs/paginação, sanitização e resposta inválida. PHPStan passou sem erros.
A suite completa também passou: 85 testes e 612 asserções. Pint, formatação e lint passaram. Não foi necessário alterar ou testar o frontend visual, pois esta entrega não o modifica.
Ainda faltam: testes reais e concorrência entre processos; configuração OAuth; RBAC no CRM; documentos binários; outbox/inbox e jobs; reconciliação; métricas/alertas; relação com consentimento e domínios do portal. Metadados de Documents podem ser enviados por create após validação do esquema; não existe upload binário genérico implementado.
Rollback
Manter SUITECRM_ENABLED=false. Como nenhum fluxo do portal chama o cliente, esta entrega não altera dados comerciais. Ao remover os ficheiros, retirar também a configuração e variáveis de exemplo. Se o cliente tiver sido activado numa instalação futura, desactivar envios e revogar o OAuth; não considerar isso reversão de registos já escritos no CRM.