Security

What we do with what you trust us with.

Specifics rather than badges. This is how authentication, money and client-facing pages actually work.

Passwords

Hashed with scrypt and a per-user random salt, then compared in constant time so response timing reveals nothing. We cannot read your password, and neither can anyone with database access. Login responses are deliberately identical for “no such user” and “wrong password”, so the form cannot be used to enumerate accounts.

Sessions

A session is an opaque random token stored server-side and delivered in an httpOnly, SameSite=Lax, signed cookie. JavaScript can never read it, which removes the entire class of token-theft-by-XSS. Sessions expire after 30 days and are purged hourly.

The server is authoritative

Every write goes through a sanitiser that re-derives the sensitive fields from the server's own copy of your workspace. Editing your plan in a request body does nothing. Stripe payments are append-only and server-owned, so they cannot be forged or deleted by the client. Pay tokens are only ever minted server-side.

Money is never taken from the request

Invoice balances are recomputed from the stored invoice, deposits from stored settings, and subscription prices from the Stripe catalogue. A tampered request body cannot change what gets charged. Applying a payment is idempotent, so a reloaded success page or a retried webhook cannot double-record.

Client-facing pages leak nothing

Portal, scope, report and pay routes are unauthenticated by design — the URL token is the credential. Each returns only that one client's slice with internal fields stripped: no other clients, no your rates, no private notes, no tokens. Password-protected portals are gated on the server, not hidden in the UI.

Concurrent writes

Workspace saves use an optimistic version counter. If two tabs write at once, the later one gets a 409 with the newer document rather than silently overwriting your work.

Card details

We never see them. Payments run through Stripe Checkout, hosted on Stripe's own domain. The Stripe secret key stays server-side; only the publishable key ever reaches the browser.

Your data, on your terms

Every table exports to CSV whenever you like, including after cancellation. Deleting your account from Settings → Security removes your workspace data. We do not sell personal data and we do not share it with advertisers.

Reporting a vulnerability

Email security@freshlance.app with steps to reproduce. We will confirm receipt and keep you posted on the fix. Please do not test against other people's workspaces or client portals.

Freshlance is pre-launch and not yet independently audited or SOC 2 certified. We would rather say so than imply otherwise.

Know when you’re free next.

Free forever for 2 projects and 2 clients. No credit card, no trial clock.