diff --git a/api/src/server.ts b/api/src/server.ts
index 5c61684..15fd15d 100644
--- a/api/src/server.ts
+++ b/api/src/server.ts
@@ -888,7 +888,11 @@ app.post(
authRateLimit,
async (req, reply) => {
const parsed = RegisterBody.safeParse(req.body);
- if (!parsed.success) return reply.code(400).send({ ok: false, message: "Invalid payload" });
+ if (!parsed.success) {
+ const firstIssue = parsed.error.issues[0];
+ const message = firstIssue?.message || "Invalid payload";
+ return reply.code(400).send({ ok: false, message });
+ }
const { email, password } = parsed.data;
const normalizedEmail = normalizeEmail(email);
const existing = await app.prisma.user.findUnique({
diff --git a/web/src/pages/RegisterPage.tsx b/web/src/pages/RegisterPage.tsx
index 01efc01..2610712 100644
--- a/web/src/pages/RegisterPage.tsx
+++ b/web/src/pages/RegisterPage.tsx
@@ -37,8 +37,13 @@ export default function RegisterPage() {
const passwordError =
(touched.password || submitted) && !password
? "Password is required."
- : (touched.password || submitted) && password.length < 8
- ? "Password must be at least 8 characters."
+ : (touched.password || submitted) &&
+ (password.length < 12 ||
+ !/[a-z]/.test(password) ||
+ !/[A-Z]/.test(password) ||
+ !/\d/.test(password) ||
+ !/[^A-Za-z0-9]/.test(password))
+ ? "Use 12+ chars with upper, lower, number, and symbol."
: "";
const confirmError =
(touched.confirmPassword || submitted) && !confirmPassword
@@ -87,7 +92,7 @@ export default function RegisterPage() {
status === 409
? "That email is already registered. Try signing in."
: status === 400
- ? "Enter a valid email and password."
+ ? (err instanceof Error ? err.message : "Enter a valid email and password.")
: err instanceof Error
? err.message
: "Unable to register. Try again.";
@@ -134,11 +139,16 @@ export default function RegisterPage() {
onBlur={() => setTouched((prev) => ({ ...prev, password: true }))}
autoComplete="new-password"
required
- minLength={8}
+ minLength={12}
/>
{passwordError && (
{passwordError}
)}
+ {!passwordError && (
+
+ Must be 12+ chars and include uppercase, lowercase, number, and symbol.
+
+ )}