For the complete documentation index, see llms.txt. This page is also available as Markdown.

Screenshot & Recording Upload

How the We360.ai desktop agent uploads screenshots and screen recordings — out-of-band signed-URL / data-relay pipeline, server-side encryption, and segregated object storage.

The desktop agent never blocks tracking on media transfer. Screenshots and screen recordings are captured to disk, referenced from the activity event by a small identifier, and uploaded out-of-band on the regular sync ticks. The telemetry event itself carries no image bytes — only the identifier the backend later resolves to the stored object.

This decoupling means a slow or unreachable object store never delays activity data, and a media upload can retry independently without ever losing an event.


The image identifier

Every screenshot is addressed by an opaque imageId — e.g. a date-scoped token, optionally prefixed with enc/ when the tenant has encryption enabled. The agent computes it at capture time and writes it into the activity event's image_path.

The backend is the single source of truth for turning an imageId into a storage key:

<tenant>/screens/<identity>/<imageId>.png

The tenant and identity segments always come from the authenticated token, never from the client — so a compromised or crafted identifier can never write into another tenant's or user's space. The agent only ever supplies the opaque imageId; it never constructs a full storage path.

Because the same derivation is used when signing the upload URL and when signing the read URL, an object written out-of-band lands exactly where the viewer later looks for it.


Upload routes

Which route the agent uses depends on whether the tenant has screenshot encryption enabled.

The full image is uploaded directly to the object store via a short-lived pre-signed PUT URL requested from the backend. A matching pre-signed URL is used for the thumbnail.

If the direct PUT is blocked (e.g. a corporate firewall that allows only the We360.ai API host), the agent transparently falls back to the data relay — same bytes, same verb, an allow-listed host.

The data relay

The data relay is a media-upload endpoint used both as the encrypted-upload path and as the firewall fallback for direct uploads. It has two wire-compatible implementations — one embedded in the core service, one a standalone service — that the agent cannot tell apart. Authentication is performed at the mesh, which forwards the validated tenant and identity; the relay derives the storage path from those authenticated principals plus the agent-supplied imageId.

For encrypted tenants the standalone relay fetches the tenant's encryption configuration from an internal, service-only API and caches it. If that configuration cannot be retrieved, the upload fails closed — the relay never stores plaintext when the encryption state is unknown.


Segregated storage

Screenshots and screen recordings are stored in separate backends and are never crossed:

  • Screenshots → image object store (full image + thumbnail).

  • Screen recordings → video object store.

The relay routes each upload by media kind to the correct backend. Screen recordings now upload through the relay endpoints as well; the earlier signed-URL recording endpoints remain available but are deprecated.


Resilience & local cleanup

Uploads are asynchronous and self-healing:

  • On a transient failure the local file is kept on disk and retried on the next sync tick; a blocked direct upload falls back to the relay automatically.

  • A local file is deleted only on a strictly-validated success response — a genuine relay acknowledgement or a confirmed object-store PUT, not merely any 2xx. A misconfigured or wrong endpoint can never trigger premature deletion.

  • As a disk-safety backstop, a file that has still not uploaded 30 days after capture is pruned.

Because the activity event is synced independently of the bytes, a stuck upload only means a temporarily missing preview in the portal — never a lost event or a lost work record.


Data flow

Last updated

Was this helpful?