feat(live): MVP de live streaming — ingest, chat, audiência e admin - #530
Draft
Clintonrocha98 wants to merge 32 commits into
Draft
feat(live): MVP de live streaming — ingest, chat, audiência e admin#530Clintonrocha98 wants to merge 32 commits into
Clintonrocha98 wants to merge 32 commits into
Conversation
O smoke test da Task 4 revelou 500 em GET /live: a diretiva @Vite emitia tags <link rel="modulepreload"> como irmãs anteriores ao <main>, e o parser HTML do libxml (usado pelo SupportMultipleRootElementDetection do Livewire em modo debug) tratava esses <link> como conteúdo de <head>, nunca criando um elemento <body> - resultando em "Attempt to read property childNodes on null". Os testes existentes não pegaram isso porque usam withoutVite(), que neutraliza a diretiva.
…yTime O hook de autenticação do mediamtx autorizava (fail-open) qualquer ação diferente de publish, incluindo ações desconhecidas. Troca para default-deny via match, autorizando explicitamente só read/playback/publish. CheckLiveStatusAction também lançava InvalidFormatException quando a Control API retornava um readyTime não-parseável, derrubando a página com a live no ar; agora o parse é protegido e cai para startedAt nulo.
… serve A porta 9997 do heartdevs-mediamtx era publicada em todas as interfaces; a Control API não passa pelo auth hook (authHTTPExclude) e tem endpoints de escrita, então deve ficar acessível só do host. Também documenta, no .env.example e na spec, que publicar via OBS exige `php artisan serve --host=0.0.0.0` — o bind padrão (127.0.0.1) não é alcançável pelo container via host.docker.internal.
…ve na página composer.json do módulo portal já exigia he4rt/live, mas o composer.lock ainda não refletia essa dependência. Aproveita para anunciar a troca offline/ao vivo a leitores de tela via aria-live="polite" no container que recebe o wire:poll.
Adiciona o bloco YAML de front matter (type, title, module, status, date, author) exigido pela convenção de documentação do repo.
…eração ganha MessageDeleted
…iliente na página de live
… redis Envolve o event() de LiveStarted/LiveEnded/ChatMessageSent/ChatMessageDeleted e o corpo de LivePage::pulse() em rescue(report: true), evitando que uma falha no broadcaster (Reverb fora do ar) ou no presence de viewers (Redis fora do ar) derrube uma operação de domínio já persistida.
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contexto
MVP de transmissões ao vivo próprias da heartdevs (sem depender de Twitch/YouTube). O mediamtx (RTMP→HLS) já roda como serviço de infra; faltava a camada de domínio que decide quem pode publicar, o que está no ar e quem participa — e a UI, tanto pública (
/live) quanto de gestão (painel admin).Decisões de produto e design estão registradas em
docs/specs/2026-08-29-live-mvp-design.md,docs/specs/2026-08-29-live-fase-2-chat-admin-robustez.mde no glossário do módulo (app-modules/live/CONTEXT.md).Alterações
Módulo
live(domínio, novo)Created→OnAir→Ended), stream key rotacionável, invariante "uma live corrente" via Action + índice único parcial.IngestAuthController,IngestWebhookController), default-deny, rate limit por IP.IdentityProvider::He4rtLives): mensagens entram no pipeline doactivity, reusando moderação e agregados em vez de um model próprio.LiveStarted,LiveEnded,ChatMessageSent,ChatMessageDeleted) via Reverb, sempre best-effort (rescue()) — Reverb fora do ar nunca derruba uma operação já persistida.SimulateLiveChatCommand+FakeChatAuthors: ferramenta de dev para gerar tráfego de chat fake numa live, útil para testar a UI sem depender de usuários reais.Módulo
panel-adminLiveResourcecom listagem, visualização, gráfico de audiência, moderação de mensagens no chat e ações de ciclo de vida (encerrar, rotacionar stream key).simulateChat(visível só emapp()->isLocal()) para ligar/desligar a simulação de comentários direto do painel.Módulo
portal/live: player HLS resiliente, polling de status a cada 10s, contador de espectadores.Módulo
identityHe4rtLivespara o enumIdentityProvider, permitindo que o chat da live seja tratado como "mais um provedor de atividade" (igual Discord/Twitch).Infra
mediamtxnodocker-compose.yml(RTMP→HLS), config de auth/webhook hooks.config/reverb.php) e dependências de broadcast noportal.Plano de Testes
./vendor/bin/rector process --dry-run --ansi./vendor/bin/pint --test --ansi./vendor/bin/phpstan analyse --ansinice -n 19 ./vendor/bin/pest --parallel --processes=10 --compact— 1722 testes, 5900 assertions, todos passandoIssues Relacionadas
Nenhuma issue vinculada.