# Section 5.3 Temporary Code Snippets

This file collects the main backend and web app snippets referenced in Section 5.3 so they can be screenshotted easily.

Each snippet includes:
- a short description of what it demonstrates
- a source reference you can cite in the report
- the code excerpt itself

---

## Snippet 1: Backend Bootstrap and Route Mounting

**What this shows:**  
This snippet shows how the backend is assembled in one place. It configures CORS and security middleware, exposes OpenAPI docs, mounts Better Auth, registers the main route groups, and starts the realtime gateway plus background workers.

**Source:** [Backend/index.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/index.ts:28)

```ts
const app = express();
const openApiDocument = buildOpenApiDocument();
const trustedOrigins = process.env.BETTER_AUTH_TRUSTED_ORIGINS
  ? process.env.BETTER_AUTH_TRUSTED_ORIGINS.split(',').map((origin) => origin.trim()).filter(Boolean)
  : [];
const corsMiddleware = cors({
  origin: trustedOrigins.length > 0 ? trustedOrigins : true,
  credentials: true,
});

app.get('/openapi.json', (_req, res) => {
  res.json(openApiDocument);
});

app.use('/docs', swaggerUi.serve, swaggerUi.setup(openApiDocument));

app.use(
  helmet({
    contentSecurityPolicy: {
      directives: {
        ...helmet.contentSecurityPolicy.getDefaultDirectives(),
        "script-src": ["'self'", "'unsafe-inline'", "cdn.jsdelivr.net", "cdn.tailwindcss.com"],
        "style-src": ["'self'", "'unsafe-inline'", "cdn.jsdelivr.net", "fonts.googleapis.com"],
        "font-src": ["'self'", "fonts.gstatic.com"],
        "connect-src": connectSrcDirectives,
        "media-src": mediaSrcDirectives,
        "img-src": ["'self'", "data:", "blob:"],
      },
    },
  }),
);
app.use(corsMiddleware);
app.all('/api/auth/*splat', corsMiddleware, toNodeHandler(auth));
app.use(rateLimit({ keyPrefix: 'global', windowMs: 60_000, max: 400 }));
app.use(requestContext);
app.use(express.json());
app.use('/sim', express.static('public'));
app.use('/videos', videosRoutes);
app.use('/admin', adminRoutes);
app.use('/devices', rateLimit({ keyPrefix: 'devices', windowMs: 60_000, max: 120 }), devicesRoutes);
app.use('/device-links', deviceLinksRoutes);
app.use('/commands', rateLimit({ keyPrefix: 'commands', windowMs: 60_000, max: 120 }), commandsRoutes);
app.use('/events', rateLimit({ keyPrefix: 'events', windowMs: 60_000, max: 120 }), eventsRoutes);
app.use('/streams', rateLimit({ keyPrefix: 'streams', windowMs: 60_000, max: 120 }), streamsRoutes);
app.use('/recordings', rateLimit({ keyPrefix: 'recordings', windowMs: 60_000, max: 120 }), recordingsRoutes);
app.use('/push-notifications', pushNotificationsRoutes);
app.use('/audit', auditRoutes);
app.use('/ops', opsRoutes);

const start = async () => {
  try {
    await ensureMinioBucket();
  } catch (error) {
    console.error('MinIO initialization failed', error);
    process.exit(1);
  }

  setupRealtimeGateway(server);
  startRecordingsWorker();
  startPushWorker();

  server.listen(port, () => {
    console.log(`Server is running on port ${port}`);
  });
};
```

---

## Snippet 2: Better Auth Configuration

**What this shows:**  
This snippet shows how session-based user authentication is integrated with the project database through Better Auth and Drizzle.

**Source:** [Backend/auth.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/auth.ts:13)

```ts
export const auth = betterAuth({
  database: drizzleAdapter(db, {
    provider: 'pg',
    schema: {
      ...schema,
      user: schema.users,
      account: schema.accounts,
      session: schema.sessions,
      verification: schema.verifications,
    },
  }),
  advanced: {
    database: {
      generateId: 'uuid',
    },
  },
  emailAndPassword: {
    enabled: true,
    password: {
      hash: async (password) => hashPassword(password),
      verify: async ({ hash, password }) => verifyPassword(password, hash),
    },
  },
  secret: getRequiredEnv('BETTER_AUTH_SECRET'),
  baseURL: getBetterAuthBaseUrl(),
  trustedOrigins,
});
```

---

## Snippet 3: Core Database Schema

**What this shows:**  
This excerpt shows the main persistence model used by the system: devices, links between camera and client devices, live stream sessions, recordings, motion events, notifications, and audit logs.

**Source:** [Backend/db/schema.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/db/schema.ts:14)

