наблюдаемость: завершить базовый контур Community
CI / Rust Checks (push) Failing after 4m28s
CI / UI Checks (push) Has been skipped
CI / Frontend E2E (push) Has been skipped
CI / Community Image Smoke (push) Has been skipped
CI / Deploy (push) Has been skipped

Добавить структурированные журналы, метрики, трассировку и безопасный канал критических ошибок. Усилить границы рантайма, тесты, проверку зависимостей и сценарии развёртывания.
This commit is contained in:
2026-07-31 01:01:14 +03:00
parent 99bd05c145
commit 0e8f1ca03a
160 changed files with 13506 additions and 1499 deletions
+2 -2
View File
@@ -97,8 +97,8 @@
</div>
<div class="danger-zone-action">
<div class="danger-zone-text">
<div class="danger-zone-title" data-i18n="workspace_setup.danger.export_title">Export all data</div>
<div class="danger-zone-desc" data-i18n="workspace_setup.danger.export_body">Download a JSON snapshot of workspace settings, operations, agents, secrets, usage data and agent access keys.</div>
<div class="danger-zone-title" data-i18n="workspace_setup.danger.export_title">Export workspace catalog</div>
<div class="danger-zone-desc" data-i18n="workspace_setup.danger.export_body">Download a non-restorable JSON catalog of workspace settings, operation summaries, agent summaries and API key metadata.</div>
</div>
<button class="btn-danger" id="export-workspace-btn" type="button" data-i18n="workspace_setup.export">Export</button>
</div>
+4 -4
View File
@@ -442,8 +442,8 @@ var TRANSLATIONS = {
'workspace_setup.create.subtitle': 'This Community installation uses one workspace for MCP operations and agents.',
'workspace_setup.create.footer': 'This Community installation uses one workspace.',
'workspace_setup.danger.title': 'Danger zone',
'workspace_setup.danger.export_title': 'Export all data',
'workspace_setup.danger.export_body': 'Download a JSON snapshot of workspace settings, operations, agents, secrets, usage data and agent access keys.',
'workspace_setup.danger.export_title': 'Export workspace catalog',
'workspace_setup.danger.export_body': 'Download a non-restorable JSON catalog of workspace settings, operation summaries, agent summaries and API key metadata.',
'workspace_setup.export': 'Export',
'workspace_setup.role.owner': 'Owner',
'workspace_setup.role.admin': 'Admin',
@@ -1334,8 +1334,8 @@ var TRANSLATIONS = {
'workspace_setup.create.subtitle': 'В Community используется один воркспейс для MCP-операций и агентов.',
'workspace_setup.create.footer': 'В Community используется один воркспейс.',
'workspace_setup.danger.title': 'Опасная зона',
'workspace_setup.danger.export_title': 'Экспортировать все данные',
'workspace_setup.danger.export_body': 'Скачать JSON-снимок настроек воркспейса, операций, агентов, секретов, данных использования и ключей доступа агентов.',
'workspace_setup.danger.export_title': 'Экспорт каталога рабочего пространства',
'workspace_setup.danger.export_body': 'Скачать невосстанавливаемый JSON-каталог настроек рабочего пространства, сводок операций и агентов, а также метаданных ключей API.',
'workspace_setup.export': 'Экспорт',
'workspace_setup.role.owner': 'Владелец',
'workspace_setup.role.admin': 'Администратор',
+40 -4
View File
@@ -8,6 +8,8 @@ document.addEventListener('DOMContentLoaded', function () {
openId: null,
liveMode: true,
timer: null,
searchTimer: null,
refreshPromise: null,
workspaceId: null,
loading: false,
loadError: '',
@@ -457,7 +459,13 @@ document.addEventListener('DOMContentLoaded', function () {
}
async function refreshOperationalData() {
await Promise.all([loadLogs(), loadApprovals()]);
if (state.refreshPromise) {
return state.refreshPromise;
}
state.refreshPromise = Promise.all([loadLogs(), loadApprovals()]).finally(function () {
state.refreshPromise = null;
});
return state.refreshPromise;
}
async function loadLogDetail(logId) {
@@ -494,10 +502,14 @@ document.addEventListener('DOMContentLoaded', function () {
function startPolling() {
stopPolling();
if (!state.liveMode) {
if (!state.liveMode || document.hidden) {
return;
}
state.timer = setInterval(refreshOperationalData, 4000);
state.timer = setTimeout(async function poll() {
state.timer = null;
await refreshOperationalData();
startPolling();
}, 4000);
}
function toggleLive() {
@@ -526,7 +538,13 @@ document.addEventListener('DOMContentLoaded', function () {
if (logSearch) {
logSearch.addEventListener('input', function () {
state.search = this.value.trim();
loadLogs();
if (state.searchTimer) {
clearTimeout(state.searchTimer);
}
state.searchTimer = setTimeout(function () {
state.searchTimer = null;
loadLogs();
}, 250);
});
}
@@ -572,6 +590,24 @@ document.addEventListener('DOMContentLoaded', function () {
refreshOperationalData();
});
document.addEventListener('visibilitychange', function () {
if (document.hidden) {
stopPolling();
return;
}
if (state.liveMode) {
refreshOperationalData().finally(startPolling);
}
});
window.addEventListener('pagehide', function () {
stopPolling();
if (state.searchTimer) {
clearTimeout(state.searchTimer);
state.searchTimer = null;
}
});
setLiveState();
startPolling();
+1 -1
View File
@@ -196,7 +196,7 @@ async function exportWorkspaceSnapshot() {
var slug = workspaceFormState.workspaceRecord && workspaceFormState.workspaceRecord.workspace
? workspaceFormState.workspaceRecord.workspace.slug
: tKey('settings.nav.workspace');
downloadJsonFile(slug + '-snapshot.json', snapshot);
downloadJsonFile(slug + '-catalog-snapshot.json', snapshot);
} catch (error) {
if (window.CrankUi) {
window.CrankUi.error(error.message || tKey('workspace_setup.export_error'), tKey('workspace_setup.export_error_title'));
+4 -4
View File
@@ -9,7 +9,7 @@
"@fontsource/inter": "5.2.8",
"@fontsource/jetbrains-mono": "5.2.8",
"alpinejs": "3.15.12",
"js-yaml": "5.2.1"
"js-yaml": "5.2.2"
},
"devDependencies": {
"@playwright/test": "1.61.1",
@@ -580,9 +580,9 @@
}
},
"node_modules/js-yaml": {
"version": "5.2.1",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.1.tgz",
"integrity": "sha512-zfLtNfQqxVqq3uaTqSkh4x4hZw3KHobGUA0fJUj4wawW8bsQLTVqpHdXSIzidh7o+4lEW36tANuAGdaFx6Zgnw==",
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-5.2.2.tgz",
"integrity": "sha512-dayzUzKkJ1MkuUtZglSebU43utNXH0OWQByK9rKOOuYIO8M5TV1y+n8ALMdG0rdzBnfNkOmZEqrURepb0ejqBw==",
"funding": [
{
"type": "github",
+1 -1
View File
@@ -11,7 +11,7 @@
"@fontsource/inter": "5.2.8",
"@fontsource/jetbrains-mono": "5.2.8",
"alpinejs": "3.15.12",
"js-yaml": "5.2.1"
"js-yaml": "5.2.2"
},
"devDependencies": {
"@playwright/test": "1.61.1",
+3 -3
View File
@@ -161,15 +161,15 @@ test('wizard builds visual request mappings from JSON sample and path params', a
await page.goto('/wizard/');
await page.locator('[data-testid="wizard-protocol-rest"]').click();
await page.evaluate(() => window.CrankWizardShell.doGoToStep(2));
await page.evaluate(() => window.CrankWizardShell.goToStep(2));
await expect(page.locator('#step-panel-2')).toBeVisible();
await page.locator('#endpoint-path').fill('/rates/{date}');
await page.evaluate(() => window.CrankWizardShell.doGoToStep(3));
await page.evaluate(() => window.CrankWizardShell.goToStep(3));
await expect(page.locator('#step-panel-3-rest')).toBeVisible();
await page.locator('.method-card[data-method="GET"]').click();
await page.evaluate(() => window.CrankWizardShell.doGoToStep(5));
await page.evaluate(() => window.CrankWizardShell.goToStep(5));
await expect(page.locator('#step-panel-5')).toBeVisible();
await page.locator('#wizard-input-sample').fill(JSON.stringify({
@@ -11,6 +11,12 @@ test('workspace and settings pages show live session data', async ({ page }) =>
await expect(page.locator('#section-members')).toHaveCount(0);
await expect(page.locator('#section-invite')).toHaveCount(0);
await expect(page.locator('#delete-workspace-btn')).toHaveCount(0);
await expect(page.locator('[data-i18n="workspace_setup.danger.export_title"]')).toHaveText(
localized('Export workspace catalog', 'Экспорт каталога рабочего пространства'),
);
await expect(page.locator('[data-i18n="workspace_setup.danger.export_body"]')).not.toContainText(
localized('all data', 'все данные'),
);
await page.goto('/settings');
await expect(page.locator('.page-title')).toHaveText(localized('Account settings', 'Настройки аккаунта'));