Phase 9: Admin & DevOps — health check, rate limiting, logging, site admin, Docker healthcheck
- Health check endpoint (GET /api/health) with DB probe and uptime - In-memory sliding window rate limiting on login (10/60s) and register (5/3600s) - Structured logging with pino (request timing in hooks, Socket.IO events in server.js) - Site admin dashboard with tenant stats, CRUD, and requireSiteAdmin guard - Tenant admin enhanced with tag and category management UI - Docker HEALTHCHECK in Dockerfile and docker-compose.yml - Backup documentation (docs/backup.md) Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -2,8 +2,11 @@ import express from 'express';
|
||||
import { createServer } from 'http';
|
||||
import { Server } from 'socket.io';
|
||||
import { PrismaClient } from '@prisma/client';
|
||||
import pino from 'pino';
|
||||
import { handler } from './build/handler.js';
|
||||
|
||||
const logger = pino({ name: 'pounce' });
|
||||
|
||||
const app = express();
|
||||
const server = createServer(app);
|
||||
|
||||
@@ -64,7 +67,7 @@ io.use(async (socket, next) => {
|
||||
}
|
||||
next();
|
||||
} catch (err) {
|
||||
console.error('Socket auth error:', err);
|
||||
logger.error({ err }, 'Socket auth error');
|
||||
socket.data.user = null;
|
||||
next();
|
||||
}
|
||||
@@ -73,7 +76,7 @@ io.use(async (socket, next) => {
|
||||
// ─── Socket.IO connection handler ────────────────────────────
|
||||
io.on('connection', (socket) => {
|
||||
const user = socket.data.user;
|
||||
console.log(`Socket connected: ${socket.id} (user: ${user?.name ?? 'anon'})`);
|
||||
logger.info({ socketId: socket.id, user: user?.name ?? 'anon' }, 'Socket connected');
|
||||
|
||||
// Join user-specific room for notifications
|
||||
if (user) {
|
||||
@@ -122,7 +125,7 @@ io.on('connection', (socket) => {
|
||||
});
|
||||
|
||||
socket.on('disconnect', () => {
|
||||
console.log(`Socket disconnected: ${socket.id}`);
|
||||
logger.info({ socketId: socket.id }, 'Socket disconnected');
|
||||
for (const boardId of joinedBoards) {
|
||||
if (presence.has(boardId)) {
|
||||
presence.get(boardId).delete(socket.id);
|
||||
@@ -152,5 +155,5 @@ const port = process.env.PORT || 3000;
|
||||
const host = process.env.HOST || '0.0.0.0';
|
||||
|
||||
server.listen(port, host, () => {
|
||||
console.log(`Server running on http://${host}:${port}`);
|
||||
logger.info({ host, port }, 'Server running');
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user