feat(auth,gateway,user): X-API-Key 真接线 + key 一律超管 + owner 档案真落盘(裁决 15.4.2/15.4.3/10.4.5/08.4.2)
CI / Backend (build / vet / test / cross-compile) (push) Has been cancelled
CI / Frontend (tsc + vite build) (push) Has been cancelled

- 15.4.2:管理 API 与 Bearer 共用同一 Authorize 路径,X-API-Key 命中签发表即过门;未知/已吊销/空值 401 且不回落 Bearer(fail-closed)
- 15.4.3:key 表去掉角色维度,任一有效 key 鉴权后即 owner;签发接口取消 role 分级(不再读请求体)
- 10.4.5:新增 GET/PUT /api/v1/admin/owner-profile(owner-only,PUT 带审计 owner.profile.update),0600 原子落盘 + 活档案热替换;前端主人档案改接真实 API,读不到即禁用保存,删掉硬编码默认档案
- 08.4.2:persona 的 identity.systemPrompt 必填,缺失/空白 400 显式报错,不再派生回落
This commit is contained in:
AskaEth committed 2026-10-04 12:07:51 +08:00
1 parent 8c6466cb00
commit adef36538f
13 files changed
+1223 -199

No files matched your search

+23
View File
@@ -68,6 +68,29 @@ func SaveOwnerProfile(path string, p *OwnerProfile) error {
return nil
}
// Replace 把 src 的**落盘字段**(owner.yaml 的那些)原地装进 p,**保留 p 的指针
// 身份与互斥量**。
//
// 这是「后台面板改主人白名单立即生效」的实现方式:渠道 bridge 在启动时就捕获
// 了同一个 *OwnerProfile 指针并用它解析 actor(见 IsOwner),换指针则那些组件
// 仍看着旧档案。内存态来源(例如每渠道配置在热重载时带进来的层)不在这里的字段
// 之列,因此不会被一次面板保存抹掉。accounts 取副本,调用方之后改动 src 不会
// 影响活档案。它通过 mu 与 IsOwner/RegisterAccount 并发安全;src 为 nil 时是安全
// 的空操作。
func (p *OwnerProfile) Replace(src *OwnerProfile) {
if p == nil || src == nil {
return
}
p.mu.Lock()
defer p.mu.Unlock()
p.ID = src.ID
p.DisplayName = src.DisplayName
p.DefaultPersona = src.DefaultPersona
p.IdentityFile = src.IdentityFile
p.Notes = src.Notes
p.Accounts = append([]OwnerAccount(nil), src.Accounts...)
}
// RegisterOwnerAccount loads the owner whitelist at path, appends (platform,
// accountID) when it is not already present (idempotent), and writes the updated
// profile back. It returns an error when the profile cannot be loaded or saved.