Skip to page

Security

Last reviewed [LAST REVIEWED DATE]Version [VERSION]
In this document

Introduction

SorviAI is a multi-tenant platform holding general ledgers, invoices, customer lists, stock positions and pricing. That is a company’s commercial core, and the first thing this page has to explain is how one company’s is kept apart from every other company’s.

It is written for the security or IT reviewer who has been handed a questionnaire and told to clear us before procurement can proceed. So it is specific on purpose: nouns, numbers and versions rather than adjectives. Where a control is not in place, it says so and gives a date, because you will ask anyway and an omission costs you a week you did not have.

This page is our own account of what we do. It is self-reported, and no external auditor has tested any of it. What independent verification exists, and what does not, is set out on the Compliance page, and the short version is that we hold no certification yet.

What this page answers

The job of this page is to pre-answer the standard vendor security questionnaire. If you can tick every row below without emailing us, it has worked.

What you are being asked to establishAnswered under
Is customer data logically or physically separated from other customers’?Tenant isolation
Is data encrypted in transit and at rest?Encryption
How are sessions established, carried and expired?Authentication
Is multi-factor authentication available?Authentication
Is access granted on least privilege, and can it be scoped?Authorisation
Are administrative actions recorded, and for how long?Audit logging
How is code tested before release, and how are dependencies patched?Application security
Do you carry out penetration testing?Application security
Where is the service hosted, and which third parties can reach the data?Infrastructure and hosting
What are your RPO and RTO, and do you test restores?Backups and recovery
Will you notify us of a breach, and how quickly?Incident response
How do we report a vulnerability to you?Reporting a vulnerability
Who at your company can reach production, and how is that controlled?Our people and our own systems

Tenant isolation

Every SorviAI customer is provisioned with a dedicated PostgreSQL schema. Customer records are held in separate database schemas, not in shared tables partitioned by an identifier column.

The ordinary approach to multi-tenancy is a single shared table with a tenant_id column and a WHERE clause on every query. That works until one query is written without the filter, and then one customer can read another’s ledgers. It is a control that depends on every developer getting every query right, forever, including the ones written at speed on a Friday.

Schema separation removes that entire class of bug structurally rather than by discipline. There is no shared table to forget to filter. Sitting on top of that database boundary are three further controls, each of which would independently have to fail before a cross-tenant read became possible.

LayerControlWhat it does
DatabaseSchema per tenant, via django-tenantsEach customer’s records live in their own PostgreSQL schema. Tenant data is not co-mingled in shared tables
Request routingTenantMiddlewareResolves the tenant from the subdomain before the request reaches any view. A request that cannot be resolved to a tenant does not reach application code at all
Data accessTenantUserManagerApplies schema-aware filtering automatically, so isolation does not rest on each individual query being written correctly
AuthenticationTenant-scoped JWTsTokens carry the tenant schema and are validated against it on every request. A token minted for one workspace cannot be replayed against another

Public storefronts

Businesses can publish a catalogue to a public web address through SorviAI. That read path resolves the tenant from the Host header through the same middleware used everywhere else, and serves published content only. No authenticated session is involved on the public side.

This is worth stating explicitly because a public surface on a multi-tenant platform is exactly where a reviewer will look for a leak, and rightly so. The answer is that the public path shares the tenant resolution used by the authenticated application and reads only records a tenant has marked published.

Encryption

Reviewers look for isolation and encryption first, in that order. The first half of this section is straightforward. The second half is not finished, and we are not going to write it as though it is.

WhereWhat is appliedStatus
In transitbrowser to SorviAITLS, minimum version [MINIMUM TLS VERSION], [CIPHER POLICY]In place
In transitbetween our own services[CONFIRM: TLS BETWEEN APPLICATION, DATABASE AND STORAGE][CONFIRM STATUS]
At restdatabase[CONFIRM LAYER: FULL-DISK, DATABASE-LEVEL, OR COLUMN-LEVEL]Not yet stated
At restfiles and attachments[CONFIRM: FILE AND ATTACHMENT STORAGE]Not yet stated
At restbackups[CONFIRM: BACKUPS]Not yet stated

Authentication

Sessions are carried by signed tokens rather than server-side session state, and every token is bound to exactly one workspace.

  • Access tokens expire after 60 minutes. A refresh flow renews them silently while you are active, so the expiry is short without being disruptive.
  • Tokens carry the tenant schema and are validated against it on every request. This is the same control described under Tenant isolation, and it is worth counting twice: it is both an authentication and an isolation control.
  • Portal users authenticate on a separate path. Customers and suppliers signing in to a Portal do not use the platform authentication route, so a portal credential is not a staff credential that happens to have fewer permissions.
  • Password policy: [MINIMUM LENGTH, COMPLEXITY, BREACH-LIST CHECKING]
  • Failed attempts: [RATE LIMITING AND LOCKOUT BEHAVIOUR]
  • Single sign-on: [SAML / OIDC AVAILABILITY, OR STATE PLAINLY THAT IT IS NOT AVAILABLE]

