Phantom Unit OS · mapa do sistema e ordem de construção

Do formulário à loja,
e de volta ao bolso do artista.

Todo nó, toda seta, todo disparo, todo prazo, todo botão e todo arquivo — com o estado real de cada um. O mapa é o plano: onde ele está vermelho é onde falta construir.

existe e funciona existe pela metade / é maquete não existe decidido, não começou

01 A espinha — o ciclo de um lançamento

Uma linha só, de cima pra baixo. Cada nó diz quem age, o que cria no banco, o que dispara e quanto tempo tem. As ramificações saem à direita.

Entrada — como uma pessoa vira alguém que pode lançar

✉️CONVITE staff · qualquer papelno ar
grava convites — código, artist_id, papel, validade 30d e-mail pelo Resend, contato@phantomunit.com.br · retry pelo cron duas portas: pessoa nova · re-vínculo (troca a porta de quem já existe) o WhatsApp digitado no modal do artista é descartado — o INSERT não tem a coluna
🔑LOGIN GOOGLE a pessoano ar
cria pessoas + pessoa_projeto + pessoa_funcao sessão de 30 dias em sessoes, cookie pu_sessao o vínculo é pelo LINK, não pelo e-mail — logar com outra conta Google funciona igual convite vencido + pessoa que já existe = entra calado e o projeto não vincula
📋FICHA · /bemvindo o artistatrava cedo demais
nome artístico · nome civil · CPF · cidade · gênero · redes · foto · logo · bio grava fichas (declaração, trava) + artists (vitrine, sempre editável) "deixar pra depois" faz o mesmo POST — a ficha vira enviada e nunca mais abre CPF é opcional ali, e não existe segunda porta pra digitar depois

O formulário de lançamento — o nó que abre tudo

🎛️FORMULÁRIO · /submit o artista · 5 passosquebrado hoje
1 projeto e contato fiscal — artist_name · legal_name · cpf · email · whatsapp 2 o lançamento — release_title · release_type · genre · data_lancamento 3 as faixas — title · version · bpm · key · collab · master_option + WAV e mixdown 4 a capa — cover_option (própria ou do designer) + conceito e referência 5 o contrato — cpf_aceite · declaration_security submit.html:1373 inventa id:'PHANTOM-4823'ficha.js:88 procura essa ficha, não acha → 404 "nao_encontrada" o array faixas[] é coletado e jogado foraachata() só lê track.title
💿O LANÇAMENTO NASCE sistemanasce incompleto
cria releases · release_artists · tracks cria as 4 linhas de release_etapas: capa wav mkt distro faixa_artistas fica vazio — não existe um único INSERT nessa tabela em todo o app data_alvo não é gravado no nascimento — só quando mkt/distro destravam. Hoje: 0 de 1.428 linhas deveria disparar pro designer e pro master que entrou trabalho — não dispara

As duas colunas que correm em paralelo

ao mesmo tempo · nenhuma espera a outra
🎨CAPA Bagre · designer · 7 diasmeio caminho
o artista sobe, ou o designer produz a partir do conceito do passo 4 arquivo → R2 covers/ · jpg/png · teto 25 MB · registra arquivos.capa3000 o upload move o estado por SQL direto — sem etapa_eventos, sem avisar o Bagre aprovar → 🟢 · recusar → volta pra 🔴 com o motivo
🎚️WAV · MASTER Lutz · master · 7 diasmeio caminho
o artista sobe o premaster, o Lutz devolve o master arquivo → R2 masters/ · só .wav · teto 300 MB · registra arquivos.master o prefixo masters/ só sai com sessão, e responde 404 sem login — não 401 mesmo defeito: sobe e ninguém é avisado
🔓DESTRAVA sistema · na mesma transaçãono ar
capa E wav em 🟢 → mkt e distro saem de pra só aí data_alvo é gravado — o relógio conta da liberação, não da criação e nunca passa da data de lançamento: de nada adianta ter 3 dias se o disco sai amanhã avisa a Amanda e o Basso que foram chamados pro jogo
ao mesmo tempo
📣MARKETING Amanda · marketing · 3 diasbotão morto
1 ZIP → R2 mkt/ · teto 500 MB · ~120 MB (1 reel + 4-5 artes + 1 vídeo) mkt/ não está na lista de prefixos trancados — nasceu público no R2 o CHECK de arquivos.tipo recusa "mkt": sobe no R2 e estoura no INSERT APROVAR é impossível de clicar: mede o estado em vez do arquivo. A coluna dela está morta na tela
🚚DISTRIBUIÇÃO Basso · manager · 3 diassó aprova
⧉ COPIAR METADADOS → leva pro painel da distribuidora ⬇ BAIXAR WAV → o master sai do masters/ aprovar → distribuído → trava definitiva dos arquivos
🌐SAI NAS LOJAS a data que o artista informou no passo 2a data manda
é ela que dispara prazo, aviso e esfriamento — nunca a planilha do Label Worx, que atrasa um trimestre
🔊GERAR OS DERIVADOS sistemanão construído
MP3 do player → mp3/ · capa web 1200 → capaweb · reel de preview → previews/ Tem que existir ANTES do original esfriar. Se inverter, o WAV vai pro armário e o painel fica sem o que tocar hoje: 324 capaweb e 115 mp3 no banco, todos vindos da migração do catálogo — o app não gera nenhum
📦ARMÁRIO · +30 dias cron semanalnão construído
master · capa 3000 · pacote de mkt → R2 Infrequent Access a régua nativa do R2 não serve: ela conta idade do objeto, e esfriaria o WAV no meio da produção falha manso: se o cron quebrar, o arquivo só fica quente mais tempo e custa centavos a mais
por que a esteira nunca cresce

