@cat-factory/app 0.260.1 → 0.261.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (32) hide show
  1. package/app/components/auth/LoginScreen.vue +4 -3
  2. package/app/components/settings/ConnectionTestVerdict.vue +62 -0
  3. package/app/components/settings/InfraHandlersConfigurator.logic.spec.ts +64 -0
  4. package/app/components/settings/InfraHandlersConfigurator.logic.ts +41 -0
  5. package/app/components/settings/InfraHandlersConfigurator.vue +36 -9
  6. package/app/components/settings/KubernetesEngineForm.vue +24 -7
  7. package/app/components/settings/KubernetesEnvironmentForm.vue +20 -7
  8. package/app/components/settings/McpAuthorizeScreen.vue +262 -0
  9. package/app/components/settings/ProviderConnectionTab.vue +3 -7
  10. package/app/components/settings/ProviderManifestEditor.vue +3 -7
  11. package/app/composables/api/mcpAuthorization.ts +30 -0
  12. package/app/composables/useApi.ts +2 -0
  13. package/app/composables/useServiceAccountTokenProblem.ts +52 -0
  14. package/app/pages/mcp-authorize.vue +7 -0
  15. package/app/stores/auth/session.ts +14 -2
  16. package/app/stores/ui/k3sDeepLink.spec.ts +79 -0
  17. package/app/stores/ui/modals.ts +25 -2
  18. package/app/types/providerConnections.ts +9 -0
  19. package/app/utils/connectionFailures.ts +32 -0
  20. package/app/utils/postSignIn.spec.ts +29 -0
  21. package/app/utils/postSignIn.ts +29 -0
  22. package/i18n/locales/de.json +57 -0
  23. package/i18n/locales/en.json +57 -0
  24. package/i18n/locales/es.json +57 -0
  25. package/i18n/locales/fr.json +57 -0
  26. package/i18n/locales/he.json +57 -0
  27. package/i18n/locales/it.json +57 -0
  28. package/i18n/locales/ja.json +57 -0
  29. package/i18n/locales/pl.json +57 -0
  30. package/i18n/locales/tr.json +57 -0
  31. package/i18n/locales/uk.json +57 -0
  32. package/package.json +2 -2
