feat: every agent and probe must have an owner passkey, enforced by the panel, the installers and fleet-enroll [CI]

This commit is contained in:
justme committed 2026-10-08 06:04:04 +08:00
1 parent 0b384a58f5
commit 8c37db1577
14 files changed
+207 -12

No files matched your search

+2 -2
View File
@@ -50,7 +50,7 @@ function AddAgentDialog({ onClose, onCreated }: { onClose: () => void; onCreated
<button
type="button"
className="btn primary"
disabled={busy}
disabled={busy || !controllers?.length}
onClick={async () => {
await run(async () => {
const token = await api.post<CreatedJoinTokenDto>('/api/admin/join-tokens', {
@@ -92,7 +92,7 @@ function AddAgentDialog({ onClose, onCreated }: { onClose: () => void; onCreated
<input className="input" type="number" min={1} max={720} value={hours} onChange={(e) => setHours(Number(e.target.value))} />
</Field>
<div className="wide">
<Field label="属主(passkey)" hint="允许授权这个节点 web ssh 等敏感操作的 Passkey;只是选,不用触碰。装上后固定在节点本地,面板改不了。">
<Field label="属主(passkey)" hint="必选(至少一把):这个节点的敏感操作(web ssh 等)和加密内容只认它们。只是选,不用触碰;装上后固定在节点本地,面板改不了。">
<OwnerPicker value={controllers} onChange={setControllers} />
</Field>
</div>
+2 -2
View File
@@ -3,7 +3,7 @@ import { api } from '@shared/api/client'
import type { Page, PasskeyDto, TrustStateDto } from '@shared/api/types'
/**
* 选这个节点的属主:允许授权它 extension 会话(web ssh 等,以后)的 passkey。只是选,不需要触碰 Passkey:
* 选这个节点的属主(必选,至少一把):允许授权它 extension 会话(web ssh 等,以后)、解密它加密内容的 passkey。只是选,不需要触碰 Passkey:
* 选定的凭证 id 会写进安装命令,节点装上时固定在本地,之后面板改不了。默认是操作员集合里的全部。
* 还没有建立信任根时不显示选项,只提示去建立。
*/
@@ -33,7 +33,7 @@ export function OwnerPicker({ value, onChange }: { value: string[] | null; onCha
if (!trust) return null
if (!trust.initialized) {
return <div className="notice warn">还没有建立信任根:这个节点装上后不会固定属主,也不会校验面板的操作员集合。先到「系统 → 信任」用 Passkey 建立。</div>
return <div className="notice warn">还没有建立信任根:每个节点都必须有属主(passkey),先到「系统 → 信任」用 Passkey 建立信任根,才能添加节点。</div>
}
const chosen = new Set(value ?? [])
+2 -2
View File
@@ -113,7 +113,7 @@ function AddProbeDialog({ onClose, onCreated }: { onClose: () => void; onCreated
<button
type="button"
className="btn primary"
disabled={busy}
disabled={busy || !controllers?.length}
onClick={async () => {
await run(async () => {
const token = await api.post<CreatedJoinTokenDto>('/api/admin/join-tokens', {
@@ -147,7 +147,7 @@ function AddProbeDialog({ onClose, onCreated }: { onClose: () => void; onCreated
<input className="input" type="number" min={1} max={720} value={hours} onChange={(e) => setHours(Number(e.target.value))} />
</Field>
<div className="wide">
<Field label="属主(passkey)" hint="允许授权这个节点 web ssh 等敏感操作的 Passkey;只是选,不用触碰。装上后固定在节点本地,面板改不了。">
<Field label="属主(passkey)" hint="必选(至少一把):这个节点的敏感操作(web ssh 等)和加密内容只认它们。只是选,不用触碰;装上后固定在节点本地,面板改不了。">
<OwnerPicker value={controllers} onChange={setControllers} />
</Field>
</div>