Este documento unifica e consolida o plano de desenvolvimento de backend para a Integração com GLPI e a fundação do Framework de Ações e Eventos Externos (compatível e reutilizável para outras integrações).
O sistema é dividido em dois fluxos complementares:
ON_REQUEST_CONFIRMED).As seguintes tabelas serão adicionadas/atualizadas no arquivo schema.prisma:
// 1. Ações Externas e Histórico (Outbound)
model agent_template_tool_actions {
id String @id @default(dbgenerated("uuidv7()")) @db.Uuid
agent_template_id String @db.Uuid
integration_action_id String @db.Uuid
trigger String // ex: ON_REQUEST_CONFIRMED
input_mapping Json // Mapeia chaves do schema da action para caminhos (ex: artifact.name)
output_mapping Json?
status_mapping Json?
required Boolean @default(true)
sort_order Int @default(0)
created_at DateTime @default(now()) @db.Timestamptz(6)
updated_at DateTime @default(now()) @db.Timestamptz(6)
integration_actions integration_actions @relation(fields: [integration_action_id], references: [id], onDelete: Cascade)
integration_executions integration_executions[]
}
model request_external_references {
id String @id @default(dbgenerated("uuidv7()")) @db.Uuid
request_id String @db.Uuid
integration_tool_id String @db.Uuid
external_id String // ex: ID do ticket no GLPI
resource_state String? // ex: open, solved, closed
sync_enabled Boolean @default(true)
last_synced_at DateTime? @db.Timestamptz(6)
metadata Json? @default("{}") // Armazena dados extras retornados pela API externa
created_at DateTime @default(now()) @db.Timestamptz(6)
requests requests @relation(fields: [request_id], references: [id], onDelete: Cascade)
integration_tools integration_tools @relation(fields: [integration_tool_id], references: [id])
integration_executions integration_executions[]
}
model integration_executions {
id String @id @default(dbgenerated("uuidv7()")) @db.Uuid
request_id String @db.Uuid
agent_template_tool_action_id String @db.Uuid
request_external_reference_id String? @db.Uuid
status String // PENDING, RUNNING, SUCCESS, FAILED
started_at DateTime @default(now()) @db.Timestamptz(6)
finished_at DateTime? @db.Timestamptz(6)
duration_ms Int?
input_payload Json?
output_payload Json?
error Json?
metadata Json? @default("{}")
created_at DateTime @default(now()) @db.Timestamptz(6)
requests requests @relation(fields: [request_id], references: [id], onDelete: Cascade)
agent_template_tool_actions agent_template_tool_actions @relation(fields: [agent_template_tool_action_id], references: [id], onDelete: Cascade)
request_external_references request_external_references? @relation(fields: [request_external_reference_id], references: [id], onDelete: SetNull)
}
// 2. Eventos Recebidos / Ingress (Webhooks / Inbound)
model integration_events {
id String @id @default(dbgenerated("uuidv7()")) @db.Uuid
integration_tool_id String @db.Uuid
event_key String // ex: ticket_updated, message_received
description String? @default("")
payload_schema Json? @default("{}") // Validação do payload recebido do webhook
created_at DateTime @default(now()) @db.Timestamptz(6)
integration_tools integration_tools @relation(fields: [integration_tool_id], references: [id], onDelete: Cascade)
agent_template_tool_events agent_template_tool_events[]
integration_event_logs integration_event_logs[]
@@unique([integration_tool_id, event_key], map: "uq_integration_events_tool_event")
}
model agent_template_tool_events {
id String @id @default(dbgenerated("uuidv7()")) @db.Uuid
agent_template_id String @db.Uuid
integration_event_id String @db.Uuid
handler_key String // Nome da classe/função que processa (ex: update_request_status)
config Json // Configurações específicas do processamento (mapeamento de campos)
enabled Boolean @default(true)
created_at DateTime @default(now()) @db.Timestamptz(6)
integration_events integration_events @relation(fields: [integration_event_id], references: [id], onDelete: Cascade)
}
model integration_event_logs {
id String @id @default(dbgenerated("uuidv7()")) @db.Uuid
tenant_id String? @db.Uuid // Pode ser resolvido a partir do webhook (subdomínio ou payload)
integration_tool_id String @db.Uuid
integration_event_id String? @db.Uuid // Opcional, caso não consiga mapear o evento
event_key String // Salva a key crua recebida
raw_payload Json // Payload integral recebido do webhook
status String // PENDING, PROCESSED, FAILED, IGNORED
error_log Json? @default("{}")
created_at DateTime @default(now()) @db.Timestamptz(6)
integration_tools integration_tools @relation(fields: [integration_tool_id], references: [id])
integration_events integration_events? @relation(fields: [integration_event_id], references: [id], onDelete: SetNull)
}
Abaixo estão listadas as especificações detalhadas de cada subtask necessárias para a execução completa do plano.
agent_template_tool_actions, request_external_references, integration_executions, integration_events, agent_template_tool_events e integration_event_logs ao arquivo schema.prisma.uuidv7() e definir relacionamentos de exclusão em cascata (onDelete: Cascade) adequados.pnpm prisma migrate dev).input_schema e output_schema em formato JSON Schema (Draft-07) na tabela integration_actions (via seed).InputMappingResolver responsável por parsear caminhos definidos no mapeamento.artifact (especificações geradas pelo agente).outputs (valores derivados do processamento interno).request (metadados estruturados da solicitação).create_ticket: Exige título (name), descrição (content) e retorna o id do ticket.add_ticket_followup: Exige ID do ticket e texto do acompanhamento.get_ticket_status: Exige ID do ticket e retorna o status atualizado do recurso.InputMappingResolver processa mapeamentos válidos compostos exclusivamente das três fontes permitidas.ToolExecutor), o mecanismo de Factory e o adaptador do GLPI isolado de regras de negócio, assegurando amarração rígida entre banco e código.ToolExecutor e implementar a ToolExecutorFactory para instanciar dinamicamente adaptadores de acordo com a ferramenta catalogada.ToolExecutor deve realizar verificação em tempo de execução (ou inicialização do NestJS) para assegurar que a action_type_key carregada do banco possui um método tratador implementado no código do adaptador. Caso falte, deve lançar erro UnimplementedIntegrationActionException.GlpiToolAdapter implementando o ciclo de vida da sessão da API REST do GLPI:SECRET_MANAGER_CLIENT a partir do secret_path./initSession enviando os cabeçalhos App-Token e Authorization para obter o session_token.POST /Ticket/ para create_ticket).GET /killSession em um bloco finally.SCHEMA_VALIDATOR usando os schemas configurados no banco de dados tanto para os dados enviados quanto para as respostas recebidas.requests (ON_REQUEST_CONFIRMED) para atuar como interceptor bloqueante:integration_executions com status PENDING.InputMappingResolver.RUNNING.ToolExecutor.execute().request_external_references.SUCCESS em integration_executions junto com o payload de resposta e duração.integration_executions com o status FAILED.required: true), abortar a confirmação da Request lançando exceção para o usuário e revertendo as alterações locais no banco de dados.integration_executions é persistido com sucesso para auditoria tanto nas transações que falham quanto nas que têm êxito.POST /integrations/test-action exposto no IntegrationsController.agentTemplateToolActionId e um objeto mockContext (com dados simulados de request, artifact e outputs).ToolExecutor.success: true/false.success: false.@nestjs/schedule rodando de forma parametrizável (ex: a cada 15 minutos).request_external_references com sync_enabled = true.integration_executions.resource_state traduzindo o retorno para valores mapeados (ex: solved, closed).sync_enabled = false para encerrar futuras buscas.join com request_external_references, trazendo a relação com tenant_integrations e integration_tools.externalReferences do tipo array no DTO RequestDashBoardItemDto.integrationName (nome configurado da conexão).toolName (ex: "GLPI").externalId (ID do recurso na ferramenta de origem).state (status sincronizado do recurso).lastSyncedAt (timestamp da última atualização).metadata (dados extras como link direto, nome do técnico).GET /requests e GET /requests/:requestId expõem de maneira estruturada a lista de referências externas em seu DTO.POST /integrations/webhooks/:toolName desprovida da autenticação de sessão do usuário local.integration_event_logs com status PENDING.integration_events.agent_template_tool_events.handler_key mapeado no banco sem a classe de implementação equivalente herdando de IIntegrationEventHandler no código do backend.integration_event_logs.glpi.ticket_updated).GlpiTicketUpdatedHandler implementando a interface IIntegrationEventHandler e vinculando-a com a chave glpi_ticket_updated_handler.payload.item.id e o status correspondente.request_external_references.resource_state.sync_enabled para false.