Changelog
O que há de novo.
Cada melhoria para a plataforma, como ele envia.
· kamo-internal
Mostrar todas as categorias de armazenamento separadamente
Gravações de chamadas, mensagens de voz, anexos de chat, recursos de RH e marketing materiais cada obter sua própria linha em vez de compartilhar um "Documentos e imagens" remar com tudo o mais que acontece para viver na mesma mesa. Duas consequências para o visual. Quatorze categorias excedem o que qualquer paleta categórica pode codificar — passados cerca de oito, tons adicionados deixar de ser Separável para leitores de cor-cegos e tornar-se decoração — assim identidade é transportada pela etiqueta e pela barra de partilha utiliza uma tonalidade puramente como um sinal de magnitude. E a tendência é agora uma única série total em vez de uma pilha de 14 vias: a pergunta que uma tendência responde é ¿é o meu armazenamento crescendo¿, e qual a categoria Cresceu no trabalho da mesa, que a mesa faz exatamente.
· kamo-shared-library
Contar cada tipo de arquivo armazenado como sua própria categoria
Gravações de chamadas, mensagens de voz, anexos de chat, recursos de RH, marketing materiais, gravações de reuniões e qualquer tipo de documento são todas linhas em imgs, distinguido apenas pelo ImageAssocType e todos compartilhando um balde, porque associação é metadados em vez de um limite de armazenamento. Comunicá-los como um linha única foi precisa e inútil: para uma organização de produção escondeu 5,08 GB de uma pegada de 5,09 GB eram anexos de bate-papo. Cada associação agora pertence a um domínio, para que uma organização possa ver o que é consumindo realmente seu armazenamento em vez de um total indiferenciado. StorageDomainCoverageTest faz uma omissão uma falha de compilação: cada ImageAssocType deve ser reivindicado por exatamente um domínio — uploads de meios não reclamados são armazenados e nunca faturados, reivindicado duas vezes significa faturado duas vezes. Verificado por sonda: remover HR RESOURCE de seu domínio falha a construção com a razão, em vez de passar em silêncio. RECORDAÇÕES DAS REUNIÕES REET RECORDING association. MeetRecording Serviço escreve apenas o primeiro, então não se sobrepõem.
· EmailService
Meça as caixas de correio KamoMail de cada org
Caminha cada caixa de correio Kamo hospeda e registra, por dia de chegada, o RFC822 bytes retém — cabeçalhos, corpo e anexos codificados, em todas as pastas, incluindo Lixo e Lixo, já que uma mensagem no Lixo ainda está no disco. Uma ida e volta por pasta: o provedor de IMAP de Mail Jakarta expande o FetchProfile. INVESTIGAÇÃO ENVELOPE INTERNALDATE RFC822.Tamanho, assim tamanho e data de chegada chegar juntos. O que conta é decidido se Dovecot tem credenciais para o endereço, não através da leitura da configuração do prestador. Presença em virtual users É a definição de "Kamo armazena esta caixa de correio", enquanto uma coluna de provedor pode ser velha, herdada a partir de um pai, ou meio-migração. Uma caixa de correio hospedada pela Microsoft ou pelo Google Não há credenciais e é ignorado, por isso a sua organização não é cobrado nada. Quem conta vem do próprio org id de cada caixa de correio. KamoMail não é um único locatário — produção tem 18 caixas de correio sob uma organização e 41 sob outro, entremeado em quatro domínios — assim somando um domínio ou o maildir Cobraria uma organização pelo correio de outra. Os endereços são iguais em minúsculas. A tabela de usuários do Dovecot e os caminhos do maildir são minúsculas enquanto a mesa da caixa de correio mantém o invólucro que a caixa de correio foi criada com, e um caso de descompasso aqui já dividiu uma vez entrega e recuperação através de dois maildirs diferentes. Também protege /api/internal como um todo, em vez de endpoint por endpoint. A filtro denominado /api/internal/calendar e /api/internal/leader-comms individualmente, assim, o próximo controlador montado sob esse prefixo — este — teria sido Atingível sem segredo, silenciosamente e em direcção à exposição. 6 novos testes de atribuição, tratamento de casos e o caso não apresentado; 152 Total, todos a passar.
· InitializerService
Esquema para medição de armazenamento por caixa de correio
* * * * * * * por caixa de correio e por dia de chegada, o RFC822 bytes que a caixa de correio está a aguentar. Contabilidade de armazenamento não tinha fonte honesta para os bytes da caixa de correio: o índice de pesquisa abrange apenas as mensagens indexadas, e cobre-os, independentemente de quem os armazena. ORG ID é desnormalizado de email provider.mailboxes assim por-organização agregação é uma soma indexada, e assim a atribuição permanece por caixa de correio — vários as organizações podem estar no KamoMail imediatamente e o maildir de um domínio pode manter caixas de correio pertencentes a diferentes organizações. Correr contra a produção 2026-08-08; tabela e índices verificados.
· kamo-shared-library
Meça o correio que o Kamo hospeda, por caixa de correio
EMAIL foi fonte do email metadata.search index, que estava errado em ambos Direcção. Perdeu KamoMail inteiramente — uma org on KAMO MAIL tem suas mensagens e anexos no próprio Dovecot maildir, 62 MB dele em produção, contado como zero. E teria carregado uma org no Microsoft 365 ou Google Espaço de trabalho para o correio sentado nos discos do provedor, onde Kamo não tem nada mas um índice de busca próprio. **************************** substitui-a: por caixa de correio, por dia de chegada, total RFC822 bytes — cabeçalhos, corpo e anexos codificados, que é o que ocupa o maildir. Baldear de dia em vez de por mensagem mantém a mesa proporcional a dias-com-mail enquanto ainda permite uma janela de faturamento arbitrária ser resumido exatamente em vez de arredondado para meses inteiros. A atribuição é por caixa de correio via seu próprio org id, nunca por domínio e nunca por maildir. KamoMail não é um único inquilino: produção já tem 18 caixas de correio sob um org e 41 sob outro, entremeados em quatro domínios em uma tabela. Somando um domínio, ou o maildir como um todo, cobraria uma org para outro Correio. Esquema verificado na produção antes do desembarque: email provider .mailbox storage days existe com sua restrição de singularidade após uma execução do KI.
· kamo-internal
Diga por que o armazenamento da caixa de correio pode ler zero
Os bytes da caixa de correio contam apenas as máquinas do Kamo. Uma organização em Microsoft 365 ou Google Workspace tem suas mensagens nos discos desse provedor, então sua linha Mailboxes é legitimamente 0 — que, inexplicável, lê-se como um quebrado Número em vez de número correcto.
· BillingService
Deixe um administrador de plataforma executar a varredura de instantâneos sob demanda
A varredura é o que faz remoções de período e totais de vida para o domínios de exclusão difícil respondê-los em tudo, então dias perdidos para uma falha são perdidos permanentemente, a menos que a lacuna seja preenchida. Esperar pela próxima corrida 04:20 não é um Plano de recuperação. A varredura já alcança 14 dias e é idempotent por (org, dia, domínio), assim chamadas repetidas resolver em vez de dupla contagem. Isto só o expõe, por trás @PlatformAdminOnly, e retorna a contagem de linha para que o chamador possa vê-lo funcionar.
· kamo-internal
Mostrar a utilização do armazenamento na página de estatísticas da conta
A aba dizia "Nenhum dado de uso disponível para este período" para cada organização. billingApi.getCurrentUsage() é um stub retornando { metros: [] }, e UsesMeters torna o seu estado vazio a zero metros — por isso a mensagem estava a comunicar o stub, Não os dados. StorageUsagePanel lê o endpoint real BillingService e mostra os dois figuras que são fáceis de misturar lado a lado: o que a organização está segurando agora, que cai quando os arquivos são excluídos, e o que ele adicionou sobre o seu vida, o que não. Ao lado deles, o que moveu este período, e um repartição por domínio entre documentos, caixas de correio, meios de base de conhecimento, reuniões gravações e divulgações. Quando uma figura é um piso em vez de uma medição, ela diz isso — uma remoção total sem instantâneo de abertura atrás dele, ou um total vitalício para uma área de armazenamento que apaga os seus registos. Um chip explica a base de registro: uma org é Contado para cada arquivo que ele detém, mesmo que Kamo armazena uma cópia por hash. A tendência torna apenas uma vez dois dias de história existem; um ponto não é uma tendência, e desenhar implicaria uma história que ainda não foi coletada. As cores da série são a ordem categórica validada — pior DCV adjacente ΔE 9.1, pior visão normal adjacente ΔE 19.6 nesta superfície. Três lugares abaixo de 3:1 contraste, por isso a tabela de desagregação não é decorativa: é a leitura não-color dos mesmos dados. Contagens de bytes permanecem cadeias de caracteres de fim a fim (O BillingService serializa Longa via ToStringSerializer) e só são ampliados onde a magnitude é comprovadamente segura.
· BillingService
Relatar o que uma organização está armazenando
A página de estatísticas da conta sempre disse "Nenhum dado de uso disponível para este período", para cada organização, porque getCurrentUsage() no kamo-internal é um stub Devolvendo zero metros e nada atrás dele nunca armazenamento agregado. Serve três figuras distintas por área de armazenamento, mais um total: - o que a organização detém agora, que cai quando os arquivos são excluídos - o que acrescentou ao longo da sua vida, que não - o que se moveu durante o período de faturamento atual Remoção é derivada — nenhuma tabela de armazenamento marca uma desativação, uma vez que EmbRecordState.DATE UPDAted é inserível=false e nunca atualiza — como abertura + adicionado - atual contra o instantâneo de abertura do período. Sem abrindo instantâneo ele cai de volta para timestamps lixo e se reporta como um chão em vez de apresentar um palpite como uma medida. A vida é exactamente onde as linhas removidas sobrevivem e acumulam-se a partir de instantâneos onde não sobrevivem; ambas Diz quais são, para que a UI também possa. BillingPeriodResolver prefere um período de assinatura ao vivo e volta a o mês calendário no fuso horário da org. Esse recuo é a característica completa em produção: cada assinatura lá carrega NULL current period start e current period end, então sem ele as figuras de período estariam vazias para cada organização que existe — a mesma classe de bug que o stub que substitui. StorageSnapshotSweep escreve a posição diária do histórico de cada org depende, alcançando até 14 dias perdidos e semeando um primeiro instantâneo do questionável vida útil assim que o rastreamento não reinicia em zero. O endpoint da plataforma relata os bytes fisicamente armazenados. Clientes são faturados por registro; img dats detém uma cópia por hash no entanto muitos orgs têm esse arquivo, e miniaturas e conversões custam bytes ninguém é cobrado para. Ambos lacunas são a economia de Kamo, então eles se sentam atrás @PlatformAdminOnly. 21 novos testes, 113 no total, todos a passar.
· InitializerService
Esquema para 'org storage snapshots'
Espelhos OrgStorageSnapshot como DDL explícita, por estilo de casa — ddl-auto cria a tabela em primeiro lugar, então o CREATE é um retrocesso e os SET DEFAULTS são o que realmente torná-lo utilizável a partir de SQL simples (Hibernate emite nenhuma coluna padrão para valores a entidade preenche em Java). Também índices imgs on (ORG ID, DATE CREED) e (ORG ID, DATE TRASHED). Armazenamento a agregação lê tanto em cada requisição sumária como nos índices existentes em forma de assoc e pasta. Executar contra produção 2026-08-08; org storage snapshots verificados com todos os 16 colunas e sua restrição de singularidade antes da entidade de compartilhamento-lib foi empurrada.
· kamo-shared-library
Modelo de uso de armazenamento por organização
Nada nunca resumiu o armazenamento por organização. Seis entidades carregam um byte contagem por arquivo, e nenhum código agregado nenhum deles, por isso a conta tab stats renderiza "Nenhum dado de uso disponível para este período" para cada org. Adiciona o modelo compartilhado que a agregação precisa: - StorageDomain — as cinco áreas de armazenamento atribuíveis a org, cada uma declarando Se os seus registos removidos sobrevivem. Documentos e mídia KB soft-delete, então um total vitalício é uma consulta direta; caixas de correio, gravações e divulgações duro-delete, para que o deles só pode acumular para a frente. - OrgStorageSnapshot — uma linha por (org, dia, domínio). Existe para três números que são irrecuperáveis após o facto: domínios de exclusão difícil, a posição de abertura que as remoções de período são diferença em relação (sem tabela timestamps uma desativação — EmbRecordState's DATA UPDAted é inserível=falso e nunca atualiza), e um período-fechado número fixado quando o período terminou. - OrgStorageAggregator — cada agregado por domínio em uma classe. Os totais são somado sobre registros, nunca sobre objetos armazenados: img dats mantém um físico cópia por hash no entanto muitos orgs manter esse arquivo, e que salvar é Kamo. O agregador deliberadamente não carrega nenhum estereótipo. Todos os serviços são executados @ComponentScan("com.kamo"), então anotar isso iria construí-lo em todos ~40 de Eles; BillingService declara o feijão. Também adiciona as consultas de índice de busca as necessidades de backfill de tamanho de email — size bytes foi escrito como um hardcoded 0 desde que o índice foi criado, assim que o armazenamento da caixa de correio lê-se como zero bytes de plataforma até que essas linhas sejam reparadas. Esquema verificado na produção antes deste pouso: org storage snapshots existe com todas as 16 colunas após uma corrida KamoInitializer.
· InitializerService
Declare a divisão da aplicação
O recheio só preencheu uma linha do plano que estava faltando — deliberadamente, de modo que não podia silenciosamente mover um nível — que deixou aplicativos que nunca tinham sido preços onde quer que os colocasse primeiro. Ponto de venda e Ferramentas de Marketing acabaram em Free dessa forma, que não é o que Free é vendido como. Ancorado ao que cada plano já promete na página de preços, então a matriz e a cópia de marketing not drif: Free is assessment (CRM, chat, documentos, notas, KB, calculadora); Starter adiciona os aplicativos a negócios com (apoio, comércio, marketing); negócio adiciona o conjunto premium mais telefonia, inventário e clube; Empresa adiciona Legal. Hospedagem por e-mail e os dois sistemas de origem pertencem para nenhum nível — o e-mail é pago por assento em qualquer plano, os sistemas de origem são negociados por mutuante. Ao contrário do backfill isso se reconcilia em vez de preencher lacunas, que é o ponto de ser a fonte de true: uma mudança de nível pertence aqui, em revisão, não em uma edição de UI a próxima execução reverteria. Aplicado ao prod: 11 linhas alteradas. POS e Marketing Livre, e os quatro aplicativos não liberados dada a camada que eles vão pousar quando eles enviam, por isso publicar um é uma mudança de fase em vez de uma mudança de dados. Uma segunda execução reporta zero alterações.
· kamo-internal
Dividir aplicativos e recursos em disponíveis / não disponíveis / obsoleto
Uma lista plana mixou aplicativos que a plataforma oferece com os que não oferece e os que Se aposentou, então o operador teve que ler cada chip para diferenciá-los. Os baldes são exclusivos e a depreciação é testada primeiro: um aplicativo aposentado é aposentado qualquer que seja a sua disponibilidade bandeira ainda diz, por isso só aparece sob Depreciada. Isso também faz o chip "Deprecado" por linha e o escurecimento redundante — todas as linhas dessa aba estão aposentadas — por isso ambas se foram. O particionamento lê o estado do servidor em vez do rascunho, por isso, assinale a opção trocar deixa a linha no lugar até que o salvar terras em vez de puxá-lo para fora de baixo da edição.
· SecurityService
Um catálogo de aplicativos legíveis por inquilinos para Tipos de Filial
Tipos de ramo -> Aplicativos permitidos começaram a carregar sua lista de aplicativos de /platform-config/app-catalog, que requer um proprietário de org de nível superior. A página do host está fechada no CONFIGURE SYSTEM, então para cada inquilino o GET 403'd: o editor renderizou zero aplicativos e o manipulador de salvar se recusou a salvar o modelo de segurança — bloqueando seu nome, faixas etárias, papéis e tipos de comércio, nenhum dos quais envolver o catálogo. Ele falhou para um administrador KamoCRM sem isOrganizaçãoOwner também. ************* serve o mesmo catálogo resolvido sob CONFIGURE SYSTEM, como um Projecção deliberadamente mais estreita: tipo, nome, descrição, estágio, disponível, desactualizado. Nenhuma nota de operador, nenhum padrão de enum, nenhum diagnóstico de direito – aqueles descrevem como a plataforma é Corre, e a escrita fica só na plataforma.
· kamo-internal
Adicione uma guia Apps & Features e corrija a lista de aplicativos permitidos
A nova guia, à direita das Organizações, controla o que cada organização é oferecido: disponibilidade, fase de desenvolvimento, nome do nota de operador, e depreciação. A disponibilidade já não é derivada da fase, para que um aplicativo possa ser publicado enquanto ainda em testes ou retido após ele é terminado; estágio agora conduz apenas o distintivo eo bar. Campos sobrepostos são marcada e revertida individualmente, e depreciação — que esconde uma aplicação cada inquilino usando-o — precisa do nome do aplicativo digitado para confirmar. Aplicativos permitidos no editor de modelo de segurança era um TypeScript mantido à mão cópia do ServiceType.java, com um comentário pedindo aos editores para mantê-lo alinhado. Invisivelmente à deriva. - A MLOS estava completamente desaparecida, por isso nenhum modelo de segurança podia conceder hipoteca originação. - LOS foi rotulado como "Sistema de Origem de Empréstimo de Mortgage" - significa pessoal empréstimos desde o 2026-08-08 renomear, então o editor escreveu um empréstimo pessoal Subsídio para um operador que pensou que estava a conceder hipoteca. O POS e o ESIG mostraram PLANEAMENTO muito depois de terem enviado. A inclusão de indicadores de disponibilidade nessa lista só teria conseguido confiantemente errado, então ele agora lê o mesmo catálogo a nova aba escreve e Não pode discordar. A poupança está bloqueada até que o catálogo carregue: cada appConfigs builder o itera, então uma lista vazia teria despojado o subsídios de modelo.
· SecurityService
Sirva o catálogo de aplicativos e leia recursos através dele
FeatureController derivado "é este aplicativo oferecido" do estágio do enum em quatro lugares separados, de modo que a resposta só poderia ser alterada reposicionando o plataforma. Cada um deles agora lê AppCatalogService, juntamente com o Indicar o nome, a descrição e a depreciação. A sutileza comportamental é a porta do root-org. Costumava ler "estágio é Não COMPLETADO, então as orgs de crianças podem não permitir isso" — o caminho de alimentação de cães. Ele agora lê-se "a plataforma atualmente não oferece isso". Enquanto não houver sobreposição existe que são a mesma frase, porque a disponibilidade não definida resolve stage == COMPLETED. Uma vez que um operador publica um aplicativo que ainda está em TESTAMENTO, apenas o novo formulário faz a coisa certa: sem ele o aplicativo iria ficar silenciosamente bloqueado para cada org infantil. PlatformAppCatalogController é fechado para proprietários de topo-nível-org, o mesmo público como as páginas da plataforma vizinha, e relata se um disponível app está realmente na matriz do plano — um aplicativo nenhum plano menciona resolve através a configuração de abertura de falha em vez de através de qualquer coisa que o operador escolheu.
· kamo-shared-library
Torne a disponibilidade do aplicativo e editável em fase de execução
Cada atributo que a página de configurações de apps renderiza — nome, descrição, fase, depreciação — era uma constante de tempo de compilação na série ServiceType, e "Disponível" não foi armazenado em tudo: ele foi derivado como estágio == na UI e em três lugares servidor-lado. Mudar qualquer coisa significava editar A biblioteca partilhada e a reinstalação da plataforma. PLATFORM APP CATALOG mantém uma linha por aplicativo com cada coluna de substituição nullable, e AppCatalogService resolve sobreposição ??? enum. Falta uma linha significa o enum verbatim, então instalar isso não muda nenhum comportamento. Disponibilidade torna-se seu próprio valor, que é o que faz um lançamento suave (oferecido durante o ensaio) ou um aplicativo COMPLETED retido expressível. O seu recuo lê a etapa RESOLVED em vez da enum's, então um operador que só se move um aplicativo para COMPLETED obtém disponibilidade sem também apertar o interruptor.
· InitializerService
Uma linha de catálogo devidamente categorizada por aplicativo, em cada raiz de direito
Nove aplicativos — POS, Ferramentas de Marketing, Calculadora, Clube, Inventário, Legal, Jogos e os dois Sistemas de origem — não tinha qualquer representação em catálogo: nenhuma linha de preços, nenhuma categoria, nenhuma camada. Doze outros já foram descritos por uma linha de marketing, por isso vinculando-os e adicionando um paralelo A linha APP * teria dado uma linha ServiceType duas linhas e feito planoFeatureIncluded depende de Ordem de iteração. O corredor agora converge com o catálogo: - liga uma linha de marketing publicada ao aplicativo que descreve (VIDEO CONF is Meet, MESSAGING is Chat), Manter os seus valores de código, nome, categoria e nível para que a matriz publicada não se mova; - cria uma linha para uma aplicação que o catálogo não descreve, numa categoria real — incluindo uma nova Comércio & categoria de origem; - promove qualquer placeholder APP * anterior para sua identidade real e apaga os aplicativos planos balde uma vez vazio; - remove linhas duplicadas para o mesmo aplicativo, preferindo a linha de marketing. Não resta nenhum recurso APP : cada aplicativo tem um código legível, e aplicativos o catálogo publicado já nomes reutilizar esse código exato para uma org com sua própria matriz e um sem descrever o mesmo produto de forma idêntica. Isso importava — sign.pink não tem matriz de marketing e ficou com onze linhas com o nome das constantes de enum. A MLOS e os Empréstimos Pessoais são negociados pelas empresas, não por assento: preço nulo, modelo de preços FLAT, compatível apenas com planos do tipo CUSTOM (Enterprise), agrupados em nenhuma camada. Eles são criados sobre o Org de plataforma apenas — uma org de produto de marca branca não os revende, e os dois criados em sinal. rosa por uma passagem anterior são desativados. Verificado contra prod após a execução: 0 códigos APP * deixados, 0 linhas de serviço tipo duplicado, 21 apps on cada raiz, 0 combinações de plano a aplicativo descobertas, e uma re-run é um no-op.
· kamo-internal
Consola de organizações paginadas por servidor
A aba carregou cada organização em um pedido e renderizou um cartão cada, com a infra-estrutura fanning out por org, em seguida, por conta, em seguida, por assinatura. Procurar, ordenar, filtrar e chamar agora executar servidor-lado contra toda a propriedade, assim, o custo da página é plana, não importa quantas organizações existam. A linha também é o objeto certo agora. Uma assinatura é HELD por uma conta e TARGETS uma org, então o cartão antigo -- com a chave no titular -- teve que imprimir o o nome do alvo dentro de uma tabela aninhada, e orgs do cliente apareceram como strings dentro de outras fileiras de orgs em vez de como fileiras. Cada linha tem agora direito (inbound: o que governa esta org) e faturamento realizada (outbound: o que conta para outros) como facetas separadas. Design: uma grade de status na borda esquerda de cada linha e uma barra proporcional, então uma página lê como um histograma de cor da saúde comercial antes de uma palavra é ler; numerais tabulares com zeros silenciados, uma vez que a maioria das células em uma propriedade de faturamento são zero. O estado da tabela vive na URL para que uma visão filtrada seja linkable -- writed através de uma cópia que preserva `tab`, e sem publicar ActiveTab, que pertence ao tabSync.
· SecurityService
Falha fechada em aplicativos um plano nunca menciona
Torna o kamo.entitlement.fail-open agora que o AppEntitlementCatalogMigration foi executado contra prod e cada plano ativo sobre ambas as raízes de direito (KamoCRM, Sign Pink) carrega um explícito linha para todos os 21 aplicativos não-core — verificado zero descobertos combinação plano-a-app, então há Não resta nada para uma recusa-por-default apanhar, excepto uma aplicação genuinamente pouco cara. Isso não altera o que qualquer org pode usar hoje: aplicativos enviados estão explicitamente incluídos, e MLOS e o aplicativo pessoal-empréstimo já foram negados por explicitamente isIncluded=falsas linhas, que se ligam independentemente desta bandeira. O que fecha é um aplicativo deslizando através de sem preço por nunca aparecer na matriz de um plano. Voltar para true se uma nova raiz de direito for adicionada antes da migração ter sido executada para ela.
· BillingService
Serve a pasta org como uma página filtrada, ordenada e paginada
GET /orgs pega página/tamanho/q/sort/dir mais sete filtros e retorna a casa envelope de página com agregados de toda a propriedade. GET /orgs/{orgId} serve detalhes completos para a gaveta de perfuração do console, onde o ventilador por conta está bem porque está limitado a uma org. listAllOrgs() é substituído em vez de mantido como um delegado truncado: tinha exatamente um chamador (este controlador), e a lista de frontendOrgs() tinha exatamente um (a aba sendo reescrita), então um shim de compatibilidade só teria adicionado um Risco de desvio silencioso sem nada dependendo disso.
· BillingService
Hidratação da página rebatida em uma constante contagem de consultas
Títulos dos pais, domínio primário, plano/mercado subjacente ao direito e a assinatura-marca de catálogo são cada um loteado IN (:ids) em toda a página, Assim, uma página de 100 linhas custa as mesmas seis declarações como uma página de 1 linha. O teste assevera que a igualdade diretamente -- a implementação que isso substitui iria marcar 6 contra 600. A assinatura que rege é escolhida pelo direitoModeResolver, o mesmo código que decidiu o modo da linha, então o plano mostrado sempre pertence ao estado mostrado. Consultas passam pelo EntityManager em vez de novos métodos de repositórios Kamo-shared-library, do qual cada serviço depende, não tem que mudar.
· BillingService
DTOs de linha/página de diretório e o repositório de consultas nativo
PlatformOrgRow carrega as duas facetas separadamente: direito (subs de entrada) visando o org -- o que o governa) e faturamento realizado (conta o org possui -- não-zero apenas para as orgs de plataforma e revendedores). Os agregados descrevem o conjunto inteiro filtrado, não a página, por isso a tira KPI não muda o significado como as páginas do operador. Cada valor do driver é coagido através de Number/Boolean em vez de elenco: a coalesce(...,0) que não corresponde a nenhuma linha retorna Integer onde a mesma coluna com linhas retorna Long, que passaria em dev e jogaria em prod. O dinheiro atravessa o fio como uma cadeia decimal.
· BillingService
SQL do diretório Org com CTEs por faceta
Contas, assinaturas, membros, licenciados e crianças cada Agregar nas suas próprias CTE antes de serem unidas às orgs. Juntando-os em um passar multiplicaria linhas e inflaria cada SUM. Testes puros e unitários (26): sem ':' moldes, todos os valores ligados, ordenar chaves Lista branca através da OrgSort. Duas coisas o pino testes porque eles são fáceis de "tidy" into bugs -- ORDER BY e os predicados derivados (mode rank, has stripe) deve nomear as colunas projetadas do CTE base, uma vez que o alias `o` está fora de escopo na consulta externa; e um teste PENDING não relata nenhum prazo em vez do A última expirada. Verificado contra o cluster ao vivo: ambas as declarações são executadas, a contagem concorda com as linhas, e filtros/agregados aplicam-se. O uso do índice NÃO é demonstrado -- em 12 orgs / 9 subs BarataDB full-scans independentemente, corretamente.
· BillingService
Pedido de directório de orgs validado e apertado
As pinças de tamanho para [1,100] e um tipo não reconhecido cai de volta ao título, por isso um URL editada à mão não pode solicitar toda a propriedade nem atingir o SQL como texto livre. O OrgSort enum é o tipo de lista branca.
· BillingService
Modo de direito derivado através de um resolvedor determinístico partilhado
TrialAdminService escolheu sua assinatura de teste com findFirst() sobre uma lista não ordenada, então uma org segurando tanto um pendente quanto um teste ativo poderia relatório qualquer um dos dois. A próxima pasta de organização tem de ordenar e filtrar este estado, e uma consulta não pode reproduzir uma regra não determinística. A precedência agora vive em testes ao vivo, vitórias activas sobre vitórias pendentes expiradas e expiração activa reportado é o último. status() mantém sua forma exata de resposta. Primeiros testes neste acordo (11).
· InitializerService
Reforço das linhas de direito do aplicativo no catálogo do plano da plataforma
O título agora resolve em uma coluna tipo service digitada, mas nenhuma linha do catálogo carregou uma, então cada plano ainda resolvido para 'tudo incluído' através do padrão fail-open. Esta semente matricity so kamo.entitlement.fail-open pode eventualmente ser desligado sem aplicativos de fogo escuro. - AppEntitlementCatalogMigration (@ Order( 51), after PlatformOwnerPlanSeeder): idempotent Reenchimento. Cria uma categoria de funcionalidades 'Aplicações' com uma linha BOOLEAN por aplicativo não-core ligado ao seu ServiceType, religa qualquer linha pré-existente que tenha o código mas não serviceType, e insere as linhas faltantes do plano para aplicação por nível. Inserir apenas em caso de omissão — ele nunca apaga e nunca substitui o éIncluded de um operador, então uma camada editada no configurações UI sobrevive a reinicialização. Também religa o VIDEO CONF existente / AI ASSISTANT / HR SISTEMA / ESIGNATURAS / EMAIL HOSTING add-ons, que não estavam concedendo nada. - KamoCRMPricingLoader: mesma matriz para um cluster fresco. As linhas do aplicativo são adicionadas dentro upsertCaracterísticas em vez de escritas em uma segunda passagem, porque upsertPlanCaracterísticas apaga o as linhas do plano antes de inserir — uma segunda chamada limparia silenciosamente a matriz de marketing. Nota este carregador está desativado (retorno antecipado, e sua chamada DataLoader é comentada), que é por que a migração acima é o caminho de produção.
· SecurityService
Obrigações hipotecárias e empréstimos pessoais sobre o direito à aplicação
Um mercado MORTGAGE apareceu no /commerce sempre que POS estava em, independentemente da aplicação MLOS, e /features/enable não tinha nenhuma verificação de faturamento em tudo — o cadeado nas configurações UI foi apresentação somente, assim que um POST direto ligado em um aplicativo sem título. - FeatureController: 403 on enable quando o plano não inclui o aplicativo; serialize um Veredito 'intitulado' sobre ambos os recursos[] e disponível[] assim que o cadeado UI e o 403 são calculado pelo mesmo serviço e não pode discordar. - CommerceMarketController: GET /allowed-types for the market-type picker (modelo allow-list Intersecção com o direito); a lista de mercado deixa cair verticais sem título — ocultas, nunca arquivado, então restaurar o plano traz de volta o mercado com seus dados intactos. Guarda fechado em todas as sub-rotas. AppDisponível O interceptor não pode expressar isso — seu prefixo map é um prefixo para um ServiceType e /commerce-mercados serve todos os sete verticais sob POS. - POSController: as chamadas públicas do catálogo de assinaturas não mais ver linhas ligadas a um aplicativo que não atingiu COMPLETED, então mover um ServiceType para COMPLETED é o que publica para o site de marketing. Os ouvintes internos ainda vêem tudo para precará-lo de antemão. - HipotecaVerticalResolver: prontidão medida apenas POS, então uma org que nunca comprou MLOS ainda ler como pronto; agora relata MLOS em 'falta' também.
· kamo-internal
Renomear LOS para MLOS, adicionar Sistema de Origem de Empréstimo Pessoal, verticais de comércio de portão
A aba de Apps agora mostra 'Commerce: Sistema de Origem de Empréstimos Hipotecários' (o título é servido a partir do backend enum, não o espelho TS) e um novo 'Commerce: Personal Loan Origination System' sob Não disponível. Os mercados MORTGAGE e PERSONAL LOANS estão fechados em sua aplicação. - espelhos AppType/ServiceType: MLOS(14) + novo LOS(25); também fixa a deriva preexistente onde os espelhos discordaram do Java enum. - Organização: isMlos adicionado; isLos agora significa empréstimos pessoais. IsLos tinha zero consumidores. - FeaturesManager: gating lê a bandeira 'intitulada' fornecida pelo servidor. Foi reconstruído lado cliente de billingApi, cujo getCurrentAsscriction lança e getAvailablePlans retorna [] (legacy Assim, cada aplicativo silenciosamente resolvido para 'ungado' e nenhum cadeado nunca renderizado. - Seletores de mercado: tanto as páginas de criação como de edição possuíam seu próprio array COMMERCE TYPES; Eles agora render get ************* então uma org vertical não comprou é não selecionável. A página de edição também estava pulando a regra de um-MORTGAGE-per-org. Continua o tipo atual do mercado selecionável para que uma org caducada ainda possa abri-lo e renomeá-lo. - Configurações hipotecárias da porta de superfícies em isMlos em vez de isPos.
· kamo-shared-library
Resolver o direito de aplicação por ServiceType; renomear LOS para MLOS
Título resolvido ServiceType.name () contra **************************** Os códigos do catálogo são códigos de marketing (USERS, VIDEO CONF, HR SYSTEM, ...) e nunca corresponderam, assim planoFeatureIncluída falta-linha padrão concedido cada aplicativo em cada plano — o faturamento-para-aplicação A ligação estava inerte. As linhas de catálogo agora carregam um tipo serviço nullable digitado e a resolução passa para que um aplicativo possa ser renomeado sem mover o direito. - **************** coluna tipo serviço digitado (persistido como o ID). - Está bem. resolver por ServiceType; add-ons de honra através do anteriormente não lido ************* jsonb; comportamento perdido-linha atrás de kamo.entitlement.fail-open (default true até que a matriz do catálogo seja semeada). - Serviço de Assinatura: transporte de serviçosType through create/update/DTOs, and derivate feature code do nome quando omitido — o diálogo de configurações nunca enviou um, então cada criação a partir do A UI atingiu a restrição NOT NULL. - CommerceType: ligar cada vertical à sua aplicação exigida (MORTGAGE->MLOS, PERSONAL LOANS->LOS). - AppliedModelEnforcementService: getAllowedCommerceTypes intersecta o modelo de segurança allow-list com direito; assevereCommerceTypeAllowed já cobre criar e editar. - ServiceType: LOS -> MLOS mantendo id 14 (ORG FEATURES persiste o id, não o nome, então não migração de dados); novo LOS(25) para empréstimos pessoais — id 25 porque a reutilização de 14 Todas as linhas hipotecárias existentes. - RoleRightType: MLOS * reboot, ids 139-144 inalterado; LOS pessoal-empréstimo * adicionado em 190-195. - PhiModule. PLOS adicionado: o renome deixou o aplicativo de empréstimo pessoal mapeado para a hipoteca PHI módulo e hipoteca não mapeado, que compilou limpo.

Seu universo está esperando.
Comece gratuitamente em minutos.Adicione produtos sempre que estiver pronto — sem migração, sem novos logins.
Gratuito para sempre — não é necessário cartão de crédito