apps/web/app/api/auth/login/route.ts:9-9已由 Worker 驗證if (!body?.password || !equal(body.password, expectedPassword)) return failure("密碼錯誤", 401);目前認證失敗訊息直接描述密碼錯誤,需要改為不洩漏驗證細節的通用提示。
需求以來源平台為準;工程狀態、Agent 與 PR 在此整合。
登入失敗時提供可採取行動的錯誤訊息。 ## Acceptance criteria 錯誤訊息不洩漏帳號是否存在,並通過既有測試。 Agent-Desk-Work-Item: 8b89cb4c-36fd-4378-85a0-192564972441
錯誤訊息不洩漏帳號是否存在,並通過既有測試。
待核准 低風險
模型:gpt-5.6-luna
分支:尚未建立
目前沒有關聯的 Pull Request。
將登入驗證失敗訊息改為不透露帳號或驗證細節的通用、可採取行動提示。
apps/web/app/api/auth/login/route.ts:9-9已由 Worker 驗證if (!body?.password || !equal(body.password, expectedPassword)) return failure("密碼錯誤", 401);目前認證失敗訊息直接描述密碼錯誤,需要改為不洩漏驗證細節的通用提示。
apps/web/components/login-form.tsx:19-19引用無法驗證if (!response.ok) throw new Error(body.error ?? "登入失敗");
前端會直接顯示 API 回傳的 error,因此 API 的通用訊息可被既有登入表單使用。
apps/web/app/api/auth/login/route.tsapps/web/components/login-form.tsx--- a/apps/web/app/api/auth/login/route.ts+++ b/apps/web/app/api/auth/login/route.ts@@ -6,7 +6,7 @@ export async function POST(request: Request) { const sessionSecret = process.env.DASHBOARD_SESSION_SECRET; if (!expectedPassword || !sessionSecret) return failure("Dashboard login is not configured", 503); const body = await request.json().catch(() => null) as { password?: string; next?: string } | null; if (!body?.password || !equal(body.password, expectedPassword)) return failure("密碼錯誤", 401); if (!body?.password || !equal(body.password, expectedPassword)) return failure("登入失敗,請確認密碼後再試。", 401); const next = body.next?.startsWith("/") && !body.next.startsWith("//") ? body.next : "/"; const response = ok({ authenticated: true, next }); response.cookies.set("dashboard_session", sessionSecret, { httpOnly: true, secure: process.env.NODE_ENV === "production", sameSite: "lax", path: "/", maxAge: 60 * 60 * 12 }); 最終檢查已通過,沒有失敗紀錄。