@@ -0,0 +1,29 @@
1
+ import { describe, expect, it } from 'vitest'
2
+ import { postSignInUrl } from './postSignIn'
3
+
4
+ // The regression this exists for: every sign-in path reloaded to `location.pathname`, so a flow
5
+ // whose subject rides the query string lost it the moment a person signed in. The MCP consent
6
+ // screen is the one that fails hardest, and signing in first is the ordinary way a first connect
7
+ // goes, so the loss is on the common path rather than an edge of it.
8
+
9
+ describe('postSignInUrl', () => {
10
+ it('keeps the query string the destination needs', () => {
11
+ expect(postSignInUrl({ pathname: '/mcp-authorize', search: '?request=sealed-value' })).toBe(
12
+ '/mcp-authorize?request=sealed-value',
13
+ )
14
+ })
15
+
16
+ it('drops the invite token, which the signup call already spent', () => {
17
+ // Not a matter of tidiness: a consumed invite left in the address bar is a token in every
18
+ // place a URL gets pasted, and it buys the reader nothing because it no longer works.
19
+ expect(postSignInUrl({ pathname: '/', search: '?invite=tok_1' })).toBe('/')
20
+ expect(postSignInUrl({ pathname: '/', search: '?invite=tok_1&ws=ws_9' })).toBe('/?ws=ws_9')
21
+ })
22
+
23
+ it('answers a bare path unchanged, and drops a fragment', () => {
24
+ expect(postSignInUrl({ pathname: '/', search: '' })).toBe('/')
25
+ // The fragment is absent by construction: it is never read here, so a stale one would only
26
+ // scroll the freshly booted app to an anchor the previous screen owned.
27
+ expect(postSignInUrl({ pathname: '/boards', search: '?a=1' })).toBe('/boards?a=1')
28
+ })
29
+ })
@@ -0,0 +1,29 @@
1
+ /**
2
+ * Where the browser reloads to once a sign-in succeeds.
3
+ *
4
+ * Every sign-in path reloads rather than routing, because the app has to boot with the new session
5
+ * rather than patch itself around it. What it reloads TO is the question this answers, and the
6
+ * naive `location.pathname` gets it wrong: the login screen renders at whatever URL the person
7
+ * arrived at, so the query string belongs to the destination, not to the sign-in. Dropping it
8
+ * silently strands any flow that carries its subject there. The MCP consent screen is the case that
9
+ * bites hardest (`/mcp-authorize?request=<sealed>`): signing in first is the COMMON path for a
10
+ * first connect, and landing back with no `request` leaves a person looking at "this page was
11
+ * opened without an authorization request" with no way forward except restarting from the host.
12
+ *
13
+ * `invite` is the one parameter dropped, and it is dropped because it has already been SPENT: the
14
+ * signup call consumed it, so keeping it would leave a consumed token in the address bar and in
15
+ * every place a URL gets pasted. Everything else is the destination's business, not this module's,
16
+ * which is why the rule is a named exception rather than an allowlist nobody remembers to extend.
17
+ */
18
+ const SPENT_PARAMS = ['invite']
19
+
20
+ /**
21
+ * The post-sign-in URL for one location: its path, its query minus the spent parameters, and no
22
+ * fragment (nothing in this app puts state there, and a stale one would scroll to nowhere).
23
+ */
24
+ export function postSignInUrl(location: { pathname: string; search: string }): string {
25
+ const params = new URLSearchParams(location.search)
26
+ for (const spent of SPENT_PARAMS) params.delete(spent)
27
+ const query = params.toString()
28
+ return query ? `${location.pathname}?${query}` : location.pathname
29
+ }
@@ -1,4 +1,43 @@
1
1
  {
2
+ "mcpAuthorize": {
3
+ "title": "{client} verbinden?",
4
+ "subtitle": "Die Anwendung gibt an, {client} zu sein, und diese Installation leitet sie zurück an {origin}.",
5
+ "workspace": {
6
+ "label": "Board, auf dem sie handeln darf"
7
+ },
8
+ "scopeLabel": "Was sie tun darf",
9
+ "scopeHint": "Jede Stufe schließt die darüberliegenden ein.",
10
+ "scope": {
11
+ "read": {
12
+ "label": "Nur lesen",
13
+ "description": "Services, Aufgaben, Pipelines und Läufe ansehen."
14
+ },
15
+ "write": {
16
+ "label": "Lesen und schreiben",
17
+ "description": "Zusätzlich Aufgaben anlegen und starten."
18
+ },
19
+ "decide": {
20
+ "label": "Lesen, schreiben und entscheiden",
21
+ "description": "Zusätzlich die Fragen beantworten, auf die ein pausierter Lauf wartet."
22
+ },
23
+ "admin": {
24
+ "label": "Voller Zugriff",
25
+ "description": "Zusätzlich Aufgaben löschen und auf Benachrichtigungen reagieren, was einen Pull Request zusammenführen kann."
26
+ }
27
+ },
28
+ "requestedScope": "{client} hat {scope} angefragt. Wählen Sie das oben nur, wenn Sie es wirklich gewähren möchten.",
29
+ "approve": "Verbinden",
30
+ "deny": "Abbrechen",
31
+ "back": "Zurück zur App",
32
+ "noWorkspaces": "Sie haben noch kein Board, mit dem sich das verbinden ließe.",
33
+ "revokeHint": "Dabei wird ein API-Schlüssel ausgestellt, den Sie jederzeit in den Board-Einstellungen widerrufen können.",
34
+ "error": {
35
+ "title": "Diese Verbindung konnte nicht eingerichtet werden",
36
+ "noRequest": "Diese Seite wurde ohne Autorisierungsanfrage geöffnet. Starten Sie die Verbindung in Ihrem MCP-Host.",
37
+ "expired": "Diese Autorisierungsanfrage ist ungültig oder abgelaufen. Starten Sie die Verbindung in Ihrem MCP-Host erneut.",
38
+ "failed": "Die Entscheidung konnte nicht gespeichert werden. Starten Sie die Verbindung in Ihrem MCP-Host erneut."
39
+ }
40
+ },
2
41
  "settings": {
3
42
  "modelConfiguration": {
4
43
  "title": "Modellkonfiguration",
@@ -239,6 +278,11 @@
239
278
  "blurb": "Wo die Coding-Agenten laufen, wenn keine Cloudflare Containers verwendet werden. Wähle einen selbst gehosteten Runner-Pool (deinen eigenen Scheduler) oder einen Kubernetes-Cluster und konfiguriere dann dessen Endpunkt und Zugangsdaten."
240
279
  }
241
280
  },
281
+ "serviceAccountToken": {
282
+ "whitespace": "Dieses Token enthält ein Leerzeichen oder einen Zeilenumbruch, was bei einem Bearer-Token nie vorkommt. Vermutlich wurde es über einen Zeilenumbruch im Terminal hinweg kopiert. Kopieren Sie es erneut als eine einzige ununterbrochene Zeile.",
283
+ "base64Encoded": "Das sieht nach dem Base64-Wert aus dem Feld .data.token des Secrets aus, nicht nach dem Token selbst. Dekodieren Sie ihn zuerst, zum Beispiel mit base64 -d.",
284
+ "notAJwt": "Das sieht nicht nach einem ServiceAccount-Token aus, das ein JWT aus drei durch Punkte getrennten Teilen ist. Prüfen Sie, ob der gesamte Wert kopiert wurde. Ignorieren Sie diesen Hinweis, wenn Ihr Cluster statische Bearer-Token verwendet."
285
+ },
242
286
  "kubernetesEnv": {
243
287
  "label": "Name",
244
288
  "labelPlaceholder": "Preview-Cluster",
@@ -325,6 +369,19 @@
325
369
  "button": "Verbindung testen",
326
370
  "ok": "Verbindung OK",
327
371
  "failed": "Verbindung fehlgeschlagen",
372
+ "causes": {
373
+ "refused": "An dieser Adresse wartet nichts: Die Verbindung wurde abgelehnt.",
374
+ "dns": "Dieser Hostname lässt sich von dieser Installation aus nicht auflösen.",
375
+ "timeout": "Es kam keine Antwort, bevor die Prüfung abgelaufen ist.",
376
+ "aborted": "Die Anfrage wurde abgebrochen, bevor eine Antwort ankam.",
377
+ "unreachable": "Von dieser Installation aus gibt es keine Netzwerkroute zu dieser Adresse.",
378
+ "reset": "Die Verbindung wurde geschlossen, bevor eine Antwort ankam.",
379
+ "tlsUntrusted": "Diese Installation vertraut dem TLS-Zertifikat nicht.",
380
+ "tlsExpired": "Das TLS-Zertifikat liegt außerhalb seines Gültigkeitszeitraums.",
381
+ "tlsHostname": "Das TLS-Zertifikat wurde nicht für diesen Hostnamen ausgestellt.",
382
+ "tlsProtocol": "Der TLS-Handshake ist fehlgeschlagen.",
383
+ "invalidHeader": "Die Anfrage ließ sich nicht erstellen: Ein Zugangsdaten-Wert enthält ein Zeichen, das ein HTTP-Header nicht übertragen kann."
384
+ },
328
385
  "warningsTitle": "Lücken in dieser Konfiguration",
329
386
  "warnings": {
330
387
  "runner_manifest_no_release": "Kein Release-Template: Beim Abbrechen eines Laufs kann dem Pool nicht mitgeteilt werden, dass er seinen Job stoppen soll. Ein verwaister Job belegt seinen Runner, bis der Pool ihn von selbst zurücknimmt.",
@@ -2682,6 +2682,45 @@
2682
2682
  }
2683
2683
  }
2684
2684
  },
