Skip to main content

Media Library & Operational Logs (Admin)

Audience: Ops · Super-admins · Support · Engineering · Where in app: /admin/call-backgrounds, /admin/call-recordings, /admin/default-videos, /admin/api-request-logs, /admin/email-logs, /admin/logs, /admin/notifications, /admin/webhook-events, /admin/storage/maintenance · Access: Super-admin only (verify — admin-portal routes; the log routes are passport-authed admin-only).

This cluster covers two things. Media library: the platform-default assets shown in product surfaces (call backgrounds, the widget/invitation default videos) and the browsing UI for call recordings. Operational logs: read-only forensics for support and engineering — what API requests came in, what emails went out (and which failed), what errored in the system, what notifications were broadcast, plus the webhook-event registry tenants can subscribe to.

What it does

  • Call Backgrounds — upload/delete the default background images offered in calls; mark one default.
  • Call Recordings — browse recordings across four sources (Twilio, AI, inbound/outbound AI phone, forwarded), with playback.
  • Default Videos — manage the default widget video and the client-invitation demo video (file upload or URL); set the active default.
  • API Request Logs — inspect incoming API requests (method, path, platform); 30-day TTL.
  • Email Logs — every sent/failed outbound email with full headers and content.
  • System Logs — error/info/warning entries with company/session/user context; 30-day TTL.
  • Notifications — broadcast an admin notification to companies/users and view history.
  • Webhook Events — the catalog of subscribable webhook event types with sample payloads.
  • Storage Maintenance — storage stats (Mongo + S3) and dry-run-first session-recording cleanup.

How it works

Frontend repos live under frontend/src/repositories/admin/ and views under frontend/src/views/admin/. Media uploads use multipart form-data (backgrounds) or a chunked/streamed upload with client-side compression (utils/streamUpload, default videos). Recordings are not stored in Mongo directly here — playback URLs point at ms-communication endpoints (Twilio compositions, Ultravox/ElevenLabs AI recordings). Logs are MongoDB collections; two of them (api_requests, logs) carry a 30-day TTL index that auto-purges old rows.

Screens & fields

Call Backgrounds — /admin/call-backgrounds

Source: call-backgrounds/List.vuefrontend/src/repositories/admin/call-backgrounds.js (/default-call-backgrounds). Model DefaultCallBackgroundModel.js (collection default_call_background).

Grid of background image cards; one shows a Default badge. An upload card creates a new background (POST multipart with the image file). Delete per card.

FieldNotes
fileObjectId → files (the stored image)
defaultbool — the active default background
timestampscreated_at / updated_at

Call Recordings — /admin/call-recordings

Source: call-recordings/Index.vue (tabbed) → frontend/src/repositories/admin/call-recordings.js. Four tabs:

TabSourceRepo call / endpoint
Twilio RecordingsTwilio compositionsgetCallRecordings/call-recordings; playback …/twilio/play-recording/:sid
AI RecordingsUltravox/ElevenLabs AI callsgetAICallRecordings/ai-call-recordings; playback …/ultravox/play-ai-recording/:callId
Inbound & Outboundms-communication AI phone callsgetAIPhoneTranscripts…/inbound-outbound-calls (transcripts + ElevenLabs audio)
Forwarded Callsforwarded callsgetForwardedCalls/call-forwarded

Common list filters: page/pageSize, sort/order, start/end date. Helpers: getCallType (video vs audio), formatDuration (→ HH:mm:ss), markCallAsHeard / markAllCallsAsHeard, getUnheardCallsCount, deleteRecording (soft delete), getElevenLabsAudio (blob). The inbound/outbound super-admin view can pass include_deleted=true to show soft-deleted calls; deleteAIPhoneCall soft-deletes (sets deleted_at, company-scoped).

Default Videos — /admin/default-videos

Source: default-videos/List.vue ("Video Templates") → frontend/src/repositories/admin/default-videos.js (/default-video). Model DefaultVideoModel.js (collection defaultvideos).

Category selector drives the view: widget (grid of templates) and client_invitation (a single demo-video URL field). Upload is staged (Uploading → Compressing → Saving) with progress; videos can also be created from a URL (createDefaultVideoUrl). Star icon = Set as Default (setDefaultVideoPUT /create-default-video/:id).

FieldNotes
video_pathstored video path (URL-sourced)
video_fileObjectId → files (uploaded file)
categorywidget (default) / client_invitation
is_defaultbool — active default for the category
has_audiobool
is_activebool, default true

API Request Logs — /admin/api-request-logs + …/:id

Source: api-request-logs/List.vue + Detail.vuefrontend/src/repositories/admin/api-request-logs.js (/api-request-logs). Controller ApiRequestLogController, model ApiRequestModel.js (collection api_requests).

FilterNotes
Searchpath / method / IP / platform
MethodAll · GET · POST · PUT · PATCH · DELETE
Platformsortable column/filter
Start/End daterange

List columns: Method, Path, Platform, IP, time. Detail shows the full record:

FieldNotes
method, path
headers, params, query, bodymixed/JSON, nullable
ip, user_agent, platform
user_idref → users
created_at

Retention: 30 daysSchema.index({ created_at: -1 }, { expireAfterSeconds: 60*60*24*30 }) (the same index serves date-range sort).

Email Logs — /admin/email-logs + …/:id

Source: email-logs/List.vue + Detail.vuefrontend/src/repositories/admin/email-logs.js (/email-logs). Model EmailLogModel.js (collection email_logs).

FilterNotes
Search
Sort / order
Start/End daterange