```ts
export const devices = pgTable('devices', {
  id: uuid('id').defaultRandom().primaryKey(),
  userId: uuid('user_id').notNull().references(() => users.id),
  name: varchar('name', { length: 255 }),
  role: varchar('role', { length: 32 }).default('client').notNull(),
  platform: varchar('platform', { length: 32 }),
  appVersion: varchar('app_version', { length: 64 }),
  pushToken: text('push_token'),
  status: varchar('status', { length: 32 }).default('offline').notNull(),
  isCamera: boolean('is_camera').default(false).notNull(),
  lastSeenAt: timestamp('last_seen_at', { withTimezone: true }),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
});

export const deviceLinks = pgTable(
  'device_links',
  {
    id: uuid('id').defaultRandom().primaryKey(),
    ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
    cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id),
    clientDeviceId: uuid('client_device_id').notNull().references(() => devices.id),
    status: varchar('status', { length: 32 }).default('active').notNull(),
    createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
    updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
  },
  (table) => ({
    uniqueDevicePair: unique('device_links_camera_client_unique').on(table.cameraDeviceId, table.clientDeviceId),
  }),
);

export const streamSessions = pgTable('stream_sessions', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id),
  requesterDeviceId: uuid('requester_device_id').notNull().references(() => devices.id),
  status: varchar('status', { length: 32 }).default('requested').notNull(),
  reason: varchar('reason', { length: 32 }).default('on_demand').notNull(),
  mediaProvider: varchar('media_provider', { length: 32 }).default('mock').notNull(),
  mediaSessionId: varchar('media_session_id', { length: 255 }),
  publishEndpoint: text('publish_endpoint'),
  subscribeEndpoint: text('subscribe_endpoint'),
  streamKey: varchar('stream_key', { length: 255 }),
  startedAt: timestamp('started_at', { withTimezone: true }),
  endedAt: timestamp('ended_at', { withTimezone: true }),
  metadata: jsonb('metadata').$type<Record<string, unknown> | null>().default(null),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const recordings = pgTable('recordings', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  streamSessionId: uuid('stream_session_id').references(() => streamSessions.id),
  cameraDeviceId: uuid('camera_device_id').notNull().references(() => devices.id),
  requesterDeviceId: uuid('requester_device_id').references(() => devices.id),
  eventId: uuid('event_id').references(() => events.id),
  objectKey: varchar('object_key', { length: 1024 }),
  bucket: varchar('bucket', { length: 255 }),
  durationSeconds: integer('duration_seconds'),
  sizeBytes: integer('size_bytes'),
  status: varchar('status', { length: 32 }).default('awaiting_upload').notNull(),
  availableAt: timestamp('available_at', { withTimezone: true }),
  error: text('error'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const events = pgTable('events', {
  id: uuid('id').defaultRandom().primaryKey(),
  userId: uuid('user_id').notNull().references(() => users.id),
  deviceId: uuid('device_id').references(() => devices.id),
  title: varchar('title', { length: 255 }),
  triggeredBy: varchar('triggered_by', { length: 64 }).default('motion'),
  status: varchar('status', { length: 32 }).default('recording').notNull(),
  startedAt: timestamp('started_at', { withTimezone: true }).notNull(),
  endedAt: timestamp('ended_at', { withTimezone: true }),
  notifiedAt: timestamp('notified_at', { withTimezone: true }),
  videoUrl: varchar('video_url', { length: 1024 }).unique(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const notifications = pgTable('notifications', {
  id: uuid('id').defaultRandom().primaryKey(),
  eventId: uuid('event_id').references(() => events.id).notNull(),
  userId: uuid('user_id').references(() => users.id).notNull(),
  sentAt: timestamp('sent_at', { withTimezone: true }).defaultNow().notNull(),
  channel: varchar('channel', { length: 32 }).notNull(),
  status: varchar('status', { length: 32 }).default('queued').notNull(),
  isRead: boolean('is_read').default(false).notNull(),
});

export const notificationDeliveries = pgTable('notification_deliveries', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  recipientDeviceId: uuid('recipient_device_id').notNull().references(() => devices.id),
  type: varchar('type', { length: 64 }).notNull(),
  payload: jsonb('payload').$type<Record<string, unknown> | null>().default(null),
  status: varchar('status', { length: 32 }).default('queued').notNull(),
  attempts: integer('attempts').default(0).notNull(),
  lastError: text('last_error'),
  sentAt: timestamp('sent_at', { withTimezone: true }),
  nextAttemptAt: timestamp('next_attempt_at', { withTimezone: true }).defaultNow().notNull(),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
  updatedAt: timestamp('updated_at', { withTimezone: true }).defaultNow().notNull(),
});

export const auditLogs = pgTable('audit_logs', {
  id: uuid('id').defaultRandom().primaryKey(),
  ownerUserId: uuid('owner_user_id').notNull().references(() => users.id),
  actorDeviceId: uuid('actor_device_id').references(() => devices.id),
  action: varchar('action', { length: 128 }).notNull(),
  targetType: varchar('target_type', { length: 64 }).notNull(),
  targetId: varchar('target_id', { length: 255 }).notNull(),
  metadata: jsonb('metadata').$type<Record<string, unknown> | null>().default(null),
  ipAddress: text('ip_address'),
  createdAt: timestamp('created_at', { withTimezone: true }).defaultNow().notNull(),
});
```

