feat: ship single-file run distribution and list key reset

Compile-time run auth replaces zip sidecars, lengthens run keys, revokes
active sessions on reset, and exposes run-key reset in the server list.
This commit is contained in:
npc0-hue
2026-07-24 14:14:26 +08:00
parent 2b1f553df0
commit 292b380f3c
17 changed files with 397 additions and 9 deletions
+3 -3
View File
@@ -132,8 +132,8 @@ const runtimeDownload: ArtifactDownloadReferenceResponse = {
artifactId: "artifact-run-1",
ownerKind: "server-instance",
ownerId: server.id,
filename: "run-linux-amd64.zip",
contentType: "application/zip",
filename: "run-linux-amd64",
contentType: "application/octet-stream",
sizeBytes: 128,
checksum: "sha256:runchecksum",
state: "available",
@@ -398,7 +398,7 @@ describe("PlatformApiClient AI providers", () => {
runEndpointId: endpoint.id,
targetOs: "linux",
targetArch: "amd64",
packageFormat: "zip",
packageFormat: "raw-executable",
artifactId: "artifact-run-1",
checksum: "sha256:runchecksum",
keyGeneration: 1,
@@ -77,6 +77,13 @@ export const runtimeUpdateStages: RuntimeTaskStage[] = [
{ key: "job_track", label: "等待确认", description: "记录 job id 并刷新后台任务状态。" }
];
export const runtimeKeyResetStages: RuntimeTaskStage[] = [
{ key: "scope_check", label: "权限校验", description: "确认当前账号可以重置该服务器的 run 密钥。" },
{ key: "confirm_reset", label: "确认重置", description: "记录本次密钥轮换并撤销旧 run 会话。" },
{ key: "key_rotate", label: "轮换密钥", description: "生成新密钥代际并撤销旧发行物。" },
{ key: "regenerate_hint", label: "等待重发", description: "提示重新生成并部署新的 run 可执行文件。" }
];
export const runtimeDependencyStages: RuntimeTaskStage[] = [
{ key: "profile_read", label: "读取声明", description: "读取插件声明的 probe 和 install plan。" },
{ key: "env_probe", label: "环境检查", description: "让 run 节点评估当前运行环境。" },
+8
View File
@@ -159,6 +159,14 @@ describe("first-party console pages", () => {
expect(serversPageSource).toContain("onClick={() => void refreshMetrics()}");
});
it("exposes run key reset from the compact server list danger menu", () => {
expect(serversPageSource).toContain("reset-run-key");
expect(serversPageSource).toContain("重置 run 密钥");
expect(serversPageSource).toContain("runtimeKeyResetStages");
expect(serversPageSource).toContain("platformApiClient.resetRunKey");
expect(serversPageSource).toContain("旧 run 会话已失效");
});
it("submits declared runtime profiles and logical bindings from the create workflow", () => {
expect(serversPageSource).toContain("<ManagementDialog");
expect(serversPageSource).toContain('className="provider-form dialog-form"');
+31
View File
@@ -10,6 +10,7 @@ import {
runtimeBuildStages,
runtimeDependencyStages,
runtimeDownloadStages,
runtimeKeyResetStages,
runtimeLogStages,
runtimeRunBuildStages,
runtimeUpdateStages,
@@ -271,6 +272,12 @@ export function ServersPage({ session, operations, onNavigate }: PageComponentPr
openRunTargetSelection(instance);
return;
}
if (action === "reset-run-key") {
const confirmed = typeof window === "undefined" || window.confirm("重置 run 密钥会立刻断开已部署 run,并要求重新生成新的 run 可执行文件。继续?");
if (!confirmed) {
return;
}
}
const defaults = quickRuntimeDefaultsForPlugin(instance.pluginId);
const intent = quickRuntimeActionLabel(action);
const operationId = operations.begin({ intent, targetKind: "server", targetId: `${instance.id}:${action}`, requester: session.displayName });
@@ -319,6 +326,10 @@ export function ServersPage({ session, operations, onNavigate }: PageComponentPr
const update = await platformApiClient.pushRunUpdate(instance.id, runUpdateRequest(instance.id, reference.artifactId, reference.checksum));
return `run 更新任务已排队,job ${update.jobId ?? update.id}`;
}
if (action === "reset-run-key") {
const key = await platformApiClient.resetRunKey(instance.id);
return `run 密钥已重置到第 ${key.generation} 代,旧 run 会话已失效,请重新生成并部署 run`;
}
if (action === "dependencies-check") {
const job = await platformApiClient.checkDependencies(instance.id, dependencyJobRequest(instance.id, defaults.probeKey));
return `依赖检查任务已排队,job ${job.id}`;
@@ -691,6 +702,7 @@ type ServerQuickRuntimeAction =
| "generate-run"
| "download-run"
| "push-run-update"
| "reset-run-key"
| "generate-client-manager"
| "dependencies-check"
| "dependencies-install"
@@ -873,6 +885,17 @@ function ServerCard({ card, metricsPending, metricsUnavailable, canManage, delet
<section className="runtime-action-group" aria-label="危险操作">
<span className="runtime-action-group-label"></span>
<div className="runtime-action-grid">
<button
type="button"
className="runtime-action-item danger-command"
role="menuitem"
disabled={!canManage}
title={canManage ? "重置 run 密钥" : "当前账号没有运行操作权限"}
onClick={() => chooseQuickAction("reset-run-key")}
>
<AlertTriangle size={13} />
<span> run </span>
</button>
<button
type="button"
className="runtime-action-item danger-command"
@@ -915,6 +938,8 @@ function quickRuntimeActionLabel(action: ServerQuickRuntimeAction): string {
return "下载 run";
case "push-run-update":
return "更新 run";
case "reset-run-key":
return "重置 run 密钥";
case "generate-client-manager":
return "生成客户端";
case "dependencies-check":
@@ -941,6 +966,9 @@ function quickRuntimeStages(action: ServerQuickRuntimeAction) {
if (action === "push-run-update") {
return runtimeUpdateStages;
}
if (action === "reset-run-key") {
return runtimeKeyResetStages;
}
if (action === "dependencies-check" || action === "dependencies-install") {
return runtimeDependencyStages;
}
@@ -954,6 +982,9 @@ function quickRuntimeExecuteStageIndex(action: ServerQuickRuntimeAction): number
if (action === "push-run-update") {
return 2;
}
if (action === "reset-run-key") {
return 2;
}
return 1;
}