A esteira é rotativa: entra quando o lançamento nasce, sai 30 dias depois de sair nas lojas. Ela é função do ritmo (~25 lançamentos/ano), não do tamanho do acervo — com 300 ou 3.000 releases ela continua com os mesmos ~2 GB. Vitrine + Esteira cabem na franquia grátis de 10 GB. O que paga é só o Armário.

02 A mecânica das bolinhas

Quatro estados, quatro ações, e um ciclo. O estado de origem nunca vem da tela — é lido do banco na hora. Se o navegador pudesse dizer "estava em andamento", bastava mentir pra aprovar o que nem foi entregue.

BLOQUEADO não se aplica destrava PENDENTE falta fazer entregar ANDAMENTO esperando aprovação aprovar CONCLUÍDO pode esquecer recusar · nota obrigatória ⚡ avisa o artista COM o motivo reabrir · só admin · fica no histórico
a sua pergunta, respondida na letra

"o que acontece quando o masterizador recusa a master? de laranja volta pra vermelho, isso gera um alerta pro artista"é exatamente isso, e a regra já está escrita no código. recusar leva 🟡 andamento → 🔴 pendente, a nota é obrigatória (recusa sem motivo é só um "não", e o artista fica sem saber o que arrumar), e o aviso sai uma linha por pessoa do projeto — duo recebe nos dois contatos.

Só falta o botão. As quatro chamadas de moverEtapa no painel são todas 'aprovar'. RECUSAR e REABRIR não existem em lugar nenhum da tela.

AçãoVai dePraQuem podeDisparatela
entregar🔴 pendente🟡 andamentodono do projeto (capa/wav), quem responde pela etapa, ou adminavisa quem aprova
aprovar🟡 andamento🟢 concluídoquem tem o papel da etapa, ou adminavisa o artista
recusar🟡 andamento🔴 pendentequem tem o papel da etapa, ou adminavisa o artista, com o motivo
reabrir🟢 concluído🔴 pendentesó admin

existe pela metade (o upload move o estado por fora e não avisa) · tem botão · sem botão

três leis que a bolinha tem que obedecer

1. Toda bolinha tem dono e próxima ação. 2. Toda bolinha é filtro — clicar nela abre a fila daquele estado. 3. Bolinha sem estado real por trás é pior que texto: parece informação e não é.

Onde isso está sendo quebrado hoje: a aba ARTISTAS pinta 207 artistas de vermelho por "sem lançar há mais de um ano" — vermelho sem dono e sem próxima ação, que é julgamento e não trabalho. E o painel cobra 92 tarefas de releases que já saíram. Quando 80% da tela é vermelha, o vermelho para de puxar o olho em todas as outras.

03 A comunicação — todo disparo, todo prazo

Nada aqui é opcional: metade do painel de trabalho é sobre coisa que não aconteceu, e ninguém clica em "não fiz nada ainda". Por isso existe o relógio.

Os 13 disparos

