Merge branch 'dev' into feat/ip-filtering

This commit is contained in:
Fred KISSIE
2026-08-24 22:06:55 +02:00
38 changed files with 410 additions and 97 deletions
+4
View File
@@ -4,6 +4,10 @@ perpetual license to use, modify, and redistribute these contributions under any
choose, including both the AGPLv3 and the Fossorial Commercial license terms. I
represent that I have the right to grant this license for all contributed content.
## AI Disclosure
> Please disclose how AI was used in this pull request. The use of AI does not preclude this from being merged but is an important factor in how we review your request.
## Description
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Инструментът за кодиране на Anthropic за терминала.",
"aiClientConfigDescriptionCodex": "Инструментът за кодиране на OpenAI за терминала.",
"aiClientConfigDescriptionOpencode": "Отворен кодиращ агент за терминал.",
"aiClientConfigDescriptionCursor": "AI редактор на код, базиран на VS Code.",
"aiClientConfigDescriptionGemini": "Агентски инструмент на Google за кодиране на терминал.",
"aiClientConfigSetup": "Настройка",
"aiClientConfigTabCli": "Автоматичен (CLI)",
"aiClientConfigTabManual": "Ръчна конфигурация",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Маршрутиране чрез цели на вашите сайтове",
"aiProviderRoutingModeTargetNote": "След създаването на този доставчик, конфигурирайте целите на сайта в раздела Настройки на мрежата.",
"aiProviderTargetNoOne": "Този доставчик няма цели. Добавете цел за маршрутиране на заявки чрез вашите сайтове.",
"aiProviderRemoteNodeTargetsWarning": "Уебсайтовете, свързани с отдалечени възли, са недостъпни за пренасочване към AI Gateway доставчици.",
"aiProviderSkipTlsVerification": "Пропуснете проверката на TLS",
"aiProviderSkipTlsVerificationDescription": "Деактивирайте проверката на TLS сертификат за възходящото свързване",
"aiProviderBudget": "Бюджет",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Поддържа /v1/responses",
"aiCapabilityAnthropicMessages": "Anthropic Съобщения",
"aiCapabilityAnthropicMessagesDescription": "Поддържа /v1/messages",
"aiCapabilityV1Models": "Списък на модели",
"aiCapabilityV1ModelsDescription": "Поддържа /v1/models откриване на модели",
"aiCapabilityGeminiGenerateContent": "Gemini Генериране на Съдържание",
"aiCapabilityGeminiGenerateContentDescription": "Поддържа директния Gemini API",
"aiCapabilityBedrockModelInvoke": "Бедрок Модел Активирай",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Дневници на действията",
"logRetention": "Задържане на логове",
"logRetentionDescription": "Управлявайте времето за задържане на различни видове логове за тази организация или ги деактивирайте",
"logRetentionDisabledWarningTitle": "Деактивирано съхранение на дневници",
"logRetentionDisabledWarningDescription": "{logType} не се съхраняват за тази организация, така че новите дейности няма да се показват тук. Активирайте съхранението в настройките за сигурност, за да започнете събирането на тези дневници.",
"logRetentionDisabledWarningButton": "Отидете на настройки за сигурност",
"requestLogsDescription": "Прегледайте подробни логове на заявки за ресурси в тази организация",
"aiSessionLogs": "Журнали на AI Портал Сесиите",
"aiSessionLogsDescription": "Прегледайте подканянета и транскрипции на отговори за запитванията към AI портал в тази организация",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Събития на свързване и прекъсване на сайта и тунела, включително свръзки и прекъсвания.",
"httpDestRequestLogsTitle": "Логове за HTTP заявки",
"httpDestRequestLogsDescription": "Регистри за HTTP заявките към проксирани ресурси, включително метод, път и код на отговор.",
"httpDestAISessionLogsTitle": "Дневници за AI сесии",
"httpDestAISessionLogsDescription": "AI заявки до шлюза и отговори на сесии, включително подканвания, отговори на модели и използване на жетони.",
"httpDestSaveChanges": "Запази промените",
"httpDestCreateDestination": "Създаване на дестинация",
"httpDestUpdatedSuccess": "Дестинацията беше актуализирана успешно",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Antropický agentický kódovací nástroj pro terminál.",
"aiClientConfigDescriptionCodex": "Agentický kódovací nástroj OpenAI pro terminál.",
"aiClientConfigDescriptionOpencode": "Open source terminální kódovací agent.",
"aiClientConfigDescriptionCursor": "AI editor kódu postavený na VS Code.",
"aiClientConfigDescriptionGemini": "Agentický nástroj Google pro kódování v terminálu.",
"aiClientConfigSetup": "Nastavení",
"aiClientConfigTabCli": "Automatické (CLI)",
"aiClientConfigTabManual": "Ruční konfigurace",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Směrujte přes cíle na svých stránkách",
"aiProviderRoutingModeTargetNote": "Po vytvoření tohoto poskytovatele, nakonfigurujte cíle stránek na záložce Nastavení sítě.",
"aiProviderTargetNoOne": "Tento poskytovatel nemá žádné cíle. Přidejte cíl pro směrování požadavků přes vaše stránky.",
"aiProviderRemoteNodeTargetsWarning": "Stránky připojené k vzdáleným uzlům nejsou dostupné pro přesměrování na poskytovatele AI Gateway.",
"aiProviderSkipTlsVerification": "Přeskočit ověření TLS",
"aiProviderSkipTlsVerificationDescription": "Zakázat ověření certifikátu TLS pro upstream připojení",
"aiProviderBudget": "Rozpočet",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Podporuje /v1/responses",
"aiCapabilityAnthropicMessages": "Zprávy Anthropic",
"aiCapabilityAnthropicMessagesDescription": "Podporuje /v1/messages",
"aiCapabilityV1Models": "Seznam modelů",
"aiCapabilityV1ModelsDescription": "Podporuje objevování modelů /v1/models",
"aiCapabilityGeminiGenerateContent": "Generování obsahu Gemini",
"aiCapabilityGeminiGenerateContentDescription": "Podporuje přímé API Gemini",
"aiCapabilityBedrockModelInvoke": "Vyvolání modelu Bedrock",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Záznamy akcí",
"logRetention": "Zaznamenávání záznamu",
"logRetentionDescription": "Spravovat, jak dlouho jsou různé typy logů uloženy pro tuto organizaci nebo je zakázat",
"logRetentionDisabledWarningTitle": "Zakázáno uchování logů",
"logRetentionDisabledWarningDescription": "{logType} nejsou uchovávány pro tuto organizaci, takže nová aktivita se zde neprojeví. Aktivujte uchovávání v nastavení zabezpečení pro zahájení sběru těchto logů.",
"logRetentionDisabledWarningButton": "Přejít na nastavení zabezpečení",
"requestLogsDescription": "Zobrazit podrobné protokoly požadavků pro zdroje v této organizaci",
"aiSessionLogs": "Protokoly AI Gateway Session",
"aiSessionLogsDescription": "Zobrazit uložené výzvy a odpovědi na žádosti AI brány v této organizaci",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Události týkající se připojení lokality a tunelu, včetně připojení a odpojení.",
"httpDestRequestLogsTitle": "Záznamy HTTP požadavků",
"httpDestRequestLogsDescription": "HTTP záznamy požadavků pro proxy zdroje, včetně metod, cesty a kódu odpovědi.",
"httpDestAISessionLogsTitle": "Logy AI sezení",
"httpDestAISessionLogsDescription": "Relace požadavků a odpovědí AI gateway, včetně podnětů, odpovědí modelů a využití tokenů.",
"httpDestSaveChanges": "Uložit změny",
"httpDestCreateDestination": "Vytvořit cíl",
"httpDestUpdatedSuccess": "Cíl byl úspěšně aktualizován",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Anthropics agentikodningsværktøj til terminalen.",
"aiClientConfigDescriptionCodex": "OpenAIs agentikodningsværktøj til terminalen.",
"aiClientConfigDescriptionOpencode": "Open source terminal kodningsagent.",
"aiClientConfigDescriptionCursor": "AI-kodeeditor bygget på VS Code.",
"aiClientConfigDescriptionGemini": "Googles agentiske kodningsværktøj til terminalen.",
"aiClientConfigSetup": "Opsætning",
"aiClientConfigTabCli": "Automatisk (CLI)",
"aiClientConfigTabManual": "Manuel Konfiguration",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Rute gennem mål på dine steder",
"aiProviderRoutingModeTargetNote": "Efter oprettelse af denne udbyder, konfigurer mål på Netværksindstillinger fanen.",
"aiProviderTargetNoOne": "Denne udbyder har ingen mål. Tilføj et mål for at rute forespørgsler gennem dine steder.",
"aiProviderRemoteNodeTargetsWarning": "Websteder, der er forbundet til eksterne noder, kan ikke tilgås for at blive dirigeret til via AI Gateway-udbydere.",
"aiProviderSkipTlsVerification": "Spring TLS-verifikation over",
"aiProviderSkipTlsVerificationDescription": "Deaktiver TLS-certifikat verifikation for opstrømsforbindelsen",
"aiProviderBudget": "Budget",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Understøtter /v1/responses",
"aiCapabilityAnthropicMessages": "Anthropic Beskeder",
"aiCapabilityAnthropicMessagesDescription": "Understøtter /v1/messages",
"aiCapabilityV1Models": "Model Liste",
"aiCapabilityV1ModelsDescription": "Understøtter opdagelse af /v1/models modeller",
"aiCapabilityGeminiGenerateContent": "Gemini Generer Indhold",
"aiCapabilityGeminiGenerateContentDescription": "Understøtter den direkte Gemini API",
"aiCapabilityBedrockModelInvoke": "Bedrock Modeller Invoker",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Handlingsloger",
"logRetention": "Logopbevaring",
"logRetentionDescription": "Håndter hvor længe ulike typer logs beholdes for denne organisation, eller deaktivér dem",
"logRetentionDisabledWarningTitle": "Logbevaring deaktiveret",
"logRetentionDisabledWarningDescription": "{logType} gemmes ikke for denne organisation, så nye aktiviteter vises ikke her. Aktiver logbevaring i sikkerhedsindstillingerne for at begynde at indsamle disse logs.",
"logRetentionDisabledWarningButton": "Gå til sikkerhedsindstillinger",
"requestLogsDescription": "Se detaljerede forespørgselslogs for ressourcer i denne organisation",
"aiSessionLogs": "AI Gateway Øktsprotokoller",
"aiSessionLogsDescription": "Se prompt og svarudskrifter for AI gateway forespørgsler i denne organisation",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Udstyrs- og tunnelforbindelseshændelser, inklusive forbindelser og frakobling.",
"httpDestRequestLogsTitle": "HTTP-forespørgselslogs",
"httpDestRequestLogsDescription": "HTTP-forespørgsel logs for bekræftede ressourcer, inklusive metode, sti og responskode.",
"httpDestAISessionLogsTitle": "AI-session Logs",
"httpDestAISessionLogsDescription": "AI-gateway anmodninger og respons-sessioner, inklusive prompts, modelresponser og tokenforbrug.",
"httpDestSaveChanges": "Gem ændringer",
"httpDestCreateDestination": "Opret mål",
"httpDestUpdatedSuccess": "Målet er opdateret",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Agentisches Codierwerkzeug von Anthropic für das Terminal.",
"aiClientConfigDescriptionCodex": "Agentisches Codierwerkzeug von OpenAI für das Terminal.",
"aiClientConfigDescriptionOpencode": "Open-Source-Coding-Agent für das Terminal.",
"aiClientConfigDescriptionCursor": "KI-Code-Editor basierend auf VS Code.",
"aiClientConfigDescriptionGemini": "Googles agentic Coding-Tool für das Terminal.",
"aiClientConfigSetup": "Einrichtung",
"aiClientConfigTabCli": "Automatisch (CLI)",
"aiClientConfigTabManual": "Manuelle Konfiguration",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Über Ziele auf Ihren Sites routen",
"aiProviderRoutingModeTargetNote": "Konfigurieren Sie nach der Erstellung dieses Anbieters Site-Ziele auf der Registerkarte 'Netzwerkeinstellungen'.",
"aiProviderTargetNoOne": "Dieser Anbieter hat keine Ziele. Fügen Sie ein Ziel hinzu, um Anfragen über Ihre Sites zu leiten.",
"aiProviderRemoteNodeTargetsWarning": "Sites, die mit entfernten Knoten verbunden sind, können bei AI-Gateway-Anbietern nicht weitergeleitet werden.",
"aiProviderSkipTlsVerification": "TLS-Überprüfung überspringen",
"aiProviderSkipTlsVerificationDescription": "TLS-Zertifikatsüberprüfung für die Upstream-Verbindung deaktivieren",
"aiProviderBudget": "Budget",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Unterstützt /v1/antworten",
"aiCapabilityAnthropicMessages": "Anthropic Nachrichten",
"aiCapabilityAnthropicMessagesDescription": "Unterstützt /v1/nachrichten",
"aiCapabilityV1Models": "Modellliste",
"aiCapabilityV1ModelsDescription": "Unterstützt /v1/models Modellentdeckung",
"aiCapabilityGeminiGenerateContent": "Gemini Inhalt erzeugen",
"aiCapabilityGeminiGenerateContentDescription": "Unterstützt die direkte Gemini-API",
"aiCapabilityBedrockModelInvoke": "Bedrock Modell Aufruf",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Aktionsprotokolle",
"logRetention": "Log-Speicherung",
"logRetentionDescription": "Verwalten, wie lange verschiedene Logs für diese Organisation gespeichert werden oder deaktivieren",
"logRetentionDisabledWarningTitle": "Protokoll-Aufbewahrung deaktiviert",
"logRetentionDisabledWarningDescription": "{logType} werden für diese Organisation nicht aufbewahrt, daher erscheinen neue Aktivitäten hier nicht. Aktivieren Sie die Aufbewahrung in den Sicherheitseinstellungen, um diese Protokolle zu sammeln.",
"logRetentionDisabledWarningButton": "Zu den Sicherheitseinstellungen gehen",
"requestLogsDescription": "Detaillierte Request-Logs für Ressourcen in dieser Organisation anzeigen",
"aiSessionLogs": "AI-Gateway Sitzungsprotokolle",
"aiSessionLogsDescription": "Zeigen Sie Aufforderungs- und Antwortprotokolle für Anfragen des KI-Gateways in dieser Organisation an",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Site- und Tunnelverbindungen, einschließlich Verbindungen und Trennungen.",
"httpDestRequestLogsTitle": "HTTP Anforderungsprotokolle",
"httpDestRequestLogsDescription": "HTTP-Request-Protokolle für proxiierte Ressourcen, einschließlich Methode, Pfad und Antwort-Code.",
"httpDestAISessionLogsTitle": "AI-Sitzungsprotokolle",
"httpDestAISessionLogsDescription": "AI-Gateway-Anfrage- und Antwortsitzungen, einschließlich Eingabeaufforderungen, Modellantworten und Token-Nutzung.",
"httpDestSaveChanges": "Änderungen speichern",
"httpDestCreateDestination": "Ziel erstellen",
"httpDestUpdatedSuccess": "Ziel erfolgreich aktualisiert",
+2
View File
@@ -4090,6 +4090,8 @@
"httpDestConnectionLogsDescription": "Site and tunnel connection events, including connects and disconnects.",
"httpDestRequestLogsTitle": "HTTP Request Logs",
"httpDestRequestLogsDescription": "HTTP request logs for proxied resources, including method, path, and response code.",
"httpDestAISessionLogsTitle": "AI Session Logs",
"httpDestAISessionLogsDescription": "AI gateway request and response sessions, including prompts, model responses, and token usage.",
"httpDestSaveChanges": "Save Changes",
"httpDestCreateDestination": "Create Destination",
"httpDestUpdatedSuccess": "Destination updated successfully",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Herramienta de codificación agentic de Anthropic para el terminal.",
"aiClientConfigDescriptionCodex": "Herramienta de codificación agentic de OpenAI para el terminal.",
"aiClientConfigDescriptionOpencode": "Agente de codificación de terminal de código abierto.",
"aiClientConfigDescriptionCursor": "Editor de código AI construido sobre VS Code.",
"aiClientConfigDescriptionGemini": "La herramienta de codificación de agente de Google para el terminal.",
"aiClientConfigSetup": "Configuración",
"aiClientConfigTabCli": "Automático (CLI)",
"aiClientConfigTabManual": "Configuración manual",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Ruta a través de objetivos en sus sitios",
"aiProviderRoutingModeTargetNote": "Después de crear este proveedor, configure objetivos de sitio en la pestaña de Configuración de Red.",
"aiProviderTargetNoOne": "Este proveedor no tiene objetivos. Agregue un objetivo para enrutar solicitudes a través de sus sitios.",
"aiProviderRemoteNodeTargetsWarning": "Los sitios conectados a nodos remotos son inaccesibles para ser enrutados a los proveedores de AI Gateway.",
"aiProviderSkipTlsVerification": "Omitir verificación de TLS",
"aiProviderSkipTlsVerificationDescription": "Deshabilitar la verificación del certificado TLS para la conexión de upstream",
"aiProviderBudget": "Presupuesto",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Admite /v1/responses",
"aiCapabilityAnthropicMessages": "Mensajes Antropicos",
"aiCapabilityAnthropicMessagesDescription": "Admite /v1/messages",
"aiCapabilityV1Models": "Lista de Modelos",
"aiCapabilityV1ModelsDescription": "Soporta el descubrimiento de modelos /v1/models",
"aiCapabilityGeminiGenerateContent": "Generar contenido Gemini",
"aiCapabilityGeminiGenerateContentDescription": "Admite la API directa de Gemini",
"aiCapabilityBedrockModelInvoke": "Invocar modelo de Bedrock",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Registros de acción",
"logRetention": "Retención de Log",
"logRetentionDescription": "Administrar cuánto tiempo se conservan los diferentes tipos de registros para esta organización o desactivarlos",
"logRetentionDisabledWarningTitle": "Retención de Registros Deshabilitada",
"logRetentionDisabledWarningDescription": "{logType} no se están reteniendo para esta organización, por lo que la nueva actividad no aparecerá aquí. Habilita la retención en la configuración de seguridad para comenzar a recopilar estos registros.",
"logRetentionDisabledWarningButton": "Ir a Configuración de Seguridad",
"requestLogsDescription": "Ver registros de solicitudes detallados para los recursos de esta organización",
"aiSessionLogs": "Registros de Sesiones del Portal de IA",
"aiSessionLogsDescription": "Ver transcripciones de solicitud y respuesta para solicitudes del portal de IA en esta organización",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Eventos de conexión de sitios y túneles, incluyendo conexiones y desconexiones.",
"httpDestRequestLogsTitle": "Registros de Solicitud HTTP",
"httpDestRequestLogsDescription": "Registros de peticiones HTTP para recursos proxyficados, incluyendo método, ruta y código de respuesta.",
"httpDestAISessionLogsTitle": "Registros de Sesión AI",
"httpDestAISessionLogsDescription": "Sesiones de solicitud y respuesta de AI gateway, incluyendo indicaciones, respuestas de modelos, y uso de tokens.",
"httpDestSaveChanges": "Guardar Cambios",
"httpDestCreateDestination": "Crear destino",
"httpDestUpdatedSuccess": "Destino actualizado correctamente",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Outil de codage agentique d'Anthropic pour le terminal.",
"aiClientConfigDescriptionCodex": "Outil de codage agentique d'OpenAI pour le terminal.",
"aiClientConfigDescriptionOpencode": "Agent de codage terminal open source.",
"aiClientConfigDescriptionCursor": "Éditeur de code IA basé sur VS Code.",
"aiClientConfigDescriptionGemini": "Outil de codage agentique de Google pour le terminal.",
"aiClientConfigSetup": "Configuration",
"aiClientConfigTabCli": "Automatique (CLI)",
"aiClientConfigTabManual": "Configuration manuelle",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Route à travers les cibles sur vos sites",
"aiProviderRoutingModeTargetNote": "Après avoir créé ce fournisseur, configurez les cibles du site dans l'onglet Paramètres du réseau.",
"aiProviderTargetNoOne": "Ce fournisseur n'a aucune cible. Ajoutez une cible pour acheminer les requêtes via vos sites.",
"aiProviderRemoteNodeTargetsWarning": "Les sites connectés à des nœuds distants sont inaccessibles pour être routés vers les fournisseurs de passerelles AI.",
"aiProviderSkipTlsVerification": "Ignorer la vérification TLS",
"aiProviderSkipTlsVerificationDescription": "Désactiver la vérification du certificat TLS pour la connexion amont",
"aiProviderBudget": "Budget",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Prend en charge /v1/responses",
"aiCapabilityAnthropicMessages": "Messages Anthropiques",
"aiCapabilityAnthropicMessagesDescription": "Prend en charge /v1/messages",
"aiCapabilityV1Models": "Liste des modèles",
"aiCapabilityV1ModelsDescription": "Prise en charge de la découverte de modèles /v1/models",
"aiCapabilityGeminiGenerateContent": "Générer du Contenu Gemini",
"aiCapabilityGeminiGenerateContentDescription": "Prend en charge l'API directe de Gemini",
"aiCapabilityBedrockModelInvoke": "Invocation du Modèle Bedrock",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Journaux des actions",
"logRetention": "Journaliser la rétention",
"logRetentionDescription": "Gérer la durée de conservation des différents types de logs pour cette organisation ou les désactiver",
"logRetentionDisabledWarningTitle": "Conservation des journaux désactivée",
"logRetentionDisabledWarningDescription": "{logType} ne sont pas conservés pour cette organisation, donc aucune nouvelle activité napparaîtra ici. Activez la conservation dans les paramètres de sécurité pour commencer à collecter ces journaux.",
"logRetentionDisabledWarningButton": "Aller aux paramètres de sécurité",
"requestLogsDescription": "Voir les journaux détaillés des requêtes pour les ressources de cette organisation",
"aiSessionLogs": "Journaux de Session du Portail AI",
"aiSessionLogsDescription": "Voir les transcriptions de l'invite et de la réponse pour les requêtes de portail AI dans cette organisation",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Événements de connexion du site et du tunnel, y compris les connexions et les déconnexions.",
"httpDestRequestLogsTitle": "Journal des Requêtes HTTP",
"httpDestRequestLogsDescription": "Journaux des requêtes HTTP pour les ressources proxiées, y compris la méthode, le chemin et le code de réponse.",
"httpDestAISessionLogsTitle": "Journaux de session AI",
"httpDestAISessionLogsDescription": "Sessions de requête et de réponse de la passerelle AI, y compris les invites, les réponses du modèle et l'utilisation des jetons.",
"httpDestSaveChanges": "Enregistrer les modifications",
"httpDestCreateDestination": "Créer une destination",
"httpDestUpdatedSuccess": "Destination mise à jour avec succès",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Strumento di coding agente di Anthropic per il terminale.",
"aiClientConfigDescriptionCodex": "Strumento di coding agente di OpenAI per il terminale.",
"aiClientConfigDescriptionOpencode": "Agente di coding open source per il terminale.",
"aiClientConfigDescriptionCursor": "Editor di codice AI basato su VS Code.",
"aiClientConfigDescriptionGemini": "Lo strumento di codifica agentica di Google per il terminale.",
"aiClientConfigSetup": "Impostazione",
"aiClientConfigTabCli": "Automatico (CLI)",
"aiClientConfigTabManual": "Configurazione Manuale",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Instrada tramite target sui tuoi siti",
"aiProviderRoutingModeTargetNote": "Dopo aver creato questo provider, configura i target del sito nella scheda Impostazioni di Rete.",
"aiProviderTargetNoOne": "Questo provider non ha alcun target. Aggiungi un target per instradare le richieste attraverso i tuoi siti.",
"aiProviderRemoteNodeTargetsWarning": "I siti collegati a nodi remoti non sono accessibili per essere instradati sui fornitori di AI Gateway.",
"aiProviderSkipTlsVerification": "Salta la verifica TLS",
"aiProviderSkipTlsVerificationDescription": "Disabilita la verifica del certificato TLS per la connessione a monte",
"aiProviderBudget": "Budget",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Supporta /v1/responses",
"aiCapabilityAnthropicMessages": "Messaggi Anthropic",
"aiCapabilityAnthropicMessagesDescription": "Supporta /v1/messages",
"aiCapabilityV1Models": "Elenco dei Modelli",
"aiCapabilityV1ModelsDescription": "Supporta la scoperta del modello /v1/models",
"aiCapabilityGeminiGenerateContent": "Generazione di Contenuti Gemini",
"aiCapabilityGeminiGenerateContentDescription": "Supporta l'API diretta di Gemini",
"aiCapabilityBedrockModelInvoke": "Invoca Modello Bedrock",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Log Azioni",
"logRetention": "Ritenzione Registro",
"logRetentionDescription": "Gestisci per quanto tempo i diversi tipi di log sono mantenuti per questa organizzazione o disabilitali",
"logRetentionDisabledWarningTitle": "Conservazione del Log Disabilitata",
"logRetentionDisabledWarningDescription": "{logType} non vengono conservati per questa organizzazione, quindi le nuove attività non appariranno qui. Abilita la conservazione nelle impostazioni di sicurezza per iniziare a raccogliere questi log.",
"logRetentionDisabledWarningButton": "Vai alle Impostazioni di Sicurezza",
"requestLogsDescription": "Visualizza i registri di richiesta dettagliati per le risorse in questa organizzazione",
"aiSessionLogs": "Log delle Sessioni AI Gateway",
"aiSessionLogsDescription": "Visualizza trascrizioni di prompt e risposte per le richieste del gateway AI in questa organizzazione",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Eventi di connessione al sito e al tunnel, inclusi collegamenti e disconnessioni.",
"httpDestRequestLogsTitle": "Log Richieste HTTP",
"httpDestRequestLogsDescription": "Registri di richiesta HTTP per le risorse proxy, inclusi metodo, percorso e codice di risposta.",
"httpDestAISessionLogsTitle": "Log di Sessione AI",
"httpDestAISessionLogsDescription": "Sessioni di richiesta e risposta AI gateway, comprese le domande, le risposte del modello e l'utilizzo dei token.",
"httpDestSaveChanges": "Salva Modifiche",
"httpDestCreateDestination": "Crea Destinazione",
"httpDestUpdatedSuccess": "Destinazione aggiornata con successo",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Anthropic의 터미널 에이전트 코딩 도구입니다.",
"aiClientConfigDescriptionCodex": "OpenAI의 터미널 에이전트 코딩 도구입니다.",
"aiClientConfigDescriptionOpencode": "오픈 소스 터미널 코딩 에이전트.",
"aiClientConfigDescriptionCursor": "VS Code를 기반으로 한 AI 코드 편집기.",
"aiClientConfigDescriptionGemini": "터미널용 구글의 에이전시 코딩 도구.",
"aiClientConfigSetup": "설정",
"aiClientConfigTabCli": "자동 (CLI)",
"aiClientConfigTabManual": "수동 구성",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "사이트의 타겟을 통해 라우트",
"aiProviderRoutingModeTargetNote": "이 공급자를 생성한 후 네트워크 설정 탭에 사이트 타겟을 구성합니다.",
"aiProviderTargetNoOne": "이 공급자에게 타겟이 없습니다. 사이트를 통해 요청을 라우트하기 위한 타겟을 추가하십시오.",
"aiProviderRemoteNodeTargetsWarning": "원격 노드에 연결된 사이트는 AI 게이트웨이 공급자에게 라우팅되지 않습니다.",
"aiProviderSkipTlsVerification": "TLS 검증 건너뛰기",
"aiProviderSkipTlsVerificationDescription": "상류 연결에 대한 TLS 인증서 검증 비활성화",
"aiProviderBudget": "예산",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "/v1/responses 지원",
"aiCapabilityAnthropicMessages": "Anthropic 메시지",
"aiCapabilityAnthropicMessagesDescription": "/v1/messages 지원",
"aiCapabilityV1Models": "모델 목록",
"aiCapabilityV1ModelsDescription": "/v1/models 모델 검색 지원",
"aiCapabilityGeminiGenerateContent": "Gemini 콘텐츠 생성",
"aiCapabilityGeminiGenerateContentDescription": "직접 Gemini API 지원",
"aiCapabilityBedrockModelInvoke": "Bedrock 모델 실행",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "작업 로그",
"logRetention": "로그 보관",
"logRetentionDescription": "다양한 유형의 로그를 이 조직에 대해 얼마나 오래 보관할지 관리하거나 비활성화합니다",
"logRetentionDisabledWarningTitle": "로그 보존 비활성화",
"logRetentionDisabledWarningDescription": "{logType}이/가 이 조직에 대해 보존되지 않으므로 새로운 활동이 여기에 나타나지 않습니다. 보안을 설정해서 보존을 활성화하여 이러한 로그를 수집하기 시작하세요.",
"logRetentionDisabledWarningButton": "보안 설정으로 이동",
"requestLogsDescription": "이 조직의 자원에 대한 상세한 요청 로그를 봅니다",
"aiSessionLogs": "AI 게이트웨이 세션 로그",
"aiSessionLogsDescription": "이 조직의 AI 게이트웨이 요청에 대한 프롬프트 및 응답 대본을 봅니다",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "사이트 및 터널 연결 이벤트, 연결 및 연결 끊기를 포함합니다.",
"httpDestRequestLogsTitle": "HTTP 요청 로그",
"httpDestRequestLogsDescription": "프록시된 리소스에 대한 HTTP 요청 로그, 메서드, 경로 및 응답 코드를 포함합니다.",
"httpDestAISessionLogsTitle": "AI 세션 로그",
"httpDestAISessionLogsDescription": "AI 게이트웨이 요청 및 응답 세션, 프롬프트, 모델 응답 및 토큰 사용을 포함합니다.",
"httpDestSaveChanges": "변경 사항 저장",
"httpDestCreateDestination": "대상지 생성",
"httpDestUpdatedSuccess": "대상지가 성공적으로 업데이트되었습니다",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Anthropics agentiske kodingsverktøy for terminalen.",
"aiClientConfigDescriptionCodex": "OpenAIs agentiske kodingsverktøy for terminalen.",
"aiClientConfigDescriptionOpencode": "Åpen kildekode terminal kodeagent.",
"aiClientConfigDescriptionCursor": "AI-kodeeditor bygget på VS Code.",
"aiClientConfigDescriptionGemini": "Googles agentiske koding verktøy for terminalen.",
"aiClientConfigSetup": "Oppsett",
"aiClientConfigTabCli": "Automatisk (CLI)",
"aiClientConfigTabManual": "Manuell konfigurasjon",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Rute gjennom mål på dine nettsteder",
"aiProviderRoutingModeTargetNote": "Etter å ha opprettet denne leverandøren, konfigurer områdemål på fanen Nettverksinnstillinger.",
"aiProviderTargetNoOne": "Denne leverandøren har ingen mål. Legg til et mål for å rute forespørsler gjennom dine nettsteder.",
"aiProviderRemoteNodeTargetsWarning": "Nettsteder tilkoblet eksterne noder er utilgjengelige for ruting til på AI Gateway leverandører.",
"aiProviderSkipTlsVerification": "Hopp over TLS-verifisering",
"aiProviderSkipTlsVerificationDescription": "Deaktiver TLS-sertifikatverifisering for oppstrøms tilkobling",
"aiProviderBudget": "Budsjett",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Støtter /v1/responser",
"aiCapabilityAnthropicMessages": "Anthropic Meldinger",
"aiCapabilityAnthropicMessagesDescription": "Støtter /v1/meldinger",
"aiCapabilityV1Models": "Modelliste",
"aiCapabilityV1ModelsDescription": "Støtter /v1/modeller modelloppdagelse",
"aiCapabilityGeminiGenerateContent": "Gemini Generer Innhold",
"aiCapabilityGeminiGenerateContentDescription": "Støtter direkte Gemini API",
"aiCapabilityBedrockModelInvoke": "Bedrock Modell Påkalling",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Handlingslogger",
"logRetention": "Logg tilbaketrekning",
"logRetentionDescription": "Håndter hvor lenge ulike typer logger beholdes for denne organisasjonen, eller deaktiver dem",
"logRetentionDisabledWarningTitle": "Loggbevaring deaktivert",
"logRetentionDisabledWarningDescription": "{logType} blir ikke lagret for denne organisasjonen, så ny aktivitet vises ikke her. Aktiver lagring i sikkerhetsinnstillingene for å begynne å samle inn disse loggene.",
"logRetentionDisabledWarningButton": "Gå til sikkerhetsinnstillinger",
"requestLogsDescription": "Se detaljerte forespørselslogger for ressurser i denne organisasjonen",
"aiSessionLogs": "AI Portal Sesjonslogger",
"aiSessionLogsDescription": "Vis stikkord- og responsutskrifter for AI-portal forespørsler i denne organisasjonen",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Utstyrs- og tunneltilkoblingshendelser, inkludert forbindelser og frakobling.",
"httpDestRequestLogsTitle": "HTTP-forespørselslogger",
"httpDestRequestLogsDescription": "HTTP-forespørsel logger for bekreftede ressurser, inkludert metode, bane og responskode.",
"httpDestAISessionLogsTitle": "AI øktlogger",
"httpDestAISessionLogsDescription": "Forespørsels- og svarøkter for AI gateway, inkludert forespørsler, modellresponser og tokenbruk.",
"httpDestSaveChanges": "Lagre endringer",
"httpDestCreateDestination": "Opprett mål",
"httpDestUpdatedSuccess": "Målet er oppdatert",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Anthropic's agentische coderingstool voor de terminal.",
"aiClientConfigDescriptionCodex": "OpenAI's agentische coderingstool voor de terminal.",
"aiClientConfigDescriptionOpencode": "Open source terminal coderingsagent.",
"aiClientConfigDescriptionCursor": "AI-code-editor gebouwd op VS Code.",
"aiClientConfigDescriptionGemini": "Agentisch coderingstool van Google voor de terminal.",
"aiClientConfigSetup": "Instellen",
"aiClientConfigTabCli": "Automatisch (CLI)",
"aiClientConfigTabManual": "Handmatige configuratie",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Routeer door doelen op uw sites",
"aiProviderRoutingModeTargetNote": "Nadat u deze provider hebt aangemaakt, configureert u site-doelen op het tabblad Netwerkinstellingen.",
"aiProviderTargetNoOne": "Deze provider heeft geen doelen. Voeg een doel toe om verzoeken via uw sites te routeren.",
"aiProviderRemoteNodeTargetsWarning": "Sites die verbonden zijn met externe nodes zijn niet toegankelijk om naar te worden gerouteerd op AI Gateway-providers.",
"aiProviderSkipTlsVerification": "Sla TLS-verificatie over",
"aiProviderSkipTlsVerificationDescription": "Schakel TLS-certificaatverificatie voor de upstream-verbinding uit",
"aiProviderBudget": "Budget",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Ondersteunt /v1/responses",
"aiCapabilityAnthropicMessages": "Anthropic Berichten",
"aiCapabilityAnthropicMessagesDescription": "Ondersteunt /v1/messages",
"aiCapabilityV1Models": "Modellenlijst",
"aiCapabilityV1ModelsDescription": "Ondersteunt /v1/models modelontdekking",
"aiCapabilityGeminiGenerateContent": "Gemini Inhoud Genereren",
"aiCapabilityGeminiGenerateContentDescription": "Ondersteunt de directe Gemini API",
"aiCapabilityBedrockModelInvoke": "Bedrock Model Aanroep",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Actie logs",
"logRetention": "Log bewaring",
"logRetentionDescription": "Beheren hoe lang verschillende soorten logs bewaard worden voor deze organisatie of schakel ze uit",
"logRetentionDisabledWarningTitle": "Logboekbewaring Uitgeschakeld",
"logRetentionDisabledWarningDescription": "{logType} worden niet bewaard voor deze organisatie, dus nieuwe activiteiten zullen hier niet verschijnen. Schakel bewaren in beveiligingsinstellingen in om deze logboeken te verzamelen.",
"logRetentionDisabledWarningButton": "Ga naar Beveiligingsinstellingen",
"requestLogsDescription": "Bekijk gedetailleerde verzoeklogboeken voor resources in deze organisatie",
"aiSessionLogs": "AI Gateway Sessie Logs",
"aiSessionLogsDescription": "Bekijk prompt- en reactie-transcripten voor AI-gateway-aanvragen in deze organisatie",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Verbinding met de Site en tunnel maken verbroken, inclusief verbindingen en verbindingen.",
"httpDestRequestLogsTitle": "HTTP-aanvraaglogboeken",
"httpDestRequestLogsDescription": "HTTP request logs voor proxied hulpmiddelen, waaronder methode, pad en response code.",
"httpDestAISessionLogsTitle": "AI Sessielogboeken",
"httpDestAISessionLogsDescription": "AI gateway verzoek- en reactiesessies, inclusief prompts, modelreacties en tokengebruik.",
"httpDestSaveChanges": "Wijzigingen opslaan",
"httpDestCreateDestination": "Maak bestemming aan",
"httpDestUpdatedSuccess": "Bestemming succesvol bijgewerkt",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Agent narzędzia kodującego Anthropic dla terminala.",
"aiClientConfigDescriptionCodex": "Agent narzędzia kodującego OpenAI dla terminala.",
"aiClientConfigDescriptionOpencode": "Agent open source do kodowania w terminalu.",
"aiClientConfigDescriptionCursor": "Edytor kodu AI oparty na VS Code.",
"aiClientConfigDescriptionGemini": "Agent narzędzi kodowych Google dla terminala.",
"aiClientConfigSetup": "Ustawienie",
"aiClientConfigTabCli": "Automatyczne (CLI)",
"aiClientConfigTabManual": "Konfiguracja ręczna",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Trasa przez cele na Twoich witrynach",
"aiProviderRoutingModeTargetNote": "Po utworzeniu tego dostawcy, skonfiguruj cele witryny na karcie Ustawienia sieci.",
"aiProviderTargetNoOne": "Ten dostawca nie ma żadnych celów. Dodaj cel, aby trasować zapytania przez swoje witryny.",
"aiProviderRemoteNodeTargetsWarning": "Witryny podłączone do zdalnych węzłów są niedostępne do trasowania przez dostawców AI Gateway.",
"aiProviderSkipTlsVerification": "Pomiń weryfikację TLS",
"aiProviderSkipTlsVerificationDescription": "Wyłącz weryfikację certyfikatu TLS dla połączenia w górę",
"aiProviderBudget": "Budżet",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Obsługuje /v1/responses",
"aiCapabilityAnthropicMessages": "Anthropic Wiadomości",
"aiCapabilityAnthropicMessagesDescription": "Obsługuje /v1/messages",
"aiCapabilityV1Models": "Lista modeli",
"aiCapabilityV1ModelsDescription": "Obsługuje odkrywanie modeli /v1/models",
"aiCapabilityGeminiGenerateContent": "Gemini Generowanie Treści",
"aiCapabilityGeminiGenerateContentDescription": "Obsługuje bezpośredni Gemini API",
"aiCapabilityBedrockModelInvoke": "Model Bedrock Wywołanie",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Dzienniki działań",
"logRetention": "Zachowanie dziennika",
"logRetentionDescription": "Zarządzaj jak długo różne typy logów są zachowane dla tej organizacji lub wyłącz je",
"logRetentionDisabledWarningTitle": "Wyłączone przechowywanie logów",
"logRetentionDisabledWarningDescription": "{logType} nie są przechowywane dla tej organizacji, więc nowe aktywności nie pojawią się tutaj. Włącz przechowywanie w ustawieniach bezpieczeństwa, aby zacząć zbierać te logi.",
"logRetentionDisabledWarningButton": "Przejdź do ustawień bezpieczeństwa",
"requestLogsDescription": "Zobacz szczegółowe dzienniki żądań zasobów w tej organizacji",
"aiSessionLogs": "Dzienniki Sesji Bramy AI",
"aiSessionLogsDescription": "Zobacz transkrypcje podpowiedzi i odpowiedzi dla żądań bramy AI w tej organizacji",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Zdarzenia związane z miejscem i tunelem, w tym połączenia i rozłączenia.",
"httpDestRequestLogsTitle": "Dzienniki żądań HTTP",
"httpDestRequestLogsDescription": "Logi żądań HTTP dla zasobów proxy, w tym metody, ścieżki i kodu odpowiedzi.",
"httpDestAISessionLogsTitle": "Dzienniki sesji AI",
"httpDestAISessionLogsDescription": "Żądania i sesje odpowiedzi bramki AI, w tym zapytania, odpowiedzi modeli i użycie tokenów.",
"httpDestSaveChanges": "Zapisz zmiany",
"httpDestCreateDestination": "Utwórz cel",
"httpDestUpdatedSuccess": "Cel został pomyślnie zaktualizowany",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Ferramenta de codificação agentic de Anthropic para o terminal.",
"aiClientConfigDescriptionCodex": "Ferramenta de codificação agentic da OpenAI para o terminal.",
"aiClientConfigDescriptionOpencode": "Agente de codificação de terminal de código aberto.",
"aiClientConfigDescriptionCursor": "Editor de código de IA baseado no VS Code.",
"aiClientConfigDescriptionGemini": "Ferramenta de codificação agêntica do terminal do Google.",
"aiClientConfigSetup": "Configuração",
"aiClientConfigTabCli": "Automático (CLI)",
"aiClientConfigTabManual": "Configuração Manual",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Roteie através de alvos em seus sites",
"aiProviderRoutingModeTargetNote": "Após criar este provedor, configure alvos do site na aba Configurações de Rede.",
"aiProviderTargetNoOne": "Este provedor não tem alvos. Adicione um alvo para rotear pedidos pelos seus sites.",
"aiProviderRemoteNodeTargetsWarning": "Sites conectados a nós remotos estão inacessíveis para serem roteados para os provedores do Gateway de IA.",
"aiProviderSkipTlsVerification": "Pular Verificação TLS",
"aiProviderSkipTlsVerificationDescription": "Desativar a verificação de certificado TLS para a conexão upstream",
"aiProviderBudget": "Orçamento",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Suporta /v1/responses",
"aiCapabilityAnthropicMessages": "Mensagens Antropicas",
"aiCapabilityAnthropicMessagesDescription": "Suporta /v1/messages",
"aiCapabilityV1Models": "Lista de Modelos",
"aiCapabilityV1ModelsDescription": "Suporta descoberta de modelos /v1/models",
"aiCapabilityGeminiGenerateContent": "Gêmeos Gerar Conteúdo",
"aiCapabilityGeminiGenerateContentDescription": "Suporta a API diretta do Gêmeos",
"aiCapabilityBedrockModelInvoke": "Modelo Bedrock Invocar",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Logs de Ações",
"logRetention": "Retenção de Log",
"logRetentionDescription": "Gerenciar quanto tempo os diferentes tipos de logs são mantidos para esta organização ou desativá-los",
"logRetentionDisabledWarningTitle": "Retenção de Logs Desativada",
"logRetentionDisabledWarningDescription": "{logType} não estão sendo retidos para esta organização, portanto, novas atividades não aparecerão aqui. Ative a retenção nas configurações de segurança para começar a coletar esses logs.",
"logRetentionDisabledWarningButton": "Ir para Configurações de Segurança",
"requestLogsDescription": "Ver registros de pedidos detalhados de recursos nesta organização",
"aiSessionLogs": "Registros de Sessão do Gateway de IA",
"aiSessionLogsDescription": "Veja as transcrições de prompt e resposta para solicitações de gateway de IA nesta organização",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Eventos de conexão de site e túnel, incluindo conexões e desconexões.",
"httpDestRequestLogsTitle": "Registros de Pedidos HTTP",
"httpDestRequestLogsDescription": "Logs de solicitação HTTP para recursos proxy incluindo o método, o caminho e o código de resposta.",
"httpDestAISessionLogsTitle": "Logs de Sessão de IA",
"httpDestAISessionLogsDescription": "Sessões de solicitação e resposta de gateway de IA, incluindo prompts, respostas de modelos e uso de tokens.",
"httpDestSaveChanges": "Salvar as alterações",
"httpDestCreateDestination": "Criar destino",
"httpDestUpdatedSuccess": "Destino atualizado com sucesso",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Агентивное кодирующее средство Anthropic для терминала.",
"aiClientConfigDescriptionCodex": "Агентивное кодирующее средство OpenAI для терминала.",
"aiClientConfigDescriptionOpencode": "Открытый исходный агент для кодирования в терминале.",
"aiClientConfigDescriptionCursor": "AI редактор кода на основе VS Code.",
"aiClientConfigDescriptionGemini": "Инструмент программирования Google для терминала.",
"aiClientConfigSetup": "Настройка",
"aiClientConfigTabCli": "Автоматическое (CLI)",
"aiClientConfigTabManual": "Ручная конфигурация",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Маршрутизация через цели на ваших сайтах",
"aiProviderRoutingModeTargetNote": "После создания этого провайдера настройте целевые сайты на вкладке Сетевые настройки.",
"aiProviderTargetNoOne": "У этого провайдера нет целей. Добавьте цель для маршрутизации запросов через ваши сайты.",
"aiProviderRemoteNodeTargetsWarning": "Сайты, подключенные к удалённым узлам, недоступны для маршрутизации с помощью провайдеров AI Gateway.",
"aiProviderSkipTlsVerification": "Пропустить проверку TLS",
"aiProviderSkipTlsVerificationDescription": "Отключить проверку сертификата TLS для исходного соединения",
"aiProviderBudget": "Бюджет",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "Поддерживает /v1/responses",
"aiCapabilityAnthropicMessages": "Сообщения Anthropic",
"aiCapabilityAnthropicMessagesDescription": "Поддерживает /v1/messages",
"aiCapabilityV1Models": "Список моделей",
"aiCapabilityV1ModelsDescription": "Поддерживает обнаружение моделей /v1/models",
"aiCapabilityGeminiGenerateContent": "Gemini Создание контента",
"aiCapabilityGeminiGenerateContentDescription": "Поддерживает прямой API Gemini",
"aiCapabilityBedrockModelInvoke": "Вызов модели Bedrock",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Журнал действий",
"logRetention": "Сохранение журнала",
"logRetentionDescription": "Управление сохранением различных типов журналов для этой организации или отключение их",
"logRetentionDisabledWarningTitle": "Хранение логов отключено",
"logRetentionDisabledWarningDescription": "Логи {logType} не сохраняются для этой организации, поэтому здесь не будет отображаться новая активность. Включите хранение в настройках безопасности, чтобы начать собирать эти логи.",
"logRetentionDisabledWarningButton": "Перейти в настройки безопасности",
"requestLogsDescription": "Просмотреть подробные журналы запроса ресурсов в этой организации",
"aiSessionLogs": "AI Логи сессии шлюза",
"aiSessionLogsDescription": "Просмотр транскриптов запросов и ответов для шлюзов AI в этой организации",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "События связи с сайтами и туннелями, включая соединения и отключения.",
"httpDestRequestLogsTitle": "HTTP Запросы Логи",
"httpDestRequestLogsDescription": "Журналы запросов HTTP для проксируемых ресурсов, включая метод, путь и код ответа.",
"httpDestAISessionLogsTitle": "Логи AI сессий",
"httpDestAISessionLogsDescription": "Запросы и ответы AI gateway, включая подсказки, ответы моделей и использование токенов.",
"httpDestSaveChanges": "Сохранить изменения",
"httpDestCreateDestination": "Создать адрес назначения",
"httpDestUpdatedSuccess": "Адрес назначения успешно обновлен",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Anthropic'in terminal için aracılık kodlama aracı.",
"aiClientConfigDescriptionCodex": "OpenAI'nin terminal için aracılık kodlama aracı.",
"aiClientConfigDescriptionOpencode": "Açık kaynak terminal kodlama aracı.",
"aiClientConfigDescriptionCursor": "VS Code üzerine kurulu yapay zeka kod editörü.",
"aiClientConfigDescriptionGemini": "Google'un terminal için agentik kodlama aracı.",
"aiClientConfigSetup": "Kurulum",
"aiClientConfigTabCli": "Otomatik (CLI)",
"aiClientConfigTabManual": "Manuel Yapılandırma",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "Siteniz üzerindeki hedefler üzerinden yönlendirin",
"aiProviderRoutingModeTargetNote": "Bu sağlayıcıyı oluşturduktan sonra, site hedeflerini Ağ Ayarları sekmesinde yapılandırın.",
"aiProviderTargetNoOne": "Bu sağlayıcının herhangi bir hedefi yok. Sitemiz üzerinden istekleri yönlendirmek için bir hedef ekleyin.",
"aiProviderRemoteNodeTargetsWarning": "Uzaktaki düğümlere bağlı siteler, AI Geçidi sağlayıcılarına yönlendirilemez durumda.",
"aiProviderSkipTlsVerification": "TLS Doğrulamayı Atla",
"aiProviderSkipTlsVerificationDescription": "Yukarı akış bağlantısı için TLS sertifika doğrulamasını devre dışı bırakın",
"aiProviderBudget": "Bütçe",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "/v1/yanıtlar desteği sağlar",
"aiCapabilityAnthropicMessages": "Anthropic Mesajlar",
"aiCapabilityAnthropicMessagesDescription": "/v1/mesajlar desteği sağlar",
"aiCapabilityV1Models": "Modeller Listesi",
"aiCapabilityV1ModelsDescription": "T /v1/models model keşfini destekler",
"aiCapabilityGeminiGenerateContent": "Gemini İçerik Üret",
"aiCapabilityGeminiGenerateContentDescription": "Doğrudan Gemini API desteği sağlar",
"aiCapabilityBedrockModelInvoke": "Bedrock Modeli Çağır",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "Eylem Günlükleri",
"logRetention": "Kayıt Saklama",
"logRetentionDescription": "Bu organizasyon için farklı türdeki günlüklerin ne kadar süre saklanacağını yönetin veya devre dışı bırakın",
"logRetentionDisabledWarningTitle": "Günlük Saklama Devre Dışı Bırakıldı",
"logRetentionDisabledWarningDescription": "{logType} bu organizasyon için saklanmıyor, bu nedenle yeni etkinlikler burada görünmeyecek. Bu günlükleri toplamak için güvenlik ayarlarında saklamayı etkinleştirin.",
"logRetentionDisabledWarningButton": "Güvenlik Ayarlarına Git",
"requestLogsDescription": "Bu organizasyondaki kaynaklar için ayrıntılı istek günlüklerini görüntüleyin",
"aiSessionLogs": "AI Ağ Geçidi Oturum Günlükleri",
"aiSessionLogsDescription": "Bu organizasyondaki AI ağ geçidi isteklerinin istem ve yanıt transkriptlerini görüntüleyin",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "Site ve tünel bağlantı olayları, bağlantılar ve bağlantı kesilmeleri dahil.",
"httpDestRequestLogsTitle": "HTTP İstek Günlükleri",
"httpDestRequestLogsDescription": "Yönlendirilmiş kaynaklar için HTTP istek kayıtları, yöntem, yol ve yanıt kodu dahil.",
"httpDestAISessionLogsTitle": "AI Oturum Günlükleri",
"httpDestAISessionLogsDescription": "AI geçidi istek ve yanıt oturumları, istemler, model yanıtları ve token kullanımı dahil.",
"httpDestSaveChanges": "Değişiklikleri Kaydet",
"httpDestCreateDestination": "Hedef Oluştur",
"httpDestUpdatedSuccess": "Hedef başarıyla güncellendi",
+9 -1
View File
@@ -1785,7 +1785,7 @@
"aiClientConfigDescriptionClaude": "Anthropic 的终端代理编码工具。",
"aiClientConfigDescriptionCodex": "OpenAI 的终端代理编码工具。",
"aiClientConfigDescriptionOpencode": "开源终端编码代理。",
"aiClientConfigDescriptionCursor": "基于 VS Code 的 AI 代码编辑器。",
"aiClientConfigDescriptionGemini": "Google的终端代理编码工具。",
"aiClientConfigSetup": "设置",
"aiClientConfigTabCli": "自动 (CLI)",
"aiClientConfigTabManual": "手动配置",
@@ -1891,6 +1891,7 @@
"aiProviderRoutingModeTargetDescription": "通过您站点上的目标进行路由",
"aiProviderRoutingModeTargetNote": "创建此提供商后,在“网络设置”选项卡中配置站点目标。",
"aiProviderTargetNoOne": "该提供商没有任何目标。 添加目标以通过您的站点路由请求。",
"aiProviderRemoteNodeTargetsWarning": "连接到远程节点的站点无法在AI网关供应商上被路由。",
"aiProviderSkipTlsVerification": "跳过TLS验证",
"aiProviderSkipTlsVerificationDescription": "禁用上游连接的TLS证书验证",
"aiProviderBudget": "预算",
@@ -1923,6 +1924,8 @@
"aiCapabilityOpenaiResponsesDescription": "支持 /v1/responses",
"aiCapabilityAnthropicMessages": "Anthropic 消息",
"aiCapabilityAnthropicMessagesDescription": "支持 /v1/messages",
"aiCapabilityV1Models": "模型列表",
"aiCapabilityV1ModelsDescription": "支持/v1/models模型发现",
"aiCapabilityGeminiGenerateContent": "Gemini 生成内容",
"aiCapabilityGeminiGenerateContentDescription": "支持直接Gemini API",
"aiCapabilityBedrockModelInvoke": "Bedrock 模型调用",
@@ -3548,6 +3551,9 @@
"sidebarLogsAction": "操作日志",
"logRetention": "日志保留",
"logRetentionDescription": "管理不同类型的日志为这个机构保留多长时间或禁用这些日志",
"logRetentionDisabledWarningTitle": "日志保留已禁用",
"logRetentionDisabledWarningDescription": "{logType}未在此组织中被保留,因此新活动不会显示在此处。请在安全设置中启用日志保留以开始收集这些日志。",
"logRetentionDisabledWarningButton": "转到安全设置",
"requestLogsDescription": "查看此机构资源的详细请求日志",
"aiSessionLogs": "AI 网关会话日志",
"aiSessionLogsDescription": "查看此组织中AI网关请求的提示和响应记录",
@@ -4081,6 +4087,8 @@
"httpDestConnectionLogsDescription": "站点和隧道连接事件,包括连接和断开连接。",
"httpDestRequestLogsTitle": "请求日志",
"httpDestRequestLogsDescription": "HTTP 请求代理资源日志,包括方法、路径和响应代码。",
"httpDestAISessionLogsTitle": "AI会话日志",
"httpDestAISessionLogsDescription": "AI网关请求和响应会话,包括提示、模型响应和令牌使用。",
"httpDestSaveChanges": "保存更改",
"httpDestCreateDestination": "创建目标",
"httpDestUpdatedSuccess": "目标已成功更新",
+3
View File
@@ -468,6 +468,9 @@ export const eventStreamingDestinations = pgTable(
sendRequestLogs: boolean("sendRequestLogs").notNull().default(false),
sendActionLogs: boolean("sendActionLogs").notNull().default(false),
sendAccessLogs: boolean("sendAccessLogs").notNull().default(false),
sendAISessionLogs: boolean("sendAISessionLogs")
.notNull()
.default(false),
type: varchar("type", { length: 50 }).notNull(), // e.g. "http", "kafka", etc.
config: text("config").notNull(), // JSON string with the configuration for the destination
enabled: boolean("enabled").notNull().default(true),
+3
View File
@@ -459,6 +459,9 @@ export const eventStreamingDestinations = sqliteTable(
sendAccessLogs: integer("sendAccessLogs", { mode: "boolean" })
.notNull()
.default(false),
sendAISessionLogs: integer("sendAISessionLogs", { mode: "boolean" })
.notNull()
.default(false),
type: text("type").notNull(), // e.g. "http", "kafka", etc.
config: text("config").notNull(), // JSON string with the configuration for the destination
enabled: integer("enabled", { mode: "boolean" })
+27 -14
View File
@@ -1,20 +1,26 @@
import { db, exitNodes, Transaction } from "@server/db";
import { db, exitNodes, exitNodeOrgs, Transaction } from "@server/db";
import config from "@server/lib/config";
import { findNextAvailableCidr } from "@server/lib/ip";
import { lockManager } from "#dynamic/lib/lock";
import { eq } from "drizzle-orm";
/**
* Reserves the next available exit node subnet.
*
* Exit node subnets must never overlap with one another - regardless of
* which org(s) they belong to - since HA exit nodes can end up routing for
* the same org. This acquires a lock that the caller MUST release (via the
* returned `release`) only after the chosen address has been durably
* persisted (e.g. after the enclosing transaction commits), otherwise
* concurrent callers can race and pick the same subnet.
* There isn't enough address space to give every exit node in every org a
* globally unique subnet, so we only guarantee uniqueness among exit nodes
* that already belong to the same org - that's all that actually matters,
* since HA only routes multiple exit nodes for a single org. Pass `orgId` to
* scope the search to that org's existing exit nodes; without it, the search
* considers every exit node (used by flows with no org context, e.g. the
* initial gerbil exit node bootstrap). This acquires a lock that the caller
* MUST release (via the returned `release`) only after the chosen address
* has been durably persisted (e.g. after the enclosing transaction commits),
* otherwise concurrent callers can race and pick the same subnet.
*/
export async function getNextAvailableSubnet(
trx: Transaction | typeof db = db
trx: Transaction | typeof db = db,
orgId?: string
): Promise<{ value: string; release: () => Promise<void> }> {
const lockKey = "exit-node-subnet-allocation";
const acquired = await lockManager.acquireLockWithRetry(lockKey, 6000);
@@ -24,12 +30,19 @@ export async function getNextAvailableSubnet(
const release = () => lockManager.releaseLock(lockKey, acquired);
try {
// Get all existing subnets from routes table
const existingAddresses = await trx
.select({
address: exitNodes.address
})
.from(exitNodes);
// Get existing subnets, scoped to this org's exit nodes when known
const existingAddresses = orgId
? await trx
.select({ address: exitNodes.address })
.from(exitNodes)
.innerJoin(
exitNodeOrgs,
eq(exitNodeOrgs.exitNodeId, exitNodes.exitNodeId)
)
.where(eq(exitNodeOrgs.orgId, orgId))
: await trx
.select({ address: exitNodes.address })
.from(exitNodes);
const addresses = existingAddresses.map((a) => a.address);
let subnet = findNextAvailableCidr(
@@ -19,7 +19,8 @@ import {
requestAuditLog,
actionAuditLog,
accessAuditLog,
connectionAuditLog
connectionAuditLog,
aiSessionLog
} from "@server/db";
import logger from "@server/logger";
import { and, eq, gt, desc, max, sql } from "drizzle-orm";
@@ -309,6 +310,7 @@ export class LogStreamingManager {
if (dest.sendActionLogs) enabledTypes.push("action");
if (dest.sendAccessLogs) enabledTypes.push("access");
if (dest.sendConnectionLogs) enabledTypes.push("connection");
if (dest.sendAISessionLogs) enabledTypes.push("aiSession");
if (enabledTypes.length === 0) return;
@@ -585,6 +587,13 @@ export class LogStreamingManager {
.where(eq(connectionAuditLog.orgId, orgId));
return row?.maxId ?? 0;
}
case "aiSession": {
const [row] = await logsDb
.select({ maxId: max(aiSessionLog.id) })
.from(aiSessionLog)
.where(eq(aiSessionLog.orgId, orgId));
return row?.maxId ?? 0;
}
}
} catch (err) {
logger.warn(
@@ -670,6 +679,21 @@ export class LogStreamingManager {
.limit(limit)) as Array<
Record<string, unknown> & { id: number }
>;
case "aiSession":
return (await logsDb
.select()
.from(aiSessionLog)
.where(
and(
eq(aiSessionLog.orgId, orgId),
gt(aiSessionLog.id, afterId)
)
)
.orderBy(aiSessionLog.id)
.limit(limit)) as Array<
Record<string, unknown> & { id: number }
>;
}
}
@@ -694,6 +718,14 @@ export class LogStreamingManager {
timestamp =
typeof row.startedAt === "number" ? row.startedAt : 0;
break;
case "aiSession":
// createdAt is stored as epoch milliseconds; normalise to
// epoch seconds to match the other log types.
timestamp =
typeof row.createdAt === "number"
? Math.floor(row.createdAt / 1000)
: 0;
break;
}
const orgId = typeof row.orgId === "string" ? row.orgId : "";
+3 -2
View File
@@ -15,13 +15,14 @@
// Log type identifiers
// ---------------------------------------------------------------------------
export type LogType = "request" | "action" | "access" | "connection";
export type LogType = "request" | "action" | "access" | "connection" | "aiSession";
export const LOG_TYPES: LogType[] = [
"request",
"action",
"access",
"connection"
"connection",
"aiSession"
];
// ---------------------------------------------------------------------------
@@ -37,7 +37,8 @@ const bodySchema = z.strictObject({
sendConnectionLogs: z.boolean().optional().default(false),
sendRequestLogs: z.boolean().optional().default(false),
sendActionLogs: z.boolean().optional().default(false),
sendAccessLogs: z.boolean().optional().default(false)
sendAccessLogs: z.boolean().optional().default(false),
sendAISessionLogs: z.boolean().optional().default(false)
});
export type CreateEventStreamingDestinationResponse = {
@@ -122,7 +123,8 @@ export async function createEventStreamingDestination(
sendAccessLogs: parsedBody.data.sendAccessLogs,
sendActionLogs: parsedBody.data.sendActionLogs,
sendConnectionLogs: parsedBody.data.sendConnectionLogs,
sendRequestLogs: parsedBody.data.sendRequestLogs
sendRequestLogs: parsedBody.data.sendRequestLogs,
sendAISessionLogs: parsedBody.data.sendAISessionLogs
})
.returning();
@@ -60,6 +60,7 @@ export type ListEventStreamingDestinationsResponse = {
sendRequestLogs: boolean;
sendActionLogs: boolean;
sendAccessLogs: boolean;
sendAISessionLogs: boolean;
}[];
pagination: {
total: number;
@@ -83,7 +84,8 @@ const ListEventStreamingDestinationsResponseDataSchema = z.object({
sendConnectionLogs: z.boolean(),
sendRequestLogs: z.boolean(),
sendActionLogs: z.boolean(),
sendAccessLogs: z.boolean()
sendAccessLogs: z.boolean(),
sendAISessionLogs: z.boolean()
})
),
pagination: z.object({
@@ -40,7 +40,8 @@ const bodySchema = z.strictObject({
sendConnectionLogs: z.boolean().optional(),
sendRequestLogs: z.boolean().optional(),
sendActionLogs: z.boolean().optional(),
sendAccessLogs: z.boolean().optional()
sendAccessLogs: z.boolean().optional(),
sendAISessionLogs: z.boolean().optional()
});
export type UpdateEventStreamingDestinationResponse = {
@@ -125,7 +126,7 @@ export async function updateEventStreamingDestination(
);
}
const { type, config: configToUpdate, enabled, sendAccessLogs, sendActionLogs, sendConnectionLogs, sendRequestLogs } = parsedBody.data;
const { type, config: configToUpdate, enabled, sendAccessLogs, sendActionLogs, sendConnectionLogs, sendRequestLogs, sendAISessionLogs } = parsedBody.data;
const updateData: Record<string, unknown> = {
updatedAt: Date.now()
@@ -141,6 +142,7 @@ export async function updateEventStreamingDestination(
if (sendActionLogs !== undefined) updateData.sendActionLogs = sendActionLogs;
if (sendConnectionLogs !== undefined) updateData.sendConnectionLogs = sendConnectionLogs;
if (sendRequestLogs !== undefined) updateData.sendRequestLogs = sendRequestLogs;
if (sendAISessionLogs !== undefined) updateData.sendAISessionLogs = sendAISessionLogs;
await db
.update(eventStreamingDestinations)
@@ -191,13 +191,20 @@ export async function createRemoteExitNode(
// If this remote exit node isn't already backing an exit node in
// another org, we're about to create a brand new one. Reserve a
// subnet for it up front so the allocation lock is held across the
// whole insert - this guarantees exit node subnets never overlap,
// even under concurrent creation, which matters for HA setups.
// subnet for it up front, scoped to this org's existing exit nodes,
// so the allocation lock is held across the whole insert - this
// guarantees exit node subnets never overlap within the org, even
// under concurrent creation, which matters for HA setups. Subnets
// may still be reused across different orgs; there isn't enough
// address space to avoid that, and it isn't necessary since HA only
// routes multiple exit nodes for the same org.
let releaseSubnetLock: (() => Promise<void>) | null = null;
let newExitNodeAddress: string | null = null;
if (!existingExitNode) {
const { value, release } = await getNextAvailableSubnet();
const { value, release } = await getNextAvailableSubnet(
db,
orgId
);
newExitNodeAddress = value;
releaseSubnetLock = release;
}
@@ -23,6 +23,12 @@ export async function createCertificate(
throw new Error(`Domain with ID ${domainId} not found`);
}
// Note: certificates.domain has a global UNIQUE constraint (it is not
// scoped per-domainId), so existence must be checked by domain value
// alone. Filtering on domainId here as well can cause this check to
// miss an existing cert (e.g. if it was stored under a different but
// still-valid domainId), leading to an INSERT that then fails on the
// unique constraint.
let existing: Certificate[] = [];
if (domainRecord.type == "ns" || domainRecord.type == "wildcard") {
const domainLevelDown = domain.split(".").slice(1).join(".");
@@ -32,16 +38,13 @@ export async function createCertificate(
.select()
.from(certificates)
.where(
and(
eq(certificates.domainId, domainId),
or(
eq(certificates.domain, domain),
and(
eq(certificates.wildcard, true),
or(
eq(certificates.domain, domainLevelDown),
eq(certificates.domain, wildcardPrefixed)
)
or(
eq(certificates.domain, domain),
and(
eq(certificates.wildcard, true),
or(
eq(certificates.domain, domainLevelDown),
eq(certificates.domain, wildcardPrefixed)
)
)
)
@@ -51,12 +54,7 @@ export async function createCertificate(
existing = await trx
.select()
.from(certificates)
.where(
and(
eq(certificates.domainId, domainId),
eq(certificates.domain, domain) // exact match for non-NS domains
)
);
.where(eq(certificates.domain, domain)); // exact match for non-NS domains
}
if (existing.length > 0) {
@@ -87,16 +85,22 @@ export async function createCertificate(
}
}
// No cert found, create a new one in pending state
await trx.insert(certificates).values({
domain: domainToWrite,
domainId,
wildcard:
domainRecord.type == "ns" ||
(domainRecord.type == "wildcard" &&
domainRecord.preferWildcardCert), // we can only create wildcard certs for NS domains
status: "pending",
updatedAt: Math.floor(Date.now() / 1000),
createdAt: Math.floor(Date.now() / 1000)
});
// No cert found, create a new one in pending state. onConflictDoNothing
// guards against the domain having been inserted concurrently (or under
// a different domainId) between the existence check above and this
// insert, since certificates.domain is globally unique.
await trx
.insert(certificates)
.values({
domain: domainToWrite,
domainId,
wildcard:
domainRecord.type == "ns" ||
(domainRecord.type == "wildcard" &&
domainRecord.preferWildcardCert), // we can only create wildcard certs for NS domains
status: "pending",
updatedAt: Math.floor(Date.now() / 1000),
createdAt: Math.floor(Date.now() / 1000)
})
.onConflictDoNothing();
}
+38 -3
View File
@@ -1,7 +1,7 @@
import { Request, Response, NextFunction } from "express";
import { z } from "zod";
import { db } from "@server/db";
import { idp, userResources, users } from "@server/db"; // Assuming these are the correct tables
import { idp, resources, userPolicies, userResources, users } from "@server/db"; // Assuming these are the correct tables
import { eq } from "drizzle-orm";
import response from "@server/lib/response";
import HttpCode from "@server/types/HttpCode";
@@ -14,7 +14,23 @@ const listResourceUsersSchema = z.strictObject({
resourceId: z.coerce.number().int().positive()
});
async function queryUsers(resourceId: number) {
async function queryUsers(resourceId: number, policyId: number | null) {
if (policyId !== null) {
return await db
.select({
userId: userPolicies.userId,
username: users.username,
type: users.type,
idpName: idp.name,
idpId: users.idpId,
email: users.email
})
.from(userPolicies)
.innerJoin(users, eq(userPolicies.userId, users.userId))
.leftJoin(idp, eq(users.idpId, idp.idpId))
.where(eq(userPolicies.resourcePolicyId, policyId));
}
return await db
.select({
userId: userResources.userId,
@@ -104,7 +120,26 @@ export async function listResourceUsers(
const { resourceId } = parsedParams.data;
const resourceUsersList = await queryUsers(resourceId);
const [resource] = await db
.select()
.from(resources)
.where(eq(resources.resourceId, resourceId))
.limit(1);
if (!resource) {
return next(
createHttpError(HttpCode.NOT_FOUND, "Resource not found")
);
}
const isInlinePolicy =
resource.resourcePolicyId === null &&
resource.defaultResourcePolicyId !== null;
const resourceUsersList = await queryUsers(
resourceId,
isInlinePolicy ? resource.defaultResourcePolicyId! : null
);
return response<ListResourceUsersResponse>(res, {
data: {
@@ -8,6 +8,8 @@ import ExitNodesTable, {
import SettingsSectionTitle from "@app/components/SettingsSectionTitle";
import { getTranslations } from "next-intl/server";
import type { Metadata } from "next";
import { build } from "@server/build";
import { redirect } from "next/navigation";
export const metadata: Metadata = {
title: "Remote Exit Nodes"
@@ -22,6 +24,10 @@ export const dynamic = "force-dynamic";
export default async function RemoteExitNodesPage(
props: RemoteExitNodesPageProps
) {
if (build != "saas") {
redirect("/");
}
const params = await props.params;
let remoteExitNodes: ListRemoteExitNodesResponse["remoteExitNodes"] = [];
try {
@@ -88,8 +88,8 @@ export default async function ClientResourcesPage(
siteNiceIds: siteResource.siteNiceIds,
niceId: siteResource.niceId,
enabled: siteResource.enabled,
tcpPortRangeString: siteResource.tcpPortRangeString || null,
udpPortRangeString: siteResource.udpPortRangeString || null,
tcpPortRangeString: siteResource.tcpPortRangeString ?? null,
udpPortRangeString: siteResource.udpPortRangeString ?? null,
disableIcmp: siteResource.disableIcmp || false,
authDaemonMode: siteResource.authDaemonMode ?? null,
authDaemonPort: siteResource.authDaemonPort ?? null,
+5 -5
View File
@@ -79,7 +79,7 @@ function MessageBubble({ message }: { message: NormalizedAiMessage }) {
)}
</div>
<div
className={`max-w-[80%] rounded-lg px-3 py-2 text-sm whitespace-pre-wrap break-words ${
className={`min-w-0 max-w-[80%] rounded-lg px-3 py-2 text-sm whitespace-pre-wrap break-words ${
isUser
? "bg-primary text-primary-foreground"
: isTool
@@ -108,7 +108,7 @@ function RawFallbackBlock({
}) {
const pretty = prettyRaw(raw);
return (
<div className="rounded-md border bg-muted/30 p-3">
<div className="min-w-0 rounded-md border bg-muted/30 p-3">
<div className="mb-1 text-xs font-medium text-muted-foreground">
{label}
{pretty && unparsedLabel && (
@@ -117,7 +117,7 @@ function RawFallbackBlock({
</span>
)}
</div>
<pre className="max-h-64 overflow-auto whitespace-pre-wrap break-words text-xs text-muted-foreground">
<pre className="max-h-64 overflow-auto whitespace-pre-wrap break-all text-xs text-muted-foreground">
{pretty ?? noDataLabel}
</pre>
</div>
@@ -172,7 +172,7 @@ export function AiSessionChatView({
</Button>
</div>
{rawMode ? (
<div className="flex max-h-[32rem] flex-col gap-3 overflow-y-auto rounded-md border bg-background p-4">
<div className="flex min-w-0 max-h-[32rem] flex-col gap-3 overflow-y-auto rounded-md border bg-background p-4">
<RawFallbackBlock
label={t("aiSessionRequest")}
raw={normalizedRequest}
@@ -185,7 +185,7 @@ export function AiSessionChatView({
/>
</div>
) : (
<div className="flex max-h-[32rem] flex-col gap-3 overflow-y-auto rounded-md border bg-background p-4">
<div className="flex min-w-0 max-h-[32rem] flex-col gap-3 overflow-y-auto rounded-md border bg-background p-4">
{hasRequestMessages ? (
requestMessages!.map((message, i) => (
<MessageBubble key={`req-${i}`} message={message} />
+29 -1
View File
@@ -57,6 +57,7 @@ export interface Destination {
sendActionLogs: boolean;
sendConnectionLogs: boolean;
sendRequestLogs: boolean;
sendAISessionLogs: boolean;
lastError: string | null;
lastErrorAt: number | null;
createdAt: number;
@@ -180,6 +181,7 @@ export function HttpDestinationCredenza({
const [sendActionLogs, setSendActionLogs] = useState(false);
const [sendConnectionLogs, setSendConnectionLogs] = useState(false);
const [sendRequestLogs, setSendRequestLogs] = useState(false);
const [sendAISessionLogs, setSendAISessionLogs] = useState(false);
useEffect(() => {
if (open) {
@@ -190,6 +192,7 @@ export function HttpDestinationCredenza({
setSendActionLogs(editing?.sendActionLogs ?? false);
setSendConnectionLogs(editing?.sendConnectionLogs ?? false);
setSendRequestLogs(editing?.sendRequestLogs ?? false);
setSendAISessionLogs(editing?.sendAISessionLogs ?? false);
}
}, [open, editing]);
@@ -226,7 +229,8 @@ export function HttpDestinationCredenza({
sendAccessLogs,
sendActionLogs,
sendConnectionLogs,
sendRequestLogs
sendRequestLogs,
sendAISessionLogs
};
if (editing) {
await api.post(
@@ -778,6 +782,30 @@ export function HttpDestinationCredenza({
</p>
</div>
</div>
<div className="flex items-start gap-3 rounded-md border p-3">
<Checkbox
id="log-ai-session"
checked={sendAISessionLogs}
onCheckedChange={(v) =>
setSendAISessionLogs(v === true)
}
className="mt-0.5"
/>
<div>
<label
htmlFor="log-ai-session"
className="text-sm font-medium cursor-pointer"
>
{t("httpDestAISessionLogsTitle")}
</label>
<p className="text-xs text-muted-foreground mt-0.5">
{t(
"httpDestAISessionLogsDescription"
)}
</p>
</div>
</div>
</div>
</div>
</HorizontalTabs>
+16 -3
View File
@@ -313,6 +313,15 @@ export function LogDataTable<TData, TValue>({
}
}, [currentPage, table, isServerPagination]);
// Collapse any expanded rows whenever the page changes, since row ids
// are reused across pages and would otherwise show the wrong content
// in the same expanded position.
const pageIndex = table.getState().pagination.pageIndex;
useEffect(() => {
setExpandedRows(new Set());
// eslint-disable-next-line react-hooks/exhaustive-deps
}, [pageIndex]);
const handleTabChange = (value: string) => {
if (disabled) return;
@@ -515,9 +524,13 @@ export function LogDataTable<TData, TValue>({
}
className="p-4 bg-muted/50"
>
{renderExpandedRow(
row.original
)}
{/* w-0 min-w-full keeps this cell's content from */}
{/* blowing out the table's auto column widths */}
<div className="w-0 min-w-full">
{renderExpandedRow(
row.original
)}
</div>
</TableCell>
</TableRow>
)
+28 -1
View File
@@ -90,6 +90,7 @@ export function S3DestinationCredenza({
const [sendActionLogs, setSendActionLogs] = useState(false);
const [sendConnectionLogs, setSendConnectionLogs] = useState(false);
const [sendRequestLogs, setSendRequestLogs] = useState(false);
const [sendAISessionLogs, setSendAISessionLogs] = useState(false);
useEffect(() => {
if (open) {
@@ -98,6 +99,7 @@ export function S3DestinationCredenza({
setSendActionLogs(editing?.sendActionLogs ?? false);
setSendConnectionLogs(editing?.sendConnectionLogs ?? false);
setSendRequestLogs(editing?.sendRequestLogs ?? false);
setSendAISessionLogs(editing?.sendAISessionLogs ?? false);
}
}, [open, editing]);
@@ -121,7 +123,8 @@ export function S3DestinationCredenza({
sendAccessLogs,
sendActionLogs,
sendConnectionLogs,
sendRequestLogs
sendRequestLogs,
sendAISessionLogs
};
if (editing) {
await api.post(
@@ -510,6 +513,30 @@ export function S3DestinationCredenza({
</p>
</div>
</div>
<div className="flex items-start gap-3 rounded-md border p-3">
<Checkbox
id="s3-log-ai-session"
checked={sendAISessionLogs}
onCheckedChange={(v) =>
setSendAISessionLogs(v === true)
}
className="mt-0.5"
/>
<div>
<Label
htmlFor="s3-log-ai-session"
className="cursor-pointer font-medium"
>
{t("httpDestAISessionLogsTitle")}
</Label>
<p className="text-xs text-muted-foreground mt-0.5">
{t(
"httpDestAISessionLogsDescription"
)}
</p>
</div>
</div>
</div>
</div>
</HorizontalTabs>
@@ -129,6 +129,7 @@ export function ToggleableTrendChart(props: ToggleableTrendChartProps) {
payload?.[0]?.payload?.day
)
}
valueFormatter={valueFormatter}
/>
}
/>
@@ -172,6 +173,7 @@ export function ToggleableTrendChart(props: ToggleableTrendChartProps) {
payload?.[0]?.payload?.day
)
}
valueFormatter={valueFormatter}
/>
}
/>
+2 -1
View File
@@ -47,7 +47,8 @@ export function buildSeriesFromData(
export const currencyFormatter = new Intl.NumberFormat(undefined, {
style: "currency",
currency: "USD",
maximumFractionDigits: 2
minimumFractionDigits: 2,
maximumFractionDigits: 4
});
export const compactNumberFormatter = new Intl.NumberFormat(undefined, {
+16 -10
View File
@@ -135,6 +135,7 @@ type ChartTooltipContentProps = React.ComponentProps<"div"> & {
labelKey?: string;
color?: string;
labelClassName?: string;
valueFormatter?: (value: number) => string;
};
const ChartTooltipContent = React.forwardRef<
@@ -155,7 +156,8 @@ const ChartTooltipContent = React.forwardRef<
formatter,
color,
nameKey,
labelKey
labelKey,
valueFormatter
},
ref
) => {
@@ -302,19 +304,23 @@ const ChartTooltipContent = React.forwardRef<
item.name}
</span>
</div>
{item.value && (
{item.value !== undefined && (
<span className="font-mono font-medium tabular-nums text-foreground">
{!isNaN(
item.value as number
)
? new Intl.NumberFormat(
navigator.language,
{
maximumFractionDigits: 0
}
).format(
item.value as number
)
? valueFormatter
? valueFormatter(
item.value as number
)
: new Intl.NumberFormat(
navigator.language,
{
maximumFractionDigits: 0
}
).format(
item.value as number
)
: item.value.toLocaleString()}
</span>
)}
+2 -2
View File
@@ -43,8 +43,8 @@ export async function fetchSiteResourceByNiceId(
aliasAddress: match.aliasAddress || null,
siteNiceIds: match.siteNiceIds,
niceId: match.niceId,
tcpPortRangeString: match.tcpPortRangeString || null,
udpPortRangeString: match.udpPortRangeString || null,
tcpPortRangeString: match.tcpPortRangeString ?? null,
udpPortRangeString: match.udpPortRangeString ?? null,
disableIcmp: match.disableIcmp || false,
authDaemonMode: match.authDaemonMode ?? null,
authDaemonPort: match.authDaemonPort ?? null,