Security

What actually protects your data — in the ERP, at sign-in and on this website — described so you can check it.

What is in place

Your data

One company's records are fenced at the database

Every record belongs to exactly one studio, and the database itself enforces it: row-level security is FORCED on the tenant table, so a query that forgot to filter returns nothing rather than somebody else's data. The application cannot opt out of it, and neither can a mistake in the application.

Your clients are encrypted before they reach the database

A client's record, and a client's name and contact details wherever they are copied — onto a quotation, a project, an invoice, a tender — are encrypted with AES-256-GCM in the application, on their way into the database. Each studio has its own data key, and each value is bound to its studio, record and field, so a value moved anywhere else refuses to open. The master key is held outside the cloud where the database lives, so a database dump, a backup or somebody at the database console reads ciphertext, not your customers.

The database has no door on the internet

The database accepts connections from no network address at all. The application reaches it through a small gateway that authenticates with short-lived, federated cloud identities — there is no database password anywhere to leak, and the gateway refuses to start if one is configured. Every statement is sent with bound parameters, never pasted into SQL text.

Files are served only after the same check the screens use

Uploaded files are never handed to a browser by a public storage link. The request is checked for membership first, and the bytes are then streamed by the application — so the access decision stays in code rather than being delegated to a store that cannot express who may read what.

Every change is recorded, from one place

Each change records who made it, which kind of identity they were, which studio, what they did, which record, and what the system told them. It is written by the single wrapper every changing request already passes through — one place that can be got right, rather than one per screen that somebody could forget.

Access inside the ERP

Membership authorises, never the address

Knowing a studio's URL grants nothing. Access is resolved once per person, and holding no role means holding nothing — there is no fallback that quietly allows more. Nobody can grant a right they do not hold themselves, checked both where roles are assigned and where join requests are approved.

Roles decide every screen, down to the action

Rights are granted per area and per action — view, create, edit, delete, approve — so a payroll clerk can run payroll without opening the employee register, and a site engineer can run a job without seeing what it is allowed to cost. A right can be limited to a person's own records or their department.

Whoever prepares a record does not also approve it

Approvals walk a chain the studio sets, by amount. The person who raised a bid, a purchase requisition or a payment release can never sign it, and nobody signs two steps of one record. The studio's owner or Admin may approve their own bill, payroll run or stock adjustment — so a one-person company can still pay itself — and that signature is recorded like any other.

API keys can never do more than their owner

A key acts as a real person in the studio and passes the same checks a browser does. What it may do is the overlap of its own scopes and what that person may do right now — so removing somebody's role shrinks their keys in the same act. The full key is shown once and never stored; only a digest is kept, compared in constant time.

A session can be locked, and locks on every request

Anybody can lock their session or set an idle timeout; a locked session is refused on every request, every tab and the live stream, not only the screen showing the lock. A personal PIN unlocks it, and five wrong PINs end the session outright.

Signing in

Passwords are hashed at cost 12, and re-hashed on the way in

bcrypt at a work factor of 12. When someone signs in with a password stored at an older, weaker factor, it is re-hashed on that login — so raising the factor protects the accounts that already exist rather than only the ones created afterwards.

A new device must prove itself

A password alone does not open an account on a device it has never been used from: a one-time code is emailed first. Anyone can switch on an authenticator app, so a new device then needs their phone instead — with single-use recovery codes stored only as digests. Passkeys are supported too: a key that never leaves the person's phone or security key, unlocked by the device itself.

Repeated guesses are slowed, then stopped

Failed sign-ins are counted three ways — by source, by account, and by the pair — and a source that keeps failing is locked out for progressively longer, up to a day. Three counters rather than one on purpose: a single per-account limit would hand anybody a way to lock a named person out of their own account by typing their address wrong. Automated sign-in and sign-up attempts are refused before a password is even checked.

A trusted device stays in its own browser

Ticking "trust this device" binds the trust to that browser. Copying the cookie to another machine does not carry it: that machine is asked for a code again.

You can see, and end, every session

Session tokens are stored only as SHA-256 digests, so anyone reading the store finds nothing that can be replayed as a session. Your Security page lists every place you are signed in — device, place, last activity — and signs any of them out; a session ended elsewhere is told why.

Our own console requires a second factor

The administrative console nompany's staff use is behind its own authenticator-app sign-in, separate from the product's, and sees where each account is signed in so a shared login can be noticed.

This website

Browser protections are set on every response

HTTPS is enforced with a two-year HSTS policy. No page may be framed by another site — except a studio's own public form, which is built to be embedded on that studio's website. MIME sniffing is disabled, the referrer is cut to the origin when you leave, and camera, microphone, payment and USB are switched off by policy; location may be asked for by our own pages only, and your browser still asks you every time.

Third parties, named

Three outside scripts exist and all three are named here. The public marketing pages load Google Analytics, and only after you accept it in the banner — decline and nothing is requested from Google; it never runs on the sign-in pages or inside the ERP. The sign-in and sign-up pages load Fingerprint's agent, used only to spot automated attacks and to bind trusted devices. And ERP screens that show a map load Google Maps. No chat widget, no advertising pixels. Our fonts are self-hosted. Server errors go to Sentry with headers, cookies, request bodies, IP addresses and query strings stripped before they leave.

Reporting something

If you believe you have found a vulnerability, write to us and say so in the subject line. You will get a human reply.

Run your whole company from one place

Open a studio, choose the departments you run and invite your team, each person in their own language. There is nothing to install, and the first 3 months are free.

nompany is an ERP for small and medium companies across the region — every department on one data model, in Arabic and English, so work moves from one team to the next without anybody typing it out again.

© 2026 nompany