#QuandoVai pra quemCanalestado
1convite criadoa pessoa convidadae-mail
2convite de re-vínculoa pessoa que já existee-mail (texto próprio)
3etapa liberadaquem responde por elae-mail
4alguém entregouquem aprova aquela etapae-mail
5etapa aprovadao artista — uma linha por pessoa do projetoe-mail
6etapa recusadao artista, com o motivoe-mail
7capa e wav fecharam → destravouAmanda e Bassoe-mail
8metade do prazoquem responde pela etapae-mail · cron 9h
9faltam 24hquem responde pela etapae-mail · cron 9h
10prazo estourouquem responde pela etapae-mail · cron 9h
11membro parado há mais de um anoa direçãoe-mail · cron 9h
12saque solicitadocontato@ + WhatsApp Nathan e Amandae-mail + zap
13saque pagoo artistae-mail
os três avisos de prazo nunca dispararam — nenhuma vez

O cron das 9h roda, filtra WHERE data_alvo IS NOT NULL, e não acha nada: data_alvo é nulo nas 1.428 linhas de release_etapas. Os prazo_dias da tabela funcoes (7 · 7 · 3 · 3) são decoração.

E foi exatamente essa funcionalidade que motivou sair do Pages pro Workers. O motor está montado, ligado e girando em falso — falta só alguém gravar a data-alvo quando o lançamento nasce.

Os prazos, e de onde eles contam

EtapaPapelQuem é hojeprazoConta a partir de
🎨 CAPAdesignerBagre7 diascriação do lançamento
🎚️ WAVmasterLutz7 diascriação do lançamento
📣 MKTmarketingAmanda3 diasda liberação (capa + wav 🟢)
🚚 DISTROmanagerBasso3 diasda liberação

E o teto é sempre a data de lançamento: se o prazo cair depois dela, vale a data. O relógio roda uma vez por dia, às 9h de Brasília — prazo de 7 dias não muda de status entre 9h e 10h. A fila de avisos é esvaziada de 15 em 15 minutos, como rede de segurança de quem falhou no envio imediato.

três defeitos na entrega

Subir arquivo não avisa ninguém. O upload move a etapa por SQL direto, sem passar pela rota que dispara o aviso. O Bagre e o Lutz só descobrem se abrirem o painel.

A fila não tem trava de posse. Cron e rota podem pegar a mesma linha e mandar duas vezes. Não mordeu porque só existem 7 avisos no banco.

O WhatsApp ainda não está ligado — a Evolution precisa de um VPS, e a URL está vazia no wrangler.toml. Hoje tudo é e-mail. E e-mail é registro; WhatsApp é o aviso que a galera vê.

04 Os arquivos — quente, esteira, armário

O eixo não é tamanho. É por quanto tempo o app precisa servir aquele arquivo. O banco não se divide: o D1 continua sendo o catálogo inteiro, e sabe onde cada byte está. Só os bytes se espalham por função.

CamadaO que moraOndeAcessotamanhoestado
🪟 Vitrinecapa web 1200 · MP3 do player · reel de previewcovers/ mp3/ previews/capa pública · mp3 e preview só com login~7 GB
🔧 Esteiramaster · capa 3000 · pacote de mkt em produção até +30dmasters/ covers/ mkt/só com login · 404 sem sessão~2 GB rotativo
📦 Armárioos mesmos, já lançadosR2 Infrequent Accesssó com login~65 GB
🚫 Forastems · projeto · mockup · vídeo bruto · pacotes de mkt antigosDropbox / backup

O caminho de cada arquivo

🎚️WAVo master
upload → masters/ · só .wav · 300 MB · arquivos.master o Basso baixa pra distribuir · o artista vê que está lá no lançamento: trava (ninguém altera mais) · +30 dias: esfria pro armário a extensão é conferida no servidor e a chave é montada lá — o cliente nunca escolhe o caminho
🔉MP3derivado do WAV
mp3/, interno de propósito: é o acervo, não a vitrine pública toca no perfil da música dentro do app, pra o artista ver que a música dele está ali nenhum código do app gera MP3. Os 115 que existem vieram da migração do catálogo
🖼️CAPA3000 e web
3000×3000 → covers/ (esteira, depois armário) · web 1200 → vitrine, pública 324 de cada no banco · a API pública da Apple resolveu 239 sem uma falha
📦PACOTE DE MKTAmanda
1 ZIP → mkt/ · ~120 MB: 1 reel (~15) + 4-5 artes (~15) + 1 vídeo YouTube (~90) do pacote, só o reel fica quente (vira preview na página) — o resto vai direto pro armário nasceu público no R2 e o registro no banco estoura. Zero uploads até hoje
onde a música toca, e por quê

