Files
Investidor-V2/docs/investmoz/suitecrm/architecture.md
T
nala e65cb26901
tests / ci (push) Canceled after 0s
varias alteracoes
2026-10-06 14:50:12 +02:00

13 KiB
Raw Blame History

SuiteCRM — decisão de arquitectura e plano de transição

Data: 25/09/2026. O utilizador delegou a escolha da solução e confirmou que não existe SuiteCRM nem cliente OAuth. Esta decisão define o destino da arquitectura; não significa que a integração esteja instalada ou aprovada para produção.

1. Diagnóstico

Portal confirmado: Laravel 13.30.1, React 19.2.8, Inertia React 3.7.0, Inertia Laravel 3.3.3, Fortify 1.39.0, PostgreSQL 17.11/PostGIS 3.6.2. PHP de trabalho 8.5.11; o PATH ainda resolve outro PHP 8.5.0. Filas/cache/sessões usam database. Gestão autorizada por email verificado e lista de gestores; não existe RBAC organizacional completo.

Há CRM local (CrmController, ConvertInterestToLead), catálogo público, projectos e clusters. O InterestRequestController aceita Idempotency-Key opcional UUID; InterestSubmission guarda apenas o hash da chave, compara o hash canónico do pedido e, na mesma transacção, regista recibo, consentimentos e evento na outbox. Replay com payload igual devolve a manifestação original; reutilização com dados diferentes responde 409. InterestSubmissionTest cobre replay, conflito, rollback transaccional e submissão antiga sem chave. A conversão em lead também é idempotente por pedido. Outbox/inbox/reconciliação continuam sem processadores. O agregado da outbox exige UUID, enquanto pedidos usam bigint. A referência IR não é credencial de acesso.

O cliente existe em app/Integrations/SuiteCrm/ e está desligado por defeito (SUITECRM_ENABLED=false); os testes usam HTTP simulado. Não há instalação SuiteCRM, credenciais, tráfego real nem implantação Docker do portal. A integração e os processadores de outbox/inbox continuam pendentes.

2. Decisões e pendências

Escolha para homologação: SuiteCRM 8.10.2, PHP 8.4, Apache 2.4, MariaDB 11.4, isolados em Linux/Docker. A release foi confirmada no repositório oficial e a combinação na matriz oficial. O PHP 8.5 do portal não será usado para executar o CRM. O pacote pré-compilado dispensa ferramentas de compilação Angular na imagem do CRM.

SuiteCRM será o único sistema de escrita comercial após a transição. As páginas comerciais do portal passarão a consulta ou comandos enviados ao Laravel e executados via API do CRM. Não haverá escrita dupla nem sincronização bidireccional irrestrita. Antes da transição, o CRM local permanece operacional; não activar envios externos neste estado.

Pendentes externos: motor Docker num ambiente Linux de testes; domínio/TLS da homologação; regras de atribuição e SLA; perfis institucionais; finalidade, retenção, transferências e eliminação validadas pelas áreas jurídica e institucional. Nenhum prazo legal é presumido.

3. Arquitectura proposta

Laravel é o único intermediário entre React e SuiteCRM. Credenciais ficam no backend. Os sistemas não partilham utilizadores de base de dados. Laravel não recebe credenciais MariaDB. A conta técnica OAuth será não administrativa e terá acesso apenas aos módulos necessários. OAuth máquina-a-máquina não é SSO dos utilizadores; manter Fortify nesta fase.

Reutilizar a outbox transaccional: gravação do pedido, UUID de integração e evento na mesma transacção. O worker resolve o payload mínimo autorizado e chama a API oficial. A resposta ao investidor confirma recepção, nunca sincronização ainda pendente. Webhooks assinados entram pela inbox; não se assume que SuiteCRM emita nativamente o contrato de assinatura proposto. Será necessária uma extensão suportada e testada.

4. Componentes

