How FlowTrack Pro handles your data — the mechanics, not the marketing.
FlowTrack Pro — flowtrackpro.net
Last updated: May 28, 2026
Our posture: Tenant isolation is enforced at two layers — Express middleware and Postgres row-level security. Even if the application code has a bug, the database rejects cross-tenant queries. The page below walks through the mechanics: what we run, what we retain, what gets deleted, where it lives. Every claim links back to a policy doc in this repository.
1. Encryption
All traffic between your browser and FlowTrack Pro is encrypted in transit over TLS. Render, our application host, terminates TLS at its edge load balancer and presents a valid certificate for flowtrackpro.net; HTTP requests redirect to HTTPS. Outbound calls from our application to Supabase, Stripe, Resend, Twilio, Mapbox, and Anthropic also use TLS — none of those provider APIs accept plaintext HTTP.
At rest, your data lives in Supabase's managed Postgres cluster,
which encrypts the underlying disk volumes by default. Supabase
Storage objects (uploaded device photos, district form templates,
and company logos) are encrypted at rest in the same way.
Authentication tokens issued by Supabase Auth are signed JWTs; we
store them only in the browser's localStorage on your
device, never on disk on our servers.
We do not run our own database, our own key-management system, or our own SMTP server — we delegate the encryption surface to providers whose entire business is operating it correctly.
2. Tenant Isolation
FlowTrack Pro is multi-tenant: every customer's company shares one
Postgres database, and every tenant-scoped row carries a
company_id foreign key. Two layers enforce isolation,
and they are independent of each other.
Layer one is application-level. Every authenticated API request hits an Express middleware that reads the caller's Supabase JWT, then constructs a per-request Supabase client scoped to that user's session. This client is what every route handler uses to read or write data — there is no shared, ambient database connection that could be reused across requests.
Layer two is database-level. Every tenant-scoped table has a
Postgres row-level security policy that re-checks
company_id = auth_company_id() on every
SELECT, INSERT, UPDATE, and
DELETE. auth_company_id() is a SECURITY
DEFINER function that reads the caller's JWT and returns the
company UUID embedded in their profile. If layer one were ever
bypassed — a routing bug, a stale connection, a forgotten
req.supabase swap — the database still rejects the
query.
Even if the application code has a bug, the database rejects cross-tenant queries.
Two endpoints intentionally bypass row-level security: Stripe's billing webhook (no user JWT exists yet) and the signup flow (the company row doesn't exist yet either). Both use a separate Supabase service-role client with narrow, audited responsibilities.
3. Backups
FlowTrack Pro's database runs on the Supabase Pro tier at $25/month. Pro tier provides Daily logical backups of the entire Postgres database, taken automatically, with 7-day retention — the most recent seven daily backups are accessible from the Supabase dashboard and can be restored to a new project by the operator.
Point-in-Time Recovery is not enabled. PITR is a separate Supabase add-on at $100/month per 7 days of retention and requires an additional compute add-on. Daily backups with 7-day retention meet our ~24h RTO and ~24h RPO at our current scale, and we have intentionally chosen not to overstate this. If a customer contract requires sub-24h RPO, PITR can be enabled in the Supabase dashboard with no application code change and this page updated to match.
The backup posture and disaster-recovery runbook (operator triages → restore from backup → new project created → env vars repointed → smoke test) are documented in full in the policy below. Recovery time at current data size is estimated at 30–60 minutes.
Full policy: docs/backup-policy.md
4. Data Export
Company admins can download a complete copy of their company's data
at any time from Settings → Data Export. The
endpoint is POST /api/account/export, defined in
src/routes/account.js, and it returns a ZIP archive in
seconds — there is no async email pipeline.
The archive contains JSON and per-table CSV dumps covering
customers, customer_locations, devices, test_records, work_orders,
scheduled_jobs, invoices, audit_log, and team profiles, plus URL
manifests for device photos and district form templates. The exact
layout is generated by src/services/exportBuilder.js.
Access is restricted to the company_admin role —
technicians, office staff, customer-portal users, and district
admins cannot trigger an export. The endpoint is also rate-limited
to 5 requests per hour per IP to prevent runaway scripted exports.
Every export call is recorded in audit_log.
Full policy: docs/data-retention.md
5. Deletion on Cancellation
When you cancel your subscription via the Stripe customer portal,
Stripe records a "cancel at end of period" event and fires a
customer.subscription.updated webhook to FlowTrack
Pro. Our handler in src/routes/billing.js reads
cancel_at_period_end=true and pins a grace clock to
your paid-period end timestamp.
The 30-day grace window starts when that timestamp
passes. During grace, your account remains read-only — you can
still log in, view your data, and run a full export via
POST /api/account/export. The 30-day number is locked
in code as GRACE_DAYS = 30 in
src/services/anonymize.js and is not configurable
per-account. If you reverse the cancellation during grace, the
grace clock is cleared and your account returns to normal active
state with no data lost.
Once the grace clock expires, the daily anonymization sweep (runs
at 04:00 America/Los_Angeles via
src/services/scheduler.js) identifies your company
and performs hard anonymization, transactionally per company, in
this order: invoice customer_snapshot frozen with
identity fields, invoice customer_id nulled,
audit_log identity stripped, companies row
tombstoned, then customers, customer_locations, devices,
test_records, work_orders, scheduled_jobs, notification_log,
notification_emails, company_settings, profiles, and finally
auth.users for every team member — all permanently
deleted.
Three records survive anonymization with identity stripped so we
can answer "what happened?" without disclosing "who did it": the
tombstoned companies row, invoices (with
customer_id=NULL and the frozen
customer_snapshot JSONB), and audit_log
entries. Everything else — your customer list, device records,
test results, scheduled jobs, and team auth identities — is
irreversibly gone.
The anonymization service refuses to run unless three independent
safety layers pass: identity (company exists), cancellation
(subscription_status === 'canceled'), and grace
expired (deletion_clock_starts_at non-NULL and at
least 30 days in the past). Any failed layer halts every write.
Full policy: docs/data-retention.md
6. Hosting Region
FlowTrack Pro's Node + Express application runs on Render.com in
Render Oregon (us-west). The Supabase project
that holds the database, Auth, and Storage runs in
Supabase us-west — verified as Supabase region
us-west-1 on 2026-05-28 (see the Verification History
table in docs/backup-policy.md and docs/hosting-regions.md). The
two providers are colocated; typical round-trip between Render and
Supabase within the same physical region is under 5 ms.
Customer data does not leave US infrastructure unless required by law. Our operator confirms the live regions in both provider dashboards before every major release and records the result in the Verification History tables on the policy docs below — so the claim on this page is dated, not implied.
Full policy: docs/hosting-regions.md
Questions?
We are happy to walk through any of this in detail — particularly if your buying process needs technical specifics for a security review. The policy docs linked from each section are the source of truth; this page is a guided tour.