Na página pública do release: embed de Spotify/YouTube — o play conta como stream e vira royalty. Player próprio ali seria pagar storage pra perder dinheiro em cada play. No painel interno: MP3 real, porque ali ninguém ia streamar de qualquer jeito.

Hoje as duas páginas públicas tocam um MP3 de demonstração genérico ao lado do texto "Qualidade Master 24-bit", e é ele que faz a página levar 18 segundos pra terminar de carregar.

05 As telas e todos os botões

41 botões no painel, mais os que os geradores criam em tempo de execução. Um por um, com o que cada um faz de verdade.

Navegação e conta

BotãoO que faz
DASHBOARD · ARTISTAS · MÚSICAS · FINANCEIRO · CHAT · CONFIGtroca de aba sem recarregar · a aba do endereço manda no boot · cada uma busca os dados na 1ª abertura
↩ SAIRapaga a linha em sessoes, não só o cookie
🔔 AVISAR NO CELULARinscreve no Web Push (PWA)

Artistas

BotãoO que faz
+ CADASTRAR ARTISTAcria o projeto no casting e convida · trata "já existe" em verde, sem duplicar
+ EQUIPEconvite sem artist_id, com seletor de papel — é a porta da Amanda
✉️ CONVIDARconvite com artist_id — sem isso a discografia dele fica órfã
⚡ VER PERFIL · 👁️ GERENCIAR PERFILabre a vitrine do projeto
SALVAR ALTERAÇÕESgrava em artists · o nome oficial não entra: só admin renomeia
bolinhas de perfillogo · foto · descrição · links — clicáveis como filtro e ordenáveis

Músicas — a esteira

BotãoO que faz
CAPA · MASTER · MKT · DISTRIBUIÇÃO (cards do topo)filtram a fila daquela etapa · ainda cinza, fora do padrão de etiqueta verde
bolinhas da tabelacada uma é filtro · title explica o estado do ponto de vista de quem lê
⚡ GERENCIARabre a ficha do lançamento com os 4 módulos
⬇ ORIGINAL · ⬇ BAIXAR WAV · ⬇ BAIXAR PACKpuxam do R2 · BAIXAR PACK nunca liga (o mesmo bug do APROVAR do mkt)
APROVAR (capa · wav · distro)🟡 → 🟢 · avisa o artista · capa+wav fechando destrava mkt e distro
APROVAR (mkt)impossível de clicar — mede o estado em vez do arquivo
RECUSARnão existe — a rota existe, o texto do aviso existe, o botão não
REABRIRnão existe — a rota é admin-only e está pronta
⧉ COPIAR METADADOSleva a ficha pro painel da distribuidora
zona de arrastarupload de capa · WAV · pack
💬 WHATSAPP do responsávelabre a conversa · o número de teste ainda está em um deles

Financeiro

BotãoO que faz
SOLICITAR SAQUEsó aparece com a janela aberta e ninguém tendo pedido · modal com PIX digitado na hora
CONFIRMAR PEDIDOehDono antes de gravar · valor recalculado no servidor · idempotente por projeto+trimestre
AGUARDANDO PAGAMENTObotão desabilitado amarelo — é estado, não ação: deveria ser um selo, não ocupar o lugar do botão
exportar CSV do trimestrea planilha de pagamento · hoje qualquer logado baixa
MARCAR COMO PAGOnão existe — o 🟡 → 🟢 só acontece por SQL na mão

Ainda maquete

BotãoO que faz de verdade
SALVAR CHAVES DE APIalert('✅ Chaves salvas com sucesso!') — e os campos vêm com chave falsa preenchida
🟢 SPOTIFY · 📸 INSTAGRAM · + APURAÇÃOdesabilitados com "EM BREVE" — estes estão certos, dizem a verdade
4× "Baixar…" no press kit públicoalert('Baixando fotos oficiais HD...') — nada baixa, em 227 páginas
PRÉ-SAVE (público)alert('PRÉ-SAVE REALIZADO COM SUCESSO!') — não salva nada, pro público
▶ PLAY PREVIEW (público)toca uma faixa genérica de demonstração

06 As páginas públicas

