From 2b2ff9214655da46811a27dced102d95fb141fbb Mon Sep 17 00:00:00 2001 From: github-ops Date: Sat, 27 Jun 2026 07:12:04 +0000 Subject: [PATCH] Remove approval confirmation copy --- .../src/service/operation_validation.rs | 22 ------------- .../catalog_access/approval_access.rs | 12 ++----- apps/ui/css/wizard.css | 31 ------------------- apps/ui/html/wizard/step3-rest.html | 18 ----------- apps/ui/js/i18n.js | 14 --------- apps/ui/js/logs.js | 8 +---- apps/ui/js/wizard-live.js | 14 --------- apps/ui/tests/e2e/wizard.spec.js | 8 ----- crates/crank-community-mcp/src/app.rs | 4 --- crates/crank-core/src/approval.rs | 2 -- crates/crank-core/src/operation.rs | 2 -- crates/crank-registry/src/migrations.rs | 9 ++++-- .../crank-registry/src/postgres/approval.rs | 26 ++-------------- .../tests/integration/workspace_access.rs | 2 -- 14 files changed, 13 insertions(+), 159 deletions(-) diff --git a/apps/admin-api/src/service/operation_validation.rs b/apps/admin-api/src/service/operation_validation.rs index 2bb58a3..711771d 100644 --- a/apps/admin-api/src/service/operation_validation.rs +++ b/apps/admin-api/src/service/operation_validation.rs @@ -125,24 +125,6 @@ pub(super) fn validate_approval_policy( )); } - if policy.confirmation_title.trim().is_empty() { - return Err(ApiError::validation_with_context( - "approval confirmation title is required".to_owned(), - json!({ - "field": "execution_config.approval_policy.confirmation_title", - }), - )); - } - - if policy.confirmation_body_template.trim().is_empty() { - return Err(ApiError::validation_with_context( - "approval confirmation body is required".to_owned(), - json!({ - "field": "execution_config.approval_policy.confirmation_body_template", - }), - )); - } - Ok(()) } @@ -291,8 +273,6 @@ mod tests { config.approval_policy = Some(OperationApprovalPolicy { required: true, risk_level: OperationApprovalRiskLevel::Dangerous, - confirmation_title: "Подтвердите действие".to_owned(), - confirmation_body_template: "Выполнить действие?".to_owned(), ttl_seconds: 300, show_payload_preview: true, payload_preview_mode: OperationApprovalPayloadPreviewMode::MaskedJson, @@ -307,8 +287,6 @@ mod tests { config.approval_policy = Some(OperationApprovalPolicy { required: true, risk_level: OperationApprovalRiskLevel::Dangerous, - confirmation_title: "".to_owned(), - confirmation_body_template: "Выполнить действие?".to_owned(), ttl_seconds: 0, show_payload_preview: true, payload_preview_mode: OperationApprovalPayloadPreviewMode::MaskedJson, diff --git a/apps/mcp-server/tests/integration/catalog_access/approval_access.rs b/apps/mcp-server/tests/integration/catalog_access/approval_access.rs index 22d5dd3..fcf0307 100644 --- a/apps/mcp-server/tests/integration/catalog_access/approval_access.rs +++ b/apps/mcp-server/tests/integration/catalog_access/approval_access.rs @@ -23,8 +23,6 @@ async fn approval_key_lists_and_decides_pending_requests() { operation_version: 1, status: ApprovalRequestStatus::Pending, risk_level: OperationApprovalRiskLevel::Dangerous, - confirmation_title: "Подтвердите создание лида".to_owned(), - confirmation_body: "Проверьте email перед отправкой в CRM.".to_owned(), request_payload: json!({"email": "ada@example.com"}), response_payload: None, created_at: OffsetDateTime::now_utc(), @@ -79,8 +77,8 @@ async fn approval_key_lists_and_decides_pending_requests() { let pending_body = pending.json::().await.unwrap(); assert_eq!(pending_body["items"].as_array().unwrap().len(), 1); assert_eq!( - pending_body["items"][0]["approval"]["confirmation_title"], - "Подтвердите создание лида" + pending_body["items"][0]["approval"]["request_payload"], + json!({"email": "ada@example.com"}) ); let approve_url = format!( @@ -196,8 +194,6 @@ async fn approval_key_denies_without_executing_upstream() { operation_version: 1, status: ApprovalRequestStatus::Pending, risk_level: OperationApprovalRiskLevel::Dangerous, - confirmation_title: "Подтвердите создание лида".to_owned(), - confirmation_body: "Проверьте email перед отправкой в CRM.".to_owned(), request_payload: json!({"email": "deny@example.com"}), response_payload: None, created_at: OffsetDateTime::now_utc(), @@ -295,8 +291,6 @@ async fn approval_key_expires_without_executing_upstream() { operation_version: 1, status: ApprovalRequestStatus::Pending, risk_level: OperationApprovalRiskLevel::Dangerous, - confirmation_title: "Подтвердите создание лида".to_owned(), - confirmation_body: "Проверьте email перед отправкой в CRM.".to_owned(), request_payload: json!({"email": "expired@example.com"}), response_payload: None, created_at: OffsetDateTime::now_utc() - time::Duration::minutes(10), @@ -366,8 +360,6 @@ async fn tool_call_with_approval_policy_creates_pending_request() { operation.execution_config.approval_policy = Some(OperationApprovalPolicy { required: true, risk_level: OperationApprovalRiskLevel::Dangerous, - confirmation_title: "Подтвердите создание лида".to_owned(), - confirmation_body_template: "Проверьте email перед отправкой в CRM.".to_owned(), ttl_seconds: 300, show_payload_preview: true, payload_preview_mode: OperationApprovalPayloadPreviewMode::MaskedJson, diff --git a/apps/ui/css/wizard.css b/apps/ui/css/wizard.css index d07114a..4addd82 100644 --- a/apps/ui/css/wizard.css +++ b/apps/ui/css/wizard.css @@ -1138,37 +1138,6 @@ justify-content: center; } -.approval-preview-card { - display: grid; - gap: 6px; - padding: 14px 16px; - border: 1px solid rgba(47, 129, 247, 0.28); - border-radius: 10px; - background: - linear-gradient(135deg, rgba(47, 129, 247, 0.12), rgba(35, 134, 54, 0.06)), - var(--bg-overlay); -} - -.approval-preview-eyebrow { - font-size: 11px; - font-weight: 700; - letter-spacing: 0.04em; - text-transform: uppercase; - color: var(--accent); -} - -.approval-preview-title { - font-size: 14px; - font-weight: 700; - color: var(--text-primary); -} - -.approval-preview-body { - font-size: 12.5px; - line-height: 1.6; - color: var(--text-secondary); -} - /* ══════════════════════════════════════════════════ BOTTOM ACTION BAR — frosted dark glass ══════════════════════════════════════════════════ */ diff --git a/apps/ui/html/wizard/step3-rest.html b/apps/ui/html/wizard/step3-rest.html index e2172b7..877cd7b 100644 --- a/apps/ui/html/wizard/step3-rest.html +++ b/apps/ui/html/wizard/step3-rest.html @@ -123,18 +123,6 @@ -
- - -
Этот текст увидит внешний интерфейс подтверждения.
-
- -
- - -
Коротко объясните, что произойдет после подтверждения.
-
-
- -
-
Предпросмотр для интерфейса подтверждения
-
Подтвердите выполнение операции
-
Проверьте параметры операции и подтвердите выполнение.
-
diff --git a/apps/ui/js/i18n.js b/apps/ui/js/i18n.js index 48552d3..f40fc31 100644 --- a/apps/ui/js/i18n.js +++ b/apps/ui/js/i18n.js @@ -599,17 +599,10 @@ var TRANSLATIONS = { 'wizard.approval.required_label': 'Require confirmation before execution', 'wizard.approval.required_desc': 'The MCP client receives a pending request, and the action runs only after confirmation through a separate approval endpoint.', 'wizard.approval.ttl': 'How long to wait for confirmation', - 'wizard.approval.confirmation_title': 'Confirmation title', - 'wizard.approval.confirmation_title_hint': 'This text will be shown by the external confirmation interface.', - 'wizard.approval.confirmation_body': 'Description for the user', - 'wizard.approval.confirmation_body_hint': 'Explain briefly what will happen after confirmation.', 'wizard.approval.show_payload': 'Show request parameters', 'wizard.approval.payload_mode': 'How to show parameters', 'wizard.approval.payload.summary': 'Short summary', 'wizard.approval.payload.masked_json': 'JSON with masked secrets', - 'wizard.approval.preview_label': 'Preview for confirmation UI', - 'wizard.approval.default_title': 'Confirm operation execution', - 'wizard.approval.default_body': 'Review operation parameters and confirm execution.', 'wizard.step5.security_level_title': 'Operation security', 'wizard.step5.community_security_note': '', 'wizard.step5.live_title': 'Check and publish', @@ -1461,17 +1454,10 @@ var TRANSLATIONS = { 'wizard.approval.required_label': 'Требовать подтверждение перед выполнением', 'wizard.approval.required_desc': 'MCP клиент получит ожидающий запрос, а действие выполнится только после подтверждения через отдельный эндпоинт подтверждения.', 'wizard.approval.ttl': 'Сколько ждать подтверждение', - 'wizard.approval.confirmation_title': 'Заголовок подтверждения', - 'wizard.approval.confirmation_title_hint': 'Этот текст увидит внешний интерфейс подтверждения.', - 'wizard.approval.confirmation_body': 'Описание для пользователя', - 'wizard.approval.confirmation_body_hint': 'Коротко объясните, что произойдет после подтверждения.', 'wizard.approval.show_payload': 'Показывать параметры запроса', 'wizard.approval.payload_mode': 'Как показывать параметры', 'wizard.approval.payload.summary': 'Краткое описание', 'wizard.approval.payload.masked_json': 'JSON с маскированием секретов', - 'wizard.approval.preview_label': 'Предпросмотр для интерфейса подтверждения', - 'wizard.approval.default_title': 'Подтвердите выполнение операции', - 'wizard.approval.default_body': 'Проверьте параметры операции и подтвердите выполнение.', 'wizard.step5.security_level_title': 'Защита операции', 'wizard.step5.community_security_note': '', 'wizard.step5.live_title': 'Проверка и публикация', diff --git a/apps/ui/js/logs.js b/apps/ui/js/logs.js index 534d05a..db55fb1 100644 --- a/apps/ui/js/logs.js +++ b/apps/ui/js/logs.js @@ -138,8 +138,6 @@ document.addEventListener('DOMContentLoaded', function () { operationVersion: approval.operation_version, status: approval.status, riskLevel: approval.risk_level, - title: approval.confirmation_title, - body: approval.confirmation_body, requestPayload: approval.request_payload, responsePayload: approval.response_payload, createdAt: approval.created_at, @@ -186,7 +184,7 @@ document.addEventListener('DOMContentLoaded', function () { var header = element('div', 'approval-item-header'); var titleWrap = element('div', 'approval-item-title-wrap'); - titleWrap.appendChild(element('div', 'approval-item-title', item.title || tKey('approvals.untitled'))); + titleWrap.appendChild(element('div', 'approval-item-title', tKey('approvals.untitled') + ' ' + item.id)); var meta = element('div', 'approval-item-meta'); meta.textContent = [ @@ -200,10 +198,6 @@ document.addEventListener('DOMContentLoaded', function () { header.appendChild(badge); card.appendChild(header); - if (item.body) { - card.appendChild(element('p', 'approval-item-body', item.body)); - } - var timing = element('div', 'approval-timing'); timing.textContent = item.status === 'pending' ? tKey('approvals.expires_at') + ': ' + formatDateTime(item.expiresAt) diff --git a/apps/ui/js/wizard-live.js b/apps/ui/js/wizard-live.js index f8b7270..314030b 100644 --- a/apps/ui/js/wizard-live.js +++ b/apps/ui/js/wizard-live.js @@ -41,14 +41,9 @@ function normalizeApprovalTtlSeconds(value) { function buildApprovalPolicy() { if (!checkedValue('approval-required')) return null; - var title = textValue('approval-title') || tKey('wizard.approval.default_title'); - var body = textValue('approval-body') || tKey('wizard.approval.default_body'); - return { required: true, risk_level: 'normal', - confirmation_title: title, - confirmation_body_template: body, ttl_seconds: normalizeApprovalTtlSeconds(textValue('approval-ttl-seconds')), show_payload_preview: checkedValue('approval-show-payload-preview'), payload_preview_mode: textValue('approval-payload-preview-mode') || 'summary', @@ -192,8 +187,6 @@ function setApprovalPolicyEditor(policy) { var required = document.getElementById('approval-required'); if (required) required.checked = enabled; setValue('approval-ttl-seconds', policy && policy.ttl_seconds ? String(policy.ttl_seconds) : '300'); - setValue('approval-title', policy && policy.confirmation_title ? policy.confirmation_title : tKey('wizard.approval.default_title')); - setValue('approval-body', policy && policy.confirmation_body_template ? policy.confirmation_body_template : tKey('wizard.approval.default_body')); var showPayload = document.getElementById('approval-show-payload-preview'); if (showPayload) { showPayload.checked = !policy || policy.show_payload_preview !== false; @@ -208,19 +201,12 @@ function updateApprovalPolicyUi() { var fields = document.getElementById('approval-config-fields'); if (toggle) toggle.classList.toggle('on', enabled); if (fields) fields.hidden = !enabled; - - var title = textValue('approval-title') || tKey('wizard.approval.default_title'); - var body = textValue('approval-body') || tKey('wizard.approval.default_body'); - setTextContent('approval-preview-title', title); - setTextContent('approval-preview-body', body); } function bindApprovalPolicyControls() { [ 'approval-required', 'approval-ttl-seconds', - 'approval-title', - 'approval-body', 'approval-show-payload-preview', 'approval-payload-preview-mode', ].forEach(function(id) { diff --git a/apps/ui/tests/e2e/wizard.spec.js b/apps/ui/tests/e2e/wizard.spec.js index 52f3b0e..9b2ce21 100644 --- a/apps/ui/tests/e2e/wizard.spec.js +++ b/apps/ui/tests/e2e/wizard.spec.js @@ -553,8 +553,6 @@ test('wizard shows agent-facing MCP preview from current draft fields', async ({ approval_policy: { required: true, risk_level: 'financial', - confirmation_title: 'Подтвердите обмен валюты', - confirmation_body_template: 'Проверьте валюты и подтвердите выполнение операции.', ttl_seconds: 180, show_payload_preview: true, payload_preview_mode: 'masked_json', @@ -777,8 +775,6 @@ test('wizard edit mode preserves explicit request mapping targets on save', asyn approval_policy: { required: true, risk_level: 'financial', - confirmation_title: 'Подтвердите обмен валюты', - confirmation_body_template: 'Проверьте валюты и подтвердите выполнение операции.', ttl_seconds: 180, show_payload_preview: true, payload_preview_mode: 'masked_json', @@ -833,8 +829,6 @@ test('wizard edit mode preserves explicit request mapping targets on save', asyn await expect(page.locator('#approval-config-fields')).toBeVisible(); await expect(page.locator('#approval-risk-level')).toHaveCount(0); await expect(page.locator('#approval-ttl-seconds')).toHaveValue('180'); - await expect(page.locator('#approval-title')).toHaveValue('Подтвердите обмен валюты'); - await expect(page.locator('#approval-body')).toHaveValue('Проверьте валюты и подтвердите выполнение операции.'); await expect(page.locator('#approval-payload-preview-mode')).toHaveValue('masked_json'); await page.locator('.btn-save-draft').click(); await expect.poll(() => updatePayload).not.toBeNull(); @@ -864,8 +858,6 @@ test('wizard edit mode preserves explicit request mapping targets on save', asyn approval_policy: { required: true, risk_level: 'normal', - confirmation_title: 'Подтвердите обмен валюты', - confirmation_body_template: 'Проверьте валюты и подтвердите выполнение операции.', ttl_seconds: 180, show_payload_preview: true, payload_preview_mode: 'masked_json', diff --git a/crates/crank-community-mcp/src/app.rs b/crates/crank-community-mcp/src/app.rs index 164f542..3c3234d 100644 --- a/crates/crank-community-mcp/src/app.rs +++ b/crates/crank-community-mcp/src/app.rs @@ -1086,8 +1086,6 @@ async fn maybe_create_pending_approval( }, "expires_at": expires_at, "risk_level": policy.risk_level, - "confirmation_title": policy.confirmation_title, - "confirmation_body": policy.confirmation_body_template, "payload_preview": if policy.show_payload_preview { arguments.clone() } else { @@ -1102,8 +1100,6 @@ async fn maybe_create_pending_approval( operation_version: tool.operation.version, status: ApprovalRequestStatus::Pending, risk_level: policy.risk_level, - confirmation_title: policy.confirmation_title.clone(), - confirmation_body: policy.confirmation_body_template.clone(), request_payload: arguments.clone(), response_payload: None, created_at: now, diff --git a/crates/crank-core/src/approval.rs b/crates/crank-core/src/approval.rs index e651b44..e1f6863 100644 --- a/crates/crank-core/src/approval.rs +++ b/crates/crank-core/src/approval.rs @@ -26,8 +26,6 @@ pub struct ApprovalRequest { pub operation_version: u32, pub status: ApprovalRequestStatus, pub risk_level: OperationApprovalRiskLevel, - pub confirmation_title: String, - pub confirmation_body: String, pub request_payload: Value, pub response_payload: Option, #[serde(with = "time::serde::rfc3339")] diff --git a/crates/crank-core/src/operation.rs b/crates/crank-core/src/operation.rs index b06b736..626579a 100644 --- a/crates/crank-core/src/operation.rs +++ b/crates/crank-core/src/operation.rs @@ -125,8 +125,6 @@ pub enum OperationApprovalPayloadPreviewMode { pub struct OperationApprovalPolicy { pub required: bool, pub risk_level: OperationApprovalRiskLevel, - pub confirmation_title: String, - pub confirmation_body_template: String, pub ttl_seconds: u32, pub show_payload_preview: bool, pub payload_preview_mode: OperationApprovalPayloadPreviewMode, diff --git a/crates/crank-registry/src/migrations.rs b/crates/crank-registry/src/migrations.rs index a9c7a9d..d5bceac 100644 --- a/crates/crank-registry/src/migrations.rs +++ b/crates/crank-registry/src/migrations.rs @@ -568,8 +568,6 @@ pub async fn apply_postgres(pool: &PgPool) -> Result<(), sqlx::Error> { operation_version integer not null, status text not null, risk_level text not null, - confirmation_title text not null, - confirmation_body text not null, request_payload_json jsonb not null, response_payload_json jsonb null, created_at timestamptz not null, @@ -581,6 +579,13 @@ pub async fn apply_postgres(pool: &PgPool) -> Result<(), sqlx::Error> { ) .execute(pool) .await?; + + query("alter table approval_requests drop column if exists confirmation_title") + .execute(pool) + .await?; + query("alter table approval_requests drop column if exists confirmation_body") + .execute(pool) + .await?; query( "create index if not exists approval_requests_agent_status_idx on approval_requests(workspace_id, agent_id, status, expires_at)", diff --git a/crates/crank-registry/src/postgres/approval.rs b/crates/crank-registry/src/postgres/approval.rs index 2662ef3..2739ba7 100644 --- a/crates/crank-registry/src/postgres/approval.rs +++ b/crates/crank-registry/src/postgres/approval.rs @@ -14,8 +14,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -24,9 +22,9 @@ impl PostgresRegistry { decided_by_key_id, decision_note ) values ( - $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, - $11, $12::timestamptz, $13::timestamptz, $14::timestamptz, - $15, $16 + $1, $2, $3, $4, $5, $6, $7, $8, + $9, $10::timestamptz, $11::timestamptz, $12::timestamptz, + $13, $14 )", ) .bind(request.approval.id.as_str()) @@ -42,8 +40,6 @@ impl PostgresRegistry { &request.approval.risk_level, "approval_risk_level", )?) - .bind(&request.approval.confirmation_title) - .bind(&request.approval.confirmation_body) .bind(Json(&request.approval.request_payload)) .bind(request.approval.response_payload.as_ref().map(Json)) .bind(request.approval.created_at) @@ -77,8 +73,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -116,8 +110,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -157,8 +149,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -195,8 +185,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -241,8 +229,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -286,8 +272,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -328,8 +312,6 @@ impl PostgresRegistry { operation_version, status, risk_level, - confirmation_title, - confirmation_body, request_payload_json, response_payload_json, created_at, @@ -362,8 +344,6 @@ fn map_approval_request_row(row: PgRow) -> Result("risk_level"), "approval_risk_level", )?, - confirmation_title: row.get("confirmation_title"), - confirmation_body: row.get("confirmation_body"), request_payload: row.get::("request_payload_json"), response_payload: row.get::, _>("response_payload_json"), created_at: row.get("created_at"), diff --git a/crates/crank-registry/tests/integration/workspace_access.rs b/crates/crank-registry/tests/integration/workspace_access.rs index 0558843..2fffcb7 100644 --- a/crates/crank-registry/tests/integration/workspace_access.rs +++ b/crates/crank-registry/tests/integration/workspace_access.rs @@ -487,8 +487,6 @@ async fn manages_approval_request_lifecycle() { operation_version: 1, status: ApprovalRequestStatus::Pending, risk_level: OperationApprovalRiskLevel::Dangerous, - confirmation_title: "Confirm action".to_owned(), - confirmation_body: "Check payload before running.".to_owned(), request_payload: json!({"amount": 100}), response_payload: None, created_at: timestamp("2026-03-25T12:01:00Z"),