diff --git a/scripts/svc.sh b/scripts/svc.sh index d23cc814..ed4028fe 100755 --- a/scripts/svc.sh +++ b/scripts/svc.sh @@ -2819,10 +2819,13 @@ print_agent_plan() { return 0 } -# seed_settings:把 CLI/环境变量给出的模型与搜索配置写入 settings(幂等)。 -# 认证开启(PG 档默认)时 PUT /api/settings/user 同样要求凭证:自动铸一把临时 -# API key(name=svc-seed)完成写入后立即回收;owner 缺省取库内首个管理员(回落 -# 首个账号),--seed-owner / SVC_SEED_OWNER 可指定。铸 key 失败维持无头 PUT(旧行为)。 +# seed_settings:把 CLI/环境变量给出的模型与搜索配置写入系统设置(幂等)。 +# P2 受管(提案 2026-10-13 rdm-settings-members-duties-perms-increment):models.* +# 与 tools.tavily.* 是系统受管项,user 层写入整笔拒绝,播种改走系统管理面 +# PUT /api/settings/system。认证开启(PG 档默认)时该面要求管理员凭证:自动铸一把 +# 临时 API key(name=svc-seed)完成写入后立即回收;owner 缺省取库内首个管理员 +#(系统面必须 isAdmin,不再回落普通账号),--seed-owner / SVC_SEED_OWNER 可指定。 +# 铸 key 失败维持无头 PUT(仅无认证单机档可成)。 seed_settings() { local host="$1" port="$2" local cb="${CLI_MBASE:-${SVC_MODEL_BASE:-}}" ck="${CLI_MKEY:-${SVC_MODEL_KEY:-}}" cn="${CLI_MNAME:-${SVC_MODEL_NAME:-}}" @@ -2865,18 +2868,21 @@ except Exception: sys.exit(0) for u in users: if u.get("isAdmin"): - print(u["owner"]); break -else: - for u in users: print(u["owner"]); break' 2>/dev/null || true)" fi - if [ -n "$seed_owner" ]; then - seed_key="$("$ENV_BIN" apikey create ${seed_dbf[@]+"${seed_dbf[@]}"} --owner "$seed_owner" --name svc-seed 2>/dev/null || true)" - [ -n "$seed_key" ] && seed_hdr=(-H "Authorization: Bearer $seed_key") + if [ -z "$seed_owner" ]; then + c_warn "[$ENV_NAME] 跳过配置播种:系统设置面需要管理员账号(user list 未见 isAdmin)" + return 0 + fi + seed_key="$("$ENV_BIN" apikey create ${seed_dbf[@]+"${seed_dbf[@]}"} --owner "$seed_owner" --name svc-seed 2>/dev/null || true)" + [ -n "$seed_key" ] && seed_hdr=(-H "Authorization: Bearer $seed_key") + if [ -z "$seed_key" ]; then + c_warn "[$ENV_NAME] 跳过配置播种:铸临时管理员 key 失败(认证档系统面拒绝无头写入)" + return 0 fi fi local resp - resp="$(curl -s -m 5 -X PUT "http://$host:$port/api/settings/user" -H 'Content-Type: application/json' ${seed_hdr[@]+"${seed_hdr[@]}"} -d "$payload")" + resp="$(curl -s -m 5 -X PUT "http://$host:$port/api/settings/system" -H 'Content-Type: application/json' ${seed_hdr[@]+"${seed_hdr[@]}"} -d "$payload")" # 用后即回收;失败只提示吊销途径,不回显任何密钥材料。 if [ -n "$seed_key" ]; then "$ENV_BIN" apikey revoke ${seed_dbf[@]+"${seed_dbf[@]}"} --owner "$seed_owner" --name svc-seed >/dev/null 2>&1 \ diff --git a/tests/integration/multi-instance/multi_instance_test.go b/tests/integration/multi-instance/multi_instance_test.go index 6b4d9a0d..9ef9467e 100644 --- a/tests/integration/multi-instance/multi_instance_test.go +++ b/tests/integration/multi-instance/multi_instance_test.go @@ -461,8 +461,9 @@ func (e *env) loginAlice(t *testing.T) *userClient { } // --mock 只写 OwnerDefault 的设置;alice 是独立租户,须显式开 mock // (selectConversationRunner 按 EffectiveSettings 分流),否则 run 走 - // LLMRunner 且无模型配置直接失败。 - e.do(t, uc.api, "PUT", "/api/settings/user", map[string]any{"runtime": map[string]any{"mock": true}}, nil) + // LLMRunner 且无模型配置直接失败。P2 受管:runtime.mock 是系统受管项, + // user 层写入被拒;改走系统面(无认证单机档本机即管理员),对全部租户生效。 + e.do(t, uc.api, "PUT", "/api/settings/system", map[string]any{"runtime": map[string]any{"mock": true}}, nil) return uc }