v0.10.0 — três consertos de segurança que não estão no ar, e o servidor MCP¶
Release de development para main, e não hotfix. main e produção estão na v0.9.2
(/version responde 0.9.2); development está 37 commits à frente. Merge commit, nunca squash
(AGENTS.md §12, L83), e back-merge de main para development depois, também por merge
commit, para que o commit da release volte à integração (L92).
Proposta em 2026-09-27. Decisão da pessoa mantenedora no mesmo dia: levar produção pela
release inteira, e não por um hotfix de cada conserto, porque ela carrega três consertos de
segurança que não estão no ar (N5, H2-R e #989). Segurança vem primeiro (AGENTS.md §14.0):
exposição ativa em produção entra na primeira release possível, e esta é a primeira. O momento
do delivery é da pessoa mantenedora: todo merge em main é deploy.
A versão, e por quê¶
v0.10.0, MINOR. A release entrega capacidade que não existia: um agente com o token da API
passa a perguntar sobre uma equipe por POST /mcp, com quatro ferramentas. Nada do que a API
prometia a quem tem alcance deixa de valer.
| Grau | Carrega? | Por quê |
|---|---|---|
| MAJOR | não | nenhum contrato legítimo quebra. A única resposta que muda de forma é a de quem o veredito recusa, e o que ela carregava era o próprio defeito. A decisão está em O contrato da API para quem o veredito recusa, abaixo |
| MINOR | sim | o servidor MCP (spec 062): rota nova, quatro ferramentas, docs/api/mcp.md. Funcionalidade nova, sem quebra |
| PATCH | também, e absorvido | os três consertos de segurança e o #941 sozinhos seriam PATCH. Numa release que carrega MINOR, o PATCH não sobe o número por conta própria |
mix.exs já diz 0.10.0, e não foi tocado por esta nota.
A exceção à regra de que só aceito embarca, e fica registrada¶
Não existe registro de aceitação da 062. docs/sprints/034-servidor-mcp/ tem só o
sprint-backlog.md: nenhum aceitacao.md, nenhum sprint-review.md. Pela regra deste papel, a
062 não compõe release.
Ela embarca por decisão da pessoa mantenedora de 2026-09-27, e a razão registrada é de
segurança, não de valor: levar os três consertos já. A alternativa seria reverter a 062 em
development ou abrir um hotfix por conserto a partir de main; o custo dela não foi medido, e
a observação de que o #981 carrega junto a parte de segurança da 062 (a US3 e o A3) é leitura da
descrição do PR, não medição. Então:
- a 062 está no ar, e não aceita. Isso é diferente de recusada, e diferente de aceita;
- a aceitação dela é ato pendente, a fazer contra os critérios de
specs/062-servidor-mcp/spec.md, e o que se puder medir em produção só se mede com token de conta: pelo registro de 2026-09-24, o lado autenticado é não medível pelos agentes, e fica "não medível", nunca "aceito"; - a aplicação não deve anunciar a 062 como entregue enquanto a aceitação não existir. Hoje a superfície de anúncio não existe (ver Depois do merge), e por isso a restrição não custa nada nesta release, mas fica dita para a primeira que a tiver.
Os três consertos de segurança¶
Os três vêm do mesmo exercício: o inventário de segurança feito antes da 062
(docs/seguranca/2026-09-24-inventario-antes-do-mcp.md), porque o servidor MCP reusa a porta do
token e serve a outro modelo o dado sobre pessoas. Dois deles o inventário classificou como
bloqueantes da 062, e por isso entram na mesma release que ela, e antes dela nesta nota.
#945 — suspender uma organização passa a cortar também os tokens da API dela (achado N5)¶
O que entrega: a porta do token (ApiAuth.com_tenant/2) passa a conferir tenant.status,
como as três portas de sessão já conferiam desde o #837. Token de organização suspensa é recusado
com o mesmo corpo das outras recusas (SC-003), e o motivo organizacao_suspensa vai ao log
(SC-004). Guarda: test/the_band_web/api/organizacao_suspensa_test.exs.
O que estava no ar, desde a v0.9.0: suspender uma organização derrubava a sessão e recusava a
entrada pela tela, e não tocava nos tokens. Medido no inventário: o token responde 200, a
organização é suspensa, e o mesmo token segue respondendo 200 em GET /api/v1/people. Toda
pessoa da organização suspensa com token emitido continuava lendo pessoas, equipes, medidas,
projetos e sincronizações até o token vencer, ou nunca, para o token sem expiração. Quem
suspendesse acharia que suspendeu. Severidade alta.
O que o conserto não desfaz: o que foi lido depois da suspensão já foi lido. A pergunta que importa é se há organização suspensa em produção, e o inventário registra que isso não foi lido (item 3 das suas limitações). Para rodar em produção:
-- Leituras por token feitas por organizações que hoje estão suspensas.
-- A base não guarda QUANDO a organização foi suspensa: tenants tem status, e não suspended_at.
-- O updated_at do tenant é só um teto aproximado: ele muda com qualquer alteração do registro.
SELECT t.id AS tenant_id, t.updated_at AS alterado_em,
r.token_public_id, r.route,
count(*) AS leituras, min(r.occurred_at) AS primeira, max(r.occurred_at) AS ultima
FROM api_access_reads r
JOIN tenants t ON t.id = r.tenant_id
WHERE t.status = 'suspended'
GROUP BY t.id, t.updated_at, r.token_public_id, r.route
ORDER BY ultima DESC;
Nenhuma linha: nenhuma organização suspensa leu por token, e o N5 fica sem consequência. Com linhas: as leituras posteriores à suspensão foram indevidas; a data exata da suspensão não está na base e precisa vir de quem suspendeu.
#946 — o perfil escrito pelo modelo passa a seguir o veredito, na tela e na API (achado H2-R)¶
O que entrega: o perfil que o modelo escreve sobre uma pessoa (forças, evolução, "atenção") e
as competências contadas que saem dele passam a seguir o mesmo veredito pode_ver/3 do painel de
trabalho, nas três portas. Decisão da pessoa mantenedora de 2026-09-24: o perfil é agregado,
e virou linha na tabela da FR-024 da 045.
| Porta | Antes | Depois |
|---|---|---|
tela /people/:id |
a seção #profile para qualquer conta do tenant |
só com alcance; sem ele, o perfil nem é lido, e o evento gerar_perfil é recusado no handler |
GET /api/v1/people/:id |
profile sempre |
profile é null sem alcance, e a nota diz recusa, não "nenhum perfil gerado" |
GET /api/v1/people |
competencies de todas as pessoas da página |
só das pessoas alcançadas, com o alcance da página numa só chamada (pessoas_alcancadas/2, L38) |
O que estava no ar: qualquer conta autenticada do tenant lia, na página de qualquer pessoa, o
texto que um modelo escreveu sobre ela; e qualquer token lia as competências contadas de todas.
Medido na tela no inventário (conta member sem elo, {:nao, :sem_elo_declarado}, as marcas do
perfil visíveis); lido, não medido, na API. Severidade alta. Desde quando está no ar não foi
medido nesta nota: é desde que a seção #profile existe na página da pessoa. Nenhum dado de
outro tenant: o alcance era o tenant inteiro.
O que o conserto não desfaz: quem viu, viu. O rastro é o mesmo do #989, abaixo, porque a
porta é a mesma página e a mesma rota: o evento painel recusado marca cada conta que abriu a
pessoa sem alcance, e naquele momento o perfil estava na tela. Para a listagem, a consulta em
api_access_reads com route = '/api/v1/people' lista os tokens que a leram; quais pessoas
estavam na página de cada leitura não fica gravado (target_id só existe na rota de detalhe), e
isso fica dito.
Muda uma tela em uso sem protótipo novo: a seção some para quem não alcança, e a recusa que aparece ao lado é a da seção Work, já aprovada. Nenhum elemento novo foi desenhado.
#992 — as mudanças e as discussões de uma pessoa passam pelo veredito (issue #989)¶
O que entrega: quem o veredito recusa deixa de ver, na página da pessoa e em
GET /api/v1/people/:id, os títulos dos PRs dela e as issues em que ela comentou. A identidade e
a proveniência continuam visíveis a todo o tenant. Quem tem alcance vê o mesmo de antes.
Decisão da pessoa mantenedora de 2026-09-27: PRs e discussões de que a pessoa participou são
trabalho, e não identidade.
O que estava no ar, desde a v0.6.x (#430, 2026-08-18): a página da pessoa tem uma seção, Where this came from, que fica fora do painel que o veredito protege. Ela devia ter só a proveniência — de onde a pessoa veio, com que identificador, desde quando —, mas carregava também duas listas que são trabalho:
- Changes: os títulos dos PRs que a pessoa abriu, revisou e integrou, e os commits;
- Discussions they took part in: as issues em que ela comentou, com o título.
As duas eram carregadas para qualquer conta autenticada do tenant. Quem a tela recusava via o
painel fechado e, logo abaixo, os títulos. A API repetia a exposição de propósito:
GET /api/v1/people/:id devolvia changes e discussion_participation a quem o veredito
recusava, "porque na tela também estão fora". Não há dado de outro tenant: o alcance era o
tenant inteiro, contra o que a pessoa mantenedora decidiu em 2026-08-26 (FR-012 da 023: a própria
pessoa, a liderança declarada, o escopo e a administração).
Achado pela avaliação de segurança da feature 069, parte 2, como achado lateral, e medido em
2026-09-26 com uma sonda: conta recusada com {:nao, :sem_elo_declarado}, título do PR visível,
seção de trabalho escondida.
Por que nenhum teste pegava: havia um teste, e ele exigia a exposição
(person_detail_test.exs, "discussões e mudanças continuam vindo para quem o veredito
RECUSA"), e conferia só is_map, sem dado povoado: não teria como ver um título vazar.
| Porta | Antes | Depois |
|---|---|---|
tela /people/:id |
as duas listas carregadas e desenhadas para todos | carregadas só com o veredito (se_pode), e os dois blocos só aparecem com @ve_o_trabalho? |
API GET /api/v1/people/:id |
changes e discussion_participation sempre |
null quando access.can_see_work é false, como work |
O contrato da 061 (specs/061-api-publica/contracts/api-v1-people.md) e o esquema OpenAPI foram
emendados no mesmo PR: os dois campos são nullable, com a razão escrita.
A evidência: test/the_band_web/trabalho_dentro_do_veredito_test.exs, cinco testes, as duas
portas, com um PR e uma discussão de títulos únicos. A conta recusada não vê nenhum dos dois; o
admin vê os dois, e é isso que prova que o refute não é vazio. Defeito injetado: a tela de
main no lugar da corrigida reprova 1 de 5 ("a tela mostrou o PR a quem o veredito recusa"); a
API de main reprova 1 de 5 (changes não é null). Restaurado das cópias conferidas, os 5
passam.
O que o conserto não desfaz: quem pode ter visto¶
Vale para o #992 e para o #946, que expunham na mesma página e na mesma rota.
O título que já foi visto não volta, nem o perfil. O que se pode saber é quem viu, e as duas portas deixam rastro:
- Toda visualização recusada gerou o evento
painel recusadono log da aplicação, nívelwarning, comuser_id,tenant_id,alvo_person_ide o motivo. Na tela e na API, o evento é emitido exatamente no caso que expunha os títulos. Buscar no log de produção:
Cada linha é uma conta que abriu a página, ou a rota, de uma pessoa que não podia ver. Se a pessoa tinha PR ou discussão coletados, a conta viu os títulos; se tinha perfil gravado, viu o perfil.
- Na API, cada leitura concedida pelo token fica em
api_access_reads, desde a v0.9.0. A consulta abaixo lista os tokens que leram/people/:id. Cruzando otarget_idcom as linhas do log acima, sabe-se quais credenciais receberam os títulos:
SELECT r.token_public_id,
r.target_id AS person_id,
count(*) AS leituras,
min(r.occurred_at) AS primeira,
max(r.occurred_at) AS ultima
FROM api_access_reads r
WHERE r.route = '/api/v1/people/:id'
GROUP BY r.token_public_id, r.target_id
ORDER BY ultima DESC;
O que não se sabe: a retenção do log de produção não foi medida. Se ele guarda menos que desde 2026-08-18, as visualizações de antes do corte ficam sem rastro, e isso fica dito.
As buscas rodam em produção, e são ato de quem opera: o agente deploy-producao ou a pessoa
mantenedora. Nenhum agente desta sessão acessa produção.
O servidor MCP (spec 062)¶
O que a pessoa passa a conseguir fazer: ligar um agente de IA ao The Band com o token da API
que já emite em /api-tokens, e perguntar a ele sobre uma equipe — quem está nela, o que cada
pessoa tem aberto, quanto o trabalho espera por revisão e o que está parado —, recebendo em cada
resposta a ressalva no mesmo objeto: a composição, a janela, a origem, a regra com versão, as
limitações e as interpretações erradas, lidas da base de conhecimento, e a data da coleta. O
agente vê exatamente o que a pessoa dona do token veria na tela e na API, e nada além.
Embarca sem aceitação registrada: ver A exceção à regra de que só aceito embarca, acima.
A superfície nova: POST /mcp, na pipeline [:api, :api_autenticada] do router, a mesma de
/api/v1. Documentada para quem integra em docs/api/mcp.md.
#944 — o plano da 062 passa a descrever o código que existe¶
O que entregou: antes de uma linha de implementação, o plano deixou de mandar criar um registro de leitura e um limite que a 061 já tinha, e passou a tratar os dois defeitos que o reuso traria. Trouxe junto o inventário de segurança de 2026-09-24, de onde saíram o N5 e o H2-R. Só documentação.
#977 — a biblioteca do protocolo entra, fixada, com a exceção do cowlib guardada¶
O que entregou: {:ex_mcp, "== 1.5.0"} e, em mix.exs,
hex: [ignore_advisories: ["EEF-CVE-2026-43966", "EEF-CVE-2026-43969"]]. A exceção cobre as duas
advisories do cowlib que a ex_mcp traz, com a medição de alcance em
specs/062-servidor-mcp/r3-cowlib-alcance.md e as guardas em
test/the_band/cowlib_inalcancavel_test.exs, que reprovam se qualquer premissa da exceção cair.
Abriu o sprint 034 (sprint-backlog.md e 30 issues). Nenhuma rota, nenhuma tela.
#979 — a fundação do contexto MCP¶
O que entregou: lib/the_band/mcp/ com Ferramentas, Envelope e Ausencia (T002);
KnowledgeBase.measurement/1, de onde o envelope lê as ressalvas (T003); os três estados da
ausência — checked, not_checked, refused —, e nenhum dos dois de ausência sai com 0
(T005, SC-002); a guarda de que nenhum módulo do contexto fala com Repo, Ecto.Query ou
Ecto.Adapters.SQL (T008). Nada alcançava o usuário ainda.
#981 — o servidor MCP responde em /mcp, com a ressalva no mesmo objeto¶
O que entregou: as quatro ferramentas (team_roster, team_open_work, team_review_wait,
team_stale_work) com dado real, pelos mesmos contextos da 061, e a parte de segurança da
062, que é a maior do PR:
- caminho único por chamada: argumento fechado, equipe carregada no tenant, veredito, só então ferramenta (R6);
- lista fechada de métodos JSON-RPC antes da biblioteca, e nada abre stream (R4);
- a leitura gravada no ponto do veredito, com ferramenta e equipe (R1), e um limite só por
token:
/mcpe/api/v1gastam o mesmo contador (FR-026); - texto de terceiro marcado no schema como
untrusted_text, com os caracteres invisíveis sinalizados, e nenhuma ferramenta busca URL (A3); - a resposta inteira varrida: nenhum segredo, e-mail nem
platform_access_level(SC-005).
Toca código da 061 em produção, e fica dito: a recusa de equipe passa a deixar rastro nas três
portas (N6), inclusive em /teams/:id, onde a recusa da quebra por pessoa passa a ser registrada
no log sem mudança visível; o ApiReadLog pula o /mcp para não gravar duas vezes.
#986 — paridade das três portas, e o token revogado cai na chamada seguinte¶
O que entregou: prova de que a tela, a API e o MCP dão o mesmo veredito de acesso a uma equipe, nos quatro caminhos de concessão e na recusa; de que sem alcance as quatro ferramentas recusam com razão, nunca com lista vazia; e de que um token revogado é recusado na chamada seguinte, sem reiniciar nada (062/US2, T017–T019). Só teste.
#988 — fecha a 062: o que não responde, quanto custa, e um cliente real¶
O que entregou: prova de que as quatro ferramentas declaram o que não respondem, de quanto
custam contra a rota HTTP, e de que um cliente MCP real (o SDK oficial de Python) as usa de ponta a
ponta (T015, T028–T031); e docs/api/mcp.md, para quem vai ligar um agente.
O resto que embarca¶
#941 — o botão de copiar passa a copiar, e o estado do token fala inglês¶
O que entregou: em /api-tokens, o botão Copy value passa a copiar o valor, e a dizer
quando não consegue; a coluna state passa a imprimir active / revoked / expired em vez de
"ativo" / "revogado" / "expirado". Os dois defeitos estão no ar desde a v0.8.0. Muda tela em
uso, na direção do que o protótipo aprovado já dizia.
#942 — a régua da tela de tokens ganha guarda (061)¶
O que entregou: só teste. A conferência de QA achou que o SC-013 da 061 — o hash do token não aparece no HTML — era declarado conforme por um teste que não afirmava nada: com o hash injetado em cada linha, os 84 testes ficavam verdes. O teste passa a reprovar com o defeito injetado. Nada muda em produção.
#980 — segurança vem primeiro, e o CLAUDE.md¶
O que entregou: a decisão de 2026-09-25 escrita em AGENTS.md §14.0 e no CLAUDE.md novo,
que importa o AGENTS.md e passa a ser carregado em toda sessão de agente. Só documentação.
#982 — o roster deixa de devolver e-mail (já em produção pela v0.9.2)¶
Já está no ar: foi a produção pelo hotfix v0.9.2 (#984), e o back-merge o trouxe de volta a
development. Entra nesta lista só como registro; esta release não muda nada nele. O
registro completo, com a consulta de quem pode ter lido, é docs/releases/v0.9.2.md.
#983 — o relatório da pessoa e da equipe entra no backlog¶
O que entregou: o registro do pedido de relatório em HTML ou PDF, gerado a partir das duas telas, e das decisões que vêm antes. Ainda não é spec, e nada dele chega a quem usa.
Os três riscos medidos¶
Medidos em 2026-09-27 sobre origin/main..origin/development, com a árvore limpa.
| Risco | Veredito | Medido como |
|---|---|---|
| migração destrutiva | nenhuma migração | nenhum arquivo em priv/repo/migrations/ entre origin/main e origin/development. O ensaio de restauração não é pré-condição desta release |
| variável obrigatória nova | nenhuma | .env.example sem variável nova; compose.yaml e config/runtime.exs sem mudança. O Dokploy não precisa de configuração nova |
| mudança em tela em uso | sim, em três telas, e numa rota da API | ver a tabela abaixo |
| Superfície | O que muda | Para quem |
|---|---|---|
/api-tokens |
o botão de copiar passa a copiar; o estado sai em inglês (#941) | todos que emitem token |
/people/:id |
o perfil escrito pelo modelo (#946) e os blocos Changes e Discussions they took part in (#992) somem | só para quem o veredito recusa; quem tem alcance vê o mesmo |
/teams/:id |
a recusa da quebra por pessoa passa a ser registrada no log (#981, N6) | nenhuma mudança visível |
GET /api/v1/people/:id |
profile, changes e discussion_participation passam a null |
só para token sem alcance sobre a pessoa |
GET /api/v1/people |
competencies só das pessoas alcançadas (#946) |
só para as pessoas fora do alcance do token |
POST /mcp |
rota nova (062) | quem liga um agente |
Dependência nova, e fica dita porque é o quarto risco que esta release traz: ex_mcp == 1.5.0,
com uma exceção num gate de segurança (mix hex.audit) para as duas advisories do cowlib.
É risco residual aceito, e não falso positivo, e cumpre o que o §14.0 exige de exceção: a
medição (r3-cowlib-alcance.md), a decisão da pessoa mantenedora de 2026-09-24 (escrita no
comentário ao lado da exceção, em mix.exs), e a guarda que a derruba quando a premissa cai
(cowlib_inalcancavel_test.exs): o endpoint deixar de ser Bandit, um listener Cowboy ser
iniciado, algum código chamar :cow_* ou gun, ou a ex_mcp mudar de versão.
O contrato da API para quem o veredito recusa¶
A pergunta: GET /api/v1/people/:id passa a devolver profile, changes e
discussion_participation como null para token sem alcance sobre a pessoa, e
GET /api/v1/people deixa de trazer competencies das pessoas fora do alcance. Para quem integra
sem alcance, a forma da resposta muda. Isso torna a release MAJOR?
Decisão: não. É conserto, e a release fica MINOR. As razões, em ordem de peso:
- O que a resposta carregava para quem não tinha alcance era o defeito, e não uma garantia. O contrato da 061 devolvia os dois campos ao recusado "porque na tela também estão fora": ele copiava a exposição da tela, e a exposição da tela contrariava a FR-012 da 023, decidida em 2026-08-26, que é quem define quem vê trabalho de uma pessoa. Semver protege o que o produto promete a quem o usa; não protege o acesso a dado que a regra de acesso já negava. Chamar isto de MAJOR seria declarar o vazamento como funcionalidade;
- quem tem alcance recebe exatamente a mesma resposta. Nenhum campo muda de tipo, de nome ou de significado para o uso legítimo da rota;
- o sinal já estava na resposta.
access.can_see_workjá existia, eworkjá eranullquando ele éfalse;profileecompetenciesjá podiam sernull(nenhum perfil gerado). Um cliente que lê a resposta como documentada já tratanullnesses campos. O que muda é quechangesediscussion_participationpassam a seguir o mesmo sinal quework, e a nota diz recusa, não ausência; - o contrato foi emendado no mesmo PR que mudou o código: o
api-v1-people.mdda 061 e o esquema OpenAPI declaram os camposnullable, com a razão (#946, #992). Não há divergência silenciosa entre o que a documentação promete e o que a rota faz.
O que fica dito, porque é verdade mesmo sem ser MAJOR: um integrador que lia changes ou
discussion_participation com um token sem alcance, e não tratava null, vai quebrar depois
do merge. Isso é consequência pretendida: ele lia o que não devia. Se houver token nessa situação,
a consulta de Quem pode ter visto o mostra, e a conversa com quem o emitiu é a mesma da
exposição.
E, por completude: a série é 0.x. Pela semver, antes da 1.0.0 a API pública não é estável, e
nem uma quebra real obrigaria o salto para 1.0.0. A decisão acima não se apoia nisso: as notas
de release desta casa aplicam a tabela MAJOR, MINOR e PATCH à 0.x como se fosse estável
(ver v0.9.2.md), e é por essa régua que a mudança
não é MAJOR.
O que esta release não carrega¶
O que alguém pode esperar ver nela, e não está:
| O quê | Onde está | Por que alguém esperaria, e o que fica |
|---|---|---|
| a 069: localizar pessoa e o trabalho aberto dela pelo MCP, e o espelho das oito rotas da API | branch 069-mcp-busca-de-pessoas, 4 commits à frente de development, só documentação (spec e avaliação de segurança), sem PR aberto |
é a continuação da 062, e foi dela que saiu o #989. O MCP desta release só responde sobre equipes: nenhuma ferramenta busca pessoa |
#991: GET /api/v1/people/:id diz a qualquer conta do tenant se a pessoa tem conta na plataforma |
issue aberta, label de segurança | é da mesma rota do #992, e quem ler esta nota pode supor que o #992 fechou tudo nela. Não fechou: o dado de que a pessoa tem conta continua saindo para todo o tenant. Não é dado de outro tenant |
#987: team_open_work declara is_composed: false para equipe composta |
issue aberta | é defeito de uma ferramenta que esta release publica. Está no ar com o defeito: para equipe composta de outras, a ressalva de composição que a ferramenta devolve está errada. Medido em 2026-09-25 com o SDK oficial de Python, na LEDS - ConectaFapes de dev: o team_roster conta 48 membros (31 diretos e 17 via partes), e o team_open_work conta 31 e declara is_composed: false. Quem lê a resposta de uma equipe composta deve saber disso |
#985: a cláusula vinculo_vigente de pode_ver_equipe/3 nunca é alcançada, e quem pertence é registrado como escopo de equipe |
issue aberta | o veredito de equipe que as três portas usam, inclusive o /mcp. O resultado da concessão não muda (quem pertence continua vendo), e o motivo registrado está errado: o log e a leitura gravada dizem "escopo" onde é "vínculo". A paridade do #986 prova o mesmo veredito nas três portas, e não prova o motivo certo |
| a aceitação da 062 | não existe | ver A exceção à regra de que só aceito embarca |
| a superfície que anuncia a versão na aplicação | não existe | a página do The Band não diz qual versão está no ar nem o que ela trouxe; só a rota /version, que é endpoint e não página. Lacuna aberta desde a v0.9.1 |
Os efeitos do #987 e do #985 foram medidos: o #987 com o cliente Python real (a própria issue traz a tabela), e o #985 pela paridade de test/the_band_web/mcp/paridade_test.exs, que fixa a razão escopo_de_equipe no caso do vínculo vigente.
Depois do merge¶
A ordem, e de quem é cada passo. Nenhum agente desta sessão acessa produção.
- o CD publica e entrega: o merge do PR de release em
maindispara o workflow, que cria a tagv0.10.0, publicaghcr.io/the-band-solution/theband:v0.10.0e chama o webhook do Dokploy. Ninguém builda, tagueia nem publica à mão; - a versão no ar, conferida pela origem e não pelo
mix.exs:
Enquanto responder 0.9.2, os três consertos não estão no ar, e nada abaixo começa;
3. o agente deploy-producao acompanha a entrega e confere a saúde depois dela;
4. as buscas de quem pode ter visto, em produção, pelo deploy-producao ou pela pessoa
mantenedora:
- N5: a consulta de leituras por token de organização suspensa;
- H2-R e #989: o evento acesso: painel recusado no log, e a consulta de /people/:id em
api_access_reads, cruzadas pelo alvo_person_id;
- a retenção do log de produção, medida, porque sem ela não se sabe o que a busca alcança;
- resultado registrado nesta nota, em O que se observou depois, com linha ou com "nenhuma
linha", e nunca omitido;
5. o agente aceitacao-em-producao mede o que é medível sem conta: /version e o lado
anônimo. /mcp, /people/:id, /api-tokens e /teams/:id são autenticados, e ficam
não medível, nunca "aceito" (registro de 2026-09-24);
6. back-merge de main para development, por merge commit (L92).
A pergunta que fecha a release, e a resposta de hoje:
| Pergunta | Resposta |
|---|---|
| a aceitação está confirmada? | não para a 062, que embarca por exceção registrada; os consertos de segurança têm guarda com defeito injetado (#992) ou teste de cenário (#945, #946) |
| o CI está verde no PR de release? | a conferir no PR, pelo código de saída |
| a página anuncia esta versão? | não, e a superfície não existe. Quem usa a aplicação não será informado de que as seções da página da pessoa mudaram |
O que se observou depois¶
A preencher depois do delivery: a data do merge, a resposta de /version, e o resultado das
buscas do passo 4.