feat(security): add phase8 hardening with rate limits, audit logs, and auth-first simulator flow
This commit is contained in:
@@ -5,6 +5,7 @@ import { z } from 'zod';
|
||||
import { db } from '../db/client';
|
||||
import { recordings, streamSessions } from '../db/schema';
|
||||
import { requireDeviceAuth } from '../middleware/device-auth';
|
||||
import { writeAuditLog } from '../services/audit';
|
||||
import { minioBucket, minioClient, minioPresignedExpirySeconds } from '../utils/minio';
|
||||
|
||||
const router = Router();
|
||||
@@ -105,6 +106,16 @@ router.post('/:recordingId/finalize', requireDeviceAuth, async (req, res) => {
|
||||
.returning();
|
||||
|
||||
res.json({ message: 'Recording finalized', recording: updated });
|
||||
|
||||
await writeAuditLog({
|
||||
ownerUserId: recording.ownerUserId,
|
||||
actorDeviceId: recording.cameraDeviceId,
|
||||
action: 'recording.finalized',
|
||||
targetType: 'recording',
|
||||
targetId: recording.id,
|
||||
metadata: { objectKey: parsed.data.objectKey, bucket: parsed.data.bucket },
|
||||
ipAddress: req.ip,
|
||||
});
|
||||
});
|
||||
|
||||
router.get('/:recordingId/download-url', requireDeviceAuth, async (req, res) => {
|
||||
@@ -156,6 +167,16 @@ router.get('/:recordingId/download-url', requireDeviceAuth, async (req, res) =>
|
||||
downloadUrl,
|
||||
expiresInSeconds: minioPresignedExpirySeconds,
|
||||
});
|
||||
|
||||
await writeAuditLog({
|
||||
ownerUserId: recording.ownerUserId,
|
||||
actorDeviceId: deviceAuth.deviceId,
|
||||
action: 'recording.download_url_issued',
|
||||
targetType: 'recording',
|
||||
targetId: recording.id,
|
||||
metadata: { objectKey: recording.objectKey, bucket: recording.bucket },
|
||||
ipAddress: req.ip,
|
||||
});
|
||||
});
|
||||
|
||||
// Internal helper used by stream lifecycle to create recording placeholder rows.
|
||||
|
||||
Reference in New Issue
Block a user