Authorisation

Access inside a workspace is governed by role-based permissions scoped to each application. A role granted in Finance conveys no access to Inventory, or to any other module, unless it is granted there too.

Roles carry an application code, so the unit of a grant is an application plus a permission rather than a job title that quietly widens as the platform grows. Permission checks are resolved against a central registry rather than being scattered through individual views, which means there is one place a permission is defined and one place it is enforced.

Administrative tiers

Administrative rights are tiered rather than binary, so granting someone the ability to manage one application does not hand them the workspace.

TierReachesHeld by
Super administratorThe platform itself, across workspaces[SORVIAI STAFF ONLY - CONFIRM AND STATE HOW MANY]
Platform administratorOne entire workspaceThe customer
Application administratorOne application within one workspaceThe customer
UserOnly what is granted, per application, per permissionThe customer

Administrative status is cached for performance, and the cache is tenant-scoped, so a cached administrative decision cannot leak across the workspace boundary.

What least privilege means here in practice

A finance user cannot reach inventory functions unless someone explicitly granted them there. The default for a new user is not “everything except what we remembered to take away”, which is the shape most access problems actually take.

The corollary is that the workspace administrator list is the thing worth auditing, and it is yours to audit rather than ours.

Audit logging

An audit log is written into the tenant’s own schema, which means audit records are isolated on exactly the same boundary as the data they describe. Your audit trail is not co-mingled with anyone else’s, and it cannot be read from another workspace.

QuestionAnswerStatus
Where do audit records live?In the tenant schema, alongside the records they describeIn place
Which events are captured?[AUTHENTICATION, PERMISSION CHANGES, RECORD CREATE/UPDATE/DELETE, EXPORTS, ADMIN ACTIONS - CONFIRM]Not yet stated
How long are they retained?[RETENTION PERIOD]Not yet stated
Can an administrator read or export the log?[CONFIRM WHETHER EXPOSED IN THE INTERFACE]Not yet stated
Can it be altered or deleted from the interface?[CONFIRM: ALTERATION AND DELETION]Not yet stated

Application security

How code reaches production, and what stands between a newly written line and your ledgers.

  • Code review before merge: [REQUIRED? BY WHOM? ENFORCED HOW?]
  • Dependency management: [SCANNING TOOL AND PATCH CADENCE FOR CRITICAL ADVISORIES]
  • Static analysis and secret scanning: [WHAT RUNS IN CI]
  • Environment separation: [CONFIRM PRODUCTION IS SEPARATE FROM DEVELOPMENT, AND WHETHER PRODUCTION DATA IS EVER COPIED INTO NON-PRODUCTION]
  • External penetration testing: Not yet carried out. No independent test has been performed. One is planned as part of certification readiness, and when a report exists a summary will be available under NDA. See the Compliance page for that timetable.

Framework protections, described as what they are

SorviAI is built on Django. Cross-site request forgery protection, parameterised queries through the ORM, and template auto-escaping against cross-site scripting are all framework defaults that we have left in place rather than disabled for convenience.

We state that precisely because reviewers ask, and because there is a difference worth preserving between a control we engineered and a sound default we did not undermine. Both are worth having. Only one of them is a claim about us.

Infrastructure and hosting

SorviAI runs on [HOSTING PROVIDER], in [REGION]. We operate no data centre of our own, so physical security, power, and hardware disposal are our provider’s responsibility and are described in their documentation rather than invented here.

  • Network segmentation and firewall posture: [DESCRIBE]
  • Denial-of-service protection: [PROVIDER-LEVEL OR APPLICATION-LEVEL - DESCRIBE]
  • Database reachability: [CONFIRM THE DATABASE IS NOT REACHABLE FROM THE PUBLIC INTERNET]
  • Production access: [WHO HAS IT, HOW IT IS GRANTED, HOW OFTEN IT IS REVIEWED, WHETHER IT IS LOGGED]
  • Sub-processors: every third party that can reach customer data is listed on the Compliance page, with advance notice before a new one is added.

Backups and recovery

This section is incomplete. Every row below is a question a reviewer will ask, and none of them yet has an answer we can evidence.

