Read-only by design: what that actually means for a storage optimizer
Every vendor claims "read-only". Very few explain what they are asking for at the Graph permission layer or what they store on their side. Here is exactly what TSO asks for and why.
When you consent to a Microsoft 365 app, the permissions you approve are the ceiling of what it can ever do. Not what it currently does — what it can ever do, up until you revoke consent. That is why the exact permission list matters more than the marketing copy.
The exact scopes TSO requests
- Sites.Read.All — read SharePoint site + drive metadata.
- Files.Read.All — read file metadata (name, size, hash, timestamps). Not file content.
- Reports.Read.All — read the usage reports Microsoft already generates for the tenant.
- Directory.Read.All — resolve user and group names for the ownership column.
- User.Read.All — resolve mailbox owners.
That is it. There is no Sites.Manage.All, no Files.ReadWrite.All, no Mail.Send. The Graph API physically will not let the TSO service delete, move or modify anything in your tenant even if it wanted to.
What TSO stores on its side
Every scan writes to the TSO SQL database in Azure UK South (default) or your chosen region (MSP self-hosted). The stored rows are:
- Site + drive metadata — id, name, url, storage used, item count.
- File-level rows for anything above the size threshold — name, path, size, hash, timestamps, owner id.
- Aggregated recommendations derived from those rows.
Never file contents. Never email bodies. Never Teams messages. Every row deletes on scan-record deletion. Every workspace deletes on request — the export button on the settings page ships you a JSON of everything TSO knows about your tenant before we purge.
