A 0.17: o que mudou e a compatibilidade
A 0.17 não conversa com a 0.16
A 0.17 fala o Servidor 2.0, que usa outra conexão, o WebRTC. Ela não conversa com a 0.16 nem com as anteriores, em nenhuma direção: quem ficar na 0.16 não entra nos servidores da 0.17, e a 0.17 não entra nos servidores da 0.16 sozinha.
A 0.16 continua disponível: ao atualizar, o SEELE guarda as suas conversas e o servidor que você hospeda para o Servidor 1.0 e abre a 0.16 ao lado quando um link ou um servidor pedir.
Ao instalar, o SEELE fecha, e quem estiver no servidor que você hospeda sai junto. Combine com o seu grupo antes: todos precisam da 0.17 para continuar juntos no Servidor 2.0.
A 0.17 fala o Servidor 2.0, pelo WebRTC
O SEELE trocou a conexão de rede: o QUIC saiu, e o app, o seeled e a página do navegador passam a falar WebRTC, a mesma tecnologia das chamadas de vídeo no navegador. A 0.17 fala o Servidor 2.0.
A chave do servidor que você hospeda não muda: quem já entrou nele continua reconhecendo a mesma impressão digital.
Os dois não se entendem em nenhuma direção. Um servidor hospedado na 0.16 fala o Servidor 1.0, e a 0.17 o abre pela 0.16 guardada ao lado (abaixo). Quem ainda está na 0.16 e recebe um link da 0.17 lê que precisa de uma versão mais nova.
O que a 0.16 vê, sem promessa para trás. A 0.16 que você já tem instalada mostra este aviso no bloco O QUE MUDA, antes do botão de instalar, e não pede confirmação: instalar continua sendo um clique. A confirmação antes de atualizar, com cancelar, adiar e prosseguir, existe da 0.17 em diante. Na linha da 0.16, ela existe só na 0.16.1, preparada junto com esta versão (com essa confirmação e os endereços novos), e só para quem a instalar.
Uma 0.16 que digita à mão o endereço de um servidor 0.17, sem link, não recebe frase nenhuma: a tela diz que nada respondeu.
No navegador, quando a conexão segura com o servidor não se confirma, a página diz que a verificação falhou, e não por quê: o navegador não conta a causa. O app diz quando a chave do servidor mudou.
Medido na página do navegador (Chromium 149 e WebKit 26.5), com a fila real do rtc-web.js contra o eco de produto: 10 rodadas por configuração, nos dois sentidos (32 MiB subindo e os mesmos descendo), com 1 e 4 canais, 0 perdas de voz nas 40 rodadas. O p99 da voz com a subida saturada ficou em 21 a 57 ms, e na descida em 1,4 a 65 ms. Limites: isto não prova voz sem perda sob qualquer carga; a CPU disputada não foi repetida pela página; a variação grande que o spike viu (8 a 9 % de perda, depois 17 de 102) não reapareceu e a origem dela segue indeterminada; o app nativo e redes reais não entraram nesta medida.
A 0.16 continua abrindo, guardada ao lado
Na primeira vez que abre, antes de mexer em qualquer coisa, a 0.17 copia os dados da 0.16 (o servidor que você hospeda, a lista de servidores, as preferências) para uma pasta só do Servidor 1.0, e baixa a 0.16 em segundo plano, uma vez. A sua identidade não é copiada: é a mesma nas duas. Isso foi medido sobre um perfil de verdade, criado pela 0.16.0 publicada, no Mac e no Windows: até você confirmar, o banco do servidor e o registro dele ficam byte a byte iguais, e a conversão faz antes uma cópia conferida do banco como a 0.16 o deixou. No Mac, a 0.17 chegou pelo atualizador do app, e a pasta do Servidor 1.0 também foi conferida; no Windows, a 0.17 foi aberta trocando o programa por uma compilação de teste, e não pelo atualizador. O download da 0.16 em segundo plano e o link de um servidor 1.0 abrindo a 0.16 não fizeram parte dessa medida.
Daí em diante, um link de um servidor 1.0 abre a 0.16 noutra janela, e ao hospedar dá para escolher o Servidor 2.0, que é o padrão, o Servidor 1.0 ou o Servidor 0.15.
Pela internet, também do navegador
O navegador tem o caminho de entrada pelo ponto de encontro; hospedar continua só no app. O smoke externo de rendzvous.seele.sh permanece um gate de ativação, ainda não executado: não há PASS externo da build final.
Na mesma rede local, uma rodada de uma hora, com o servidor num Mac, quem fala num Windows e quem ouve no Safari do simulador do iOS, instalado na Tela de Início, recebeu todos os pulsos sintéticos, sem perda. Não foi medida na build final a travessia entre duas casas pelo ponto de produção, nem esse caminho externo no Chrome e no Firefox.
A conversa vai direto entre as máquinas: o SEELE não usa servidor de retransmissão (TURN), por decisão, e o ponto de encontro só apresenta os dois lados. Duas redes com NAT simétrico, ou uma rede que só sai por um proxy sem UDP direto, não se alcançam assim, e a tela diz que o caminho não abriu, em vez de ficar conectando.
Endereços novos, e o SEELE no navegador começa do zero
O SEELE passou para o domínio seele.sh: o app no navegador em seele.sh, o site e os downloads em get.seele.sh, a documentação em docs.seele.sh, o índice de MODs em mods.seele.sh e o ponto de encontro em rendzvous.seele.sh. O domínio antigo será desligado, e a 0.17 não depende dele: um convite antigo colado ainda diz o servidor e o ponto de encontro, que é lido no endereço novo.
No navegador, a identidade é nova. Ela fica guardada no navegador, presa ao endereço em que foi criada, e não passa sozinha do endereço antigo para o novo. Quem usava o SEELE pelo navegador entra em seele.sh como uma pessoa nova: os cargos e os acessos da identidade antiga não vêm junto, e quem administra o servidor pode admitir de novo, com um convite novo. O app no computador mantém a identidade dele.
Vários servidores ao mesmo tempo, e a voz em um só
Dá para estar em vários servidores ao mesmo tempo, inclusive enquanto você hospeda o seu: trocar de servidor na trilha não desconecta os outros, e sair de um não mexe nos demais nem no que você hospeda.
O microfone vai para um servidor de cada vez, o que está com a voz. Trazer a voz para outro é um ato seu: entrar numa sala de voz dele. O microfone para no anterior antes de abrir no novo, e o anterior sai da sala de voz. Fora do servidor com a voz, não se ouve a voz dos outros servidores; o texto, a presença e as telas continuam chegando. Isso foi provado em teste, no transporte da 0.17: com três servidores de verdade, contando a voz que chega a cada um durante três trocas, nenhum instante teve dois servidores recebendo a voz.
Cargos, e um dono declarado
Quem entra primeiro num servidor não vira mais o dono. O dono é declarado pela máquina que hospeda, pela impressão da chave dele, e cargos dão a cada pessoa o que ela pode fazer. O servidor confere cada pedido: ninguém se dá um cargo acima do próprio, nem concede uma permissão que não tem, e a migração dos papéis de antes não dá a ninguém mais do que já tinha. No app, quem hospeda é o dono do próprio servidor, e a sala pessoal é da pessoa dona da chave dela. No seeled, o dono é declarado com seeled --proprietario <impressão>; ele não lê arquivo de configuração.
Hospedar um servidor antigo: nada muda antes de você confirmar
Na tela ANTES DE HOSPEDAR, escolher ATUALIZAR ou DESLIGAR um MOD que esta versão não roda não toca nos dados do servidor: a escolha fica guardada, e a tela diz «a aplicar ao hospedar». É o botão do fim que faz tudo, nesta ordem: uma cópia de segurança nova e verificada, a conversão dos dados para esta versão, as suas escolhas de MOD e só então a subida. Quem hospeda não é perguntado de novo pelos MODs que acabou de escolher. Desistir e voltar mostra a mesma escolha, e você pode desfazê-la. Cada escolha vale para o servidor em que você a fez, e nenhum outro servidor guardado muda. Medido no Mac nativo pela interface (XCTest de macOS, 26 e 27/10, a build final), com um app de teste isolado (bundle-id próprio, perfil descartável, feed local, chave efêmera) e um servidor de fixture da 0.15 com os Perfis 3.3.1, partindo do 0.16.0 publicado e do 0.16.1: nada mudou no banco antes do botão do fim, e a cópia verificada saiu antes da conversão. O MOD novo veio do catálogo OFICIAL ASSINADO, servido localmente com as assinaturas conferidas pela chave do app (o domínio novo ainda não está no ar); esse catálogo tem os MODs da API 6. As versões da API 7 dos MODs oficiais foram testadas à parte e ainda não estão no catálogo público. Sobre uma pasta que a 0.16 de verdade criou, a primeira abertura foi medida à parte (acima).
O que não faz: converter sem a cópia; atualizar o MOD de servidores parados pela gestão de MODs (ali só o pacote chega a esta máquina, e a tela diz isso).
Uma cara nova
A tela inicial passou a ocupar a largura toda, e a ligação ganhou uma vista própria, com quem está nela. Antes de hospedar, a tela separa três coisas: os dados do servidor (e se eles vão ser convertidos), a versão do servidor (e quem consegue entrar) e os MODs.
Limites e pendências desta versão
Medido, com o alcance de cada medida (25 e 26/10/2026):
- Windows 11 real, checkout isolado: o app compilou (perfil dev) e 8 testes
passaram, entre eles a voz depois de voltar ao servidor e a pausa e o fim da tela com reconexão. Outros 8 testes, diferentes dos de conformidade e dos do jitter, passaram com o codec oficial (SEELE_EXIGE_CODEC=1), só com imagens geradas;
- Windows 11 real, 1 hora (3600 s corridos), em loopback e sintética: voz
gerada e H264 gerado, 57299 quadros de tela contados no transporte, uma saída e reconexão do servidor inteiro, e o primeiro som depois de entrar de novo na voz (12 s depois de reconectar) em 62 ms; maior silêncio de 247 ms, 0 erros, supressão de ruído desligada. Nessa hora não houve captura de GUI, WASAPI, decodificação de vídeo nem rede externa;
- Windows 11 real, smoke físico de 3 s a 48 kHz: os callbacks de captura e de
saída abriram, sem erro de stream e com 2496 underruns. Não é áudio físico aprovado: 3 s não fecham estabilidade nem latência;
- Windows 11 real, ritmo físico de 10 min: 600 s completos, exit 0, em 60
intervalos de 10 s. Só o primeiro teve falta (1056 amostras, 1 bloco inicial); dos 20 s aos 600 s, todos com falta 0 e anel cheio 0; reserva de 44 ms e 1 reposição. O aparelho a 48 kHz foi alimentado com silêncio, no compasso real: não é uma chamada completa nem latência física;
- Linux ARM64 em Docker (Rust 1.97.1): o app compilou e 8 testes do jitter
passaram, sem GUI nem hardware;
- Mac, app nativo, voz sintética e vídeo H264 gerado, em loopback: 15 minutos
de vídeo e voz nos dois sentidos sem intervalos mudos, nem perda ou PLC registrados (build anterior ao reparo da fila de voz, abaixo);
- Mac, build com o reparo da fila de voz: sair do servidor inteiro, voltar,
esperar mais de 12 s e entrar na voz; mais de 3 min com blocos contínuos com som nos dois sentidos, profundidade da fonte em 20 ms, sem perda nem PLC. É continuidade e profundidade de buffer, não latência física;
- voz depois de uma pausa da máquina, numa LAN de bancada (180 s): a fila ficou
em 40 a 60 ms, sem silêncio prolongado, e a voz voltou à sala em 68 ms. Esse ensaio não é verde por inteiro: o processo receptor saiu com erro pelo gate de tela durante a pausa planejada, e o ramo do buraco pulado não foi exercitado ali (um teste dirigido o cobre). Um teste dirigido de pausa de 8 s mede a maior lacuna sem voz em até 540 ms nos primeiros 5 s depois da pausa, e não durante ela; não é uma garantia geral;
- Mac, amigos e vista pessoal: o código próprio, adicionar, renomear, bloquear
e tirar uma amiga, a persistência depois de reiniciar e a ligação a uma amiga salva sem redigitar o código passaram, contra uma amiga de bancada;
- Mac nativo, build de teste isolada (
br.app.seele.teste017, binário
SHA-256 398e50f5…), perfil de fixture de um servidor da 0.15 (schema 13, MOD de estilo 3.1.0): ATUALIZAR, DESLIGAR e DESFAZER antes de confirmar deixaram o banco byte-idêntico e sem cópia nova; ao confirmar, a cópia de segurança saiu em schema 13 com dump SQL idêntico ao original, e o banco passou ao schema 18 com o MOD 4.0.0. Os Perfis oficiais, MOD API 5 para 6, também passaram no CUA (outro bundle e outro perfil de fixture), com o mod_data antigo preservado. Medido com fixture, não com uma pasta da 0.16 real;
- Mac nativo, bundle de teste ee58eee8: o CUA dos cargos passou (a lista com 5
cargos, «QUEM PODE O QUÊ» explicando o proprietário, a prévia de renomear o Operator dizendo que ninguém muda de permissão, DESCARTAR e as mensagens);
- a validação usa **bateria completa mais retestes dos
afetados**, e não uma segunda rodada completa limpa: a bateria do workspace deu 4387 aprovados, 5 reprovados e 15 ignorados; as falhas foram corrigidas e os retestes focais passaram. A retomada web também passou nos 78 testes de seele-web e no frontend (350), além das provas Xcode. Depois do reparo ARIA, o frontend deu 349 aprovados e uma falha de fixture desktop, corrigida; o focal Node e o reteste Rust (1/1) passaram. O check-runtime foi corrigido e passou, e o clippy com --all-targets --all-features passou. O E0463 dos doctests, de causa só provável, não se repetiu.
Não foi medido:
- NAT real entre duas casas e IPv6 global (não há TURN: o que o caminho direto não atravessa fica sem caminho);
- Safari.app no Mac e a build final no iPhone físico. Numa build anterior,
o dono confirmou voz nos dois sentidos pelo 5G no iPhone; a tela congelou. Isso não valida a tela nem a build final física. A validação final escolhida foi o Safari/PWA no simulador iOS via Xcode, além dos testes de viewport;
- a captura de tela, a decodificação de vídeo e a chamada de áudio física no
Windows com WebView2. A primeira abertura e a migração do perfil foram medidas na interface com um executável de teste; o relato de 15 a 60 minutos no aplicativo Windows de quem usa, que não foi reproduzido com o aplicativo real;
- o Linux com interface ou hardware, e o Linux x86_64;
- a cadeia de atualização no Windows, com o instalador e com a chave de produção. No Mac ela foi medida pela interface
(XCTest de macOS), com um app de teste (bundle-id próprio, perfil descartável, feed local, chave efêmera), partindo do 0.16.0 publicado e do 0.16.1 (o backport), com um servidor da 0.15 (schema 13) e os Perfis 3.3.1: escolher ATUALIZAR no MOD deixou o banco nos mesmos bytes e sem cópia; ao confirmar, saiu uma cópia do schema 13 que passa no integrity_check, ANTES de o banco chegar ao 18 com os Perfis 4.0.0; CANCELAR a travessia no 0.16.1 e VOLTAR antes de hospedar deixaram o banco intacto; a reversão (nos caminhos do 0.16.0 e do 0.16.1) devolveu um banco do schema 13 íntegro, com o mesmo conteúdo do de antes (o mesmo despejo SQL), e não os mesmos bytes. Repetido em 27/10 na build final (com os endereços novos e a interface nova), com o MOD vindo do catálogo oficial assinado servido localmente (os MODs da API 6; os da API 7 ainda não estão no catálogo público);
- a captura do microfone no Safari do simulador do iOS: ali o
getUserMedianão entrega amostras (mesmo sem eco,
supressão e ganho, e sem o SEELE), e a faixa cai aos 20 s. Foram medidos ali o encerramento (desligar, sair da página, fechar o Safari: nenhuma faixa fica viva) e que a página não diz «áudio ligado» com uma faixa morta. Sair da sala de voz solta o microfone, e entrar de novo na mesma página abre outro, com a voz voltando (medido em 27/10, no app do navegador instalado no simulador, com uma entrada silenciosa de teste no lugar do microfone). O R8 passou na volta do fundo durante a queda e no ciclo sair/entrar, com pulsos novos e zero faixas ao sair; a queda sem volta passou no R7;
- o atraso acústico da voz, e o atraso absoluto. Do Windows ao app do navegador instalado no simulador do iOS (um
emissor de pulsos sintéticos, sem microfone, até a saída do processamento da página, antes do alto-falante), os pulsos chegaram todos, em ordem, sem perda nem salto, em rodadas de 1 e 2 minutos e numa de uma hora (1798 de 1798, com a fila do receptor limitada entre 20 e 160 ms). O atraso absoluto e a tendência dele na hora NÃO são afirmados: a hora de cada máquina, medida pelo NTP antes e depois, tem incerteza maior que o que se queria medir, e o relógio do Windows andou cerca de 79 ms na hora em relação à hora certa;
- a chamada longa com interface e hardware, e o DSP. Do hardware foram
medidos o smoke de 3 s (os callbacks abertos, 2496 underruns, sem erro de stream) e o ritmo de 10 min acima, e nenhum dos dois é uma chamada.
Medido na build final do Mac:
- 900,890 s de áudio sintético nos dois sentidos no aplicativo nativo: as
181 amostras do app e os 180 agregados do outro participante avançaram. As 21 capturas do palco cobriram 903,789 s, com mudança na área de vídeo entre cada par adjacente. A inspeção confirmou barras e quadrado em movimento, inclusive depois de abrir CONFIGURAÇÕES e voltar, sem pedir para assistir de novo. SAIR, com um clique, terminou fora da sala, com zero aparelhos de áudio sintéticos abertos e bitrate zero; o perfil real ficou intacto. São aplicativo e decodificação reais com áudio e vídeo sintéticos: a continuidade do áudio foi medida na resolução de 5 s e o vídeo por capturas, não quadro a quadro. Não mede latência acústica, DSP ou microfone físico, 5G final nem instalador de produção.
Corrigido nesta rodada:
- SAIR e COMPARTILHAR respondem durante a atualização da chamada no Mac:
o texto dos botões não é mais substituído quando continua igual. O clique atravessando um redesenho foi medido no WebKit, com mutante, e o smoke nativo confirmou a saída da sala e o fechamento do áudio;
- o microfone que continuava aberto ao sair da voz: a saída libera a captura,
sem confundir uma sala transitória vazia durante a reconexão com uma saída;
- AJUSTES no celular: a recusa ao listar saídas de som, o índice vazio ao
voltar de ÁUDIO (CSS) e a navegação excluída da acessibilidade por uma declaração modal indevida. O teste Xcode AJUSTES6 passou em 92,974 s: dispositivos e controles, índice, volta ao servidor, voz e SAIR sem faixas. Chromium e WebKit também passaram na regressão e nos mutantes;
- a voz que ficava muda depois de voltar ao servidor (a partida pelo relógio
da máquina, com a âncora por processo, no nativo e na web);
- a voz velha depois de reconectar: a fila do enlace acumulava até cerca de 5 s
de voz antes de a Voice abrir, e o app a despejava no jitter. A fila preexistente passa a ser descartada no começo do pipeline. Sem o reparo, o teste de conformidade novo falhou (616 de 901 blocos com som, cauda de 2,3 s); com ele, 900 de 900, e no Mac nativo a medida de 3 min acima;
- a voz depois de uma pausa da máquina, no jitter: o corte da rajada, o pulo do
buraco vencido e o descarte do passado, com testes;
- a tela que sumia ao voltar a uma vista depois de passar por outra: o palco é
restaurado;
- a vista pessoal, aberta fora de uma sala, mostrava uma grade vazia e
escondia ENTRAR e DESLIGAR; agora mostra o painel de fora pela ocupação real;
- a fila de criações por IP: o balde passou a contar só os apertos
incompletos, e a devolução vem depois do try_send;
- a legenda «ninguém compartilhando» com a tela viva, corrigida na FFI e no
retrato, com testes e reversões; e o banner PRIMEIRO CONTATO com a impressão de outra sessão, corrigido na UI, com o guarda estado-por-sessao.cjs. Os dois sem nova observação nativa registrada;
- o aviso «Não foi possível conferir os MODs: disconnected», que vinha de um
pedido de uma geração anterior: o erro e o sucesso tardios de outra geração são descartados, com teste;
- a leitura de tela abortada, e o quadro e o som de uma leitura velha;
- o RUSTSEC-2026-0387: o DTLS passou a usar o backend aws-lc-rs do dimpl, e a
cadeia crypto-bigint e elliptic-curve saiu.
Sobre o guia da API 7 dos MODs: o guia interno, api/README.md neste repositório, foi conferido com o código (APIS_ACEITAS, APIS_POR_LINHA, a capacidade acoes, as recusas). O guia externo, o do indexador, vive em outro repositório. Ele foi atualizado localmente, no repositório dele, para a API 7, a linha 2 e a 0.17, mantendo a API 6 e as linhas legadas, e conferido contra os contratos, o código e os testes focados do guia (não foi uma auditoria integral do indexador): o teste do guia em Python passa e o em Node também. Nada foi publicado, e o exemplo do contador segue na API 6, de propósito. Nenhum dos dois diz que a 0.17 foi publicada.