5654ebaecd
Deploy to route.crispygoat.com / deploy (push) Successful in 3m14s
Cleanup after Auth.js v5 became the only sign-in path. The platform
had three overlapping auth modes (dev cookie, legacy rc_auth_uid, Auth.js
JWT) and a pile of dead-code pages/routes that only existed to support
the legacy path.
What changed:
* getAdminUser() now has only two auth paths:
1. dev_session cookie (auto-issued by src/proxy.ts for /admin/* when
ALLOW_DEV_LOGIN is enabled)
2. Auth.js v5 JWT (the encrypted cookie + auth() lookup)
The legacy rc_auth_uid/rc_uid branch and the Supabase REST fetch
against admin_users are gone.
* The signIn callback in src/lib/auth.ts enforces ADMIN_ALLOWED_EMAILS
when set. Unset = open mode (backward compatible with demo/dev). Dev
credentials provider is exempt. The new env var is wired through
.env.example and .gitea/workflows/deploy.yml (read from
secrets.ADMIN_ALLOWED_EMAILS, written to the server .env file).
* change-password/page.tsx now uses auth() server-side instead of
fetching the deleted /api/auth/uid endpoint. The form is split into
page.tsx (server component, auth check) + ChangePasswordForm.tsx
(client component, form state). updatePasswordAction now reads the
user id from auth() instead of the rc_auth_uid cookie.
* Deleted 14 dead-code files:
- Pages: login2, logout, auth/callback, admin/debug-auth,
admin/test-auth
- API routes: api/login, api/logout, api/auth/uid, api/force-admin,
api/set-auth-cookie, api/debug-cookie, api/debug-me,
api/debug-auth
- Actions: src/actions/login.ts
These were the old email/password login, the old Supabase OAuth
callback, the old /api/auth/uid probe, and a pile of debug endpoints
that have been superseded by the new proxy + the new /login page.
* next.config.ts: set outputFileTracingRoot: '.' to silence the
Next.js 16 lockfile-inference warning. Without this the build
walked up from package.json looking for a lockfile, found the
homelab runner's stale act cache at /home/tyler/.cache/act/.../package-lock.json,
and warned on every build. '. resolves to the project root in both
dev and CI, so it's the right answer.
Out of scope (deferred):
* src/actions/admin/users.ts still uses rc_auth_uid internally for its
dev-bypass logic. It works (the rc_auth_uid branch is gated on
NODE_ENV != 'production' and DEV_FORCE_UID), but it's now genuinely
unreachable in production. Clean up in a follow-up.
Pre-flight:
* npx tsc --noEmit: clean
* npm run lint (touched files): clean
* npm run build: clean — proxy picked up, no lockfile warning, all
93 static pages generated.
129 lines
3.1 KiB
TypeScript
129 lines
3.1 KiB
TypeScript
import type { NextConfig } from "next";
|
|
|
|
const nextConfig: NextConfig = {
|
|
// Lock the file-tracing root to the project directory. Without this,
|
|
// Next.js 16 walks up from package.json looking for a lockfile, finds
|
|
// the homelab runner's stale `act` cache at
|
|
// /home/tyler/.cache/act/.../package-lock.json, and warns:
|
|
// "We detected multiple lockfiles and selected the directory of
|
|
// /home/tyler/package-lock.json as the root directory."
|
|
// The deploy runner's APP_DIR is /home/tyler/route-commerce, so
|
|
// resolving relative to the project root is correct both locally and
|
|
// in CI.
|
|
outputFileTracingRoot: ".",
|
|
|
|
// Enable strict mode
|
|
reactStrictMode: true,
|
|
|
|
// Optimize images
|
|
images: {
|
|
remotePatterns: [
|
|
{
|
|
protocol: "https",
|
|
hostname: "*.supabase.co",
|
|
},
|
|
{
|
|
protocol: "https",
|
|
hostname: "images.unsplash.com",
|
|
},
|
|
{
|
|
protocol: "https",
|
|
hostname: "picsum.photos",
|
|
},
|
|
],
|
|
formats: ["image/avif", "image/webp"],
|
|
deviceSizes: [640, 750, 828, 1080, 1200, 1920, 2048, 3840],
|
|
imageSizes: [16, 32, 48, 64, 96, 128, 256, 384],
|
|
},
|
|
|
|
// Security headers
|
|
async headers() {
|
|
return [
|
|
{
|
|
source: "/:path*",
|
|
headers: [
|
|
{
|
|
key: "X-Content-Type-Options",
|
|
value: "nosniff",
|
|
},
|
|
{
|
|
key: "X-Frame-Options",
|
|
value: "DENY",
|
|
},
|
|
{
|
|
key: "X-XSS-Protection",
|
|
value: "1; mode=block",
|
|
},
|
|
{
|
|
key: "Referrer-Policy",
|
|
value: "strict-origin-when-cross-origin",
|
|
},
|
|
{
|
|
key: "Permissions-Policy",
|
|
value: "camera=(), microphone=(), geolocation=()",
|
|
},
|
|
],
|
|
},
|
|
{
|
|
// API routes - more restrictive
|
|
source: "/api/:path*",
|
|
headers: [
|
|
{
|
|
key: "Access-Control-Allow-Methods",
|
|
value: "GET, POST, PUT, DELETE, OPTIONS",
|
|
},
|
|
{
|
|
key: "Access-Control-Allow-Headers",
|
|
value: "Content-Type, Authorization, X-API-Key",
|
|
},
|
|
{
|
|
key: "Access-Control-Max-Age",
|
|
value: "86400",
|
|
},
|
|
],
|
|
},
|
|
];
|
|
},
|
|
|
|
// Redirects
|
|
async redirects() {
|
|
return [
|
|
// Redirect old paths if needed
|
|
// {
|
|
// source: '/old-path',
|
|
// destination: '/new-path',
|
|
// permanent: true,
|
|
// },
|
|
];
|
|
},
|
|
|
|
// Rewrites for API proxy
|
|
async rewrites() {
|
|
return [
|
|
// Add any necessary rewrites here
|
|
];
|
|
},
|
|
|
|
// Experimental features
|
|
experimental: {
|
|
// Enable optimizePackageImports for better bundle size
|
|
optimizePackageImports: ["lucide-react", "@radix-ui/react-icons", "framer-motion"],
|
|
},
|
|
|
|
// Compiler options
|
|
compiler: {
|
|
// Remove console.log in production
|
|
removeConsole: process.env.NODE_ENV === "production"
|
|
? { exclude: ["error", "warn"] }
|
|
: false,
|
|
},
|
|
|
|
// Logging
|
|
logging: {
|
|
fetches: {
|
|
fullUrl: process.env.NODE_ENV === "development",
|
|
},
|
|
},
|
|
};
|
|
|
|
export default nextConfig; |