feat(security): add phase8 hardening with rate limits, audit logs, and auth-first simulator flow

This commit is contained in:
2026-01-24 18:45:00 +00:00
parent 6d6c77f77e
commit f6d66c3650
11 changed files with 355 additions and 5 deletions

View File

@@ -7,6 +7,7 @@ import { deviceLinks, devices, events, notifications } from '../db/schema';
import { requireAuth } from '../middleware/auth';
import { requireDeviceAuth } from '../middleware/device-auth';
import { sendRealtimeToDevice } from '../realtime/gateway';
import { writeAuditLog } from '../services/audit';
import { enqueuePushNotification } from '../services/push';
const router = Router();
@@ -126,6 +127,16 @@ router.post('/motion/start', requireDeviceAuth, async (req, res) => {
event,
notifiedClients: activeLinks.length,
});
await writeAuditLog({
ownerUserId: deviceAuth.userId,
actorDeviceId: cameraDevice.id,
action: 'event.motion_started',
targetType: 'event',
targetId: event.id,
metadata: { notifiedClients: activeLinks.length },
ipAddress: req.ip,
});
});
router.post('/:eventId/motion/end', requireDeviceAuth, async (req, res) => {
@@ -210,6 +221,16 @@ router.post('/:eventId/motion/end', requireDeviceAuth, async (req, res) => {
}
res.json({ message: 'Motion event ended', event: updated, notifiedClients: activeLinks.length });
await writeAuditLog({
ownerUserId: deviceAuth.userId,
actorDeviceId: deviceAuth.deviceId,
action: 'event.motion_ended',
targetType: 'event',
targetId: event.id,
metadata: { status: parsed.data.status, notifiedClients: activeLinks.length },
ipAddress: req.ip,
});
});
router.get('/', requireAuth, async (req, res) => {