fix(security): W4-E1 approvals admin-session only, shared redact table, TMDB key redaction, prod mock gate
- POST /approvals and PATCH /approvals/{id} require a console admin session
(EndpointDef auth:"session"); API keys incl. admin scope get 403, so an
organize.execute key can no longer approve its own plan (S1)
- tests for single-use approval checks: expired, revision/payload hash
mismatch, consumed, revoked, pending/rejected, plan mismatch; re-approve
after plan change succeeds once and cannot be replayed (S4)
- one redact key table in @umt/contracts shared by server logger and agent
redactForModel: rsskey, torrent_pass, authkey, downhash, c_secure_pass,
passkey variants, x-api-key, cookie headers, nested objects/arrays (S2)
- TMDB network errors: message and cause redacted via redactUrl (S3)
- web Agent ?mock=1 only in DEV builds or when pi.provider is fake (S7)
- EndpointDef auth annotations for /auth/*, asserted against
PUBLIC_AUTH_PATHS (S10); doc drift fixes (S11)
Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
1 parent
79cdd26457
commit
f48e1aac96
25 files changed
+825
-235
No files matched your search
@@ -23,10 +23,18 @@ export const API_PREFIX = "/api/v1";
|
||||
|
||||
export type HttpMethod = "get" | "post" | "patch" | "put" | "delete";
|
||||
|
||||
/**
|
||||
* 鉴权方式(不写即按 scope 校验,cookie 会话与 API Key 同样适用):
|
||||
* - public:免鉴权(必须与服务端 http/auth.ts 的 PUBLIC_AUTH_PATHS 一致,测试断言);
|
||||
* - session:只接受控制台管理员 cookie 会话,API Key(含 admin scope)一律 403。
|
||||
*/
|
||||
export type EndpointAuth = "public" | "session";
|
||||
|
||||
export interface EndpointDef {
|
||||
method: HttpMethod;
|
||||
path: string;
|
||||
scope: ApiScope;
|
||||
auth?: EndpointAuth;
|
||||
summary: string;
|
||||
params?: z.ZodObject;
|
||||
query?: z.ZodType;
|
||||
@@ -793,16 +801,27 @@ export const Api = {
|
||||
"审批",
|
||||
{
|
||||
row: agent.Approval,
|
||||
update: agent.ApprovalUpdate,
|
||||
filters: { status: agent.ApprovalStatus.optional(), planId: Id.optional() },
|
||||
},
|
||||
{ read: "read", write: "organize.execute" },
|
||||
R,
|
||||
),
|
||||
// 审批的申请与决定只在控制台管理员会话里做:API Key(哪怕持 organize.execute)不能给自己的计划开审批(验收 S1)
|
||||
update: ep({
|
||||
method: "patch",
|
||||
path: "/approvals/{id}",
|
||||
scope: "admin",
|
||||
auth: "session",
|
||||
summary: "批准/拒绝/撤销单次审批(只接受控制台管理员会话)",
|
||||
params: IdParam,
|
||||
body: agent.ApprovalUpdate,
|
||||
response: agent.Approval,
|
||||
}),
|
||||
create: ep({
|
||||
method: "post",
|
||||
path: "/approvals",
|
||||
scope: "organize.execute",
|
||||
summary: "为计划申请单次审批(绑定 plan id + payload hash + revision + 有效期)",
|
||||
scope: "admin",
|
||||
auth: "session",
|
||||
summary: "为计划申请单次审批(绑定 plan id + payload hash + revision + 有效期;只接受控制台管理员会话)",
|
||||
body: agent.ApprovalRequest,
|
||||
response: agent.Approval,
|
||||
}),
|
||||
@@ -1040,6 +1059,7 @@ export const Api = {
|
||||
method: "post",
|
||||
path: "/auth/setup",
|
||||
scope: "read",
|
||||
auth: "public",
|
||||
summary: "首次初始化管理员",
|
||||
body: auth.AdminSetupRequest,
|
||||
response: auth.SessionInfo,
|
||||
@@ -1048,6 +1068,7 @@ export const Api = {
|
||||
method: "post",
|
||||
path: "/auth/login",
|
||||
scope: "read",
|
||||
auth: "public",
|
||||
summary: "管理员登录",
|
||||
body: auth.LoginRequest,
|
||||
response: auth.LoginResult,
|
||||
@@ -1057,6 +1078,7 @@ export const Api = {
|
||||
method: "get",
|
||||
path: "/auth/session",
|
||||
scope: "read",
|
||||
auth: "public",
|
||||
summary: "当前登录态(免鉴权)",
|
||||
response: auth.SessionInfo,
|
||||
}),
|
||||
@@ -1064,6 +1086,7 @@ export const Api = {
|
||||
method: "post",
|
||||
path: "/auth/password",
|
||||
scope: "admin",
|
||||
auth: "session",
|
||||
summary: "修改密码(吊销其它会话)",
|
||||
body: auth.PasswordChangeRequest,
|
||||
response: auth.PasswordChangeResult,
|
||||
@@ -1072,6 +1095,7 @@ export const Api = {
|
||||
method: "get",
|
||||
path: "/auth/totp",
|
||||
scope: "admin",
|
||||
auth: "session",
|
||||
summary: "TOTP 状态",
|
||||
response: auth.TotpStatus,
|
||||
}),
|
||||
@@ -1079,6 +1103,7 @@ export const Api = {
|
||||
method: "post",
|
||||
path: "/auth/totp",
|
||||
scope: "admin",
|
||||
auth: "session",
|
||||
summary: "TOTP 绑定/启用/停用",
|
||||
body: auth.TotpAction,
|
||||
response: auth.TotpActionResult,
|
||||
|
||||
Reference in new issue
Block a user