Changelog
Qué hay de nuevo.
Cada mejora de la plataforma, a medida que se envía.
· KBService
Cierre los barridos compartidos, y ejecute dos vainas
Cada barrido programado aquí cuyo efecto se comparte ahora toma un contrato de arrendamiento distribuido con nombre a través de SingletonTaskRunner antes de hacer nada, así que corre una vez a través de la flota en lugar de una vez por pod. Eso fue lo único que mantiene este servicio en una réplica. esta plataforma, por lo que el conteo de réplicas fue lo que hizo que los barridos corrigieran. Transacción y amigos permanecen en el método OUTER donde está: La primavera los aplica con un proxy, y el método interno se alcanza a través de un esto:: referencia, que nunca pasa por uno. Movirlos hacia adentro dejaría el barrido silenciosamente no transaccional. réplicas 1 - 2o con un PodDisruptionBudget en KlusterServices para que un drenaje de nodos espere.
· ESigService
Cierre los barridos compartidos, y ejecute dos vainas
Cada barrido programado aquí cuyo efecto se comparte ahora toma un contrato de arrendamiento distribuido con nombre a través de SingletonTaskRunner antes de hacer nada, así que corre una vez a través de la flota en lugar de una vez por pod. Eso fue lo único que mantiene este servicio en una réplica. esta plataforma, por lo que el conteo de réplicas fue lo que hizo que los barridos corrigieran. Transacción y amigos permanecen en el método OUTER donde está: La primavera los aplica con un proxy, y el método interno se alcanza a través de un esto:: referencia, que nunca pasa por uno. Movirlos hacia adentro dejaría el barrido silenciosamente no transaccional. réplicas 1 - 2o con un PodDisruptionBudget en KlusterServices para que un drenaje de nodos espere.
· AIService
Cierre los barridos compartidos, y ejecute dos vainas
Cada barrido programado aquí cuyo efecto se comparte ahora toma un contrato de arrendamiento distribuido con nombre a través de SingletonTaskRunner antes de hacer nada, así que corre una vez a través de la flota en lugar de una vez por pod. Eso fue lo único que mantiene este servicio en una réplica. esta plataforma, por lo que el conteo de réplicas fue lo que hizo que los barridos corrigieran. Transacción y amigos permanecen en el método OUTER donde está: La primavera los aplica con un proxy, y el método interno se alcanza a través de un esto:: referencia, que nunca pasa por uno. Movirlos hacia adentro dejaría el barrido silenciosamente no transaccional. réplicas 1 - 2o con un PodDisruptionBudget en KlusterServices para que un drenaje de nodos espere.
· kamo-internal
sesiones de coder junto a las conchas corridas, y una barra de desplazamiento que llega a ambos extremos
Terminales es ahora dos vistas de una máquina Sub-tabs en lugar de dos pestañas de primer nivel, porque no son dos destinos: un terminal es una concha que puede estar corriendo una sesión, una sesión es una conversación que puede tener una concha. El interruptor es un control segmentado, no una segunda pestañas MUI tiras y dos barras de pestañas apiladas se leen como cromo, un raíl segmentado se lee como "uno de Estos dos", que es lo que es. Cada mitad lleva su propia creación, por lo que un solo En la cabecera del navegador (que podría significar uno de ellos) es ahora mostrado sólo mientras colapsaba, donde ninguna de las dos filas encaja. TerminalsWorkbench es compartido por el Centro de Interacción y el máximo navegante, exactamente como ya lo era TerminalsPane, así que los dos no pueden derivar. Es toma la lista de terminales como un apoyo en lugar de volver a votar . Ambas superficies ya aguanta. Dos verbos, y cuál aparece EI el Estado Una sesión que ya está en marcha en un terminal dice **Abierto** y levanta esa ventana. Uno que no se dice **Resume** y abre un terminal que lo recoge de nuevo. Nunca las dos cosas, y nunca una fila discapacitada. Reanudando una sesión que ya está adjunto da una conversación dos cabezas: ambos CLI escriben a la misma La transcripción y la segunda se abre reprochando lo que es la primera en medio de. La regla es una función, "terminalForSession", por lo que nada puede responderla dos veces y de otra manera. la máquina deja un recibo en el momento en que prepara uno y lo dice más bien que ofrecer reanudar algo que aún no se ha escrito. Las sesiones se agrupan de día. Cuatrocientos de ellos en una columna plana es una pared; los mismos cuatrocientos bajo Today / Ayer / A principios de esta semana / Antes es una lista que puedes encontrar ayer por la tarde. La lista mantiene los alrededores reglas: la misma geometría de la hilera y el carril 3px que la lista de terminales, y la misma División tipográfica se establece en la interfaz lo que la máquina reporta está en el mono del emulador. Nada aquí puede pedir un modo de permiso. Cada sesión comienza con permisos sorteados y que se decide sobre la máquina de dev; los nombres de la solicitud qué sesión y nada más. Una prueba pincha que el cliente no puede crecer tal parámetro. La propia barra de desplazamiento del terminal xterm dibuja la barra gris del navegador en su vistaporte, que sólo puede ofrecer "un poco arriba" y "un poco abajo". En un terminal los dos extremos no son dos posiciones más. son los dos lugares que realmente quieres, el comienzo de lo que corriste y el prompt en vivo - para que cada uno tenga un botón: saltar-a-start por encima de la flecha hacia arriba, saltar a punta debajo de la flecha hacia abajo, con la pulsación y la repetición en las flechas, clic a página en la pista y un pulgar arrastrable. la propia barra de xterm está oculta, no rediseñada; el aporte de visión todavía se desplaza, por lo que rueda, trackpad y tacto no cambian. Las luces de botón salto a extremo cuando la salida ha llegado debajo del pliegue. Un terminal que ha dejado de seguir se ve exactamente como uno que ha terminado, y eso es La única cosa que el bar sabe que el lector no puede ver. - Verificación La puerta completa: 14 guardias de origen y 5322 pruebas, más tsc. La nueva IU también fue renderizado en un navegador de un arnés local y leer en lugar de asumir que atrapado con un chip de verbo transparente que muestra el título truncado a través de la palabra "Resume", y un estado vacío que brilló sobre una máquina con cuatrocientos sesiones porque la carga sigue siendo falsa en la representación antes de que el efecto se ejecute. ax-core reporta cero violaciones de WCAG AA en los nuevos componentes. El workbench lleva su propia MotionConfig: el Centro de Interacción envuelve su panel en uno, el navegador no, y enmarcar-momomo fuera uno anima recto a través de los preferidos-reducido-momomo sin una palabra. Las llaves del diccionario aterrizaron primero, como lo requiere CI.
· SecurityService
Enumera las sesiones de codificador de un miembro y abra una en un terminal
Dos endpoints al lado de los terminales, y siguen la misma regla que ellos sí: la cuenta de Linux se resuelve de la sesión de OWN de CALLER y sin nombre de cuenta siempre está arrebatado de la petición. Por lo tanto, un miembro sólo puede ver o reabrir su propias sesiones no hay identificación que puedan suministrar que llegue a alguien de lo contrario, porque la cuenta no es parte de lo que suministran. máquina de dev inalcanzable vuelve 200 con "no-curable": true- y un vacío lista, como hace el listado del terminal: "la máquina ha bajado" es algo que la pestaña puede decir, cuando un error lo deja sin poder decir nada. nueva sesión o se reanuda una existente. Nada se ejecuta cuando el POST regresa. La máquina escribe la sesión abajo y devuelve un recibo; la ventana de la terminal que la consola abre a continuación presenta su billete ordinario, y el recibo es lo que convierte ese terminal en esta sesión. El mismo paso a mano Utiliza Send-to-AI, a través de la misma TerminalDispatchRegistry. El identificador de la ventana se llama AQUI porque ambas mitades lo necesitan: la consola para abrir el ventana, el registro para dar en clave el recibo, y tmux para sobrevivir a la reconexión existe para permitir. Este endpoint no puede expresar un comando, un modelo, un esfuerzo o un modo de permiso. Cada uno de esos es de la máquina. Lo que cruza el alambre es cuál sesión, y nada más, así que, porbypassPermissions, que cada uno de estos las sesiones se llevan a cabo, no es un parámetro aquí y no pueden convertirse en uno. TerminalResumume crece "coderSessionId": la sesión que se está ejecutando una concha, lea fuera de la opción de usuario de tmux que el agente establece. Es lo que deja decir la consola "ya abierto" en lugar de retomar una conversación que está en vivo en otra No hay otro lugar de donde esto pueda venir. La apertura se audita exactamente como abrir una cáscara es el mismo tipo de evento, el mismo ALTA severidad porque es una. Verificado con la prueba de .mvn; Java CI no corre ninguna, por lo que un repo rojo todavía se desplegaría.
· KlusterServices
Mida si un despliegue realmente le cuesta una solicitud a alguien
Cada arreglo en este programa es una afirmación sobre lo que sucede durante un despliegue. Hasta ahora esas reclamaciones no fueron probadas: MediaService envió con estrategia Recrearte en una sola réplica durante toda su vida, así que cada despliegue eliminó el único chat de servicio de la cápsula y los archivos adjuntos y comenzó el reemplazo después un agujero de 65 segundos, varias veces al día y nada lo midió. El primero de todos sabían que era un miembro que reportaba una descarga fallida de documento, e incluso que se leía como una característica escamosa más bien que como chat estando abajo en un horario. Un exportador de blackbox carga ahora a los ocho anfitriones públicos cada 10 segundos. Diez, no el efecto de los 30. el fracaso que esto existe para atrapar es corto por diseño, y a los 30 un gráfico limpio sólo significaría el El agujero cayó entre dos rasguños. Dos alertas importan, y la segunda es la más útil: PublicHostDown, un anfitrión no ha respondido ni por un minuto. Un apagón, despliegue o no. PublicHostFlunte por debajo del 100% de éxito en diez minutos. Este es el que atrapa un lanzamiento. Dejando caer un púmulo de peticiones - se recupera mucho antes de que un 1m 'para' ap. que es precisamente por lo que ese fracaso se reporta como 'me a veces se insinuó al azar fuera y nunca como un incidente. Además de una alerta de certificado (el fallo autofirmado en frío-Traefik no tenía ningún detector), un atascado alerta de despliegue, y una para un Despliegue sentado debajo de su conteo de réplicas deseados . réplicas: 2 sólo ayuda mientras la segunda vaina está realmente arriba, y una que no se ve saludable. La verificación TLS está deliberadamente activada: un certificado que esta plataforma sirve erróneamente debe fallar el sonda, ya que eso es exactamente lo que un Traefik frío solía hacerle a cada org a la vez. monitoreo/ no es un objetivo de aplicación de CI por convención de larga data aquí, por lo que ambos archivos llevan su línea de aplicación.
· KlusterServices
sesiones de código de coder en la máquina de dev, listado y resumible
está aquí, porque la máquina es lo único que sabe de ella. - El índice de sesión en casa, exactamente como sus terminales son lo que sea que los tmux están funcionando. Sin tabla, para el la misma razón: el disco ya sabe, es de lo que el CLI mismo se reanuda, y Memoizado en (mtime, tamaño), y tiene que ser la máquina que se construyó contra contiene 444 sesiones y 1,1 GB de transcripción, una de ellas 205 MB. Sólo el primero y el último 128 KB de cada archivo se lee: el directorio de trabajo, la rama y la el aviso inicial están en los primeros registros, el título generado y el resumen son Apareado a medida que avanza la sesión, y el medio es la herramienta llama. Medidas en contra la tienda real: 2,8s de frío, 17ms caliente. Dos cosas que una transcripción no puede decir Una transcripción no registra que la consola lo inició, por lo que comenzó una sesión sin ella la fila que un miembro acaba de crear falta en la lista que son mirando, que se lee como el botón sin haber hecho nada. Y una transcripción no registra de dónde está siendo expulsada, así que una concha que está ejecutando uno ahora lleva el identificador de sesión como una opción de usuario de tmux (-kamo-coder), al lado del título que ya vive allí. Esa es la regla duplicada: reanudar una sesión que ya está adscrita da una conversación dos cabezas, con ambos CLIs escribiendo a una transcripción y la segunda reprochando lo que el primero está en medio de. Por lo tanto, el listado crece un campo, así que las sesiones de la lista -F. Ahora pide siete, el título se queda después y las estancias divididas se limitaron, porque el separador es imprimible y un miembro puede escribirlo. El llamante todavía nunca proporciona un comando La línea de comandos se compone aquí: la ruta del CLI resuelta bajo la cuenta propia casa, la sesión id acuñada o encontrada en este disco, y -------modo bypassPermissions, que no es un parámetro y no puede ser uno. Los registros preparados ahora llevan un tipo, y uno que es anterior al campo es un Enviar-a-AI hand-off, que es el único tipo que había. El directorio de trabajo es lo único que una petición puede influir y está limitado por camino a la propia casa de la cuenta. Eso no es un límite de privilegio. terminal ya funciona como esa cuenta - mantiene el conjunto de directorios a VER Peticiones puede nombrar más pequeño que el conjunto que una persona puede llegar. Un registro que nombra a la cuenta también sólo es canjeable por el terminal de esa cuenta. 40 nuevas pruebas, 199 en la suite, todas pasajeras. El índice se verifica con la tienda real de 444 sesiones en lugar de accesorios solo. Buqueos por install-agent.sh, no por CI: empujar esto no despliega nada a la VM.
· KlusterServices
Presupuesto cada drenaje, y falle un despliegue que regrese la seguridad de despliegue
PodDisruptionPresupuestos para los 25 Despliegues que ahora realmente ejecutan dos réplicas. minDisponible: 1 deja que un drenaje desaloje una vaina y espere a su reemplazo en lugar de bajar todo un nodo de la misma manera. El espacio de nombres de kamo tenía ZERO de estos mientras los servicios de racimo, kamo-universo, ratestack, El sistema de cuernos largos y kubevirt todos los tenían. La producción de espacio de retención era la única. Sólo aparecen despliegues en dos réplicas. Un PDB en un despliegue de una sola-replicación es peor que ninguno: minDisponible: 1 contra réplicas: 1 permite cero interrupciones, por lo que no protege el La carga de trabajo, bloquea el mantenimiento del nodo para siempre. LEADME.mdd lo dice, y nombra el deliberado solteros que nunca deben ser listados. scripts/auditoría-deploy-safety.sh falla el despliegue si un Despliegue en kamo se ha devuelto a una forma que deja las peticiones durante un despliegue: no hay sonda de preparación, no preStop gancho, no minReadySeconds, Recrea sin un opt-out, o dos réplicas sin que nada las difunda entre los ganglios. Audiciona el CLUSTER en lugar de los manifiestos. Esos escenarios viven en 48 repositorios separados con 48 flujos de trabajo; un guardia por-repoería desperveniría un retroceso antes, pero son 48 copias para conservar en el paso y cualquier repo que nunca lo adopte está en silencio. Cada uno de esos manifiestos termina aquí. El comercio es que es una alarma de humo en lugar de una cerradura, informa después del hecho, por lo que imprime toda la tabla y nombra lo que se desvíaba en lugar de simplemente fallar. Las exenciones son anotaciones sobre el propio despliegue, y una razón es obligatoria: una exención sin uno es un fracaso. Eso es lo que le permite a la siguiente persona decirle a un monotón deliberado (kamodaemon une los duraderos exclusivos NATS) de algo a lo que nadie llegó.
· RAGService
Comparte los consumidores indexados y ejecute dos vainas
RAGService ata dos JetStream duraderos de su propio rag-note-consumer y rag-kb-consumer y un consumidor de empuje duradero sin grupo de entrega admite exactamente un suscriptor. Una segunda vaina se les ha denegado [SUB-90012], dejando la indexación pegada a cualquier cápsula encuadernado primero con nada de tomar el control cuando esa cápsula es la que muere. Ambos ahora se unen a un grupo de entrega, así que NATS entrega cada evento a exactamente una cápsula. Eso es lo que indexó necesidades: una vez, ni una sola vez por vaina, y ni una sola vez por vaina que resultó ganar una carrera. réplicas 1 - 2. Este servicio no funciona sin trabajo programado y no se une a ningún NATS exclusivo duradero, por lo que un La segunda vaina no duplica nada, es una petición apátrida que sirve, y lo único que lo mantiene en Una réplica era que nada había elevado el número. En una réplica maxSurge oculta la exposición durante un despliegue limpio y en ningún otro lugar: una OOM mata, un sonda de vida fallida o un drenaje de nodos sacó la capacidad por completo para los 59-79 segundos a El contexto de primavera toma el arranque. Un PodDisruptionBudget en KlusterServices ahora hace una espera de drenaje.
· VectorService
Ejecute dos vainas
réplicas 1 - 2. Este servicio no funciona sin trabajo programado y no se une a ningún NATS exclusivo duradero, por lo que un La segunda vaina no duplica nada, sino sirvencia a la única cosa que lo mantiene en Una réplica era que nada había elevado el número. En una réplica maxSurge oculta la exposición durante un despliegue limpio y en ninguna otra parte: una OOM mata, a sonda de vida fallida o un drenaje de nodos sacó la capacidad por completo para los 59-79 segundos a El contexto de primavera toma la bota. Un PodDisruptionBudget en KlusterServices ahora hace una espera de drenaje.
· ConversionService
Ejecute dos vainas
réplicas 1 - 2. Este servicio no funciona sin trabajo programado y no se une a ningún NATS exclusivo duradero, por lo que un La segunda vaina no duplica nada, sino sirvencia a la única cosa que lo mantiene en Una réplica era que nada había elevado el número. En una réplica maxSurge oculta la exposición durante un despliegue limpio y en ninguna otra parte: una OOM mata, a sonda de vida fallida o un drenaje de nodos sacó la capacidad por completo para los 59-79 segundos a El contexto de primavera toma la bota. Un PodDisruptionBudget en KlusterServices ahora hace una espera de drenaje.
· APIService
Ejecute dos vainas
réplicas 1 - 2. Este servicio no funciona sin trabajo programado y no se une a ningún NATS exclusivo duradero, por lo que un La segunda vaina no duplica nada, sino sirvencia a la única cosa que lo mantiene en Una réplica era que nada había elevado el número. En una réplica maxSurge oculta la exposición durante un despliegue limpio y en ninguna otra parte: una OOM mata, a sonda de vida fallida o un drenaje de nodos sacó la capacidad por completo para los 59-79 segundos a El contexto de primavera toma la bota. Un PodDisruptionBudget en KlusterServices ahora hace una espera de drenaje.
· kamo-internal
Contesta una sonda de preparación y dirige dos vainas
Este despliegue no tenía sonda de preparación, por lo que una vaina contaba como Ready el instante de su contenedor proceso iniciado. Con maxUnavailable 0 Kubernetes lee que como "la nueva vaina está sirviendo" y retira el antiguo, mientras que Next sigue rubricando y no ha obligado a su puerto. Solicitudes aterrizadas En un puerto nada estaba escuchando, que es de donde provenían los intermitentes 502 en despliegue. /api/salud responde sólo para esta vaina y deliberadamente toca sin backend: una sonda de preparación decide si esta cápsula deja el Servicio, y cablearlo a un backend gira un backend blip en un Reinicio de cada cápsula aquí. El drenaje y el período de gracia de los 660 ya estaban aquí; la sonda faltante es lo que los detuvo Contando. Kubernetes estaba retirando la vaina drenante antes de que el reemplazo pudiera servir. réplicas 1 - 2. Estado del lado del servidor vive en Redis, no en la cápsula, y no hay trabajo programado duplicar, por lo que una segunda réplica no cambia nada excepto que perder una vaina deja de ser un apagón. En una réplica una OOM matar, una sonda de vida fallida o un drenaje de ganglios se llevó todo por el tiempo que sea necesario para arrancar. topologíaSpreadConstraints (añadidas antes, inerte hasta ahora) mantienen los dos en diferentes nodos donde el racimo puede manejarlo, y un PodDisruptionBudget en KlusterServices hace una espera de drenaje.
· kamo-marketing
Escurrir en SIGTERM y ejecutar dos vainas
Siguiente maneja SIGTERM con un proceso desnudo.exit(143), para que cada despliegue se corte lo que sea esta vaina tenía en vuelo, un poste de formulario, una acción de servidor, una carga RSC en streaming, una carga. Invisible cuando a La petición duró milisegundos; no invisible en un clúster que se despliega en cada empuje. scripts/standalone-entry.cjs envuelve el servidor independiente: en SIGTERM deja de aceptar, deja inaccionar mantener-alimaves a la vez para que una vaina sin nada en vuelo todavía sale en aproximadamente un segundo, y deja correr las solicitudes terminan bajo un tope que se encuentra por debajo de la terminaciónGracePeriodSeconds. Portado de kamo-internal, que lo ha llevado a cabo en producción durante meses. El envoltorio inicia server-nonce.js en vez de server.js, a través de NEXT-SERVER-ENTRY. el servidor se queda exactamente donde estaba en la cadena. réplicas 1 - 2. Estado del lado del servidor vive en Redis, no en la cápsula, y no hay trabajo programado para duplicar, por lo que una segunda réplica no cambia nada excepto que perder una vaina deja de ser un apagón. En una réplica una OOM matar, una fallida sonda de vivacidad o un drenaje de ganglios se llevó todo por el tiempo que sea necesario para arrancar. topologíaSpreadConstraints (añadidos antes, inerte hasta ahora) mantener los dos en diferentes nodos donde el racimo puede manejarlo, y un PodDisruptionBudget en KlusterServices hace una espera de drenaje.
· kamo-capcha
Ejecute dos vainas
réplicas 1 - 2. Estado del lado del servidor vive en Redis, no en la cápsula, y no hay trabajo programado para duplicar, por lo que una segunda réplica no cambia nada excepto que perder una vaina deja de ser un apagón. En una réplica una OOM mata, una sonda de vida fallida o un drenaje de ganglios se llevó todo el asunto por siempre que sea necesario para arrancar. topologíaSpreadConstraints (agregados anteriormente, inertes hasta ahora) mantienen los dos en diferentes nodos donde el racimo puede manejarlo, y un PodDisruptionBudget en KlusterServices hace una espera de drenaje.
· kamo-register
Escurrir en SIGTERM, responder una sonda de preparación y ejecutar dos vainas
Siguiente maneja SIGTERM con un proceso desnudo.exit(143), por lo que cada despliegue se cortó lo que sea esta vaina tener en vuelo, un poste de formulario, una acción del servidor, una carga útil RSC en streaming, una carga. Invisible cuando a La petición duró milisegundos; no invisible en un clúster que se despliega en cada empuje. scripts/standalone-entry.cjs envuelve el servidor independiente: en SIGTERM deja de aceptar, se queda de ocioso mantener-almuerzos a la vez para que una vaina sin nada en vuelo todavía sale en aproximadamente un segundo, y deja correr las solicitudes terminan bajo un tope que se encuentra por debajo de la terminaciónGracePeriodSeconds. Portado de kamo-internal, que lo ha llevado a cabo en producción durante meses. Este despliegue no tenía sonda de preparación, por lo que una vaina contaba como Ready el instante de su contenedor proceso iniciado. Con maxUnavailable 0 Kubernetes lee que como "la nueva vaina está sirviendo" y retira el antiguo, mientras que Next sigue rubricando y no ha atado su puerto. Solicitudes aterrizadas en un puerto nada estaba escuchando, que es de donde provenían los intermitentes 502 en el despliegue. /api/salud responde sólo para esta vaina y deliberadamente toca sin backend: una sonda de preparación decide si esta cápsula sale del Servicio, y cablearlo a un backend convierte un backend en un blip de backend en un Reencuentro de cada vaina aquí. El Dockerfile HEALTHCHECK ha apuntado a /api/salud desde que fue escrito; la ruta no existen, por lo que ese cheque ha estado fracasando durante todo el tiempo que ha estado allí. réplicas 1 - 2. Estado del lado del servidor vive en Redis, no en la cápsula, y no hay trabajo programado para duplicar, por lo que una segunda réplica no cambia nada excepto que perder una vaina deja de ser un apagón. En una réplica una OOM mata, una fallida sonda de vida o un drenaje de ganglios se llevó todo por el tiempo que sea necesario para arrancar. topologíaSpreadConstraints (añadidos anteriormente, inerte hasta ahora) mantener los dos en diferentes nodos donde el racimo puede manejarlo, y un PodDisruptionBudget en KlusterServices hace una espera de drenaje.
· kamo-login
Escurrir en SIGTERM, responder una sonda de preparación y ejecutar dos vainas
Siguiente maneja SIGTERM con un proceso desnudo.exit(143), por lo que cada despliegue se cortó lo que sea esta vaina tener en vuelo, un poste de formulario, una acción del servidor, una carga útil RSC en streaming, una subida. Invisible cuando a La solicitud duró milisegundos; no invisible en un clúster que se despliega en cada empuje. scripts/standalone-entry.cjs envuelve el servidor independiente: en SIGTERM deja de aceptar, deja inactivos mantener-alera a la vez para que una vaina sin nada en vuelo todavía sale en aproximadamente un segundo, y deja correr Las solicitudes terminan bajo un tope que se encuentra por debajo de la terminaciónGracePeriodSeconds. Portado de kamo-internal, que lo ha llevado a cabo en producción durante meses. Este despliegue no tenía sonda de preparación, por lo que una vaina contaba como Ready el instante de su contenedor proceso iniciado. Con maxUnavailable 0 Kubernetes lee que como "la nueva vaina está sirviendo" y retira el antiguo, mientras que Next sigue rubricando y no ha obligado a su puerto. Solicitudes desembarcadas en un puerto nada estaba escuchando, que es de donde provenían los intermitentes 502 en despliegue. /api/salud responde sólo para esta vaina y deliberadamente toca sin backend: una sonda de preparación decide si esta vaina deja el Servicio, y cablearlo a un backend convierte un backend en un blip de backend en un reinicio de cada vaina aquí. réplicas 1 - 2. Estado del lado del servidor vive en Redis, no en la cápsula, y no hay trabajo programado duplicar, por lo que una segunda réplica no cambia nada excepto que perder una vaina deja de ser un apagón. En una réplica una OOM mata, una sonda de vivacidad fallida o un drenaje de nodos se llevó todo por Mientras sea necesario para arrancar. topologíaSpreadConstraints (añadidas antes, inerte hasta ahora) mantienen los dos en diferentes nodos donde el racimo puede manejarlo, y un PodDisruptionBudget en KlusterServices hace una espera de drenaje.
· kamo-nowww
Escurrir en SIGTERM, y responder a una sonda de preparación
Siguiente maneja SIGTERM con un proceso desnudo.exit(143), por lo que cada despliegue se cortó lo que sea esta cápsula tenía en vuelo, un post de formulario, una acción del servidor, una carga RSC en streaming, una subida. Invisible cuando a La solicitud duró milisegundos; no invisible en un clúster que se despliega en cada empuje. scripts/standalone-entry.cjs envuelve el servidor independiente: en SIGTERM deja de aceptar, se deja intenunciar mantener los almuerzos a la vez para que una vaina sin nada en vuelo todavía salga en aproximadamente un segundo, y deja correr las solicitudes terminan bajo un tope que se encuentra por debajo de la terminaciónGracePeriodSeconds. Portado de kamo-internal, que lo ha llevado a cabo en producción durante meses. Este despliegue no tenía sonda de preparación, por lo que una vaina contaba como Ready el instante de su contenedor proceso iniciado. Con maxUnavailable 0 Kubernetes lee que como "la nueva vaina está sirviendo" y retira el antiguo, mientras que Next sigue rubricando y no ha obligado a su puerto. Solicitudes desembarcadas En un puerto nada estaba escuchando, que es de donde vinieron los intermitentes 502 en el despliegue. /api/salud responde sólo para esta vaina y deliberadamente toca sin backend: una sonda de preparación decide si esta cápsula sale del Servicio, y cablearlo a un backend gira un backend en un blip de backend en un reinicio de cada cápsula aquí. Ya en dos réplicas; esto es lo que hace que el segundo cubra realmente el primero durante un rollout en lugar de ser reemplazados ciegos.
· kamo-shared-library
Una cerracerración distribuida, por lo que un barrido programado puede sobrevivir a una segunda réplica
No hay ShedLock en ninguna parte de esta plataforma y nunca lo ha habido. El 97 desquitulado Los barridos a través de 18 servicios son correctos sólo porque cada servicio ejecuta exactamente una cápsula. Escala cualquiera de ellos y el barrido corre dos veces una garra de la garra de dos recordatorios de reunión en la bandeja de entrada de un miembro, dos chat-email avisos, dos pases en un período de facturación. Esos despliegues de una sola-replica no eran meramente sin escala; el conteo de réplicas era de carga, y el código lo dice en tres lugares ya. ************* lease, body) ejecuta un cuerpo en exactamente una vaina. UN LLLLLlámaga, NO AN ANNOTATION. El diseño obvio es el diseño obvio y lo hace un singletonTask junto a la lista. es una trampa aquí: sería aplicado por un proxy AOP, y un proxy se pasa completamente cuando un método se alcanza desde dentro del mismo grano. El problema de autoinvocación de primavera esta base de código ha sido atrapado por cinco veces distintas. Un barrido que perdió silenciosamente su cerradura y corrió en cada vaina es que el mismo fracaso, y nada lo revelaría hasta que un cliente contara sus correos electrónicos. Tomando la cerradura por Llamándolo no puede ser pasado por alto por cómo se alcanzó el método, y se agacha. REDIS, NO LOS DATABASE. Una mesa de bloqueo necesita DDL, y DDL en este racimo hace cada respuesta de servicio 500 'desajuste de la versión de esquema' por 15 minutos, mientras que las conexiones de Hikari envejecen. Pagar un Apagón para toda la plataforma para instalar la maquinaria que evita los cortes de toda la plataforma es un mal comercio cuando Redis ya está desplegado. FAILS CLOSED. Si Redis es inalcanzable la tarea se salta, no correr: para trabajar que envíe correo electrónico o mueve dinero, correr dos veces es peor que no correr, y la siguiente garrafa de reinicia. La liberación es un script de compare-y-dederación para que un cuerpo que invadió su contrato de arrendamiento no puede borrar una cerradura otra vaina tiene desde entonces, y el sobrecoste se detecta en ERROR porque nada más lo revelaría. Donde un servicio no tiene Redis el retroceso corre el cuerpo siempre lo que el código hace hoy, Así que adoptar esto nunca cambia el comportamiento por sí solo y advierte en la puesta en marcha. La guardia manifiesta en CI rechaza réplicas 1 para un servicio en ese estado. 7 pruebas; suite completa 2710 verde.
· kamo-register
Pintar cada logotipo en el sitio de inscripción en el color de superposición de la org
La org elige "Register Site Logo Overlay" en kamo-internal junto a la página de inicio y capturas de pantalla de carga. Un escenario para todo el sitio: cada paso del flujo de registro, la organización y las pantallas del equipo, la pantalla de terminación y la pantalla de señalización cerrada. Así que ThemeLogo no toma ningún apoyo para él y lee el color en sí, la forma en que ya lee la identidad del logotipo de la empresa-vs-software - config.json es La única fuente de marca de org en este sitio, y un apoyo sería uno más lo que cada sitio de llamadas tiene que recordar. El color llega ya resuelto: kamo-internal almacena un TOKEN para un org que re-noja una superposición a juego, y el servicio de seguridad resuelve en contra de la paleta de esa org cuando escribe config.json. Nada aquí. necesita el vocabulario de trece ficha. Se deja caer un valor CSS en lugar de pasar - un color de fondo inválido pinta el enmascarado caja transparente, que se lee como un logotipo que desapareció. Una máscara, no un filtro: un filtro sólo puede empujar los colores existentes de un logotipo alrededor y no puede alcanzar un objetivo arbitrario. Las estancias de .img. se montan y meramente invisible para que siga sosteniendo su caja exacta para que la máscara se llene, Dejando el trazado de todos los que llaman sin cambios. Su propia columna y su propia llave config.json, separada de la sesión de inscripción sitio: los dos son de marca independiente, y un org que blanquea uno no necesita marca blanca el otro.
· kamo-login
Pintar cada logotipo en el sitio de inicio de sesión en el color de superposición de la org
El org elige "Login Site Logo Overlay" en kamo-internal al lado de la casa página y carga de capas de pantalla. Un escenario para todo el sitio: el formulario de inicio de sesión, el selector del espacio de trabajo, recuperación de contraseñas y restablecimiento, y el La pantalla de salida son el mismo logotipo en el mismo fondo, y nadie quiere para poner la sombra cinco veces. Así que ThemeLogo no toma ningún apoyo para ello y lee el color en sí, la forma en que ya lee la identidad del logotipo de la empresa-v-v-software auth - config.json es la única fuente de marca de org de este sitio, y un apoyo sería uno más Lo que cada sitio de llamadas tiene que recordar. El color llega ya resuelto: kamo-internal almacena un TOKEN así que un org que rebautiza mantiene una superposición a juego, y el servicio de seguridad resuelve en contra de la paleta de esa org cuando escribe config.json. Nada aquí. necesita el vocabulario de trece ficha. Se deja caer un valor CSS en lugar de pasar - un color de fondo inválido pinta el enmascarado caja transparente, que se lee como un logotipo que desapareció. Una máscara, no un filtro: un filtro sólo puede empujar los colores existentes de un logotipo alrededor y no puede alcanzar un objetivo arbitrario. Las estancias de .img. se montan y meramente invisible para que todavía se incendie en Load (la única fuente de natural Tamaño) y enError (que camina la extensión llena de logotipos), y por lo tanto todavía tiene su caja exacta para que la máscara se llene. El diseño de todo llamante es Sin cambios. La pequeña marca animada en la píldora "Powered by KamoCRM" es la propia de la org logo también, por lo que sigue la configuración - sólo se renderiza a través de la siguiente / imagen para la carga ansiosa de esa píldora, así que lleva la máscara en sí convertirse en TemeLogo. De lo contrario, habría sido el único logotipo de la Sitio la configuración se perdió.
· kamo-internal
Elija una superposición de logo para los lugares de registro y registro
Una cuarta y quinta superficie junto a la página de inicio, pantalla de carga y KamoMeets superpone, compartiendo su vocabulario de trece y su vida avispas. Ambos siempre se ofrecen, a diferencia de los KamoMeets: cada org tiene un inicio de sesión y un sitio de registro de las aplicaciones que ejecuta, y un org sin dominio de su propio todavía los alcanza en login./register.kamocrm.com pintado en su propio marca. También son las dos únicas superposiciones aquí que no se aplican en el momento en que son salvados. kamo-login y kamo-register no tienen OrgContext para leer, así que el servicio de seguridad resuelve el token y hornea el color en el tema config.json esos sitios que consiguen; el cambio de tierras al aprovisionarse reescribes ese archivo, que el mismo salvo ya desencadena. Cinco desplegaciones casi idénticas habrían sido de cinco lugares a la deriva, por lo que el el bloque de editor es ahora un renderOverlaySeleccionar () la cuota de superficies - un sexto la superficie es una llamada en lugar de otras veinte líneas. Las filas de sólo lectura ya compartía la suya. Los dos campos cabalgan a la organización.fromJSON como sus hermanos, con un Prueba de viaje redondo: el mapper se ejecuta dos veces en el camino al navegador, y un campo que no puede leer de su propia salida es un escenario que en silencio vuelve en su próxima carga.
· MediaService
Haz que MediaService sea correcto en más de una vaina, y ejecuta dos
MediaService sólo ha corrido una sola réplica, por lo que un despliegue de él fue un corte de chat total y una OOM era la misma. No pudo ejecutar dos, por razones que estaban todas en el código: 1. EL BROKER STOMP IS IN-HEAP. enableSimpleBroker significa convertAndSend llega sólo a los WebSockets conectado a la vaina haciendo la llamada. Trece controladores de relevos ya manejaban esto correctamente suscribirse a NATS con un despachador sencillo (sin grupo de colas, por lo que cada cápsula recibe cada mensaje) y volver a publicar localmente. Trece otros sitios de llamadas no hicieron indicadores de mecografía, presencia, insigniques no leídos, subvenciones de respuesta, oferta/respuesta/ICE, notificaciones de chat entrante y cada uno habría entregado a aproximadamente la mitad de su público previsto. StompFanout generaliza el patrón que esos relevos ya utilizan: publicar el destino, la carga útil en un tema NATS básico, cada cápsula lo transmite en su propio bróker. Core NATS, no JetStream, porque se trata de eventos de momento en vivo sin valor reproducido y sin transmisión que cubra el tema. Debido a que el núcleo NATS también entrega al editor, envíe () NO escriba localmente, también que Entregaría dos veces aquí. Con NATS abajo cae de nuevo a un enviado local, que es lo que el la plataforma lo hizo antes. 2. EL CONSUMER PER-CONVERSACION ES UN DURABLE EXCLUSIVE. ChatSessionSubscriptionManager nombró su JetStream duradero después de la sesión de chat GUID, y un consumidor de empuje duradero admite exactamente uno Suscriptor. El segundo vínculo de la cápsula fue rechazado [SUB-90012] y todos los miembros cuyo enchufe aterrizó no había nada, ni mensajes, ni recibos de lectura, sin eventos de miembros-añadidos, sin error. Ahora un consumidor efímero: sin nombre para colisionar, uno por cápsula, cosechado por el servidor. El reinicio que se elimina inventó un nuevo nombre duradero en la colisión. Funviró, y filechó un consumidor permanente del lado del servidor por colisión que nada borró nunca. 3. CINCO MÁS DURABLES FIXED-NAME, que necesitan tratamiento opuesto dependiendo del trabajo. La conversión y los relés VOIP STOMP pasaron por JetStream en lugar de un despachador de núcleo, por lo que tenían lo mismo bug de exclusividad, ahora efímero, ya que cada vaina debe recibir. El notificante de chat-email, social consumidor y reconversión de marketing debe correr exactamente la ONCE, por lo que se quedan con la suya duradero y unirse a un grupo de entrega, lo que también significa que un sobreviviente recoge el trabajo cuando una vaina muere. Se requieren sesiones de pegajosas en la ruta de los medios, no opcionales: estos clientes STOMP utilizan SockJS, cuya caída xhr-streaming/xhr-polling es varias solicitudes de HTTP parado de una conexión En contra de la sesión dice que vive en la memoria de una vaina. Round-robin lo rompe. Ver ingressroute.yaml. réplicas 1 - 2. Pasan 367 pruebas.
· SecurityService
Hornee las entradas de logotipo de inscripción y registro se sobres despaja en config.json
kamo-login y kamo-register corren en sus propios anfitriones sin OrgContext, así que este archivo es la única ruta que toma su marca - la misma que KamoMeet ya usos. El token se resuelve contra la paleta de la org AQUI y el hechizo terminado está escrito, que mantiene fuera del botelgón el 3o simnipojo de dos códigos más que cada uno necesitaría su propia copia de él. Hornear un color resuelto no es el error que el token almacenado evita: esto archivo se regenera en cada marca guardar, cambios de color incluidos, por lo que el valor no puede quedar rancio. Ausente no significa superposición, así que un org que no ha elegido ninguna gana ninguna llave y sus logos se vuelven intactos - que es cada org hasta que uno es elegido. Las pruebas cubren las tres superficies que se mantienen separadas: comparten un constructor, y una org superponer su sitio de inicio de sesión no debe pintarse su logotipo de KamoMeet como efecto secundario.
· kamo-shared-library
Una superposición de logo para los lugares de registro e inscripción
Dos columnas más en el vocabulario home-logo-overlay ya establecido: un token, no un hechizo, por lo que una oreja que rebautiza mantiene una superposición que coincide con su nuevos colores. Ambos nulos sin relleno - null es NONE, que es lo que Cada org se parece hoy. Columnas separadas en lugar de un ajuste compartido, por la misma razón el página de inicio y pantalla de carga tienen su propia: los dos sitios están marcados Independientemente, y una org que blanquea uno necesita no tener en cuenta la marca blanca el otro. Parche es un ALLOW-LIST, así que los nombres también van allí. Una columna este servicio felizmente deserializa pero ese método no nombra aceptado con un 200 y silenciosamente nunca almacenado - sin error, sin línea de registro, y el único síntoma es un ajuste que revierte en su próxima carga.
· kamo-login
Contesta el enlace en una carta de cambio de dirección
/verify-email-change gasta la ficha en una carta de cambio de dirección y dice lo que pasó. Vive aquí más que en el espacio de trabajo porque la letra va a un buzón PERSONAL - por lo general leer en un teléfono que nunca se ha firmado el espacio de trabajo, y a menudo no se ha iniciado en nada. login. anfitrión que siempre resuelve para una organización y nunca necesita una sesión, por lo que es el único lugar donde el vínculo es seguro que trabajará para la persona que más lo necesita. Nada en la página pide nada. Llega, gasta la ficha, y informes - un formulario aquí sería un formulario que el lector no puede rellenar de la buzón que abrieron. El gasto está protegido contra el desarrollo de React doble invocación, porque la ficha es de un solo uso y una segunda llamada lo pasaría y luego reportar el éxito como "este vínculo ya no es válido". El relé junto a /api/recuperar y moldeado de la misma manera: SecurityService es Sólo ClusterIP, por lo que pasa por el clúster DNS, que hace de Host el nombre de servicio y pone el nombre de host del navegador en X-Forwarded-Host. el único encabezado de la el backend lo lee.
· kamo-internal
Camete su propia dirección y una pestaña de plataforma para cada cuenta
Dos superficies, a las que se unió una distinción a la que la plataforma nunca ha explicado cualquier persona: una cuenta de usuario es la PERSONA, y un miembro es de una organización relación con esa persona. Mi perfil gana una tarjeta de dirección de correo electrónico personal, en la sala de acceso al lado de la contraseña porque eso es lo que es uno de los tres identificadores inicia sesión de inicio acepta, y la dirección a la que se reaparece una contraseña se envía por correo. Archiparlo bajo contacto Los detalles estarían archivando una llave bajo papelería. Se compromete a sí mismo en lugar de pasando por la barra de salvación de la habitación: un cambio es una petición, una carta y un confirmación, y un botón Guardar que escribió un identificador de inicio de sesión sin pruebas el buzón existente sería todo el problema en un solo control. La cuenta pertenece a la organización nombrada por security.provider.id, y sólo que uno puede cambiarlo. La tarjeta es por lo tanto visible en todas partes y editable en un lugar. Esconderlo en los otros dejaría a un miembro cazando por un escenario parece haberse borrado. Donde no se puede editar dice de quién es, y ofrece ambos caminos de vuelta: cambiando desde el menú de arriba-izquierda sin salir la aplicación, y la entrada directamente en la propia dirección de inicio de sesión de esa organización (o, cuando no tiene ninguno todavía, en el compartido, nombrado como tal). Ambos vienen de OrgEntryDomainResolver, así que el huésco nunca es uno que no se resuelva. Un explicador se sienta bajo la tarjeta en TODO organización, no sólo dentro de la negativa. "Constación de usuario" versus "cuenta de miembros" es una distinción que nadie fuera la plataforma tiene cualquier razón para saber, y se convierte en carga en exactamente el momento en que a alguien se le niega algo que es el peor momento posible para reunirse una idea por primera vez. /account gana una cuarta pestaña, Usuarios, cerrados en la nueva plataforma MANAGE-USERS Bien. La derecha que ya lleva la "organización actual debe ser la plataforma organización" condición previa . PlatformRightsResolver no devuelve nada a a sesión dentro de un inquilino, para que la pestaña no revise la organización por separado; una segunda autoridad allí sólo podría estar en desacuerdo con la del servidor. Búsqueda y paging son también los del servidor: el filtro de la propia red busca las filas que sucede mantener, que en una tabla de plataformas significa no informar "no hay resultados" para un la cuenta que existe. El cajón detrás de una fila está ligado por consecuencia más que por tema. Identidad Edite en un borrador y ahorra una vez; el estado de cuenta se compromete por conmutación e informes Cuántas sesiones fueron con ella; la recuperación se distingue y confirma. Dios mío. cuentas y el Usuario del Sistema de renderizado solo, porque el servidor los rechaza y componer una edición que nunca iba a tierra es peor de lo que se le dijo Primero. También fija el banner de protección de seguridad que ha estado en esta página todo el tiempo. Construyó su enlace a partir de .org.domain. plus. id miembro de esta organización. Nombre de host que no es el huésped del espacio de trabajo, en un miembro id que no existe Ahí. Ahora apunta a la pantalla de inicio de sesión que el servidor resuelve.
· kamo-shared-library
Añadir un suscribirse a un grupo de colas, por lo que el trabajo se comparte en lugar de fijarlo a una vaina
Compañero para suscribirEfemeral. Dos puestos de trabajo diferentes, dos consumidores diferentes: SuscribirEfemeral cada cápsula debe ver cada mensaje (cualquier cosa que termine en una transmisión STOMP) SuscripciónEl trabajo debe ocurrir exactamente la ONCE (enviar un correo electrónico, llamar a un proveedor) Tampoco lo que hace un simple duradero en más de una réplica. Sin grupo de entrega un empujón duradero el consumidor admite un solo suscriptor, por lo que la segunda vaina es denegada [SUB-90012] y el trabajo es clavada a cualquier cápsula atado primero, sin que nada se apodere si esa es la vaina que muere. Agregar un grupo de entrega convierte lo mismo duradero en una cola que las vainas comparten, manteniendo la redelivery y MaxEntregar exactamente como estaban. reconciliarDeliverGroup refleja la reconciliación existenteDurableFilter, y no es opcional: cada Este cambio se convierte ya existe en el arroyo en la forma antigua, y los jnats no unirse a una llaga duradera como cola. Sin la conciliación el primer despliegue después de esto saldría esas suscripciones permanentemente muertas en lugar de compartidas - el mismo fracaso silencioso y perpetuoante El filtro se escribió para. El bucle de entrega es ahora un método detrás de los tres puntos de entrada.
· kamo-shared-library
Añadir un suscripción efímero, por lo que más de una vaina puede servir una conversación
Un consumidor de presión duradero admite exactamente un suscriptor. La segunda vaina en atar el mismo nombre es El consumidor ya está obligado a una suscripción, y nada vuelve a la cuestión. ChatSessionSubscriptionManager nombra a su duradero después de la sesión de chat GUID, así que con dos Las vainas de MediaService que uno ataría una conversación primero lo poseería silenciosamente y cada miembro cuyo WebSocket aterrizó en la otra vaina no recibiría nada, ni mensajes, ni recibos de lectura, no hechos de miembros-añadiles, sin error. Esa propiedad única es la razón por la que MediaService ha sido sujeta a uno réplica, y por qué un despliegue de ella es un corte de chat total en lugar de un vuelco. SuscríbeteEfemeral () crea un consumidor sin nombre en su lugar. No hay identidad transversal para chocar por encima, por lo que cada cápsula recibe cada mensaje y los fans a sus propios clientes STOMP, que es lo que el en-heap simple bróker requiere. Mantenga el filtroSujeto de la ruta duradera aprendida a establecer (an filtro vacío consume todo el flujo), y añade un umbral inactivo para que una cápsula que se encuentre SIGKILLed Sin darse cuenta no deja a su consumidor en la corriente para siempre. No hay cambio de comportamiento para las personas que llaman: suscríbanse () no se toca, y el bucle de entrega El uso de caminos es ahora un método por lo que no pueden derivar. Los consumidores efímeros no reproducen mensajes publicados mientras no se suscribe nada. Tampoco el Los duraderos utilizan DeliverPolicy.Nuevo para que esto no sea una regresión.
· kamo-internal
"Qué pasó?", llena la ventana, así que maximizarla la agrande.
Todos los demás campos del formulario del informe se dimensionan por su contenido. El descripción es en la que alguien está escribiendo, así que ahora se necesita cualquier altura que se deje y maximización de la ventana de la herramienta es por lo tanto vale la pena. Se necesitan tres partes y las tres: El área del desplazamiento gana una columna de flexión interior en la Altura: 100%, no Estatura: 100%. A una altura fija una forma más alta que la ventana comprimiría sus propios campos, porque los niños flexionan por defecto. Como mínimo, es exactamente la altura completa cuando hay espacio para sobrar. que es la habitación la descripción toma y crece más allá de ella cuando hay no, en ese momento la caja exterior se desplaza y nada se aplasta. El campo se convierte en un elemento flexible con un piso de la Altura .minHeight. "minRows" se ha ido con ella: que impulsa TextareaAutosize, que mide el contenido y escribe una altura en línea, y con la base de la . . . . . . . . . . . . . . . . . . . no sea nada para detener el campo colapsando a cero. La esfera de texto se publica con la altura: autoimportante, NO Estatura: 100%. El envoltorio esbozo estira a sus hijos, por lo que el textarea lo llenaría sin ayuda excepto un elemento flexible con un definido El tamaño cruzado no se estira, y el autosize le da una en línea. Fije altura de espaldas a auto restaura el tramo en lugar de luchar contra él. 100% era probado primero y silenciosamente no hace nada en absoluto: el porcentaje no bloque definido que contiene bloque para resolver en contra, por lo que se cae de nuevo a la auto y el campo se vuelve a sus dos filas intrínsecas, sin error en ninguna parte A notarlo. Medido, no asumido. Un arnés tititista construido a partir de este componente propia salida de emoción da 240px de área de texto en una ventana de 720px, 444px en 940px, y un campo de piso con la forma de desplazamiento a 430px con el campo de título todavía 40px en los tres. El guardia comprometido afirma el gobernar en lugar de la altura, ya que Jsdom no hace ningún diseño, y era confirmados para fracasar cuando la regla se vuelve al 100%.

Tu universo está esperando.
Comience gratis en minutos y agregue productos cuando esté listo, sin migración ni nuevos inicios de sesión.
Gratis para siempre: no se requiere tarjeta de crédito