Docs menu Security & data
Docs

Security & data

Where your data lives, how it's protected, what isolation looks like under the hood, and how the right-to-be-forgotten flow works.

Where the data lives

Everything customer-facing runs on Cloudflare's UK edge — the application Worker, the API, the static assets and the CDN cache. The database sits on PlanetScale Postgres (UK region) fronted by Cloudflare Hyperdrive for low-latency edge access. Authentication is WorkOS AuthKit; the user / member tables on our database are a mirror of the WorkOS source-of-truth so every authenticated request resolves through one identity provider.

Some services that support the platform — sign-in, billing, product analytics and weather — run outside the UK. The sub-processors page lists each one with its region.

Maps and location look-ups

Postcode and address look-ups run from our servers, and only when you ask for one — saving a site, importing sites or pressing "Find location". Here is what each outside service receives:

  • Postcodes go to postcodes.io, which returns the postcode's centre point. When a search includes a postcode that it recognises, nothing else from the address is sent anywhere. Northern Ireland postcodes aren't looked up.
  • Address searches without a usable postcode are sent to OpenStreetMap's Nominatim service. We cache the search text and its results for 30 days so the same search isn't repeated.
  • Weather requests to Open-Meteo carry a site's latitude and longitude, and nothing that identifies you or the site's owner.
  • Map tiles are loaded by your browser from the map tile provider, which sees the area you're viewing.

The open data behind these, and the attribution each licence asks for, is on the data attributions page.

solarfleet.io/settings/data
Data governance UK data residency · Cloudflare
Roles & permissions
Full control · billing · delete org Owner
Manage sites · members · integrations Admin
View & act on every site Member
Right to be forgotten Hard-delete every tenant row · 24h confirmation window Delete organisation
Illustrative: the data-governance panel under Settings. Role permissions are intra-org; deletion runs the owner-only right-to-be-forgotten cascade. Values shown are generic examples.

Tenant isolation

Every query the application makes filters by organisation. There is no shared-cache or shared-state path where one organisation's data could leak into another's response. Two enforcement layers:

  • Code-level. Every API route resolves the caller's organisation from their session and applies an organisation_id = ? filter on every query. This is the primary guard.
  • Test-level. A repo-wide integration test sweeps every /api/* route and asserts that none of them can be coaxed into returning another organisation's data. The test runs on every push to main; a regression blocks the deploy.

The internal /admin namespace is locked down: internal-only endpoints are gated to InspireGreen staff. Customers can't reach it even with a valid session for their own org.

Credential encryption

All third-party API credentials (SolarEdge keys, Solis Cloud secrets, Stripe webhook secrets, future provider tokens) are encrypted at rest with AES-256-GCM. The master encryption key is a Cloudflare Workers secret — it isn't present in source, isn't in environment files, and isn't accessible to non-platform code.

Credentials are stored encrypted at rest (AES-256-GCM). The scheme is versioned so we can rotate it without breaking historic rows.

Transport security

  • TLS on every connection; modern browsers negotiate TLS 1.3. Plain HTTP redirects to HTTPS.
  • HSTS on every response (one-year max-age, including subdomains). We don't use the browser preload list.
  • X-Content-Type-Options: nosniff and a strict-origin-when-cross-origin referrer policy on every response. Nothing can frame SolarFleet: pages and the API send X-Frame-Options: DENY and an enforced frame-ancestors 'none' (the one exception is the report preview, which only our own pages can frame).
  • The API sends an enforced Content Security Policy (default-src 'none'). Pages send a resource Content Security Policy in report-only mode for now — they use inline scripts that need nonces before it can be enforced — which allows only the third parties listed on our sub-processors page, plus the map tile hosts named on the data attributions page.
  • A Permissions-Policy turns the microphone off everywhere. Pages keep the camera and location for our own origin only, because the field app takes and geotags inspection photos; the API turns both off.

UK GDPR posture

We're UK GDPR compliant. The legal basis for processing customer data is contract performance — without it the platform doesn't work. Telemetry from third-party APIs is captured under the customer's contract with those providers; we don't acquire or share data with anyone outside the platform.

You can review the full privacy policy for the legal version.

Right to be forgotten

Owners can initiate a complete data deletion from Settings → Billing → Delete organisation. The flow has a 24-hour confirmation window — the request is logged, an email goes to every owner on the account, and the destructive action only fires after a second click from the original initiator confirming intent.

On confirmation:

  • Every tenant row across telemetry, equipment, alerts, cases, visits, reports, documents is hard-deleted.
  • The organisation record itself is anonymised (we keep an audit row that an org with this id existed and was deleted on this date, but no identifying fields remain).
  • All member rows, pending invitations, integration credentials and notification subscriptions are deleted.
  • The corresponding Stripe customer is closed and billing terminates.

The deletion is atomic and irreversible. We confirm completion to the initiator's email of record.

Reporting a security issue

Responsible disclosure: security@solarfleet.io. We acknowledge within one working day and aim to triage within three. We don't run a bug bounty programme right now, but we'll credit you on the security page if you'd like.

Next up