Changelog
Cosa c'è di nuovo.
Ogni miglioramento alla piattaforma, come si spedisce.
· kamo-shared-library
Linea, nota, venditore, firma e orologio scrive su un lavoro
SW6b Task 3, biblioteca metà. Otto nuove operazioni su ServiceJobService, più il record di fili per loro e i tre legge la pagina di dettaglio ha bisogno. Tre cose che il server possiede e nessun client può inviare: - I totali. il lavoro totale, il materiale totale e il totale sono calcolati dal le linee di lavoro su ogni riga scrivono, e il totale di una linea è la quantità x UnitAmount. LineInput non ha membri totali e JobInput non ha più Il lavoro e' tre. Erano su JobInput quando SW6a spedito perché c'era nulla da cui derivare; lasciarli una volta che ci sarebbe stato un secondo porta subito oltre la regola. E' quello che e' successo. il lato lontano di quella porta sembra -- ci vuole un subtotale dalla richiesta E aggiunge la sua linea totale a esso, quindi un client che invia entrambi ottiene una cifra che non corrisponde né, che è il fallimento QuoteTotals' javadoc esiste per il nome. - Il timestamp di segnale. signOff timbri signoffAt quando la bandiera va vera e chiarisce quando va falso, in modo che la coppia non possa mai disaccordo. Registrazione porta un testo booleano e libero e non c'è tempo. - L'orologio. orologioVisita francobolli effettivoInizio/fine E muove la visita stato con loro -- ON SITE in, COMPLETATO. Un orologio senza orologio è un IllegalStateException che nomina lo stato della visita (409 al controller): una fine senza inizio contribuisce a zero al totaleLabourMinutes, così il il sintomo sarebbe un foglio di tempo breve per un giorno con nulla che lo dica. Un secondo Anche l'orologio viene rifiutato; un secondo stint è una seconda visita. Ogni bambino viene risolto con il suo lavoro uid E l'org come predica in UN query -- findByUidForJob on the line, vendor and visit repositories. Risolvere da uid e org da solo farebbe DELETE /{jobUid}/lines/{lineUid} raggiungere qualsiasi linea in org attraverso un URL che sembra completamente corretto. JobView acquisisce linee/note/vendori: null nella proiezione dell'elenco (non caricato), sempre riempito nella proiezione dei dettagli (vuoto significa nessuno). Caricarli per fila leggerebbe quattro tavoli per dipingere una griglia che non mostra nessuno di esso. Mutation-tested: 9 mutazioni di questo file, ognuno produce un nome distinto guasto -- cadere il ricomputo, aggiungendo i totali della linea in cima al memorizzato figura, cadere la guardia orologio, non spostare lo stato della visita, non timbrare il segnale-off, non cancellarlo, e risolvere ciascuno dei tre bambini da uid da solo.
· VOIPService
Implement KamoPBX estensione, gestione utente e dispositivo
Il fornitore pubblicizzato estensioneManagement, userManagement e deviceManagement come vero durante l'attuazione di nessuno di loro, quindi l'interfaccia utente avrebbe mostrato pulsanti che butta 501. Le capacità ora corrispondono al comportamento. Un'estensione in KamoPBX è tre documenti — un utente, un dispositivo di proprietà di quell'utente, e un callflow mappando il numero all'utente. Creare solo alcuni di loro produce o un numero che non suona niente o un ricevitore nulla si dirige verso, così tutti e tre sono creati insieme e un fallimento parziale rotola indietro ciò che è stato fatto. Cancellare un'estensione rimuove solo il flusso di chiamata. Un membro può possedere diversi dispositivi, e l'eliminazione del portatile registrato di qualcuno perché un numero è stato rimosso sarebbe una sorpresa molto peggiore di un documento orfano. 253 passano i test, 5 nuove copertine creano, rollback, validazione, eliminazione del campo di applicazione e capacità onestà.
· kamo-shared-library
Linee di lavoro, note e venditori in modo che le schede di ordine di lavoro possono persistere
Lavoro e parti diventano file ServiceJobLine sul lavoro piuttosto che ServiceLineItem righe, perché OrderLineItem.order è facoltativo = falso: a ServiceLineItem non può esistere senza un Ordine e un record tecnico il lavoro molto prima che qualcosa sia fatturato. Rendere il genitore nulla lasciare che un BuyLineItem esista anche al di fuori di un ordine, quindi il test di mappatura Perde invece l'invariante. ServiceJobNote è autore e append-only - no aggiornatoAt, creatoAt updatable = falso e timbrato in @PrePersist. ServiceJobVendor è il la scheda Vendors è sempre visualizzata; il ruolo rimane testo gratuito perché nessun vocabolario di tipo fornitore esiste per congelare nello schema. Ogni repository raggiunge l'org attraverso una EXPLICIT parte del lavoro. L'implicito l.job.organization.id rende come un INNER unire e silenziosamente gocce file la cui associazione è null; ServiceJobLineMapping Test afferma la forma piuttosto che fidarsi di esso.
· kamo-internal
Un carico clinico fallito non deve essere visualizzato come risultato vuoto
Due di questi spediti prima che qualcuno se ne accorse, e la guardia trovò altri due nuovo pannello nel momento in cui ha funzionato — non caricare quali altre pratiche di un paziente hanno già inviato letto come "niente ricevuto ancora", e non riuscire a caricare il partner elenco letto come "nessuno partner di scambio sono impostati", che invierebbe qualcuno per aggiungere partner che già esistono. Ecco perché questa è una guardia di costruzione e non una nota di revisione. Il fallimento è silenzioso da costruzione: nessun errore, nessun log, niente sullo schermo, e sembra esattamente come il stato vuoto sano. Nessuno lo riferirà mai come un bug. Su un grafico un elenco vuoto è una dichiarazione — "non misurazioni", "nessuno in ritardo", "senza allergie" — e la gente agisce su di esso. La stessa distinzione già attraversa il modulo sul lato server: "non hanno nulla" contro "non potremmo chiedere", e 503 piuttosto che un elenco vuoto dal trasporto di scambio. Questo lo fa rispettare il cliente. Passato alle superfici cliniche, perché altri verticali hanno la propria convenzioni. Una cattura che imposta un errore, logs, rethrows, restituisce o ricarica passa — e così si porta un commento spiegando perché il silenzio è giusto, su cui si basa il pazienteCommsPanel: la sua timeline sibling riporta lo stesso outage e un secondo banner direbbe al lettore niente di nuovo. Incatenato alla prova npm.
· SecurityService
Esporre le impostazioni della piattaforma attraverso l'API di configurazione di sistema
toDto è una lista esplicita e l'aggiornamentoConfig prende un corpo digitato, quindi i sette nuove colonne SYSTEM CONFIGURATION sarebbero state invisibili e instabili — le piattaforma impostazioni scheda avrebbe reso vuoto e il risparmio avrebbe fatto Niente. La password dell'amministratore non viene mai restituita. È il maestro delle credenziali dietro ogni account inquilino, quindi un GET produce il sentinel "***" quando impostato e invia "***" indietro significa mantenere - altrimenti salvare qualsiasi altro campo sul modulo sarebbe sovrascrivere le credenziali con la stringa letterale. Gated by MANAGE VOIP SMS accanto ai campi VoIP esistenti, in modo da MANAGE DOCUMENT AI non può raggiungerlo.
· VOIPService
Decrittografare le credenziali KamoPBX; testare il percorso di rifiuto
Le credenziali master vengono memorizzate come cifrario dalle impostazioni della piattaforma UI, quindi deve essere decifrato prima dell'uso — consegnare il testo cifrato all'API come password sarebbe presente come una cattiva credenziale e inviare chiunque lo debug il modo sbagliato. Due nuovi test coprono il percorso di rifiuto che in precedenza ha superficiale un Kubernetes grezzo Errore DNS a un amministratore org: nessun account master id e nessun amministratore credenziali. Entrambi affermano che il messaggio nomina la pagina delle impostazioni. 248 test passano.
· KlusterServices
Passa il saluto in arrivo a KamoCRM-Main-Intro-3
Terza presa, 40 (sotto i 60). Caricato accanto ai due precedenti piuttosto che sopra di loro, in modo da tornare a entrambi è un cambiamento di una linea KAMO ATTENDANT INTRO plus a dialplan reload — no re-upload. 48 kHz sorgente stereo convertito in 8 kHz mono Asterisk richiede. Verificato live: checksum corrisponde al file locale, Asterisk lo ha decodificato a 319914 byte di u-law (39,99 a 8000 B/s), e gli spettacoli CDR BackGround personalizzato/kamocrm-main-intro-3.
· InitializerService
Per-seat storage e una piscina Enterprise
2 GB per posto su Gratis, 4 su Starter, 5 su Business. Enterprise smette di scalare con sedili interamente - un appartamento 150 GB per l'organizzazione - che "N GB per il sedile" non può esprimere, in modo che la riga porta una prosa override le superfici di acquisto ora preferiscono il numero. Unità caratteristica è GB / sedile. L'unità di fatturazione è un posto in tutto; i conti rimangono utenti, essere persone piuttosto che unità.
· kamo-internal
Scheda impostazioni della piattaforma e smettere di mostrare la copia FreePBX
Tre problemi sulla pagina del telefono KamoPBX, tutti miei: - La scheda PHONE SERVER ID è stata sganciata, così ogni fornitore — KamoPBX, RingCentral e Team inclusi — è stato detto di incollare il id in kamo-asterisk-supporto config su un host FreePBX. E 'solo FreePBX e ora rende solo lì. - KamoPBX non aveva alcun contenuto specifico del fornitore. Un org vide un nome, un numero, un gioco attivo e che FreePBX istruzione. Ora prende una carta che dice Kamo lo gestisce, il suo indirizzo SIP, lo stato di provisioning, e cosa fare dopo. - Non c'era alcuna configurazione della piattaforma per KamoPBX, che ha reso il provider inutilizzabile: nulla potrebbe impostare l'account master o le credenziali. Una carta su ?tab=voip-sms ora li possiede e mette in guardia mentre non configurato. Le chiavi del dizionario hanno spinto prima (i messaggi/ sono gitignored qui).
· VOIPService
Leggi la configurazione della piattaforma KamoPBX dal database
L'aggiunta di un server telefonico KamoPBX non è riuscita con un errore DNS Kubernetes raw — "I/O errore su PUT ... ****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** organizzazione amministratore che non può leggere né agire su di esso. Due cause, entrambe fissate: - Il provvista ha tentato la chiamata senza alcuna configurazione della piattaforma. Si'. ora controlla prima e rifiuta con un messaggio actionable che nomina le impostazioni pagina, invece di non aprirsi a un errore DNS. - Le impostazioni erano solo @Value, quindi non c'era modo di configurare KamoPBX senza un Redeploy. Ora provengono dal singleton SYSTEM CONFIGURATION, che il le impostazioni della piattaforma UI scrive; i default di @Value rimangono un fallback in modo che il servizio ancora stivali prima che la migrazione è in esecuzione.
· kamo-shared-library
Impostazioni della piattaforma KamoPBX su SYSTEM CONFIGURATION
KamoPBX è la piattaforma di Kamo, quindi tutta la sua configurazione è su piattaforma: base URL, master account id, nome dell'account, credenziali amministratore, suffisso SIP realm e URL WSS. Siedono sul singleton SYSTEM CONFIGURATION accanto all'esistente VoIP sintonizza in modo che un operatore possa impostarli dalle impostazioni della piattaforma UI invece di aver bisogno di un reinserimento per cambiare una variabile di ambiente. La colonna della password di amministratore è AES-256-GCM ciphertext e trasporta @JsonIgnore: questa riga serializza direttamente alle impostazioni della piattaforma UI, e senza di essa le credenziali master per ogni inquilino sarebbero sul filo.
· InitializerService
Predefiniti della piattaforma Seed KamoPBX
Hibernate ddl-auto aggiunge le colonne SYSTEM CONFIGURATION; @ColumnDefault solo si applica alle righe appena inserite, quindi il singleton esistente ha bisogno di backfilling. Semi i non-segreti di default solo. Il master account id e le credenziali di amministrazione sono deliberatamente lasciati NULL — questo è ciò che rende il rapporto del provvidente 'non configurato ancora' e rifiutare, invece di non aprire o navigare Kubernetes DNS errore a un amministratore org che non può leggere né agire su di esso. Ogni dichiarazione riempie solo un NULL, quindi l'interfaccia utente di un operatore modifica le modifiche sopravvivono a ridicoli.
· kamo-internal
La griglia di lavoro-ordine legge lavori di servizio reali
Ogni fila in questa griglia era un collegamento morto per costruzione. generareMockWorkOrders ids String (8000 + i), il clic di riga ha spinto /commerce/servizio/8001, e il gestore ha dichiarato @PathVariable UUID id — così il id ha fallito la conversione prima qualsiasi gestore corse e la pagina dei dettagli rese il suo stato non-fondato. Quindici file, quindici collegamenti morti, su uno schermo che sembrava finito. Entrambe le superfici ora leggono ServiceJob attraverso l'autorita'. Il proxy esporta GET, PUT e PATCH — esattamente ciò che ServiceJobController mappa, e né il proxy commerciale accanto a esso era un modello sicuro: quotazioni esportazioni GET/POST/PATCH/DELETE senza PUT, service-task-books export GET/POST/PUT/DELETE senza PATCH. Copiare o e uno salvare risposte 405 sollevato da Next stesso, con nulla nei registri del server, mentre ogni lettura continua a funzionare. serviceJobWireContract.test.ts pins the verb set against the controller's annotazioni in entrambe le direzioni e confronta ogni JobView/VisitView/AddressView record componente al membro TypeScript per nome. Quel confronto dei nomi e' la seconda soluzione. PosApi. WorkOrder ha dichiarato serviceName, serviceId e engagementId contro un servizio di invio DTOOfferta Nome, serviceOfferingUid e engagementUid. I tre non si sono mai abbinati, quindi il dettaglio sottotitolo di pagina e la sua riga di riepilogo "Servizio" non sono stati definiti per la vita di lo schermo e cadde a un trattino — che legge come "niente registrato" piuttosto che come tipo, per questo nessuno l'ha trovato. Eliminato 489 righe di un dettaglio Dialogo che non poteva aprire: dettaglioApri è stato falsi inizializzati, setDetailOpen(true) non è apparso da nessuna parte nel file, e selezionatoOrdine è stato indipendentemente sempre nullo. Sei gestori lo hanno nutrito e niente e se ne andò. La sua scheda Note era l'unica nella base di codice, quindi era prima — E' il momento giusto. Partenze da sapere: - Nessun nome tecnico da nessuna parte. ServiceJobApi porta visite[].assignedMemberId e nient'altro, e nessun endpoint risolve un gruppo di id membri a nomi — membroDirectory è una ricerca a pagina la cui nota vieta di tenere il personale lista. La colonna è andata piuttosto che mostrare un id vestito da persona. - "Time Attended", non "Labor Hours". Il server somma totaleLabourMinutes da la finestra reale di ogni visita perché il lavoro a prezzi si blocca da un Ordine senza link a un lavoro. Rendered con formatoLabourMinutes; nessun campo galleggiante ore su da entrambe le parti. - il commercio sostituisce le dieci stringhe di categoria libere, che non erano mai un vocabolario tutto potrebbe fare un giro: "Plumbing Repair" è PLUMBING plus WorkClass.REPAIR. - Lo stato Bulk ora emette un PATCH per lavoro e riferisce rifiuti parziali, perché la macchina di stato controlla ogni transizione. Il vecchio handler imposta il campo localmente su tutti loro e ha segnalato il successo. - Lavoro, parti, voci temporali e venditori rimangono locali useState. Nessuna entita' qualsiasi di loro; SW6b li costruisce. Il dizionario è atterrato prima: kamo-translation-dictionary 947e585.
· kamo-marketing
Le carte di programma mostrano che un livello ADDS, non tutto ha
Le carte elencate ogni funzione inclusa - 16 su Free, 30 su Starter, 52 su Affari, 57 su Enterprise. Quattro carte di altezza selvaggiamente disuguale, ciascuna una parete di testo, e tra loro un riesame quasi completo della tabella di confronto seduto direttamente sotto. I piani sono cumulativi, quindi l'unica domanda che una carta deve rispondere è "che cosa mi fa capire che quello più economico non lo fa». Ogni carta ora conduce con linea di seduta (l'unica figura che non si accumula), dice quale livello costruisce su, elenca al massimo sei differenziatori, e invia il resto al confronto tavolo tramite "e N più caratteristiche". Gocce di affari da 52 linee a otto, il quattro carte vengono fuori quasi uguali, e il tavolo smette di essere un duplicato e inizia essere la destinazione. L'ordine delle caratteristiche ora segue il proprio display order del catalogo. E' stato ordinato. alfabeticamente per nome di categoria, che ha messo "AI & Intelligence" sopra "Core Piattaforma" e sepolto che cosa realmente vende un livello. CONTRATTO: bianco sull'accento dell'oliva misurato 3.78:1 all'estremità scura del gradiente e 3.01:1 alla sua estremità luminosa - sia sotto il 4.5 che 14px semibold etichette bisogno, che è il motivo per cui i pulsanti e i distintivi leggere lavato fuori. Ogni superficie d'accento ora utilizza il colore di sfondo della pagina come inchiostro: 4.53:1 e 5.68:1, con il verde mantenuto a piena forza piuttosto che muddied per salvare il testo bianco. Fallback e JSON-LD conta sedili corretti a 25 / 100 per abbinare il catalogo; hanno detto ancora 5 / 25 dalla stessa confusione che il titolo aveva. Verificato con una costruzione di produzione completa, che ha catturato due fori digitati tsc - NoEmit no.
· kamo-internal
Estrarre la storia di un paziente dalle pratiche che frequentavano
La metà di scambio in uscita, sulla scheda record accanto alla superficie di rilascio — i registri che partono e arrivano sono il lavoro di una persona, e qualcuno che ha appena inviato un riepilogo ad un'altra pratica è la persona più probabile che voglia la loro. Tre passaggi indicati come tre passi, perché questo è ciò che gli standard sono: chiedere se conoscono questa persona, chieda che cosa tengono, prenda quelli che vale la pena avere. Un pulsante "importa tutto" nasconde la decisione centrale e tira un decennio duplicati su un paziente che ha spostato le pratiche due volte. La partita non è mai auto-picked: uno sbagliato legge la storia di un'altra persona in questo grafico. Recuperato e riconciliato non assomiglia mai. Un documento da un'altra pratica è la loro affermazione — si trova attaccato e leggibile, e nulla in esso raggiunge questo problema del grafico, farmaci o allergia elenca fino a quando un ambulatorio registra ciò che essi hanno preso e quello che hanno lasciato. Lo stato vuoto lo dice, perché "riceveto" tranquillamente leggere come "applied" è come una condizione 2019 risolta diventa un problema attivo. Una pratica senza rete a bordo viene detto una volta, chiaramente, invece di essere dato un pulsante che fallisce sempre - e "non hanno record corrispondente a questo paziente" è etichettato come la loro risposta piuttosto che un fallimento da chiedere. Questi due devono mai guardare allo stesso modo: il primo è un fatto clinico che qualcuno può smettere di guardare perché di. Anche catturato dalla guardia i18n e fisso: Ho passato un valore {partner} a un messaggio con nessun tale segnaposto, e il valore era l'ID paziente remoto comunque.
· SecurityService
La metà in uscita di TEFCA — chiedere, non solo rispondere
Tutto costruito finora risponde alle domande degli altri: scoperta, documento query, documento recuperare, la coda di visualizzazione, la contabilità. Una pratica potrebbe essere chiesto e non poteva chiedere — e chiedere è la direzione di un medico in realtà ha bisogno, perché la storia di un nuovo paziente è a qualsiasi pratica essi abituato a frequentare. ExchangeRequest ha portato una colonna di direzione per tutto il tempo e solo INBOUND ci ha scritto. Una domanda in uscita è un'AZIONE, non una divulgazione. Il PHI viaggia verso noi, così nulla qui tocca il registro di rivelazione — registrazione che ci avrebbe messo una linea nel §164.528 di un paziente che dice il loro record è andato da qualche parte esso Sono venuto da qui. Discovery legge demografici dal nostro record, mai dal chiamante. Un punto finale che accetta nomi digitati è un modo per chiedere alla rete "Hai chiunque chiamato questo", che è una capacità diversa e molto peggiore di "mettere la mia la storia del paziente". Ogni passo ha bisogno di VIEW CHART e di un rapporto di cura, scoperta inclusa: che le pratiche tengono record per qualcuno è di per sé informazioni su di loro. Un documento recuperato è archiviato UNRECONCILED e rimane in quel modo fino ad un ambulatorio dice quello che hanno preso. Il riassunto di un'altra pratica è la loro affermazione, non record di questa pratica; auto-merging uno è come una condizione risolta dal 2019 diventa un problema attivo e un farmaco interrotto riappare in una lista qualcuno prescrive contro. La riconciliazione richiede una nota, perché "riconciliata" da sola lascia il prossimo lettore incapace di dire se la storia esterna è nel grafico o ancora solo nell'allegato. Le domande fallite sono registrate con fermezza come quelle di successo, nella loro transazione. "Abbiamo chiesto e hanno rifiutato" è quello che qualcuno indaga un divario la storia di un paziente ha bisogno, e rotolare la fila indietro con il fallimento sarebbe cancellare esattamente il caso che vale la pena mantenere. Il TRASPORTO è un SEAM DELIBERATO. Sotto TEFCA un partecipante autentica con un certificato X.509 rilasciato a norma dell'accordo comune — ottenuto con la firma Accordo partecipativo e completamento del QHIN a bordo, non mettendo una stringa in un database. Questa piattaforma non ha crittografia a riposo per un segreto di quel tipo e nessun rapporto QHIN per ottenere uno da, quindi inventare una colonna di token e chiamando TEFCA produrrebbe qualcosa che sembra federato e si connette a nulla. Che navi è un trasporto che rifiuta ogni chiamata con una frase che nomina il mancante a bordo, e 503 piuttosto che una lista vuota — "nessuno documenti trovati" è un fatto clinico un medico può agire su e "non potevamo chiedere" non è, e un sistema che risponde sia con una lista vuota insegna alle persone a fidarsi di un'assenza che non è mai stato stabilito. Documenti recuperati ottenere il proprio secchio e la loro linea di archiviazione, keyed inquilino-prima come le esportazioni, perché nulla li cancella e una pratica che query la rete accumula ogni sommario che è mai stato inviato. 16 test su tutto sopra la cucitura.
· kamo-shared-library
Una linea per documenti recuperati da altre organizzazioni
Il suo dominio piuttosto che una quota di DOCUMENTI, per il motivo le esportazioni di massa hanno ottenuto una: una pratica che interroga una rete di informazioni sulla salute accumula regolarmente ogni sommario è stato mai inviato, e nulla li cancella — un documento recuperato è la prova di ciò che è stato detto questa pratica e quando, che è quello che più tardi il lettore verifica quando il grafico e la storia esterna non sono d'accordo. Billed anche se i byte provenivano da qualche altra parte. Il deposito è reale, è per questa pratica, ed è tenuto perché questa pratica lo ha chiesto.
· VOIPService
Fornire un account KamoPBX quando viene creato un server telefonico
L'aggiunta di un server telefonico KamoPBX ora crea l'account sottostante e scrive il account id e realm torna a configJson. Qualsiasi configJson il client inviato è SCONTO piuttosto che fuso: non c'è campo legittimo da portare, e accettare uno sarebbe un modo per puntare un org sul conto di un altro inquilino. Un guasto di provisioning lascia la riga dietro marcata non collegata con ragione, piuttosto che eliminarlo — il id può già avere un account creato contro di esso, e l'operatore può riprovare dalla pagina delle istanze. Il client è un fagiolo condiviso in modo che la cache di token venga riutilizzata; la costruzione di uno per chiamata sarebbe riautentico contro KamoPBX su ogni richiesta. kamo.pbx.* sono le impostazioni della piattaforma con le credenziali vuote, quindi un rapporti di piattaforma non configurati 'non configurati' invece di non essere aperti. 246 test passano.
· kamo-internal
KamoPBX è selezionabile
Il fornitore è implementato in VOIPService, così il cancello di prossima uscita. Descrizione non nomina più il progetto a monte e dice cosa realmente conta al compratore: Kamo lo gestisce, e non c'è nulla per iscriversi. Solo la modifica chirurgica. Questo array ora trasporta anche billingClass e feed bloccato il diritto di reason gating da lavoro concomitante, quindi è lasciato in luogo piuttosto che estratti — due fonti di verità per il catalogo del fornitore essere peggio di un lungo file. Dizionario fornitori chiaveBullet1 è stato spinto prima (c822cfeb); messaggi / è gitignored qui così una costruzione locale verde non prova nulla circa la produzione.
· SecurityService
API di lavoro di servizio di destra
****************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** Copies ServiceTaskBookController's idiom: orgId(req) o 401, un controllo destro o 403, una variabile di percorso di stringa attraverso parseUuid o 400, e uno non riuscito() helper dividere il servizio IllegalArgumentException in 404 per una riga mancante e 400 per tutto il resto. Un lavoro mancante è un 404 per abbinare ogni manubrio di fratelli — la pagina di dettaglio rende il suo stato non-fondato da quel codice, e un 400 ci nasconderebbe 'no esiste più a lungo, dietro "la vostra richiesta è stata malformata". Uno status rifiutato la transizione è una richiesta ben formata contro un lavoro che esiste, quindi Il messaggio di ServiceJobStatusMachine che nomina entrambi gli stati raggiunge il cliente come un leggibile 400. Leggi prendere VIEW SERVICE WORK e scrive prendere MANAGE SERVICE WORK, che è un CHILD di VIEW nell'albero dei diritti — così una scrittura che si stabilì per VIEW sarebbe un downgrade silenzioso che ancora sembrava gated in recensione. La prova del cancello chiama ogni scrivere con una sessione di sola vista per dimostrare che non accade. Il test guida i veri gestori piuttosto che incollare la fonte. ServiceTaskBookRightsGateTest dice nel proprio javadoc che una scansione sorgente 'non è possibile dimostrare le operazioni di controllo prima del lavoro'; BaseLosController risolve il sessione da un attributo di richiesta, quindi un MockHttpServletRequest che trasporta una l'elenco dei diritti è sufficiente per leggere il codice di stato reale — e per affermare il servizio non è mai stato raggiunto, che è la metà di una scansione non può vedere: agisce e quindi controlla restituisce 403 avendo già scritto la riga. Mutation-tested: la gestione giusta scambiata per la vista, un controllo destro cancellato outright, il controllo destro spostato dopo la chiamata di servizio, fallito() appiattito a sempre-400, PATCH /status si trasformò in PUT, e l'org della sessione sostituito da un Letterale. Ognuno ha prodotto una distinta mancanza nominando il maniglione in errore.
· kamo-shared-library
API di lettura/scrittura org-scoped per lavori di servizio
ServiceJob è stata un'entità mappata con repository e test di passaggio e Non c'è modo di leggere una fila. Questo gli dà l'intestazione l'interfaccia di lavoro finito già rende, così la griglia può smettere di generare la propria. Formata su ServiceTaskBookApi/Service: String ids e stringhe ISO-8601 sulle filo, orgId prima su ogni metodo, ogni lettura mappata a una vista INSIDE transazione perché ServiceJob.visite è LAZY, e l'inquilino predicato in il JPQL piuttosto che un assegno dopo il carico. ServiceJobRepository già ha portato tutte e quattro le domande, così è intatto. Due decisioni di forma hanno dovuto prendere il DTO: - totaleLabourMinutes è un Integer, mai ore di galleggiamento. Un compito di 20 minuti è 0.333 ore e tre non sono un'ora; ServiceLineItem.labourMinutes discute il caso per la colonna e tiene anche sul filo. È riassunto dalle finestre reali delle visite, che è l'unico lavoro che un lavoro può raggiungere: ServiceLineItem blocca un Ordine senza alcun link a un lavoro. Tempo frequentato, Non e' il momento giusto. - il commercio non è la categoria dell'UI. Dieci corde composte libere contro quindici ServiceTrade costanti, non 1:1 — 'Plumbing Repair' è PLUMBING plus WorkClass.REPAIR, e la classe di lavoro vive su un elemento di linea. Il filo porta il commercio e il cliente rende un'etichetta. Lo stato si muove attraverso ServiceJobStatusMachine e nessun altro luogo, motivo per cui JobInput non ha membro dello stato e StatusInput è il suo record. Uno stato raggiungibile tramite l'aggiornamento generale sarebbe una seconda porta sulla colonna, e la seconda porta è quella che nessuno controlla. I test sono comportamentali, non scansioni di sorgenti: il repository è un proxy il cui trovareByIdForOrg onora l'org e la cui ricercaById deliberatamente non lo fa, quindi una lettura non incorniciata è presa come una perdita piuttosto che come una rottura. Testato di mutazione — asserireTrasmissione cancellata, affermareTrasferimento spostato dopo setStatus, org-scoped query swapped per findById, i minuti convertiti in ore, il stato filtro spostato da SQL, ottenereVisits() lasciato illeggi, \@Transactional rimosso, e un componente 'status' aggiunto a JobInput. Ognuno ha prodotto un distinto fallimento nominare la proprietà che protegge.
· kamo-login
Rivelare lo spazio di lavoro prescelto e dare all'elenco la barra di scorrimento dell'org
Due cose sul picker dello spazio di lavoro, entrambi sulla stessa lista. Lo spazio di lavoro che un membro utilizzato per ultimo è prescelto e nominato sul pulsante, perché questo schermo è una conferma piuttosto che un sondaggio. Ma non c'e' niente che sia andato. A membro di venti organizzazioni il cui solito siede quattordicesimo ha aperto una lista mostrando una riga evidenziata che non potevano vedere, sotto una voce, sopra un pulsante nominare uno spazio di lavoro che non è apparso da nessuna parte sullo schermo. Se la preimpostazione fosse visibile è venuto giù a dove quel org è accaduto cadere nella lista. E 'portato in vista una volta, su aperto, e solo quando è veramente fuori vista — una riga già sullo schermo rimane dove è, perché scorrendo un elenco che non è necessario scorrere legge come la pagina che si muove sotto di voi. Incentrato piuttosto che arrossire a un bordo, così le righe sopra e sotto dicono ancora "questa è una posizione in una lista". `scrollTop` piuttosto che `scrollIntoView`: che scorre ogni antenato rotabile, e su uno schermo di accesso può prendere la pagina con esso. La lista è ora `posizione: relativo` quindi `offsetTop` di una riga viene misurato contro l'elenco stesso — esatto, e a differenza di un recto di rilegatura non è spostato dall'ingresso delle file trasformarsi. La barra di scorrimento è la seconda cosa. Ogni accento su questo schermo è mescolato da `--colore-primario`, che il foglio di stile tema ha già impostato a qualsiasi organizzazione lo schermo è marcato come: la guida di selezione, la fila tint, "Ultima pillola usata", il pulsante. La barra di scorrimento era l'unico pezzo di cromo ancora rendering nel grigio predefinito del browser, che su un inquilino fortemente marcato è l'unico grigio sul pannello. È toni dello stesso token ora — un traslucido pollice che approfondisce su hover, una traccia debole, entrambi arrotondato. Scritto come elemento <style> piuttosto che gli stili in linea il resto di questo componente utilizza, perché una barra di scorrimento è raggiungibile solo attraverso pseudo-elementi. Entrambi i vocabulari sono lì e non è un fallback per l'altro: WebKit e Cromo leggere gli pseudo-elementi e ignorare `scrollbar-color`, Firefox legge `scrollbar-color` e non ha pseudo-elementi.
· VOIPService
Implement the KamoPBX provider
Replaces the stub. KamoPBX is Kamo's own platform, so the organization holds no credential at all: KamoPBXAccountProvisioner creates the account when a phone server is added, and KamoPBXClient mints a short-lived child-scoped token per call from Kamo's single master credential. Auth uses the child account's OWN api_key, read with the master token and exchanged — documented and schema'd. The undocumented as:{account_id,owner_id} claim is deliberately not used: it fails open, returning the full-privilege PARENT token with no error when owner_id is omitted. scopedToken() asserts the returned token is scoped to the child and rejects a parent-scoped one as the privilege escalation it is. Also fixed from the stub: - getCallHistory returned null, which NPEs any caller that iterates. - CDRs are per-leg, so history is collapsed on interaction_id or one call shows up two or three times. - callResult is pinned by test to exactly ANSWERED/NO ANSWER/BUSY/FAILED; anything else silently makes missed-call counters read zero, so unknown hangup causes collapse to FAILED rather than passing through. Platform settings (base URL, master account, admin credential, WSS URL) are @Value-injected and never per-org. 246 tests pass, 29 of them new.
· KlusterServices
App, media, edge manifests e politica di rete
- config.ini porta un blocco [zona] dal primo giorno quindi una seconda regione è una configurazione modificare, non chirurgia. I segreti sono sostituiti da un punto di ingresso all'inizio del contenitore piuttosto che cotto nel ConfigMap. - ecallmgr è co-locato con FreeSWITCH in ONE pod: distribuzione cruda di Erlang, cookie condiviso, no TLS, e dividendoli attraversa il confine 1500/1420 MTU. - Kamailio pubblicizza 47.181.8.87 mentre ascolta 192.168.4.36. - Cilium è inadempiente e toEndpoints:[{}] è namespace-scoped, quindi il esplicito kamo/kamovoip -> kamopbx-apps: 8000 regola è ciò che impedisce Fase 3 fallire come una pausa silenziosa.
· kamo-internal
Blocca la scheda Enterprise
Registra il lato client giusto - elenco, colore, icona - e aggiunge al il test di copertura è set non-tab con una nota su che cosa realmente cancelli, dal momento che esso protegge un'azione attraverso due servizi piuttosto che una scheda Configurazione. La procedura guidata ha reso ogni piano attivo, Enterprise incluso, con un prezzo leggere direttamente dal catalogo. Il server ora tiene quel prezzo e rifiuta l'abbonamento outright, quindi la carta stava per mostrare un piano che non aveva numero per e non poteva comprare. È disabilitato con una nota invece di lasciare qualcuno camminare tutto il mago e incontrare il rifiuto alla fine. Il server è il confine in entrambi i modi - EnterprisePlanGuard in BillingService, e POSController per il prezzo. Questo salva solo il viaggio sprecato.
· BillingService
Rifiutare un abbonamento self-serve Enterprise
L'impresa è negoziata. Nascondere il prezzo è la presentazione; questo è il confine. Una richiesta che nomina il piano Enterprise viene rifiutata a meno che il chiamante detiene # Quindi indovina il codice del piano e pubblicalo # direttamente ottiene la stessa risposta di lettura della console. Fuoco solo su un codice di piano CALLER-SUPPLIED. I riconciliatori di notte ammettono dal vivo sottoscrizioni attraverso lo stesso percorso di aggiornamento con un corpo vuoto e senza HTTP richiesta a tutti - la protezione di un null sarebbe smettere di fatturare ogni cliente negoziato. La regola è "può non nominare questo piano", non "questo piano può non essere toccato". L'identità è risolta esattamente come PlatformAdminInterceptor lo risolve, e il il verdetto è lasciato al PlatformRightsResolver condiviso, quindi questo non può derivare da che cosa SecurityService decide sulla stessa persona. Il rifiuto non nomina alcun permesso. Un cliente ottiene la cosa su cui possono agire. contattarci - non un suggerimento che un diritto esiste e potrebbero ottenerlo.
· SecurityService
Conhold Enterprise prezzi dal catalogo
L'impresa è negoziata direttamente con KamoCRM, quindi il suo tasso non è nostro a pubblicare. Ogni superficie che cita un prezzo di piano legge questo punto finale - il pagina dei prezzi pubblici attraverso il proxy APIService, la procedura guidata in-app e l'imbuto di registrazione - quindi i prezzi sono calati dal payload qui piuttosto che chiedere a tre clienti ciascuno di ricordare a un piano speciale. Una chiamata interna (pubblico-proxy) non ha alcun diritto di piattaforma ed è sempre redatta. Una chiamata di sessione è redatta a meno che il chiamante non detiene E' il momento giusto. La fila del piano rimane: un lettore deve ancora vedere cosa è Enterprise e Si dica di parlarci. Solo i numeri vanno. Questa è la presentazione. EnterprisePlanGuard in BillingService è il confine che rifiuta l'acquisto - qualcuno che indovina il codice del piano e lo posta direttamente ottiene la stessa risposta di qualcuno che legge la console.
· kamo-internal
Mostra cosa dice il grafico prima che la prescrizione sia scritta
Il server ora rifiuta una prescrizione che contrasta con un'allergia registrata, una droga il paziente è già acceso, o un paziente nessuno ha mai chiesto allergie — e restituisce ciò che ha trovato. Questo lo rende. Una carta sotto il modulo piuttosto che un errore in linea, perché la prescrizione è intatta e la prossima azione è una decisione clinica, non una correzione. Alto rischio avvertenze sono marcate: "penicillina" e "penicillina, alta criticità" non sono la stesso avvertimento. Il campo di override pone la domanda — "perché lo prescrivi comunque?" — e il suo aiutante dice a cosa serve la risposta. Prescrizione di un'allergia registrata è una decisione clinica che qualcuno potrebbe aver bisogno di difendere più tardi, e la ragione è che cosa La difende. Il pulsante rimane disattivato fino a quando non c'è uno. "Non prescrivere" siede accanto a esso. Un avvertimento con una sola via d'uscita è un avvertimento le persone imparano a fare clic su. I avvertimenti sono chiariti su ogni nuovo tentativo a meno che non si tratti di una ragione, quindi un riconoscimento digitato per un farmaco non può essere riutilizzato contro uno diverso.
· KlusterServices
CouchDB e RabbitMQ su k3m1
CouchDB q=8 / n=1, verificato dal vivo. q è fissato alla creazione di database e KamoPBX crea un database per account più MODB mensili, quindi q è dimensionato ora per il eventuale cluster a 3 nodi; n può essere sollevato in seguito modificando le mappe shard, q non può. Auto-compazione abilitata — a monte lo spedisce e modello di scrittura di KamoPBX frammenti male. Tre bug di distribuzione trovati e fissi dal vivo: - Montare il ConfigMap su /opt/couchdb/etc/local.d lo rende in sola lettura e il punto di ingresso muore scrivendo docker.ini. Utilizza subPath per il singolo file. - Un volume di Longhorn fresco è di proprietà della radice; il divano funziona come uid 5984 ed è uscito 1 senza uscita di log affatto. Aggiunto fsGroup più un chown initContainer. - conigliomq-diagnostics ha bisogno di più del timeout di sonda predefinito 1s; il server era sano (avvio 9s) ma la sonda ha fallito. RabbitMQ corre come kamopbx, non l'ospite spedito:ospite con loopback users off.
· kamo-shared-library
Dite "i byte sono andati" a parte "la tempesta è giù"
openRange collasssò ogni guasto del nodo in una IOException, quindi un chiamante potrebbe fare niente con esso ma restituire 500. <img> / <video> / <audio> non può rendere un 500 — ottiene un bit, "fallito", e latches su di esso — così un attaccamento il cui oggetto non è mai stato scritto risposto a un pulsante di gioco di un membro andando tranquillo. Il fallimento ci ha raggiunto solo perché qualcuno ha detto "ha mandato ma non possono suonarlo". Le due cause meritano risposte opposte. Contenuto assente è permanente e vale la pena dicendo chiaramente; lo stoccaggio non raggiungibile è transitorio e vale la pena di riprovare. Raise ObjectNotStoredException solo quando la flotta WHOLE ha risposto e ogni risposta è stata NoSuchKey: un nodo che non poteva essere raggiunto potrebbe essere quello che tiene l'oggetto, quindi un mix rimane un IOException ordinario. Dire a un membro il loro file è permanentemente perso durante un'interruzione parziale è l'unico errore qui che non può essere è tornato. Si estende IOException, così tutti e sette i siti di chiamata esistenti continuano a lavorare intatti e optare per la distinzione catturandola prima.

Il tuo universo ti sta aspettando.
Aggiungi i prodotti quando sei pronto: nessuna migrazione, nessun nuovo login, nessuna richiesta di pagamento.
Gratis per sempre — nessuna carta di credito richiesta