2685
+ "mcpAuthorize": {
2686
+ "title": "Connect {client}?",
2687
+ "subtitle": "It says it is {client}, and this deployment will send it back to {origin}.",
2688
+ "workspace": {
2689
+ "label": "Board it may act on"
2690
+ },
2691
+ "scopeLabel": "What it may do",
2692
+ "scopeHint": "Each level includes the ones above it.",
2693
+ "scope": {
2694
+ "read": {
2695
+ "label": "Read only",
2696
+ "description": "See services, tasks, pipelines and runs."
2697
+ },
2698
+ "write": {
2699
+ "label": "Read and write",
2700
+ "description": "Also create and start tasks."
2701
+ },
2702
+ "decide": {
2703
+ "label": "Read, write and decide",
2704
+ "description": "Also answer the questions a parked run is waiting on."
2705
+ },
2706
+ "admin": {
2707
+ "label": "Full access",
2708
+ "description": "Also delete tasks and act on notifications, which can merge a pull request."
2709
+ }
2710
+ },
2711
+ "requestedScope": "{client} asked for {scope}. Choose it above only if you mean to grant that.",
2712
+ "approve": "Connect",
2713
+ "deny": "Cancel",
2714
+ "back": "Back to the app",
2715
+ "noWorkspaces": "You have no boards to connect this to yet.",
2716
+ "revokeHint": "This issues an API key you can revoke at any time from the board's settings.",
2717
+ "error": {
2718
+ "title": "This connection could not be set up",
2719
+ "noRequest": "This page was opened without an authorization request. Start the connection from your MCP host.",
2720
+ "expired": "This authorization request is invalid or has expired. Start the connection again from your MCP host.",
2721
+ "failed": "The decision could not be recorded. Start the connection again from your MCP host."
2722
+ }
2723
+ },
2685
2724
  "settings": {
2686
2725
  "modelConfiguration": {
2687
2726
  "title": "Model Configuration",
@@ -2922,6 +2961,11 @@
2922
2961
  "blurb": "Where the coding agents run when not using Cloudflare Containers. Choose a self-hosted runner pool (your own scheduler) or a Kubernetes cluster, then configure its endpoint and credentials."
2923
2962
  }
2924
2963
  },
2964
+ "serviceAccountToken": {
2965
+ "whitespace": "This token contains a space or line break, which a bearer token never has. It was most likely copied across a wrapped line in your terminal. Re-copy it as a single unbroken line.",
2966
+ "base64Encoded": "This looks like the base64 value from the Secret's .data.token field rather than the token itself. Decode it first, for example with base64 -d.",
2967
+ "notAJwt": "This does not look like a ServiceAccount token, which is a JWT of three dot-separated parts. Check that the whole value was copied. Ignore this if your cluster uses static bearer tokens."
2968
+ },
2925
2969
  "kubernetesEnv": {
2926
2970
  "label": "Name",
2927
2971
  "labelPlaceholder": "Preview cluster",
@@ -3011,6 +3055,19 @@
3011
3055
  "button": "Test connection",
3012
3056
  "ok": "Connection OK",
3013
3057
  "failed": "Connection failed",
3058
+ "causes": {
3059
+ "refused": "Nothing is listening at that address: the connection was refused.",
3060
+ "dns": "That host name does not resolve from this deployment.",
3061
+ "timeout": "No answer arrived before the test timed out.",
3062
+ "aborted": "The request was cancelled before an answer arrived.",
3063
+ "unreachable": "There is no network route to that address from this deployment.",
3064
+ "reset": "The connection was closed before an answer arrived.",
3065
+ "tlsUntrusted": "This deployment does not trust the TLS certificate.",
3066
+ "tlsExpired": "The TLS certificate is outside its validity window.",
3067
+ "tlsHostname": "The TLS certificate was not issued for that host name.",
3068
+ "tlsProtocol": "The TLS handshake failed.",
3069
+ "invalidHeader": "The request could not be built: a credential holds a character an HTTP header cannot carry."
3070
+ },
3014
3071
  "warningsTitle": "Gaps in this configuration",
3015
3072
  "warnings": {
3016
3073
  "runner_manifest_no_release": "No release template: cancelling a run cannot tell the pool to stop its job, so an orphaned job keeps its runner until the pool reclaims it on its own.",
@@ -2575,6 +2575,45 @@
2575
2575
  }
2576
2576
  }