---

## Snippet 4: Device Registration and Token Issuance

**What this shows:**  
This route creates a device record, automatically links it to opposite-role devices under the same account, and returns a signed device token used for device-level authentication.

**Source:** [Backend/routes/devices.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/devices.ts:41)

```ts
router.post('/register', requireAuth, async (req, res) => {
  const parsed = registerSchema.safeParse(req.body);

  if (!parsed.success) {
    res.status(400).json({ message: 'Invalid request body', errors: parsed.error.flatten() });
    return;
  }

  const authSession = req.auth;

  if (!authSession?.user?.id) {
    res.status(401).json({ message: 'Unauthorized' });
    return;
  }

  const now = new Date();
  const [device] = await db
    .insert(devices)
    .values({
      userId: authSession.user.id,
      name: parsed.data.name,
      role: parsed.data.role,
      isCamera: parsed.data.role === 'camera',
      platform: parsed.data.platform,
      appVersion: parsed.data.appVersion,
      pushToken: parsed.data.pushToken,
      status: 'online',
      lastSeenAt: now,
      updatedAt: now,
    })
    .returning({
      id: devices.id,
      userId: devices.userId,
      name: devices.name,
      role: devices.role,
      status: devices.status,
      platform: devices.platform,
      appVersion: devices.appVersion,
      lastSeenAt: devices.lastSeenAt,
      createdAt: devices.createdAt,
      updatedAt: devices.updatedAt,
    });

  if (!device) {
    res.status(500).json({ message: 'Unable to register device' });
    return;
  }

  const oppositeRole = device.role === 'camera' ? 'client' : 'camera';
  const oppositeDevices = await db.query.devices.findMany({
    where: and(eq(devices.userId, device.userId), eq(devices.role, oppositeRole)),
  });

  if (oppositeDevices.length > 0) {
    const linksToCreate = oppositeDevices.map((otherDevice) => ({
      ownerUserId: device.userId,
      cameraDeviceId: device.role === 'camera' ? device.id : otherDevice.id,
      clientDeviceId: device.role === 'client' ? device.id : otherDevice.id,
      status: 'active' as const,
    }));

    await db.insert(deviceLinks).values(linksToCreate).onConflictDoNothing();
  }

  const deviceToken = createDeviceToken({
    userId: device.userId,
    deviceId: device.id,
    role: device.role as 'camera' | 'client',
  });

  res.status(201).json({
    message: 'Device registered',
    device,
    deviceToken,
  });
});
```

---

## Snippet 5: Stream Request Lifecycle

**What this shows:**  
This route validates the client device, confirms the target is a linked camera, inserts a `stream_sessions` row, and emits a realtime `stream:requested` event in simplified mode.

**Source:** [Backend/routes/streams.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/streams.ts:97)

