Security
For the person who has to say yes before a new service gets real data: an IT administrator, a procurement officer, a careful engineer. It takes about five minutes, and every statement on it describes what runs today.
Tag Historian is built and run by Softi AB, a small company in Sweden. Where we do not do something a larger supplier would, this page says so.
Last updated
At a glance
| Question | Answer |
|---|---|
| Where is my data stored? | In Microsoft Azure's Sweden Central region. The offsite copies of our backups are in Sweden South, the paired Swedish region, though the measurement backup cannot be restored from there yet: what we do not have yet says why. |
| Is it encrypted? | In transit with TLS 1.2 or later on every connection to Tag Historian, and at rest by Azure. The one exception is yours to choose: an alert webhook you give an http:// address is sent unencrypted. |
| How do people sign in? | Email and password, with lockout and rate limits, and two-factor sign-in with an authenticator app, which each person can turn on and an Admin can require of the whole team. |
| How do devices send data? | With API keys that are stored only as hashes and limited to Read, Write or Admin. A key is a machine's credential and takes no second factor. |
| Can I get all my data out? | Yes, at any time: measurements, tags and settings in one archive, as CSV or Parquet, and the alert history and team list from the API, as JSON. |
| Can I have it deleted? | Yes. Every store that holds your account's data has to confirm it is gone before we call the deletion done. Six things outlive it, each for a stated reason: listed below. |
| Who else processes it? | Microsoft (Azure and Microsoft 365), Stripe for payments and Resend for email. |
| Any certifications? | None of our own. Azure's certifications cover the platform we run on, not our service. |
| How do I report a vulnerability? | Email support@taghistorian.com. We acknowledge every report within five business days. |
Where your data lives
Measurements, the account database and our service logs are kept in Azure Sweden Central. Measurements are backed up every night to a geo-redundant Azure Backup vault, and the account database is copied every day to geo-redundant storage; the offsite copy of both is in Sweden South. There is no region to choose, and your measurement data does not leave Sweden unless you read or export it, or an alert you set up carries a value to where you told it to go.
Every file is written under your own customer id, and a request for another account's data is refused, not filtered. Both recovery points, and what happens when something breaks, are on where your data lives.
Encryption
- In transit. This website, the Explorer and the API answer over HTTPS only, and plain HTTP is redirected. All three send HSTS, so a browser that has been here once will not try plain HTTP again. Our storage refuses connections older than TLS 1.2, and the database requires TLS 1.2 or later. What we send out goes over HTTPS as well: email, the push and chat services you connect, and your webhooks, unless you give a webhook an
http://address, which we then use as given. - At rest. Measurements, the account database, backups and logs are encrypted by Azure with keys Microsoft manages. It is always on. We do not hold a separate key per customer, so treat it as protection for the disks and the copies, not as a wall between customers; the customer id on every file and every request is that wall.
- Secrets you give us. The tokens and webhook addresses of alert channels, and the secret an alert rule signs its webhooks with, are stored encrypted and never shown again in clear.
Signing in, and who can reach what
Your side
- Passwords are stored as salted, deliberately slow hashes (ASP.NET Core Identity's PBKDF2), never in clear. Five wrong passwords lock the account for 15 minutes, and one network address can make at most 10 sign-in attempts a minute, whichever accounts it aims them at, so a list of leaked passwords tried from one machine goes no faster than that.
- Two-factor sign-in. Anyone who signs in to the Explorer can turn it on in Settings, with any authenticator app that makes time-based codes. Signing in then takes a code from the app after the password. Each code works once, and wrong codes count toward the same 15-minute lock as wrong passwords. Ten recovery codes, each good once, get you in without your phone; they are shown once and stored only as hashes. Turning it on ends every other session you had, at once, and every change to it, and every recovery code used, is emailed to you.
- An Admin who uses two-factor sign-in can require it of everyone on the account. A member without it sets it up at their next sign-in, before they get in, and their open sessions are not renewed until they have.
- Signed-in sessions are kept on our side only as hashes. Signing out revokes the session on our side as well, so it cannot be renewed, and signs out every open tab. Removing someone from the team deletes their sessions with them, and they are signed out at once.
- Team members each have a role, Viewer, Editor or Admin, and every API key a scope: Read, Write or Admin. A key is shown once, when it is made, and stored only as a SHA-256 hash, so nobody can read it back out of our database, us included.
- API keys are credentials for machines, and a request with one never asks for a second factor. Give each device or integration a key of its own, with the smallest scope that works, and revoke it in Settings when the device goes.
- Read-only links. An Editor or Admin, signed in, can share one saved chart view with someone who has no account. The link opens that chart and nothing else - not the API, not another view, not a tag's own name - and is stored only as a hash, like a key. Its secret part sits after the
#, which browsers send to no server. Every link expires within a year, Settings lists them all with who made each and when it was last opened, and revoking one stops it at once. See sharing a chart by link.
Our side
- Password sign-in to the account database is switched off. The service signs in to the database and to its archive storage with an Azure managed identity, and a person who administers it signs in with their own Microsoft Entra account. No password opens it.
- The daily copy of the database is made by a job with an identity of its own, which can read the database and change nothing in it, and write only to the storage the copies are kept in.
- Our release pipeline signs in to Azure with short-lived tokens (OpenID Connect), not with a stored secret.
- Export archives are kept in private storage. They download only with the account's own credentials and a role that may export, or through a link made at that moment, which stops working after 15 minutes.
How the service is built
- No third-party code in your browser. This website and the Explorer load no analytics, trackers, fonts or scripts from anyone else, and set no cookies. A Content-Security-Policy tells your browser to refuse scripts from any other site, and neither site can be shown inside another site's frame.
- Nothing ships untested. The full test suite runs on every change to our main branch, and any compiler or lint warning fails it. A release is built and deployed only from a commit whose suite passed; the one way around that is a deliberate override for emergencies, which announces itself in the release's log.
- No credentials in the code. An automated scan checks every push to our main branch for the credential patterns we know to look for, and fails it when it finds one.
- Dependencies kept current. Updates for our libraries, container images and build tools are proposed every week, and every build of the .NET service checks its packages against the public database of known vulnerabilities.
- The code on your side is open. The Home Assistant integration, the Python client and the MCP server are published under the Apache 2.0 licence at github.com/softi-dev/tag-historian-clients, so you can read exactly what they send. The collector is not open source.
How it is run
- Monitoring. Azure checks the API, the Explorer and this website every 15 minutes from two locations in the EU, and emails us when one stops answering, when the API's errors or restarts rise, when the database or storage has trouble, and when a nightly job fails: the backup, the archive, retention or the database copy.
- Status. The status page shows whether the API and the Explorer are answering right now.
- Backups. Measurements are backed up nightly and kept for 30 days. The account database can be put back to any moment of the last 35 days, and its daily copy is kept for 35 days; every copy is restored into a scratch database and checked table by table before it counts.
- Restore drills: one of several. On 20 October 2026 we restored the account database's daily copy from Sweden South, and every table matched. Restoring measurements, or the account database to an earlier moment, within Sweden Central is written down and its commands checked; standing the account database up on a new server from its daily copy is written down. None of those has been rehearsed end to end yet, so we publish no recovery time, and restoring measurements after losing the whole region waits on Microsoft (below). The durability page says which paths have been drilled.
- Logs. Our service logs are deleted within 90 days of being written and are used only to run and troubleshoot the service. The privacy policy lists what they hold.
- Uptime. The self-service plans are best-effort, with no uptime SLA, and there is no staffed round-the-clock operations team: alerts reach us by email.
Your data, your rights
- Take it with you. Export everything, in Settings, builds your measurements, your tags and the account's settings into one archive, as CSV or Parquet with a README that explains every file, and it can be downloaded for 7 days. The alerts your rules raised and the team's users come from the API, as section 9 of the privacy policy lists. The API also exports any single tag at any time. No fee, open formats: how long data is kept.
- Have it deleted. An Admin of the account can schedule its deletion through the API, or you can ask us by email. You have 30 days to change your mind. Then an automated job deletes the account's data from every store that holds it, and calls the deletion done, and emails you, only when each of them has answered that nothing of the account is left.
- What outlives a deletion. Six things, each for a stated reason: invoices, for the seven years Swedish accounting law requires; encrypted backups, until they age out within 90 days; a dated record that the deletion happened; the audit log with its descriptions erased; our service logs, for up to 90 days; and the email you have written to us. Section 4 of the privacy policy describes each one.
- Who else handles it. Microsoft hosts the service (Azure) and our mailboxes (Microsoft 365), both in the EU; Stripe handles payments, and Resend delivers our email from the United States. GitHub holds our code and no production data. Section 5 of the privacy policy says what each of them receives, and section 12 what the transfers outside the EU rest on.
Reporting a vulnerability
If you think you have found a security problem in Tag Historian, in this website, the Explorer, the API, the collector or the Home Assistant integration, please tell us.
How to report it
- Email support@taghistorian.com with
Securityat the start of the subject, in English or Swedish. - Say what you found, how to reproduce it, and what it let you reach. A proof of concept is welcome; other people's data is not, so please leave it out.
What we promise
- A reply from a person within five business days, saying we have your report.
- Our assessment, and news as the fix progresses.
- A note when the fix is live, and, if you want it, your name in the changelog entry for it.
What we ask
- Use only an account of your own, and stay within our Terms of Service, which do not allow trying to get into other accounts or into our systems.
- Do not open, change or delete data that is not yours. If you come across some, stop there and tell us what you saw.
- No denial of service or load testing, no spam, and no social engineering of us or of the companies we work with.
- Give us a reasonable time to fix the problem before you publish it. We suggest 90 days, and will tell you if we need longer, and why.
We do not pay bounties. The same contact is in machine-readable form in our security.txt.