2577
2577
  },
2578
+ "mcpAuthorize": {
2579
+ "title": "¿Conectar {client}?",
2580
+ "subtitle": "Dice ser {client}, y esta instalación lo devolverá a {origin}.",
2581
+ "workspace": {
2582
+ "label": "Tablero en el que podrá actuar"
2583
+ },
2584
+ "scopeLabel": "Lo que podrá hacer",
2585
+ "scopeHint": "Cada nivel incluye los anteriores.",
2586
+ "scope": {
2587
+ "read": {
2588
+ "label": "Solo lectura",
2589
+ "description": "Ver servicios, tareas, pipelines y ejecuciones."
2590
+ },
2591
+ "write": {
2592
+ "label": "Lectura y escritura",
2593
+ "description": "Además, crear e iniciar tareas."
2594
+ },
2595
+ "decide": {
2596
+ "label": "Lectura, escritura y decisión",
2597
+ "description": "Además, responder a las preguntas que espera una ejecución detenida."
2598
+ },
2599
+ "admin": {
2600
+ "label": "Acceso completo",
2601
+ "description": "Además, eliminar tareas y actuar sobre notificaciones, lo que puede fusionar un pull request."
2602
+ }
2603
+ },
2604
+ "requestedScope": "{client} solicitó {scope}. Elige esa opción arriba solo si de verdad quieres concederla.",
2605
+ "approve": "Conectar",
2606
+ "deny": "Cancelar",
2607
+ "back": "Volver a la aplicación",
2608
+ "noWorkspaces": "Todavía no tienes ningún tablero al que conectarlo.",
2609
+ "revokeHint": "Esto emite una clave de API que puedes revocar cuando quieras desde los ajustes del tablero.",
2610
+ "error": {
2611
+ "title": "No se pudo establecer esta conexión",
2612
+ "noRequest": "Esta página se abrió sin una solicitud de autorización. Inicia la conexión desde tu host MCP.",
2613
+ "expired": "Esta solicitud de autorización no es válida o ha caducado. Vuelve a iniciar la conexión desde tu host MCP.",
2614
+ "failed": "No se pudo registrar la decisión. Vuelve a iniciar la conexión desde tu host MCP."
2615
+ }
2616
+ },
2578
2617
  "settings": {
2579
2618
  "modelConfiguration": {
2580
2619
  "title": "Configuración de modelos",
@@ -2705,6 +2744,19 @@
2705
2744
  "button": "Probar conexión",
2706
2745
  "ok": "Conexión correcta",
2707
2746
  "failed": "Falló la conexión",
2747
+ "causes": {
2748
+ "refused": "No hay nada escuchando en esa dirección: la conexión fue rechazada.",
2749
+ "dns": "Ese nombre de host no se resuelve desde esta instalación.",
2750
+ "timeout": "No llegó ninguna respuesta antes de que la prueba agotara su tiempo.",
2751
+ "aborted": "La solicitud se canceló antes de que llegara una respuesta.",
2752
+ "unreachable": "No hay ruta de red hacia esa dirección desde esta instalación.",
2753
+ "reset": "La conexión se cerró antes de que llegara una respuesta.",
2754
+ "tlsUntrusted": "Esta instalación no confía en el certificado TLS.",
2755
+ "tlsExpired": "El certificado TLS está fuera de su periodo de validez.",
2756
+ "tlsHostname": "El certificado TLS no se emitió para ese nombre de host.",
2757
+ "tlsProtocol": "El protocolo de enlace TLS falló.",
2758
+ "invalidHeader": "No se pudo construir la solicitud: una credencial contiene un carácter que una cabecera HTTP no puede transportar."
2759
+ },
2708
2760
  "warningsTitle": "Carencias en esta configuración",
2709
2761
  "warnings": {
2710
2762
  "runner_manifest_no_release": "Sin plantilla de release: al cancelar una ejecución no se puede indicar al pool que detenga su trabajo, así que un trabajo huérfano ocupa su runner hasta que el pool lo recupere por su cuenta.",
@@ -2720,6 +2772,11 @@
2720
2772
  "removed": "Conexión eliminada",
2721
2773
  "removeFailed": "No se pudo eliminar la conexión"
2722
2774
  },
2775
+ "serviceAccountToken": {
2776
+ "whitespace": "Este token contiene un espacio o un salto de línea, algo que nunca ocurre en un token de portador. Lo más probable es que se haya copiado a través de una línea ajustada en la terminal. Vuelve a copiarlo como una única línea continua.",
2777
+ "base64Encoded": "Esto parece el valor en base64 del campo .data.token del Secret, no el token en sí. Descodifícalo primero, por ejemplo con base64 -d.",
2778
+ "notAJwt": "Esto no parece un token de ServiceAccount, que es un JWT de tres partes separadas por puntos. Comprueba que has copiado el valor completo. Ignora este aviso si tu clúster usa tokens de portador estáticos."
2779
+ },
2723
2780
  "kubernetesEnv": {
2724
2781
  "label": "Nombre",
2725
2782
  "labelPlaceholder": "Clúster de vista previa",
@@ -2575,6 +2575,45 @@
2575
2575
  }
2576
2576
  }
2577
2577
  },