```ts
router.post('/request', requireDeviceAuth, async (req, res) => {
  const parsed = requestStreamSchema.safeParse(req.body ?? {});

  if (!parsed.success) {
    res.status(400).json({ message: 'Invalid request body', errors: parsed.error.flatten() });
    return;
  }

  const deviceAuth = ensureDeviceAuth(req, res);
  if (!deviceAuth) return;

  const [sourceDevice, cameraDevice] = await Promise.all([
    db.query.devices.findFirst({
      where: and(eq(devices.id, deviceAuth.deviceId), eq(devices.userId, deviceAuth.userId)),
    }),
    db.query.devices.findFirst({
      where: and(eq(devices.id, parsed.data.cameraDeviceId), eq(devices.userId, deviceAuth.userId)),
    }),
  ]);

  if (!sourceDevice || !cameraDevice) {
    res.status(404).json({ message: 'Source or camera device not found' });
    return;
  }

  if (sourceDevice.role !== 'client') {
    res.status(403).json({ message: 'Only client devices can request on-demand stream sessions' });
    return;
  }

  if (cameraDevice.role !== 'camera') {
    res.status(400).json({ message: 'cameraDeviceId must point to a camera device' });
    return;
  }

  const link = await db.query.deviceLinks.findFirst({
    where: and(
      eq(deviceLinks.ownerUserId, deviceAuth.userId),
      eq(deviceLinks.cameraDeviceId, cameraDevice.id),
      eq(deviceLinks.clientDeviceId, sourceDevice.id),
      eq(deviceLinks.status, 'active'),
    ),
  });

  if (!link) {
    res.status(403).json({ message: 'No active link between requester and camera' });
    return;
  }

  const now = new Date();

  const [session] = await db
    .insert(streamSessions)
    .values({
      ownerUserId: deviceAuth.userId,
      cameraDeviceId: cameraDevice.id,
      requesterDeviceId: sourceDevice.id,
      status: 'requested',
      reason: parsed.data.reason,
      metadata: parsed.data.metadata ?? null,
      mediaProvider: mediaProvider.name,
      updatedAt: now,
    })
    .returning();

  if (!session) {
    res.status(500).json({ message: 'Failed creating stream session' });
    return;
  }

  if (simpleStreamingEnabled) {
    const requestPayload = createStreamRequestedPayload(session);
    const deliveredToCamera = sendRealtimeToDevice(cameraDevice.id, 'stream:requested', requestPayload);

    console.info('[stream.request]', {
      streamSessionId: session.id,
      requesterDeviceId: sourceDevice.id,
      cameraDeviceId: cameraDevice.id,
      mode: 'simple',
    });

    sendRealtimeToDevice(sourceDevice.id, 'stream:requested', requestPayload);

    if (!deliveredToCamera) {
      await enqueuePushNotification({
        ownerUserId: cameraDevice.userId,
        recipientDeviceId: cameraDevice.id,
        type: 'stream_requested',
        payload: requestPayload,
      });
    }

    res.status(201).json({
      message: 'Stream request sent',
      streamSession: toSimpleStreamSessionResponse(session),
    });

    await writeAuditLog({
      ownerUserId: sourceDevice.userId,
      actorDeviceId: sourceDevice.id,
      action: 'stream.requested',
      targetType: 'stream_session',
      targetId: session.id,
      metadata: { cameraDeviceId: cameraDevice.id, reason: session.reason, transport: 'webrtc' },
      ipAddress: req.ip,
    });
    return;
  }
```

---

## Snippet 6: Stream Accept Lifecycle

**What this shows:**  
This route moves a stream session from `requested` to `streaming`, records start metadata, optionally initializes SFU state, and emits `stream:started` to the viewer.

**Source:** [Backend/routes/streams.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/streams.ts:276)

```ts
router.post('/:streamSessionId/accept', requireDeviceAuth, async (req, res) => {
  const parsedParams = streamParamSchema.safeParse(req.params);

  if (!parsedParams.success) {
    res.status(400).json({ message: 'Invalid streamSessionId', errors: parsedParams.error.flatten() });
    return;
  }

  const parsed = acceptStreamSchema.safeParse(req.body ?? {});

  if (!parsed.success) {
    res.status(400).json({ message: 'Invalid request body', errors: parsed.error.flatten() });
    return;
  }

  const deviceAuth = ensureDeviceAuth(req, res);
  if (!deviceAuth) return;

  const session = await db.query.streamSessions.findFirst({
    where: and(
      eq(streamSessions.id, parsedParams.data.streamSessionId),
      eq(streamSessions.ownerUserId, deviceAuth.userId),
      eq(streamSessions.cameraDeviceId, deviceAuth.deviceId),
    ),
  });

  if (!session) {
    res.status(404).json({ message: 'Stream session not found for this camera device' });
    return;
  }

  if (session.status !== 'requested' && session.status !== 'starting') {
    res.status(409).json({ message: `Stream session cannot be accepted from status ${session.status}` });
    return;
  }

  const now = new Date();
  const streamKey = parsed.data.streamKey ?? `stream_${session.id}_${randomUUID()}`;
  const mediaSession = await createLiveMediaSession({
    streamSessionId: session.id,
    ownerUserId: session.ownerUserId,
    cameraDeviceId: session.cameraDeviceId,
    requesterDeviceId: session.requesterDeviceId,
  });

  const [updated] = await db
    .update(streamSessions)
    .set({
      status: 'streaming',
      streamKey: mediaSession ? streamKey : null,
      mediaProvider: mediaSession?.provider ?? 'simple',
      mediaSessionId: mediaSession?.mediaSessionId ?? null,
      publishEndpoint: mediaSession?.publishUrl ?? null,
      subscribeEndpoint: mediaSession?.subscribeUrl ?? null,
      metadata: parsed.data.metadata ?? session.metadata,
      startedAt: now,
      updatedAt: now,
    })
    .where(eq(streamSessions.id, session.id))
    .returning();

  if (!updated) {
    res.status(500).json({ message: 'Failed to update stream session' });
    return;
  }

  if (sfuService) {
    try {
      await sfuService.startSession({
        streamSessionId: updated.id,
        ownerUserId: updated.ownerUserId,
        cameraDeviceId: updated.cameraDeviceId,
        requesterDeviceId: updated.requesterDeviceId,
      });
      await sfuService.setSessionState(updated.id, 'live');
    } catch (error) {
      console.error('Failed starting SFU session', error);
      res.status(500).json({ message: 'Failed to initialize SFU session' });
      return;
    }
  }

  const startedPayload = createStreamStartedPayload(updated);
  console.info('[stream.accept]', {
    streamSessionId: updated.id,
    requesterDeviceId: updated.requesterDeviceId,
    cameraDeviceId: updated.cameraDeviceId,
    mode: mediaSession ? 'legacy' : 'simple',
  });
  const deliveredToRequester = sendRealtimeToDevice(session.requesterDeviceId, 'stream:started', startedPayload);

  if (!deliveredToRequester) {
    await enqueuePushNotification({
      ownerUserId: session.ownerUserId,
      recipientDeviceId: session.requesterDeviceId,
      type: 'stream_started',
      payload: startedPayload,
    });
  }

  res.json({ message: 'Stream accepted', streamSession: toSimpleStreamSessionResponse(updated) });

  await writeAuditLog({
    ownerUserId: session.ownerUserId,
    actorDeviceId: session.cameraDeviceId,
    action: 'stream.accepted',
    targetType: 'stream_session',
    targetId: session.id,
    metadata: mediaSession
      ? { mediaSessionId: updated.mediaSessionId, mediaProvider: updated.mediaProvider }
      : { transport: 'webrtc' },
    ipAddress: req.ip,
  });
});
```