What you need to knowAnswerStatus
How often are backups taken?[FREQUENCY]Not yet stated
How long are they retained?[RETENTION]Not yet stated
Are backups encrypted, and where are they held?[CONFIRM: ENCRYPTION AND LOCATION]Not yet stated
Are restores actually tested, and how often?[CONFIRM: RESTORE TESTING AND CADENCE]Not yet stated
Recovery point objective (RPO)[RPO]Not yet stated
Recovery time objective (RTO)[RTO]Not yet stated

A note on what a backup does not solve: a backup protects against loss, not against an unwanted change being made correctly by someone with valid credentials. For that, the relevant controls are Authorisation and Audit logging.

Incident response

If something goes wrong with your data, the question that matters is when you hear about it and what you are told. Commitment not yet published

  • Runbook: [WRITTEN RUNBOOK REQUIRED - WHO DECLARES AN INCIDENT, WHO LEADS, HOW IT IS RECORDED]
  • Notification commitment: [E.G. WITHOUT UNDUE DELAY AND IN ANY CASE WITHIN N HOURS OF CONFIRMING AN INCIDENT AFFECTING YOUR DATA]
  • What you would be told: what happened, which categories of your data were involved, when it occurred and when we detected it, what we have done, and what you need to do.
  • Who we would tell: the workspace administrators on record, and any additional contact you have given us for this purpose.

Why our commitment has to be shorter than 72 hours

Under the GDPR, a controller has 72 hours to notify their supervisory authority of a personal data breach. For the data in your workspace you are the controller and we are your processor, so our duty is to notify you early enough that you can still meet that deadline.

A commitment of “within 72 hours” would therefore be useless to you, because it consumes your entire window. Whatever number replaces the placeholder above has to be meaningfully shorter, and that is the constraint it will be set against. See the GDPR page for the rest of the processor relationship.

Reporting a vulnerability

If you have found a security problem in SorviAI, we want to hear about it, and we would rather hear about it from you than from someone else.

Report to
[SECURITY INTAKE EMAIL]
Monitored
[HOURS / DAYS]
Acknowledgement
[WITHIN N BUSINESS DAYS]

What we ask of you

  • Test only against a workspace you own. Do not access, modify or retain another customer’s data.
  • Do not run denial-of-service tests, or automated scanning heavy enough to degrade the service for other customers.
  • Give us reasonable time to fix the issue before disclosing it publicly.

What we commit to in return

[SAFE HARBOUR WORDING - CONFIRM WITH COUNSEL] We will not pursue legal action against a researcher who reports in good faith and stays within the boundaries above, we will keep you informed as we work on the issue, and we will credit you if you would like to be credited.

We run no bug bounty programme at present and offer no payment for reports. We would rather say that plainly than leave it ambiguous.

Our people and our own systems

The controls above describe the platform. This section describes the people who can reach it, which is the part questionnaires ask about and vendor pages routinely skip.

  • Background checks: [WHAT IS CARRIED OUT, FOR WHICH ROLES]
  • Security training: [AT ONBOARDING AND HOW OFTEN THEREAFTER]
  • Staff devices: [DISK ENCRYPTION, SCREEN LOCK, MANAGED UPDATES, WHETHER PERSONAL DEVICES MAY ACCESS SYSTEMS]
  • Production access: [NAMED ROLES ONLY, HOW APPROVED, HOW REVIEWED, WHETHER SESSIONS ARE LOGGED]
  • Access to customer data for support: [WHETHER STAFF CAN VIEW TENANT DATA, UNDER WHAT CONDITIONS, AND WHETHER IT IS RECORDED]
  • Offboarding: [ACCESS REVOKED WITHIN N, AND WHO IS ACCOUNTABLE]
  • Physical: we run no data centre. [DESCRIBE OFFICE ACCESS CONTROL, OR STATE THAT THE TEAM WORKS REMOTELY]

An honest note about the size of the company

A questionnaire written for a company of a thousand people asks about a dedicated security function, a named CISO and an internal audit programme. For several of those the truthful answer today is that we are too small to have one, and we would rather say so than describe a governance structure that does not exist.

What is worth more at our size, and is a fair thing to hold us to, is that the people who can reach production can be counted on one hand and are named on request. A short list that is actually accurate is a stronger control than an org chart nobody maintains.

How to contact us

Three different things, three different routes, so an urgent one does not sit in a queue behind a questionnaire.

Security questionnaires and vendor review

Email
[COMPLIANCE CONTACT EMAIL]
Response
[N] business days

Vulnerability reports

Email
[SECURITY INTAKE EMAIL]
Monitored
[HOURS / DAYS]

A suspected incident affecting your workspace

