chore: add pre-commit hooks, tighten ESLint, activate Sentry DSN, publish CI coverage (Phase 1)
- Install husky v9 + lint-staged: pre-commit runs eslint --fix and prettier on staged files - Tighten ESLint base config: no-console→error, ban-ts-comment (ts-ignore banned, ts-expect-error with description allowed), reportUnusedDisableDirectives→error - Migrate web app from deprecated `next lint` to `eslint src/` with flat config and react-hooks plugin - Convert all 5 @ts-ignore to @ts-expect-error with descriptions, remove stale disable comments - Add NEXT_PUBLIC_SENTRY_DSN to docker-compose.prod.yml and .env.example - Add coverage artifact upload step to CI test job - Pre-existing violations (102 warnings) downgraded to warn in web config for Phase 2 cleanup Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -115,7 +115,6 @@ export async function GET(request: Request) {
|
||||
)
|
||||
.join("; ");
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await createNotificationsForUsers({
|
||||
db: prisma as any,
|
||||
userIds: adminUsers.map((u) => u.id),
|
||||
@@ -128,7 +127,10 @@ export async function GET(request: Request) {
|
||||
});
|
||||
|
||||
logger.warn(
|
||||
{ anomalies: report.anomalies, window: { start: report.windowStartedAt, end: report.windowEndedAt } },
|
||||
{
|
||||
anomalies: report.anomalies,
|
||||
window: { start: report.windowStartedAt, end: report.windowEndedAt },
|
||||
},
|
||||
"Auth anomaly cron: anomalies detected and admins notified",
|
||||
);
|
||||
}
|
||||
@@ -140,9 +142,6 @@ export async function GET(request: Request) {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error({ error, route: "/api/cron/auth-anomaly-check" }, "Auth anomaly cron failed");
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Internal error" },
|
||||
{ status: 500 },
|
||||
);
|
||||
return NextResponse.json({ ok: false, error: "Internal error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,10 +73,7 @@ export async function GET(request: Request) {
|
||||
if (deny) return deny;
|
||||
|
||||
try {
|
||||
const [postgres, redis] = await Promise.all([
|
||||
checkPostgres(),
|
||||
checkRedis(),
|
||||
]);
|
||||
const [postgres, redis] = await Promise.all([checkPostgres(), checkRedis()]);
|
||||
|
||||
const allHealthy = postgres.status === "ok" && redis.status === "ok";
|
||||
|
||||
@@ -92,7 +89,6 @@ export async function GET(request: Request) {
|
||||
});
|
||||
|
||||
if (adminUsers.length > 0) {
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await createNotificationsForUsers({
|
||||
db: prisma as any,
|
||||
userIds: adminUsers.map((u) => u.id),
|
||||
@@ -121,9 +117,6 @@ export async function GET(request: Request) {
|
||||
);
|
||||
} catch (error) {
|
||||
logger.error({ error, route: "/api/cron/health-check" }, "Health check cron failed");
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Internal error" },
|
||||
{ status: 500 },
|
||||
);
|
||||
return NextResponse.json({ ok: false, error: "Internal error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,7 +17,7 @@ const MINIMUM_SAFE_VERSIONS: Record<string, { minVersion: string; advisory?: str
|
||||
next: { minVersion: "15.0.0", advisory: "Keep Next.js on latest 15.x" },
|
||||
prisma: { minVersion: "6.0.0", advisory: "Prisma 6.x for latest security patches" },
|
||||
"@sentry/nextjs": { minVersion: "8.0.0", advisory: "Sentry v8 for latest fixes" },
|
||||
"ioredis": { minVersion: "5.4.0", advisory: "ioredis 5.4+ for connection security" },
|
||||
ioredis: { minVersion: "5.4.0", advisory: "ioredis 5.4+ for connection security" },
|
||||
"next-auth": { minVersion: "5.0.0", advisory: "Auth.js v5 for security hardening" },
|
||||
};
|
||||
|
||||
@@ -89,7 +89,10 @@ function scanPackageJson(): Finding[] {
|
||||
}
|
||||
}
|
||||
} catch (error) {
|
||||
logger.error({ error, route: "/api/cron/security-audit" }, "Failed to scan package manifests for security audit");
|
||||
logger.error(
|
||||
{ error, route: "/api/cron/security-audit" },
|
||||
"Failed to scan package manifests for security audit",
|
||||
);
|
||||
}
|
||||
|
||||
return findings;
|
||||
@@ -124,7 +127,6 @@ export async function GET(request: Request) {
|
||||
.map((f) => `${f.package}@${f.currentVersion} (need >=${f.minimumVersion})`)
|
||||
.join(", ");
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
await createNotificationsForUsers({
|
||||
db: prisma as any,
|
||||
userIds: adminUsers.map((u) => u.id),
|
||||
@@ -147,9 +149,6 @@ export async function GET(request: Request) {
|
||||
});
|
||||
} catch (error) {
|
||||
logger.error({ error, route: "/api/cron/security-audit" }, "Security audit cron failed");
|
||||
return NextResponse.json(
|
||||
{ ok: false, error: "Internal error" },
|
||||
{ status: 500 },
|
||||
);
|
||||
return NextResponse.json({ ok: false, error: "Internal error" }, { status: 500 });
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user