---

## Snippet 7: WebRTC Signal Relay

**What this shows:**  
This Socket.IO handler validates each signal packet against the owning account and active stream session before relaying SDP or ICE data to the target device room.

**Source:** [Backend/realtime/gateway.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/realtime/gateway.ts:323)

```ts
socket.on('webrtc:signal', async (input) => {
  const parsed = webrtcSignalSchema.safeParse(input);

  if (!parsed.success) {
    socket.emit('error:webrtc_signal', {
      message: 'Invalid WebRTC signal payload',
      errors: parsed.error.flatten(),
    });
    return;
  }

  const session = await db.query.streamSessions.findFirst({
    where: and(eq(streamSessions.id, parsed.data.streamSessionId), eq(streamSessions.ownerUserId, auth.userId)),
  });

  if (!session) {
    socket.emit('error:webrtc_signal', { message: 'Stream session not found for this account' });
    return;
  }

  if (!canRelayWebrtcSignal(session, auth.deviceId, parsed.data.toDeviceId)) {
    socket.emit('error:webrtc_signal', { message: 'Signal target is not a participant in this stream session' });
    return;
  }

  console.info('[stream.signal]', {
    streamSessionId: parsed.data.streamSessionId,
    fromDeviceId: auth.deviceId,
    toDeviceId: parsed.data.toDeviceId,
    signalType: parsed.data.signalType,
  });

  io?.to(roomForDevice(parsed.data.toDeviceId)).emit('webrtc:signal', {
    fromDeviceId: auth.deviceId,
    streamSessionId: parsed.data.streamSessionId,
    signalType: parsed.data.signalType,
    data: parsed.data.data ?? null,
  });
});
```

---

## Snippet 8: Motion Event Creation and Fan-Out

**What this shows:**  
This route creates a motion event, looks up all active client links for the camera, attempts realtime delivery, and falls back to queued push delivery when the client is offline.

**Source:** [Backend/routes/events.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/events.ts:35)