Email
[INCIDENT EMAIL]
Also
[PHONE, IF ONE IS MONITORED]
Monitored
[HOURS]
Entity
[REGISTERED COMPANY NAME]
Post
[REGISTERED OFFICE ADDRESS]

Key terms

The words on this page that carry a specific technical meaning, in plain language.

Multi-tenancy

One running system serving many separate customer organisations, each of which is called a tenant. It is what makes software affordable at this price: everyone shares the infrastructure and the cost of running it.

It is also the source of the risk this page opens with, because sharing infrastructure means the boundary between customers is enforced by software rather than by having separate machines. How that boundary is built is the single most important question to ask any multi-tenant vendor.

Database schema

In PostgreSQL, a named container inside a database holding its own set of tables. Two schemas in the same database can each have a table called invoices, and they are entirely different tables.

Giving every tenant their own schema means there is no shared invoices table holding several customers’ rows, and therefore no query that could return the wrong customer’s rows by omitting a filter. That is the structural argument, and it is the reason this term appears so early on the page.

JSON Web Token

A signed token issued at sign-in and sent with each subsequent request, carrying a small amount of information about who you are. Because it is signed, the server can trust its contents without looking anything up.

SorviAI’s tokens also carry the tenant schema, and it is checked on every request. That is what makes a token useless outside the workspace it was issued for, even if someone were to obtain one.

Refresh token

A second, longer-lived token used only to obtain a new access token when the current one expires. It exists to resolve a genuine tension: short-lived access tokens are safer, and being signed out every hour is unusable.

The refresh flow keeps the access token’s life short, at 60 minutes, while letting an active session continue without interruption.

Role-based access control

Granting permissions to named roles and assigning people to roles, rather than granting permissions to individuals one at a time. It makes access reviewable, because you can ask what a role can do rather than reconstructing it person by person.

In SorviAI each role is bound to a specific application, so a role in Finance carries no meaning in Inventory. The scoping is the part that matters; role-based access with one global role list is only bookkeeping.

Least privilege

The principle that an account should hold exactly the access needed to do its job and nothing more, so that a compromised or misused account reaches as little as possible.

The practical test is what a brand new user can reach before anybody grants them anything. If the answer is “most things, minus whatever we remembered to remove”, the principle is being described rather than applied.

Multi-factor authentication

Requiring a second proof of identity beyond a password, typically a code from an app or a hardware key. It is the single most effective control against stolen or reused passwords, which is how the large majority of account compromises actually begin.

SorviAI does not offer it today. That is stated in Authentication, in the gap ledger, and here, because it is the one absence most likely to matter to your decision.

Transport Layer Security

The protocol that encrypts traffic between your browser and a server; it is what the padlock in the address bar indicates. It protects data while it is moving across a network.

The version matters, which is why a page that says only “encrypted in transit” is under-specified. Older versions of the protocol have known weaknesses, so the useful statement names the minimum version accepted.

Encryption at rest

Encrypting data where it is stored rather than while it travels. The layer it is applied at determines what it actually defends against, and the layer is the part vendors usually omit.

Full-disk encryption protects against physical theft of a drive and nothing else. Database-level encryption protects against someone reading the files directly. Column-level encryption protects specific fields even from parts of the application. They are not interchangeable, and “we encrypt data at rest” does not distinguish between them.

RPO and RTO

Two numbers describing what happens after a serious failure. The recovery point objective is how much data you could lose, measured in time: an RPO of one hour means up to an hour of work might be gone. The recovery time objective is how long the service could be unavailable before it is restored.

Reviewers ask for both because together they describe the worst realistic day. A vendor who cannot state them has usually not tested a restore, which is the underlying question being asked.

Audit log

A record of who did what, and when. It matters at two quite different moments: routinely, when someone asks why a record changed, and exceptionally, when a breach has to be investigated and the scope of what was reached must be established.

Its value is entirely determined by scope and retention. A log covering logins but not permission changes, or one that rolls over after a week, answers neither question.

Penetration test

An authorised attack on a system by an external specialist, carried out to find weaknesses before someone unauthorised does. It is distinct from automated scanning, which finds known issues in known software; a penetration test finds flaws in the logic of what you built.

Reviewers ask two things about it: whether one has been done, and how often it recurs. A single test three years ago answers the first question and fails the second.

Responsible disclosure

An arrangement under which a security researcher reports a flaw privately to a vendor and gives them a reasonable period to fix it before describing it publicly. The vendor’s side of the bargain is to respond, to fix it, and not to threaten the person who told them.

The published address and the safe harbour commitment are what make it work. Without them a researcher’s rational choice is to say nothing, and the vendor learns about the flaw from somebody with worse intentions.