0057 — A mensalidade da garantia: uma faixa por tipo de tomador, escolhida na aprovação¶
| Status | CONCLUÍDA |
| Branch | spec/0057-taxa-da-mensalidade |
| Criada em | 2026-10-12 |
| Apps afetados | api · web · e2e |
| Revisão do problema | aprovada na rodada 1 |
| Revisão da experiência | aprovada na rodada 1 |
| Revisão do detalhamento | aprovada na rodada 1 |
| Revisão da implementação | aprovada (fases e branch) |
Status:
RASCUNHO→APROVADA→EM IMPLEMENTAÇÃO→CONCLUÍDA
A spec tem três partes, escritas em ordem, e quatro portões — cada um revisado por um subagente de contexto limpo, em até 3 rodadas. A máquina de revisão é do plugin superpowers; a régua é a rubrica correspondente em .claude/rubrics/. Achados vêm classificados: qualquer Critical reprova, Important em aberto reprova salvo decisão registrada do usuário, e Minor vira pendência aceita.
- A Parte I diz qual é o problema e como se convive com ele hoje. Revisada na seção 6 (necessidade × jornada de hoje). É o portão mais barato de todos, e o único que pergunta contra que problema isto está sendo construído.
- A Parte II diz como se usa o que vai existir. Revisada na seção 8 (jornada × viewports).
- A Parte III diz como se constrói. Revisada na seção 16 (segurança × clareza técnica) — autorização, isolamento, e se sobrou decisão para quem vai codar.
- A implementação é medida contra as três, na seção 17 (aderência × qualidade × testes) — uma revisão por fase, e uma da branch inteira antes de fechar.
Cada parte só se escreve depois que a anterior passou. Descrever tela sobre problema mal enquadrado, ou detalhar endpoint sobre experiência vaga, é o jeito mais caro de descobrir que era outra coisa.
Parte I — O problema¶
Aqui não entra solução: nem tela, nem endpoint, nem botão. Só o que dói, para quem, e o que se faz hoje. Se você já sabe qual é a tela, guarde para a Parte II.
1. Dor¶
A mensalidade da garantia — o que o inquilino paga todo mês pela garantia do aluguel — é decidida caso a caso no negócio, e o sistema só sabe cobrar um número para todo mundo.
A mensalidade é um percentual sobre o Pacote Locatício (aluguel + condomínio + IPTU). A política comercial da garantidora não é um percentual único: é uma faixa, e a faixa depende de quem é o tomador. Para pessoa física a garantidora trabalha entre 8% e 11%; para pessoa jurídica, entre 15% e 18% — o risco de uma empresa inquilina é outro, e o preço também. Dentro da faixa, quem decide o percentual de cada garantia é o analista, no momento em que aprova a análise de crédito, olhando o caso.
O que o sistema oferece hoje não permite exercer essa política:
- A garantidora tem uma faixa só, sem distinção entre pessoa física e jurídica. Não há como registrar que PF vai de 8% a 11% e PJ de 15% a 18%: um intervalo único de 8% a 18% deixaria um analista aprovar uma PF a 17% ou uma PJ a 9% sem nada que o impeça.
- O analista não escolhe o percentual ao aprovar. A faixa existe na configuração, e por trás da tela o sistema até sabe receber um percentual na aprovação, conferi-lo contra a faixa e levá-lo à garantia — mas a tela de aprovação nunca ofereceu o campo. Na aprovação ninguém informa percentual nenhum, e toda garantia sai com a taxa padrão da garantidora. Na prática, a faixa configurada não governa nada.
- Não há um momento para rever o número antes do contrato. Entre aprovar a análise e emitir a garantia pode passar tempo — conversa com a imobiliária, ajuste de vigência —, e a mensalidade não pode ser revista nesse intervalo.
- Quem decide não vê o efeito em reais. O percentual é o que o analista escolhe, mas o que o inquilino e a imobiliária discutem é o valor da parcela. Hoje o valor só aparece calculado com a taxa padrão, nunca com a que está sendo considerada.
- Os nomes da configuração confundem o assunto. As configurações têm um bloco chamado "Taxas", que mistura a taxa de garantia com multa e juros por atraso, e outro chamado "Taxas — Analistas", que é a faixa da mensalidade. Quem configura não reconhece ali "a mensalidade de PF" e "a mensalidade de PJ", que é como o negócio fala.
O custo de conviver com isso:
- Não existe taxa padrão que sirva aos dois tipos de tomador. Com uma taxa padrão única, ou a PJ é cobrada abaixo do piso comercial dela (15%), ou a PF é cobrada acima do teto dela (11%) — não há valor único que respeite as duas faixas, porque elas nem se encostam.
- A decisão comercial do analista não tem onde existir. Se o caso pede 9,5%, o sistema emite a 10% e cobra 10% em todas as parcelas; o percentual que a política mandaria aplicar não fica registrado em lugar nenhum, e não há como saber depois qual teria sido.
- O número errado é cobrado o contrato inteiro. A mensalidade é congelada na emissão e vale para todas as parcelas da vigência; um percentual errado no momento da emissão não é um erro de uma parcela, é de doze ou trinta.
2. Quem sente¶
ANALYST, e oADMIN_TENANTquando aprova — é quem decide o preço de cada garantia, e hoje não tem onde decidir. Sente em toda aprovação: escolher a mensalidade é parte do caminho obrigatório de aprovar uma análise, não uma exceção.ADMIN_TENANT, ao configurar — é quem traduz a política comercial (PF 8–11%, PJ 15–18%) em parâmetro, e hoje só consegue registrar metade dela.- O inquilino, indiretamente — é quem paga a mensalidade. Não usa o sistema, mas é ele que recebe a cobrança com o percentual errado. Quando o tomador é PJ, o erro é sistemático, não eventual.
- A imobiliária (
AGENCY_USER,AGENCY_MANAGER), indiretamente — é o canal que apresenta a proposta ao inquilino e, conforme a parceria, cobra a mensalidade junto com o aluguel e repassa. Se o valor que ela comunicou não é o que o sistema emite, a correção passa por ela. Ela não decide a taxa — a decisão é da garantidora.
Alcance: caminho obrigatório. Toda análise aprovada vira, ou pode virar, uma garantia com mensalidade; não há aprovação em que a pergunta "qual percentual?" não exista. Volume não é medido aqui: a garantidora em produção começou a operar em outubro de 2026 e ainda não há histórico de aprovações para contar.
3. A jornada de hoje¶
O gatilho é uma análise de crédito chegando ao analista para decisão.
- O
ADMIN_TENANTconfigurou uma vez a taxa de garantia padrão e uma faixa mínima e máxima. A faixa é uma só, para qualquer tomador. - O analista abre a análise, confere documentos e participantes, e vê o resumo financeiro — calculado com a taxa padrão da garantidora, qualquer que seja o tomador.
- O analista aprova. Na aprovação ele informa parecer, justificativa e a taxa de adesão (spec 0056). Não informa percentual de mensalidade — a tela não tem o campo. A conferência contra a faixa do passo 1 existe no sistema, mas só seria acionada se um percentual chegasse; como nenhum chega, ela nunca roda. ← quebra aqui: é o único momento em que o analista está olhando o caso, e é justamente o momento em que ele não tem como registrar o preço que decidiu.
- Entre a aprovação e a emissão, se a conversa com a imobiliária ou com o inquilino muda o preço, não há o que ajustar no sistema. ← quebra aqui também: o preço só pode mudar mexendo na configuração da garantidora inteira.
- A garantia é emitida com a taxa padrão, e a mensalidade fica congelada para todas as parcelas da vigência.
- As parcelas saem com esse valor. A primeira, no pagamento inicial, e as mensais seguintes, todas com a mesma mensalidade congelada na emissão.
Não há passo fora do sistema: o usuário informou que ninguém ajusta o preço caso a caso — não porque não seja preciso, mas porque não há onde. A política de faixa por tipo de tomador fica no papel.
O que já se tentou: a resposta do usuário em 2026-10-12 é que toda garantia sai com a taxa padrão — ninguém ajusta caso a caso. Não há contorno em uso: nem mudar a configuração antes de emitir e depois voltar, nem planilha paralela. A política de faixa por tipo de tomador existe no negócio e não é aplicada.
O que existe e não se usa: a configuração já tem um mínimo e um máximo (bloco "Taxas — Analistas"), e o texto dele diz que é a faixa que o analista pode aplicar ao aprovar. O caminho por trás da tela também existe: a aprovação aceita um percentual, recusa o que estiver fora da faixa, grava-o na decisão, e a emissão da garantia usa esse percentual no lugar do padrão. O que quebra é a ponta e a forma: nenhuma tela oferece o campo, a faixa é uma só para PF e PJ, não há como rever o percentual depois de aprovar, e não há prévia em reais. Isto importa para o desenho: parte do que a solução precisa já está construída, e a pergunta aberta é o que fazer com a faixa única e com o percentual da decisão quando passarem a existir duas faixas.
O que muda depois do contrato: nada, e isso é desejado. Emitida a garantia, a mensalidade fica congelada; mudar o preço de um contrato vigente exige cancelar e emitir outro. Isto não é dor — é a regra, e precisa continuar sendo.
4. Resultado esperado¶
- A garantidora registra duas políticas de mensalidade, uma para pessoa física e uma para pessoa jurídica, cada uma com seu percentual sugerido e seus limites inferior e superior — e quem configura reconhece os blocos pelo nome do negócio ("mensalidade" e "atraso"), num lugar só.
- Toda aprovação registra o percentual da mensalidade, dentro da faixa do tipo do tomador. O que o analista decidiu é o que o contrato cobra; não existe mais garantia emitida com um percentual que ninguém escolheu.
- Uma PJ nunca sai com a faixa de PF, e vice-versa — é verificável abrindo qualquer garantia emitida: o percentual está dentro da faixa do tipo do tomador.
- O analista vê o valor em reais antes de gravar — muda o percentual e vê a parcela resultante, sem precisar salvar para descobrir quanto deu.
- Entre aprovar e emitir, o percentual pode ser revisto por quem pode aprovar; depois de emitida a garantia, não pode mais — vale para todas as parcelas da vigência.
Como se sabe que resolveu: emitir uma garantia de tomador PJ e outra de tomador PF, cada uma com um percentual diferente do sugerido, e conferir que cada uma cobra, em todas as parcelas, o percentual escolhido — e que um percentual fora da faixa do tipo não passa.
5. Fora de escopo¶
- Mudar a mensalidade de garantia já emitida. Contrato fechado não muda; o caminho é cancelar e emitir outro. Não entra aditivo, nem reajuste, nem renegociação.
- Faixas por imobiliária. A spec 0056 deu à imobiliária uma regra própria de taxa de adesão; foi cogitado fazer o mesmo com a mensalidade e fica de fora — o usuário descreveu a política como da garantidora, por tipo de tomador, e não por canal.
- Mais tipos de tomador que PF e PJ, ou faixa por outro critério (valor do aluguel, tipo de imóvel, score). O cadastro de inquilino tem só os dois tipos.
- Alterar multa e juros por atraso. Eles mudam de lugar e de nome junto com a reorganização da configuração, mas o comportamento deles (spec 0054) não muda.
- A taxa de adesão. Continua como a spec 0056 deixou; esta spec só põe a mensalidade ao lado dela na aprovação.
- Recalcular garantias já emitidas com os novos parâmetros. As garantias existentes seguem com o percentual com que foram emitidas.
- Quem decide o tipo do tomador. É o tipo cadastrado do locatário principal da análise; corresponsáveis e demais locatários não mudam a faixa. Corrigir um cadastro com tipo errado é edição do inquilino, não desta spec.
6. Revisão do problema¶
Preenchido pelo laço do /spec new, rubrica .claude/rubrics/problema.md. Registrar todas as rodadas, inclusive as reprovadas.
| Rodada | Critical | Important | Minor | Nota | Veredicto |
|---|---|---|---|---|---|
| 1 | 0 | 1 | 1 | 8 | Aprovada |
Resultado: aprovada na rodada 1.
Pendências aceitas: nenhuma. Os dois apontamentos foram corrigidos no texto depois da aprovação: o Important (a jornada dizia que "não há onde" informar o percentual, quando a aprovação já aceita, valida e propaga um percentual por trás da tela — o que quebra é a tela, a faixa única e a falta de revisão e de prévia) e o Minor (o título de uma consequência afirmava uma direção que o texto não sustentava).
Parte II — A experiência¶
Não preencher antes da revisão da seção 6 estar aprovada.
7. Jornada pretendida¶
São três momentos, e cada um responde a um ponto de quebra da seção 3: a garantidora registra as duas políticas (configuração); o analista escolhe o percentual ao aprovar, vendo o valor em reais (passo 3 da jornada de hoje); e quem pode aprovar revê o percentual até a garantia ser emitida (passo 4). Depois da emissão, nada muda — e a tela diz isso.
Os nomes desta parte. Na tela, o percentual se chama mensalidade — é a palavra do negócio, e é como o resumo financeiro já chama o valor em reais ("Mensalidade de garantia"). O percentual que vem preenchido é a mensalidade sugerida; os limites são a mínima e a máxima; o conjunto mínima–máxima de um tipo é a faixa. O tipo do tomador é sempre escrito por extenso na interface ("pessoa física", "pessoa jurídica"), com PF/PJ só onde falta espaço.
Momento A — A garantidora configura as duas políticas¶
- Ponto de entrada: menu Parâmetros (as configurações da garantidora), como hoje.
- Quem: quem já edita os parâmetros hoje (
ADMIN_TENANT). - Jornada, caso feliz:
- Abre Parâmetros. Os dois blocos de hoje — "Taxas" e "Taxas — Analistas" — viraram um bloco só, chamado "Mensalidade e atraso".
- Dentro dele, três grupos, cada um com um subtítulo:
- Mensalidade — pessoa física: sugerida, mínima e máxima (%).
- Mensalidade — pessoa jurídica: sugerida, mínima e máxima (%).
- Atraso: multa (%) e juros de mora (% ao mês) — os mesmos dois campos de hoje, com o mesmo comportamento da spec 0054.
- Preenche, por exemplo, PF sugerida 10%, mínima 8%, máxima 11%; PJ sugerida 16%, mínima 15%, máxima 18%.
- Salva com o botão de salvar dos Parâmetros, como hoje.
- Custo de uso: seis números para a mensalidade, uma vez, quando a política muda. O texto de apoio do bloco diz em uma frase o que eles governam: "A mensalidade é um percentual do Pacote Locatício. O analista escolhe o percentual ao aprovar, dentro da faixa do tipo do inquilino principal; a sugerida é a que vem preenchida."
- Validação, no próprio campo, ao salvar: a mínima não pode ser maior que a máxima, e a sugerida tem de estar entre as duas — a mensagem sai debaixo do campo errado e diz o que corrigir ("A sugerida para pessoa física precisa estar entre a mínima (8%) e a máxima (11%)"). Os três campos de cada tipo são obrigatórios: uma faixa pela metade deixaria a aprovação sem limite.
- O que deixa de existir na tela: a "Taxa de garantia (%)" única e a faixa única. Não há mais um percentual que vale para todo mundo.
Momento B — O analista escolhe a mensalidade ao aprovar¶
- Ponto de entrada: a tela da análise de crédito, no painel do parecer, quando a análise está em análise ou devolvida e quem vê pode decidir — o mesmo lugar onde hoje ficam o parecer, as notas internas e a taxa de adesão.
- Jornada, caso feliz:
- O analista abre a análise. No painel do parecer, logo abaixo da Taxa de adesão (R$), há o campo Mensalidade (%), já preenchido com a sugerida do tipo do inquilino principal.
- Debaixo do campo, uma linha diz de onde o número vem e quanto ele dá: "Pessoa física · faixa de 8% a 11% · R$ 300,00 por mês". O valor em reais é o Pacote Locatício da análise vezes o percentual.
- O analista muda o percentual — digamos para 9,5%. A linha de baixo se recalcula enquanto ele digita, sem salvar nada: "… · R$ 285,00 por mês". O resumo financeiro da mesma tela (bloco "Situação financeira") também passa a mostrar a mensalidade, o total da vigência e o pagamento inicial com 9,5%, para quem rolar até ele.
- Clica Aprovar, no cabeçalho, como hoje. A confirmação de aprovação — que já resume o parecer e a taxa de adesão — ganha a linha "Mensalidade: 9,5% · R$ 285,00 por mês".
- Confirma. A análise fica aprovada com a mensalidade de 9,5%.
- Custo de uso: nenhum, no caso comum — o campo já vem com a sugerida, e aprovar sem tocar nele aprova com ela. Mexe quem quer outro número.
- O que o sistema já sabe e não pergunta: o tipo do inquilino principal (está no cadastro dele), o Pacote Locatício (está na análise) e a faixa (está nos Parâmetros). O analista não escolhe "PF ou PJ" — o tipo vem do cadastro.
- Fora da faixa: se ele digita 12% numa pessoa física, o campo fica em erro na hora, com "Fora da faixa de pessoa física: de 8% a 11%", a linha do valor em reais desaparece, e o Aprovar não confirma: a confirmação mostra o mesmo erro e o botão de confirmar fica desabilitado até o número voltar para a faixa.
- Salvar rascunho, que já existe no painel, guarda parecer e notas como hoje; a mensalidade escolhida se grava na aprovação, junto com a taxa de adesão — é assim que a taxa de adesão já funciona, e as duas se decidem no mesmo gesto.
Momento C — Rever a mensalidade entre aprovar e emitir¶
- Ponto de entrada: a mesma tela da análise, agora aprovada e ainda sem garantia emitida. O painel do parecer, que hoje fica só de leitura depois da aprovação, mostra a linha "Mensalidade aprovada: 9,5% a.m. · R$ 285,00 por mês" com um botão Alterar ao lado. Ela substitui a linha "Taxa aprovada" que o modo leitura do parecer tem hoje — é o mesmo dado, com o valor em reais junto; as duas não coexistem.
- Quem vê o Alterar: quem pode aprovar análises (decisão do usuário em 2026-10-12). Quem vê o parecer sem poder aprovar vê a linha, sem o botão.
- Quem não vê o parecer — a imobiliária (o parecer é deliberação interna da garantidora e continua fechado para ela): vê a mensalidade escolhida em dois lugares, só leitura (decisão do usuário em 2026-10-12): no resumo financeiro do bloco "Situação financeira" da análise, que passa a mostrar a mensalidade com o percentual escolhido em vez do padrão, e, depois da emissão, na tela da garantia, que ela já lê. É o que ela precisa para comunicar o valor ao inquilino. A imobiliária não emite garantia (não tem a permissão de emitir), então o diálogo Emitir garantia não é dela — a resposta do usuário mencionava a emissão sob a premissa errada de que ela emitia, corrigida na Parte III.
- Jornada, caso feliz:
- Quem pode aprovar clica Alterar. A linha vira o mesmo campo do Momento B, já com 9,5%, com a mesma linha de faixa e valor em reais recalculando enquanto digita.
- Muda para 10,5%. Vê "… · R$ 315,00 por mês"; o resumo financeiro acompanha.
- Clica Salvar (ou Cancelar, que volta ao 9,5% sem gravar nada).
- Salvo, a linha volta ao modo leitura com 10,5% e, embaixo, "Definida por Fulana em 12/10/2026 14:32" — quem aprovou e quem alterou podem ser pessoas diferentes, e a tela não pode atribuir a uma o número da outra.
- Na emissão: o diálogo Emitir garantia já mostra a taxa que vai ser congelada (hoje "Taxa"); passa a mostrar "Mensalidade: 10,5% · R$ 315,00 por mês", só leitura — o diálogo de emissão não vira um segundo lugar de decidir o preço. A frase abaixo do valor depende de quem emite: para quem pode aprovar, "Para mudar, cancele e use Alterar no parecer."; para quem emite sem poder aprovar (o operador), "Definida pela garantidora na aprovação. Se o valor não é o combinado, fale com a garantidora antes de emitir." — nunca uma instrução para um botão que a pessoa não vê.
- Depois de emitida a garantia: o botão Alterar some. A linha fica só de leitura, com o texto "Garantia emitida — a mensalidade vale para todas as parcelas e não muda mais. Para outro valor, a garantia precisa ser cancelada e uma nova emitida." A tela da garantia mostra o percentual com que ela foi emitida, como já mostra hoje.
Análises que já estão aprovadas quando isto entrar no ar¶
Uma análise aprovada antes desta feature e ainda sem garantia não tem mensalidade escolhida. No painel do parecer ela aparece como "Mensalidade: não escolhida na aprovação — será usada a sugerida para pessoa jurídica (16%) · R$ 480,00 por mês", com o mesmo Alterar do Momento C. Ou seja: passa a valer a política nova, e quem pode aprovar ainda pode ajustar antes de emitir (decisão do usuário em 2026-10-12). Garantias já emitidas não mudam.
7.1 Desktop¶
Parâmetros — bloco "Mensalidade e atraso". Um painel (o FormPanel que os Parâmetros já usam), na mesma posição em que hoje está o bloco "Taxas", e o bloco "Taxas — Analistas" deixa de existir. Dentro, três grupos empilhados, cada um com subtítulo pequeno no padrão dos outros grupos da tela:
- Mensalidade — pessoa física: três campos lado a lado numa linha — Sugerida (%), Mínima (%), Máxima (%).
- Mensalidade — pessoa jurídica: a mesma linha de três campos.
- Atraso: Multa por atraso (%) e Juros de mora (% ao mês), lado a lado, como hoje.
Tudo visível de uma vez sem rolar dentro do bloco: são oito campos em três linhas. A leitura PF-sobre-PJ, com as colunas alinhadas, é o que permite comparar as duas faixas num relance.
Tela da análise — painel do parecer. Em análise: Parecer do analista, Notas internas, Taxa de adesão (R$) e Mensalidade (%) empilhados na coluna do painel, como os campos de hoje; a linha de faixa e valor em reais fica no texto de apoio do campo. O resumo financeiro, mais abaixo na página, acompanha o número — mas o analista não precisa rolar até ele para saber quanto dá: o valor em reais está colado ao campo. Ações de decisão continuam no cabeçalho.
Aprovada e sem garantia: os dados de leitura do parecer, como hoje, e a linha da mensalidade com Alterar à direita, alinhado à linha. Em modo de edição, Salvar e Cancelar ficam logo abaixo do campo, à esquerda, no padrão do "Salvar rascunho" do mesmo painel. São três cliques do começo ao fim: Alterar, digitar, Salvar.
7.2 Mobile (375px)¶
Parâmetros. O painel vira uma coluna: cada grupo com o subtítulo e seus campos empilhados, um por linha, largura inteira — é o que o grid dos Parâmetros já faz em telas estreitas. Os três campos de um tipo ficam juntos sob o subtítulo, na ordem Sugerida, Mínima, Máxima, para a validação "a sugerida entre as duas" ser lida de cima para baixo. Os campos abrem o teclado numérico com vírgula. Configurar pelo celular é raro, mas não há nada escondido: os oito campos estão lá.
Tela da análise — aprovação. A aprovação acontece às vezes pelo celular (resposta do usuário em 2026-10-12), e é aqui que o mobile pesa:
- O valor em reais fica colado ao campo, não no resumo. Em 375px o bloco "Situação financeira" está várias telas abaixo do parecer — consultas, política, documentos entre os dois. Se a prévia vivesse só no resumo, o analista no celular mudaria o percentual sem ver o efeito. É por isso que a linha "Pessoa física · faixa de 8% a 11% · R$ 285,00 por mês" fica no texto de apoio do próprio campo, nos dois viewports.
- No celular essa linha quebra em duas quando não cabe: a faixa em cima, o valor em reais embaixo, sem cortar o número.
- O campo abre o teclado numérico com vírgula. Com o teclado aberto, o campo e a linha de baixo ficam visíveis (o campo é o último do painel antes do "Salvar rascunho" — a tela rola para mantê-lo acima do teclado, como os campos de texto de hoje).
- A confirmação de aprovação continua como é hoje no celular — um diálogo centrado, de largura inteira, não tela cheia. A linha "Mensalidade" entra no resumo dela como as outras e, como elas, quebra o valor para a linha de baixo quando não cabe ao lado do rótulo.
- Alterar, depois de aprovada: o botão fica abaixo da linha da mensalidade, largura inteira, com altura de toque de 44px — ao lado da linha ele espremeria o valor em 375px. Em edição, Salvar e Cancelar ficam lado a lado, cada um com metade da largura.
- Nada some no celular. São os mesmos campos e a mesma informação; muda o empilhamento e onde o botão fica.
PWA: sem impacto próprio — nenhuma tela nova nem tela offline; o bundle novo chega pela atualização normal do app instalado.
7.3 Estados¶
- Parâmetros carregando: o painel mostra o carregamento que os Parâmetros já mostram hoje para a tela toda.
- Parâmetros com valor inválido ao salvar: erro debaixo do campo, com o que corrigir (Momento A). Nada é salvo enquanto houver erro.
- Painel do parecer, faixa ainda carregando: o campo Mensalidade aparece já preenchido assim que a faixa chega; antes disso, fica desabilitado com "Carregando a faixa…" no texto de apoio.
- Painel do parecer, faixa não carregou (erro): o campo fica desabilitado com "Não foi possível carregar a faixa de mensalidade. Tentar novamente", e o "Tentar novamente" é um link que recarrega. O Aprovar continua disponível: aprovar sem a faixa carregada aprova com a sugerida do tipo, que é o mesmo que aprovar sem tocar no campo — e a confirmação diz isso ("Mensalidade: a sugerida para pessoa física"), em vez de mostrar um número que a tela não conseguiu ler.
- Alterar com a faixa não carregada (Momento C): o Alterar abre o campo, mas desabilitado, com o mesmo "Não foi possível carregar a faixa de mensalidade. Tentar novamente"; o Salvar fica desabilitado até a faixa chegar. Ao contrário da aprovação, aqui não há o que fazer sem a faixa: a mensalidade aprovada já existe, e manter o que está é o mesmo que não alterar.
- Pacote Locatício ausente (análise antiga sem pacote registrado): o campo funciona e a faixa aparece; a parte do valor em reais diz "sem Pacote Locatício para calcular".
- Fora da faixa: erro no campo, sem valor em reais, confirmação bloqueada (Momento B). No Momento C, o Salvar fica desabilitado e o erro é o mesmo.
- Salvar a alteração falhou (Momento C): o campo continua em edição com o número digitado, e uma mensagem logo abaixo diz o motivo e oferece tentar de novo. Se o motivo é que a garantia foi emitida nesse meio-tempo por outra pessoa, a mensagem diz isso ("A garantia desta análise acabou de ser emitida; a mensalidade não pode mais ser alterada.") e a tela recarrega para o modo leitura.
- A faixa mudou depois da aprovação: a mensalidade aprovada continua valendo — foi uma decisão, e a emissão a usa. Se ela ficou fora da faixa atual do tipo, a linha da mensalidade ganha um aviso, sem bloquear: "Fora da faixa atual de pessoa física (9% a 12%). A emissão vai usar 8,5%, como aprovado — use Alterar para revisar."
- O tipo do inquilino principal mudou depois da aprovação (o cadastro foi corrigido de PF para PJ): mesma regra e mesmo aviso — a mensalidade aprovada vale, e o aviso aponta que ela está fora da faixa do tipo atual.
- Sem permissão: quem vê o parecer e não pode aprovar vê a mensalidade só como leitura no painel do parecer, sem campo e sem Alterar. Quem não vê o parecer — a imobiliária — não vê o painel, como hoje; vê a mensalidade escolhida no resumo financeiro e, depois da emissão, na garantia (Momento C). Quem não vê a análise não chega a esta tela — o comportamento de hoje.
- Vazio: não se aplica — toda análise tem inquilino principal e, portanto, um tipo e uma faixa.
8. Revisão da experiência¶
Preenchido pelo laço do /spec new, rubrica .claude/rubrics/experiencia.md.
| Rodada | Critical | Important | Minor | Nota | Veredicto |
|---|---|---|---|---|---|
| 1 | 0 | 1 | 4 | 8 | Aprovada |
Resultado: aprovada na rodada 1.
Pendências aceitas: nenhuma. Todos os apontamentos foram corrigidos no texto depois da aprovação. O Important pedia uma decisão do usuário: a imobiliária não vê o parecer, então não veria a mensalidade escolhida — respondido em 2026-10-12 que ela a vê, só leitura, no resumo financeiro e no diálogo de emissão (Momento C). Os Minor: a confirmação de aprovação não é tela cheia no celular (a 7.2 dizia que era); a linha "Mensalidade aprovada" substitui a "Taxa aprovada" de hoje; a frase do diálogo de emissão para quem emite sem poder aprovar; e o estado de faixa não carregada no Momento C.
Parte III — Detalhamento¶
Não preencher antes das revisões das seções 6 e 8 estarem aprovadas.
Vocabulário técnico desta parte. Na interface o percentual é "mensalidade"; no código ele continua sendo a taxa da garantia (guarantee_rate_percent), que é o nome que a Guarantee, a Decision, o pricing.py e a resposta de simulação já usam. Não se renomeia o que já existe — só o que muda de forma (a faixa única vira duas). O tomador é o locatário principal da análise (CreditAnalysisParticipant com role=LESSEE e is_primary=True), e o tipo do tomador é o Renter.renter_type dele (PF | PJ, apps/api/app/models/renter.py:27).
9. Regras de negócio¶
Parâmetros¶
- RN1. Seis parâmetros substituem três.
TenantSettingsdeixa de terguarantee_rate_percent,min_guarantee_rate_percentemax_guarantee_rate_percent(apps/api/app/models/tenant_settings.py:52-60) e passa a ter, para cada tipo de tomador, sugerida, mínima e máxima:pf_guarantee_rate_percent,pf_min_guarantee_rate_percent,pf_max_guarantee_rate_percent,pj_guarantee_rate_percent,pj_min_guarantee_rate_percent,pj_max_guarantee_rate_percent— todosNumeric(5, 2), não anuláveis, cada um entre0.01e100.00. - RN2. A faixa de cada tipo é coerente, sempre. Para cada tipo, depois de aplicada a alteração sobre o que está gravado:
mínima ≤ sugerida ≤ máxima. OPATCH /api/v1/settingsvalida o estado resultante (o enviado mesclado ao gravado), não só o enviado — hoje oTenantSettingsUpdate(apps/api/app/schemas/tenant_settings.py:192-195) não valida a relação entre os três campos, e umPATCHsó com a mínima pode deixá-la acima da máxima. Violação → 422GUARANTEE_RATE_RANGE_INVALID, nada gravado, com um item dedetailspor tipo que quebrou, apontando um campo só, por esta ordem: - mínima > máxima → o campo é a mínima do tipo, mensagem "A mínima para pessoa física (12%) não pode ser maior que a máxima (11%)";
- senão, sugerida fora de [mínima, máxima] → o campo é a sugerida do tipo, mensagem "A sugerida para pessoa física precisa estar entre a mínima (8%) e a máxima (11%)".
O campo apontado independe de quais campos vieram no corpo: a regra olha o estado resultante, e a tela põe a mensagem debaixo do campo que o details nomeia. - RN3. Nenhum dos seis volta a vazio. null explícito em qualquer um → 422 FIELD_REQUIRED com details no campo, no mesmo molde da spec 0056 em apps/api/app/services/tenant_settings_service.py:67-79 (o exclude_none descartaria o null em silêncio). Os três campos antigos saem do TenantSettingsUpdate e do TenantSettingsResponse; enviá-los passa a ser ignorado, como os campos que a spec 0006 removeu. - RN4. Valores de partida (decisão do usuário em 2026-10-12): PF sugerida 8,00, mínima 8,00, máxima 11,00; PJ sugerida 15,00, mínima 15,00, máxima 18,00. Valem para toda garantidora existente (a migração as grava, inclusive na produção) e para toda garantidora nova (_default_settings em apps/api/app/services/onboarding_service.py:710-716, que hoje grava 10/8/14). Depois disso, o ADMIN_TENANT edita. - RN5. Multa e juros não mudam. late_fee_percent, interest_percent_month e late_fee_grace_days seguem com o comportamento da spec 0054; só mudam de bloco na tela.
O tipo e a faixa de uma análise¶
- RN6. O tipo do tomador decide a faixa. O tipo é lido no momento do uso — na aprovação, na alteração, na emissão e em cada leitura da análise —, do cadastro atual do locatário principal. Corresponsáveis e locatários não principais não contam. A análise sem locatário principal (estado que o fluxo não produz, mas que o banco não impede) usa o primeiro locatário na ordem de
CreditAnalysisParticipantRepository.get_lessees(apps/api/app/repositories/credit_analysis_participant_repo.py:38-50), que é o que a emissão já faz para escolher oprimary_lessee_id; sem locatário nenhum, a faixa é a de PF. A escolha de faixa é uma função pura,faixa_da_mensalidade(settings, renter_type) → (sugerida, mínima, máxima), emapps/api/app/domain/mensalidade.py(arquivo novo).
Aprovar¶
- RN7. Toda aprovação grava uma taxa. No
POST /credit-analyses/{id}/decision/approve,approved_guarantee_rate_percentcontinua opcional no corpo, mas aDecisionaprovada sempre sai comapproved_guarantee_rate_percentpreenchido: - informado → validado contra a faixa do tipo do tomador (RN6). Fora → 422
RATE_OUT_OF_RANGE, mensagem "Fora da faixa de pessoa física: de 8% a 11%" (o tipo por extenso e a faixa), nada gravado; - omitido → grava-se a sugerida do tipo do tomador naquele momento.
Garantidora sem TenantSettings (caso que o onboarding não produz, mas que o approve hoje tolera com if settings: em apps/api/app/services/decision_service.py:226) → 422 SETTINGS_NOT_FOUND, como a emissão já faz (apps/api/app/services/guarantee_service.py:181-185): sem parâmetros não há faixa nem sugerida, e aprovar sem taxa recriaria a decisão sem preço que esta spec elimina.
Hoje a validação usa a faixa única (apps/api/app/services/decision_service.py:223-235) e, omitido, não grava nada — a emissão resolve depois. - RN8. A aprovação registra quem fixou a taxa. Decision ganha guarantee_rate_set_by_id (FK users.id, ondelete=SET NULL, anulável) e guarantee_rate_set_at (timestamptz, anulável). A aprovação os preenche com quem aprova e o instante. São eles que alimentam o "Alterada por … em …" da Parte II.
Alterar entre aprovar e emitir¶
- RN9. Endpoint próprio para alterar.
PATCH /api/v1/credit-analyses/{id}/decision/guarantee-rate, corpo{ "guarantee_rate_percent": "10.50" }(obrigatório,0.01–100.00). Pré-condições, conferidas nesta ordem, cada uma com seu código: - quem chama não é
ADMIN_GLOBAL— senão 403PLATFORM_ADMIN_CANNOT_PRICE, antes de resolver a análise, como a emissão faz com as guardas dela (apps/api/app/services/guarantee_service.py:143-148): oADMIN_GLOBALrecebe 403 para análise existente e inexistente, sem que a resposta revele qual é qual; - análise no escopo de quem chama (seção 10) — senão 404;
- análise em
APPROVEDe decisão emAPPROVED— senão 422ANALYSIS_NOT_APPROVED; - sem garantia emitida para a análise — senão 409
GUARANTEE_EXISTS, mensagem "A garantia desta análise acabou de ser emitida; a mensalidade não pode mais ser alterada."; - taxa dentro da faixa do tipo do tomador (RN6) — senão 422
RATE_OUT_OF_RANGE, mesma mensagem da RN7.
Passando, grava approved_guarantee_rate_percent, guarantee_rate_set_by_id (quem chama) e guarantee_rate_set_at (agora), e registra no AuditLog (entity_type="decision", action="GUARANTEE_RATE_CHANGED", payload com from e to). Mandar o mesmo valor que já está gravado é aceito e não gera auditoria. - RN10. Alterar e emitir não se atravessam. A alteração (RN9) e a emissão (GuaranteeService.create) leem a Decision com SELECT … FOR UPDATE e populate_existing, antes de checar a existência da garantia (na alteração) ou de ler a taxa (na emissão). O populate_existing não é detalhe: na alteração, o _get_decision já pôs a Decision no identity map da sessão, e uma releitura travada sem ele devolveria o objeto antigo sem refrescar os atributos — a trava seria tomada, mas o from da auditoria e a comparação "mesmo valor" (RN9) usariam o valor de antes da espera. É o padrão de apps/api/app/repositories/role_repo.py:92. Na emissão a Decision só é lida uma vez (apps/api/app/services/guarantee_service.py:174), e a leitura travada a substitui. Com isso, quem chega segundo espera o outro terminar: se a emissão venceu, a alteração vê a garantia e devolve 409; se a alteração venceu, a emissão lê a taxa nova. Sem a trava, a emissão poderia ler 9,5%, a alteração gravar 10,5% e responder 200, e a garantia sair a 9,5% com a tela dizendo 10,5%. Hoje a emissão não trava nada (apps/api/app/services/guarantee_service.py:160-175).
A taxa em vigor e o que a usa¶
- RN11. Taxa em vigor de uma análise: a
approved_guarantee_rate_percentda decisão, quando houver; senão, a sugerida do tipo atual do tomador. A segunda vale para as análises aprovadas antes desta spec e ainda sem garantia (decisão do usuário em 2026-10-12: passam a usar a política nova) e para análises ainda não decididas. Não há mais "taxa padrão do tenant". - RN12. A emissão usa a taxa em vigor, e não a revalida.
GuaranteeService.createtroca osettings.guarantee_rate_percentdo fallback (apps/api/app/services/guarantee_service.py:217-221) pela RN11. Não confere a taxa decidida contra a faixa atual: foi uma decisão, e a mudança posterior de faixa ou de tipo do tomador não a invalida (Parte II, 7.3). A garantia congela a taxa emguarantee_rate_percente a mensalidade emmonthly_value, como hoje, e todas as parcelas saem demonthly_value(apps/api/app/services/guarantee_service.py:794-800). - RN13. A simulação espelha a emissão.
GuaranteeService.simulatecom análise usa a RN11 no lugar dosettings.guarantee_rate_percent(apps/api/app/services/guarantee_service.py:482e505-507). Sem análise (simulação avulsa), usa a sugerida de PF — não há tomador de onde ler o tipo — e o corpo da simulação não ganha campo de tipo: a simulação avulsa não tem tela que a chame com tipo, e acrescentar campo para isso é escopo que nenhuma dor pediu. - RN14. Garantia emitida não muda de taxa. Nenhum endpoint altera
Guarantee.guarantee_rate_percentoumonthly_value— já é assim, e esta spec não abre caminho. Mudar o preço de contrato emitido é cancelar e emitir outro (seção 5). - RN15. O snapshot financeiro da análise acompanha a taxa. O
_apply_financial_snapshot(apps/api/app/services/credit_analysis_service.py:964-1024) trocasettings.guarantee_rate_percentpela RN11. E a aprovação (RN7) e a alteração (RN9) atualizam, no mesmo commit, só a parte do snapshot que depende da taxa:financial_guarantee_rate_percent,financial_monthly_value(Pacote × taxa, arredondado como emapps/api/app/services/pricing.py:64) efinancial_first_month_upfront(a nova mensalidade, se o snapshot cobrava o primeiro mês à vista — isto é, se o valor gravado é maior que zero; senão fica como está). Os demais campos do snapshot (LMI, adesão, custos de saída) não são recalculados aqui: a aprovação e a alteração decidem o preço mensal, não reabrem o resto.
A taxa na resposta da análise¶
- RN16.
GET /credit-analyses/{id}ganha o objetoguarantee_rate, calculado na leitura (como oinitial_feeda spec 0056 emapps/api/app/services/credit_analysis_service.py:1065-1118, o_origem_da_taxa): renter_type— tipo atual do tomador (RN6);suggested_percent,min_percent,max_percent— a faixa desse tipo hoje;approved_percent— a da decisão, ounull;effective_percentesource(GUARANTEE|APPROVED|SUGGESTED) — a RN11, com uma precedência a mais: emitida a garantia, vale a taxa dela (GUARANTEE, RN14), emonthly_valueé o da garantia. Sem isto, uma garantia emitida antes desta spec (decisão sem taxa) apareceria na análise com a sugerida de hoje ao lado de "não muda mais";monthly_value—financial_rental_package × effective_percent / 100, arredondado como nopricing.py;nullsem Pacote Locatício;within_current_range— seeffective_percentestá na faixa atual do tipo;set_by_nameeset_at— deguarantee_rate_set_by_id/_at(RN8), ounull;locked—truequando já há garantia emitida para a análise.
É a fonte do que a tela mostra sobre a mensalidade, antes e depois da aprovação — inclusive no resumo financeiro, que a imobiliária vê (Parte II, Momento C). A regra de quem vê o objeto e quais campos está na seção 10. - RN17. Prévia na tela, sem gravar. Enquanto o analista digita, o valor em reais é calculado no navegador: Pacote × percentual ÷ 100, arredondado a duas casas com meio para cima, que é o arredondamento do pricing.py (_round). A faixa vem do guarantee_rate (RN16). Nenhuma chamada à API por tecla. O número gravado é o que o servidor calcula; a prévia só o antecipa.
10. Autorização e isolamento¶
10.1 Matriz de papéis¶
"Aprovar" e "alterar" exigem as mesmas duas permissões — decisions:update e credit_analyses:approve —, porque são a mesma decisão em dois momentos (decisão do usuário em 2026-10-12: altera quem pode aprovar).
| Papel | Pode | Não pode |
|---|---|---|
ADMIN_GLOBAL | ler o objeto guarantee_rate de análise de qualquer tenant, sem a faixa (RN16 com suggested_percent/min_percent/max_percent nulos, como o initial_fee.rule da 0056); aprovar, como hoje | alterar a taxa (RN9) — recusa por guarda de código, 403 PLATFORM_ADMIN_CANNOT_PRICE (decisão do usuário em 2026-10-12); editar os parâmetros (o PATCH /settings já exige ADMIN_TENANT de sistema) |
ADMIN_TENANT | editar os seis parâmetros; aprovar com taxa; alterar a taxa até a emissão; ler o objeto completo | alterar depois da emissão (409); alterar análise de outro tenant (404) |
ANALYST | aprovar com taxa; alterar até a emissão; ler o objeto completo | editar parâmetros (403); alterar depois da emissão (409); outro tenant (404) |
OPERATOR | ler o objeto completo; emitir a garantia com a taxa em vigor | aprovar e alterar a taxa (403 — não tem credit_analyses:approve); editar parâmetros (403) |
VIEWER | ler o objeto completo | alterar (403); editar parâmetros (403) |
AGENCY_USER / AGENCY_MANAGER | ler o objeto guarantee_rate das análises da própria imobiliária, e a taxa da garantia emitida, como hoje | alterar (403 — sem decisions:*); ler análise de outra imobiliária (404); ler o parecer (como hoje) |
10.2 Permissões¶
Nenhuma permissão nova. Por endpoint:
PATCH /settings— inalterado:require_system_role("ADMIN_TENANT")(apps/api/app/api/v1/routers/tenant_settings.py:156).POST /credit-analyses/{id}/decision/approve— inalterado:require_all_permissions(("decisions", "update"), ("credit_analyses", "approve"))(apps/api/app/api/v1/routers/decisions.py:140).PATCH /credit-analyses/{id}/decision/guarantee-rate(novo) — o mesmorequire_all_permissions(("decisions", "update"), ("credit_analyses", "approve")), mais a guarda de código doADMIN_GLOBAL(10.5). Norbac_seed.py, quem tem as duas hoje:ADMIN_TENANT(apps/api/app/db/rbac_seed.py:277),ANALYST(:333) e oADMIN_GLOBALpor compreensão (:239) — que a guarda recusa.GET /credit-analyses/{id}— inalterado (credit_analyses:read); o objeto novo vem dentro da resposta.POST /guaranteesePOST /guarantees/simulate— inalterados.
10.3 Isolamento por garantidora (tenant)¶
- O endpoint novo não recebe FK no corpo — só o percentual. A análise vem do path e é resolvida pelo mesmo caminho do
approve,DecisionService._get_decision(apps/api/app/services/decision_service.py:469-479):get_by_idcom otenant_idde quem chama; análise de outro tenant → 404NOT_FOUND, nunca 403. - A faixa sempre vem do tenant da análise, não do de quem chama (
settings_repo.get_by_tenant(credit_analysis.tenant_id)), como oapprovejá faz. - O tomador e o tipo são lidos dos participantes da própria análise — não há id de inquilino no corpo para ser trocado.
10.4 Isolamento por imobiliária¶
- O endpoint novo é inalcançável pela imobiliária por permissão (403). Mesmo assim o
_get_decisionmantém o recorte porpartner_agency_id(apps/api/app/services/decision_service.py:474-475), que devolve 404 para análise de outra parceira — vale para um papel customizado que alguém crie com as duas permissões. - O objeto
guarantee_ratevem dentro doGET /credit-analyses/{id}, que já recorta por imobiliária: a imobiliária só o vê nas análises dela. Ela vê a taxa e o valor (é o que ela comunica ao inquilino, Parte II) e a faixa do tipo — que ela já lê hoje emGET /settings, onde temtenant_settings:read(apps/api/app/db/rbac_seed.py:403). Não vê o parecer, como hoje. set_by_name(quem fixou a taxa) não vai para a imobiliária: é nome de pessoa da garantidora numa deliberação interna, o mesmo motivo que fecha o parecer para ela. ParaAGENCY_USER/AGENCY_MANAGER,set_by_nameeset_atsaemnull.
10.5 Plataforma × cliente (SaaS admin)¶
- Alterar a taxa é decisão comercial do cliente, e o
ADMIN_GLOBALnão a toma (decisão do usuário em 2026-10-12). A recusa é guarda de código no serviço, comexigir_permissao-equivalente explícito (code="PLATFORM_ADMIN_CANNOT_PRICE") — não subtração norbac_seed, porque a fixture de teste doADMIN_GLOBALconcede todas as permissões sem consultar o mapa (o mesmo motivo registrado emapps/api/app/db/rbac_seed.py:220-238). A permissão em si continua com ele: tirá-la quebraria a aprovação, que segue como está. - A aprovação pelo
ADMIN_GLOBALnão muda nesta spec. Ele já aprova hoje; a RN7 só faz a aprovação dele gravar a sugerida quando omitida, como a de qualquer um. Restringir a aprovação dele é outra discussão, fora daqui. - Leitura: o
ADMIN_GLOBALlê análise cross-tenant como já lê; o objetoguarantee_ratesai sem a faixa (10.1), no mesmo critério doinitial_fee.ruleda spec 0056 (apps/api/app/services/credit_analysis_service.py:1102). A taxa e o valor ficam, porque já estão nofinancial_summaryque ele lê hoje. - Nenhuma tela do SaaS admin (
/app/admin/*) muda.
11. Impacto por app¶
apps/api¶
- Modelos/migrations:
apps/api/app/models/tenant_settings.py— RN1.apps/api/app/models/decision.py— RN8 (guarantee_rate_set_by_id,guarantee_rate_set_at); docstring da classe atualizada (a "faixa configurada" vira "a faixa do tipo do tomador").- Migration nova,
apps/api/alembic/versions/<rev>_mensalidade_por_tipo_de_tomador.py(seção 12). - Endpoints:
PATCH /api/v1/settings— schema novo (RN1–RN3).POST /api/v1/credit-analyses/{id}/decision/approve— RN7, RN8, RN15; Swagger reescrito (a faixa por tipo, a sugerida quando omitida).PATCH /api/v1/credit-analyses/{id}/decision/guarantee-rate— novo, emapps/api/app/api/v1/routers/decisions.py, que já declaraCommitRoute.GET /api/v1/credit-analyses/{id}— objetoguarantee_rate(RN16).POST /api/v1/guaranteesePOST /api/v1/guarantees/simulate— RN12, RN13.- Regras no service:
apps/api/app/domain/mensalidade.py(novo) —faixa_da_mensalidade(RN6) etaxa_em_vigor(RN11), puras.apps/api/app/services/tenant_settings_service.py— RN2 e RN3.apps/api/app/services/decision_service.py— RN7, RN8, RN9 (método novochange_guarantee_rate), RN10 (lock), RN15, guarda doADMIN_GLOBAL.apps/api/app/services/guarantee_service.py— RN10 (lock na emissão), RN12, RN13.apps/api/app/services/credit_analysis_service.py— RN15 no_apply_financial_snapshot(as leituras desettings.guarantee_rate_percentem:993e:1006), RN16 no_build_response, e a terceira leitura do campo removido, no_origem_da_taxa(:1094) — lá a taxa só alimenta o cálculo de que se aproveita o.initial_fee, que não depende dela; passa a receber a taxa em vigor (RN11) só para o campo existir, sem efeito no resultado.apps/api/app/services/onboarding_service.py— RN4.apps/api/app/repositories/decision_repo.py— leitura comFOR UPDATE(RN10).apps/api/app/repositories/credit_analysis_participant_repo.py— reaproveitaget_lessees; sem mudança.apps/api/app/services/pricing.py— sem mudança: continua sendo o cálculo da mensalidade (monthly_value) e a referência de arredondamento da prévia (RN17).- Schemas:
apps/api/app/schemas/tenant_settings.py(Update/Response; oTenantSettingsCreate, que nenhum router usa, perde os três campos antigos junto),apps/api/app/schemas/decision.py(corpo do PATCH novo;AnalysisResponsecomguarantee_rate_set_at),apps/api/app/schemas/credit_analysis.py(objetoCreditAnalysisGuaranteeRate). - Swagger e docstrings: os decorators acima, as descrições do router de parâmetros que citam a faixa única (
apps/api/app/api/v1/routers/tenant_settings.py:38e:119), a seção da taxa negociada emapps/api/app/main.py:316-317e a linha deapps/api/app/main.py:374; oCLAUDE.mdda API, seções TenantSettings e Negotiated Rate on Analysis Approval, que descrevem os campos antigos. - Testes (em
apps/api/tests/): test_tenant_settings_taxa.py— reescrito para os seis campos: RN2 (estado resultante, inclusivePATCHparcial que quebra a faixa), RN3 (null→ 422), RN4 (onboarding).test_mensalidade_por_tipo.py(novo) — RN6 (PF, PJ, sem principal), RN7 (dentro, fora, omitido grava sugerida), RN9 (cada pré-condição com seu código), RN10 (sequência emitir-depois-alterar → 409), RN11/RN12 (aprovada antes da spec emite com a sugerida do tipo; faixa alterada depois da decisão não muda a emissão), RN13, RN15, RN16 (campos,within_current_range,locked).- Negativos de autorização no mesmo arquivo:
OPERATOReVIEWER403 no PATCH novo;AGENCY_USER403;ANALYSTde outro tenant 404;ADMIN_GLOBAL403PLATFORM_ADMIN_CANNOT_PRICE;AGENCY_USERnão recebeset_by_name;ADMIN_GLOBALnão recebe a faixa. - Os testes existentes que gravam
guarantee_rate_percentemTenantSettings(os arquivos que ogrepacha emapps/api/tests/, entre elesconftest.py,test_emissao_de_garantia.pyetest_upfront_payment.py) passam a gravar os campos novos. rbac_seed.py: sem mudança.
apps/web¶
- Páginas/componentes:
apps/web/src/pages/settings/index.tsx— os doisFormPaneldeindex.tsx:953e:1001viram um, "Mensalidade e atraso", com os três grupos da Parte II;FormState,EMPTY_FORM, a carga, obodydo salvar e o conjuntoCAMPOS_DO_FORMULARIOtrocam os três campos pelos seis; os textos de ajuda das chavesguaranteeRate/minGuaranteeRate/maxGuaranteeRatesão reescritos (hoje falam de "negociações com imobiliárias", que não é o que a faixa faz).apps/web/src/pages/credit-analyses/components/DecisionPanel.tsx— o campo Mensalidade (%) no modo de edição; no modo leitura, a linha "Mensalidade aprovada" substitui a "Taxa aprovada" (DecisionPanel.tsx:331-336), com Alterar, edição, Salvar/Cancelar, avisos de faixa e de garantia emitida.apps/web/src/pages/credit-analyses/show.tsx— estado do percentual ao lado dosetupFee, envio na aprovação (handleApprove), linha "Mensalidade" no resumo doApproveDialog, bloqueio da confirmação fora da faixa, e o resumo financeiro alimentado peloguarantee_rate.apps/web/src/pages/credit-analyses/components/ApproveDialog.tsx— só recebe a linha nova noresumoe o motivo de bloqueio; sem mudança de estrutura.apps/web/src/pages/credit-analyses/components/FinancialSummaryPanel.tsx— a mensalidade, o total da vigência e o primeiro mês saem doguarantee_ratequando ele vem (e da prévia durante a edição), em vez desettings.guarantee_rate_percent(FinancialSummaryPanel.tsx:158).apps/web/src/pages/credit-analyses/components/GuaranteeCreateDialog.tsx— os doisDadode hoje, "Taxa" (GuaranteeCreateDialog.tsx:393,guarantee-create-taxa) e "Mensalidade" (:394,guarantee-create-mensalidade), viram um só: "Mensalidade" com "10,5% · R$ 315,00", notestIdguarantee-create-mensalidade; oDadode:393sai. Abaixo dele, a frase por papel da Parte II (guarantee-create-mensalidade-hint).apps/web/src/pages/credit-analyses/api.ts— tipoCreditAnalysisGuaranteeRate, campo noCreditAnalysis,approveAnalysiscom o percentual,changeGuaranteeRatenovo.apps/web/src/pages/credit-analyses/mensalidade.ts(novo) — a prévia (RN17) e a checagem de faixa, puras, para teste unitário.data-testidnovos:settings-pf-guarantee-rate-input,settings-pf-min-guarantee-rate-input,settings-pf-max-guarantee-rate-input,settings-pj-guarantee-rate-input,settings-pj-min-guarantee-rate-input,settings-pj-max-guarantee-rate-input;decision-guarantee-rate-input,decision-guarantee-rate-preview,decision-guarantee-rate-read,decision-guarantee-rate-change-button,decision-guarantee-rate-save-button,decision-guarantee-rate-cancel-button,decision-guarantee-rate-warning,guarantee-create-mensalidade-hint. Saemsettings-guarantee-rate-input,settings-min-guarantee-rate-input,settings-max-guarantee-rate-inputeguarantee-create-taxa; oguarantee-create-mensalidadepermanece, agora com "% · R$".- Sider / menu / rota: sem mudança — nenhum módulo novo.
- Botão por permissão: Alterar aparece com
decisions:updateecredit_analyses:approve, fora doADMIN_GLOBAL, com a análiseAPPROVEDeguarantee_rate.locked === false. Esconder não protege — quem protege é a 10.2. - Responsividade & PWA: como a 7.1/7.2 — grid
xs: 12, sm: 4nos grupos de mensalidade dos Parâmetros; no painel do parecer, Alterar à direita da linha emsm+e abaixo, largura inteira,minHeight: 44emxs;inputMode: "decimal"nos campos. PWA: sem impacto além do bundle novo. - Testes unitários:
apps/web/src/pages/settings/index.test.tsx(os seis campos e o erro por campo vindo do 422),apps/web/src/pages/credit-analyses/show.test.tsx(aprovação envia o percentual; confirmação bloqueada fora da faixa; Alterar só com as permissões e sem garantia),apps/web/src/pages/credit-analyses/mensalidade.test.ts(novo — arredondamento meio para cima e faixa),apps/web/src/pages/credit-analyses/components/GuaranteeCreateDialog.test.tsx(a frase por papel).
apps/e2e¶
- Specs:
apps/e2e/tests/e2e/mensalidade-por-tipo.spec.ts(novo): Parâmetros com os seis campos e erro de faixa; aprovar uma análise de tomador PF mudando o percentual e vendo a prévia; Alterar depois de aprovada; emitir e conferir que a garantia sai com o percentual escolhido e que o Alterar some; o mesmo caminho em 375px conferindoscrollWidth - clientWidth == 0e o Alterar de largura inteira. Restaura os parâmetros nofinally(lição da spec 0025: parâmetro do tenant é compartilhado).apps/e2e/tests/e2e/settings-mobile-snackbar.spec.ts— trocasettings-guarantee-rate-input(linhas 40 e 61) pelosettings-pf-guarantee-rate-input.apps/e2e/tests/e2e/emissao-de-garantia-na-analise.spec.ts— a asserção deguarantee-create-taxa(linha 242) sai, e a deguarantee-create-mensalidade(linha 243) passa a casar um número antes de%eR$(a mesma guarda contraundefined%que o comentário da linha 241 explica).- Seeds: o
seed_e2e.pycria os parâmetros pelo_default_settings(apps/api/app/db/seed_e2e.py:237e:309), então a garantidora do e2e recebe os valores da RN4 pela mudança no onboarding (e, num banco já semeado, pela migração). Nenhuma mudança no seed. Uma análise de tomador PJ, se o spec precisar, é criada pelo próprio spec.
12. Contrato de API¶
Parâmetros¶
PATCH /api/v1/settings
Authorization: Bearer <token de ADMIN_TENANT>
{ "pf_guarantee_rate_percent": "9.50", "pf_min_guarantee_rate_percent": "8.00",
"pf_max_guarantee_rate_percent": "11.00", "pj_guarantee_rate_percent": "16.00",
"pj_min_guarantee_rate_percent": "15.00", "pj_max_guarantee_rate_percent": "18.00" }
Resposta: o TenantSettingsResponse com os seis campos e sem os três antigos. Erros: 422 GUARANTEE_RATE_RANGE_INVALID (RN2), 422 FIELD_REQUIRED (RN3), 422 VALIDATION_ERROR (fora de 0,01–100), 403 para quem não é ADMIN_TENANT.
Aprovar¶
POST /api/v1/credit-analyses/{id}/decision/approve
{ "opinion": "…", "approved_initial_fee_value": "300.00",
"approved_guarantee_rate_percent": "9.50" }
Resposta: AnalysisResponse, agora com approved_guarantee_rate_percent sempre preenchido e guarantee_rate_set_at. Erros novos ou mudados: 422 RATE_OUT_OF_RANGE com a faixa do tipo. Os demais, inalterados.
Alterar¶
PATCH /api/v1/credit-analyses/{id}/decision/guarantee-rate
Authorization: Bearer <token>
{ "guarantee_rate_percent": "10.50" }
{ "id": "uuid-da-decisao", "status": "APPROVED",
"approved_guarantee_rate_percent": "10.50",
"guarantee_rate_set_at": "2026-10-12T14:32:00Z", "...": "demais campos do AnalysisResponse" }
Permissão: decisions:update e credit_analyses:approve. Erros: 404 NOT_FOUND (outro tenant, outra imobiliária, inexistente), 403 (sem as permissões), 403 PLATFORM_ADMIN_CANNOT_PRICE (ADMIN_GLOBAL), 422 ANALYSIS_NOT_APPROVED, 409 GUARANTEE_EXISTS, 422 RATE_OUT_OF_RANGE, 422 VALIDATION_ERROR (fora de 0,01–100 ou ausente).
Leitura¶
GET /api/v1/credit-analyses/{id} ganha:
"guarantee_rate": {
"renter_type": "PF",
"suggested_percent": "8.00", "min_percent": "8.00", "max_percent": "11.00",
"approved_percent": "9.50",
"effective_percent": "9.50", "source": "APPROVED",
"monthly_value": "285.00",
"within_current_range": true,
"set_by_name": "Fulana", "set_at": "2026-10-12T14:32:00Z",
"locked": false
}
null só quando o tenant não tem TenantSettings (o mesmo caso em que o initial_fee fica sem regra). Recortes por papel na 10.1/10.4.
Migration — <rev>_mensalidade_por_tipo_de_tomador¶
upgrade: acrescenta os seis campos emtenant_settings, primeiro anuláveis; grava em todas as linhas os valores da RN4; torna-osNOT NULL; removeguarantee_rate_percent,min_guarantee_rate_percentemax_guarantee_rate_percent. Acrescentaguarantee_rate_set_by_id(FKusers.id,SET NULL) eguarantee_rate_set_atemdecisions, anuláveis, sem preencher — decisões antigas não sabem quem fixou a taxa, e a tela mostra a linha sem o "Alterada por". Não tocadecisions.approved_guarantee_rate_percentnemguarantees.downgrade: recria os três campos antigos, anuláveis; preencheguarantee_rate_percent,min_emax_com os valores PF de cada linha (a PF é a que mais se aproxima da taxa única de antes); torna-osNOT NULL; remove os seis novos e as duas colunas dedecisions. O que o downgrade não devolve: os valores antigos de taxa padrão, mínima e máxima de cada garantidora — a RN4 os substitui por decisão do usuário, e não há onde guardá-los. Isso é dito aqui para não ser surpresa: voltar a versão deixa a taxa única com o valor PF.- Produção: a TXC passa a ter PF 8–11 (sugerida 8) e PJ 15–18 (sugerida 15). O
/shipfaz backup antes de migrar.
13. Critérios de aceite¶
- [x] CA1 (RN1, RN4). Depois da migração, toda linha de
tenant_settingstem PF 8/8/11 e PJ 15/15/18, e os três campos antigos não existem; uma garantidora criada pelo onboarding nasce com os mesmos valores. - [x] CA2 (RN2).
PATCH /settingscompf_min_guarantee_rate_percent=12sobre PF 8/8/11 responde 422GUARANTEE_RATE_RANGE_INVALIDcomdetails[0].fieldigual apf_min_guarantee_rate_percent, e nada muda no banco; compj_guarantee_rate_percent=14sobre PJ 15/15/18, o campo apontado épj_guarantee_rate_percent. - [x] CA3 (RN3).
PATCH /settingscompj_max_guarantee_rate_percent: nullresponde 422FIELD_REQUIRED. - [x] CA4 (RN5). Multa e juros continuam salvando e valendo como na spec 0054 (os testes existentes dessa spec seguem verdes).
- [x] CA5 (RN6, RN7). Aprovar análise de tomador PJ informando 16% grava 16%; informando 12% responde 422
RATE_OUT_OF_RANGEcom "pessoa jurídica" e "15% a 18%" na mensagem; omitindo, grava 15% (a sugerida PJ). Numa garantidora semTenantSettings, aprovar responde 422SETTINGS_NOT_FOUNDe a decisão não muda. - [x] CA6 (RN6). Numa análise com locatário principal PF e corresponsável PJ, a faixa aplicada é a de PF.
- [x] CA7 (RN8, RN9). O
ANALYSTaltera a taxa de uma análise aprovada sem garantia de 9,5% para 10,5%: 200,guarantee_rate_set_by_idé ele,guarantee_rate_set_até o instante, e há umAuditLogGUARANTEE_RATE_CHANGEDcomfrom9.50 eto10.50. - [x] CA8 (RN9, RN10). Emitida a garantia, o mesmo PATCH responde 409
GUARANTEE_EXISTSe a taxa da decisão e da garantia não mudam. - [x] CA9 (RN9). PATCH em análise
IN_ANALYSISresponde 422ANALYSIS_NOT_APPROVED; PATCH com 12% numa PF responde 422RATE_OUT_OF_RANGE. - [x] CA10 (RN11, RN12). Uma análise aprovada antes da migração (decisão sem taxa) e de tomador PJ emite garantia com
guarantee_rate_percent15 e todas as parcelas mensais comamountigual aomonthly_valuecalculado a 15%. - [x] CA11 (RN12). Aprovada a 9% (PF), a garantidora muda a faixa PF para 10–12; a emissão sai a 9%, e o
guarantee_rate.within_current_rangeda análise erafalseantes de emitir. - [x] CA12 (RN13). A simulação com análise aprovada a 10,5% devolve
guarantee_rate_percent10.5 e o mesmomonthly_valueque a emissão grava. - [x] CA13 (RN15). Depois da alteração do CA7, o
financial_summaryda análise mostraguarantee_rate_percent10.5 emonthly_value= Pacote × 10,5%; o LMI do snapshot não muda. - [x] CA14 (RN16). O
GETda análise do CA7 trazguarantee_ratecomrenter_type, a faixa,approved_percent10.5,sourceAPPROVED,monthly_value,set_by_nameelockedfalse; depois da emissão,lockedtrue. - [x] CA15 (10.1, negativo
OPERATOR). OOPERATORrecebe 403 no PATCH novo, e na tela não vê o Alterar; vê, no diálogo de emissão, a frase "Definida pela garantidora na aprovação…". - [x] CA16 (10.1, negativo
VIEWER). OVIEWERrecebe 403 no PATCH novo. - [x] CA17 (10.1/10.4, negativo imobiliária). O
AGENCY_USERrecebe 403 no PATCH novo; noGETda análise da própria imobiliária recebeguarantee_ratecomeffective_percentemonthly_value, eset_by_name/set_atnulos; noGETda análise de outra imobiliária, 404. - [x] CA18 (10.3, negativo tenant). O
ANALYSTdo tenant B recebe 404 no PATCH sobre análise do tenant A, e a taxa não muda. - [x] CA19 (10.5, negativo
ADMIN_GLOBAL). OADMIN_GLOBALrecebe 403PLATFORM_ADMIN_CANNOT_PRICEno PATCH novo, tanto para análise existente quanto para um id inexistente; noGETda análise,guarantee_ratevem comsuggested_percent,min_percentemax_percentnulos. - [x] CA20 (Parte II, Momento A). Nos Parâmetros há um só bloco "Mensalidade e atraso", com os grupos PF, PJ e Atraso; o erro de faixa aparece debaixo do campo errado; em 375px os campos empilham sem rolagem horizontal.
- [x] CA21 (Parte II, Momento B, RN17). No painel do parecer, o campo Mensalidade vem com a sugerida do tipo; digitar 9,5 numa análise de Pacote R$ 3.000 mostra "R$ 285,00 por mês" sem nenhuma requisição; 12 numa PF mostra o erro e desabilita o confirmar da aprovação; a confirmação traz a linha "Mensalidade".
- [x] CA22 (Parte II, Momento C). Aprovada e sem garantia, quem pode aprovar vê "Mensalidade aprovada" com Alterar, edita, vê a prévia, salva e vê "Alterada por …"; em 375px o Alterar fica abaixo da linha, largura inteira, 44px de altura; emitida a garantia, o Alterar some e aparece o texto de garantia emitida.
- [x] CA23 (Parte II, 7.3). O aviso "Fora da faixa atual…" aparece quando
within_current_rangeéfalse; sem parâmetros, o campo e a confirmação dizem isso e a confirmação trava; o 409 ao salvar mostra a mensagem de garantia emitida e volta ao modo leitura. (Revisto na implementação — ver Registro: não há leitura da faixa à parte que possa falhar sozinha.)
14. Plano de implementação¶
Ordem obrigatória no monorepo: api → web → e2e.
- [x]
apps/api—domain/mensalidade.pycom testes puros (RN6, RN11) - [x]
apps/api— models e migration (RN1, RN4, RN8), comdowngradeexercitado no dev-remote - [x]
apps/api— settings: schema e service (RN2, RN3), onboarding (RN4) - [x]
apps/api— decisão: aprovar (RN7, RN8, RN15), alterar (RN9, RN10), guarda doADMIN_GLOBAL(10.5) - [x]
apps/api— emissão e simulação (RN10, RN12, RN13); resposta da análise (RN16) - [x]
apps/api— docstrings, Swagger,main.py,CLAUDE.mdda API - [x]
apps/api— testes (seção 11), primeiro vermelhos - [x]
apps/web— Parâmetros, painel do parecer, aprovação, resumo financeiro, diálogo de emissão, comdata-testide os dois viewports; testes unitários - [x]
apps/e2e— spec novo e os dois ajustes - [x]
make test,make lint(sem apontamento novo nos arquivos tocados) - [x] Validado no dev-remote em desktop e 375px
15. Decisões em aberto¶
Nenhuma. As decisões tomadas pelo usuário em 2026-10-12, para referência: painel único "Mensalidade e atraso" com sugerida/mínima/máxima por tipo; o tomador decide o tipo; altera quem pode aprovar; análises aprovadas e sem garantia passam a usar a política nova; a imobiliária vê a mensalidade escolhida; valores de partida PF 8–11 e PJ 15–18 com sugerida no mínimo; o ADMIN_GLOBAL não altera a taxa.
16. Revisão do detalhamento¶
Preenchido pelo laço do /spec new, rubrica .claude/rubrics/detalhamento.md.
| Rodada | Critical | Important | Minor | Nota | Veredicto |
|---|---|---|---|---|---|
| 1 | 0 | 0 | 7 | 8,5 | Aprovada |
Resultado: aprovada na rodada 1.
Pendências aceitas: nenhuma. Os sete Minor foram corrigidos no texto depois da aprovação: a terceira leitura de settings.guarantee_rate_percent no _origem_da_taxa e as descrições do router de parâmetros entraram no impacto; a RN10 passou a exigir populate_existing na leitura travada; a RN2 passou a dizer qual campo o details aponta; o diálogo de emissão funde "Taxa" e "Mensalidade" numa linha só; a RN7 recusa aprovar sem TenantSettings; a guarda do ADMIN_GLOBAL vem antes de resolver a análise (RN9, passo 0); e três citações foram acertadas.
17. Revisão da implementação¶
Preenchido pelo /spec implement, rubrica .claude/rubrics/implementacao.md. As revisões de fase (api, web, e2e) vão nas primeiras linhas; a da branch inteira, na última.
| Rodada | Escopo | Critical | Important | Minor | Nota | Veredicto |
|---|---|---|---|---|---|---|
| 1 | apps/api | 0 | 1 | 6 | 8 | Aprovada |
| 2 | apps/web | 0 | 2 | 6 | 7 | Reprovada |
| 3 | apps/web | 0 | 3 | 4 | 7 | Reprovada |
| 4 | apps/web | 0 | 1 | 5 | 8 | Aprovada |
| 5 | apps/e2e | 0 | 1 | 4 | 7 | Reprovada |
| 6 | apps/e2e | 0 | 1 | 5 | 8 | Aprovada |
| 7 | branch | 0 | 0 | 4 | 8,5 | Aprovada |
Resultado: aprovada na rodada 1 da revisão de branch (rodada 7 da tabela).
Defeitos aceitos:
change_guarantee_ratereescreve o recorte de tenant e imobiliária em vez de usarapp/services/scoping.py— não usa o_get_decisionporque análise sem parecer deve dar 422, não 404. Está correto e testado (404 por tenant e por imobiliária), mas é uma segunda cópia da regra de escopo. Fica para quem mexer emscoping.py.- Os Minors das revisões de fase que a revisão da branch triou como "pode ficar": a frase por papel do diálogo de emissão testada no componente e não na página; a sugerida PJ do resumo do formulário sem teste próprio; no e2e, o mesmo usuário aprova e altera, a sugerida e a mínima PF coincidem no tenant compartilhado, e o diálogo de emissão não é exercitado com o percentual escolhido — cada um com cobertura em outra camada (pytest ou unitário do web).
18. Registro¶
O que divergiu do planejado na implementação, e por quê:
- CA6 testado com segundo locatário PJ, não com corresponsável PJ. Corresponsável PJ é proibido desde a spec 0003 (
CO_RESPONSIBLE_MUST_BE_PF); o que a regra quer provar — só o tomador decide a faixa — é o mesmo com um locatário PJ não principal. get_lessee_typesno repositório de participantes. A seção 11 dizia "sem mudança"; a leitura do tipo do tomador precisava do join comRenter, eget_lesseesdevolve só o participante. Mesma ordem, principal primeiro.test_tenant_settings_taxa.pynão foi reescrito — ele testa a regra de adesão da spec 0056, não a mensalidade. RN1–RN4 estão emtest_mensalidade_por_tipo.py._origem_da_taxarecebe a sugerida PF, não a taxa em vigor. A taxa ali só alimenta o cálculo de que se aproveita o.initial_fee, que não depende dela; buscar a taxa em vigor custaria duas consultas por leitura sem mudar o resultado.- Testes de aprovação existentes ganharam
TenantSettings. Treze testes aprovavam numa garantidora sem parâmetros e passaram a receber 422SETTINGS_NOT_FOUND(RN7). O de emissão sem parâmetros passou a criá-los para aprovar e apagá-los antes de emitir — é o cenário que ele guarda. - Com garantia emitida, a taxa em vigor é a da garantia (RN16 ampliada). Achado da revisão da fase web: a RN16 não dizia o que mostrar numa análise com garantia emitida e decisão sem taxa (todas as de antes da spec), e a tela mostrava a sugerida nova ao lado de "não muda mais". A resposta sai da RN14 — garantia emitida não muda — e não é decisão nova.
- "Definida por", não "Alterada por". A aprovação também grava quem fixou a taxa (RN8); numa análise só aprovada, "Alterada por" diria que alguém alterou o que só aprovou.
- Os estados "faixa carregando" e "faixa não carregou, Tentar novamente" da 7.3 não existem. A faixa vem dentro da análise (RN16), não numa leitura à parte: enquanto a análise carrega a página inteira é esqueleto, e se a leitura da análise falha a página mostra o erro dela, como já fazia antes desta spec — não há uma segunda leitura que possa falhar sozinha. O que sobra é
guarantee_ratenulo, que significa garantidora semTenantSettings: o campo diz "A garantidora ainda não configurou a mensalidade nos Parâmetros.", fica desabilitado, e a confirmação de aprovação trava com a mesma frase, porque a aprovação seria recusada (RN7). Sem parâmetros e com taxa já decidida, o parecer mostra a taxa decidida numa linha simples, para o dado gravado não sumir. - O SaaS admin não recebe o campo na aprovação. Ele aprova como hoje, mas não recebe a faixa (10.5); sem ela o campo seria um "carregando" eterno. A aprovação dele grava a sugerida, e a confirmação diz isso.
CreditAnalysisForm.tsxentrou no impacto. O resumo do formulário lia a taxa padrão, que deixou de existir; passou a receber a sugerida do tipo do inquilino principal.- A linha da mensalidade da emissão é o componente
MensalidadeNaEmissao, testado direto: o preço só aparece com a vigência preenchida, e o seletor de data não se preenche no jsdom. O fluxo com datas fica no e2e. - O e2e dos Parâmetros não tem
finallyde restauração. A seção 11 o previa; o spec não grava parâmetro nenhum — só provoca a recusa de faixa (RN2), que não grava. O risco que sobra é a RN2 regredir e a recusa virar gravação: aí o teste falha na asserção que relê a faixa pela API, e a faixa quebrada fica no tenant compartilhado até alguém salvar de novo. lockedusa a mesma régua da escrita. Achado da revisão da branch: a leitura ignorava garantia removida em soft delete (spec 0049) e a escrita não, e a tela oferecia um Alterar que sempre recebia 409. Agora garantia removida também trava a taxa — ela pode ser restaurada com a taxa congelada.videos/preparar-ambiente.mjsentrou no impacto. O script do ambiente de demonstração dos tutoriais mandava os três campos antigos; passou a mandar os seis.- A imobiliária não emite garantia (sem
guarantees:create): quem emite sem poder aprovar é o operador, e a frase "fale com a garantidora" é para ele.
Afirmações conferidas¶
Fatos sobre o repositório que uma rodada de portão já conferiu abrindo o arquivo. O recortar.py leva esta seção junto em qualquer parte, e o revisor da rodada seguinte pode tomá-los como dados em vez de reconferir tudo do zero.
| Afirmação | Onde na spec | Conferida em |
|---|---|---|
Duas regras, e a segunda é a que faz a primeira valer:
- Só entra o que um revisor conferiu — não o que você conferiu ao escrever. O ponto é aproveitar trabalho já pago por uma rodada, não abrir atalho para afirmar sem prova.
- Mexeu na frase da spec, a linha sai da tabela. A afirmação volta a ser conferível. Sem isso a tabela vira o oposto do portão: uma afirmação carimbada como verdadeira porque um dia foi.
Feature sem afirmação sobre o repositório não precisa da seção — apague-a.