Dois arquivos servem 584 páginas. Mexer no layout é mexer em um arquivo, e todas mudam junto — artista novo já nasce com página. É a maior alavanca do sistema, e hoje é o que está pior.

PáginaServeLê deSituação
/artistas/<slug>228 press kits/api/roster?id=14 de 21 do casting quebram por title:null · UTTARI e zap falso em todas
/musicas/<slug>350 lançamentos/api/roster?release=pré-save de mentira · o bloco ROYALTY já vem no HTML, escondido só por CSS
/casting.htmla grade do roster/api/rostercarregando, erro e vazio renderizam dentro de uma bolinha de 11px
/index.htmla vitrine da labelnadazero chamada de API · 11 fotos de um gerador aleatório · "Uttari" listado como artista
/login.htmla entrada/api/convite-infoa única página sem nenhum achado
a armadilha do conserto

Na página de música, o bloco #section-live já chega ao visitante anônimo populado com o royalty — £467,21, £6,24, o detalhe por loja — e o que segura é um bug: o script nunca chama setMode('live'). Consertar o modo sem antes tirar a coluna ROYALTY publica o faturamento por faixa. Os dois têm que andar juntos, e nessa ordem.

07 O dinheiro — o outro ciclo

Corre por fora da esteira, no ritmo do trimestre. É a parte mais bem construída do sistema.

📊RELATÓRIO LABEL WORX chega no mês seguinte ao trimestrena mão
XLSX → filtrar Label Name = 'Phantom Unit' (o arquivo traz 5 gravadoras) → sales o EAN vira float (...476.0) e não casa com nada — e não dá erro, só nunca encontra release novo chega com número PH e já existe como PU: funde por id, nunca cria outro hoje é script manual · importador dentro do app não existe
⚖️O RATEIO sistema · uma definição sóprova fecha
1 quebrar a faixa nos donos dela → faixa_artistas 2 resolver cada dono no perfil → artist_aliases 3 somar por perfil — nunca somar por texto e juntar depois colab divide entre os projetos primeiro; a taxa de cada um se aplica depois bruto 13.252,58 = artistas 7.580,54 + label 5.672,04 · órfão 0,00
🧾EXTRATO E JANELA o artistaa regra está certa
janela de 3 meses: Q1→31/07 · Q2→31/10 · Q3→31/01 · Q4→30/04 sem mínimo de £1 · o saque é por projeto: o primeiro que pedir trava o botão dos dois logins colab entre projetos diferentes é outra coisa — cada um saca a metade dele o artista não alcança essa tela — ela chama a rota sem o projeto dele e trava em "carregando…"
💸SAQUE artista pede · direção pagafalta o fecho
🔴 não solicitado → 🟡 aguardando → 🟢 pago · vem de royalties, por projeto+trimestre e-mail pro contato@ + WhatsApp pro Nathan e pra Amanda · com protocolo PIX digitado na hora, nunca guardado no perfil · copia-e-cola gerado no Worker, sem valor o extrato é em £ e o PIX em R$ — e nada na tela explica isso ao artista não existe botão de marcar como pago, e não há índice único: já entraram 3 linhas no mesmo trimestre

08 A ordem de construção

Sete fases. Cada uma existe porque destrava a seguinte — não é lista de desejo, é dependência. A fase 0 é a única que não pode esperar.

0Fechar a porta antes de qualquer coisa

Por quê: tem dado de artista na internet aberta agora. Nada do que vem depois vale a pena construir em cima de uma porta aberta.

  1. Apagar o Pages phantom-release-hub — 176 URLs de deploy sem Access, ligadas no D1 de produção
  2. Varrer o roster.js inteiro: lista explícita de colunas, tirar o gbp de faixas e lojas, tirar o WhatsApp das duas consultas
  3. Mover a checagem de posse pro topo do financeiro.js, antes de ramificar por parâmetro
  4. Devolver o revincular: true — ou parar de devolver o link do convite na resposta
1Fazer a esteira andar uma vez destrava tudo que tem prazo

Por quê: hoje nenhum lançamento consegue nascer no app. Enquanto isso for verdade, todo o resto da esteira é teoria.

  1. Consertar a submissão — parar de mandar id inventado no primeiro POST
  2. Gravar faixa_artistas com o faixas[] que o formulário já coleta e joga fora
  3. Gravar data_alvo no nascimento de capa e wav — é a linha que liga o relógio na tomada
  4. Fazer o upload passar pela rota de etapa: gravar etapa_eventos e disparar o aviso
  5. Recusar o upload que sai de bloqueado — hoje dá pra pular capa e master subindo o ZIP
