Add audit logging for sensitive operations

Structured logging with request ID correlation throughout:
- Auth: register, login success, login failure (warn level)
- Accounts: soft-delete
- Members: move between accounts
- Tax exemptions: approve (info), revoke (warn with reason)
- Files: upload, delete (already had logging)

All logs include userId, entityId, and contextual data for debugging.
4xx errors logged as warn, 5xx as error.
This commit is contained in:
Ryan Moon
2026-03-28 16:23:20 -05:00
parent e44d461de1
commit e0493814f7
2 changed files with 8 additions and 0 deletions

View File

@@ -88,6 +88,7 @@ export const authRoutes: FastifyPluginAsync = async (app) => {
role: user.role,
})
request.log.info({ userId: user.id, email: user.email, companyId }, 'User registered')
return reply.status(201).send({ user, token })
})
@@ -109,6 +110,7 @@ export const authRoutes: FastifyPluginAsync = async (app) => {
.limit(1)
if (!user) {
request.log.warn({ email }, 'Login failed — unknown email')
return reply.status(401).send({
error: { message: 'Invalid email or password', statusCode: 401 },
})
@@ -116,6 +118,7 @@ export const authRoutes: FastifyPluginAsync = async (app) => {
const valid = await bcrypt.compare(password, user.passwordHash)
if (!valid) {
request.log.warn({ email, userId: user.id }, 'Login failed — wrong password')
return reply.status(401).send({
error: { message: 'Invalid email or password', statusCode: 401 },
})
@@ -127,6 +130,7 @@ export const authRoutes: FastifyPluginAsync = async (app) => {
role: user.role,
})
request.log.info({ userId: user.id, email }, 'User logged in')
return reply.send({
user: {
id: user.id,