
Antes de começar: conheça o projeto original no artigo phpVirtualBox: gerencie o VirtualBox pelo navegador.
Nesta série: Parte 1: phpVirtualBox, Echo e Vue · Parte 2: IA e OpenSpec · Parte 3: implementação e testes
Série phpVirtualBox em Go — parte 3 de 3. Depois de analisar o phpVirtualBox e organizar a migração com IA e OpenSpec, chegou a hora de definir como implementar e validar o novo painel. O objetivo não é lançar uma reescrita completa de uma vez: é construir uma sequência de entregas verificáveis.
Entrega 1: provar a distribuição, sem tocar em VMs
Comece com um serviço Echo, uma rota de saúde e uma página Vue que consulta essa rota. Compile o frontend e incorpore sua saída usando go:embed. Nessa etapa, o painel não precisa conhecer nenhuma máquina virtual: a pergunta é se a API e a interface funcionam no artefato distribuído.
O Echo possui um exemplo oficial de recursos incorporados, e a documentação do pacote embed descreve como os arquivos são incluídos na compilação. Os caminhos são relativos ao pacote; não planeje incorporar arquivos de diretórios superiores com ../. Gere os arquivos do Vue antes de compilar Go.
Código Vue → build do frontend → web/dist
↓
Código Go + Echo + go:embed → executável do painel
Critério de aceitação: copie apenas o executável para uma pasta vazia, inicie-o no loopback e confira a página, os arquivos JavaScript e a rota de saúde. Pare o servidor de desenvolvimento do frontend antes desse teste. Isso demonstra a distribuição do painel, mas ainda não demonstra integração com o VirtualBox.
Não incorpore arquivos de ambiente, credenciais ou bancos de dados. Esses itens precisam continuar externos ao binário. Se a interface usar rotas de aplicação, defina o tratamento de caminhos do frontend sem transformar erros de /api/ em uma página HTML com status de sucesso.
Entrega 2: segurança e contratos antes do host real
Antes de liberar o painel para outras pessoas, implemente autenticação, sessão, expiração e autorização. Autenticação identifica o usuário; autorização decide quais máquinas e ações ele pode acessar. Um usuário autenticado não deve ganhar acesso automático a todos os hosts.
A API deve distinguir entrada inválida, falta de autenticação, falta de permissão e falha do serviço externo. Não envie mensagens SOAP completas ou caminhos sensíveis para o navegador. Registre detalhes técnicos de maneira sanitizada no servidor e devolva erros que a interface consiga apresentar.
Para o laboratório inicial, configure o serviço no endereço de loopback e use credenciais de teste. O desenho de produção deve explicitar transporte protegido, configuração externa, gerenciamento de segredos e política de acesso.
Entrega 3: inventário real em modo somente leitura
Implemente um adaptador dedicado à integração. A camada HTTP não deve conhecer cada detalhe de SOAP: ela chama um serviço de inventário que retorna a representação de máquina definida na especificação. Isso permite testar regras sem um host real e, separadamente, testar o adaptador contra o VirtualBox.
Compare os resultados com um conjunto controlado de máquinas: uma desligada, uma em execução e, quando possível, estados adicionais que seu contrato se comprometa a suportar. Registre quais versões e cenários foram realmente verificados. Não use a expressão “compatível com todas as versões” para um teste feito em um único ambiente.
O teste somente leitura deve confirmar que a consulta não dispara comandos de alteração. Não basta a interface esconder botões: essa restrição precisa existir no backend. Limite também o número de consultas e defina timeout para não esgotar conexões quando um host estiver indisponível.
Uma matriz de testes para acompanhar as entregas
| Camada | O que verificar | Evidência esperada |
|---|---|---|
| Distribuição | API e Vue fora da árvore de código | Executável funcionando sem servidor Node |
| Contrato HTTP | Autenticação, campos e erros | Testes automatizados por cenário |
| Adaptador | Respostas, falhas e timeout SOAP | Fixtures sanitizadas e testes de integração |
| Interface | Carregamento, vazio e falha | Testes de navegação e inspeção visual |
| Operações | Estado inicial, resultado e recuperação | Execução em VMs descartáveis |
| Implantação | Reinício e retorno à versão anterior | Procedimento reproduzido no laboratório |
Mocks ajudam a repetir falhas difíceis de provocar, mas não provam compatibilidade com o serviço real. Testes de integração ajudam a validar a comunicação, mas não substituem testes de autorização. Cada camada responde a uma pergunta diferente.
Entrega 4: operações com segurança
Com a leitura validada, eu criaria mudanças separadas para iniciar máquinas, solicitar desligamento, acompanhar operações e, por último, administrar recursos mais delicados. Solicitar desligamento pelo sistema convidado não é a mesma ação que cortar a energia da VM; a interface e as permissões devem distinguir essas operações.
Operações longas merecem um modelo explícito de tarefas: identificador, estado, início, resultado e erro. Após um timeout, o backend precisa consultar o estado real antes de tentar novamente. Repetir automaticamente uma ação pode duplicar trabalho ou produzir um efeito inesperado.
- Iniciar e desligar: validar estado atual, permissões e acompanhamento.
- Snapshots: tratar criação, remoção e restauração como ações distintas.
- Discos: diferenciar remover um vínculo de apagar o arquivo físico.
- Múltiplos hosts: limitar falhas e permissões por destino.
- Auditoria: registrar ator, alvo e resultado, sem registrar credenciais.
Antes de liberar escrita, acrescente proteção contra CSRF quando houver autenticação por cookies, autorização por objeto e confirmação clara para operações destrutivas. O laboratório deve usar VMs descartáveis. Snapshot não substitui uma estratégia de backup e restauração testada.
Timeout de escrita não significa operação cancelada
O navegador pode perder a conexão enquanto o hipervisor continua trabalhando. Por isso, o painel precisa distinguir falha confirmada de resultado desconhecido. Depois de um timeout, não ofereça um botão que simplesmente reenvia a mesma operação sem verificar o que aconteceu.

