diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..2b69c3f --- /dev/null +++ b/.dockerignore @@ -0,0 +1,12 @@ +node_modules +.next +.git +*.md +.env* +.gitignore +.eslint* +.prettier* +.next +npm-debug.log +yarn-debug.log +yarn-error.log diff --git a/.gitignore b/.gitignore index 92d093b..0abd857 100644 --- a/.gitignore +++ b/.gitignore @@ -31,6 +31,8 @@ yarn-error.log* # Testing coverage/ +playwright-report/ +test-results/ # Secrets (DO NOT COMMIT) *.pem @@ -50,9 +52,14 @@ coverage/ deno.lock # SQLite dev database +dev.db +dev.db-journal prisma/dev.db prisma/dev.db-journal +# Generated service worker (serwist build output) +public/sw.js + # Claude (workspace config, not project code) .claude/* !.claude/commands/ diff --git a/Dockerfile b/Dockerfile index b15a70f..d1ca3f8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -7,11 +7,10 @@ COPY package.json package-lock.json* ./ RUN npm ci FROM base AS builder -RUN apt-get update && apt-get install -y --no-install-recommends openssl && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY --from=deps /app/node_modules ./node_modules COPY . . -RUN npx prisma generate --schema=./prisma/schema.prisma && npm run build +RUN npx prisma generate && npm run build FROM base AS runner WORKDIR /app @@ -23,6 +22,7 @@ RUN mkdir -p /app/data COPY --from=builder /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static COPY --from=builder /app/prisma ./prisma +RUN npx prisma generate RUN mkdir -p /app/public USER nextjs EXPOSE 3000 diff --git a/src/app/api/chat/daily/route.ts b/src/app/api/chat/daily/route.ts index f7353a7..2343eb7 100644 --- a/src/app/api/chat/daily/route.ts +++ b/src/app/api/chat/daily/route.ts @@ -1,5 +1,6 @@ import { NextRequest, NextResponse } from 'next/server' import { prisma } from '@/lib/prisma' +import { verifyJWT } from '@/lib/auth' // ───────────────────────────────────────────── // Greeting pools — tiered by engagement level @@ -44,10 +45,15 @@ function pickRandom(pool: T[]): T { export async function POST(req: NextRequest) { try { - const { userId } = await req.json() - if (!userId) { - return NextResponse.json({ error: 'userId required' }, { status: 400 }) + const authHeader = req.headers.get('authorization') + if (!authHeader?.startsWith('Bearer ')) { + return NextResponse.json({ error: 'Unauthorized' }, { status: 401 }) } + const payload = await verifyJWT(authHeader.slice(7)) + if (!payload) { + return NextResponse.json({ error: 'Invalid token' }, { status: 401 }) + } + const userId = payload.id const user = await prisma.user.findUnique({ where: { id: userId } }) if (!user) {