Changelog
O que há de novo.
Cada melhoria para a plataforma, como ele envia.
· kamo-internal
Confirme antes de uma atualização fazer uma chamada ao vivo
A sessão SIP vive no documento e nada no servidor detém um comando para isso, assim, uma recarga termina a chamada totalmente — sem BYE, deixando o extremo fim ligado silêncio até que o registrador cronometre o contato. Uma confirmação nativa do navegador é toda a defesa que uma página tem, e F5 é a maneira mais comum uma chamada é perdida. Também extrai isCallActive como a única definição de uma chamada ao vivo, por isso o próximo O veto, o batimento cardíaco e o sinal de fuga não podem sair dele. Um toque a chamada de entrada conta, assim como a lacuna de negociação SDP que o membro experimenta como a chamada já está acontecendo.
· kamo-internal
Reconstruir o editor de disponibilidade em torno do dia que ele descreve
O editor era uma pilha de linhas de formulário que nunca mostrou o que estava fazendo. Ele agora abre-se com a própria coisa: um trilho de 24 horas com o bloco pintado nele, no mesmo verde estará na grade atrás. Isso custa o terço superior de o diálogo e o ganha, porque a questão que esta superfície provoca não é "que controles são estes" mas "o que estou criando?" — e uma imagem de um dia Responde de uma forma que outro parágrafo não responde. O trilho anima sua posição e largura como as horas mudam, e um bloco que passa da meia-noite desenha como o dois segmentos realmente é e diz assim, em vez de parecer um erro. Os dias tornaram-se uma fita. Uma semana são sete coisas e uma pessoa aponta para elas, então são sete fichas em vez de um dropdown escondendo seis atrás de um clique - e quando criando, vários ao mesmo tempo, porque "segunda, quarta e sexta de manhã" é Um pensamento e três janelas. O botão diz então quantos blocos irá Para que a multiplicação nunca seja uma surpresa. Edição mantém-no em um: a bloco não deve tornar-se cinco atrás de um botão que diz Salvar alterações. Dias já carregando um bloco idêntico são largados, reutilizando os dias testadosNeedingWindow. As horas têm as palavras que as pessoas dizem em voz alta — Manhã, Tarde, Todo o dia — porque "Eu sou manhãs livres" é o pensamento real e traduzi-lo em dois Os coletores de tempo eram o atrito que valia a pena remover. O alcance eficaz e o movimento da nota por trás Mais opções, que abrem já expandidas quando a janela está sendo editada usa-os, para que nada anteriormente definido esconde-se atrás de uma revelação. A cópia faz uma pergunta e a ação primária mantém o verbo da barra lateral, então o recurso lê como um vocabulário em vez de três. A entrada é três batidas — cabeçalho, trilho, controles. Seis regiões escalonadas foram o primeiro instinto e lido como um desfile, chamando atenção para a animação em vez do dia que está sendo descrito. Tudo desmorona para nada debaixo prefere movimento reduzido. A barra lateral é 364px, 30% mais larga. O painel de disponibilidade coloca leitura real abaixo a lista de calendários e na largura antiga o botão que inicia tudo sentado abaixo da dobra; a grade ao lado dela é fluida, então a coluna pode simplesmente levar o espaço. A paleta do diálogo vive em disponibilidade Tema com o resto da camada cores: o bloco no trilho tem que ser o mesmo verde que o bloco no grade, e uma paleta separada aqui cortaria que a primeira vez que se moveu.
· kamo-internal
Um endereço para uma conversa em qualquer uma das cinco superfícies
chat/suporte/social compartilhar o chat: espaço de nomes porque eles compartilham um não lido snapshot; SMS e IA têm o seu próprio, porque uma VoipConversation UUID e uma mídia sessão GUID são IDs não relacionados que não devem colidir em um mapa.
· kamo-internal
Rotas para as contagens e marcas da coluna de notificação
O PUT routes responde 204 e não deve chamar .json() nele — que gira um leitura de marca bem sucedida em 500.
· kamo-login
O selecionador de espaço de trabalho mostra o logotipo de cada org
Duas letras em espera por um logotipo foi uma solução para a resposta não carregando uma. Ele agora, resolvido servidor-side a partir da pasta o tema do org foi fornecido para, assim um A escolha de membros entre cinco espaços de trabalho reconhece-os em vez de descodificar iniciais. O monograma permanece como o recuo, e é um real em vez de uma formalidade: nada registra se uma org já enviou um logotipo, então a URL é onde o arquivo seria e um 404 é uma resposta comum. Falhas são lembradas por id org — sem que o navegador repita a mesma imagem em falta em cada re-render e o avatar pisca entre um quadro quebrado e Duas letras. Um logotipo se senta no branco para que ele leia o mesmo na linha selecionada como nos outros; um monograma mantém o chip colorido que sempre teve.
· SecurityService
A resposta de entrada carrega o logotipo de cada espaço de trabalho
O selecionador desenhou duas letras por linha porque a resposta tinha um nome e um nome falso e não imagem. Uma lista de espaços de trabalho é lida por marca muito antes de ser lida pelo nome. Resolvido aqui em vez de no navegador. O URL tem que nomear a pasta que o tema foi e essa regra já vive em OrgDomains. temaImageBase — reconstruindo-o em kamo-login seria uma segunda cópia para drift, e cada linha iria solicitar um arquivo escreveu. simLogoUrl espelhos resolverPrimaryDomain pela mesma razão: DNS-verificado primeiro, então apenas ativo, então {alias}. kamocrm.com para uma org que não tem nenhum domínio. Os domínios rodam na consulta de login existente como dois agregados em vez de uma pesquisa por org — este é o caminho de entrada, e um membro de uma dúzia de espaços de trabalho Consultar cada um. Dois, porque escolher entre eles é a preferência acima. Nada registra se um logotipo já foi carregado, então o URL diz onde o arquivo seria. Um 404 é um resultado comum e a linha cai para trás ao seu monograma. Verificado contra produção: kamocrm.com, b11capital.com, breakbeat. loja eo demo todos os inquilinos do subdomínio devolvem a imagem no URL estas regras constroem — os subdomínios de sua própria pasta no ápice pai, não entrou em colapso na plataforma.
· kamo-internal
Configure o RingCentral com um JWT e atribua aos membros seu próprio número
Três ecrãs, uma mudança. A aba de visão geral do servidor de telefone substitui "Conectar com RingCentral" pela forma credencial o fluxo JWT realmente precisa — ID do cliente, segredo, URL da plataforma e um serviço-usuário JWT — construído como as equipes um ao lado dele. URL da plataforma é editável porque o JWT de um aplicativo sandbox é recusado pela produção e vice-versa, e apontando para o host errado produz um grant inválido que lê exatamente como um Uma má credencial. Segredos de ida e volta como "***", então editar o nome do servidor de telefone não significa repassá-los. A guia Plataforma Avançado perde seu cartão RingCentral. Não há nenhum Kamo-wide RingCentral registro mais, e um operador preenchendo um seria introduzindo credenciais que nada lê. O mesmo raciocínio que o ADP WFN. A página de configurações de telefone do membro tinha um bug real: o dropdown do provedor listado apenas servidores de telefone que já tinham uma extensão sincronizada gratuita, então um servidor RingCentral minutos criados antes era invisível — uma lista de fornecedores vazia, nada para Atribuir, e nenhuma maneira de dizer porquê. Cada servidor de telefone ativo está listado agora, e um com nada carregado diz e oferece-se para sincronizar no lugar. A atribuição também ganha o número em si. As extensões carregam seus próprios DID, assim que o dropdown lê "101 — Ada Lovelace (+1 702 555 0134)" em vez de um nu número de extensão, e o ID de chamada de saída do membro torna-se a sua própria linha Em vez do número principal da org. E o botão de conexão RingCentral torna-se Campo JWT: o servidor prova a credencial antes de armazená-la e lê de volta qual extensão resolve, então um JWT criado na extensão de um colega é sinalizado em vez de silenciosamente registrar o softphone como esse colega. O cartão Teams mantém seu hop de consentimento, e o prompt do softphone pára de nomear RingCentral nos usuários das Equipes. A página do cartão de membro de inglês de código rígido é keyed enquanto ele está sendo reescrito.
· VOIPService
Autentique o RingCentral com um JWT, por servidor de telefone
RingCentral foi o último provedor cujas credenciais vieram de um Kamo-wide registo mais dois lúpulo de consentimento do navegador — um para a org, um por membro. Ambos desapareceram. Uma organização registra seu próprio aplicativo em seu próprio RingCentral consola de desenvolvimento com o fluxo de autenticação JWT activado, e o ID do cliente, secreto, URL de plataforma e um JWT de usuário de serviço ao vivo no VoipProviderInstance que usa Eles, exatamente como as credenciais do FreePBX e do Teams já fazem. Um cliente as credenciais já não podem autorizar uma chamada contra a conta de outro cliente, e não há consentimento para obter, nenhum token para armazenar em nome de um navegador, e nenhum estado de "reconectar" para cair. **************************** espelhos EquipasInstanceConfigFactory, menos o backback da plataforma: um JWT não tem sentido contra a conta de ninguém, então um o backback só podia deixar uma instância semi- configurada pedir emprestado o ID de outra aplicação e falhar mais tarde como um opaco 401. require() nomeia o campo em falta. RingCentralJwtTokenService mentas acessam tokens de um JWT e os armazenam com chave por um digest da credencial, assim girando um JWT é auto-evitável e um velho token nunca pode ser servido por uma credencial que tenha sido substituída. Um 4xx significa a credencial está morta e pede um novo; qualquer outra coisa permanece uma falha nunca é confundida com uma JWT revogada. RingCentralProvider está agora com endereço de extensão. Construído a partir do utilizador do serviço credencial ele chega a um membro em /account/~/extension/{id}/..., então sua chamada histórico, correio de voz, presença e reencaminhamento de chamadas no momento em que um administrador atribui- lhes uma extensão — anteriormente um membro sem ligação OAuth Nada mesmo. Construído a partir do próprio JWT do membro que ele endereços ~. Apenas client-info/sip-provision precisa deste último, e pedindo-o com a conta token não seria erro: devolveria a identidade SIP do Usuário e registar o softphone do membro como essa conta. Em vez disso, recusa-se. modelar o softphone já manipula. listExtensões agora lê o inventário de números da conta e carrega cada DirectNumber da própria extensão, para que um membro possa ser atribuído sua própria linha em vez do que todos a partilharem o número principal do servidor telefónico. Empresa e empresa principal os números são deliberadamente excluídos — tratando aqueles como pessoal daria metade o org um número idêntico "directo". O provedor webhook é expulso de instâncias em vez de uma tabela de símbolos: uma org pode executar mais de um RingCentral phone server, e cada um precisa do seu próprio subscrição contra a sua própria URL de plataforma.
· InitializerService
Adicionar as colunas RingCentral JWT e número direto
Ordem 0, porque as entidades bibliotecárias compartilhadas mapeiam ambas as colunas a partir do momento esta compilação começa: cada corredor que carrega um PhoneExtension ou um MembroVoipOAuthToken através do JPA emite-os em seu SELECT, então um corredor ordenado mais tarde nunca executaria — um anterior morre em "coluna ... não existe" e leva a corrida primeiro. Nada aqui lê uma entidade, então não há nada para esperar atrás. Ambas as declarações são ADD COLUNN SE NÃO EXISTE e ambas as colunas são nulas, então O re-running é um no-op e nenhuma linha é reescrita. As restantes linhas OAuth são deliberadamente deixado no lugar: status é lido a partir de jwt assertion agora, então uma linha velha relatórios "não conectados" em vez de reivindicar um membro é configurado quando eles não são. As colunas também foram aplicadas diretamente a Yugabyte antes do VOIPService Implantação — empurrá-lo sem nada.
· kamo-shared-library
Dê a um membro um RingCentral JWT e uma extensão seu próprio número
Duas colunas, ambas nulas para que nada seja preenchido e nenhuma mudança existente na linha Significado. ************* *** possui o próprio RingCentral JWT. RingCentral apenas prevê uma identidade SIP para a extensão que possui o token apresentado, então um softphone ainda precisa de uma credencial por pessoa; coisa de longa duração que menta-lo, no lugar o token de atualização rotativa usado para Senta-te. As equipes continuam usando o token de atualização, então a tabela agora mantém o que Credencial de longa duração seus problemas de provedor. phone extension.direct number detém a própria entrada da extensão DID. Sem ele O identificador de chamada de um membro só pode ser o número principal do servidor telefónico. por isso "atribuir a este membro o seu próprio número" não tinha onde ser gravado. Extensões que não têm linha direta, e fornecedores que modelam o roteamento de entrada separadamente A partir de extensões, deixá-lo nulo e voltar exatamente como antes. * **************** é marcado aposentado em vez de removido - ids lá são persistentes e o enum é apenas anexo. Já nada o lê. As credenciais de um servidor de telefone RingCentral são emitidas dentro do próprio cliente conta, então eles vivem na instância que os usa.
· VOIPService
A chamada falhada e o correio de voz contam para o indicador de softphone
Reportado como linhas separadas em vez de um total: o ícone mostra a soma e a sua dropdown mostra a degradação, então um valor de fio pré-sumido faria o É impossível. As mensagens de voz são contadas por instância, correspondendo ao conjunto das listas de páginas de mensagens de voz, Por isso, o distintivo e a lista que abre não podem discordar.
· AIService
Contagens de resposta sem revisão e uma leitura de marca
Teclado por guid de sessão, que é o que uma janela de ferramentas carrega. Não auditado como divulgação: retorna conta e nunca uma palavra de uma transcrição, A atualização do distintivo iria enterrar as verdadeiras revelações.
· VOIPService
Um instantâneo não lido, uma leitura de marca e uma moldura ao vivo
Seu próprio assunto NATS em vez da mensagem existente: o manipulador do navegador para /topic/voip/mensage/ toca o som de chegada e abre uma janela de ferramentas para Cada quadro que recebe, então uma atualização de crachá entregue lá iria chiar e estourar um janela cada vez que uma contagem marcada.
· kamo-internal
Disponibilidade apenas para apresentadores, e uma maneira de compreendê-lo
Três coisas, todas sobre a mesma camada. Quem vê isso. A disponibilidade foi mostrada para todos. Horas de declaração é somente significativo para alguém um tipo webinar realmente lista como apresentador — ninguém é um por padrão, e as horas declaradas por qualquer outra pessoa nunca poderiam ser Escolhido por uma alma. A opção, o painel da barra lateral e os gestos da grade são agora tudo retido, a menos que GET /api/webinar/presente volta não vazio, eo gancho começa em um estado de carga para que o controle nunca aparece na primeira pintura e Depois desaparece. Falha ao fechar: um erro esconde a camada em vez de oferecer uma editor cujas horas podem pertencer a nenhuma sessão. O que significa. Um novo painel de barras laterais lista todas as janelas com edição e exclusão, e carrega a explicação. Essa cópia é o ponto do painel: disponibilidade é a superfície rara onde o controle é fácil e o CONCEITO não é, e alguém adicionado como apresentador na semana passada não tem idéia se marcar uma hora os compromete para uma reunião, bloqueia seu calendário, ou cancela algo. Está escrito para um pessoa que nunca viu este sistema — que marcar horas não programa nada, que uma reserva se torna uma reunião real de que eles são informados, que existente reuniões bloqueá-lo automaticamente, e que remover horas nunca cancela nada Já está reservado. Também nomeia as sessões para as quais podem ser reservadas, porque membro pode não saber ao que foram adicionados. Manipulação directa. Arraste a grade vazia para marcar horas; arraste o topo de um bloco ou borda inferior para mudá-lo. Compartilhado pelo dia e semana vistas através de um gancho assim eles não podem derivar. Horas inteiras, porque as fileiras da grade SÃO horas — isso é o contrato que mantém com a coluna agora — então uma criação abre o editor pré-cheio em vez de guardar em silêncio, e meia hora depois fica o trabalho do editor. Um redimensionamento commits direto através: o membro acabou de expressar as horas com seus mãos e pode ver o resultado. A aritmética da linha é separada e testada, porque dois de seus três casos são off-by-ones que lêem como bugs de grade e o terceiro é uma armadilha de dados: um fim em ou antes do seu início é como esta plataforma armazena uma janela OVERNIGHT, O gesto nunca deve produzir um. Um arrasto para o fundo da grelha termina às 23:59, e arrastando uma borda após a outra desmorona em vez de inverter. Também renomeia a aba de configurações para Webinars agendados, na aba, as configurações menu e o cartão de lançamento. Seu valor ?tab= torna-se agendado-webinars e antigo links são reescritos ao invés de aliased, então o URL que um membro passa a compartilhar é o atual — sem isso eles pousariam em Tópicos com a barra de endereço ainda reivindicando o contrário, que é o modo de falha documentado para alterar uma Aqui é a tecla de tabulação. Os pontos de entrada do menu na própria tecla de título da aba para que os dois não possam se afastam por 22 locais.
· BillingService
Fazer um evento Stripe repetido um no-op
Adiciona BillingWebhookEventClaimService em seu próprio feijão, com REQUIRES NOVO em todos os métodos, e fios-lo em processoEvento à frente do interruptor de despacho. Um pedido perdido retorna sem enviar, então o Stripe redelivery de um dinheiro evento não faz nada em vez de escrever duas vezes. A alegação passa por um feijão injetado, nunca este.claim(...): a a auto-invocação ignora o proxy Spring e silenciosamente anula REQUIRES NOV, então um rollback do manipulador rolaria a reivindicação afastado e faria cada retry olhar como um Primeira entrega. CommissionService já enviou esse bug uma vez. A chave da conta remonta ao sentinela PLATFORM não null, porque um NULL componente em uma chave única conflitos com nada em Postgres e iria desativar silenciosamente o dedupe para exatamente os eventos que este endpoint recebe hoje. Também carimba o relógio com o relógio nu. now() lê a zona padrão do pod enquanto a cada outra data no arquivo é construído na UTC. Squashed from two commits: the bean-only commit failed BillingWebhookClaimShapeTest em isolamento, desde que a fiação de campo pousou no segundo. Nada foi empurrado.
· MediaService
GET /api/webinar/presenting
The webinar types the CALLER is a presenter for. The calendar asks this before it offers an availability layer at all: hours declared by a member no type lists can never be booked by anyone, so for almost everybody the honest answer is an empty list and the whole control is withheld. Always about the caller, with no memberId parameter, unlike the availability endpoints beside it — whether a colleague presents something is a fact about the roster and already lives on the type. No right is required: it discloses only which of the organisation's own sessions name the person asking. Narrowed to PublicWebinarTypeDTO rather than WebinarTypeDTO, which carries the rest of the presenter roster including colleagues' email addresses. Title and length are what a 'you can be booked to host these' explanation needs.
· kamo-shared-library
Encontre os tipos que um membro apresenta e analise as consultas
O calendário precisa responder a uma pergunta antes de oferecer uma disponibilidade camada: declarar horas é significativo para esta pessoa? Ninguém é apresentador. padrão, e horas declaradas por um membro nenhuma lista de tipos nunca pode ser reservada. Ambos os estados de registro são verificados. Um webinar soft-eliminado mantém seu apresentador linhas, então testar apenas a linha do apresentador manteria a camada viva para alguém cuja única sessão foi reformada há meses. WebinarQueryParseTest é a outra metade. Uma string JPQL não é verificada pela compilador e dados de mola valida uma consulta anotada quando constrói o REPOSITORY BEAN, assim que um caminho o mapeamento não tem compilações, naves, e então impede o MediaService de começar em tudo — uma implantação de crash-looping em vez de um consulta que não devolve nada. O arnês é o único ClinicalQueryParseTest já usa, apontado para o pacote webinar; os metadados são compilados sobre cada entidade na biblioteca porque um apresentador aponta para um membro da equipa, que aponta em uma organização, e nenhuma base de dados é tocada. Verificado, na verdade, captura um mau caminho antes de confiar nele: quebrando um falha a compilação com o atributo e entidade nomeada.
· MediaService
Tell a member about a webinar booked on their behalf
Not gated on a webinar right, unlike the ticket counters: the case this exists for is one where the member took no action at all, so requiring the right to request a webinar would silence exactly the people who need telling. Also updates SupportControllerClaimTest's direct constructor call, which broke when SupportController gained the WebinarAttendeeRepository dependency.
· kamo-internal
A nova organização abre na sua própria página
Criando uma aba assinada nesta, então um membro que criou uma organização em o nome foi retirado silenciosamente daquele em que trabalhavam — e teve de assinar de volta para ele. A chave única é gasta em uma nova aba agora e esta retorna para /network, onde a nova organização está listada. A mesma sequência que o Enter já usa: a página é reivindicada síncrona dentro do clique, antes de qualquer espera, ou Safari trata como um popup do usuário nunca solicitado; e sua sessãoO armazenamento é limpo primeiro, porque uma janela de origem mesma. open clona esta página, que mantém a sessão para a org ser deixada. Volta a gastar a chave aqui quando os popups estão bloqueados — melhor do que encadernar o membro com um que expira em segundos – e fecha a aba reivindicada em qualquer caminho que tenha Nada para mostrar.
· MediaService
Contar relatórios de erros não revistos para administradores de plataformas
Zero para um chamador ungado em vez de um 403: o navegador pesquisa isso em cada página carregar para cada membro, e um erro que eles devem rotineiramente engolir é quão real erros são ignorados.
· MediaService
Roteia instantâneos não lidos para seu próprio tópico STOMP
Tudo sobre voip.> foi para um tópico, cujo assinante do navegador joga o SMS som de chegada e abre uma janela de ferramentas para cada quadro. Um crachá refresca lá tocaria e abriria uma janela cada vez que uma contagem marcada.
· MediaService
Refresh unread badges when a visitor message lands
persistInbound announces its own message (publishRealtimeEvent=false, so a visitor's reply does not render as the owner's), and in doing so also skipped the unread broadcast the ordinary save path performs. The count was right on a page load and then never moved.
· kamo-internal
Escreva, assine e altere uma nota de visita
O compositor muda de forma uma vez que uma nota é assinada, e isso é o todo Design. Antes de assinar é uma área de texto que salva automaticamente. Após a assinatura a área de texto foi-se e as únicas maneiras de avançar são um addendum ou um alteração — porque uma nota assinada é um registro legal, e uma caixa de edição em um convida exatamente a coisa que torna indefensável um gráfico: um registro que não pode mostrar o que costumava dizer não é corrigido, é alterado. O atestado é mostrado na íntegra antes do sinal, não atrás de uma dica. A A assinatura no texto que o assinante nunca leu não vale nada. O projecto é flushed para o servidor primeiro, porque assinando uma nota cujos últimos quatro segundos nunca chegou atestados de texto o registro não tem. Os três tipos de alterações são escolhidos explicitamente com as suas consequências. escrita ao lado de cada um. Uma adenda deixa a nota de pé; uma emenda corrige-o e mantém o original legível; um §164.526 emenda do paciente registra uma discordância que entra no registro se o clínico ou não Concordo. São instrumentos jurídicos diferentes e a UI diz isso no momento da escolha em vez de em uma página de ajuda. Salvamento automático escreve uma nova VERSION em vez de substituir, incluindo para rascunhos, e a lista de versões mostra os substituídos — é isso que permite Uma correcção deve ser apresentada como correcção. Também salva ao desmontar: a O médico que navega no meio da frase perdeu essa sentença, caso contrário, e eles não vão digitar da mesma forma. O painel de visitas faz com que "chart open" e "chart closed" sejam diferentes Estados, porque eles são fatos diferentes geralmente dias separados. Em todo o lado caso contrário uma visita terminada e uma cuja documentação nunca foi concluída olhar idêntico, que é precisamente por que as práticas carregam semanas de encontros sem perceber. Fechamento recusa enquanto uma nota não é assinada, e o texto de recusa do servidor é mostrado como-is: nomeia a razão, e a genérico "não poderia fechar" iria enviar o clínico olhando no errado Lugar. Timestamps render na zona do MEMBRO via usoFormatters, não o do navegador. Um clínico cobrindo uma clínica em outro estado vê que o relógio da prática em qualquer outro lugar neste aplicativo, e um tempo de poupança que discorda com o próprio sinal da nota lido como um bug em vez de um fuso horário. A aba de visitas é montada apenas quando aberta: carrega o todo de um paciente histórico de documentação, e pagar por isso em cada gráfico aberto faz caso comum lento para o bem do incomum.
· SecurityService
A visita e a sua documentação — o ciclo em que uma prática é executada
Começar uma visita é o que concede ao clínico o gráfico, e isso é o design em vez de um efeito colateral. Um clínico prestes a ver um paciente não tem relacionamento com eles até que a visita comece, e exigindo um administrador para conceder um à mão faria o sistema inutilizável. Então... quarto de um paciente escreve uma relação de cuidados com o tempo, e o registro de POR QUE alguém poderia abrir um gráfico é a própria visita — uma resposta muito melhor na auditoria do que "um administrador concedeu" sem data anexa. Quem quer que seja. quartos que o paciente recebe também: um assistente médico tomando sinais vitais está fazendo trabalho clínico e tem exatamente tanto negócio no registro, para exatamente Até mais. E explica, porque o ponto de uma relação é que termina — um clínico que viu alguém uma vez em 2019 não está ainda em seu Gráfico. Começar é idempotente. Duas pessoas clicando em "iniciar visita" é comum, e dois encontros para uma visita divide a nota da carga. Terminar uma visita e fechar um gráfico são atos separados, geralmente dias separados: a saída do paciente é clínica, sendo o quadro completo administrativa, e uma prática com uma semana de encontros abertos tem problema de fluxo de trabalho que nada mais aparece. Fechando REFUSES enquanto uma nota não assinado — um gráfico fechado com uma nota não assinada é uma visita que parece documentado e não é, e não pode ser cobrado também, porque a nota é que fundamenta a alegação. Deixando-o perto esconde ambos atrás de um verde Tick. Notas nunca são editadas. Cada alteração escreve uma nova versão e a anterior um permanece passível, inclusive para rascunhos não assinados: "o que isso disse antes que o escriba ambiente o reescreva" é uma pergunta que as pessoas fazem, e o O custo da resposta é uma linha. Assinar escreve uma nova versão em vez de carimbar o atual, porque a tabela de versão @PreUpdate lança. Três recusas codificam quem pode fazer o quê. Apenas o autor assina — assinatura a nota de outra pessoa atribui o seu julgamento clínico a eles sob o seu credenciais. Só o supervisor nomeado assina contra-sinais. E um autor não pode contra-assinalar sua própria nota: isso não é supervisão, e sob incidente-para faturar a supervisão é o que torna a reivindicação válida, então um auto-assinado é Uma declaração falsa sobre quem supervisionou os cuidados. Os tipos de emenda não são intercambiáveis e a API recusa uma errada. An Addendum adiciona e a nota permanece; uma ALTERAÇÃO corrige e precisa de razão, com o original retido e apontado; um PATIENT AMENDAMENTO registra um §164.526 desacordo. Um registro que não pode mostrar o que costumava dizer não é corrigido, é alterado. 1269 testes verdes.
· kamo-shared-library
Adicione a tabela dedupe do Webhook da Listra, chaveada por conta e evento
· SecurityService
O endpoint FHIR R4, com as mesmas regras de acesso que o gráfico
Um parâmetro de avaliação da interoperabilidade é o local em que um sistema é mais susceptível de adquirir bypass tranquilo: é máquina-para-máquina, ninguém vê, e "o a integração precisa dela" é uma frase persuasiva. Este não tem bypass. Cada leitura passa pelo ClinicalAccessService exatamente como o screen gráfico — uma relação de cuidado com o paciente específico, não apenas um sessão — e escreve as mesmas linhas de auditoria por registo. Três recusas são deliberadas. 'paciente' é requerido em cada busca, exceto no próprio paciente. Uma pesquisa sem trata-se de uma consulta através de todo o histórico clínico da prática, que é um exportação: uma autorização diferente, uma forma de auditoria diferente e um diferente Conversa com um oficial de conformidade. O acesso em massa pertence a $export onde pode ser tratado como o que é. Uma leitura negada e um registro em falta respondem o mesmo 404, e uma busca negada responde a um conjunto de pesquisa vazio em vez de um erro — caso contrário o resultado contagem é um oráculo com o qual um chamador pode caminhar o espaço id com, aprendendo o que pacientes uma prática tem. Os recursos do compartimento decidem o acesso ao proprietário do registro, nunca em O próprio disco. Decidir sobre o recurso sozinho deixaria qualquer um que Adivinha se um ID de observação leu um. $all everything caps em todos os tipos com as listas críticas de segurança primeiro - alergias, problemas, medicamentos, imunização — então um paciente com quarenta mil observações não podem tirar as suas alergias da resposta. Isso. encomendar é a diferença entre um registro truncado que ainda é seguro para prescrever contra e um que não é. A declaração de capacidade é o único manipulador deliberadamente público, permitido POR NOME em EhrEndpointGuardTest em vez de por um padrão, com dois testes em torno da isenção: asseverando que o responsável não toca em nenhum dado do paciente, asseverando que a lista de allowlist nomeia um manipulador que ainda existe — um isenção para um manipulador renomeado é um buraco à espera de ser herdado por qualquer que seja o seu nome. Erros são o OperationOutcomes em vez de usar o JSON, porque um cliente FHIR analisa o corpo como um recurso qualquer que seja o código de status: entregá-lo {"erro": "..."} produz uma falha de análise em cima de tudo o que deu errado, E a verdadeira razão nunca chega a um humano. finalidade de uso defaults para TRATAMENTO aqui e apenas aqui. Os ecrãs dos gráficos requerê-lo, mas um cliente FHIR é uma máquina que não será atualizada para enviar um parâmetro específico de Kamo, e o tratamento é o padrão conservador — §164.528 exclui-a da contabilidade, portanto uma consulta de pagamento mal marcada sub-relatos em vez de sobre-notificação a um paciente sobre divulgações Isso nunca aconteceu. 1243 testes verdes.
· kamo-internal
Converter qualquer logotipo para vetor, e dizer o que a varredura encontrada por passo
Três coisas, todas relatadas pelo próprio feiticeiro. O LOGO COMPACTO não exige mais um SVG. O slot só pode armazenar um vector -- a infra- estrutura escreve- a num logotipo fixo. svg key -- mas a primeira corte transformou essa regra de armazenamento no problema do membro e escondeu um O logotipo da empresa deles porque era um PNG. A maioria dos sites não tem SVG em nenhum lugar, então o trilho compacto estava vazio exatamente nos sites O exame funcionou melhor. app/lib/logoVectorize.ts encaminha cada arquivo para o caminho mais barato que Funciona, da forma como o Comportamento & Rotulagem já funciona: um SVG entra em linha reta; .eps/.ai/.pdf converter servidor-side sem diálogo, uma vez que eles já conter caminhos e perguntar a um humano sobre eles seria teatro; um raster abre o ImageToSVGConverter do Kamo, porque o tracejamento só precisa de opções A pessoa pode fazer. Os envios e sugestões de digitalização seguem a mesma rota. O Banner agora fala ao seu passo. Costumava recitar todo o scan. em todos os lugares, por isso o passo Fundo disse "encontrado 6 logotipos e marca cores" -- nenhum dos quais está em oferta lá -- enquanto a única coisa que ele é sobre foi não mencionado e sua grade vazia lido como um bug. Cada passo agora relata seu próprio achado, INCLUINDO nada: "não poderia encontrar nenhuma imagem grande suficiente para um fundo de tela cheia. Adicione o seu próprio abaixo." Nomeia o testar as imagens falhou, porque um "nada encontrado" nu em um site o membro sabe que está cheio de fotografias lê como nós não tendo olhado. LOGOS DE LÁBULO BRANQUEADO SÃO OBDIADOS SEM NOME DE SOFTWARE, descrição própria sempre reivindicada. "Onde cada logotipo aparece" também vai: cada o controle nele é uma alternância de marca da empresa-vs-White, então sem uma marca cada tem uma resposta válida, e três dropdowns que não podem ser significativamente A alteração implica uma decisão que o membro não tem de tomar. Compensação da o nome do software também coloca esses valores de volta para COMPANY -- o passo esconde os controles nesse estado, então um SOFTWARE velho nunca poderia ser desfeito. Também remove a geração de fundo de IA desactualizada: a coluna do passo, seus manipuladores e limpeza blob-URL, gerar fundos, o aiPrompt campo, e a rota /api/generate-background.
· kamo-shared-library
Renderize o gráfico como US Core FHIR R4
O construtor JSON é laminado à mão em vez de um Jackson ObjectMapper, e É uma cicatriz em vez de uma preferência. Esta plataforma envia um global Longo-> Serializador de strings em alguns mappers e não em outros; adicionando um a O mapper do SecurityService produziu 401s em toda a plataforma e ids deixar citado quebrou um regex de dígitos nus em outro lugar inteiramente. A FHIR carga útil tem exatamente uma forma correta, e não deve mudar porque Alguém registrou um módulo por uma razão não relacionada a três serviços. Nulls são omitidos, não emitidos. FHIR não tem elemento presente e nulo: "birthDate": nulo é inválido contra a especificação, e um rigoroso o receptor rejeita todo o recurso sobre ele. Os caracteres de controle escapam em vez de cair, porque o texto livre clínico chega de scanners e faxes e silenciosamente apagar um byte da nota de um clínico é pior do que transmiti-lo de forma estranha. Os estados têm o seu sistema. Um receptor corresponde ao par (sistema, código), e "ativo" por si só poderia ser o estado clínico de uma condição, alergia ou a cobertura — três conjuntos de valores diferentes. Um código nu não é parcialmente útil: o receptor deixa cair ou adivinha. Três renderizações codificam fatos que são fáceis de perder e impossíveis de recuperar no lado oposto: - "Nenhuma alergia conhecida" é uma declaração POSITIVA com seu próprio conceito SNOMED (716186003). Enviar uma lista de alergias vazia diz "ninguém perguntou", que é um fato clínico completamente diferente, e o receptor deve então prescrever como se a pergunta estivesse em aberto. - MedicationRequest.intent distingue uma proposta de uma ordem, e Segundo Boolean, esta prática não a escreveu — sem a qual receptor atribui cada droga na lista para nós, incluindo os O paciente apenas nos contou. - Situação de imunizaçãoReason com uma dose não paciente que descodifica de um paciente ninguém perguntou. Apenas o segundo é A diferença de cuidados, tanto do lado deles como do nosso. Raça e etnia render como repetindo EUA Extensões Núcleo em vez de um valor, porque uma pessoa pode ser mais de uma raça e uma única corda modelo apaga exatamente os pacientes multirraciais a exigência de notificação existe para contar. Um gênero administrativo fora de alcance transforma como "outro" em vez de ser ele próprio: um código inválido falha a validação no receptor e leva todo o recurso com ele, de modo que um valor inesperado custaria Todos os registos do paciente em vez de um campo. Um paciente ainda fundido renderiza, com link. Tipo = substituído — respondendo a um titular legítimo de um identificador antigo que o registro nunca existiu transforma uma mescla em perda de dados do lado deles. value[x] emite exatamente um elemento. Emitir dois torna o recurso inválido e um receptor rigoroso rejeita tudo, então "enviar ambos e deixá-los escolher" custa inteiramente a observação. Erros são resultados de operação, e seus diagnósticos não carregam nenhum PHI: e o resultado é frequentemente registado pelo receptor, e o nome de um mensagem de erro é uma revelação para quem lê seus logs. 1890 testes verdes.
· kamo-internal
Dias úteis, dias de fim de semana e todos os dias no campo do dia
Declarar as mesmas horas cinco vezes foi a única forma de dizer: dias de semana. O campo Day agora oferece os três grupos acima dos dias individuais. Uma janela armazena exatamente UM dia e não há endpoint em massa, por isso um grupo é um compondo conveniência no editor: ele salva uma janela por dia, e o que pousa na tabela são linhas ordinárias por dia. Isso é deliberado em vez de um novo conceito de infra-estrutura — «dias de semana, mas não quarta-feira do próximo mês» permanece expressível, E todo leitor existente de uma janela está intocado. Três coisas que a expansão tem que acertar, então a decisão vive em app/lib/availabilityDays.ts onde é testado em vez de no formulário: - Uma edição nunca deve expandir. É uma linha atrás de um botão chamado Atualizar, e Transformá-lo em uma semana deles seria o erro caro. Grupos são retido do menu durante a edição, e diasToSave recusa-se a expandir um Não importa. - Um grupo não deve cair silenciosamente para um dia, que é o mesmo erro em a outra direcção — declararia uma fracção da disponibilidade pedida para parecer que funcionou. - Os dias que já carregam uma janela idêntica são deixados cair, então todos os dias workweek existente adiciona o fim de semana em vez de uma segunda cópia dos cinco Já lá está. Apenas uma correspondência exata é ignorada; sobrepondo janelas em outras Os tempos são legítimos e são deixados em paz. As sentinelas são prefixadas para que nunca possam ser confundidas com um nome de dia e afixado como um — o filtro de agente da rede de chumbo derivante Testa isso. Salvar várias janelas significa falha parcial agora é possível, então os dias que falhou o nome e a lista é recarregada de qualquer forma: os que salvaram são reais, e um formulário ainda mostrando-os como não salvos convidaria um segundo Tente que os duplica.
· kamo-internal
A superfície comercial de um mercado de saúde é o seu ciclo de receita
As outras verticais mostram ordens e acordos porque é aí que as suas O dinheiro é. O dinheiro de uma clínica médica está nos créditos — e especificamente no não mencionarão mais nada. Reclamações rejeitadas lideram a tela e que ordenar é todo o seu argumento. A alegar que uma câmara de compensação rejeitada nunca chegou ao ordenante, pelo que não relatório de negação; nunca foi pago, por isso não está em relatório de pagamento; seu status Mudou uma vez, semanas atrás, e depois nada. Arquivamento oportuno é o segundo porque é o único prazo absoluto no ciclo: passado o dinheiro se foi permanentemente sem recurso, e as práticas geralmente descobrem meses depois. Os procedimentos não cobrados são os últimos e são os mais silenciosos de todos, porque O fracasso é uma linha que nunca foi escrita. Nomeações e encontros deliberadamente não aparecem aqui. Eles vivem em /pacientes, onde se encontram as regras de cuidado-relação — um calendário O ecrã comercial seria uma superfície gráfica sem o controlo de acesso de um gráfico. Vocabulário espelha o Java: uma nomeação é o INTENT, um slot alguém detém e não pode manter; o ENCONTRO é o compromisso, a visita que Aconteceu e a coisa de que uma reivindicação é cobrada. Chamando ambas as "nomeações" perde o número em que todos os outros números dependem. Timestamps na formatação do paciente agora passam pelo parseServerDate. A tabelas clínicas são TIMESTAMPTZ de modo que esses valores carregam um offset, mas o o resto desta plataforma envia o LocalDateTime sem nenhum — um analisador que é certo para ambos fica certo quando uma carga muda de forma por baixo dele. 3033 testes verdes, verificação de tipo 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