2578
+ "mcpAuthorize": {
2579
+ "title": "Connecter {client} ?",
2580
+ "subtitle": "Il se présente comme {client}, et ce déploiement le renverra vers {origin}.",
2581
+ "workspace": {
2582
+ "label": "Tableau sur lequel il pourra agir"
2583
+ },
2584
+ "scopeLabel": "Ce qu'il pourra faire",
2585
+ "scopeHint": "Chaque niveau inclut les précédents.",
2586
+ "scope": {
2587
+ "read": {
2588
+ "label": "Lecture seule",
2589
+ "description": "Voir les services, les tâches, les pipelines et les exécutions."
2590
+ },
2591
+ "write": {
2592
+ "label": "Lecture et écriture",
2593
+ "description": "Et aussi créer et lancer des tâches."
2594
+ },
2595
+ "decide": {
2596
+ "label": "Lecture, écriture et décision",
2597
+ "description": "Et aussi répondre aux questions qu'attend une exécution en pause."
2598
+ },
2599
+ "admin": {
2600
+ "label": "Accès complet",
2601
+ "description": "Et aussi supprimer des tâches et agir sur les notifications, ce qui peut fusionner une pull request."
2602
+ }
2603
+ },
2604
+ "requestedScope": "{client} a demandé {scope}. Ne choisissez cette option ci-dessus que si vous voulez vraiment l'accorder.",
2605
+ "approve": "Connecter",
2606
+ "deny": "Annuler",
2607
+ "back": "Retour à l'application",
2608
+ "noWorkspaces": "Vous n'avez encore aucun tableau auquel le connecter.",
2609
+ "revokeHint": "Cela émet une clé d'API que vous pouvez révoquer à tout moment depuis les réglages du tableau.",
2610
+ "error": {
2611
+ "title": "Cette connexion n'a pas pu être établie",
2612
+ "noRequest": "Cette page a été ouverte sans demande d'autorisation. Lancez la connexion depuis votre hôte MCP.",
2613
+ "expired": "Cette demande d'autorisation est invalide ou a expiré. Relancez la connexion depuis votre hôte MCP.",
2614
+ "failed": "La décision n'a pas pu être enregistrée. Relancez la connexion depuis votre hôte MCP."
2615
+ }
2616
+ },
2578
2617
  "settings": {
2579
2618
  "modelConfiguration": {
2580
2619
  "title": "Configuration des modèles",
@@ -2705,6 +2744,19 @@
2705
2744
  "button": "Tester la connexion",
2706
2745
  "ok": "Connexion réussie",
2707
2746
  "failed": "Échec de la connexion",
2747
+ "causes": {
2748
+ "refused": "Rien n'écoute à cette adresse : la connexion a été refusée.",
2749
+ "dns": "Ce nom d'hôte n'est pas résolu depuis ce déploiement.",
2750
+ "timeout": "Aucune réponse n'est arrivée avant l'expiration du test.",
2751
+ "aborted": "La requête a été annulée avant l'arrivée d'une réponse.",
2752
+ "unreachable": "Aucune route réseau ne mène à cette adresse depuis ce déploiement.",
2753
+ "reset": "La connexion a été fermée avant l'arrivée d'une réponse.",
2754
+ "tlsUntrusted": "Ce déploiement ne fait pas confiance au certificat TLS.",
2755
+ "tlsExpired": "Le certificat TLS est en dehors de sa période de validité.",
2756
+ "tlsHostname": "Le certificat TLS n'a pas été émis pour ce nom d'hôte.",
2757
+ "tlsProtocol": "La négociation TLS a échoué.",
2758
+ "invalidHeader": "La requête n'a pas pu être construite : un identifiant contient un caractère qu'un en-tête HTTP ne peut pas transporter."
2759
+ },
2708
2760
  "warningsTitle": "Lacunes dans cette configuration",
2709
2761
  "warnings": {
2710
2762
  "runner_manifest_no_release": "Aucun modèle de release : annuler une exécution ne permet pas de demander au pool d'arrêter son job, donc un job orphelin occupe son runner jusqu'à ce que le pool le récupère de lui-même.",
@@ -2720,6 +2772,11 @@
2720
2772
  "removed": "Connexion supprimée",
2721
2773
  "removeFailed": "Impossible de supprimer la connexion"
2722
2774
  },
2775
+ "serviceAccountToken": {
2776
+ "whitespace": "Ce jeton contient une espace ou un saut de ligne, ce qu'un jeton porteur ne contient jamais. Il a probablement été copié à cheval sur un retour à la ligne du terminal. Recopiez-le sur une seule ligne ininterrompue.",
2777
+ "base64Encoded": "Ceci ressemble à la valeur base64 du champ .data.token du Secret, et non au jeton lui-même. Décodez-la d'abord, par exemple avec base64 -d.",
2778
+ "notAJwt": "Ceci ne ressemble pas à un jeton de ServiceAccount, qui est un JWT composé de trois parties séparées par des points. Vérifiez que la valeur a été copiée en entier. Ignorez cet avertissement si votre cluster utilise des jetons porteurs statiques."
2779
+ },
2723
2780
  "kubernetesEnv": {
2724
2781
  "label": "Nom",
2725
2782
  "labelPlaceholder": "Cluster de prévisualisation",
@@ -2575,6 +2575,45 @@
2575
2575
  }
2576
2576
  }
2577
2577
  },