Proponho estados internos como accepted, running, succeeded, failed e unknown. Eles pertencem ao painel, não são uma enumeração copiada do VirtualBox. Registre alvo, ator, tipo de ação e identificador da operação antes de informar sua aceitação; após reiniciar, recupere os registros pendentes e consulte o estado real.
Uma chave de idempotência ajuda a reconhecer pedidos repetidos, desde que seja persistida e vinculada à mesma identidade, alvo e ação. Ela não cria execução “exatamente uma vez” entre banco e hipervisor. Se o processo cair entre o envio e o registro do resultado, a reconciliação continua necessária. Nem toda ação tem o mesmo mecanismo de acompanhamento: não assuma que toda chamada SOAP retorna um objeto de progresso.
Teste a falha entre as etapas
- Requisição recusada antes de tocar no host: nenhuma alteração.
- Resposta perdida depois da aceitação: operação marcada para investigação, sem repetição automática.
- Reinício do painel durante a execução: registro recuperável e resultado reconciliado.
- Usuário perde permissão: novas consultas e ações continuam sujeitas à autorização.
- Host inacessível: falha isolada, sem bloquear indefinidamente outros pedidos.
Critérios de liberação por entrega
| Entrega | Só avance quando |
|---|---|
| Executável | Vue e API funcionam em diretório vazio; rotas /api/ inexistentes não retornam o HTML da SPA. |
| Segurança | 401/403 são testados e impedem chamadas SOAP; erros não revelam dados internos. |
| Inventário | GET /api/v1/vms corresponde ao host configurado e não altera VMs. |
| Escrita | Autorização por objeto, acompanhamento e cenários de resultado desconhecido funcionam em VMs descartáveis. |
| Implantação | Backup, reinício e retorno controlado à versão anterior foram ensaiados. |
Nos builds, preserve os arquivos de lock do frontend e as dependências Go; registre os comandos e o ambiente que produziram o artefato. Para detalhar a distribuição, veja Vue e Go com embed e Docker.
Rollback do painel não é rollback das máquinas
Voltar ao executável anterior não desfaz um snapshot removido nem restaura um disco apagado. Antes da troca, suspenda novas escritas, acompanhe ou reconcilie operações em andamento e confirme a compatibilidade dos dados persistidos. Reative apenas um controlador de escrita. O painel antigo só deve voltar depois dessa verificação, não como tentativa cega de resolver um erro.
Licença e implantação: duas etapas que não podem ficar para o fim
O arquivo de licença do phpVirtualBox indica GNU GPL versão 3. Reescrever em outra linguagem não é motivo para ignorar a licença do código, dos recursos visuais ou das dependências utilizados. Registre a origem do material reaproveitado e avalie as obrigações aplicáveis antes de distribuir o novo projeto. Licença do projeto original.
Na implantação, mantenha a possibilidade de voltar ao painel anterior, mas não deixe dois controladores executando alterações concorrentes sobre a mesma máquina. Comece com consultas, compare os resultados e libere operações progressivamente. Se a necessidade for mudar de hipervisor, esse é outro trabalho: o guia do ova2xva discute conversão de máquinas para XCP-ng, não substituição da interface de gerenciamento do VirtualBox.
Conclusão da série: distribuir é simples; operar exige evidência
Como projeto de engenharia, a proposta faz sentido se resolver um problema concreto: distribuição mais simples, interface melhor, API clara e manutenção previsível. O phpVirtualBox oferece uma referência valiosa, mas o novo painel precisaria conquistar confiança com testes e compatibilidade, não apenas com uma linguagem diferente.
O primeiro marco deveria ser pequeno e demonstrável: um executável com Echo e Vue incorporado, autenticação e inventário real de VMs em modo somente leitura. IA e OpenSpec podem acelerar o caminho até ele — desde que as tarefas sejam verificáveis e ninguém confunda código gerado com integração validada.
Nesta série: Parte 1: phpVirtualBox, Echo e Vue · Parte 2: IA e OpenSpec · Parte 3: implementação e testes