WattOps

Security and data flow

Last updated 14 October 2026

This page is for the people who review a vendor before their organisation uses it: what WattOps runs on your machines, what leaves them, what we keep, and how the service is built. The Privacy Policy and the Data Processing Agreement are the binding documents; this page explains the mechanics behind them. We countersign the DPA and complete security questionnaires on request through the contact form.

In one paragraph

joules, the measurement tool, is open source (MIT), written against the Python standard library only, with no dependencies. It reads the energy counters the hardware already exposes. It sends nothing unless a command asks it to (--track, --share, joules login, or joules agent --track), and then only numbers and short names: never prompts, outputs, command-line arguments, file paths, file contents or code. The website and API run on Vercel; the database and sign-in run on Supabase in the United States. The backend holds no service-role key: it reaches the database only through SQL functions that check a server secret, and every private table also has row-level security as a second lock.

What runs on your side

ComponentWhat it isWhat it readsNetwork
joules run, joules benchA command-line tool that wraps one command or benchmarks one local modelGPU energy from NVML (NVIDIA driver library), /sys/class/hwmon (AMD, Intel), CPU and DRAM energy from /sys/class/powercap (RAPL), powermetrics on Apple Silicon, and the command's CPU timeNone, unless --track or --share is given
joules agentOne process per GPU server or cluster nodeThe meters above; /proc and cgroups to map processes to Slurm jobs, Kubernetes pods, containers and users; GPU memory per process (NVML) and DRM usage per process (AMD, Intel)Listens on 127.0.0.1:9877 for Prometheus (/metrics, /jobs, /health). With --track, sends each finished job and, on the Max plan, one heartbeat every 5 seconds
joules proxyAn HTTP proxy in front of a model serverThe meters, and token counts from the server's responsesListens on 127.0.0.1:8787. With --track, one summary per model every 5 minutes
joules ciThe pull request energy checkThe meters, or the command's CPU time on hosted runnersThe GitHub API, only with --comment

Privileges. NVIDIA counters are readable by any user. AMD and Intel GPU counters are readable by any user on most distributions. RAPL counters need root, or a one-time chmod a+r on the energy_uj files (joules doctor prints the exact command). powermetrics on a Mac needs sudo; joules asks once. The agent needs root to read other users' processes, which is what lets it split energy by job. The systemd unit and the Kubernetes DaemonSet we ship (integrations/cluster-agent/) show the exact access each needs.

Updates. Nothing updates itself and nothing phones home. The installers update joules when you run them again; pipx upgrade landauer-gap does the same.

What leaves your machines

The API accepts only the fields listed here, rejects any other field, and caps every request at 32 KB. --json prints the full local report, of which the sent record is a subset.

CommandWhat is sentWhen
joules run --track, joules bench --trackProject name; a label that is the program and script name (python train.py) or your --label; start time; duration; energy; cost; CO₂; electricity price; grid intensity; the GPU model names or CPU name; GPU count; whether idle was subtracted; whether meters were simulated; joules version; which meter kinds were used; operations and Landauer gap if you gave --params or --tokens; exit code; for a bench, output tokens and joules per token; on NVIDIA GPUs, what the card was doing as percentages (clock as a share of maximum, busy, memory-controller busy, share of time throttled), its hottest temperature, its power limit, the main throttle reason and a one-word reading (compute, memory, idle, mixed)Once, when the run ends
joules bench --shareModel name, backend, device, device count, energy per token, tokens per second, average power, joules versionOnce, when you ask. The public leaderboard shows medians only, never who shared
joules agent --trackEach finished job as a tracked run (the fields above, with the job name as the label and the Unix user as the user)When a job finishes
joules agent --track on the Max planA heartbeat: node name (--name sets it), watts, idle watts, GPU count, idle GPU count, price, grid intensity, and up to 50 jobs with name, user, kind, GPU count, watts and idle wattsEvery 5 seconds; each heartbeat is deleted after 6 hours
joules proxy --trackOne tracked run per model with the model name as the labelEvery 5 minutes
joules login, joules doctorlogin sends the key once to check it. doctor checks the key and the connection unless --offline is given, and its report contains no key, machine name, user name or home folderWhen you run them

Never sent: prompts, model outputs, command-line arguments or their values, inline code, environment variables, file paths, file contents, or your machine name (the agent's node name is the one exception, and --name controls it).

How the service is built

Retention and deletion

Sub-processors

ServiceWhat it does for usWhere
Supabase, Inc.Database and sign-inUnited States (us-east-1)
Vercel Inc.Website and API hostingUnited States and Vercel's global network
Stripe, Inc. and its affiliatesPayments (billing contacts only)United States and other countries
jsDelivrServes the sign-in library to your browserGlobal network
Google FontsServes the typefaces to your browserGlobal network
GitHub and GoogleYour profile picture, if you signed in with themUnited States

We update this list at least 14 days before a new sub-processor starts processing personal data, as the DPA sets out.

Assurance

Reporting a vulnerability

Use the contact form and say it is a security report; we reply by email. Our security.txt is at wattops.dev/.well-known/security.txt. Please test only against accounts you own.

If something goes wrong

Under the DPA we tell you without undue delay after we become aware of a personal data breach affecting your data, with the information you need to meet your own obligations. Where a breach creates a real risk of significant harm, we also report it to the Privacy Commissioner of Canada as the law requires.

PHENEX TECHNOLOGIES INC., Vancouver, British Columbia, Canada.