2578
+ "mcpAuthorize": {
2579
+ "title": "לחבר את {client}?",
2580
+ "subtitle": "הוא מציג את עצמו כ־{client}, והפריסה הזו תחזיר אותו אל {origin}.",
2581
+ "workspace": {
2582
+ "label": "הלוח שבו יורשה לפעול"
2583
+ },
2584
+ "scopeLabel": "מה יורשה לעשות",
2585
+ "scopeHint": "כל רמה כוללת את הרמות שמעליה.",
2586
+ "scope": {
2587
+ "read": {
2588
+ "label": "קריאה בלבד",
2589
+ "description": "לראות שירותים, משימות, פייפליינים והרצות."
2590
+ },
2591
+ "write": {
2592
+ "label": "קריאה וכתיבה",
2593
+ "description": "וגם ליצור משימות ולהפעיל אותן."
2594
+ },
2595
+ "decide": {
2596
+ "label": "קריאה, כתיבה והכרעה",
2597
+ "description": "וגם לענות על השאלות שהרצה ממתינה להן."
2598
+ },
2599
+ "admin": {
2600
+ "label": "גישה מלאה",
2601
+ "description": "וגם למחוק משימות ולפעול על התראות, מה שעשוי למזג בקשת משיכה."
2602
+ }
2603
+ },
2604
+ "requestedScope": "{client} ביקש {scope}. בחרו באפשרות הזו למעלה רק אם אתם באמת מתכוונים להעניק אותה.",
2605
+ "approve": "חיבור",
2606
+ "deny": "ביטול",
2607
+ "back": "חזרה לאפליקציה",
2608
+ "noWorkspaces": "אין לך עדיין לוח שאפשר לחבר אליו.",
2609
+ "revokeHint": "פעולה זו מנפיקה מפתח API שאפשר לבטל בכל עת מהגדרות הלוח.",
2610
+ "error": {
2611
+ "title": "לא ניתן היה להקים את החיבור",
2612
+ "noRequest": "הדף נפתח ללא בקשת הרשאה. התחילו את החיבור מתוך מארח ה־MCP שלכם.",
2613
+ "expired": "בקשת ההרשאה אינה תקפה או שפג תוקפה. התחילו את החיבור שוב מתוך מארח ה־MCP שלכם.",
2614
+ "failed": "לא ניתן היה לרשום את ההחלטה. התחילו את החיבור שוב מתוך מארח ה־MCP שלכם."
2615
+ }
2616
+ },
2578
2617
  "settings": {
2579
2618
  "modelConfiguration": {
2580
2619
  "title": "הגדרת מודלים",
@@ -2815,6 +2854,11 @@
2815
2854
  "blurb": "היכן סוכני הקוד רצים כשלא משתמשים ב-Cloudflare Containers. בחר מאגר מריצים בניהול עצמי (מתזמן משלך) או אשכול Kubernetes, ואז הגדר את נקודת הקצה והאישורים שלו."
2816
2855
  }
2817
2856
  },