flowchart LR
  React[React] --> BFF[Laravel BFF]
  BFF --> PG[PostgreSQL e PostGIS]
  PG --> Outbox[Outbox transaccional]
  Outbox --> Worker[Worker de integração]
  Worker --> Client[SuiteCrmClient]
  Client --> API[API oficial SuiteCRM OAuth2]
  API --> CRM[SuiteCRM]
  CRM --> MariaDB[MariaDB exclusiva do CRM]
  CRM --> Hook[Extensão de eventos assinados]
  Hook --> Inbox[Laravel inbox]
  Inbox --> Projection[Projecção autorizada e reconciliação]
  Projection --> PG

5. Sequência prevista

sequenceDiagram
  actor Investidor
  participant Portal as React e Laravel
  participant DB as PostgreSQL
  participant Worker
  participant CRM as API SuiteCRM
  Investidor->>Portal: Submeter com chave idempotente
  Portal->>Portal: Validar identidade, autorização e finalidade
  Portal->>DB: Transacção pedido + identidade UUID + outbox
  DB-->>Portal: Commit
  Portal-->>Investidor: Referência e estado recebido
  Worker->>DB: Reclamar evento com lease
  Worker->>CRM: Consultar identidade externa e candidatos
  alt Identidade ambígua
    Worker->>DB: Aguardar revisão humana
  else Identidade resolvida
    Worker->>CRM: Criar ou actualizar contacto e organização
    Worker->>CRM: Criar lead, relações e tarefa com responsável
    Worker->>DB: Confirmar vínculos e resultado
  end

6. Responsabilidades dos sistemas

Domínio Sistema principal após transição Regra
Login, sessões, acesso do investidor Portal Não copiar credenciais para CRM
Organizações, representantes, contactos SuiteCRM Portal propõe alterações; CRM valida; cache mínimo
Perfil de investimento Portal Ligação ao contacto/organização por UUID estável
Leads, negociação, qualificação, responsáveis SuiteCRM Projecção no portal; revisão humana
Campanhas, reuniões, tarefas, casos e aftercare comercial SuiteCRM Estado autorizado devolvido ao portal
Manifestação submetida e comprovativo Portal Conteúdo original preservado; espelho comercial mínimo
Projectos, clusters, corredores e oportunidades publicadas Portal Réplicas de referência no CRM; sem editar cadastro lá
Oportunidade comercial de negociação SuiteCRM Não confundir com oportunidade publicada no portal
Geometrias e análise GIS Portal Não replicar geometrias completas para CRM
Consentimento recolhido no portal Portal Revogação restringe tratamento; não reactivar via CRM
Documentos submetidos Armazenamento privado do portal CRM recebe metadados e acesso controlado quando necessário
Estado técnico de entrega, conflitos e auditoria Portal Nunca tokens, passwords ou payload pessoal nos logs

7–9. Módulos, campos e mapeamentos — direcção definida

Usar Accounts para organizações, Contacts para pessoas e relações para representação. Não criar um módulo Investors que duplique esses cadastros; um perfil de investimento distinto pode referenciá-los. Usar Leads, Opportunities, Campaigns, Meetings, Tasks, Cases e Documents quando a semântica coincidir.

Avaliar módulos personalizados para manifestações, referências de projectos/clusters/corredores e jornadas. Procedimentos regulatórios permanecem no portal; um resumo no CRM só será criado com necessidade demonstrada. Aftercare usa Cases com classificação própria, salvo exigências de permissões/ciclo incompatíveis. O catálogo lógico e a matriz de mapeamento com 15 colunas foram acrescentados em mapping-catalog.md. Nomes técnicos de atributos, links e módulos personalizados permanecem candidatos até validação na instância de homologação.

Campos comuns previstos: UUID externo imutável, sistema de origem, versão, classificação, instante de recolha e código de finalidade. Nomes técnicos, relacionamentos e disponibilidade na API devem ser comprovados na instalação. Índice único de identidade externa deve ser definido por extensão suportada. Email partilhado ou telefone coincidente são candidatos a revisão, não autorização para fusão automática.

10. Endpoints — contrato a desenvolver

