feat: add workspace secrets ui
This commit is contained in:
@@ -9,6 +9,7 @@ var TRANSLATIONS = {
|
||||
'nav.operations': 'Operations',
|
||||
'nav.agents': 'Agents',
|
||||
'nav.apikeys': 'API Keys',
|
||||
'nav.secrets': 'Secrets',
|
||||
'nav.logs': 'Logs',
|
||||
'nav.usage': 'Usage',
|
||||
'nav.settings': 'Settings',
|
||||
@@ -157,6 +158,97 @@ var TRANSLATIONS = {
|
||||
'apikeys.action.delete': 'Delete',
|
||||
'apikeys.creating': 'Creating…',
|
||||
|
||||
// Secrets page
|
||||
'secrets.title': 'Secrets',
|
||||
'secrets.subtitle': 'Encrypted upstream credentials for bearer tokens, basic auth, and API keys used by auth profiles.',
|
||||
'secrets.new': 'Create secret',
|
||||
'secrets.callout.title': 'Secret plaintext is write-only.',
|
||||
'secrets.callout.body': 'Crank encrypts secret values with the workspace master key. After create or rotate, the API returns only metadata, so this page focuses on lifecycle and usage references.',
|
||||
'secrets.active.title': 'Workspace secrets',
|
||||
'secrets.active.subtitle': '{active} active · {total} total',
|
||||
'secrets.search': 'Filter secrets…',
|
||||
'secrets.th.name': 'NAME',
|
||||
'secrets.th.kind': 'KIND',
|
||||
'secrets.th.version': 'VERSION',
|
||||
'secrets.th.last_used': 'LAST USED',
|
||||
'secrets.th.used_by': 'USED BY',
|
||||
'secrets.th.status': 'STATUS',
|
||||
'secrets.kind.token': 'Token',
|
||||
'secrets.kind.username_password': 'Username/password',
|
||||
'secrets.kind.header': 'Header value',
|
||||
'secrets.kind.generic': 'Generic JSON',
|
||||
'secrets.status.active': 'Active',
|
||||
'secrets.status.disabled': 'Disabled',
|
||||
'secrets.last_used.never': 'Never',
|
||||
'secrets.used_by_count': '{count} profiles',
|
||||
'secrets.loading': 'Loading…',
|
||||
'secrets.empty.none': 'No secrets yet',
|
||||
'secrets.empty.search': 'No secrets match your search',
|
||||
'secrets.error.workspace': 'Workspace is not selected',
|
||||
'secrets.error.load': 'Failed to load secrets',
|
||||
'secrets.action.rotate': 'Rotate',
|
||||
'secrets.action.delete': 'Delete',
|
||||
'secrets.confirm.delete': 'Delete secret {name}? This cannot be undone while the secret is still referenced by an auth profile.',
|
||||
'secrets.toast.create_title': 'Secret created',
|
||||
'secrets.toast.create_message': 'The secret was stored encrypted. Plaintext cannot be viewed again through the API.',
|
||||
'secrets.toast.create_error_title': 'Secret creation failed',
|
||||
'secrets.toast.create_error_message': 'Failed to create secret',
|
||||
'secrets.toast.rotate_title': 'Secret rotated',
|
||||
'secrets.toast.rotate_message': 'A new secret version is now active.',
|
||||
'secrets.toast.rotate_error_title': 'Secret rotation failed',
|
||||
'secrets.toast.rotate_error_message': 'Failed to rotate secret',
|
||||
'secrets.toast.delete_title': 'Secret deleted',
|
||||
'secrets.toast.delete_message': '{name} was deleted.',
|
||||
'secrets.toast.delete_error_title': 'Secret deletion failed',
|
||||
'secrets.toast.delete_error_message': 'Failed to delete secret',
|
||||
'secrets.modal.create_title': 'Create secret',
|
||||
'secrets.modal.rotate_title': 'Rotate secret',
|
||||
'secrets.modal.name': 'Secret name',
|
||||
'secrets.modal.name_hint': 'Use a stable operator-facing label. Plaintext values are never returned after storage.',
|
||||
'secrets.modal.kind': 'Secret kind',
|
||||
'secrets.modal.value': 'Secret value',
|
||||
'secrets.modal.header_value': 'Header value',
|
||||
'secrets.modal.username': 'Username',
|
||||
'secrets.modal.password': 'Password',
|
||||
'secrets.modal.json_payload': 'JSON payload',
|
||||
'secrets.modal.json_hint': 'Useful for generic secret payloads. The value must be valid JSON.',
|
||||
'secrets.modal.create_note': 'Creation stores encrypted plaintext and returns metadata only.',
|
||||
'secrets.modal.rotate_note': 'Rotation creates a new encrypted version and keeps the same secret id.',
|
||||
'secrets.modal.cancel': 'Cancel',
|
||||
'secrets.modal.create_action': 'Create secret',
|
||||
'secrets.modal.rotate_action': 'Rotate secret',
|
||||
'secrets.modal.creating': 'Creating…',
|
||||
'secrets.modal.rotating': 'Rotating…',
|
||||
'secrets.hint.token': 'Best for bearer tokens and simple API key values.',
|
||||
'secrets.hint.username_password': 'Stores username and password as one encrypted payload.',
|
||||
'secrets.hint.header': 'Stores a raw header value. Header name is configured in the auth profile.',
|
||||
'secrets.hint.generic': 'Stores arbitrary JSON for advanced future integrations.',
|
||||
'secrets.validation.name_required': 'Secret name is required.',
|
||||
'secrets.validation.value_required': 'Secret value is required.',
|
||||
'secrets.validation.username_password_required': 'Username and password are both required.',
|
||||
'secrets.validation.json_invalid': 'Generic secret payload must be valid JSON.',
|
||||
'secrets.profiles.title': 'Auth profile references',
|
||||
'secrets.profiles.subtitle': 'Profiles resolve secrets at runtime before upstream execution.',
|
||||
'secrets.profiles.subtitle_count': '{count} auth profiles',
|
||||
'secrets.profiles.error_title': 'Unable to load auth profile references',
|
||||
'secrets.profiles.loading_title': 'Loading auth profile references…',
|
||||
'secrets.profiles.loading_body': 'Fetching auth profiles for the current workspace.',
|
||||
'secrets.profiles.empty_title': 'No auth profiles yet',
|
||||
'secrets.profiles.empty_body': 'Create auth profiles in the next slice to bind secrets to upstream authentication.',
|
||||
'secrets.profiles.references': 'Referenced secrets',
|
||||
'secrets.profiles.reference_count': '{count} refs',
|
||||
'secrets.profiles.meta.created': 'Created',
|
||||
'secrets.profiles.meta.updated': 'Updated',
|
||||
'secrets.profiles.summary_bearer': 'Bearer auth via {header} using {secret}.',
|
||||
'secrets.profiles.summary_basic': 'Basic auth using {username} and {password}.',
|
||||
'secrets.profiles.summary_api_key_header': 'API key header {header} using {secret}.',
|
||||
'secrets.profiles.summary_api_key_query': 'API key query param {param} using {secret}.',
|
||||
'secrets.profiles.summary_unknown': 'Unknown auth profile configuration.',
|
||||
'secrets.auth_kind.bearer': 'Bearer auth',
|
||||
'secrets.auth_kind.basic': 'Basic auth',
|
||||
'secrets.auth_kind.api_key_header': 'API key header',
|
||||
'secrets.auth_kind.api_key_query': 'API key query',
|
||||
|
||||
// Logs page
|
||||
'logs.title': 'Logs',
|
||||
'logs.subtitle': 'Real-time invocation log for all operations in this workspace.',
|
||||
@@ -797,6 +889,7 @@ var TRANSLATIONS = {
|
||||
'nav.operations': 'Операции',
|
||||
'nav.agents': 'Агенты',
|
||||
'nav.apikeys': 'API Ключи',
|
||||
'nav.secrets': 'Секреты',
|
||||
'nav.logs': 'Логи',
|
||||
'nav.usage': 'Использование',
|
||||
'nav.settings': 'Настройки',
|
||||
@@ -945,6 +1038,97 @@ var TRANSLATIONS = {
|
||||
'apikeys.action.delete': 'Удалить',
|
||||
'apikeys.creating': 'Создание…',
|
||||
|
||||
// Secrets page
|
||||
'secrets.title': 'Секреты',
|
||||
'secrets.subtitle': 'Зашифрованные upstream-учетные данные для bearer token, basic auth и API key, которые используют auth profiles.',
|
||||
'secrets.new': 'Создать секрет',
|
||||
'secrets.callout.title': 'Plaintext секрета доступен только на запись.',
|
||||
'secrets.callout.body': 'Crank шифрует secret values мастер-ключом воркспейса. После создания или ротации API возвращает только metadata, поэтому эта страница сфокусирована на lifecycle и usage references.',
|
||||
'secrets.active.title': 'Секреты воркспейса',
|
||||
'secrets.active.subtitle': '{active} активных · {total} всего',
|
||||
'secrets.search': 'Фильтр секретов…',
|
||||
'secrets.th.name': 'НАЗВАНИЕ',
|
||||
'secrets.th.kind': 'ТИП',
|
||||
'secrets.th.version': 'ВЕРСИЯ',
|
||||
'secrets.th.last_used': 'ПОСЛЕДНЕЕ ИСПОЛЬЗОВАНИЕ',
|
||||
'secrets.th.used_by': 'ИСПОЛЬЗУЕТСЯ В',
|
||||
'secrets.th.status': 'СТАТУС',
|
||||
'secrets.kind.token': 'Токен',
|
||||
'secrets.kind.username_password': 'Логин/пароль',
|
||||
'secrets.kind.header': 'Значение заголовка',
|
||||
'secrets.kind.generic': 'Общий JSON',
|
||||
'secrets.status.active': 'Активен',
|
||||
'secrets.status.disabled': 'Отключен',
|
||||
'secrets.last_used.never': 'Никогда',
|
||||
'secrets.used_by_count': '{count} профилей',
|
||||
'secrets.loading': 'Загрузка…',
|
||||
'secrets.empty.none': 'Секретов пока нет',
|
||||
'secrets.empty.search': 'Нет секретов по текущему поиску',
|
||||
'secrets.error.workspace': 'Воркспейс не выбран',
|
||||
'secrets.error.load': 'Не удалось загрузить секреты',
|
||||
'secrets.action.rotate': 'Ротировать',
|
||||
'secrets.action.delete': 'Удалить',
|
||||
'secrets.confirm.delete': 'Удалить секрет {name}? Это нельзя сделать, пока на секрет ссылается auth profile.',
|
||||
'secrets.toast.create_title': 'Секрет создан',
|
||||
'secrets.toast.create_message': 'Секрет сохранен в зашифрованном виде. Повторно посмотреть plaintext через API нельзя.',
|
||||
'secrets.toast.create_error_title': 'Не удалось создать секрет',
|
||||
'secrets.toast.create_error_message': 'Не удалось создать секрет',
|
||||
'secrets.toast.rotate_title': 'Секрет ротирован',
|
||||
'secrets.toast.rotate_message': 'Новая версия секрета теперь активна.',
|
||||
'secrets.toast.rotate_error_title': 'Не удалось ротировать секрет',
|
||||
'secrets.toast.rotate_error_message': 'Не удалось ротировать секрет',
|
||||
'secrets.toast.delete_title': 'Секрет удален',
|
||||
'secrets.toast.delete_message': 'Секрет {name} удален.',
|
||||
'secrets.toast.delete_error_title': 'Не удалось удалить секрет',
|
||||
'secrets.toast.delete_error_message': 'Не удалось удалить секрет',
|
||||
'secrets.modal.create_title': 'Создать секрет',
|
||||
'secrets.modal.rotate_title': 'Ротировать секрет',
|
||||
'secrets.modal.name': 'Имя секрета',
|
||||
'secrets.modal.name_hint': 'Используйте стабильную операторскую метку. Plaintext после сохранения не возвращается.',
|
||||
'secrets.modal.kind': 'Тип секрета',
|
||||
'secrets.modal.value': 'Значение секрета',
|
||||
'secrets.modal.header_value': 'Значение заголовка',
|
||||
'secrets.modal.username': 'Логин',
|
||||
'secrets.modal.password': 'Пароль',
|
||||
'secrets.modal.json_payload': 'JSON payload',
|
||||
'secrets.modal.json_hint': 'Подходит для общих secret payloads. Значение должно быть валидным JSON.',
|
||||
'secrets.modal.create_note': 'Создание сохраняет зашифрованный plaintext и возвращает только metadata.',
|
||||
'secrets.modal.rotate_note': 'Ротация создает новую зашифрованную версию и сохраняет тот же secret id.',
|
||||
'secrets.modal.cancel': 'Отмена',
|
||||
'secrets.modal.create_action': 'Создать секрет',
|
||||
'secrets.modal.rotate_action': 'Ротировать секрет',
|
||||
'secrets.modal.creating': 'Создание…',
|
||||
'secrets.modal.rotating': 'Ротация…',
|
||||
'secrets.hint.token': 'Лучший вариант для bearer tokens и простых API key values.',
|
||||
'secrets.hint.username_password': 'Хранит логин и пароль как один зашифрованный payload.',
|
||||
'secrets.hint.header': 'Хранит сырое значение заголовка. Имя заголовка задается в auth profile.',
|
||||
'secrets.hint.generic': 'Хранит произвольный JSON для advanced future integrations.',
|
||||
'secrets.validation.name_required': 'Нужно указать имя секрета.',
|
||||
'secrets.validation.value_required': 'Нужно указать значение секрета.',
|
||||
'secrets.validation.username_password_required': 'Нужно указать и логин, и пароль.',
|
||||
'secrets.validation.json_invalid': 'Generic secret payload должен быть валидным JSON.',
|
||||
'secrets.profiles.title': 'Ссылки auth profiles',
|
||||
'secrets.profiles.subtitle': 'Профили резолвят секреты в runtime перед upstream execution.',
|
||||
'secrets.profiles.subtitle_count': '{count} auth profiles',
|
||||
'secrets.profiles.error_title': 'Не удалось загрузить ссылки auth profiles',
|
||||
'secrets.profiles.loading_title': 'Загрузка ссылок auth profiles…',
|
||||
'secrets.profiles.loading_body': 'Получаем auth profiles для текущего воркспейса.',
|
||||
'secrets.profiles.empty_title': 'Auth profiles пока нет',
|
||||
'secrets.profiles.empty_body': 'В следующем срезе появится UI для привязки секретов к upstream authentication через auth selector.',
|
||||
'secrets.profiles.references': 'Связанные секреты',
|
||||
'secrets.profiles.reference_count': '{count} ссылок',
|
||||
'secrets.profiles.meta.created': 'Создан',
|
||||
'secrets.profiles.meta.updated': 'Обновлен',
|
||||
'secrets.profiles.summary_bearer': 'Bearer auth через {header} с использованием {secret}.',
|
||||
'secrets.profiles.summary_basic': 'Basic auth с использованием {username} и {password}.',
|
||||
'secrets.profiles.summary_api_key_header': 'API key header {header} с использованием {secret}.',
|
||||
'secrets.profiles.summary_api_key_query': 'API key query param {param} с использованием {secret}.',
|
||||
'secrets.profiles.summary_unknown': 'Неизвестная конфигурация auth profile.',
|
||||
'secrets.auth_kind.bearer': 'Bearer auth',
|
||||
'secrets.auth_kind.basic': 'Basic auth',
|
||||
'secrets.auth_kind.api_key_header': 'API key header',
|
||||
'secrets.auth_kind.api_key_query': 'API key query',
|
||||
|
||||
// Logs page
|
||||
'logs.title': 'Логи',
|
||||
'logs.subtitle': 'Живой журнал вызовов по всем операциям этого воркспейса.',
|
||||
|
||||
Reference in New Issue
Block a user