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

@@ -9,6 +9,7 @@ import { deviceCommands, deviceLinks, devices, streamSessions } from '../db/sche
import { mediaProvider } from '../media/service';
import { requireDeviceAuth } from '../middleware/device-auth';
import { dispatchCommandById, sendRealtimeToDevice } from '../realtime/gateway';
import { writeAuditLog } from '../services/audit';
import { enqueuePushNotification } from '../services/push';
import { createRecordingForStream } from './recordings';
@@ -192,6 +193,16 @@ router.post('/request', requireDeviceAuth, async (req, res) => {
streamSession: session,
command: refreshedCommand ?? command,
});
await writeAuditLog({
ownerUserId: sourceDevice.userId,
actorDeviceId: sourceDevice.id,
action: 'stream.requested',
targetType: 'stream_session',
targetId: session.id,
metadata: { cameraDeviceId: cameraDevice.id, reason: session.reason },
ipAddress: req.ip,
});
});
router.post('/:streamSessionId/accept', requireDeviceAuth, async (req, res) => {
@@ -287,6 +298,16 @@ router.post('/:streamSessionId/accept', requireDeviceAuth, async (req, res) => {
}
res.json({ message: 'Stream accepted', streamSession: updated });
await writeAuditLog({
ownerUserId: session.ownerUserId,
actorDeviceId: session.cameraDeviceId,
action: 'stream.accepted',
targetType: 'stream_session',
targetId: session.id,
metadata: { mediaSessionId: updated.mediaSessionId, mediaProvider: updated.mediaProvider },
ipAddress: req.ip,
});
});
router.get('/:streamSessionId/publish-credentials', requireDeviceAuth, async (req, res) => {
@@ -330,6 +351,16 @@ router.get('/:streamSessionId/publish-credentials', requireDeviceAuth, async (re
});
res.json(credentials);
await writeAuditLog({
ownerUserId: session.ownerUserId,
actorDeviceId: session.cameraDeviceId,
action: 'stream.publish_credentials_issued',
targetType: 'stream_session',
targetId: session.id,
metadata: { mediaProvider: credentials.provider },
ipAddress: req.ip,
});
});
router.get('/:streamSessionId/subscribe-credentials', requireDeviceAuth, async (req, res) => {
@@ -376,6 +407,16 @@ router.get('/:streamSessionId/subscribe-credentials', requireDeviceAuth, async (
});
res.json(credentials);
await writeAuditLog({
ownerUserId: session.ownerUserId,
actorDeviceId: deviceAuth.deviceId,
action: 'stream.subscribe_credentials_issued',
targetType: 'stream_session',
targetId: session.id,
metadata: { mediaProvider: credentials.provider },
ipAddress: req.ip,
});
});
router.post('/:streamSessionId/end', requireDeviceAuth, async (req, res) => {