```ts
router.post('/motion/start', requireDeviceAuth, async (req, res) => {
  const parsed = startMotionSchema.safeParse(req.body ?? {});

  if (!parsed.success) {
    res.status(400).json({ message: 'Invalid request body', errors: parsed.error.flatten() });
    return;
  }

  const deviceAuth = req.deviceAuth;

  if (!deviceAuth) {
    res.status(401).json({ message: 'Unauthorized' });
    return;
  }

  const cameraDevice = await db.query.devices.findFirst({
    where: and(eq(devices.id, deviceAuth.deviceId), eq(devices.userId, deviceAuth.userId)),
  });

  if (!cameraDevice) {
    res.status(404).json({ message: 'Device not found' });
    return;
  }

  if (cameraDevice.role !== 'camera') {
    res.status(403).json({ message: 'Only camera devices can start motion events' });
    return;
  }

  const now = new Date();

  const [event] = await db
    .insert(events)
    .values({
      userId: deviceAuth.userId,
      deviceId: cameraDevice.id,
      title: parsed.data.title,
      triggeredBy: parsed.data.triggeredBy,
      status: 'recording',
      startedAt: now,
      videoUrl: parsed.data.videoUrl,
      updatedAt: now,
    })
    .returning();

  if (!event) {
    res.status(500).json({ message: 'Failed to create motion event' });
    return;
  }

  const activeLinks = await db.query.deviceLinks.findMany({
    where: and(
      eq(deviceLinks.ownerUserId, deviceAuth.userId),
      eq(deviceLinks.cameraDeviceId, cameraDevice.id),
      eq(deviceLinks.status, 'active'),
    ),
  });

  for (const link of activeLinks) {
    const delivered = sendRealtimeToDevice(link.clientDeviceId, 'motion:detected', {
      eventId: event.id,
      cameraDeviceId: cameraDevice.id,
      title: event.title,
      triggeredBy: event.triggeredBy,
      startedAt: event.startedAt,
    });

    await db.insert(notifications).values({
      eventId: event.id,
      userId: deviceAuth.userId,
      channel: delivered ? 'realtime' : 'queued',
      status: delivered ? 'delivered' : 'queued',
      isRead: false,
      sentAt: now,
    });

    if (delivered) {
      await db.insert(notificationDeliveries).values({
        ownerUserId: deviceAuth.userId,
        recipientDeviceId: link.clientDeviceId,
        type: 'motion_detected',
        payload: {
          eventId: event.id,
          cameraDeviceId: cameraDevice.id,
          startedAt: event.startedAt.toISOString(),
        },
        status: 'delivered',
        attempts: 1,
        sentAt: now,
        nextAttemptAt: now,
        updatedAt: now,
      });
    } else {
      await enqueuePushNotification({
        ownerUserId: deviceAuth.userId,
        recipientDeviceId: link.clientDeviceId,
        type: 'motion_detected',
        payload: {
          eventId: event.id,
          cameraDeviceId: cameraDevice.id,
          startedAt: event.startedAt.toISOString(),
        },
      });
    }
  }
});
```

---

## Snippet 9: Recording Finalization and Download URL Issuance

**What this shows:**  
This backend code finalizes a recording after upload, marks it ready in the database, and later issues a presigned MinIO download URL to the viewer.

**Source:** [Backend/routes/recordings.ts](/home/matiss/Documents/Final%20Year%20Project/Backend/routes/recordings.ts:64)

```ts
router.post('/:recordingId/finalize', requireDeviceAuth, async (req, res) => {
  const parsedParams = recordingParamSchema.safeParse(req.params);

  if (!parsedParams.success) {
    res.status(400).json({ message: 'Invalid recordingId', errors: parsedParams.error.flatten() });
    return;
  }

  const parsed = finalizeSchema.safeParse(req.body ?? {});

  if (!parsed.success) {
    res.status(400).json({ message: 'Invalid request body', errors: parsed.error.flatten() });
    return;
  }

  const deviceAuth = req.deviceAuth;

  if (!deviceAuth) {
    res.status(401).json({ message: 'Unauthorized' });
    return;
  }

  const recording = await db.query.recordings.findFirst({
    where: and(eq(recordings.id, parsedParams.data.recordingId), eq(recordings.ownerUserId, deviceAuth.userId)),
  });

  if (!recording) {
    res.status(404).json({ message: 'Recording not found' });
    return;
  }

  if (recording.cameraDeviceId !== deviceAuth.deviceId) {
    res.status(403).json({ message: 'Only camera device can finalize this recording' });
    return;
  }

  const now = new Date();
  const bucket = parsed.data.bucket;
  const objectKey = parsed.data.objectKey;

  await ensureMinioBucket();

  try {
    await minioClient.statObject(bucket, objectKey);
  } catch (error) {
    if (objectKey.startsWith('sim/')) {
      const placeholder = Buffer.from(
        JSON.stringify({
          message: 'simulated recording placeholder',
          recordingId: recording.id,
          streamSessionId: recording.streamSessionId,
          createdAt: now.toISOString(),
        }),
        'utf8',
      );

      await minioClient.putObject(bucket, objectKey, placeholder, placeholder.byteLength, {
        'Content-Type': 'application/json',
      });
    } else if (isMissingStorageObjectError(error)) {
      res.status(409).json({ message: 'Recording object does not exist in storage yet' });
      return;
    } else {
      throw error;
    }
  }

  const [updated] = await db
    .update(recordings)
    .set({
      objectKey,
      bucket,
      durationSeconds: parsed.data.durationSeconds,
      sizeBytes: parsed.data.sizeBytes,
      status: 'ready',
      availableAt: now,
      updatedAt: now,
      error: null,
    })
    .where(eq(recordings.id, recording.id))
    .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) => {
  const parsedParams = recordingParamSchema.safeParse(req.params);

  if (!parsedParams.success) {
    res.status(400).json({ message: 'Invalid recordingId', errors: parsedParams.error.flatten() });
    return;
  }

  const deviceAuth = req.deviceAuth;

  if (!deviceAuth) {
    res.status(401).json({ message: 'Unauthorized' });
    return;
  }

  const recording = await db.query.recordings.findFirst({
    where: and(eq(recordings.id, parsedParams.data.recordingId), eq(recordings.ownerUserId, deviceAuth.userId)),
  });

  if (!recording) {
    res.status(404).json({ message: 'Recording not found' });
    return;
  }

  if (recording.status !== 'ready' || !recording.objectKey || !recording.bucket) {
    res.status(409).json({ message: 'Recording is not available yet' });
    return;
  }

  try {
    await minioClient.statObject(recording.bucket, recording.objectKey);
  } catch (error) {
    if (isMissingStorageObjectError(error)) {
      res.status(409).json({ message: 'Recording file is missing from storage' });
      return;
    }

    throw error;
  }

  const downloadUrl = await minioClient.presignedGetObject(
    recording.bucket,
    recording.objectKey,
    minioPresignedExpirySeconds,
  );

  res.json({
    recordingId: recording.id,
    objectKey: recording.objectKey,
    bucket: recording.bucket,
    downloadUrl,
    expiresInSeconds: minioPresignedExpirySeconds,
  });
});
```