Status enum: sent / failed (the repo also exposes EMAIL_LOG_STATUS with SENT: 'send' and color helpers — green/sent, red/failed). Fields: from, to, cc, bcc, reply_to (all mixed — string or array), subject, content, status, error (mixed), timestamps. Indexed on {status, created_at} and {created_at}. No TTL — email logs are retained.

System Logs — /admin/logs

Source: logs/List.vue ("System Logs") → frontend/src/repositories/admin/logs.js (/error-logs). Model LogModel.js (collection logs).

Filters: search, sort (Date newest/oldest). A grouped view is available (getGroupedErrorLogs/error-logs/grouped). List columns include Type, Description, context, Actions (view, delete). Fields:

FieldNotes
typeerror (default) / info / warning
description
company_id, user_session_id, service_room_idstring context, nullable
user_typeadmin / user (default user)
created_at

Indexed on {type, created_at}. Retention: 30 days (TTL on created_at). Individual logs can be deleted (deleteErrorLog).

Storage Maintenance — /admin/storage/maintenance

Source: frontend/src/views/admin/StorageMaintenance.vuefrontend/src/repositories/admin/storage.js. Backend: AdminStorageController (backend/app/routes/adminStorageRoutes.js), user_type === 'admin' enforced per request. Two panels, both background jobs with progress polling:

PanelEndpointsWhat
Storage Stats (read-only)POST /admin/storage/stats + GET /admin/storage/stats/jobs/:job_idWhole-DB and session_files sizes from Mongo metadata (no collection scan) + live S3 bucket object count/size (paged listing — large buckets take a minute)
Session Recordings CleanupPOST /admin/storage/session-files-cleanup + GET /admin/storage/session-files-cleanup/jobs/:job_idDeletes session_files docs + their S3/local chunks. Selectors: older_than_days (retention sweep) and/or min_files (runaway kiosk/bot sessions) — at least one required

Cleanup is proxied to ms-sessions' api-key-gated /migrations/session-files-cleanup; stats are computed in the backend (shares the Mongo DB and S3 bucket). Every action defaults to dry run — review counts, then Apply (confirm dialog; deletion is permanent).

Notifications — /admin/notifications

Source: notifications/Index.vuefrontend/src/repositories/admin/notifications.js. Compose + send an admin broadcast (POST /admin/notifications/send) and view history (GET /admin/notifications). Model AdminNotificationModel.js (collection admin_notifications).

FieldNotes
title, messagerequired content
target_typeall_companies / companies / all_users / users
target_ids[]specific company/user ids when not "all" (typeahead via searchCompanies / searchUsers)
target_names[]resolved labels
sent_byadmin who sent it
recipients_countcomputed fan-out size
created_at

Targeting "companies"/"users" reveals a search box to pick specific recipients; "all_companies"/"all_users" broadcasts. (Per-recipient delivered notifications land in the notifications collection — NotificationModel.js.)

Webhook Events — /admin/webhook-events

Source: webhook-events/Index.vuefrontend/src/repositories/admin/webhook-events.js (/webhook-events). Model WebhookEventModel.js (collection webhook_events). The catalog of event types companies can subscribe their webhooks to — not the per-delivery log.

Filter: status. Create/edit via modal:

FieldNotes
namemachine key, e.g. new_lead
labeldisplay, e.g. New Lead
descriptionwhen it fires
sample_payloadmixed/JSON example shown to subscribers
statusactive / inactive
created_byref → users

Distinguish from per-delivery webhook logs (WebhookLogModel.js) and tenant webhook configs (WebhookModel.js) — this screen manages the event-type definitions only.

Behaviors & edge cases

  • Retention: api_requests and logs auto-purge after 30 days (TTL index). email_logs, admin_notifications, webhook_events, and media collections are retained until manually deleted. Recording media retention is governed by the upstream provider (Twilio / ElevenLabs), not these screens.
  • One default per category: call backgrounds have a single default; default videos have one is_default per category (widget vs client_invitation). Setting a new default flips the previous one.
  • Default-video upload is staged and compressed client-side (Uploading 0–40% → Compressing 40–80% → Saving 80–99%); URL-sourced videos skip compression.
  • Recordings are external — playback URLs resolve against ms-communication; a 404 usually means the provider purged the asset. Inbound/outbound AI calls are soft-deleted (deleted_at) and only re-appear with include_deleted=true.
  • Notification "all" vs targeted: all_companies/all_users ignore target_ids; companies/users require picked ids. recipients_count reflects the resolved fan-out.
  • Webhook Events are definitions, not deliveries — editing a sample payload changes documentation/subscription scaffolding, not any past delivery.
  • Email logs store full content + headers — treat as sensitive (PII / message bodies).

Technical implementation

  • Models: backend/app/models/ApiRequestModel.js, EmailLogModel.js, LogModel.js, AdminNotificationModel.js, NotificationModel.js, WebhookEventModel.js, DefaultVideoModel.js, DefaultCallBackgroundModel.js.
  • Routes/controllers: backend/app/routes/apiRequestLogRoutes.js + ApiRequestLogController; email-log, error-log, notification, webhook-event, default-video, call-background routes/controllers under backend/app/.
  • Frontend repos: frontend/src/repositories/admin/{call-backgrounds,call-recordings,default-videos,api-request-logs,email-logs,logs,notifications,webhook-events}.js; views under frontend/src/views/admin/ (matching folders).
  • Recording playback is served by ms-communication (Twilio compositions, Ultravox/ElevenLabs AI recordings).