Comando: cat projects/media-catalog.md
Arquivo de Mídia: catálogo e lista pessoal de filmes, séries e animes
Protótipo pessoal feito em uma noite: um catálogo que busca filmes, séries e animes em quatro fontes públicas de metadados ao mesmo tempo, mostra a ficha, os trailers oficiais e onde assistir de forma legal, e guarda a lista de cada pessoa com login por link mágico. Não armazena nem transmite vídeo, e nunca foi publicado.
abrir demonstraçãosimulação do sistema com dados fictícios · 5 telas
- Papel
- Projeto pessoal, do conceito ao código
- Período
- set/2026 – set/2026
- O que eu fiz
Eu: Conceito, arquitetura, os conectores das quatro fontes, cache e limite de requisições, modelo de dados e regras de acesso, interface, testes e as decisões registradas.
Projeto privado, descrito sem identificar cliente, produto ou empresa.
Diagrama
No navegador ficam a paleta e a busca, sem nenhuma chave de API. A API própria valida o termo, aplica limite por IP, usa cache LRU com TTL e deduplica chamadas em voo; ela consulta em paralelo as fontes públicas de metadados, com uma reserva para animes, e normaliza tudo num contrato validado. A lista pessoal fica no Supabase: login por link mágico e Postgres com políticas por linha, em que só o dono lê e altera a lista, e o app nunca usa a chave de serviço. Onde assistir aponta só para serviços licenciados, o trailer vem só pelo player oficial, e nenhum vídeo é armazenado nem transmitido.
Contexto
Um catálogo pessoal de filmes, séries e animes, com estética de terminal. É um protótipo feito em uma noite, na minha máquina: nunca foi publicado e não tem usuários, então não há resultado de uso para mostrar.
O que eu construí
- Busca federada. Uma paleta de comandos (Ctrl/Cmd+K ou “/”) e uma página de busca que consultam as quatro fontes ao mesmo tempo e mesclam os resultados; a requisição anterior é cancelada a cada nova tecla.
- Ficha do título. Nota com leitura em texto, sinopse, trailers que só carregam no clique, onde assistir de forma legal (assinatura, aluguel, compra, grátis com anúncios), elenco, ficha técnica e a atribuição de cada fonte.
- Minha lista. Quero ver, assistindo, já vi e abandonei, com mudança de status otimista e anunciada para leitor de tela.
- Falhar com elegância. Cada seção do início carrega e falha sozinha; quando falta configurar uma fonte, a interface diz o que falta, e o resto segue funcionando.
- Processo. Seis ADRs, cinco gates escritos e a documentação do projeto gerada a partir do próprio código por um script determinístico.
Limites
Protótipo sem deploy, sem usuários e sem CI remoto. Os números de teste e de cobertura vêm dos relatórios gerados pelo próprio projeto e não foram reexecutados.
Restrições
- Custo recorrente zero e nenhuma credencial no navegador.
- Só metadados, de fontes com uso permitido; nenhum vídeo armazenado ou transmitido.
- Cada fonte externa pode falhar sozinha, sem derrubar a página.
- Uma noite de trabalho.
Decisões
Só metadados, com as fontes recusadas por escrito
- Contexto
- Um catálogo de filmes e séries atrai atalhos: APIs de pirataria, mirrors anônimos e wrappers sem manutenção.
- Escolha
- Quatro fontes públicas de metadados, trailers só pelo player oficial, onde assistir só com serviços licenciados, e um documento que recusa as outras fontes com motivo legal, de custo, de confiabilidade e de segurança.
- Ganhos
- Nenhum risco jurídico de conteúdo, e custo zero.
- Custos
- O catálogo depende das cotas e da disponibilidade de fontes gratuitas.
Busca federada com cache e limite no servidor
- Contexto
- Consultar quatro fontes a cada tecla seria lento, gastaria a cota e ficaria frágil quando uma delas caísse.
- Escolha
- Uma API própria valida o termo, consulta as fontes em paralelo, com uma fonte reserva para animes, e normaliza tudo num contrato validado; cache LRU com TTL, deduplicação de chamadas em voo e limite por IP.
- Ganhos
- Uma fonte instável não derruba a busca.
- Nenhuma chave de API chega ao navegador.
- Custos
- O limite vale por instância; com várias instâncias o teto real se multiplica, e essa limitação está assumida numa ADR.
Autorização no banco, sem chave de serviço no app
- Contexto
- A lista pessoal é o único dado de usuário, e ninguém pode ler a lista de outra pessoa.
- Escolha
- Login por link mágico e políticas por linha no Postgres, em que só o dono lê, cria, altera e remove; o app nunca usa a chave de serviço.
- Ganhos
- Um bug na aplicação não expõe a lista de outra pessoa.
- Custos
- Depende de um banco gerenciado gratuito, que pausa por inatividade; daí um health check.
Stack e por quê
- Next.js 15 e React 19
- App Router, com o início revalidado a cada hora e a ficha a cada 12 horas.
- TypeScript estrito e Zod
- Contrato de domínio validado em toda fronteira externa.
- Tailwind v4
- Tokens de tema com contraste medido.
- Supabase (Postgres e Auth)
- Link mágico e políticas por linha.
- Vitest
- Conectores, cache, limite de requisições e validação.
Resultados
90 casos de teste em 10 arquivos, com cobertura de 61,95% das linhas e 82,57% dos branches.
declaradoRelatório de cobertura gerado pelo projetoSeis ADRs e cinco gates escritos: requisitos, experiência, segurança, performance e custo, e testes.
repositório privado auditadoDocumentação do repositório(Auditoria do repositório privado, set/2026)
Ângulo de segurança
Superfície de ataque
- A busca pública, que chama as fontes externas pelo servidor.
- Links externos que vêm das fontes (sites oficiais e serviços).
- A lista pessoal de cada usuário.
- O login por link mágico.
Controles implementados
- Usuário sempre tirado da sessão validada no servidor.
- URL externa sanitizada, com defesa contra ataque de sufixo de domínio, e proteção contra open redirect.
- Lint que proíbe HTML cru, CSP restritiva com mídia bloqueada e HSTS.
- Termo de busca validado (mínimo de 2 caracteres, teto de página, caracteres de controle removidos) e limite por IP com resposta 429.
- Erro ao cliente sem stack.
O que eu testaria hoje
- Estourar o limite de requisições espalhando chamadas por várias instâncias.
- Uma resposta de fonte com URL de serviço forjada.
- Ler ou alterar a lista de outra pessoa trocando identificadores.
Evidências
- repositório privado auditadoRepositório local auditado(Auditoria do repositório privado, set/2026)