@cat-factory/app 0.110.3 → 0.111.0
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.
- package/app/components/board/AddTaskModal.vue +30 -2
- package/app/components/board/RecurringPipelineModal.vue +29 -2
- package/app/components/bootstrap/BootstrapModal.vue +18 -1
- package/app/components/panels/DecisionModal.vue +33 -5
- package/app/components/panels/InspectorPanel.vue +4 -0
- package/app/components/panels/inspector/ServiceTestSecrets.vue +264 -0
- package/app/composables/api/testSecrets.ts +36 -0
- package/app/composables/useApi.ts +2 -0
- package/app/composables/useUnsavedGuard.spec.ts +104 -0
- package/app/composables/useUnsavedGuard.ts +66 -0
- package/app/stores/testSecrets.ts +89 -0
- package/app/types/testSecrets.ts +15 -0
- package/i18n/locales/de.json +30 -2
- package/i18n/locales/en.json +30 -2
- package/i18n/locales/es.json +30 -2
- package/i18n/locales/fr.json +30 -2
- package/i18n/locales/he.json +30 -2
- package/i18n/locales/it.json +30 -2
- package/i18n/locales/ja.json +30 -2
- package/i18n/locales/pl.json +30 -2
- package/i18n/locales/tr.json +30 -2
- package/i18n/locales/uk.json +30 -2
- package/package.json +1 -1
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { watch } from 'vue'
|
|
2
|
+
import type { Ref } from 'vue'
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Guard a content-heavy modal against silently discarding unsaved input when the user
|
|
6
|
+
* dismisses it (Escape, backdrop click, or a Cancel button). Wire it into a controlled
|
|
7
|
+
* `UModal` whose `open` is a store-backed writable computed: route the setter's close and
|
|
8
|
+
* the Cancel button through `requestClose()` instead of closing directly.
|
|
9
|
+
*
|
|
10
|
+
* `snapshot()` returns a serialisable view of the user-facing form state. The baseline is
|
|
11
|
+
* captured every time the modal opens, so register this AFTER the component's own reset
|
|
12
|
+
* watcher — it then snapshots the *seeded* form (a prefill or an existing edit is the
|
|
13
|
+
* clean baseline, not a spurious change). A close request only prompts when the current
|
|
14
|
+
* snapshot diverges from that baseline; when nothing changed — or a submit is in flight —
|
|
15
|
+
* the close proceeds immediately, so the common path is unchanged.
|
|
16
|
+
*
|
|
17
|
+
* Keep `snapshot()` to stable, user-owned values: exclude fields mutated by async loads
|
|
18
|
+
* (they would read as dirty the instant a background fetch settles) and prefer stable ids
|
|
19
|
+
* over objects that a best-effort resolve rewrites in place.
|
|
20
|
+
*/
|
|
21
|
+
export function useUnsavedGuard(opts: {
|
|
22
|
+
/** The modal's open state (the writable computed's underlying getter). */
|
|
23
|
+
open: Ref<boolean>
|
|
24
|
+
/** A serialisable view of the current form state. */
|
|
25
|
+
snapshot: () => unknown
|
|
26
|
+
/** Actually close the modal (the store close action). */
|
|
27
|
+
close: () => void
|
|
28
|
+
/** True while a submit is in flight — a close is then a no-op (the submit closes itself). */
|
|
29
|
+
saving?: () => boolean
|
|
30
|
+
}) {
|
|
31
|
+
const { confirm } = useConfirm()
|
|
32
|
+
const { t } = useI18n()
|
|
33
|
+
|
|
34
|
+
let baseline = serialize(opts.snapshot())
|
|
35
|
+
watch(opts.open, (isOpen) => {
|
|
36
|
+
if (isOpen) baseline = serialize(opts.snapshot())
|
|
37
|
+
})
|
|
38
|
+
|
|
39
|
+
function isDirty(): boolean {
|
|
40
|
+
return serialize(opts.snapshot()) !== baseline
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
async function requestClose(): Promise<void> {
|
|
44
|
+
// A submit in flight closes itself on success — don't interrupt it or prompt.
|
|
45
|
+
if (opts.saving?.()) return
|
|
46
|
+
if (!isDirty()) {
|
|
47
|
+
opts.close()
|
|
48
|
+
return
|
|
49
|
+
}
|
|
50
|
+
const discard = await confirm({
|
|
51
|
+
title: t('common.discard.title'),
|
|
52
|
+
description: t('common.discard.body'),
|
|
53
|
+
confirmLabel: t('common.discard.confirm'),
|
|
54
|
+
cancelLabel: t('common.discard.keep'),
|
|
55
|
+
variant: 'destructive',
|
|
56
|
+
icon: 'i-lucide-triangle-alert',
|
|
57
|
+
})
|
|
58
|
+
if (discard) opts.close()
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
return { requestClose, isDirty }
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
function serialize(value: unknown): string {
|
|
65
|
+
return JSON.stringify(value ?? null)
|
|
66
|
+
}
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
import { defineStore } from 'pinia'
|
|
2
|
+
import { ref } from 'vue'
|
|
3
|
+
import type { TestSecretRef, UpsertServiceTestSecretsInput } from '~/types/testSecrets'
|
|
4
|
+
import { useWorkspaceStore } from '~/stores/workspace'
|
|
5
|
+
import { apiErrorStatus } from '~/composables/api/errors'
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* A service frame's SENSITIVE test secrets (a third-party token a Tester needs to
|
|
9
|
+
* exercise an integration). Sealed on the backend and delivered to the container out of
|
|
10
|
+
* band; the store only ever holds the non-secret refs (key + description) — values are
|
|
11
|
+
* write-only and never read back. Loaded on demand per service frame (the inspector
|
|
12
|
+
* panel), not from the snapshot, since the secrets never leave the server.
|
|
13
|
+
*/
|
|
14
|
+
export const useTestSecretsStore = defineStore('testSecrets', () => {
|
|
15
|
+
const api = useApi()
|
|
16
|
+
|
|
17
|
+
// Per service-frame block id → the configured secret refs (key + description).
|
|
18
|
+
const byBlock = ref<Record<string, TestSecretRef[]>>({})
|
|
19
|
+
const loading = ref(false)
|
|
20
|
+
// Mirrors the backend's opt-in gate (the controller 503s when ENCRYPTION_KEY is absent):
|
|
21
|
+
// `null` until first probed, then `true`/`false`. The inspector panel hides itself when
|
|
22
|
+
// this is false, so a deployment with no sealed-secret store doesn't surface a dead control.
|
|
23
|
+
const available = ref<boolean | null>(null)
|
|
24
|
+
const inFlight = new Map<string, Promise<void>>()
|
|
25
|
+
|
|
26
|
+
/** Force a refresh of one block's configured secret refs (used after a save/clear). */
|
|
27
|
+
async function load(blockId: string) {
|
|
28
|
+
const ws = useWorkspaceStore()
|
|
29
|
+
loading.value = true
|
|
30
|
+
try {
|
|
31
|
+
const view = await api.getServiceTestSecrets(ws.requireId(), blockId)
|
|
32
|
+
byBlock.value[blockId] = view.entries
|
|
33
|
+
available.value = true
|
|
34
|
+
} catch (err) {
|
|
35
|
+
if (apiErrorStatus(err) === 503) {
|
|
36
|
+
// A definitive 503 means the store is unconfigured (no encryption key on the
|
|
37
|
+
// backend): hide the UI entry point and stop probing.
|
|
38
|
+
available.value = false
|
|
39
|
+
byBlock.value[blockId] = []
|
|
40
|
+
}
|
|
41
|
+
// Any other failure (transient 5xx / network) is left untouched: it must not hide an
|
|
42
|
+
// already-available panel nor cache a false "unavailable". `available` stays `null`
|
|
43
|
+
// when never probed, so `ensureLoaded` remains retryable on the next open.
|
|
44
|
+
} finally {
|
|
45
|
+
loading.value = false
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Load one block's refs once and share the result, coalescing concurrent callers for the
|
|
51
|
+
* SAME block. `load()` forces a refresh.
|
|
52
|
+
*/
|
|
53
|
+
async function ensureLoaded(blockId: string) {
|
|
54
|
+
// Store known-unconfigured (a definitive 503) is a deployment-level fact — don't re-probe
|
|
55
|
+
// per service frame; the panel is hidden anyway.
|
|
56
|
+
if (available.value === false) return
|
|
57
|
+
if (byBlock.value[blockId] !== undefined) return
|
|
58
|
+
if (!inFlight.has(blockId)) {
|
|
59
|
+
inFlight.set(
|
|
60
|
+
blockId,
|
|
61
|
+
load(blockId).finally(() => inFlight.delete(blockId)),
|
|
62
|
+
)
|
|
63
|
+
}
|
|
64
|
+
return inFlight.get(blockId)
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/** The configured refs for a block (empty until loaded). */
|
|
68
|
+
function entriesForBlock(blockId: string): TestSecretRef[] {
|
|
69
|
+
return byBlock.value[blockId] ?? []
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
/** Replace a service frame's full secret set (values write-only); empty set clears it. */
|
|
73
|
+
async function save(blockId: string, input: UpsertServiceTestSecretsInput) {
|
|
74
|
+
const ws = useWorkspaceStore()
|
|
75
|
+
const view = await api.setServiceTestSecrets(ws.requireId(), blockId, input)
|
|
76
|
+
byBlock.value[blockId] = view.entries
|
|
77
|
+
available.value = true
|
|
78
|
+
return view
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
/** Remove all of a service frame's secrets. */
|
|
82
|
+
async function clear(blockId: string) {
|
|
83
|
+
const ws = useWorkspaceStore()
|
|
84
|
+
await api.deleteServiceTestSecrets(ws.requireId(), blockId)
|
|
85
|
+
byBlock.value[blockId] = []
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
return { byBlock, loading, available, load, ensureLoaded, entriesForBlock, save, clear }
|
|
89
|
+
})
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
// Sensitive per-service test-secret shapes (SEALED, write-only). A Tester needs these
|
|
2
|
+
// to exercise a third-party integration (e.g. a Stripe API key). Sealed at rest on the
|
|
3
|
+
// backend and injected into the Tester container OUT OF BAND — never rendered into a
|
|
4
|
+
// prompt or the telemetry snapshot. The view returns only the configured keys +
|
|
5
|
+
// descriptions (`TestSecretRef`); values are write-only and never read back.
|
|
6
|
+
//
|
|
7
|
+
// All wire shapes are sourced from @cat-factory/contracts (single source of truth).
|
|
8
|
+
// See docs/initiatives/tester-environment-access.md (Slice C).
|
|
9
|
+
|
|
10
|
+
export type {
|
|
11
|
+
TestSecretRef,
|
|
12
|
+
TestSecretEntry,
|
|
13
|
+
ServiceTestSecretsView,
|
|
14
|
+
UpsertServiceTestSecretsInput,
|
|
15
|
+
} from '@cat-factory/contracts'
|
package/i18n/locales/de.json
CHANGED
|
@@ -973,6 +973,27 @@
|
|
|
973
973
|
"clearFailed": "Zuordnung konnte nicht geleert werden",
|
|
974
974
|
"configNoun": "die Release-Health-Konfiguration"
|
|
975
975
|
},
|
|
976
|
+
"testSecrets": {
|
|
977
|
+
"title": "Test-Anmeldedaten (sensibel)",
|
|
978
|
+
"sectionHint": "Sensible Anmeldedaten, die der Tester benötigt, um ein von diesem Dienst genutztes Drittsystem anzusprechen, z. B. den API-Schlüssel eines Zahlungsanbieters. Sie werden verschlüsselt gespeichert und dem Tester als Umgebungsvariablen übergeben; sie erscheinen nie in Prompts oder Protokollen.",
|
|
979
|
+
"warning": "Dies sind echte, sensible Geheimnisse. Sie werden verschlüsselt gespeichert und dem Tester als Umgebungsvariablen übergeben, niemals in einem Prompt oder der Telemetrie des Laufs. Gib keine Produktionsdaten ein, die du nicht rotieren kannst.",
|
|
980
|
+
"replaceNote": "Beim Speichern wird der gesamte Satz für diesen Dienst ersetzt. Nimm jede Anmeldung auf, die du behalten möchtest, und gib ihren Wert erneut ein; alles Ausgelassene wird entfernt.",
|
|
981
|
+
"key": "Variablenname",
|
|
982
|
+
"keyInvalid": "Verwende Buchstaben, Ziffern und Unterstriche und beginne nicht mit einer Ziffer.",
|
|
983
|
+
"description": "Beschreibung",
|
|
984
|
+
"descriptionPlaceholder": "Wofür diese Anmeldung dient",
|
|
985
|
+
"value": "Wert",
|
|
986
|
+
"valuePlaceholder": "Geheimer Wert",
|
|
987
|
+
"addRow": "Anmeldung hinzufügen",
|
|
988
|
+
"removeRow": "Anmeldung entfernen",
|
|
989
|
+
"save": "Anmeldedaten speichern",
|
|
990
|
+
"clear": "Alle löschen",
|
|
991
|
+
"savedToast": "Test-Anmeldedaten gespeichert",
|
|
992
|
+
"saveFailed": "Test-Anmeldedaten konnten nicht gespeichert werden",
|
|
993
|
+
"clearFailed": "Test-Anmeldedaten konnten nicht gelöscht werden",
|
|
994
|
+
"configNoun": "die sensiblen Test-Anmeldedaten",
|
|
995
|
+
"duplicateKey": "Jeder Variablenname muss eindeutig sein."
|
|
996
|
+
},
|
|
976
997
|
"testConfig": {
|
|
977
998
|
"title": "Testinfrastruktur",
|
|
978
999
|
"hint": "Wie eine Testumgebung für diesen Service aufgesetzt wird, wenn eine Pipeline ihn ausführen muss: keine Infrastruktur, eine Docker-Compose-Datei, Kubernetes-Manifeste oder ein benutzerdefinierter Manifesttyp.",
|
|
@@ -1217,7 +1238,8 @@
|
|
|
1217
1238
|
"decision": {
|
|
1218
1239
|
"title": "Entscheidung erforderlich",
|
|
1219
1240
|
"agentOnBlock": "{agent} auf {block}",
|
|
1220
|
-
"visualizationHint": "Dies ist eine Visualisierung. Jede Wahl setzt einfach die Pipeline fort."
|
|
1241
|
+
"visualizationHint": "Dies ist eine Visualisierung. Jede Wahl setzt einfach die Pipeline fort.",
|
|
1242
|
+
"resolveFailed": "Entscheidung konnte nicht gespeichert werden"
|
|
1221
1243
|
},
|
|
1222
1244
|
"stepRestart": {
|
|
1223
1245
|
"restartFromStep": "Pipeline ab diesem Schritt neu starten",
|
|
@@ -3656,7 +3678,13 @@
|
|
|
3656
3678
|
"undo": "Rückgängig",
|
|
3657
3679
|
"back": "Zurück",
|
|
3658
3680
|
"next": "Weiter",
|
|
3659
|
-
"done": "Fertig"
|
|
3681
|
+
"done": "Fertig",
|
|
3682
|
+
"discard": {
|
|
3683
|
+
"title": "Änderungen verwerfen?",
|
|
3684
|
+
"body": "Du hast Änderungen vorgenommen, die noch nicht gespeichert wurden. Schließen und verlieren?",
|
|
3685
|
+
"confirm": "Verwerfen",
|
|
3686
|
+
"keep": "Weiter bearbeiten"
|
|
3687
|
+
}
|
|
3660
3688
|
},
|
|
3661
3689
|
"clarification": {
|
|
3662
3690
|
"answerPlaceholder": "Ihre Antwort",
|
package/i18n/locales/en.json
CHANGED
|
@@ -74,7 +74,13 @@
|
|
|
74
74
|
"undo": "Undo",
|
|
75
75
|
"back": "Back",
|
|
76
76
|
"next": "Next",
|
|
77
|
-
"done": "Done"
|
|
77
|
+
"done": "Done",
|
|
78
|
+
"discard": {
|
|
79
|
+
"title": "Discard your changes?",
|
|
80
|
+
"body": "You've made changes that haven't been saved. Close this and lose them?",
|
|
81
|
+
"confirm": "Discard",
|
|
82
|
+
"keep": "Keep editing"
|
|
83
|
+
}
|
|
78
84
|
},
|
|
79
85
|
"clarification": {
|
|
80
86
|
"answerPlaceholder": "Your answer",
|
|
@@ -717,6 +723,27 @@
|
|
|
717
723
|
"clearFailed": "Could not clear the mapping",
|
|
718
724
|
"configNoun": "the release health configuration"
|
|
719
725
|
},
|
|
726
|
+
"testSecrets": {
|
|
727
|
+
"title": "Test credentials (sensitive)",
|
|
728
|
+
"sectionHint": "Sensitive credentials the Tester needs to exercise a third-party system this service depends on, e.g. a payment provider's API key. They are encrypted at rest and injected into the Tester's environment as variables; they are never shown in prompts or logs.",
|
|
729
|
+
"warning": "These are real, sensitive secrets. They are encrypted at rest and passed to the Tester as environment variables, never put in a prompt or the run's telemetry. Don't enter production credentials you can't rotate.",
|
|
730
|
+
"replaceNote": "Saving replaces the entire set for this service. Include every credential you want to keep and re-enter its value; anything left out is removed.",
|
|
731
|
+
"key": "Variable name",
|
|
732
|
+
"keyInvalid": "Use letters, digits and underscores, and don't start with a digit.",
|
|
733
|
+
"description": "Description",
|
|
734
|
+
"descriptionPlaceholder": "What this credential is for",
|
|
735
|
+
"value": "Value",
|
|
736
|
+
"valuePlaceholder": "Secret value",
|
|
737
|
+
"addRow": "Add credential",
|
|
738
|
+
"removeRow": "Remove credential",
|
|
739
|
+
"save": "Save credentials",
|
|
740
|
+
"clear": "Clear all",
|
|
741
|
+
"savedToast": "Test credentials saved",
|
|
742
|
+
"saveFailed": "Could not save the test credentials",
|
|
743
|
+
"clearFailed": "Could not clear the test credentials",
|
|
744
|
+
"configNoun": "the sensitive test credentials",
|
|
745
|
+
"duplicateKey": "Each variable name must be unique."
|
|
746
|
+
},
|
|
720
747
|
"testConfig": {
|
|
721
748
|
"title": "Test infrastructure",
|
|
722
749
|
"hint": "How a test environment is stood up for this service when a pipeline needs to run it: no infrastructure, a Docker Compose file, Kubernetes manifests, or a custom manifest type.",
|
|
@@ -961,7 +988,8 @@
|
|
|
961
988
|
"decision": {
|
|
962
989
|
"title": "Decision required",
|
|
963
990
|
"agentOnBlock": "{agent} on {block}",
|
|
964
|
-
"visualizationHint": "This is a visualization. Any choice simply resumes the pipeline."
|
|
991
|
+
"visualizationHint": "This is a visualization. Any choice simply resumes the pipeline.",
|
|
992
|
+
"resolveFailed": "Couldn't record your decision"
|
|
965
993
|
},
|
|
966
994
|
"stepRestart": {
|
|
967
995
|
"restartFromStep": "Restart pipeline from this step",
|
package/i18n/locales/es.json
CHANGED
|
@@ -65,7 +65,13 @@
|
|
|
65
65
|
"undo": "Deshacer",
|
|
66
66
|
"back": "Atrás",
|
|
67
67
|
"next": "Siguiente",
|
|
68
|
-
"done": "Listo"
|
|
68
|
+
"done": "Listo",
|
|
69
|
+
"discard": {
|
|
70
|
+
"title": "¿Descartar los cambios?",
|
|
71
|
+
"body": "Has hecho cambios que no se han guardado. ¿Cerrar y perderlos?",
|
|
72
|
+
"confirm": "Descartar",
|
|
73
|
+
"keep": "Seguir editando"
|
|
74
|
+
}
|
|
69
75
|
},
|
|
70
76
|
"clarification": {
|
|
71
77
|
"answerPlaceholder": "Tu respuesta",
|
|
@@ -663,6 +669,27 @@
|
|
|
663
669
|
"clearFailed": "No se pudo limpiar la asignación",
|
|
664
670
|
"configNoun": "la configuración de salud de la versión"
|
|
665
671
|
},
|
|
672
|
+
"testSecrets": {
|
|
673
|
+
"title": "Credenciales de prueba (sensibles)",
|
|
674
|
+
"sectionHint": "Credenciales sensibles que el Tester necesita para usar un sistema de terceros del que depende este servicio, p. ej. la clave de API de una pasarela de pago. Se almacenan cifradas y se inyectan en el entorno del Tester como variables; nunca se muestran en prompts ni en registros.",
|
|
675
|
+
"warning": "Son secretos reales y sensibles. Se almacenan cifrados y se pasan al Tester como variables de entorno, nunca en un prompt ni en la telemetría de la ejecución. No introduzcas credenciales de producción que no puedas rotar.",
|
|
676
|
+
"replaceNote": "Al guardar se reemplaza el conjunto completo de este servicio. Incluye cada credencial que quieras conservar y vuelve a introducir su valor; lo que se omita se elimina.",
|
|
677
|
+
"key": "Nombre de variable",
|
|
678
|
+
"keyInvalid": "Usa letras, dígitos y guiones bajos, y no empieces por un dígito.",
|
|
679
|
+
"description": "Descripción",
|
|
680
|
+
"descriptionPlaceholder": "Para qué sirve esta credencial",
|
|
681
|
+
"value": "Valor",
|
|
682
|
+
"valuePlaceholder": "Valor secreto",
|
|
683
|
+
"addRow": "Añadir credencial",
|
|
684
|
+
"removeRow": "Eliminar credencial",
|
|
685
|
+
"save": "Guardar credenciales",
|
|
686
|
+
"clear": "Borrar todo",
|
|
687
|
+
"savedToast": "Credenciales de prueba guardadas",
|
|
688
|
+
"saveFailed": "No se pudieron guardar las credenciales de prueba",
|
|
689
|
+
"clearFailed": "No se pudieron borrar las credenciales de prueba",
|
|
690
|
+
"configNoun": "las credenciales de prueba sensibles",
|
|
691
|
+
"duplicateKey": "Cada nombre de variable debe ser único."
|
|
692
|
+
},
|
|
666
693
|
"testConfig": {
|
|
667
694
|
"title": "Infraestructura de pruebas",
|
|
668
695
|
"hint": "Cómo se levanta un entorno de prueba para este servicio cuando un pipeline necesita ejecutarlo: sin infraestructura, un archivo de Docker Compose, manifiestos de Kubernetes o un tipo de manifiesto personalizado.",
|
|
@@ -907,7 +934,8 @@
|
|
|
907
934
|
"decision": {
|
|
908
935
|
"title": "Se requiere una decisión",
|
|
909
936
|
"agentOnBlock": "{agent} en {block}",
|
|
910
|
-
"visualizationHint": "Esto es una visualización. Cualquier elección simplemente reanuda el pipeline."
|
|
937
|
+
"visualizationHint": "Esto es una visualización. Cualquier elección simplemente reanuda el pipeline.",
|
|
938
|
+
"resolveFailed": "No se pudo registrar tu decisión"
|
|
911
939
|
},
|
|
912
940
|
"stepRestart": {
|
|
913
941
|
"restartFromStep": "Reiniciar el pipeline desde este paso",
|
package/i18n/locales/fr.json
CHANGED
|
@@ -65,7 +65,13 @@
|
|
|
65
65
|
"undo": "Annuler",
|
|
66
66
|
"back": "Retour",
|
|
67
67
|
"next": "Suivant",
|
|
68
|
-
"done": "Terminé"
|
|
68
|
+
"done": "Terminé",
|
|
69
|
+
"discard": {
|
|
70
|
+
"title": "Ignorer vos modifications ?",
|
|
71
|
+
"body": "Vous avez effectué des modifications non enregistrées. Fermer et les perdre ?",
|
|
72
|
+
"confirm": "Ignorer",
|
|
73
|
+
"keep": "Continuer l'édition"
|
|
74
|
+
}
|
|
69
75
|
},
|
|
70
76
|
"clarification": {
|
|
71
77
|
"answerPlaceholder": "Votre réponse",
|
|
@@ -663,6 +669,27 @@
|
|
|
663
669
|
"clearFailed": "Impossible d'effacer le mappage",
|
|
664
670
|
"configNoun": "la configuration de santé de la version"
|
|
665
671
|
},
|
|
672
|
+
"testSecrets": {
|
|
673
|
+
"title": "Identifiants de test (sensibles)",
|
|
674
|
+
"sectionHint": "Identifiants sensibles dont le Testeur a besoin pour solliciter un système tiers utilisé par ce service, par exemple la clé d'API d'un prestataire de paiement. Ils sont chiffrés au repos et injectés dans l'environnement du Testeur sous forme de variables ; ils n'apparaissent jamais dans les prompts ni les journaux.",
|
|
675
|
+
"warning": "Ce sont de vrais secrets sensibles. Ils sont chiffrés au repos et transmis au Testeur comme variables d'environnement, jamais dans un prompt ni dans la télémétrie de l'exécution. N'entrez pas d'identifiants de production que vous ne pouvez pas renouveler.",
|
|
676
|
+
"replaceNote": "L'enregistrement remplace l'ensemble complet pour ce service. Incluez chaque identifiant à conserver et saisissez à nouveau sa valeur ; tout ce qui est omis est supprimé.",
|
|
677
|
+
"key": "Nom de variable",
|
|
678
|
+
"keyInvalid": "Utilisez des lettres, des chiffres et des tirets bas, et ne commencez pas par un chiffre.",
|
|
679
|
+
"description": "Description",
|
|
680
|
+
"descriptionPlaceholder": "À quoi sert cet identifiant",
|
|
681
|
+
"value": "Valeur",
|
|
682
|
+
"valuePlaceholder": "Valeur secrète",
|
|
683
|
+
"addRow": "Ajouter un identifiant",
|
|
684
|
+
"removeRow": "Supprimer l'identifiant",
|
|
685
|
+
"save": "Enregistrer les identifiants",
|
|
686
|
+
"clear": "Tout effacer",
|
|
687
|
+
"savedToast": "Identifiants de test enregistrés",
|
|
688
|
+
"saveFailed": "Impossible d'enregistrer les identifiants de test",
|
|
689
|
+
"clearFailed": "Impossible d'effacer les identifiants de test",
|
|
690
|
+
"configNoun": "les identifiants de test sensibles",
|
|
691
|
+
"duplicateKey": "Chaque nom de variable doit être unique."
|
|
692
|
+
},
|
|
666
693
|
"testConfig": {
|
|
667
694
|
"title": "Infrastructure de test",
|
|
668
695
|
"hint": "Comment un environnement de test est mis en place pour ce service quand un pipeline doit l'exécuter : sans infrastructure, un fichier Docker Compose, des manifestes Kubernetes ou un type de manifeste personnalisé.",
|
|
@@ -907,7 +934,8 @@
|
|
|
907
934
|
"decision": {
|
|
908
935
|
"title": "Décision requise",
|
|
909
936
|
"agentOnBlock": "{agent} sur {block}",
|
|
910
|
-
"visualizationHint": "Ceci est une visualisation. Tout choix reprend simplement le pipeline."
|
|
937
|
+
"visualizationHint": "Ceci est une visualisation. Tout choix reprend simplement le pipeline.",
|
|
938
|
+
"resolveFailed": "Impossible d'enregistrer votre décision"
|
|
911
939
|
},
|
|
912
940
|
"stepRestart": {
|
|
913
941
|
"restartFromStep": "Redémarrer le pipeline à partir de cette étape",
|
package/i18n/locales/he.json
CHANGED
|
@@ -65,7 +65,13 @@
|
|
|
65
65
|
"undo": "בטל",
|
|
66
66
|
"back": "חזרה",
|
|
67
67
|
"next": "הבא",
|
|
68
|
-
"done": "סיום"
|
|
68
|
+
"done": "סיום",
|
|
69
|
+
"discard": {
|
|
70
|
+
"title": "לבטל את השינויים?",
|
|
71
|
+
"body": "ביצעת שינויים שלא נשמרו. לסגור ולאבד אותם?",
|
|
72
|
+
"confirm": "לבטל",
|
|
73
|
+
"keep": "להמשיך לערוך"
|
|
74
|
+
}
|
|
69
75
|
},
|
|
70
76
|
"clarification": {
|
|
71
77
|
"answerPlaceholder": "התשובה שלך",
|
|
@@ -663,6 +669,27 @@
|
|
|
663
669
|
"clearFailed": "לא ניתן לנקות את המיפוי",
|
|
664
670
|
"configNoun": "תצורת בריאות הגרסה"
|
|
665
671
|
},
|
|
672
|
+
"testSecrets": {
|
|
673
|
+
"title": "פרטי גישה לבדיקה (רגישים)",
|
|
674
|
+
"sectionHint": "פרטי גישה רגישים שהבודק זקוק להם כדי לתקשר עם מערכת צד-שלישי שהשירות הזה תלוי בה, למשל מפתח API של ספק תשלומים. הם מאוחסנים מוצפנים ומוזרקים לסביבת הבודק כמשתני סביבה; הם לעולם אינם מוצגים בהנחיות או ביומנים.",
|
|
675
|
+
"warning": "אלה סודות אמיתיים ורגישים. הם מאוחסנים מוצפנים ומועברים לבודק כמשתני סביבה, לעולם לא בהנחיה או בטלמטריה של הריצה. אל תזינו פרטי גישה של סביבת ייצור שאינכם יכולים להחליף.",
|
|
676
|
+
"replaceNote": "שמירה מחליפה את כל הקבוצה של השירות הזה. כללו כל פרט גישה שברצונכם לשמור והזינו מחדש את ערכו; כל מה שיושמט יימחק.",
|
|
677
|
+
"key": "שם משתנה",
|
|
678
|
+
"keyInvalid": "השתמשו באותיות, ספרות וקו תחתון, ואל תתחילו בספרה.",
|
|
679
|
+
"description": "תיאור",
|
|
680
|
+
"descriptionPlaceholder": "למה משמש פרט הגישה הזה",
|
|
681
|
+
"value": "ערך",
|
|
682
|
+
"valuePlaceholder": "ערך סודי",
|
|
683
|
+
"addRow": "הוספת פרט גישה",
|
|
684
|
+
"removeRow": "הסרת פרט גישה",
|
|
685
|
+
"save": "שמירת פרטי הגישה",
|
|
686
|
+
"clear": "ניקוי הכול",
|
|
687
|
+
"savedToast": "פרטי הגישה לבדיקה נשמרו",
|
|
688
|
+
"saveFailed": "לא ניתן לשמור את פרטי הגישה לבדיקה",
|
|
689
|
+
"clearFailed": "לא ניתן לנקות את פרטי הגישה לבדיקה",
|
|
690
|
+
"configNoun": "פרטי הגישה הרגישים לבדיקה",
|
|
691
|
+
"duplicateKey": "כל שם משתנה חייב להיות ייחודי."
|
|
692
|
+
},
|
|
666
693
|
"testConfig": {
|
|
667
694
|
"title": "תשתית בדיקות",
|
|
668
695
|
"hint": "כיצד מוקמת סביבת בדיקה לשירות זה כאשר פייפליין צריך להריץ אותו: ללא תשתית, קובץ Docker Compose, מניפסטים של Kubernetes או סוג מניפסט מותאם אישית.",
|
|
@@ -907,7 +934,8 @@
|
|
|
907
934
|
"decision": {
|
|
908
935
|
"title": "נדרשת החלטה",
|
|
909
936
|
"agentOnBlock": "{agent} על {block}",
|
|
910
|
-
"visualizationHint": "זוהי הצגה חזותית. כל בחירה פשוט ממשיכה את הצינור."
|
|
937
|
+
"visualizationHint": "זוהי הצגה חזותית. כל בחירה פשוט ממשיכה את הצינור.",
|
|
938
|
+
"resolveFailed": "לא ניתן היה לשמור את ההחלטה שלך"
|
|
911
939
|
},
|
|
912
940
|
"stepRestart": {
|
|
913
941
|
"restartFromStep": "הפעל מחדש את הצינור משלב זה",
|
package/i18n/locales/it.json
CHANGED
|
@@ -973,6 +973,27 @@
|
|
|
973
973
|
"clearFailed": "Impossibile cancellare il mapping",
|
|
974
974
|
"configNoun": "la configurazione dello stato di rilascio"
|
|
975
975
|
},
|
|
976
|
+
"testSecrets": {
|
|
977
|
+
"title": "Credenziali di test (sensibili)",
|
|
978
|
+
"sectionHint": "Credenziali sensibili di cui il Tester ha bisogno per interagire con un sistema di terze parti da cui dipende questo servizio, ad esempio la chiave API di un fornitore di pagamenti. Sono cifrate a riposo e iniettate nell'ambiente del Tester come variabili; non compaiono mai nei prompt né nei log.",
|
|
979
|
+
"warning": "Sono segreti reali e sensibili. Vengono cifrati a riposo e passati al Tester come variabili d'ambiente, mai in un prompt o nella telemetria dell'esecuzione. Non inserire credenziali di produzione che non puoi ruotare.",
|
|
980
|
+
"replaceNote": "Il salvataggio sostituisce l'intero insieme per questo servizio. Includi ogni credenziale che vuoi mantenere e reinserisci il suo valore; tutto ciò che viene omesso viene rimosso.",
|
|
981
|
+
"key": "Nome variabile",
|
|
982
|
+
"keyInvalid": "Usa lettere, cifre e trattini bassi e non iniziare con una cifra.",
|
|
983
|
+
"description": "Descrizione",
|
|
984
|
+
"descriptionPlaceholder": "A cosa serve questa credenziale",
|
|
985
|
+
"value": "Valore",
|
|
986
|
+
"valuePlaceholder": "Valore segreto",
|
|
987
|
+
"addRow": "Aggiungi credenziale",
|
|
988
|
+
"removeRow": "Rimuovi credenziale",
|
|
989
|
+
"save": "Salva credenziali",
|
|
990
|
+
"clear": "Cancella tutto",
|
|
991
|
+
"savedToast": "Credenziali di test salvate",
|
|
992
|
+
"saveFailed": "Impossibile salvare le credenziali di test",
|
|
993
|
+
"clearFailed": "Impossibile cancellare le credenziali di test",
|
|
994
|
+
"configNoun": "le credenziali di test sensibili",
|
|
995
|
+
"duplicateKey": "Ogni nome di variabile deve essere univoco."
|
|
996
|
+
},
|
|
976
997
|
"testConfig": {
|
|
977
998
|
"title": "Infrastruttura di test",
|
|
978
999
|
"hint": "Come viene predisposto un ambiente di test per questo servizio quando una pipeline deve eseguirlo: nessuna infrastruttura, un file Docker Compose, manifest Kubernetes, o un tipo di manifest personalizzato.",
|
|
@@ -1217,7 +1238,8 @@
|
|
|
1217
1238
|
"decision": {
|
|
1218
1239
|
"title": "Decisione richiesta",
|
|
1219
1240
|
"agentOnBlock": "{agent} su {block}",
|
|
1220
|
-
"visualizationHint": "Questa e' una visualizzazione. Qualsiasi scelta riprende semplicemente la pipeline."
|
|
1241
|
+
"visualizationHint": "Questa e' una visualizzazione. Qualsiasi scelta riprende semplicemente la pipeline.",
|
|
1242
|
+
"resolveFailed": "Impossibile registrare la tua decisione"
|
|
1221
1243
|
},
|
|
1222
1244
|
"stepRestart": {
|
|
1223
1245
|
"restartFromStep": "Riavvia la pipeline da questo passaggio",
|
|
@@ -3656,7 +3678,13 @@
|
|
|
3656
3678
|
"undo": "Annulla",
|
|
3657
3679
|
"back": "Indietro",
|
|
3658
3680
|
"next": "Avanti",
|
|
3659
|
-
"done": "Fatto"
|
|
3681
|
+
"done": "Fatto",
|
|
3682
|
+
"discard": {
|
|
3683
|
+
"title": "Ignorare le modifiche?",
|
|
3684
|
+
"body": "Hai apportato modifiche non salvate. Chiudere e perderle?",
|
|
3685
|
+
"confirm": "Ignora",
|
|
3686
|
+
"keep": "Continua a modificare"
|
|
3687
|
+
}
|
|
3660
3688
|
},
|
|
3661
3689
|
"clarification": {
|
|
3662
3690
|
"answerPlaceholder": "La tua risposta",
|
package/i18n/locales/ja.json
CHANGED
|
@@ -65,7 +65,13 @@
|
|
|
65
65
|
"undo": "元に戻す",
|
|
66
66
|
"back": "戻る",
|
|
67
67
|
"next": "次へ",
|
|
68
|
-
"done": "完了"
|
|
68
|
+
"done": "完了",
|
|
69
|
+
"discard": {
|
|
70
|
+
"title": "変更を破棄しますか?",
|
|
71
|
+
"body": "保存されていない変更があります。閉じて破棄しますか?",
|
|
72
|
+
"confirm": "破棄",
|
|
73
|
+
"keep": "編集を続ける"
|
|
74
|
+
}
|
|
69
75
|
},
|
|
70
76
|
"clarification": {
|
|
71
77
|
"answerPlaceholder": "回答を入力",
|
|
@@ -663,6 +669,27 @@
|
|
|
663
669
|
"clearFailed": "マッピングをクリアできませんでした",
|
|
664
670
|
"configNoun": "リリースヘルス設定"
|
|
665
671
|
},
|
|
672
|
+
"testSecrets": {
|
|
673
|
+
"title": "テスト用認証情報(機密)",
|
|
674
|
+
"sectionHint": "このサービスが依存するサードパーティのシステム(例:決済プロバイダーの API キー)をテスターが操作するために必要な、機密性の高い認証情報です。保存時に暗号化され、環境変数としてテスターの環境に注入されます。プロンプトやログには決して表示されません。",
|
|
675
|
+
"warning": "これらは実際の機密情報です。保存時に暗号化され、環境変数としてテスターに渡されます。プロンプトや実行のテレメトリーには一切含まれません。ローテーションできない本番用の認証情報は入力しないでください。",
|
|
676
|
+
"replaceNote": "保存すると、このサービスのセット全体が置き換えられます。残しておきたい認証情報はすべて含め、その値を再入力してください。省略したものは削除されます。",
|
|
677
|
+
"key": "変数名",
|
|
678
|
+
"keyInvalid": "英字・数字・アンダースコアを使用し、数字で始めないでください。",
|
|
679
|
+
"description": "説明",
|
|
680
|
+
"descriptionPlaceholder": "この認証情報の用途",
|
|
681
|
+
"value": "値",
|
|
682
|
+
"valuePlaceholder": "秘密の値",
|
|
683
|
+
"addRow": "認証情報を追加",
|
|
684
|
+
"removeRow": "認証情報を削除",
|
|
685
|
+
"save": "認証情報を保存",
|
|
686
|
+
"clear": "すべて消去",
|
|
687
|
+
"savedToast": "テスト用認証情報を保存しました",
|
|
688
|
+
"saveFailed": "テスト用認証情報を保存できませんでした",
|
|
689
|
+
"clearFailed": "テスト用認証情報を消去できませんでした",
|
|
690
|
+
"configNoun": "機密のテスト用認証情報",
|
|
691
|
+
"duplicateKey": "変数名はそれぞれ一意である必要があります。"
|
|
692
|
+
},
|
|
666
693
|
"testConfig": {
|
|
667
694
|
"title": "テストインフラ",
|
|
668
695
|
"hint": "パイプラインがこのサービスを実行する必要があるときに、テスト環境をどう立ち上げるか: インフラなし、Docker Compose ファイル、Kubernetes マニフェスト、またはカスタムマニフェストタイプ。",
|
|
@@ -907,7 +934,8 @@
|
|
|
907
934
|
"decision": {
|
|
908
935
|
"title": "判断が必要",
|
|
909
936
|
"agentOnBlock": "{block} の {agent}",
|
|
910
|
-
"visualizationHint": "これは可視化です。どの選択でもパイプラインを再開するだけです。"
|
|
937
|
+
"visualizationHint": "これは可視化です。どの選択でもパイプラインを再開するだけです。",
|
|
938
|
+
"resolveFailed": "決定を記録できませんでした"
|
|
911
939
|
},
|
|
912
940
|
"stepRestart": {
|
|
913
941
|
"restartFromStep": "このステップからパイプラインを再開",
|
package/i18n/locales/pl.json
CHANGED
|
@@ -65,7 +65,13 @@
|
|
|
65
65
|
"undo": "Cofnij",
|
|
66
66
|
"back": "Wstecz",
|
|
67
67
|
"next": "Dalej",
|
|
68
|
-
"done": "Gotowe"
|
|
68
|
+
"done": "Gotowe",
|
|
69
|
+
"discard": {
|
|
70
|
+
"title": "Odrzucić zmiany?",
|
|
71
|
+
"body": "Masz niezapisane zmiany. Zamknąć i je utracić?",
|
|
72
|
+
"confirm": "Odrzuć",
|
|
73
|
+
"keep": "Kontynuuj edycję"
|
|
74
|
+
}
|
|
69
75
|
},
|
|
70
76
|
"clarification": {
|
|
71
77
|
"answerPlaceholder": "Twoja odpowiedź",
|
|
@@ -663,6 +669,27 @@
|
|
|
663
669
|
"clearFailed": "Nie udało się wyczyścić mapowania",
|
|
664
670
|
"configNoun": "konfigurację kondycji wydania"
|
|
665
671
|
},
|
|
672
|
+
"testSecrets": {
|
|
673
|
+
"title": "Poświadczenia testowe (wrażliwe)",
|
|
674
|
+
"sectionHint": "Wrażliwe poświadczenia potrzebne Testerowi do korzystania z zewnętrznego systemu, od którego zależy ta usługa, np. klucz API dostawcy płatności. Są przechowywane w postaci zaszyfrowanej i wstrzykiwane do środowiska Testera jako zmienne; nigdy nie pojawiają się w promptach ani w logach.",
|
|
675
|
+
"warning": "To prawdziwe, wrażliwe sekrety. Są przechowywane w postaci zaszyfrowanej i przekazywane Testerowi jako zmienne środowiskowe, nigdy w promptcie ani w telemetrii przebiegu. Nie wprowadzaj poświadczeń produkcyjnych, których nie możesz zmienić.",
|
|
676
|
+
"replaceNote": "Zapis zastępuje cały zestaw dla tej usługi. Uwzględnij każde poświadczenie, które chcesz zachować, i ponownie wprowadź jego wartość; wszystko pominięte zostanie usunięte.",
|
|
677
|
+
"key": "Nazwa zmiennej",
|
|
678
|
+
"keyInvalid": "Używaj liter, cyfr i podkreśleń i nie zaczynaj od cyfry.",
|
|
679
|
+
"description": "Opis",
|
|
680
|
+
"descriptionPlaceholder": "Do czego służy to poświadczenie",
|
|
681
|
+
"value": "Wartość",
|
|
682
|
+
"valuePlaceholder": "Tajna wartość",
|
|
683
|
+
"addRow": "Dodaj poświadczenie",
|
|
684
|
+
"removeRow": "Usuń poświadczenie",
|
|
685
|
+
"save": "Zapisz poświadczenia",
|
|
686
|
+
"clear": "Wyczyść wszystko",
|
|
687
|
+
"savedToast": "Zapisano poświadczenia testowe",
|
|
688
|
+
"saveFailed": "Nie udało się zapisać poświadczeń testowych",
|
|
689
|
+
"clearFailed": "Nie udało się wyczyścić poświadczeń testowych",
|
|
690
|
+
"configNoun": "wrażliwe poświadczenia testowe",
|
|
691
|
+
"duplicateKey": "Każda nazwa zmiennej musi być unikalna."
|
|
692
|
+
},
|
|
666
693
|
"testConfig": {
|
|
667
694
|
"title": "Infrastruktura testowa",
|
|
668
695
|
"hint": "Jak stawiane jest środowisko testowe dla tej usługi, gdy potok musi ją uruchomić: bez infrastruktury, plik Docker Compose, manifesty Kubernetes lub niestandardowy typ manifestu.",
|
|
@@ -907,7 +934,8 @@
|
|
|
907
934
|
"decision": {
|
|
908
935
|
"title": "Wymagana decyzja",
|
|
909
936
|
"agentOnBlock": "{agent} na {block}",
|
|
910
|
-
"visualizationHint": "To jest wizualizacja. Każdy wybór po prostu wznawia potok."
|
|
937
|
+
"visualizationHint": "To jest wizualizacja. Każdy wybór po prostu wznawia potok.",
|
|
938
|
+
"resolveFailed": "Nie udało się zapisać decyzji"
|
|
911
939
|
},
|
|
912
940
|
"stepRestart": {
|
|
913
941
|
"restartFromStep": "Uruchom ponownie potok od tego kroku",
|