---

## Snippet 10: Web App State Model

**What this shows:**  
This is the client-side state shape for the browser app. It tracks authentication, registered device identity, live stream state, motion activity, notifications, and UI modal state.

**Source:** [WebApp/src/lib/app/store.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/store.js:5)

```js
export const createInitialState = () => ({
	page: 'auth',
	session: null,
	device: null,
	deviceToken: null,
	socketConnected: false,
	isMotionActive: false,
	activeMotionSource: null,
	cameraStatus: 'idle',
	cameraPreviewReady: false,
	cameraInputDevices: [],
	selectedCameraInputId: '',
	linkedCameras: [],
	recordings: [],
	motionNotifications: [],
	activeCameraDeviceId: null,
	activeStreamSessionId: null,
	openLinkedCameraMenuId: null,
	activityLog: [],
	cameraSessions: {},
	connectedStreamSessionIds: [],
	loading: true,
	isRegistering: false,
	authForm: {
		email: '',
		password: '',
		name: ''
	},
	onboardingForm: {
		name: '',
		role: 'client',
		pushToken: ''
	},
	toasts: [],
	recordingModal: {
		open: false,
		title: 'Recording Playback',
		url: ''
	},
	motionDetection: {
		enabled: false,
		profile: 'balanced',
		state: 'idle',
		score: 0,
		debug: false,
		lastTriggeredAt: null
	},
	clientStreamMode: 'none',
	clientPlaceholderText: 'Select a camera to view',
	lastError: null
});
```

---

## Snippet 11: WebRTC Offer Creation in the Web App

**What this shows:**  
This frontend controller method creates an SDP offer on the camera side and sends it through the backend Socket.IO relay to the client device.

**Source:** [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:1159)

```js
const startOfferToClient = async (streamSessionId, requesterDeviceId) => {
	if (!socket) return;

	const connection = await ensurePeerConnection({
		streamSessionId,
		targetDeviceId: requesterDeviceId,
		asCamera: true
	});

	const offer = await connection.createOffer();
	await connection.setLocalDescription(offer);
	socket.emit('webrtc:signal', {
		toDeviceId: requesterDeviceId,
		streamSessionId,
		signalType: 'offer',
		data: offer
	});
};
```

---

## Snippet 12: Recording Finalization from the Web App

**What this shows:**  
This frontend code polls for the `awaiting_upload` recording row, uploads the locally captured WebM file to object storage, and then calls the backend finalize endpoint.

**Source:** [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:1178)

