Trust

Security and vulnerability disclosure

ExaVeyra Sciences is a wholesale supplier to licensed practices. This page is written for the person at a clinic or hospital who has to sign off on a new vendor: how to report a problem to us, what happens when you do, which technical controls are actually in place, and which assurances we do not yet have. Every control below names the file or database migration that implements it, so the claim can be checked rather than taken on trust.

Reporting a vulnerability

Email hello@exaveyra.com with the word Security in the subject line. Include the URL or endpoint, the steps to reproduce, what you observed, and what you expected. A proof of concept is welcome; a working exploit against live data is not needed and should not be built. The same contact is published in machine-readable form at /.well-known/security.txt, following RFC 9116.

What to expect

  • An acknowledgement from a person, not an autoresponder, within five business days.
  • A severity assessment and either a fix or a stated plan within thirty days of acknowledgement. Reports affecting submitted practitioner or patient contact data are handled first.
  • Credit on this page if you want it, once the fix has shipped. No monetary rewards are offered; there is no bug bounty programme.
  • A request to hold public disclosure until the fix is live, and an honest answer if we cannot meet a date.

Safe harbour for good-faith research

We will not pursue or support legal action against anyone who researches the security of exaveyra.com in good faith and within these limits. If your research stays inside them, we consider it authorised.

  • Do not access, modify or retain data that is not your own. If you reach another person's record while demonstrating an issue, stop, note what was reachable, and report it; do not download it.
  • Do not degrade the service. Volumetric tests, request floods and deliberate exhaustion of rate limits are out of scope and are not needed to demonstrate any finding.
  • Do not submit test entries through the practitioner, patient or contact forms beyond what a single reproduction requires. Each submission reaches a real inbox.
  • Do not use social engineering, phishing or physical approaches against our people or partners.
  • Third-party services we run on, named in the sub-processor table below, have their own disclosure programmes. A finding in one of them belongs to them; tell us as well and we will pass it on.
  • Give us a reasonable time to fix before any public disclosure. Thirty days from acknowledgement is our default, and we will say so if we need longer.

Controls in place, and where each one lives

The source repository is private, but each row names the file or migration a reviewer would be shown on request. Nothing here describes a control that is planned rather than shipped.

Transport encryption

Every request is served over TLS. HTTP Strict Transport Security is set for two years with subdomains included and preload eligibility, so a browser that has visited once will not attempt a plain HTTP connection again.

next.config.ts, Strict-Transport-Security header

Content Security Policy, enforcing

A real Content-Security-Policy header blocks scripts, styles, frames and connections from any origin not on the allow list. It enforces rather than reports, which means a new third-party script breaks production until it is deliberately added.

next.config.ts, Content-Security-Policy header

Rate limiting per route

Every form and API endpoint has its own request budget per source address, keyed by endpoint so that exhausting one cannot exhaust another. If the limiter’s backing store is unreachable, requests are allowed rather than refused, so an outage there cannot take the forms down.

lib/rate-limit.ts and each route under app/api

Schema validation on API input

Every route that accepts a request body or query string validates it against a typed schema before anything is stored or sent. Unknown fields are rejected, lengths are bounded, and a malformed request returns 400 without reaching the database.

zod schemas in each app/api route

Signature-verified webhooks

Inbound events from payment and scheduling partners are accepted only with a valid HMAC signature. Without the shared secret configured, the endpoint returns 401 rather than processing unsigned events.

app/api/stripe/webhook, app/api/webhooks/telehealth

Row-level security with staff gating

The database enforces row-level security on every table holding submitted data. Lead and application records are readable only by staff accounts identified server-side, or by holders of a scoped capability grant; the public role can insert and cannot read.

supabase/migrations, is_portal_staff() and the patient_leads policies

Append-only access audit log

Every access decision on staff surfaces, including denials, is written to an audit table. Update, delete and truncate are revoked from every database role, the service role included, so the trail is append-only as a property of the database rather than a convention.

supabase/migrations/20260809000000_access_grants_and_audit.sql

Access grants with mandatory expiry

Delegated access is granted per capability with an expiry that the schema requires: a grant without an end date cannot be written, and a grant whose end date has passed no longer satisfies any policy.

access_grants table, expires_at NOT NULL with a check constraint

Two-factor authentication on the portal

Practitioner and staff accounts can enrol an authenticator app. Enforcement for staff surfaces is a single configuration switch, set once the account owner has enrolled and verified a code.

lib/portal/mfa.ts, /portal/account/security

Consent Mode v2, denied by default

Analytics, advertising storage and personalisation are all denied before any tag loads, and stay denied until a visitor grants consent through the banner. No analytics cookie is set for a visitor who has not chosen.

app/layout.tsx consent default, components/cookie-consent.tsx

PII scrubbing in error reporting

Error reports carry no request bodies, no user object and no IP address. Messages, stack frames, extra data and breadcrumbs are passed through a redaction step that removes email addresses, phone numbers, NPI numbers and similar identifiers before anything leaves the process. Session replay is not enabled.

lib/sentry-scrub.ts, sentry.server.config.ts, instrumentation-client.ts

Gated deployment

Production is reachable only through a continuous integration job that runs the unit suite with coverage floors, the browser suite with an automated accessibility gate, a type check and a performance budget. A failing check means nothing reaches the site.

.github/workflows/perf-budget.yml, vercel.json

What this site holds, and what it does not

Forms collect practice-level and contact information: clinic name, licence credentials, an NPI for verification, an email address and a phone number. We do not request protected health information and we ask practices not to send it; our position under HIPAA is set out on the HIPAA and practice data page. Card entry for device purchases happens on the payment processor's hosted checkout, so card numbers never reach this site. Secrets are held in the hosting platform's environment, never in the repository.

Sub-processors

The same list as section 4a of the privacy policy, rendered from one shared source so the two pages cannot disagree.

ProcessorPurposeData transferredLocation
VercelWebsite hosting & edge deliveryIP address, request metadataUS / Global CDN
SupabaseDatabase & form submission storageForm data, contact info, practitioner dataUS (AWS us-east-1)
ResendTransactional email deliveryName, email address, form contentUS (AWS us-east-1)
Google AnalyticsWebsite analytics & usage measurementIP address (anonymized), page views, eventsUS / Global
Google reCAPTCHABot detection & form abuse preventionBrowser fingerprint, IP address, interaction dataUS / Global
UpstashAPI rate limitingIP address (hashed)US

Error reports, once the reporter is configured, go to Sentry with the scrubbing described above and nothing else. Card entry happens on Stripe's hosted checkout.

What we do not have

We would rather state these plainly than let a questionnaire infer otherwise.

  • No third-party attestation. There is no SOC 2 report and no ISO 27001 certification. The controls above are self-described and traceable to code; nobody independent has audited them.
  • No penetration test on record. The automated accessibility and performance gates run on every deployment; a human-led security assessment has not been commissioned.
  • No dedicated security staff. Reports go to the founder, who is also the engineer, which is why the response commitments above are measured in days rather than hours.
  • No bug bounty. Good-faith reports are welcome and credited; they are not paid.

Reviewed 2026-09-10 by Benn Bluestein-Veyra, M.Sc. Organic Chemistry. This page describes technical and organisational measures as they exist on the review date. It is not a certification, an audit report or legal advice.