Cookie Policy
Last updated: September 13, 2026
ServiceRunner uses very little browser storage, and none of it for advertising. This page lists every key the web app and mobile apps set, what it is for, how long it lasts and which consent category it belongs to.
1. Overview
"Cookies" in this policy means any technology that stores information on your device: HTTP cookies, localStorage, sessionStorage, IndexedDB, the Origin Private File System used by our offline database, service-worker caches, and the native preference store used by the iOS and Android apps. Isles Mechanical LLC sets these only for the purposes below.
We set no HTTP cookies. Authentication uses a bearer token held in localStorage and sent in the Authorization header; there is no session cookie, no CSRF cookie and no rate-limit cookie (rate limits are keyed by IP address on the server). No advertising, analytics or social-media cookies are loaded. Map tiles are fetched from a third-party tile server, which may see your IP address when tiles load; it does not set cookies on our origin.
2. Categories
- Strictly necessary. Required for the Service to work: sign-in, remembering your organization, working offline, storing your consent choice. These do not require consent under ePrivacy rules and cannot be switched off.
- Functional. Convenience preferences that are not essential, such as remembering that you dismissed a prompt today. Off by default; switching them off means the prompt may reappear.
- Analytics. Measurement of how the Service is used. None are in use. If we introduce any, they will only load after you enable this category, and this page will list them first.
- Advertising. Not used and not planned.
3. Storage We Set
3.1 localStorage (web app and mobile web view)
| Key | Purpose | Lifetime | Category |
|---|---|---|---|
sr_auth_token | Your sign-in session token. Sent with each API request. | Until sign-out or session expiry | Strictly necessary |
sr_current_org | Which organization you last worked in, so the app opens there. | Until sign-out | Strictly necessary |
sr_dark_mode | Your light/dark theme choice. | Persistent | Strictly necessary (display preference) |
sr_offline_sites | Which sites you chose to keep available offline. | Persistent | Strictly necessary |
sr_storage_persist_asked | Records that we already asked the browser for persistent storage, so we do not ask again. | Persistent | Strictly necessary |
sr_site_access | Cache of your site permissions for offline use. | Until sign-out | Strictly necessary |
sr_push_token | The push-notification registration token last sent to our server, to avoid re-registering. | Until sign-out | Strictly necessary |
sr_notif_prefs_<siteId> | Per-site notification preferences you set. | Persistent | Strictly necessary (user setting) |
servicerunner_device_id | A random identifier for this browser or device, used to attribute time entries created offline and resolve sync conflicts. Not shared with third parties. | Persistent | Strictly necessary |
sr_proximity_suppress | Remembers that you dismissed the "you are near a site" prompt today. | 1 day | Functional |
sr_cookie_consent | Your cookie choices: { necessary, functional, analytics, ts, version }. | 12 months | Strictly necessary |
sr_invoice_draft:v1:<userId>:<orgId>:<context> | An invoice form you explicitly save on this device, including customer/site labels, line items, notes and terms. It is not an issued invoice. | Until you discard it or it is removed after a confirmed save; browser storage clearing also removes it | Strictly necessary (requested draft recovery) |
sr_invoice_intent:<userId>:<orgId>:<action> | Pending invoice change and idempotency information, so an uncertain request can be retried without duplicating it. | Until the request is confirmed or definitively rejected, or browser storage is cleared | Strictly necessary |
3.2 sessionStorage
| Key | Purpose | Lifetime | Category |
|---|---|---|---|
| Reload guards (chunk-retry timestamps) | Prevents an endless reload loop when a new app version is deployed while you have it open. | Browser tab | Strictly necessary |
sr_qbo_authorization | QuickBooks connection callback check: organization and user identifiers, hashed session/state fingerprints and creation time. It does not store the Intuit authorization code or OAuth tokens. | Removed when the callback is consumed; expires for validation after 10 minutes or when the tab closes | Strictly necessary |
3.3 IndexedDB and offline database
| Database | Purpose | Lifetime | Category |
|---|---|---|---|
servicerunner-photo-blobs | Photos you captured while offline, queued for upload. | Until uploaded or sign-out | Strictly necessary |
| Offline sync database (one SQLite file per organization, in the browser's origin storage) | Local copy of the sites, tasks, equipment and records you have access to, so the app works without a connection. | Until sign-out or "clear offline data" | Strictly necessary |
3.4 Service-worker caches (installed web app)
| Cache | Purpose | Lifetime | Category |
|---|---|---|---|
| Precache (app shell) | The application's own code and assets. | Until the next version is installed | Strictly necessary |
navigation-cache, app-shell-fallback | Lets the app open offline. | Rolling | Strictly necessary |
google-fonts | Cached web fonts. | Up to 1 year | Strictly necessary |
photo-cache, plan-image-cache, plan-thumb-cache | Recently viewed photos and plan images for offline viewing. | Rolling, size-limited; cleared on sign-out | Strictly necessary |
3.5 Native apps (iOS and Android)
| Store / key | Purpose | Lifetime | Category |
|---|---|---|---|
App preferences: sr_bg_location_queue | Location points recorded in the background while clocked in, waiting to be sent to your organization. | Until synced | Strictly necessary (only when location tracking is enabled) |
| Web-view storage | The same keys as in 3.1 to 3.4. | As above | As above |
| Push token (Firebase Cloud Messaging) | Issued by the platform so notifications can reach the device. | Until app removal or token refresh | Strictly necessary (only if you allow notifications) |
4. Third-Party Content
Pages that show a map load base-map tiles from the configured map tile provider. The source default is OpenStreetMap Foundation tile servers; deployments can configure a keyed provider such as CARTO. Fonts may be loaded from Google Fonts on first visit and then cached. Our subscription checkout and billing management open Stripe-hosted pages. Customer invoice and recurring-agreement payment pages instead load Stripe's secure payment fields in the page. Stripe may use its own storage or security signals to process payments and prevent fraud; see the Stripe Privacy Policy. Connecting QuickBooks Online sends you to Intuit's authorization pages, governed by the Intuit Privacy Statement. Signing in with Google, Microsoft or Apple takes you to that provider's pages, governed by their policies. Their storage is separate from the first-party keys listed above.
5. The Consent Banner and Your Choices
On your first visit we show a small banner at the bottom of the page. It does not block the page. "Accept all" turns on the functional and analytics categories; "Necessary only" keeps only strictly necessary storage; "Manage" opens a dialog where you can set each category. Your choice is stored in sr_cookie_consent in this browser and we do not ask again for 12 months, unless this policy changes materially.
You can change your choice at any time using the "Cookie preferences" link in the page footer, or by clearing site data in your browser (which also signs you out). Because we load no optional technology today, the practical effect of your choice is limited to the functional keys listed above.
5.1 Global Privacy Control
If your browser sends the Global Privacy Control signal, we treat it as an opt-out: the analytics category is kept off regardless of what you click, and the banner tells you so.
5.2 Browser controls
You can block or clear storage in your browser settings. Blocking localStorage or IndexedDB will prevent you from signing in or working offline. The Service does not respond to "Do Not Track" headers because there is no tracking to disable; it does respond to Global Privacy Control.
6. Changes and Contact
We update this page whenever we add or remove a key, database or cache. Material changes (for example, introducing analytics) bump the consent version so that the banner is shown again. Questions: privacy@app.servicerunner.app. See also the Privacy Policy.