Session Recordings
Capture the built-in WebRTC technician screen-share as a stored video, disclose recording to the end user, control recording per agent, and replay, export, or auto-retain the results.
Session recordings extend the built-in WebRTC remote-desktop feature: when recording is enabled, the technician's screen-share of an agent is captured to a single WebM file on the server, with a metadata row you can list, replay in the browser, download, or delete. Whether a given session is recorded is decided on the server before the session starts — the technician's browser can never turn recording on by itself.
How recording works#
Recording is decided once, at session start, and enforced by the server:
- When a screen-share session reaches the connected state, the server resolves a record decision and a disclose decision and stamps them on the live session. These flags — not any browser or helper reply — are the authoritative truth.
-
Only if the record flag is
truedoes the browser obtain a recording id (POST api/recordings/begin). If recording is not enabled for the session,beginis refused with409 Conflictand no recording row is ever created. - The browser then streams captured video to the server in chunks, appended to a single per-session file. Chunks are written straight to disk — the whole session is never buffered in memory.
- When the session ends the recording is finalized: the server repairs the WebM duration, computes a whole-file SHA-256, and stamps the end time, duration and final size.
Because the record decision is resolved server-side and begin is refused unless
that decision is true, a technician cannot self-authorize a recording — even by
calling the API directly.
Recording captures the built-in WebRTC screen-share only. The optional RustDesk integration is a separate remote-access path and is not captured by this feature.
Record policy & disclosure#
Whether a session is recorded is the combination of a global default and an optional per-agent override:
-
Global default —
RemoteSession:Recording:RecordSessionssets the fleet-wide default (record on or off). -
Per-agent override — each agent carries a tri-state
RecordPolicyOverride. When set, it beats the global default for that machine: Always forces recording on, Never forces it off, and Inherit clears the override so the agent follows the global default again.
Policy resolution is default-deny: if the server cannot read the effective policy for any reason, the session is not recorded. The per-agent override is exposed in the agent-details UI and via the API and PowerShell (see below).
Disclosure to the end user is controlled globally, independent of the per-agent record override:
| Setting | Purpose | Default |
|---|---|---|
RemoteSession:Recording:DiscloseToUser | Show the end user that the session is being recorded | true |
RemoteSession:Recording:DisclosureMessage | Text shown to the end user when disclosure is on | This session is being recorded. |
Every recording row also snapshots, at capture start, the consent state and whether recording
was disclosed (wasDisclosed), so the disclosure that was in effect is preserved
with the recording.
Recording metadata#
Each recording is described by a metadata row. The recording id is also the name
of its on-disk folder.
| Field | Meaning |
|---|---|
id | Recording unique identifier (also the on-disk folder name) |
agentId | Agent the recording belongs to |
sessionId | Screen-share session the recording captures |
technicianUsername | Technician who captured the recording |
startTime | When capture started |
endTime | When capture finished (null until finalized) |
durationSeconds | Total duration in seconds (null until finalized) |
fileSizeBytes | On-disk size of the recording file (grows as chunks arrive) |
sha256 | Whole-file SHA-256 hash (null until finalized) |
consentState | Snapshot of the consent state at capture start |
wasDisclosed | Whether recording was disclosed to the end user |
status | Lifecycle status (see below) |
A recording moves through these statuses:
| Status | Meaning |
|---|---|
recording | Capture in progress — chunks are being appended |
finalizing | Close in progress (duration repair + hashing) |
complete | Finalized cleanly — duration, size and SHA-256 stamped |
partial | Finalized from the uploaded prefix (e.g. an interrupted in-flight recording) |
failed | Finalize could not produce a usable file (e.g. the on-disk file was missing) |
Viewing, exporting & deleting#
Recordings are served as WebM video. Any Operator or Admin may list an agent's recordings, read a recording's metadata, stream it in the player, or download it:
- Stream supports HTTP Range requests, so the player can seek within the recording.
- Download returns the file as a named attachment (
recording-<id>.webm). Because a download exports data off the system, it is written to the audit log. - Delete removes both the metadata row and the on-disk folder. Deleting a recording is Admin-only and is audited.
Reads are not ownership-restricted — any Operator or Admin can view any recording; the controls are the unguessable recording id plus the role policy. Uploads and finalize are restricted to the owning technician (or an Admin).
Storage & retention#
Recordings are stored on the server as one WebM file per recording, under
{StoragePath}/{recordingId}/recording.webm. A background retention sweep runs
about once an hour and purges recordings whose start time is older than the retention window,
deleting the file first and then the metadata row, and writing a RecordingPurged
audit event for each.
| Setting | Purpose | Default |
|---|---|---|
Recording:Enabled | Master switch for session recording storage | false in code; true in the shipped appsettings.json |
Recording:StoragePath | Where recording folders are written | ./recordings |
Recording:RetentionDays | Age (in days) after which recordings are purged; 0 or blank = keep forever | 30 |
Recording:MaxSessionSizeMB | Maximum size captured for a single session | 2048 |
Set Recording:RetentionDays to 0 (or leave it blank) to retain
recordings indefinitely — the retention sweep becomes a no-op and nothing is purged.
Roles#
| Action | Minimum role |
|---|---|
| List / view / stream / download recordings | Operator |
| Upload chunks / finalize a recording | Owning technician (or Admin) |
| Set an agent's record policy | Operator |
| Delete a recording | Admin |
See Roles & Permissions for the full role model.
REST API#
| Method & path | Purpose |
|---|---|
POST api/recordings/begin | Mint the recording id for a live, record-enabled session (idempotent per session; 409 if recording is not enabled) |
GET api/agents/{agentId}/recordings | List an agent's recordings, newest first |
GET api/recordings/{id} | Get a single recording's metadata |
POST api/recordings/{id}/chunk | Append captured bytes to the recording (owner/Admin) |
POST api/recordings/{id}/finalize | Close the recording — repair duration, hash, stamp end time (owner/Admin) |
GET api/recordings/{id}/stream | Stream the WebM with Range support for the player |
GET api/recordings/{id}/download | Download the WebM as an attachment (audited) |
DELETE api/recordings/{id} | Delete the recording row and file (Admin only, audited) |
POST api/agents/{id}/record-policy | Set the per-agent record override ({ "policy": true | false | null } = Always / Never / Inherit) |
Recording endpoints require the Operator or Admin role, with DELETE restricted to
Admin. See the API Reference for conventions and authentication.
PowerShell#
| Cmdlet | Purpose |
|---|---|
Get-AthenaRecording | List an agent's recordings (-AgentId) or fetch one by id (-Id) |
Set-AthenaAgentRecordPolicy | Set an agent's record override: -Policy Always / Never / Inherit |
# Force recording on for every "kiosk"-tagged agent, then list a machine's recordings
Get-AthenaAgent -Tag "kiosk" | Set-AthenaAgentRecordPolicy -Policy Always
Get-AthenaRecording -AgentId "12345678-1234-1234-1234-123456789012"
See the PowerShell Module reference for connection and session details.
Recording start, finalize, download, delete and retention purge are all written to the
audit log (RecordingStarted, RecordingFinalized /
RecordingPartial / RecordingFailed, RecordingDownloaded,
RecordingDeleted, RecordingPurged). See
Audit & SIEM.