Preservar /api/v1/interest-requests durante a migração. O novo contrato de manifestações deverá partilhar o mesmo serviço e registo idempotente; não criar dois fluxos de escrita independentes. Dashboard, consulta, documentos e reuniões exigem utilizador autenticado e propriedade do pedido. Nunca autorizar consulta apenas pela referência IR.

Reconcile e health detalhado serão restritos à operação autorizada. Webhook exige assinatura do corpo bruto, timestamp, identificador único e protecção contra replay. Não implementar upload de binários supondo suporte genérico da API: validar Documents/DocumentRevisions e o mecanismo oficial da versão instalada.

11. Eventos e filas

Entrega pelo menos uma vez, com idempotência persistente; não prometer exactly-once distribuído. Evento leva identificadores, versão, correlação e finalidade, evitando cópias de dados pessoais. Reutilizar inbox/outbox e acrescentar leases, tentativas e estado de entrega onde necessário, respeitando os triggers de envelope imutável.

Retries limitados, backoff exponencial com jitter e respeito por Retry-After. Respostas 401 permitem uma reautenticação; 403/422 exigem intervenção, não repetição cega. Após timeout de criação, pesquisar pelo UUID externo antes de repetir. Conflitos, duplicados ambíguos e falhas definitivas ficam em revisão, com reprocessamento autorizado e auditado. Reconciliação compara identificador, versão e campos permitidos, sem substituir automaticamente o sistema principal.

Eventos previstos incluem ExpressionOfInterestSubmitted, InvestorRegistered, OrganizationCreated, LeadCreated, LeadQualified, OpportunityCreated, OpportunityStageChanged, MeetingScheduled, FollowUpOverdue, ProjectLinked, ClusterLinked, CorridorLinked e PostInvestmentCaseOpened. Ainda não publicados pela aplicação.

12. Estrutura futura e etapas verificáveis

O cliente em app/Integrations/SuiteCrm/ e os testes em tests/Feature/SuiteCrm/ já existem e estão descritos em client.md. O catálogo lógico está em mapping-catalog.md; jobs, eventos, listeners, mapeamento técnico confirmado na instalação e contratos completos dos domínios continuam por implementar.

  1. Decisão e preparação da instalação isolada (esta entrega).
  2. Instalação, conta técnica, OAuth, descoberta dos módulos e prova de contrato de API.
  3. Catálogo detalhado, campos, mapeamento e endpoints; testes de contrato primeiro.
  4. Cliente HTTP, autenticação segura, circuit breaker e testes com respostas simuladas.
  5. Outbox/idempotência e jornada completa numa base de homologação.
  6. Reconciliação, webhooks, documentos, painéis e restantes domínios.
  7. Migração, reconciliação integral, congelamento da escrita comercial local e Go/No-Go.

Migração e rollback

Criar backup e inventário; ensaiar importação pela API numa instalação limpa. Associar cada registo local a um UUID externo antes de migrar relações. Não fundir pessoas automaticamente. Comparar contagens, vínculos, responsáveis e consentimentos; resolver divergências.

Durante o corte, congelar escrita comercial local, escoar a outbox, reconciliar e só depois activar o CRM como principal. Não eliminar tabelas antigas. Desactivar a integração pára novos envios, mas não desfaz alterações já feitas no CRM. Um rollback após escrita no SuiteCRM exige exportação/reconciliação dessas alterações antes de reabrir o CRM local; restaurar simplesmente um backup perderia trabalho.

Go/No-Go e estado da entrega

NO-GO para produção. Faltam instalação real, OAuth técnico, ligação do cliente aos fluxos, módulos, contratos completos, testes ponta a ponta, validação de segurança/privacidade/Produto e ensaio de recuperação. Os testes do cliente com HTTP simulado não comprovam uma integração real.

Esta alteração acrescenta documentação e um modelo Docker de homologação. Não altera rotas, migrations, dados ou comportamento do portal. Para desfazer esta preparação basta deixar de usar o directório de implantação; não há migração de dados a reverter.

Fontes oficiais