2Dar à equipe os botões que faltam a máquina de estado já existe inteira

Por quê: sem RECUSAR não existe ciclo de correção — existe carimbo. E a coluna da Amanda está morta na tela.

  1. RECUSAR com campo de nota (a rota já exige, o texto do aviso já existe)
  2. REABRIR pro admin — inclusive pra reabrir ficha, que hoje não tem conserto por dentro
  3. Consertar o APROVAR do marketing: medir o arquivo, não o estado — e devolver tem_mkt na rota
  4. Trancar mkt/ no R2 e corrigir o CHECK de arquivos.tipo
  5. MARCAR COMO PAGO no financeiro, com UNIQUE(artist_id, period) antes
3O artista existir de verdade tem um lá dentro desde 30/07

Por quê: o GreenTech entrou e recebeu a interface de staff — o roster inteiro, os 350 lançamentos, e a aba do próprio dinheiro travada.

  1. O escopo cair pelo projeto da sessão quando a pessoa é artista — como o /api/dashboard já faz no servidor
  2. Remover o filtro PH/GM do app.html:2318 — ele esconde 64 lançamentos na visão do artista
  3. Toda aba mostrar erro em vez de return mudo: hoje três catch deixam a tela em "carregando…" pra sempre
  4. Tirar o "50%" dos rótulos de tela — o número está certo, o rótulo mente e publica acordo confidencial
  5. Explicar £ → R$ no extrato, e separar "deixar pra depois" de "enviar" na ficha
4Limpar o que vai pra fora é o rosto da label

Por quê: 227 press kits e 350 páginas de lançamento entregam hoje o nome de um artista que nunca existiu, downloads que não baixam e um pré-save que não salva.

  1. Preencher os 39 title: null no banco — uma correção de dado que conserta 14 press kits de uma vez
  2. Apagar UTTARI, o zap de teste, os 4 alert('Baixando…'), o pré-save falso e o áudio de demonstração
  3. Tirar a coluna ROYALTY do release-page.htmlantes de consertar o setMode
  4. Ligar a home na API: 327 capas reais paradas enquanto 11 fotos vêm de um gerador aleatório
  5. Fazer a bio do artista aparecer no press kit — ele escreve e nunca é lido
  6. Corrigir booking@phantomunit.com.com.br
5Os derivados e o armário a ordem aqui não é negociável

Por quê: o preview tem que existir antes do original esfriar. Se inverter, o WAV vai pro armário e o painel fica sem o que tocar.

  1. Gerar MP3, capa web e reel de preview no fechamento do lançamento, não no esfriamento
  2. Só depois: cron semanal que move master, capa 3000 e pack pra Infrequent Access +30 dias do lançamento
  3. Trava definitiva do arquivo no dia do lançamento — é regra de negócio, separada do esfriamento, que é só billing
6Um painel só, e a fila de cada um a missão, enfim

Por quê: hoje existem dois front-ends divergindo, e nenhuma tela responde "o que eu preciso fazer agora" — só "o que a label tem parado, por função".

  1. Limpar as 92 bolinhas falsas: releases que já saíram não são trabalho pendente
  2. frio vira cinza "não se aplica" — vermelho é trabalho, e 207 artistas de vermelho matam o vermelho
  3. Criar os 5 tokens que faltam: --brand-accent separado dos 4 --estado-*
  4. Uma fila por pessoa, com prazo visível e "você está esperando fulano"
  5. Decidir a virada /novo/app com a matriz de paridade na mão
  6. Ligar o WhatsApp (Evolution no VPS) — e-mail é registro, zap é o que a galera vê

09 A leitura em uma frase

o que este mapa mostra

O sistema não está pela metade — ele está construído e desligado. A máquina de estado tem as quatro transições certas, os 13 avisos têm texto pronto, o relógio roda de 15 em 15 minutos, o rateio fecha ao centavo e a arquitetura de armazenamento está desenhada até o custo em reais.

O que falta são ligações, não peças: uma linha que grave a data-alvo, uma que grave o dono da faixa, um botão de recusar, um escopo que caia pela sessão. São poucas linhas em lugares certos — e cada uma delas acende um pedaço inteiro que já está pronto esperando.

A fase 0 é a exceção. Ela não constrói nada: ela fecha uma porta que está aberta agora.