```js
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));

const finalizeRecordingForStream = async (streamSessionId, captureResult) => {
	const currentDevice = getAppState().device;
	if (!currentDevice?.id) {
		addActivity('Recording', 'No device identity for finalize');
		return false;
	}

	for (let attempt = 0; attempt < 8; attempt += 1) {
		const recs = await api.ops.listRecordings().catch(() => ({ recordings: [] }));
		const recording = (recs.recordings || []).find(
			(rec) => rec.streamSessionId === streamSessionId && rec.status === 'awaiting_upload'
		);

		if (recording?.id) {
			try {
				if (!captureResult?.blob || captureResult.blob.size === 0) {
					throw new Error('No captured video blob to upload');
				}
				const compressedBlob = await compressRecordingBlob(captureResult.blob);

				const uploadMeta = await api.request('/videos/upload-url', {
					method: 'POST',
					body: JSON.stringify({
						fileName: `stream-${streamSessionId}.webm`,
						deviceId: currentDevice.id,
						prefix: 'recordings',
						recordingId: recording.id
					})
				});

				const uploadResponse = await fetch(uploadMeta.uploadUrl, {
					method: 'PUT',
					headers: { 'Content-Type': compressedBlob.type || 'video/webm' },
					body: compressedBlob
				});

				if (!uploadResponse.ok) {
					throw new Error(`Upload failed with status ${uploadResponse.status}`);
				}

				await api.events.finalizeRecording(recording.id, {
					objectKey: uploadMeta.objectKey,
					bucket: uploadMeta.bucket,
					durationSeconds: captureResult.durationSeconds,
					sizeBytes: compressedBlob.size
				});

				addActivity('Recording', 'Recording uploaded and finalized');
				return true;
			} catch (error) {
				console.error('Recording upload failed, falling back to simulated key', error);
				const fallbackObjectKey = `sim/${streamSessionId}/${Date.now()}.webm`;
				await api.events.finalizeRecording(recording.id, {
					objectKey: fallbackObjectKey,
					durationSeconds: captureResult?.durationSeconds ?? 15,
					sizeBytes: captureResult?.blob?.size ?? 5000000
				});
				addActivity('Recording', 'Upload failed; finalized with simulator fallback');
				return true;
			}
		}

		await sleep(350);
	}

	addActivity('Recording', 'No recording row found to finalize');
	return false;
};
```

---

## Snippet 13: Motion Event Lifecycle in the Web App

**What this shows:**  
This controller code starts a motion event, begins local recording, and later ends the motion event while either closing a stream or uploading a standalone motion clip.

**Source:** [WebApp/src/lib/app/controller.js](/home/matiss/Documents/Final%20Year%20Project/WebApp/src/lib/app/controller.js:1299)

```js
const getMotionStartPayload = (source = 'manual') =>
	source === 'auto'
		? { title: 'Automatic Motion', triggeredBy: 'auto_motion' }
		: { title: 'Simulated Motion', triggeredBy: 'motion' };

const startMotionEvent = async ({ source = 'manual' } = {}) => {
	if (getAppState().isMotionActive || lastMotionEventId) {
		return false;
	}

	const response = await api.events.startMotion(getMotionStartPayload(source));
	await startCameraPreview();
	await startLocalRecording();
	lastMotionEventId = response.event.id;

	const startedAt = new Date().toISOString();
	setAppState({
		isMotionActive: true,
		activeMotionSource: source
	});

	if (source === 'auto') {
		updateMotionDetectionRuntime({ lastTriggeredAt: startedAt });
	}

	pushToast(source === 'auto' ? 'Automatic motion event started' : 'Motion Event Started', 'success');
	addActivity(
		'Motion',
		source === 'auto' ? `Automatic motion event started (${response.event.id})` : `Started event ${response.event.id}`
	);
	return true;
};

const endMotionEvent = async ({ source = 'manual' } = {}) => {
	if (!lastMotionEventId) {
		return false;
	}

	const eventId = lastMotionEventId;
	const streamSessionId = activeRecordingStreamSessionId;

	if (streamSessionId) {
		await api.streams.end(streamSessionId);
		addActivity('Stream', `Ended stream ${streamSessionId}`);
	} else if (activeMediaRecorder?.state === 'recording') {
		const captureResult = await stopLocalRecording();
		await uploadStandaloneMotionRecording(captureResult);
	}

	await api.events.endMotion(eventId);
	lastMotionEventId = null;
	setAppState({
		isMotionActive: false,
		activeMotionSource: null
	});

	pushToast(source === 'auto' ? 'Automatic motion event ended' : 'Motion Ended', 'success');
	addActivity(
		'Motion',
		source === 'auto' ? `Automatic motion event ended (${eventId})` : `Ended event ${eventId}`
	);
	return true;
};

const syncAutoMotionLifecycle = async ({ activeMotion }) => {
	if (autoMotionTransitionInFlight) {
		return;
	}

	if (activeMotion) {
		if (getAppState().isMotionActive || lastMotionEventId) {
			return;
		}

		autoMotionTransitionInFlight = true;
		try {
			await startMotionEvent({ source: 'auto' });
		} catch (error) {
			console.error('Failed to auto-start motion event', error);
			pushToast(error.message || 'Failed to start automatic motion event', 'error');
		} finally {
			autoMotionTransitionInFlight = false;
		}
		return;
	}

	if (!isAutoMotionEventActive()) {
		return;
	}

	autoMotionTransitionInFlight = true;
	try {
		await endMotionEvent({ source: 'auto' });
	} catch (error) {
		console.error('Failed to auto-end motion event', error);
		pushToast(error.message || 'Failed to end automatic motion event', 'error');
	} finally {
		autoMotionTransitionInFlight = false;
	}
};
```
