Trust & security

Built for trades that handle PII.

Stelid is enterprise-grade by construction — RLS-isolated tenancy, GDPR Article 17 / 20 / 30 flows, EU AI Act Article 50 transparency, biometric app lock, runtime tamper protection. Plain English on this page; the real proof is in the code.

AES-256 Encryption
SOC 2 Infrastructure
GDPR Compliant
Row-Level Security
PCI DSS via Stripe
HSTS Preloaded
Security

Defence in depth, not lipstick on a CRUD app.

Tenant isolation by default

Every table is RLS-enabled with org-scoped policies enforced inside Postgres. Cross-tenant reads are physically impossible — not policy-prevented, structurally prevented. Magic-link and survey-token paths route through the admin client, never via permissive policies.

Encrypted in transit and at rest

TLS 1.3 to every endpoint (HSTS preload-eligible). Postgres at rest encrypted by Supabase. Tokens stored in Capacitor Preferences (iOS Keychain / Android EncryptedSharedPreferences) on native, IndexedDB on web — never in plain localStorage.

Hardened authentication

Email + magic link via Supabase Auth, OAuth via Google. CSRF protection on every state-changing route via Origin validation. Rate-limited at the edge: 10 auth attempts/min per IP, 5 password resets/hour.

Biometric app lock (opt-in)

Face ID, Touch ID, fingerprint, or PIN guards the dashboard on native. PIN is PBKDF2-hashed (600k iterations); 20 wrong PINs wipes local data. Off by default — your call.

Runtime app self-protection

capacitor-freerasp detects root, jailbreak, debugger, emulator, Frida/Objection/Xposed hooks, app-integrity tampering, unofficial install source, malware, screen capture, ADB, dev mode, time spoofing, and system VPN. High-severity threats surface as a toast and write an audit row.

Rate-limited at the API edge

Email 10/hr, AI 30/hr, upload 30/hr, public 5/min, write 60/min, admin destructive 5/hr. Rate-limit metadata returned via standard 429 + Retry-After headers.

Compliance

Regulators don't accept good intentions. They accept evidence.

GDPR Article 17 — right to erasure

One-click account deletion at /account/delete. Sweeps all PII-bearing tables (devices, map pins, AI audit, bookings, time entries, marketing leads). Audit row written before anonymisation so the trail survives the deletion.

GDPR Article 20 — data portability

One-click export at /account/export returns a single JSON document covering jobs, properties, customers, invoices, time entries, AI audit log, sync conflict log, devices, marketing lead, and PostHog event history.

GDPR Article 30 — record of processing

Every export and deletion is logged to data_subject_requests with IP, user agent, timestamp, and request type. Append-only — supervisory authorities get a tamper-evident audit on demand.

GDPR Articles 33-34 — breach notification

data_breach_incidents tracks detection, containment, authority notification, and affected-party notification timelines. The 72-hour clock starts when status moves out of "investigating".

EU AI Act Article 50 — AI transparency

Every AI surface renders an AIGeneratedBadge and carries data-ai-generated="true" on the output element. Every AI call writes an audit row with model + provider + token usage. Org-wide kill switch one click away in /settings/ai-transparency.

PostHog kill-switch (org-wide)

Setting "Disable analytics" suppresses both client-side captures and server-side captures (Stripe webhook, AI audit, estimate-accept, all of it). Enforced at the database layer — no event escapes.

Operational integrity

Things that go wrong, before they go wrong.

Offline-first by construction

401 session expiry parks queued work indefinitely (never dead-letters). The sync engine persists across app restarts, network changes, and OS-killed background tasks. Your data is never silently dropped.

Native runtime isolation

Native iOS + Android apps are thin Capacitor 8 WebViews around stelid.com. iOS runs under App Sandbox; Android under per-app data directory. No app code ships with secrets — everything flows through the auth-gated API.

EU-hosted analytics

PostHog runs in eu.posthog.com. No analytics data leaves the EU.

Security headers on every response

HSTS (preload-eligible), X-Frame-Options DENY, X-Content-Type-Options nosniff, Referrer-Policy strict-origin-when-cross-origin, Permissions-Policy locking down camera/microphone/geolocation per-route, CSP allowing only the hosts we actually use.

Found something?

Responsible disclosure.

Email security@stelid.com with a description, reproduction steps, and (if you have one) a proof of concept. We acknowledge within 48 hours and aim to fix critical issues within 7 days.

Please don't run automated scanners against production. We have a staging environment available on request — same code, no real customer data.