Changelog
Cosa c'è di nuovo.
Ogni miglioramento alla piattaforma, come si spedisce.
· kamo-internal
Un "perché non posso accettare?" override sulla barra dei filtri
Allineato a destra sulla barra filtro /leads, indossando l'icona Leads nav con la stessa emblema proibito — così la cosa sul nav che dice "sei bloccato" e la cosa qui che dice "qui è il motivo" sono visibilmente una dichiarazione. Solo reso mentre il membro è bloccato. Non è un filtro che accade essere vuoto, è uno stato che esiste o non lo fa, quindi quando divieto di sgomberi — un evento di accettazione in tempo reale, o un aggiornamento dopo l'ultimo nota è stata scritta — il controllo scompare e i filtri ritornano sul loro proprio. Un effetto cade l'override quando ciò accade: lasciare la guarnizione fili la griglia su un `uid IN ()` che non corrisponde nulla, con i filtri ancora grigi e nessun controllo visibile lasciato per voltarli indietro. Premuta, è overRIDEs piuttosto che restringe. buildLeadGridQuery ritorna presto blockingLeadUids, quindi nessuna scheda di mercato, scheda di stato, agente, data o termine di ricerca vale. Questo è deliberato: i cavi di blocco sono sparsi su qualsiasi cosa mercati e stati in cui si verificano, e l'intersezione con la barra sarebbe mostrare un sottoinsieme durante la lettura come l'intero elenco — esattamente la cosa sbagliata da dire Qualcuno che cerca di farsi sbloccare. Un set vuoto chiede `uid=0` piuttosto che cadere il vincolo, in modo da non poter mai allargare all'organizzazione. Le schede di stato e ogni controllo sulla barra sono grigiati e fatti inerti mentre esso è acceso, perché un bar che sembrava ancora vivo sarebbe mentire su quello che ha scelto righe. Il toggle stesso è escluso dall'attributo in modo da rimanere premuto, e pulsanti azione accanto alle schede non sono filtri in modo da rimanere in diretta. Ripristino del posizionamento su ogni gioco — il set di risultati è diverso e il numero di pagina vecchio Niente contro di esso. Fuori, il pulsante pulsa: è l'unica cosa sulla barra un membro bloccato deve Nota, poiché è per questo che i loro cavi hanno smesso di arrivare. Su, la griglia stessa è il segnale e l'animazione sarebbe rumore. Gli onori preferiscono-ridotta-mozione.
· SecurityService
Elenca, rinomina e termina i terminal di un membro
E' il momento giusto. DELETE e PATCH su /terminals/{id}. Ognuno di loro risolve l'account Linux dalla SESSIONE OWN di CALLER e non passa alcun nome di conto all'agente che è venuto dalla richiesta. Un membro può Pertanto, solo mai vedere, rinominare o porre fine ai propri terminali — non esiste potrebbe fornire che arriverebbe a qualcun altro, perché il conto non è parte di quello che forniscono. Una macchina irraggiungibile risponde a 200 con una lista vuota e `non raggiungibile: true` piuttosto che un errore: "la macchina dev è giù" è un fatto sulla macchina, non un fallimento della domanda, e la console può dire in modo da dove una pagina di errore potrebbe solo dire niente. Questa è la stessa regola DesktopSsoController segue. Rinominare una sessione conclusa è un 404 con una frase — lo stato onesto per "hai rinominato qualcosa che non c'è più", che dopo un riavvio è ogni terminale che il membro aveva.
· KlusterServices
Elenca, rinomina e termina i terminal di un membro
GET /terminals?user=X, POST /terminals / <id>/kill, POST /terminals/δid>/title. Non c'è alcun dato in questo modo, e questo è il disegno piuttosto che una scorciatoia. Il server tmux sulla macchina è il registro: i terminali di un membro sono esattamente le sessioni che esistono, in modo che uno che finisce non venga elencato con nulla riconciliare e riavviare — che prende il server tmux con esso — svuota l'elenco da solo. Un tavolo dovrebbe essere detto tutto questo, e sarebbe sbagliato ogni il tempo non era. I titoli personalizzati vivono in un'opzione utente tmux sulla sessione, quindi un titolo ha lo stesso la vita come il guscio che chiama. I caratteri di controllo vengono rimossi prima dell'archiviazione: un titolo è reso in una lista, e una sequenza di fuga in uno avrebbe riverniciato schermo intorno a esso — stripping è anche ciò che mantiene il separatore di campo fuori valore, che è ciò che rende l'elenco parassibile dividendo su di esso. I titoli sono passato come un unico elemento argv, mai attraverso un guscio. "Nessun server tmux" è un elenco vuoto, non un errore. Questo è lo stato della macchina dopo un riavvio, che è proprio quando il membro ha bisogno della lista per dire "niente qui" piuttosto che fallire. 20 test: la forma di elenco e la sua ordinazione, sessioni senza titolo segnalazione null piuttosto che "", sessioni questo agente non ha creato rimanere invisibile, malformato e le file non numeriche sono saltate piuttosto che fatali, uccidere essere idempotent, titoli spogliati/verniciati/unset, e un titolo contenente metacaratteri di shell arrivare come un elemento argv. Inoltre sorveglia la selezione della pompa contro un descrittore chiuso sotto di esso — lo stesso ordinaria aggancio che termina il percorso rev già gestito. 131 test.
· kamo-internal
Una password scorciatoia nell'eroe, e un cancello più stretto
Due metà dello stesso soggetto. La scorciatoia. Cambiare la password era tre camere profonde dietro la ferrovia — l'unica cosa che il layout della camera reso veramente più difficile da raggiungere rispetto al vecchio scorrere, ed è il controllo più consequenziale dell'account. L'eroe ora porta, deliberatamente NON come una terza pillola di vetro: i due accanto sono destinazioni, questa è un'azione, quindi è solida. Quando il multifattore è spento gira ambra e lo dice così, perché questo è il momento in cui il prompt vale fare. Percorre lo stesso percorso di messa a fuoco che la tavolozza di comando utilizza, quindi si apre la sala di accesso e scorre la scheda di password in vista. Quella strada è ora una funzione condivisa dalla tavolozza, l'anello di forza e questa scorciatoia, piuttosto che tre che potrebbero derivare; i segmenti dell'anello hanno già chiamato i campo che li fissa e ora effettivamente usarlo. PasswordSecurityCard non è un ProfileCard, quindi il suo wrapper trasporta l'ancora di scorrimento. Il cancello. MANAGE MEMBER SECURITY non mostra più la scheda password su il record di qualcun altro — solo il membro stesso o un dio-eleggibile spettatore. Questa è la metà DISPLAY; la metà che conta spediti SecurityService 197b591, che restituisce 403 per la stessa condizione. A destra rimosso da uno schermo è uno schermo di livello, non un controllo di sicurezza. Le chiavi del dizionario sono atterrate prima in kamo-translation-dictionary 982c1f62. Verificato: npm test (14 guardie + 5.139 test), tsc --noEmit, successiva costruzione.
· kamo-internal
Proibito emblema nav, Assegna a me stesso, e mascheramento di contatto offuscato
**L'icona Leads nav dice quando non puoi accettare.** Un membro che detiene i lead loro non hanno lavorato ottiene un emblema di blocco rosso sopra l'icona Leads e un tooltip nominare ciò che è bloccato, perché, e cosa liberare. Fed by /leads/disponibile-sommario e tenuto dal vivo da un nuovo evento di accettazione-gate sulla presa di credito/assegnazione — il payload trasporta solo un id membro, quindi ogni browser ignora tutti gli altri e re-asks il server per il proprio. Mostrato a qualsiasi membro che può vedere i lead, non solo i titolari di credito: da un free-for-all lead può ora essere auto-claimed, il cancello li governa anche. The disponibilità dot rimane solo credito, quindi le due dichiarazioni rimangono separabili — si può essere bloccati da accettare mentre i conducenti siedono lì a disposizione, e quelli sono cose diverse da dire. **Ogni status è chiamato come questo org lo nomina.** Il tooltip, il /leads/avviso disponibile e la copia di dettaglio-pagina risolvere Nuovo Piombo / Farm fresco attraverso l'usoStatusLabels: le etichette sono sostituibili su /settings/features/crm, e dire a un membro di spostare una pista da "New Lead" quando il loro org lo chiama qualcosa altri nomi uno stato che non possono trovare nel raccoglitore. **/leads/avviso disponibile si suddivide nei suoi due motivi** — conduce una nota, porta a un cambiamento di stato — perché fuso in una lista che leggono come un pila indifferenziata e il membro deve aprire ogni piombo per imparare che cosa vuole. Una volta è elencato un piombo che non funziona. **Assegna a me stesso** siede sotto Hot Reassign su una pista non firmata. Offerto su un free-for-all piombo a chiunque non attualmente sbarrato, e su qualsiasi piombo senza firma a un titolare di ASSIGN LEADS. La risposta porta il piombo indietro smascherato, quindi impostarlo in capolinea di stato assegnatoToMe, ricomputa la decisione maschera di UNMASKED, e rivela le informazioni di contatto senza ricarica. **Il controllo dello stato pulsa ** mentre il piombo è mio e ancora a Nuovo Piombo o Farm Fresh — questo è il controllo che lo fissa, e l'intestazione è letto lungo prima di un tooltip nav. Gli onori preferiscono-ridotta-mozione. **Le informazioni di contatto mascherate sono offuscate, non vuote.** contactObfuscator.ts mirrors il ContactObfuscator del server esattamente, affermando le stesse stringhe, perché il in tempo reale, il relè di piombo navi un DTO completamente smascherato ad ogni abbonato nel org e il browser è l'unica cosa che sta davanti a esso. Un campo vuoto legge come "questo piombo non ha e-mail", che è una dichiarazione diversa e sbagliata. **Il filtro /leads Unassigned è offerto a tutti.** Senza VIEW UNASSIGNED LEADS restituisce il non firmato free-for-all conduce questo membro può rivendicare, e l'etichetta dice così piuttosto che l'opzione tranquillamente che significa due cose diverse. Il cliente non più forze assegnate=ASSIGNED per quelli membri — il piano del server è più ampio di quello ora, e l'invio di ASSIGNED sarebbe clip esattamente le righe che questo cambiamento esiste per mostrare.
· SecurityService
Servire il cancello di accettazione allargato, aggiungere auto-assegnamento, e chiudere due bypass di maschera di contatto
**Endpoints for the new gate.** /leads/ available-summary and /leads/ available ora riferire entrambi i motivi che un membro è bloccato — conduce deve una nota in quanto erano assegnato, e conduce ancora al loro stato di assunzione — con i conducenti stessi e lo status wording SYSTEM più ids, così il browser può risolvere il proprio org etichette personalizzate prima di mostrare a chiunque il motivo per cui sono bloccati. bloccatoByComments è tenuto come alias del nuovo `prohibited` quindi un browser ancora in esecuzione il fascio precedente continua a funzionare attraverso il deploy. Il cancello è valutato per chiunque può vedere i lead, non solo i membri che tengono SPEND RECEIVE LEAD CREDIT: un membro che può solo richiedere un comando gratuito per tutti sotto la stessa disciplina e il loro nav deve essere in grado di dirlo. The credit-pool scansione sotto richiede ancora il diritto di credito. **POST /leads/{id}/assign-to-me** sostiene una pista non firmata. Ritorna il piombo UNMASKED — il chiamante è il suo cessionario dal momento in cui il server risponde — che è ciò che consente alla pagina dei dettagli di rivelare le informazioni di contatto senza ricaricare. Un nuovo soggetto NATS... pubblicato quando una nota atterra su una pista, quando uno stato cambia, e su entrambi i lati di ogni incarico cambiamento. Il relè di MediaService si iscrive già a security.leads.> e mappe soggetti a argomenti genericamente, quindi non ha bisogno di modifiche. Il carico utile trasporta solo un membro: la risposta del cancello dipende dall'intero libro di quel membro, quindi c'è nulla di utile per mettere su un argomento di org-wide, e un soggetto ogni membro riceve è il posto sbagliato per tutto ciò che vale la pena di trattenere. ** Due bypass per la maschera di contatto, entrambi hanno trovato l'auditing dove i dettagli di un lead possono raggiungere un browser:** - GET /leads/{id}/history non aveva alcun incarico o cancello di contatto. Un cambiamento di campo log è un record completo di ogni valore che un campo ha mai tenuto, quindi è tornato l'e-mail e i numeri di telefono la maschera del piombo fuori — e non solo il quelli attuali, anche quelli precedenti. Ora ha le stesse due decisioni come getLeadById, e LeadHistoryContactMask obfusca le righe di contatto-portanti. Stato, assegnazione e prestito-importo della storia sono intatti: questo si blocca informazioni di contatto, non il percorso di audit. - GET /leads/callback-context/{id} spedito un indirizzo e-mail e due telefono numeri per qualsiasi callback nell'org, ungated. Un id callback era un modo per leggere i dettagli di contatto di qualsiasi collega. Una guardia di ritorno sull'aggiornamentoLead. La maschera di lettura non più vuoti contatto campi, li ofusca — così un chiamante mascherato ora tiene stringhe realistiche che persevererebbe perfettamente felice. La giusta gerarchia lo rende difficile raggiungere, ma "difficile da raggiungere" non è una garanzia e la modalità di fallimento è silenziosa corruzione del numero di telefono di un cliente. - Si'. Senza VIEW UNASSIGNED LEADS il pavimento /leads diventa "il mio conduce più senza firma free-for-all lead" piuttosto che "i miei lead", e un unssigned free-for-all lead può essere aperto e la sua storia leggere — una fila si può vedi ma non si può aprire è un bug. Leggere il CORRESPONDENCE su uno è un diverso domanda e LeadCommsReadGate risponde ancora con VIEW LEAD CONTACT INFO OTHERS; la griglia-comms portata deliberatamente mantiene il pavimento più stretto, con un commento dicendo perché i due ora differiscono.
· kamo-shared-library
Widen il cancello di accettazione, ofuscate informazioni di contatto mascherato, lasciare libero per tutti i conducenti essere rivendicato
Tre modifiche correlate al nucleo di consegna. **La porta d'accettazione ora fa due domande, su ogni pista assegnata. LeadAcceptEligibilityService sostituisce il cancello di commento che viveva all'interno CreditLeadAssignmentService. Un piombo blocca il suo supporto da prendere un altro quando o non ha alcuna nota da loro scritto SINCE è stato assegnato loro, o è ancora seduto a fresco > Nuovo piombo / Fattoria > Farm fresco. Entrambi chiudono un buco. La vecchia regola contò qualsiasi nota mai scritta, quindi una pista che è tornato a un membro ha passato una nota dal loro precedente stint con esso. E guardava solo i cavi acquisiti attraverso il sistema di auto-assegnazione, che ha lasciato ogni altra strada — l'assegnamento di mano di un manager, un'importazione, un'auto-riclamazione — come un modo per accumulare intatti conduce con la piscina ancora aperto. La regola è di due query basate sul set, qualunque sia la dimensione del libro del membro: assegnazioni attuali, poi un aggregato MediaObj raggruppato sul loro flusso Guids. Ampliamento della portata di ogni assegnazione ha reso il vecchio anello query-per-lead inaccettabile — è la forma che ha reso la griglia /leads lento, e questo corre su ogni rendering della guida nav per ogni membro firmato. Gli stati di blocco sono nominati esplicitamente in LeadStatusType piuttosto che derivati da isAllowSwitchBack. Quei due sono gli unici stati che portano questo bandiera, ma risponde a una domanda diversa, e uno stato futuro segnato lo stesso modo non deve silenziosamente iniziare a bloccare accetta. La corrispondenza è sul sistema memorizzato descrizioni, quindi le etichette di stato personalizzate di un org non influenzano mai la regola. **Le informazioni di contatto mascherate sono offuscate piuttosto che vuote.** ContattoObfuscatore trasforma (555) 555-5555 in (555) 555-**55, snadjafinia@gmail.com in ***************@gmail.com e 123 Main St in *** Main St Un campo vuoto è indistinguibile da uno nessuno riempito in, quindi un visualizzatore limitato non poteva dire "c'è un numero qui che non si può leggere" da "questo piombo non ha numero" — e il personale ha inseguito la seconda lettura. Città, codice postale e paese ora sopravvivono sulla stessa base che lo stato ha sempre fatto: abbastanza grossolano da identificare un duplicato, inutile per raggiungere chiunque una volta che il numero di strada è andato. Data di nascita assente; nessuna forma parziale è riconoscibile e sicura. Il browser lo rispecchia esattamente. LeadRealtime Publisher fan un DTO completamente smascherato fuori ad ogni abbonato nel org senza proiezione per-recipiente possibile. Le suite Java e vitest affermano le stesse stringhe in modo che i due non possano allontanarsi inosservati. **Le porte libere non firmate sono visibili e dichiarabili.** Una pista specifica non firmata. Free-for-all è la porta aperta e porta con sé il cancello di accettazione — altrimenti esso sarebbe il modo per aggirare la disciplina che esiste accanto — e le menti/spese il suo proprio credito esattamente come accetta NextLead fa, così Max Daily Spend ancora lo cattura. ASSIGN LEADS è la porta sopraelevata: qualsiasi piombo non firmato, nessun cancello, nessun credito. Licensing è un vincolo legale e nessuna porta lo rinuncia. LeadGridQuery guadagni E' il momento giusto. girare la griglia permesso piano da "leads assegnato a me" in "leads assegnato a me, più qualsiasi cosa veramente su per afferrare". Nascondere non reclamato free-for-all conduce da tutti senza VIEW UNASSIGNED LEADS li hanno lasciati dichiarabili in teoria e non raggiungibile in pratica.
· kamo-internal
Bandiere sulle lingue, e smettere di copiare liste della piattaforma
Completa c20bac57. Le lingue ora portano la loro bandiera, la stessa che il commutatore NavTop mostra e dalla stessa fonte — il valore chiuso così come ogni riga nel menu. Ottenere lì esposto il vero problema: options.ts era cresciuto copie private di quattro elenchi la piattaforma già possiede, che è come la pagina che ha sostituito ha funzionato anche. • Le lingue erano una copia ridisegnata senza codici di paese, quindi una bandiera non era anche possibile. Ora app/lib/languages.ts, che il commutatore NavTop e il traduttore di chat già condividere. • Le valute erano un seme di 34 entrate contro i 160-odd della piattaforma, quindi un membro pagato in naira o sicli leggere la propria valuta come codice nudo senza simbolo e senza nome. Ora app/constants/currencies.ts. • Le fusi orari sono state ridisegnate dagli stessi 27 nomi. Ora derivato da TIMEZONE ENUM TO IANA, la mappa completa, quindi il raccoglitore non può offrire una zona nulla può risolvere. • La posizione di lavoro mantiene i suoi valori, ma ora sono controllati contro Java enum per prova. Lo status di membro del team rimane un elenco esplicito di proposito: il generato Specchio TypeScript è STALE e mancante CONTRACTS SENT, quindi derivante da ci sarebbe silenziosamente cadere un membro di stato sono veramente impostati a. L'enum Java ha nove; un perno di prova tutti e nove. Le righe del fuso orario mostrano ora che ora è lì. Ventisette nomi enum con il underscores rimosso è un elenco che devi già sapere la risposta a leggere; il tempo è la cosa che viene scelta, quindi è la cosa mostrata. Corregge anche un reclamo il primo commit non ha consegnato: framer-motion non consultare preferi-ridotta-mozione da solo, così la camera crossfade e il salvataggio bar animato indipendentemente dall'impostazione. MotionConfig ridottoMotion="utente" ora copre entrambi; i pezzi CSS-driven già portato loro query. E il campo di campagna rende la sua bandiera nella vista letta, corrispondente al picker che l'ha prodotto. Verificato: npm test (14 guardie + 5.121 test, 70 di loro oltre app/lib/memberProfile), tsc --noEmit, prossima costruzione.
· kamo-internal
Ricostruire il mio profilo come eroe e cinque camere
E' stato un rendering di 1,999 componenti. tredici carte identiche giù una singola colonna. Un aiuto della SezioneCard ha dato tutti loro lo stesso raggio, la stessa ombra, lo stesso chip icona e stesso Modifica / Salva / Annulla trio, quindi "Informazioni sugli account" — due date nessuno può modificare — portato esattamente il peso di "Password & MFA". Il layout era dicendo la verità su una gerarchia che la pagina non aveva. La ricostruzione: • Un eroe che mantiene la risoluzione della carta da parati di MemberHeader verbatim, cicatrice commenti inclusi, e aggiunge l'identità che era solo decorazione: nome come un pezzo di grande tipo della pagina, l'ora locale del membro ticchettio nella zona THEIR, stato MFA, ultimo accesso e un anello di forza. • Cinque camere dietro una rotaia — identità, aspetto, lavoro, accesso, regionale — uno aperto alla volta, portato nell'URL come &room=. Una stanza di cui ogni scheda è gated via per il visualizzatore non rende alcun elemento ferroviario affatto. • Campi Click-to-edit e una barra di salvataggio a livello di camera, sostituendo 39 pulsanti. Salva fan fuori per endpoint sotto allSettled: un gruppo che riesce impegna mentre un gruppo che non riesce mantiene i suoi campi sporchi con una ragione. • Cmd+K su ogni campo, così le camere nascondono le cose senza nasconderle. • Scheletri a forma di carta staggered invece di uno spinner full-tab. Due difetti trovati durante la lettura, fissati qui: • L'indirizzo non ha mai lavorato in direzione EITHER. Il caricatore ha codificato cinque vuote stringhe e mai leggere data.address, che SecurityService fa inviare; e il cliente {strada, città, stato, zip, paese} non è il forma di filo — Member.address è un EmbAddress di {indirizzo, indirizzoDettagli, località, suddivisione, PostalCode, paese}. Così ha reso vuoto per tutti e le chiavi salvate l'entità non porta. Ora usa la forma il resto della piattaforma già invia, con test di andata e ritorno. • "Nome legale:" e "Born " erano letterali inglesi in MemberHeader, e lavoro-localizzazione e occupazione-status etichette erano letterali inglesi nel componente. Tutto nascosto. Struttura. Le regole si sono spostate a app/lib/memberProfile, dove vitest raccoglierli — app/settings/** non è nella lista dei permessi inclusi, quindi un test scritto accanto alla pagina sarebbe passato non correndo mai. campi. la chiave: ogni campo ha dichiarato una volta con la sua stanza, carta, etichetta, cancello e endpoint. La tavolozza, l'anello di forza, il risparmio fan-out e i diritti gating tutti lo leggono invece di reimplementarlo, e 57 test pin le porte giù — compreso che nessun campo è sempre più visibile della sua carta, e che la modifica non è mai più ampio che vedere. Suggerimenti rapidi sono calati solo per questa scheda, omettendo helpTips; SettingsView rende la rotaia dalla scheda attiva, quindi gli altri nove mantengono la loro. Impersonate si sposta dalle impostazioni intestazione all'eroe. Elimina anche ProfileTab.tsx (2,650 linee), LoginSecurityTab.tsx (787) e MembershipPermissionsTab.tsx (2,136), che non aveva importatori. Le chiavi del dizionario sono atterrate prima in kamo-translation-dictionary 4bb91245. Verificato: npm test (14 guardie + 5.106 test), tsc --noEmit, successiva costruzione, e check-i18n-keys --require-messages contro un clone fresco del dizionario.
· kamo-internal
Un vero terminale Linux in una finestra degli strumenti e un sottomenu per raggiungerlo
L'opzione Linux Desktop nav diventa un menu invece di un lancio — Desktop remoto con le sue dimensioni, Terminale remoto — esattamente come il softphone possiede chiamata, segreteria e testo. Un cambiamento di registro lo fa: `kind: 'action'` diventa `kind: 'tool'`, e NavToolButton già rende un submenu in tutti e tre i posizionamenti mentre toolSections è già la fonte condivisa per il nav e la home launchpad, quindi i due non possono allontanarsi. TERMINALE. xterm.js contro un vero e proprio PTY sulla propria macchina dev, quindi è un terminale e non un comando runner: applicazioni alt-screen (vim, htop, meno), 24-bit colore, segnalazione del mouse, pasta staffata, ampia e combinante glifi, cliccabile OSC 8 collegamenti. Nulla è interpretato nel senso attraverso — tastiere sono byte a il PTY e l'output sono byte indietro — che è l'unico modo in cui un terminale è sempre realmente compatibile con quello che le persone corrono in uno. In cima all'emulatore: uno stato chip che pulsa piuttosto che contare sul colore da solo, un titolo che segue il sequenza OSC propria shell in modo da traccia cd e il comando in esecuzione, copy-on-select con Ctrl+Shift+C/V, ricerca Ctrl+Shift+F, zoom Ctrl +/-/0 e una palette che segue il tema dello spettatore. Il guscio vive la finestra. Funziona sotto tmux keyed sulla finestra id, quindi un rinfrescare, una connessione caduta o un riattacca-finestra degli strumenti sessione con il suo scrollback e il suo comando in esecuzione — che è anche per un ha lasciato cadere le connessioni di presa con backoff invece di segnalare un fallimento. The Il trasporto vive in un ******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** xterm, così backoff e la divisione frame sono testabili senza DOM. LA STORIA DESKTOP SIZE È GONE, e con esso DesktopResolutionPicker. Era pronto. su una pagina delle impostazioni quattro schermi da ogni lancio e leggere da localStorage, così "perché ha aperto piccolo?" non aveva risposta da nessuna parte vicino alla cosa che ha aperto piccolo. La dimensione è ora scelta nello stesso clic che apre il desktop; openKamoDesktop lo prende esplicitamente e un chiamante senza alcuna opinione passa `fit`, che è quello che il default è sempre stato. Tre difetti trovati e fissati in auto-review, tutti silenziosi: il manubrio di collegamento è stato attaccato da un effetto che incendi prima che l'emulatore asinciano esiste, quindi mai vincolato a tutti; chiudere una finestra mentre la sua richiesta di biglietto era in volo ancora ha aperto una presa dopo, lasciando un guscio attaccato a nulla che il il tappo per-membro ha continuato a contare; e le decorazioni di ricerca omesse ISearchOptions' due colori REQUIRED-ruler. Digitare le refs xterm invece di `any` è quello che ha catturato l'ultimo. 405 file di prova / 5049 test passa, le 14 guardie sono pulite, tsc è pulito, e il La costruzione di produzione reale ha successo — un tsc verde da solo non dimostra nulla qui. Dizionario spinto prima (115c267f); verificato contro un clone fresco il modo CI lo fa, dal momento che i messaggi locali / è gitignored.
· kamo-internal
Uno stato di quarta finestra — galleggiante, trascinare a staccare, trascinare per riordinare
Una finestra di strumento popup ha avuto tre stati: attraccato in fila lungo la inferiore, massimizzato sopra il viewport, o minimizzato a una testa di chat. Questo aggiunge FLOATING — staccato dalla riga, caduto ovunque sullo schermo, e ridimensionato da qualsiasi bordo — e raggiunge due modi. Il becco. Un controllo nella barra del titolo, indossando la stessa icona che stacca una nota, solleva la finestra dalla fessura che era dentro e le cascate libera dal molo in modo che l'occhio possa seguirlo. Premiato di nuovo torna a la fila. Una finestra massimizzata è invece non massimizzata e incentrata, poiché non ha slot per uscire. IL DRAG, che è la metà interessante. Premere la barra dei titoli e tirare è un gesto con tre risultati, e dove la finestra è lasciato decide quale: - rilasciato con il suo bordo inferiore a 96px del fondo del viewport, ci vuole una fessura nella riga — quindi trascinando una finestra attraccata lateralmente REORDERS il molo, che non era affatto possibile in precedenza; - rilasciato altrove galleggia lì, che per una finestra attraccata è nel momento in cui si stacca. Si stacca esattamente da dove era, quindi nulla salta; - e una finestra galleggiante trascinato indietro giù scatta nella riga come esso si avvicina, alle sue dimensioni standard e in ordine con i suoi vicini. Il fondo EDGE è misurato, non il puntatore: trascinando una finestra da 650px la sua barra del titolo mette il puntatore 600px sopra il molo sul primo telaio, e un test di puntatore avrebbe staccato ogni tentativo di riordinare. Niente si impegna finché non arriva il puntatore. La finestra trasportata, la vicini tremano per fare spazio (o di chiusura ranghi dietro di esso), la goccia rotaia illuminante come il molo vicino e l'alone intorno alla fessura sarà terreno in sono tutte un'anteprima risolta dalla scatola live ogni frame — che è ciò che fa fuggire, e cambiare la vostra mente a metà strada, non costa nulla. Due decisioni più piccole vale la pena di nominare. Finestre Docked sono ora posizionate dal loro bordo TOP piuttosto che pinned con "bottom: 0"; superiore e inferiore sono proprietà diverse e nessuna transizione porta un elemento tra loro, così lo scatto sarebbe saltato comunque era tempo. E "resizable: false" diventa un FLOOR una volta che una finestra è fuori dalla riga piuttosto che un veto — il compositore e-mail è uno degli strumenti a dimensione fissa, e esso è i membri della finestra più vogliono più spazio per. L'ordine di riga e la geometria del galleggiante sopravvivono entrambi a un reload: l'istantanea trasporta la scatola di galleggiamento, la dimensione del dock per tornare a, e l'ordine di array, che è la disposizione di sinistra a destra del membro. Richiede @kamo/tool-core 0.1.6 (setFloating / setFloatGeometry / setWindowOrder), urtato qui.
· SecurityService
Serve Remote Terminal — una vera shell su un WebSocket
Bridges un browser a un PTY sulla propria macchina dev del membro. Cornici binari sono il terminale, i frame di testo sono controllati; sul lungi dall'alto un HTTP 101 su un flusso prefisso lungo raggiunge l'agente sul porto la politica di rete già permessi, quindi non è necessario alcun cambiamento Cilium. Il primo WebSocket in questo servizio, e deliberatamente uno grezzo. STOMP è un messaggio broker su una presa e che cosa viaggia qui è un flusso byte tra un browser e un guscio — una busta intorno ad ogni tasto non compra nulla. AUTORIZZAZIONE SUPERIORE PRIMA DEL SOCKET. Un browser non può mettere un'intestazione su un WebSocket costruttore, quindi piuttosto che insegnare il handshake a parse ***, un il punto finale autenticato ordinario prende l'intera decisione con la sessione mano e la consegna in avanti come biglietto singolo che è inutile 30 secondi poi e ancora dopo un uso. Che rispecchia il link KamoDesktop, che era indurito per esattamente questo motivo: un token riproducibile siede nella storia e nella Ctrl+Shift+T, e una shell è peggio di un desktop, non meglio. La stretta di mano non legge altro dal cliente — non un nome utente, non un conto, solo una dimensione accennare l'agente morsetti comunque. L'account Linux proviene da credenzialiPer(l'identificativo del chiamante id>), quindi una richiesta non può nominare qualcuno La conchiglia dell'altro, e l'Origine è fissata al destinatario. Nessuna password è leggere a tutti: l'agente è radice e scende nel conto, quindi il reversibile le credenziali Guacamole non è mai toccato su questo percorso. Audited prima del fatto, sincronizzato, nello stesso registro di accesso che già risposte "che hanno firmato da dove" — con IP, geo e user-agent, a HIGH gravità. Una fila che è apparso solo sul successo sarebbe mancare esattamente i casi che importa. Otto terminali per membro, perché ciascuno è un PTY e un filo su un VM condivisa che è stata assorbita dalla pressione di memoria prima. La chiusura della presa non uccide la shell; l'agente lo gestisce sotto tmux in modo da rinfrescare o un collegamento abbandonato reattacchi al lavoro ancora in esecuzione. 21 test: uso singolo, scadenza sia lato del silenzio di confine, sconosciuto, per-membro tappo e il suo rilascio, token non sequenziali, e il frame codec tra cui consegna di un byte-at-a-time, una lunghezza dichiarata assurda e lettura la linea di stato dell'aggiornamento senza ingoiare il flusso dietro di esso.
· KlusterServices
Dare all'agente un endpoint PTY per il terminale remoto
GET /pty aggiorna la connessione a `kamo-pty` e diventa un guscio: un PTY per finestra strumento del browser, `su - <user>` in `tmux nuova sessione -A`, cornici pompate entrambi i modi sopra la presa grezza. Una 101 piuttosto che una WebSocket. Il chiamante è SecurityService che tiene il portatore token, non un browser, quindi non c'è motivo di hand-roll RFC 6455 che si inquadra rimanere stdlib-solo. Dopo la linea di stato è `uint32 lunghezza | uint8 tipo | payload` e ThreadingHTTPServer thread-per-connection è esattamente la forma questo ha bisogno. tmux, non un guscio nudo, e questo è l'intero motivo per cui è qui. Un PTY crudo muore con la sua presa, quindi una pagina di aggiornamento, un portatile chiuso o un blip wifi uccidere un costruzione in esecuzione — e kamo-internal restaura le finestre degli strumenti su carico, così un restaurato Il terminal sarebbe tornato a tenere un cadavere. `new-session -A` rende la prima connessione e riconnettere lo stesso comando. La sicurezza segue la regola esistente del file: il nome utente arriva già risolto dalla sessione del membro ed è rivalutato contro USERNAME RE e la elenco riservato prima di iniziare qualsiasi processo, id di sessione vengono controllati perché tmux legge `.` e `: ` come sintassi dell'indirizzo, le dimensioni sono bloccate perché allocate un framebuffer su una macchina condivisa e un account disabilitato viene rifiutato anche se "su" funzionerebbe ancora per esso. Nessuna password è letta a tutti — l'agente è radice e scende all'account, quindi a differenza del percorso Guacamole le credenziali memorizzate non lascia il database. TERM è costretto attraverso `env` perché `su -` ricostruisce l'ambiente da graffio, e un terminale che arriva come `dumb` non ha vim, htop o meno. Le sessioni tmux abbandonate sono potute quando il membro successivo si connette, che ha bisogno né un timer né una lista di ogni account sulla macchina. 24 test: forma argv, rifiuti riservati/invalidi, bloccaggio delle dimensioni, frame codec incluso un telaio diviso tra le letture e una lunghezza dichiarata assurda, controllo La gestione del telaio e i quattro casi del mietitore. Passo 107.
· kamo-shared-library
Registrare un terminale dev-machine nel registro di accesso
Un membro che apre una shell sul desktop-1 ora ha un tipo di evento proprio. Che cosa? macchina detiene un cluster-admin kubeconfig e i suoi account hanno senza password gestione del pacchetto, che è root-equivalent — "che aveva un guscio lì, da quale indirizzo, e quando" deve essere rispondebile dallo stesso Accedi che già risponde per i login. Sicuro da aggiungere: system access logs non comporta alcun vincolo CHECK (verified in produzione oggi) e event type è varchar(30). Contrast PhiResourceType, il cui valore Hibernate-emesso whitelist ddl-auto: l'aggiornamento non si allarga mai.
· SecurityService
Inviare l'azienda al fianco del contatto ovunque sia etichettato un record
Un record che è sia un'organizzazione che una persona si chiama "Harmony Home Prestiti (Nickolas McGarry)" — la società conduce, il contatto si qualifica. Questa regola vive nell'entità del browserLabel(), quindi questi endpoints smettere di scegliere una metà e inviare Entrambi. - La timeline /leads griglia timbrata ogni voce con il contatto e rientra a l'azienda. Stesso piombo, quindi, letto come una persona sulla sua linea temporale e come una azienda sulla griglia che l'ha prodotto. - La storia del credito/assegnamento di piombo ha risolto il solo contatto. Risolto qui piuttosto che nel servizio di storia condiviso perché questo è il suo unico rendering, e si trovaAllById sopra la pagina dei comandi distinti è una singola query. - Una scheda Leads di un account stava inviando {uid, organizzazioneId} e nient'altro, quindi ogni colonna legge "---" e ogni riga collegata a /leads/view/non definita. Ora invia id (che è ciò che quella tabella chiavi e link su), i due nomi ha, stato e dataCreated. L'e-mail del piombo è gated il modo di piombo contatto dettaglio è ovunque: il tuo capo sempre, chiunque altro è solo con VIEW LEAD CONTACT INFO Altri.
· kamo-shared-library
Invia una società di account insieme al suo contatto per i raccoglitori di clienti
Sei raccoglitori del cliente leggono AccountSummaryDTO — l'editor dell'ordine, il servizio-job modulo, dettagli di abbonamento e procedura guidata, e la scheda di registrazione pipeline — e ognuno di loro ha nominato cliente da chiunque fosse il punto di contatto. Qualcuno scegliere quale cliente un lavoro o un ordine appartiene è alla ricerca di organizzazione. DisplayName è ora il contatto ALONE. Portava un suffisso "(#123)", che ha avuto senso mentre era l'intera etichetta e ha prodotto le parentesi nidificate il momento la società lo ha condotto — "Harmony Home Loans (Nickolas McGarry (#123)). L'Uid è già un campo proprio per qualsiasi picker che ha bisogno di separare due clienti con lo stesso nome, e il browser compone le metà attraverso una entitàLabel() che ogni altro schermo rivolto al cliente passa anche attraverso.
· kamo-internal
Comunicazione View — l'intero libro filtrato come una linea temporale
Tre modifiche a /leads. La ricerca rapida si sposta nell'eroe, sopra i link Impostazioni CRM. Nel filtro riga è stato l'ultimo controllo su una linea di undici dropdown, rilevabile solo da scansione oltre tutti loro. LeadManager possiede ancora il viaggio del valore nel query e nello storage di sessione che ripristina la barra del filtro sul ritorno da un piombo — la scatola si è spostata, nient'altro ha fatto. Un flip switch, incentrato nella riga di paginazione: Lead View / Communication View. Due posizioni chiamate piuttosto che un Interruttore, perché nessuno di questi è "off" — sono due modi per guardare lo stesso set filtrato, e una denominazione di controllo uno lascerebbe il lettore indovinando cosa fa l'altra posizione. Communication View sostituisce la griglia con la stessa timeline di un lead La scheda delle comunicazioni estrae — lo stesso componente, lo stesso sei sottotabs, la stessa voce renderrs — indirizzato a qualsiasi cosa la barra filtro attualmente corrisponde. Ogni voce porta un chip che nomina il suo piombo e il collegamento in esso: cross-lead, una fila che fa non dire la cui chiamata era illeggibile, e trovare l'unica conversazione vale la pena l'apertura è l'intero motivo per scansionare la lista. Nessun compositore di nota, deliberatamente: un nota deve essere circa una pista, e una scatola che non poteva dire quale è una trappola piuttosto che una convenienza. Dettagli che sono portanti di carico piuttosto che incidentali: - La pagina della griglia è SUSPENDED in Communication View. G /api/security/leads scrive una riga di accesso PHI per guida ritorna, e fetching una pagina per rendere uno schermo che mostra nessuno di loro metterebbe le letture nell'audit il sentiero che nessuno ha eseguito. - La stringa filtrante consegnata alla timeline è debunced sul ritardo della griglia. La griglia debuisce la sua richiesta; la linea temporale non può — si rifiuta ogni volta che la modifiche di stringhe e incendi due richieste per cambiamento, quindi digitando "smith" era dieci viaggi rotondi, ogni scrittura di un record di ricerca PHI, nessuno di loro abortito. - pagina/dimensione/scelta sono spogliati da esso. dimensione attivamente collide, perché la la linea temporale imposta la propria. Le due tracce del cercapersone rimangono MOUNTED quando svuotano. Un display: nessun bambino è non un elemento griglia affatto, quindi nasconderli avrebbe lasciato l'interruttore come il primo l'oggetto e l'ha messo nella pista sinistra, fuori centro.
· kamo-internal
Aggiungi JustCall come tipo di server telefonico
Aggiunge JustCall al picker con l'API chiave e segreto, un contatto-import toggle, stato delle credenziali sui fornitori scheda, e il logo. La parte interessante è dialling. JustCall non pubblica alcun registrar SIP e nessun Le credenziali WebRTC alle applicazioni di terze parti, e il suo unico outbound-call endpoint guida un agente vocale AI piuttosto che una persona — così il backend segnala voiceCalls=false, che usanoSoftphone già cancelli registrazione su, e non softphone è costruito. Ma un membro di JustCall può mettere una chiamata perfettamente bene, solo non qui, e "le chiamate di fattura non disponibili con il fornitore corrente" sarebbe un bugia. comporre() quindi consegna il numero al proprio web dialler di JustCall. Quel handoff è il suo modulo piuttosto che un ramo all'interno del gancio: è un lib preoccupazione, e metterla lì rende provabile. Usa il web dialler piuttosto che il justcall: protocollo l'app desktop registra, perché un browser non può dire se l'applicazione è installata e una navigazione del protocollo non gestita non fa nulla a tutti — un membro senza l'applicazione farebbe clic comporre e guardare Non succede niente. ProviderCapabilities guadagnato providerTipo in modo che una falsa voceCalls può essere agito su piuttosto che semplicemente segnalato: per la maggior parte dei fornitori significa "no dialling", per questo uno significa "guadagnare là". Specchi SipCredentialsResult.provider, che esiste per la stessa ragione. Il nuovo test di copertura è il gemello frontend di PbxProviderBillingCoverageTest — un fornitore che nessuno ha ricordato di etichetta non fallisce forte, rende come un scheda vuota nella schermata che un amministratore utilizza per sceglierlo. Verificato: tsc clean, tutte le 14 guardie incluse check-i18n-keys --require-messages, 4.938 prove. `next build` NON è stato eseguito contro questi cambiamenti: un altro sessione ha tenuto questa directory di lavoro con le proprie costruzioni contemporaneamente in tutto.
· SecurityService
Una linea temporale di comunicazione sull'intero filtro /leads, non un piombo
# E' la stringa di query # la pagina di dettaglio di piombo tira — attraverso ogni piombo la barra del filtro corrisponde. "Che cosa ha è una domanda su un set, e fino ad ora l'unico modo per chiederlo era aprirli uno alla volta. La traduzione del filtro si sposta a LeadGridFilters in modo che entrambi i endpoint risolvano un la stringa di query identicamente; una seconda copia andrebbe alla deriva, e il modo in cui deriva è un timeline che copre diversi cavi dalla griglia che l'ha prodotto. Due diversi limiti, per due diversi motivi. Chiamate, segreteria, testi e Le e-mail non sono rimbalzate: LEAD COMMUNICATIONS trasporta ORG ID ed è indicizzato su (ORG ID, OCCURRED AT), quindi una query dei tasti cammina la corrispondenza dell'org e testa ogni riga contro il predicato della griglia come correlato EXISTS — lo stesso costo se sette cavi corrispondono o settantamila. Note e la chat non può essere: vivono in MEDIA OBJS, che non porta org e nessuna pista, e l'unico torna indietro è LEADS.STREAM GUID, che non è indicizzato. Quei due risolvi prima i comandi corrispondenti, bloccati a 1000, e la risposta dice quando ha bloccato piuttosto che tranquillamente cadere la storia. L'autorizzazione è la linea temporale principale, applicata in SQL. Una voce porta un piombo proprio numero o indirizzo più contenuto di messaggi, quindi LeadCommsReadGate ora anche stati la sua regola sulle tre forme un piombo può avere ed emette il predicato corrispondente. Scrivere una seconda volta è dove è stato il bug: la prima bozza legge "non firmata ha bisogno di VIEW UNASSIGNED LEADS" e ha mancato il rifiuto() cade THROUGH che il controllo al contatto-info uno, che avrebbe messo ogni portata in piscina di fronte a un membro che tiene solo la piscina destra. Le due forme sono ora fissate l'un l'altro esaustivamente — ogni giusta combinazione contro ogni forma. A differenza del rollup di un account questo NON crolla un evento che ha raggiunto due porta abbinata. Due motivi che indicano lo stesso modo: ogni riga nomina il piombo appartiene a e "questa chiamata raggiunto entrambi" è un fatto circa il libro che viene lavorato, e la raccolta delle righe da una singola pagina a dimensione fissa può lasciare l'ultimo sopravvissuto twin come un ingresso fresco il cliente non può de-duplicare. Le query dei criteri sono estratte in LeadGridCommsQueries come funzioni pure così LeadGridCommunicationsSqlTest può renderli contro i veri metadati Hibernate. Ciò conta qui più del solito: le specifiche proprie della griglia già emettono Esiste sottoquerie, e questo lo nidifica dentro un altro — che è esattamente dove questo servizio è Hibernate 6.2.13 e la biblioteca condivisa 6.5 differiscono.
· VOIPService
Wire JustCall attraverso l'astrazione del fornitore del telefono
JustCall (api.justcall.io/v2.1) come completo PhoneProvider: cronologia delle chiamate, testi, voicemail, registrazioni, directory agente e disponibilità, più firmato account webhooks e un'importazione di contatti facoltativi. Auth è un conto in tutto key/secret pair inviato come il raw "key:secret" valore di autorizzazione — non un Bearer token, che non autentica nulla e restituisce un 401 che legge come un male credenziali. Tre forme di API di JustCall guidano il design: * Voicemail non è una risorsa. È una chiamata la cui call info. tipo è "Voicemail", portando la sua trascrizione in linea e il suo audio dietro lo stesso registrazione endpoint come qualsiasi altra chiamata — così ottenereVoicemails è getCallHistory con un filtro, e non c'è stato di lettura da contrassegnare. * Non ci sono credenziali softphone. JustCall non pubblica alcun registrar SIP e nessun WebRTC token a terze parti, e il suo unico endpoint in uscita guida un Agente vocale AI piuttosto che una persona. voiceCalls è quindi falso, che è che usoSoftphone già cancelli registrazione su, e ottenereSipCredentials rifiuta con una spiegazione invece di mezza registrazione. * La directory è di sola lettura, e non c'è nessun concetto di dispositivo, quindi quelli mantenere l'interfaccia sta gettando i default piuttosto che fingere di scrivere. I Webhooks sono registrati per istanza all'indirizzo. abbonamento per tipo di evento. L'HMAC-SHA256 di JustCall copre l'URL registrato, in modo che la stringa di query è all'interno del materiale firmato e non può essere riscritta atterrare gli eventi di un org sul server di un altro telefono. L'URL è registrato in config json al provisioning perché la verifica deve firmare la stessa stringa JustCall ha fatto — ricostruirlo dalla configurazione avrebbe cominciato a fallire silenziosamente quando l'URL di base è cambiato. I testi in entrata e gli eventi di chiamata raggiungono i sentieri che RingCentral già utilizza. VoipMessageService's handler was RingCentral-shaped in tutto, quindi la sua parsing è diviso dalla sua ingestione: entrambi i binari ora condividono il dedupe, l'intercettazione della parola chiave, conversazione upsert e lead linking. Questa condivisione è deliberata — la parola chiave passo è quello che registra un opt-out, e una seconda ferrovia che cresce la propria copia della la sequenza è come si finisce per non onorare STOP. Interruttore di risposta di SmsKeywordService ha guadagnato la nuova ferrovia per lo stesso motivo: è un interruttore di dichiarazione, quindi un costante non quotata avrebbe risposto a nessuno. MMS è solo per URL pubblico — JustCall non accetta byte caricate — quindi un l'allegato è parcheggiato dietro un URL inguessable di breve durata su questo servizio e che il collegamento è consegnato. Deliberatamente non un oggetto-store URL prefirmato: MinIO Qui c'e' scritto: un URL prefirmato per l'ospite che chiama, e il fetcher di JustCall non può risolvere un indirizzo incluster — sarebbe 404 per loro mentre funziona perfettamente dall'interno del cluster. Questo il servizio è già pubblicamente raggiungibile perché riceve i loro webhooks. L'importazione di contatti è spenta a meno che non sia attivata: è la rubrica del cliente l'accesso per-membro controllato, e l'importazione il momento in cui una chiave è incollata essere una sorpresa. I contatti sono di proprietà tramite l'agente JustCall id la sincronizzazione dell'estensione già registrato, e qualsiasi il cui agente mappa a nessun membro Kamo è saltato piuttosto che parcheggiato da qualche parte condiviso. Persistenza va a EmailService, che possiede il tabelle di contatto. JustCall's AI call sommario, sentimento e punteggio giro sulla stessa chiamata leggere e sono di superficie su CallLogEntry. Non persistito: PHONE CALL LOG non ha tali colonne, il fornitore li restituisce su ogni lettura, e l'aggiunta di colonne costerebbe un DDL finestra per un duplicato del loro negozio. Nessun DDL in questo cambiamento.
· EmailService
Endpoint interno per l'importazione di contatti da un sistema esterno
L'integrazione JustCall di VOIPService ha bisogno di mettere a terra i contatti di un cliente l'indirizzo del membro giusto, e questo è dove i contatti sono scritti: un contatto mappe solo scalari, con le sue email, telefoni, indirizzi, org, URL, IM e relazioni in sette tavoli senza cascata, raggiungibili solo attraverso ContattoStore. Un chiamante che scrive quei tavoli da un altro servizio cadere silenziosamente ogni numero di telefono — l'unico campo che un'integrazione del telefono esiste per consegna — così la persistenza rimane qui e il chiamante ci invia. La proprietà è la parte portante. CONTACT.OWNER ID NON è NULL e punti a utenti, e un proprietario di ContactBook è il suo controllo di accesso (un libro senza proprietario appartiene a nessuno e 404s per tutti), quindi un lotto deve nominare il suo membro i contatti appartengono e si rifiutano in modo definitivo quando non lo fa. Ogni fonte ottiene il suo libro dietro una riga di ContactIntegration piuttosto che essere mescolato in "My Contatti: righe sincronizzate e righe di tipo mano hanno diversi cicli di vita, e membro può nascondere o rilasciare quelli importati senza toccare il proprio. Gli avvisi corrispondono a uid, che il caller namespaces al suo sistema. UID è unico per libro, in modo che sia anche ciò che rende un ri-sincrona un aggiornamento invece di un secondo copia di tutto. montato sotto /api/internal, sorvegliato tutto da InternalAuthFilter — non c'è sessione membro dietro queste chiamate, quindi senza quel filtro questo sarebbe un endpoint per la scrittura di contatti arbitrari nei libri dei membri arbitrari.
· kamo-shared-library
Aggiungi JUST CALL come tipo di provider telefonico
Allegato all'ordinazione 5. EnumType.ORDINAL e non ha alcun vincolo CHECK, quindi l'appending è sicuro e l'inserimento ovunque altri ridefinirebbero silenziosamente le righe esistenti in un fornitore diverso — PbxProviderBillingCoverageTest spilla l'ordine dall'altra parte. Billed THIRD PARTY: l'organizzazione detiene il proprio abbonamento JustCall (il loro API ha bisogno di almeno un Team plan) e JustCall porta le chiamate, quindi questo è un carica di integrazione, non hosting. PbxBillingClass.of non ha un braccio predefinito, che è che cosa ha costretto la decisione piuttosto che lasciare un nuovo fornitore fattura nulla Per sempre.
· kamo-internal
Un colore di carta per blocco, e blocchi che si adattano al loro testo
Ora tocca a loro. I blocchi del lettore erano tutti alti 200px qualunque hanno tenuto, perché RichTextExtension configura l'editor con minHeight: 200px — la forma del compositore dell'articolo, dove l'editore è la pagina. Passare il lettore a RichTextView rimosso; niente nel pannello blocca un l'altezza del blocco ora, quindi è esattamente alto come le sue parole. Gli EDITORI del COMPOSER mettono sotto controllo. Stesso 200px, più overflow: auto sul contenitore, significava che ogni blocco ha aperto tre linee troppo alte e poi si consegna una barra di scorrimento piuttosto che crescere — una barra di scorrimento all'interno di un blocco all'interno del pergamena della pagina. Kb ArticleEditor guadagna `autoGrow`: il contenitore smette di scorrere, l'area di scrittura inizia all'altezza di una linea, e le dimensioni della radice per soddisfare invece di riempire il suo ospite. Opt-in, quindi l'articolo compositore mantiene la forma giusta per un documento di dimensioni pagina. PAPER COLORE. Ogni blocco porta uno, scelto da NoteColorMenu — lo stesso menu e la stessa tavolozza che usano le note e i riquadri di lancio, quindi un orologio significa una cosa attraverso il prodotto piuttosto che tre. Il colore viene memorizzato come ID tavolozza e risolto tramite risolutezzaStickyColor al render, così sia il compositore e l'Interaction Center dipingono da una fonte e una tavolozza successiva la correzione raggiunge gli script scritti oggi. Nel lettore un blocco colorato mantiene il suo colore sia che sia attuale. "Dove sono" è già trasportato dal confine, l'ascensore e il spina dorsale; dimming la carta pure farebbe la scelta dell'autore assomigliare a un rendering difetto.
· kamo-internal
Aggiungi il logo del fornitore JustCall
La cartella del logo VOIP aveva FreePBX, Microsoft e RingCentral ma no JustCall mark, quindi qualsiasi elenco di superficie JustCall come fornitore aveva niente da rendere.
· kamo-shared-library
Colore cartaceo per blocco
"Lemon", "glass" — e mai un valore esagonale. Archiviato il modo in cui le note e i riquadri di lancio memorizzano i loro, per il motivo che la tavolozza è definita una volta sulla client (STICKY PALETTE) e ogni superficie risolve un id attraverso risolvereStickyColor. Persistente hex avrebbe congelato l'ombra di oggi nella fila, quindi una successiva correzione alla tavolozza risolverebbe le note e tranquillamente lasciare la scritture sul vecchio colore — e lo stesso orologio significherebbe poi due diversi cose a seconda di quale schermo è stato scelto. Null non è colore: il blocco indossa qualsiasi superficie siede. Un vuoto o il valore dello spazio bianco è normalizzato a nullo durante il viaggio, perché "" non è "no colore" per risolvereStickyColor - consegna il primo swatch della tavolozza, quindi un autore che ha sgomberato il colore avrebbe avuto il limone. Carried attraverso il blocco completo sostituire come ogni altro campo, e coperto là: il colore sopravvive ad una modifica, e uno sgomberato torna nullo.
· EmailService
Lasciate un messaggio inviato portare immagini nel suo corpo
Il corpo aveva quattro possibili forme e inviare() poteva costruire solo tre. The ramo multipart / relativo — quello che mette un'immagine in cui cid HTML: punti in esso — seduto dietro il ramo allegato, quindi un messaggio con entrambi un incollato immagine e un file ha perso l'immagine sulla via d'uscita: il corpo ha tenuto un cid: riferimento a una parte che non era più nel messaggio, e nulla ha detto così. Era anche non raggiungibile in pratica, perché solo il percorso transazionale mai impostato inlineImages; niente che un membro inviato potrebbe arrivare lì. applicationBody ora costruisce qualsiasi forma il contenuto richiede — html da solo, relativo quando il corpo fa riferimento alle immagini, mescolato quando ci sono allegati, confezionamento misto relativo quando ci sono entrambi — e un invito di calendario mantiene le sue immagini offrendo il relativo come alternativa HTML. rispondere e andare avanti attraverso inviare, così essi eredita tutto. /send prende le immagini come proprie parti binarie, ciascuno chiamato per il contenuto id l'HTML già riferimenti. Base64 nella parte JSON costerebbe di nuovo un terzo in dimensioni contro il più piccolo soffitto della catena, quindi uno screenshot o due sarebbe essere rifiutato per un motivo di cui il membro non poteva fare nulla. Il nome di una parte diventa un intestazione Content-ID, quindi InlineImageParts lo abbina contro la forma esatta compositore menti e rifiuta tutto il resto — uno sbagliato fallisce l'invio piuttosto che cadere tranquillamente e lasciare un buco nel corpo.
· kamo-asterisk-support
Reconcile per-estensione blocchi WebRTC invece di hand-editing un roster
Un'estensione creata tramite l'API di FreePBX non ottiene nessun blocco WebRTC, quindi registra su WSS e quindi non ha DTLS o ICE — il softphone del browser mostra un chiamata collegata senza audio. Queste impostazioni non possono essere espresse da nessuna parte FreePBX li accetterà: `dtls cert file` e `transport` non sono colonne in la tabella `sip` e non i campi sulla mutazione `addExtension`, quindi devono * ***************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************** Fino ad ora quel file era un roster tenuto a mano in un ConfigMap, che significava ogni nuova estensione era silenziosamente rotto fino a quando qualcuno si ricordava di modificarlo e redeploy (888888 sat per mesi). L'estensione 8777 è stata l'ultima. WebRTCReconciler legge l'elenco delle estensioni dal FreePBX-generato pjsip.endpoint.conf e mantiene una sezione gestita limitata in fase con ogni 30. Le estensioni cancellate perdono il blocco automaticamente — un blocco (+) per una sezione che non esiste più rende Asterisk log "Sezione non esiste" su ogni ricarica. Riempi solo le lacune: qualsiasi blocco scritto al di fuori dei nostri marcatori (i KlusterServices roster, un amministratore) è lasciato esattamente come è, mai duplicato e mai preso il controllo. Solo gli endpoint totali sono toccati, quindi i tronchi non sono fissati per un trasporto WS con DTLS forzato. Un pjsip.endpoint.conf mancante è un no-op piuttosto che "lunghezze zero", che altrimenti strisciare WebRTC da ogni estensione che ha uno. OFF per impostazione predefinita (MANAGE WEBRTC ENDPOINTS), su per k1m1. Il blocco è esattamente sbagliato per un telefono da scrivania SIP: forza DTLS-SRTP il telefono non può fare e pin esso a un trasporto che non parla. Due cose misurate sulla scatola live k1m1 piuttosto che assumere: - Il reload deve essere `module reload res pjsip.so`, non `pjsip reload`. Dopo aggiungere un blocco `[8999](+)`, `pjsip reload` lasciato il punto finale su webrtc=no; un modulo di ricarica lo ha applicato, e un modulo di ricarica ha anche reindirizzato quando il il blocco è stato rimosso. Utilizzando il proprio `pjsip reload` qui scrivere un correggere il file e lasciare la configurazione in esecuzione sbagliata. - Un blocco (+) può solo opzioni ADD, mai override. Finanziamenti `direct media=yes` a un endpoint il cui config generato ha detto `direct media=no` ha lasciato su `no` — il primo valore vince. (`webrtc=yes` è il l'eccezione solo perché è una cortina additiva, non un campo memorizzato.) Tutto ciò che deve CHANGE un valore generato deve essere fissato nel FreePBX database. Verificato contro il reale /etc/asterisk: correttamente scelto quello l'estensione scoperta da 23, ha saltato il tronco Erik Primary, ha lasciato l'esistente roster byte-for-byte identico, ed era un no-op sul secondo passaggio.
· kamo-internal
Impersonate, così un operatore può aprire un org come uno dei suoi membri
Mostrato accanto a entrare in ogni vista /network per un amministratore di piattaforma in possesso il nuovo diritto IMPERSONATO. Un diritto diverso da SYSTEM USER e deliberatamente non implicito da esso: entrare come l'Utente del Sistema è un'identità visibile, separata inquilino può vedere nella propria lista membro, mentre questo non produce una sessione nulla a valle può dire da quella persona che firma in se stessi. Il raccoglitore è MemberPickerDialog — lo stesso popup il filtro /leads Agent apre — invariato. Possiede già la ricerca, la paging, la gestione della tastiera e il modo in cui una riga insopportabile si spiega. Ciò che è nuovo è il suo `fetcher`, che sostituisce la directory endpoint outright e punti all'organizzazione di destinazione membri, perché la directory predefinita è il proprio org della sessione e questo è proprio la lista sbagliata. Nessuno viene filtrato sul lato client. Il server segna un account dio, una piattaforma amministratore o un membro non selezionato con un motivo, e la tabella dei motivi del dialogo è cresciuta per coprirli: nascondere quelle righe lascerebbe un operatore alla ricerca di un collega chiaramente nell'organizzazione e ottenere niente indietro, che legge come una ricerca rotta piuttosto che come rifiuto. La scheda viene rivendicata sincronamente all'interno del proprio clic del raccoglitore, prima del attendere, e la sua sessioneStorage sgomberato — la stessa maniglia di balloI documenti dell'utente, per gli stessi due motivi: un popup aperto dopo un'attesa è uno il browser mai ha visto qualcuno chiedere, e una finestra dello stesso inizio.open CLONES lo stoccaggio di questa scheda, sessione inclusa. Aggiunge anche l'icona la scheda Admins Piattaforma esigenze per il nuovo diritto; tsc catturato questo, che è quello per cui RIGHT ICON è un record esaustivo.
· SecurityService
Immettere un'organizzazione inquilina come uno dei suoi membri, da /network
Una seconda porta accanto a quella dio-mode. Gated sul nuovo IMPERSONATO piattaforma destra via @RequirePlatformRight, dove la porta esistente è gated su la sessione con GD. Prese due manici piuttosto che uno con una bandiera. Le loro porte sono veramente diverso, e @RequirePlatformRight non ha variante in-handler da design — un cancello che dovete ricordare di chiamare è uno che alla fine ottiene dimenticata sul punto finale che importava. Chi può essere ENTERED AS è una domanda separata, e ImpersonationTargetRules risponde come una funzione pura sui fatti risolti: rifiutato per il livello superiore org, te stesso, un abbonamento senza utente, l'Utente di sistema, un account dio, un amministratore di piattaforma, o chiunque non poteva firmare in se stessi. Lo stesso la funzione decide se una riga nel raccoglitore è selezionabile, quindi l'elenco non può offrire a qualcuno il punto finale si sarebbe allontanato. La porta stessa-org deliberatamente non condivide queste regole. Funziona dentro la propria organizzazione del chiamante, che per un dio admin è di solito il livello superiore uno, e su persone che sono spesso amministratori stessi — sia duro rifiuti qui. Piegare i due insieme romperebbe la pagina delle impostazioni o allargare tranquillamente questo. Mi riempie il raccoglitore. È l'unico punto di vista che il controllore nomina un'organizzazione diversa dalla sessione, ecco perché è un handler separato piuttosto che un parametro su /search: la promessa della classe che /ricerca non può essere ampliato per caso rimane vero. Le persone rifiutate rimangono in la lista con un motivo piuttosto che svanire da una ricerca di un collega che è chiaramente nell'org. workspaceHost Per spostare EnterAsController in WorkspaceHostResolver, dal entrambe le porte hanno bisogno della risposta identica. Due copie di "che ospite è apribile" è come si continua a inviare gli operatori a un certificato interstiziale dopo l'altro Si e' fermato. I suoi test si sono mossi con esso.
· kamo-shared-library
IMPERSONATO, così un operatore può entrare in un inquilino come uno dei suoi membri
Appendato a PlatformRightType piuttosto che inserito: getSortOrder() restituisce ordinal(), quindi un diritto aggiunto nel centro rinumera ogni destra sotto di esso in console. Le sovvenzioni sono @Enumerated(STRING), quindi l'appending cambia nulla già concesso. Deliberatamente non piegato in SYSTEM USER. Quella destra entra come un visibile, identità separata un inquilino può vedere nella propria lista membro e il percorso di audit; questo produce una sessione nulla a valle può dire dal membro firma in se stessi. Domande diverse, raggio d'esplosione diverso, quindi un operatore il primo non ha quindi diritto al secondo. RelazioneVisibilità Test ha indicato MANAGE REPORTS come il valore LAST, che appending rompe mentre non prova nulla — l'invariante che conta è che nulla era inserito ABOVE, quindi ora spilla l'ordinale invece. Due ricerca di repository batch per il picker dietro di esso: i membri un insieme di gli utenti tengono in una organizzazione, e quale di un insieme di membri sono piattaforma amministratori. Row-at-a-time che è due query per nome, su un controllo che corre su ogni tasto.

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