2857
+ "serviceAccountToken": {
2858
+ "whitespace": "האסימון הזה מכיל רווח או שבירת שורה, דבר שלא קיים באסימון נושא. סביר להניח שהוא הועתק תוך חציית שורה שנשברה במסוף. העתיקו אותו מחדש כשורה אחת רציפה.",
2859
+ "base64Encoded": "זה נראה כמו הערך בבסיס 64 מהשדה .data.token של ה-Secret, ולא כמו האסימון עצמו. פענחו אותו קודם, למשל באמצעות base64 -d.",
2860
+ "notAJwt": "זה לא נראה כמו אסימון ServiceAccount, שהוא JWT בן שלושה חלקים המופרדים בנקודות. ודאו שהערך הועתק במלואו. התעלמו מההודעה אם האשכול שלכם משתמש באסימוני נושא סטטיים."
2861
+ },
2818
2862
  "kubernetesEnv": {
2819
2863
  "label": "שם",
2820
2864
  "labelPlaceholder": "אשכול תצוגה מקדימה",
@@ -2901,6 +2945,19 @@
2901
2945
  "button": "בדוק חיבור",
2902
2946
  "ok": "החיבור תקין",
2903
2947
  "failed": "החיבור נכשל",
2948
+ "causes": {
2949
+ "refused": "אין דבר שמאזין בכתובת הזו: החיבור נדחה.",
2950
+ "dns": "שם המחשב המארח הזה אינו נפתר מהפריסה הזו.",
2951
+ "timeout": "לא הגיעה תשובה לפני שתם הזמן שהוקצב לבדיקה.",
2952
+ "aborted": "הבקשה בוטלה לפני שהגיעה תשובה.",
2953
+ "unreachable": "אין נתיב רשת לכתובת הזו מהפריסה הזו.",
2954
+ "reset": "החיבור נסגר לפני שהגיעה תשובה.",
2955
+ "tlsUntrusted": "הפריסה הזו אינה סומכת על אישור ה-TLS.",
2956
+ "tlsExpired": "אישור ה-TLS נמצא מחוץ לתקופת התוקף שלו.",
2957
+ "tlsHostname": "אישור ה-TLS לא הונפק עבור שם המחשב המארח הזה.",
2958
+ "tlsProtocol": "לחיצת היד של TLS נכשלה.",
2959
+ "invalidHeader": "לא ניתן היה לבנות את הבקשה: פרטי גישה מכילים תו שכותרת HTTP אינה יכולה לשאת."
2960
+ },
2904
2961
  "warningsTitle": "פערים בתצורה הזו",
2905
2962
  "warnings": {
2906
2963
  "runner_manifest_no_release": "אין תבנית שחרור: ביטול הרצה לא יכול להודיע למאגר להפסיק את המשימה שלו, ולכן משימה יתומה תופסת את הראנר שלה עד שהמאגר משחרר אותה בעצמו.",
@@ -1,4 +1,43 @@
1
1
  {
2
+ "mcpAuthorize": {
3
+ "title": "Collegare {client}?",
4
+ "subtitle": "Dichiara di essere {client}, e questa installazione lo rimanderà a {origin}.",
5
+ "workspace": {
6
+ "label": "Bacheca su cui potrà agire"
7
+ },
8
+ "scopeLabel": "Cosa potrà fare",
9
+ "scopeHint": "Ogni livello include quelli precedenti.",
10
+ "scope": {
11
+ "read": {
12
+ "label": "Sola lettura",
13
+ "description": "Vedere servizi, attività, pipeline ed esecuzioni."
14
+ },
15
+ "write": {
16
+ "label": "Lettura e scrittura",
17
+ "description": "Inoltre creare e avviare attività."
18
+ },
19
+ "decide": {
20
+ "label": "Lettura, scrittura e decisione",
21
+ "description": "Inoltre rispondere alle domande su cui un'esecuzione è in attesa."
22
+ },
23
+ "admin": {
24
+ "label": "Accesso completo",
25
+ "description": "Inoltre eliminare attività e agire sulle notifiche, il che può unire una pull request."
26
+ }
27
+ },
28
+ "requestedScope": "{client} ha richiesto {scope}. Seleziona quell'opzione qui sopra solo se intendi davvero concederla.",
29
+ "approve": "Collega",
30
+ "deny": "Annulla",
31
+ "back": "Torna all'app",
32
+ "noWorkspaces": "Non hai ancora una bacheca a cui collegarlo.",
33
+ "revokeHint": "Questo emette una chiave API che puoi revocare in qualsiasi momento dalle impostazioni della bacheca.",
34
+ "error": {
35
+ "title": "Non è stato possibile creare questo collegamento",
36
+ "noRequest": "Questa pagina è stata aperta senza una richiesta di autorizzazione. Avvia il collegamento dal tuo host MCP.",
37
+ "expired": "Questa richiesta di autorizzazione non è valida o è scaduta. Riavvia il collegamento dal tuo host MCP.",
38
+ "failed": "Non è stato possibile registrare la decisione. Riavvia il collegamento dal tuo host MCP."
39
+ }
40
+ },
2
41
  "settings": {
3
42
  "modelConfiguration": {
4
43
  "title": "Configurazione del modello",
@@ -239,6 +278,11 @@
239
278
  "blurb": "Dove vengono eseguiti gli agenti di coding quando non si usano i Cloudflare Containers. Scegli un pool di runner self-hosted (il tuo scheduler) o un cluster Kubernetes, poi configura il suo endpoint e le sue credenziali."
240
279
  }
241
280
  },
281
+ "serviceAccountToken": {
282
+ "whitespace": "Questo token contiene uno spazio o un'interruzione di riga, cosa che un token bearer non ha mai. Probabilmente è stato copiato a cavallo di una riga mandata a capo nel terminale. Ricopialo come un'unica riga ininterrotta.",
283
+ "base64Encoded": "Sembra il valore base64 del campo .data.token del Secret, non il token vero e proprio. Decodificalo prima, ad esempio con base64 -d.",
284
+ "notAJwt": "Non sembra un token di ServiceAccount, che è un JWT composto da tre parti separate da punti. Verifica di aver copiato il valore completo. Ignora questo avviso se il tuo cluster usa token bearer statici."
285
+ },
242
286
  "kubernetesEnv": {
243
287
  "label": "Nome",
244
288
  "labelPlaceholder": "Cluster di anteprima",
@@ -325,6 +369,19 @@
325
369
  "button": "Testa la connessione",
326
370
  "ok": "Connessione OK",
327
371
  "failed": "Connessione fallita",
372
+ "causes": {
373
+ "refused": "Nessuno è in ascolto a quell'indirizzo: la connessione è stata rifiutata.",
374
+ "dns": "Quel nome host non viene risolto da questa installazione.",
375
+ "timeout": "Nessuna risposta è arrivata prima della scadenza del test.",
376
+ "aborted": "La richiesta è stata annullata prima che arrivasse una risposta.",
377
+ "unreachable": "Non esiste una rotta di rete verso quell'indirizzo da questa installazione.",
378
+ "reset": "La connessione è stata chiusa prima che arrivasse una risposta.",
379
+ "tlsUntrusted": "Questa installazione non considera attendibile il certificato TLS.",
380
+ "tlsExpired": "Il certificato TLS è fuori dal suo periodo di validità.",
381
+ "tlsHostname": "Il certificato TLS non è stato emesso per quel nome host.",
382
+ "tlsProtocol": "L'handshake TLS è fallito.",
383
+ "invalidHeader": "Non è stato possibile costruire la richiesta: una credenziale contiene un carattere che un header HTTP non può trasportare."
384
+ },
328
385
  "warningsTitle": "Lacune in questa configurazione",
329
386
  "warnings": {
330
387
  "runner_manifest_no_release": "Nessun template di release: annullare un'esecuzione non può dire al pool di fermare il suo job, quindi un job orfano tiene occupato il suo runner finché il pool non lo recupera da solo.",
@@ -2575,6 +2575,45 @@
2575
2575
  }
2576
2576
  }
2577
2577
  },
2578
+ "mcpAuthorize": {
2579
+ "title": "{client} を接続しますか?",
2580
+ "subtitle": "{client} を名乗っており、このデプロイは接続後に {origin} へ戻します。",
2581
+ "workspace": {
2582
+ "label": "操作を許可するボード"
2583
+ },
2584
+ "scopeLabel": "許可する操作",
2585
+ "scopeHint": "各レベルは上位のレベルを含みます。",
2586
+ "scope": {
2587
+ "read": {
2588
+ "label": "読み取りのみ",
2589
+ "description": "サービス、タスク、パイプライン、実行を閲覧します。"
2590
+ },
2591
+ "write": {
2592
+ "label": "読み取りと書き込み",
2593
+ "description": "加えて、タスクの作成と開始ができます。"
2594
+ },
2595
+ "decide": {
2596
+ "label": "読み取り、書き込み、判断",
2597
+ "description": "加えて、停止中の実行が待っている質問に回答できます。"
2598
+ },
2599
+ "admin": {
2600
+ "label": "フルアクセス",
2601
+ "description": "加えて、タスクの削除と通知への対応ができ、プルリクエストがマージされることもあります。"
2602
+ }
2603
+ },
2604
+ "requestedScope": "{client} は {scope} を要求しました。本当に許可する場合のみ、上でその項目を選んでください。",
2605
+ "approve": "接続",
2606
+ "deny": "キャンセル",
2607
+ "back": "アプリに戻る",
2608
+ "noWorkspaces": "接続できるボードがまだありません。",
2609
+ "revokeHint": "これにより API キーが発行されます。ボードの設定からいつでも無効化できます。",
2610
+ "error": {
2611
+ "title": "この接続を設定できませんでした",
2612
+ "noRequest": "認可リクエストなしでこのページが開かれました。MCP ホストから接続を開始してください。",
2613
+ "expired": "この認可リクエストは無効か、有効期限が切れています。MCP ホストから接続をやり直してください。",
2614
+ "failed": "判断を記録できませんでした。MCP ホストから接続をやり直してください。"
2615
+ }
2616
+ },
2578
2617
  "settings": {
2579
2618
  "modelConfiguration": {
2580
2619
  "title": "モデル設定",
@@ -2815,6 +2854,11 @@
2815
2854
  "blurb": "Cloudflare Containers を使用しない場合にコーディングエージェントが実行される場所。セルフホストのランナープール (自前のスケジューラー) または Kubernetes クラスターを選択し、エンドポイントと認証情報を構成します。"
2816
2855
  }
2817
2856
  },
2857
+ "serviceAccountToken": {
2858
+ "whitespace": "このトークンにはスペースまたは改行が含まれています。ベアラートークンには本来含まれないもので、ターミナルで折り返された行をまたいでコピーした可能性が高いです。改行のない 1 行としてコピーし直してください。",
2859
+ "base64Encoded": "これはトークン自体ではなく、Secret の .data.token フィールドの Base64 値のように見えます。先に base64 -d などでデコードしてください。",
2860
+ "notAJwt": "これは ServiceAccount トークン (ピリオドで区切られた 3 つの部分から成る JWT) には見えません。値全体をコピーしたか確認してください。クラスターが静的なベアラートークンを使用している場合は無視して構いません。"
2861
+ },
2818
2862
  "kubernetesEnv": {
2819
2863
  "label": "名前",
2820
2864
  "labelPlaceholder": "プレビュークラスター",
@@ -2901,6 +2945,19 @@
2901
2945
  "button": "接続をテスト",
2902
2946
  "ok": "接続 OK",
2903
2947
  "failed": "接続に失敗しました",
2948
+ "causes": {
2949
+ "refused": "そのアドレスでは何も待ち受けていません。接続が拒否されました。",
2950
+ "dns": "そのホスト名はこのデプロイからは解決できません。",
2951
+ "timeout": "テストがタイムアウトするまでに応答がありませんでした。",
2952
+ "aborted": "応答が届く前にリクエストがキャンセルされました。",
2953
+ "unreachable": "このデプロイからそのアドレスへのネットワーク経路がありません。",
2954
+ "reset": "応答が届く前に接続が閉じられました。",
2955
+ "tlsUntrusted": "このデプロイは TLS 証明書を信頼していません。",
2956
+ "tlsExpired": "TLS 証明書は有効期間を外れています。",
2957
+ "tlsHostname": "TLS 証明書はそのホスト名向けに発行されていません。",
2958
+ "tlsProtocol": "TLS ハンドシェイクに失敗しました。",
2959
+ "invalidHeader": "リクエストを組み立てられませんでした。認証情報に HTTP ヘッダーが扱えない文字が含まれています。"
2960
+ },
2904
2961
  "warningsTitle": "この設定の不足点",
2905
2962
  "warnings": {
2906
2963
  "runner_manifest_no_release": "release テンプレートがありません。実行をキャンセルしてもプールにジョブの停止を伝えられないため、取り残されたジョブはプールが自分で回収するまでランナーを占有し続けます。",