This is an automated email from the ASF dual-hosted git repository.

lizhimins pushed a commit to branch rocketmq-studio
in repository https://gitbox.apache.org/repos/asf/rocketmq-dashboard.git


The following commit(s) were added to refs/heads/rocketmq-studio by this push:
     new 6df871445 fix(studio): remove k8s certificate lifecycle management 
(#3130)
6df871445 is described below

commit 6df87144557469b26d09d3004c52772762a15287
Author: aias00 <[email protected]>
AuthorDate: Mon Sep 7 14:58:25 2026 +0800

    fix(studio): remove k8s certificate lifecycle management (#3130)
    
    Signed-off-by: liuhy <[email protected]>
---
 README.md                                          |   2 +-
 README_zh.md                                       |   2 +-
 docs/api-spec.md                                   | 143 ++++++++---------
 docs/kubernetes-certificate-provider.md            | 177 ---------------------
 server/README.md                                   |   2 +-
 .../studio/cluster/k8s/K8sCertController.java      |   6 -
 .../studio/cluster/k8s/K8sCertService.java         |  22 ---
 .../rocketmq/studio/cluster/k8s/RenewCertDTO.java  |  32 ----
 .../studio/cluster/k8s/K8sCertControllerTest.java  |  13 +-
 .../studio/cluster/k8s/K8sCertServiceTest.java     |  71 ---------
 web/src/api/cluster.test.ts                        |  11 --
 web/src/api/cluster.ts                             |   5 -
 web/src/i18n/translations.ts                       |   3 +-
 .../pages/cluster/__tests__/K8sCertsPage.test.tsx  |   2 +-
 web/src/pages/cluster/certs.tsx                    |   6 +-
 web/src/pages/ops/auditPresentation.ts             |   5 -
 web/src/services/clusterService.ts                 |  18 ---
 17 files changed, 76 insertions(+), 444 deletions(-)

diff --git a/README.md b/README.md
index 4ebe26507..64bf29078 100644
--- a/README.md
+++ b/README.md
@@ -59,7 +59,7 @@ development.
 | **Dashboard** | Global statistics for clusters, brokers, topics, and 
consumer groups with TPS trends |
 | **Instances** | Multi-instance access (Proxy / Direct mode), instance CRUD |
 | **Clusters** | Cluster details, Broker / NameServer / Proxy node operations, 
hot config updates, NameServer configuration drift detection |
-| **K8s Certs** | TLS / mTLS / ServiceAccount certificate management and 
renewal |
+| **K8s Certs** | Studio-local TLS / mTLS / ServiceAccount certificate 
configuration |
 | **Topics** | Topic CRUD, route viewer, consumer list, multi-type support 
(Normal / FIFO / Delay / Transaction / Lite) |
 | **Consumer Groups** | Consumer group CRUD, consumption progress, 
subscription details, offset reset, config import/export |
 | **ACL** | ACL rules and user management, v1 / v2 dual version support |
diff --git a/README_zh.md b/README_zh.md
index fcf461372..2049a1b6c 100644
--- a/README_zh.md
+++ b/README_zh.md
@@ -49,7 +49,7 @@ cd .. && docker compose up -d --build
 | **监控面板** | 集群/ Broker / Topic / 消费组全局统计,TPS 趋势图 |
 | **实例管理** | 多实例接入(Proxy / Direct 模式),实例 CRUD |
 | **集群管理** | 集群详情、Broker / NameServer / Proxy 节点运维、集群配置热更新 |
-| **K8s 证书** | TLS / mTLS / ServiceAccount 证书管理与续期 |
+| **K8s 证书** | Studio 本地 TLS / mTLS / ServiceAccount 证书配置 |
 | **Topic 管理** | Topic CRUD、路由查看、消费者列表、多类型支持(Normal / FIFO / Delay / 
Transaction / Lite) |
 | **消费组管理** | 消费组 CRUD、消费进度、订阅详情、位点重置、配置导入导出 |
 | **ACL 权限** | ACL 规则与用户管理,支持 v1 / v2 双版本 |
diff --git a/docs/api-spec.md b/docs/api-spec.md
index 98bd46da8..e4781e1e8 100644
--- a/docs/api-spec.md
+++ b/docs/api-spec.md
@@ -61,69 +61,68 @@
 | 18 | GET | `/api/k8s-certs` | K8s 证书列表 |
 | 19 | POST | `/api/k8s-certs/create` | 添加证书 |
 | 20 | POST | `/api/k8s-certs/update` | 更新证书 |
-| 21 | POST | `/api/k8s-certs/renew` | 续期证书 |
-| 22 | POST | `/api/k8s-certs/delete` | 删除证书 |
-| 23 | GET | `/api/topics` | Topic 列表 |
-| 24 | POST | `/api/topics/create` | 创建 Topic |
-| 25 | POST | `/api/topics/update` | 更新 Topic |
-| 26 | POST | `/api/topics/delete` | 删除 Topic |
-| 27 | GET | `/api/topics/:name/routes` | Topic 路由 |
-| 28 | GET | `/api/topics/:name/consumers` | Topic 消费者 |
-| 29 | POST | `/api/topics/send` | 发送消息到 Topic |
-| 30 | GET | `/api/groups` | 消费组列表 |
-| 31 | GET | `/api/groups/:name` | 消费组详情 |
-| 32 | GET | `/api/groups/:name/progress` | 消费进度 |
-| 33 | GET | `/api/groups/:name/subscriptions` | 订阅详情 |
-| 34 | POST | `/api/groups/create` | 创建消费组 |
-| 35 | POST | `/api/groups/delete` | 删除消费组 |
-| 36 | POST | `/api/groups/reset-offset` | 重置位点 |
-| 37 | POST | `/api/groups/import` | 导入配置 |
-| 38 | GET | `/api/groups/export` | 导出配置 |
-| 39 | GET | `/api/acl/rules` | ACL 规则列表 |
-| 40 | POST | `/api/acl/rules/create` | 创建 ACL 规则 |
-| 41 | POST | `/api/acl/rules/delete` | 删除 ACL 规则 |
-| 42 | GET | `/api/acl/users` | ACL 用户列表 |
-| 43 | POST | `/api/acl/users/create` | 创建 ACL 用户 |
-| 44 | POST | `/api/acl/users/delete` | 删除 ACL 用户 |
-| 45 | GET | `/api/messages` | 消息查询 |
-| 46 | GET | `/api/messages/:msgId/trace` | 消息轨迹 |
-| 47 | GET | `/api/dlq` | 死信队列列表 |
-| 48 | POST | `/api/dlq/resend` | 重发死信 |
-| 49 | GET | `/api/clients` | 客户端连接列表 |
-| 50 | GET | `/api/alert-rules` | 告警规则列表 |
-| 51 | POST | `/api/alert-rules/create` | 创建告警规则 |
-| 52 | POST | `/api/alert-rules/update` | 更新告警规则 |
-| 53 | POST | `/api/alert-rules/toggle` | 切换启用状态 |
-| 54 | POST | `/api/alert-rules/delete` | 删除告警规则 |
-| 55 | GET | `/api/system-alerts` | 系统告警列表 |
-| 56 | POST | `/api/system-alerts/acknowledge` | 确认告警 |
-| 57 | POST | `/api/system-alerts/clear-acknowledged` | 清除已确认告警 |
-| 58 | GET | `/api/audit-logs` | 审计日志列表 |
-| 59 | GET | `/api/audit-logs/filter-options` | 审计日志筛选项 |
-| 60 | GET | `/api/audit-logs/export` | 导出审计日志 |
-| 61 | POST | `/api/audit-logs/cleanup` | 清理审计日志 |
-| 62 | GET | `/api/settings/general` | 获取通用设置 |
-| 63 | POST | `/api/settings/general/save` | 保存通用设置 |
-| 64 | GET | `/api/settings/datasources` | 数据源选择器列表(未分页) |
-| 65 | GET | `/api/settings/datasources/page` | 分页数据源列表 |
-| 66 | POST | `/api/settings/datasources/create` | 创建数据源 |
-| 67 | POST | `/api/settings/datasources/update` | 更新数据源 |
-| 68 | POST | `/api/settings/datasources/delete` | 删除数据源 |
-| 69 | POST | `/api/settings/datasources/test` | 测试数据源连接 |
-| 70 | POST | `/api/ai/chat` | AI 对话(SSE) |
-| 71 | POST | `/api/ai/execute` | 执行 AI 指令 |
-| 72 | GET | `/api/ai/tools` | 可用工具列表 |
-| 73 | POST | `/api/ai/tools/:name/execute` | 执行只读 AI 工具 |
-| 74 | POST | `/api/metrics/query` | 查询监控指标数据 |
-| 75 | GET | `/api/acl/cluster-config` | 集群 ACL 配置概要(存储级) |
-| 76 | POST | `/api/acl/plain-access-config` | 创建/更新 Plain Access 账号 |
-| 77 | GET | `/api/acl/users/:id/credentials` | 查看单个用户明文凭证 |
-| 78 | GET | `/api/metrics/grafana/dashboards` | Grafana 看板列表 |
-| 79 | GET | `/api/metrics/grafana/dashboards/:uid` | Grafana 看板 JSON 模型 |
-| 80 | GET | `/api/metrics/grafana/dashboards/:uid/export` | 导出单个 Grafana 看板 
JSON |
-| 81 | GET | `/api/metrics/grafana/dashboards/export` | 打包导出全部 Grafana 看板 |
-| 82 | GET | `/api/instances/:instanceId/capabilities` | 实例能力契约 |
-| 83 | GET | `/api/topics/page` | Topic 分页列表 |
+| 21 | POST | `/api/k8s-certs/delete` | 删除证书 |
+| 22 | GET | `/api/topics` | Topic 列表 |
+| 23 | POST | `/api/topics/create` | 创建 Topic |
+| 24 | POST | `/api/topics/update` | 更新 Topic |
+| 25 | POST | `/api/topics/delete` | 删除 Topic |
+| 26 | GET | `/api/topics/:name/routes` | Topic 路由 |
+| 27 | GET | `/api/topics/:name/consumers` | Topic 消费者 |
+| 28 | POST | `/api/topics/send` | 发送消息到 Topic |
+| 29 | GET | `/api/groups` | 消费组列表 |
+| 30 | GET | `/api/groups/:name` | 消费组详情 |
+| 31 | GET | `/api/groups/:name/progress` | 消费进度 |
+| 32 | GET | `/api/groups/:name/subscriptions` | 订阅详情 |
+| 33 | POST | `/api/groups/create` | 创建消费组 |
+| 34 | POST | `/api/groups/delete` | 删除消费组 |
+| 35 | POST | `/api/groups/reset-offset` | 重置位点 |
+| 36 | POST | `/api/groups/import` | 导入配置 |
+| 37 | GET | `/api/groups/export` | 导出配置 |
+| 38 | GET | `/api/acl/rules` | ACL 规则列表 |
+| 39 | POST | `/api/acl/rules/create` | 创建 ACL 规则 |
+| 40 | POST | `/api/acl/rules/delete` | 删除 ACL 规则 |
+| 41 | GET | `/api/acl/users` | ACL 用户列表 |
+| 42 | POST | `/api/acl/users/create` | 创建 ACL 用户 |
+| 43 | POST | `/api/acl/users/delete` | 删除 ACL 用户 |
+| 44 | GET | `/api/messages` | 消息查询 |
+| 45 | GET | `/api/messages/:msgId/trace` | 消息轨迹 |
+| 46 | GET | `/api/dlq` | 死信队列列表 |
+| 47 | POST | `/api/dlq/resend` | 重发死信 |
+| 48 | GET | `/api/clients` | 客户端连接列表 |
+| 49 | GET | `/api/alert-rules` | 告警规则列表 |
+| 50 | POST | `/api/alert-rules/create` | 创建告警规则 |
+| 51 | POST | `/api/alert-rules/update` | 更新告警规则 |
+| 52 | POST | `/api/alert-rules/toggle` | 切换启用状态 |
+| 53 | POST | `/api/alert-rules/delete` | 删除告警规则 |
+| 54 | GET | `/api/system-alerts` | 系统告警列表 |
+| 55 | POST | `/api/system-alerts/acknowledge` | 确认告警 |
+| 56 | POST | `/api/system-alerts/clear-acknowledged` | 清除已确认告警 |
+| 57 | GET | `/api/audit-logs` | 审计日志列表 |
+| 58 | GET | `/api/audit-logs/filter-options` | 审计日志筛选项 |
+| 59 | GET | `/api/audit-logs/export` | 导出审计日志 |
+| 60 | POST | `/api/audit-logs/cleanup` | 清理审计日志 |
+| 61 | GET | `/api/settings/general` | 获取通用设置 |
+| 62 | POST | `/api/settings/general/save` | 保存通用设置 |
+| 63 | GET | `/api/settings/datasources` | 数据源选择器列表(未分页) |
+| 64 | GET | `/api/settings/datasources/page` | 分页数据源列表 |
+| 65 | POST | `/api/settings/datasources/create` | 创建数据源 |
+| 66 | POST | `/api/settings/datasources/update` | 更新数据源 |
+| 67 | POST | `/api/settings/datasources/delete` | 删除数据源 |
+| 68 | POST | `/api/settings/datasources/test` | 测试数据源连接 |
+| 69 | POST | `/api/ai/chat` | AI 对话(SSE) |
+| 70 | POST | `/api/ai/execute` | 执行 AI 指令 |
+| 71 | GET | `/api/ai/tools` | 可用工具列表 |
+| 72 | POST | `/api/ai/tools/:name/execute` | 执行只读 AI 工具 |
+| 73 | POST | `/api/metrics/query` | 查询监控指标数据 |
+| 74 | GET | `/api/acl/cluster-config` | 集群 ACL 配置概要(存储级) |
+| 75 | POST | `/api/acl/plain-access-config` | 创建/更新 Plain Access 账号 |
+| 76 | GET | `/api/acl/users/:id/credentials` | 查看单个用户明文凭证 |
+| 77 | GET | `/api/metrics/grafana/dashboards` | Grafana 看板列表 |
+| 78 | GET | `/api/metrics/grafana/dashboards/:uid` | Grafana 看板 JSON 模型 |
+| 79 | GET | `/api/metrics/grafana/dashboards/:uid/export` | 导出单个 Grafana 看板 
JSON |
+| 80 | GET | `/api/metrics/grafana/dashboards/export` | 打包导出全部 Grafana 看板 |
+| 81 | GET | `/api/instances/:instanceId/capabilities` | 实例能力契约 |
+| 82 | GET | `/api/topics/page` | Topic 分页列表 |
 
 ## 通用响应格式
 
@@ -624,6 +623,8 @@ POST /api/proxies/restart
 
 ### 4.12 获取 K8s 证书列表
 
+K8s 证书接口仅管理 Studio 本地配置记录,不会连接 Kubernetes API,也不会创建、修改或删除集群中的 Secret 或证书资源。
+
 ```
 GET /api/k8s-certs
 ```
@@ -681,21 +682,7 @@ POST /api/k8s-certs/update
 
 **Response `data`:** `K8sCertInfo`
 
-### 4.15 续期 K8s 证书
-
-```
-POST /api/k8s-certs/renew
-```
-
-**Request Body:**
-
-| 字段 | 类型 | 必填 | 说明 |
-|------|------|------|------|
-| `id` | `string` | 是 | 证书 ID |
-
-**Response `data`:** `K8sCertInfo`
-
-### 4.16 删除 K8s 证书
+### 4.15 删除 K8s 证书
 
 ```
 POST /api/k8s-certs/delete
diff --git a/docs/kubernetes-certificate-provider.md 
b/docs/kubernetes-certificate-provider.md
deleted file mode 100644
index 541e7461d..000000000
--- a/docs/kubernetes-certificate-provider.md
+++ /dev/null
@@ -1,177 +0,0 @@
-# Kubernetes Certificate Provider Design
-
-## Status
-
-Proposed implementation contract for 
[#1314](https://github.com/apache/rocketmq-dashboard/issues/1314).
-
-## Context
-
-The existing K8s certificate page stores Studio-local metadata. Those records 
are not an inventory of
-Kubernetes Secrets or cert-manager `Certificate` resources, and create, renew, 
or delete requests do
-not change a Kubernetes cluster. Studio must not represent that local metadata 
as applied runtime
-state.
-
-This document defines the boundary required before adding a Kubernetes-backed 
certificate view.
-
-## Goals
-
-- Resolve certificate inventory through the selected managed instance, never 
through a process-global
-  Kubernetes client.
-- Support a read-only inventory phase before exposing certificate lifecycle 
actions.
-- Keep Kubernetes credentials in the existing credential store as references; 
never return kubeconfig,
-  bearer tokens, client private keys, or Secret data to the browser.
-- Make unsupported capability and provider failures distinguishable from an 
empty certificate list.
-- Define least-privilege RBAC for each release phase.
-
-## Non-goals
-
-- Infer a Kubernetes cluster from a RocketMQ NameServer or Proxy endpoint.
-- Treat Studio-local `rmq_k8s_certificate` records as Kubernetes resources.
-- Create, renew, or delete certificates before a provider can prove that it is 
operating against the
-  selected Kubernetes context.
-- Add a general-purpose Kubernetes resource browser.
-
-## Instance Model
-
-A Kubernetes certificate source is associated with one managed Studio 
instance. The instance must
-reference a Kubernetes credential and an explicit Kubernetes target:
-
-| Field | Meaning |
-| --- | --- |
-| `instanceId` | Studio instance that owns the operational context. |
-| `credentialId` | Reference to an encrypted Kubernetes credential; the 
credential value is never returned by the API. |
-| `kubernetesContext` | Named kubeconfig context or in-cluster identity 
selector. |
-| `namespaceScope` | Optional allow-list of namespaces. An omitted value means 
the provider's configured default, not all namespaces. |
-| `certificateSource` | `CERT_MANAGER`, `TLS_SECRET`, or both when a provider 
explicitly supports both inventories. |
-
-Existing RocketMQ instance endpoints remain RocketMQ connection endpoints. 
They are not Kubernetes
-credentials and must not be reused to construct a Kubernetes API URL.
-
-## Provider Contract
-
-The server owns provider resolution. A provider is selected by the instance 
vendor/capability and a
-validated Kubernetes credential reference.
-
-```java
-public interface KubernetesCertificateProvider {
-    KubernetesCertificateCapabilities capabilities(String instanceId);
-
-    KubernetesCertificateInventory listCertificates(
-            String instanceId, KubernetesCertificateQuery query);
-
-    default KubernetesCertificate renewCertificate(
-            String instanceId, KubernetesCertificateRef certificate) {
-        throw new UnsupportedOperationException("Certificate renewal is not 
supported");
-    }
-
-    default void deleteCertificate(
-            String instanceId, KubernetesCertificateRef certificate) {
-        throw new UnsupportedOperationException("Certificate deletion is not 
supported");
-    }
-}
-```
-
-`KubernetesCertificateProviderRegistry` resolves this interface. It must 
reject an instance with no
-Kubernetes binding rather than silently selecting a default context.
-
-`KubernetesCertificateInventory` contains:
-
-- `items`: certificates from the requested source;
-- `source`: `CERT_MANAGER` or `TLS_SECRET`;
-- `observedAt`: provider observation timestamp;
-- `capabilities`: supported read/write operations;
-- `partialFailures`: namespace/source failures that did not invalidate the 
whole response.
-
-An empty `items` list means a successful observation with no matching 
resources. A missing provider,
-invalid credential, RBAC denial, or API failure is an explicit structured 
error and must not be
-converted to an empty inventory.
-
-## API Shape
-
-The first external API is read-only:
-
-```
-GET /api/instances/{instanceId}/kubernetes/certificates
-    ?namespace=<optional>
-    &source=CERT_MANAGER|TLS_SECRET
-```
-
-The response includes the selected instance ID and source so cached UI data 
cannot be reused for a
-different instance. The request must validate that `namespace`, when supplied, 
is inside the instance
-namespace scope.
-
-The existing `/api/k8s-certs` endpoints remain explicitly Studio-local until 
they are removed or
-migrated. They must not be mixed with provider inventory results in one table 
without a visible
-source label.
-
-Future mutation endpoints use resource references, not Studio-local record IDs:
-
-```
-POST 
/api/instances/{instanceId}/kubernetes/certificates/{namespace}/{name}/renew
-DELETE /api/instances/{instanceId}/kubernetes/certificates/{namespace}/{name}
-```
-
-Mutations require an advertised provider capability and create an audit entry 
containing the Studio
-user, instance ID, namespace, resource name, provider source, and result. They 
must never log token,
-kubeconfig, Secret value, or certificate private key material.
-
-## Credentials and RBAC
-
-Phase 1 supports either a ServiceAccount token reference or a kubeconfig 
secret reference stored by
-the server. The browser only receives the credential display name and 
non-sensitive metadata.
-
-Read-only cert-manager inventory requires:
-
-```yaml
-apiGroups: ["cert-manager.io"]
-resources: ["certificates"]
-verbs: ["get", "list", "watch"]
-```
-
-Read-only TLS Secret inventory requires:
-
-```yaml
-apiGroups: [""]
-resources: ["secrets"]
-verbs: ["get", "list"]
-```
-
-The TLS Secret provider returns metadata only: namespace, name, type, creation 
time, and parsed
-certificate expiry. It never returns `data.tls.crt` or `data.tls.key`.
-
-Renewal requires cert-manager `patch` permission on `certificates` and must 
define the exact renewal
-mechanism before implementation. Deletion is a separate high-risk capability 
and requires a
-confirmation workflow plus `delete` permission.
-
-## Delivery Phases
-
-1. **Provider foundation:** introduce the provider registry, Kubernetes 
credential reference model,
-   capability endpoint, and a provider-unavailable response. No mutation UI.
-2. **Read-only cert-manager inventory:** list `Certificate` resources for one 
selected instance and
-   namespace scope, including Ready condition and expiry data.
-3. **Read-only TLS Secret inventory:** optional source for clusters without 
cert-manager, metadata
-   only.
-4. **Renewal:** add only after a cert-manager-compatible renewal operation and 
audit contract are
-   tested against a real cluster.
-5. **Deletion:** explicit opt-in, confirmation, audit, and post-condition 
verification.
-
-Each phase is independently deployable. A missing Kubernetes provider must 
leave the rest of Studio
-operational and show a capability-unavailable state rather than fabricated 
certificate data.
-
-## Test Matrix
-
-- provider registry rejects an instance without Kubernetes binding;
-- selected instance A cannot read inventory using instance B 
credentials/context;
-- empty inventory is distinct from RBAC denial and transport failure;
-- namespace scope is enforced before a Kubernetes client call;
-- TLS Secret results never serialize Secret data or private-key fields;
-- cert-manager resources with missing status are rendered as unknown, not 
valid;
-- write endpoints reject missing capability and produce audit records only 
after the provider call is
-  attempted.
-
-## Migration
-
-Studio-local certificate records remain available only in the current 
local-metadata view during the
-transition. They are not automatically migrated because their `cluster` field 
does not identify a
-Kubernetes API context, credential, or authoritative resource name. Operators 
explicitly bind an
-instance to a Kubernetes provider, then use the provider inventory as the 
runtime source of truth.
diff --git a/server/README.md b/server/README.md
index cef879dae..e45e1e242 100644
--- a/server/README.md
+++ b/server/README.md
@@ -34,7 +34,7 @@ org.apache.rocketmq.studio
 | `cluster.proxy` | Proxy 节点管理(列表/重启/地址维护、兼容旧 `.do` 路径) |
 | `cluster.client` | 客户端连接信息 |
 | `cluster.metrics` | Prometheus 指标接入(多数据源、健康检查),`metrics.grafana` 子包提供 
Grafana 面板嵌入 |
-| `cluster.k8s` | K8s 证书管理 |
+| `cluster.k8s` | K8s 证书本地配置 |
 | `cluster.config` | Broker 配置更新 DTO/VO |
 
 ### common — 公共基础
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertController.java
 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertController.java
index 2446e6c9a..65bc10f2f 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertController.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertController.java
@@ -52,12 +52,6 @@ public class K8sCertController {
         return Result.ok(k8sCertService.updateCert(command));
     }
 
-    @PostMapping("/renew")
-    public Result<K8sCertVO> renewCert(@Valid @RequestBody(required = false) 
RenewCertDTO command) {
-        requireCommand(command);
-        return Result.ok(k8sCertService.renewCert(command));
-    }
-
     @PostMapping("/delete")
     public Result<Void> deleteCert(@Valid @RequestBody(required = false) 
DeleteCertDTO command) {
         requireCommand(command);
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertService.java
 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertService.java
index 287d576aa..dfa541627 100644
--- 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertService.java
+++ 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertService.java
@@ -144,28 +144,6 @@ public class K8sCertService {
         return saved;
     }
 
-    public K8sCertVO renewCert(RenewCertDTO command) {
-        requireCommand(command);
-        log.info("Renewing K8s certificate: {}", command.getId());
-        K8sCertVO existing = k8sCertRepository.findById(command.getId())
-                .orElseThrow(() -> new BusinessException(404, "Certificate not 
found: " + command.getId()));
-
-        LocalDateTime now = LocalDateTime.now(clock);
-        LocalDateTime notAfter = now.plusYears(1);
-
-        K8sCertVO renewed = copyOf(existing);
-        renewed.setNotBefore(now);
-        renewed.setNotAfter(notAfter);
-        renewed.setStatus(CertStatus.valid);
-        renewed.setDaysRemaining((int) ChronoUnit.DAYS.between(now, notAfter));
-        renewed.setGmtModified(now);
-
-        K8sCertVO saved = k8sCertRepository.save(renewed);
-        auditCertificate("RENEW_K8S_CERTIFICATE", saved);
-        log.info("K8s certificate renewed: {} (id={}), new expiry: {}", 
saved.getK8sId(), saved.getId(), notAfter);
-        return saved;
-    }
-
     public void deleteCert(DeleteCertDTO command) {
         requireCommand(command);
         log.info("Deleting K8s certificate: {}", command.getId());
diff --git 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/RenewCertDTO.java 
b/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/RenewCertDTO.java
deleted file mode 100644
index 23b00def5..000000000
--- 
a/server/src/main/java/org/apache/rocketmq/studio/cluster/k8s/RenewCertDTO.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.rocketmq.studio.cluster.k8s;
-
-import jakarta.validation.constraints.NotNull;
-import lombok.AllArgsConstructor;
-import lombok.Builder;
-import lombok.Data;
-import lombok.NoArgsConstructor;
-
-@Data
-@Builder
-@NoArgsConstructor
-@AllArgsConstructor
-public class RenewCertDTO {
-    @NotNull(message = "id is required")
-    private Long id;
-}
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertControllerTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertControllerTest.java
index 9f3d34a13..04b93751d 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertControllerTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertControllerTest.java
@@ -140,7 +140,6 @@ class K8sCertControllerTest {
         String[] paths = {
             "/api/k8s-certs/create",
             "/api/k8s-certs/update",
-            "/api/k8s-certs/renew",
             "/api/k8s-certs/delete"
         };
 
@@ -227,17 +226,11 @@ class K8sCertControllerTest {
     }
 
     @Test
-    void renewCertShouldRejectBlankId() throws Exception {
+    void renewEndpointShouldNotBeExposed() throws Exception {
         mockMvc.perform(post("/api/k8s-certs/renew")
                         .contentType(MediaType.APPLICATION_JSON)
-                        .content("""
-                                {
-                                    "id": null
-                                }
-                                """))
-                .andExpect(status().isBadRequest())
-                .andExpect(jsonPath("$.code").value(400))
-                .andExpect(jsonPath("$.message").value("id is required"));
+                        .content("{\"id\":1}"))
+                .andExpect(status().isNotFound());
 
         verifyNoInteractions(k8sCertService);
     }
diff --git 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertServiceTest.java
 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertServiceTest.java
index e86a10e64..39d55cd24 100644
--- 
a/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertServiceTest.java
+++ 
b/server/src/test/java/org/apache/rocketmq/studio/cluster/k8s/K8sCertServiceTest.java
@@ -189,10 +189,6 @@ class K8sCertServiceTest {
                 .isInstanceOf(BusinessException.class)
                 .hasMessage("K8s certificate request is required")
                 .satisfies(ex -> assertThat(((BusinessException) 
ex).getCode()).isEqualTo(400));
-        assertThatThrownBy(() -> k8sCertService.renewCert(null))
-                .isInstanceOf(BusinessException.class)
-                .hasMessage("K8s certificate request is required")
-                .satisfies(ex -> assertThat(((BusinessException) 
ex).getCode()).isEqualTo(400));
         assertThatThrownBy(() -> k8sCertService.deleteCert(null))
                 .isInstanceOf(BusinessException.class)
                 .hasMessage("K8s certificate request is required")
@@ -400,73 +396,6 @@ class K8sCertServiceTest {
         
assertThat(sampleCert.getGmtModified()).isEqualTo(LocalDateTime.of(2025, 1, 2, 
0, 0));
     }
 
-    @Test
-    void renewCertShouldRenewCertValidity() {
-        sampleCert.setStatus(CertStatus.expired);
-        sampleCert.setDaysRemaining(0);
-        LocalDateTime originalNotBefore = sampleCert.getNotBefore();
-        LocalDateTime originalNotAfter = sampleCert.getNotAfter();
-
-        
when(k8sCertRepository.findById(1L)).thenReturn(Optional.of(sampleCert));
-        
when(k8sCertRepository.save(any(K8sCertVO.class))).thenAnswer(invocation -> 
invocation.getArgument(0));
-
-        RenewCertDTO command = RenewCertDTO.builder().id(1L).build();
-
-        K8sCertVO result = k8sCertService.renewCert(command);
-        LocalDateTime now = LocalDateTime.now(CLOCK);
-
-        assertThat(result.getStatus()).isEqualTo(CertStatus.valid);
-        assertThat(result.getDaysRemaining()).isEqualTo(365);
-        assertThat(result.getNotBefore()).isEqualTo(now);
-        assertThat(result.getNotAfter()).isEqualTo(now.plusYears(1));
-        assertThat(result.getGmtModified()).isEqualTo(now);
-        assertThat(result.getId()).isEqualTo(1L);
-        assertThat(result.getGmtCreate()).isEqualTo(sampleCert.getGmtCreate());
-        assertThat(result).isNotSameAs(sampleCert);
-        assertThat(sampleCert.getStatus()).isEqualTo(CertStatus.expired);
-        assertThat(sampleCert.getDaysRemaining()).isZero();
-        assertThat(sampleCert.getNotBefore()).isEqualTo(originalNotBefore);
-        assertThat(sampleCert.getNotAfter()).isEqualTo(originalNotAfter);
-        verify(k8sCertRepository).save(any(K8sCertVO.class));
-        verify(operationAuditService).record(eq("RENEW_K8S_CERTIFICATE"), 
eq("K8S_CERTIFICATE"),
-                eq("1"), eq(null), eq("k8sId=rocketmq-tls, 
cluster=prod-cluster"),
-                eq("SUCCESS"), eq(null));
-    }
-
-    @Test
-    void renewCertShouldNotMutateStoredCertWhenSaveFails() {
-        sampleCert.setStatus(CertStatus.expired);
-        sampleCert.setDaysRemaining(0);
-        LocalDateTime originalNotBefore = sampleCert.getNotBefore();
-        LocalDateTime originalNotAfter = sampleCert.getNotAfter();
-
-        
when(k8sCertRepository.findById(1L)).thenReturn(Optional.of(sampleCert));
-        when(k8sCertRepository.save(any(K8sCertVO.class))).thenThrow(new 
IllegalStateException("save failed"));
-
-        RenewCertDTO command = RenewCertDTO.builder().id(1L).build();
-
-        assertThatThrownBy(() -> k8sCertService.renewCert(command))
-                .isInstanceOf(IllegalStateException.class)
-                .hasMessage("save failed");
-
-        assertThat(sampleCert.getStatus()).isEqualTo(CertStatus.expired);
-        assertThat(sampleCert.getDaysRemaining()).isZero();
-        assertThat(sampleCert.getNotBefore()).isEqualTo(originalNotBefore);
-        assertThat(sampleCert.getNotAfter()).isEqualTo(originalNotAfter);
-        
assertThat(sampleCert.getGmtModified()).isEqualTo(LocalDateTime.of(2025, 1, 2, 
0, 0));
-    }
-
-    @Test
-    void renewCertShouldThrowWhenNotFound() {
-        when(k8sCertRepository.findById(999L)).thenReturn(Optional.empty());
-
-        RenewCertDTO command = RenewCertDTO.builder().id(999L).build();
-
-        assertThatThrownBy(() -> k8sCertService.renewCert(command))
-                .isInstanceOf(BusinessException.class)
-                .hasMessageContaining("Certificate not found: 999");
-    }
-
     @Test
     void deleteCertShouldDeleteWhenFound() {
         
when(k8sCertRepository.findById(1L)).thenReturn(Optional.of(sampleCert));
diff --git a/web/src/api/cluster.test.ts b/web/src/api/cluster.test.ts
index 4a2db972b..f0e8dbef5 100644
--- a/web/src/api/cluster.test.ts
+++ b/web/src/api/cluster.test.ts
@@ -28,7 +28,6 @@ import {
   getCluster,
   listK8sCerts,
   previewClusterConfig,
-  renewK8sCert,
   restartBroker,
   restartNameServer,
   restartProxy,
@@ -91,16 +90,6 @@ describe('K8s certificate API', () => {
     await expect(updateK8sCert({ id: cert.id, issuer: 'vault' 
})).resolves.toEqual(updated);
   });
 
-  it('renews a certificate using its id', async () => {
-    const renewed = { ...cert, daysRemaining: 365, status: 'valid' };
-    mock.onPost('/k8s-certs/renew').reply((config) => {
-      expect(JSON.parse(config.data)).toEqual({ id: cert.id });
-      return [200, { code: 200, message: 'success', data: renewed }];
-    });
-
-    await expect(renewK8sCert(cert.id)).resolves.toEqual(renewed);
-  });
-
   it('sends the certificate id when deleting', async () => {
     mock.onPost('/k8s-certs/delete').reply((config) => {
       expect(JSON.parse(config.data)).toEqual({ id: cert.id });
diff --git a/web/src/api/cluster.ts b/web/src/api/cluster.ts
index c5a70851d..e83f09782 100644
--- a/web/src/api/cluster.ts
+++ b/web/src/api/cluster.ts
@@ -357,11 +357,6 @@ export async function updateK8sCert(data: 
Partial<K8sCertInfo>) {
   return res.data.data;
 }
 
-export async function renewK8sCert(id: number) {
-  const res = await client.post<{ data: K8sCertInfo }>('/k8s-certs/renew', { 
id });
-  return res.data.data;
-}
-
 export async function deleteK8sCert(id: number) {
   await client.post('/k8s-certs/delete', { id });
 }
diff --git a/web/src/i18n/translations.ts b/web/src/i18n/translations.ts
index 0352c2f46..7408f2e78 100644
--- a/web/src/i18n/translations.ts
+++ b/web/src/i18n/translations.ts
@@ -29,7 +29,7 @@ const translations: Record<string, Record<Lang, string>> = {
   'nav.message': { zh: '消息查询', en: 'Message Search' },
   'nav.dlq': { zh: '死信队列', en: 'Dead Letter Queue' },
   'nav.clusterOps': { zh: '集群管理', en: 'Cluster Management' },
-  'nav.certs': { zh: 'K8s 证书管理', en: 'K8s Certificates' },
+  'nav.certs': { zh: 'K8s 证书配置', en: 'K8s Certificate Config' },
   'nav.rocketmqCluster': { zh: 'RocketMQ 集群', en: 'RocketMQ Cluster' },
   'nav.clients': { zh: '客户端连接', en: 'Client Connections' },
   'nav.alertEvents': { zh: '告警事件', en: 'Alert Events' },
@@ -902,7 +902,6 @@ const translations: Record<string, Record<Lang, string>> = {
   'audit.op.DELETE_INSTANCE': { zh: '删除实例', en: 'Delete Instance' },
   'audit.op.CREATE_K8S_CERTIFICATE': { zh: '创建 K8s 证书', en: 'Create K8s 
Certificate' },
   'audit.op.UPDATE_K8S_CERTIFICATE': { zh: '更新 K8s 证书', en: 'Update K8s 
Certificate' },
-  'audit.op.RENEW_K8S_CERTIFICATE': { zh: '续期 K8s 证书', en: 'Renew K8s 
Certificate' },
   'audit.op.DELETE_K8S_CERTIFICATE': { zh: '删除 K8s 证书', en: 'Delete K8s 
Certificate' },
   'audit.res.TOPIC': { zh: 'Topic', en: 'Topic' },
   'audit.res.GROUP': { zh: '消费组', en: 'Consumer Group' },
diff --git a/web/src/pages/cluster/__tests__/K8sCertsPage.test.tsx 
b/web/src/pages/cluster/__tests__/K8sCertsPage.test.tsx
index dd52f7815..1573ac2dc 100644
--- a/web/src/pages/cluster/__tests__/K8sCertsPage.test.tsx
+++ b/web/src/pages/cluster/__tests__/K8sCertsPage.test.tsx
@@ -125,7 +125,7 @@ describe('K8sCertsPage', () => {
     renderPage();
 
     expect(await 
screen.findByTestId('k8s-cert-local-metadata-notice')).toHaveTextContent(
-      '当前证书记录仅保存为 Studio 本地元数据',
+      '当前证书记录仅保存为 Studio 本地配置',
     );
   });
 
diff --git a/web/src/pages/cluster/certs.tsx b/web/src/pages/cluster/certs.tsx
index 1dd7d4b72..10b6b78c7 100644
--- a/web/src/pages/cluster/certs.tsx
+++ b/web/src/pages/cluster/certs.tsx
@@ -249,11 +249,11 @@ const K8sCertsPage = () => {
 
   return (
     <div style={{ padding: 24 }}>
-      <PageHeader title="K8s 证书管理" subtitle={`共 ${filteredCerts.length} 个证书`} 
/>
+      <PageHeader title="K8s 证书配置" subtitle={`共 ${filteredCerts.length} 个证书`} 
/>
       <InfoBanner
         data-testid="k8s-cert-local-metadata-notice"
-        title="当前证书记录仅保存为 Studio 本地元数据"
-        description="创建、续期和删除操作尚不会应用到 Kubernetes 集群或 
cert-manager。请在集群侧管理实际证书,直到 Kubernetes Provider 接入完成。"
+        title="当前证书记录仅保存为 Studio 本地配置"
+        description="这些操作不会连接 Kubernetes 集群或修改集群中的证书资源。请在集群侧管理实际证书。"
       />
       <Flex justify="space-between" style={{ marginBottom: 16 }}>
         <Space>
diff --git a/web/src/pages/ops/auditPresentation.ts 
b/web/src/pages/ops/auditPresentation.ts
index c19fd274d..e2fc110a6 100644
--- a/web/src/pages/ops/auditPresentation.ts
+++ b/web/src/pages/ops/auditPresentation.ts
@@ -133,11 +133,6 @@ const operationPresentation: Record<string, 
AuditOperationPresentation> = {
     color: 'cyan',
     category: 'certificate',
   },
-  RENEW_K8S_CERTIFICATE: {
-    label: 'Renew K8s Certificate',
-    color: 'green',
-    category: 'certificate',
-  },
   DELETE_K8S_CERTIFICATE: {
     label: 'Delete K8s Certificate',
     color: 'volcano',
diff --git a/web/src/services/clusterService.ts 
b/web/src/services/clusterService.ts
index 823ef557e..0f46640eb 100644
--- a/web/src/services/clusterService.ts
+++ b/web/src/services/clusterService.ts
@@ -235,24 +235,6 @@ export async function updateK8sCert(data: 
Partial<K8sCertInfo>): Promise<K8sCert
   return clusterApi.updateK8sCert(data);
 }
 
-export async function renewK8sCert(id: number): Promise<K8sCertInfo> {
-  if (isMockMode()) {
-    const existing = mockCertStore.find((cert) => cert.id === id);
-    if (!existing) throw new Error(`Certificate not found: ${id}`);
-    const now = new Date();
-    const notAfter = new Date(now);
-    notAfter.setFullYear(notAfter.getFullYear() + 1);
-    Object.assign(existing, {
-      notBefore: now.toISOString(),
-      notAfter: notAfter.toISOString(),
-      status: 'valid',
-      daysRemaining: Math.round((notAfter.getTime() - now.getTime()) / (24 * 
60 * 60 * 1000)),
-    });
-    return { ...existing, san: existing.san ? [...existing.san] : existing.san 
};
-  }
-  return clusterApi.renewK8sCert(id);
-}
-
 export async function deleteK8sCert(id: number): Promise<void> {
   if (isMockMode()) {
     const index = mockCertStore.findIndex((cert) => cert.id === id);

Reply via email to