Skip to content

The rules it cannot break

Nobody buys a company store on their own. Somebody in People sends it to a security reviewer and a finance controller, and those two ask the harder questions. This page is written for them.

Enforced in code, not in a policy

Each of these is held in one place in the code rather than remembered in eight, which is the difference between a rule and a convention.

Ledgers are append only

No stock or credit balance is ever stored in a column. Every balance on every screen is a sum of entries, so a wrong number can be traced to the row that caused it and a correction is a new entry rather than an edit.

Money is integer minor units

Nothing financial is ever a floating point number: money is integer minor units and credits are integer whole units. A quantity or an amount that arrives fractional is rejected rather than rounded, because rounding is how a ledger silently stops balancing.

What a person changes goes through one door

Every mutation a signed-in person makes through the product passes a single action wrapper, which enforces authentication, a permission check, one database transaction and an audit row. A few paths write outside it by design rather than by omission: signing in before a session exists, a preview, an integration calling the API with its own token, a carrier callback, the nightly sweep, and the platform operator's own provisioning. Each of those audits its writes, and none of them acts on an instruction from somebody at a client company.

Permissions are checked, never role names

Code asks whether this account may manage the catalog, never whether it is called a merchandiser. Roles can be reshaped for a client without a rewrite, and a permission granted to nobody is held by nobody.

A permission is not an ownership check

Holding the right to edit a product is not the right to edit that product. Any action taking an id from a form proves the record belongs to the caller's scope before it mutates.

Out of scope reads as not found

A record outside your tenant returns 404, never 403. A forbidden response confirms the record exists, which is itself a leak: it lets an outsider enumerate another company's orders by watching which ids change the answer.

Nobody grants a role at or above their own

Privilege escalation by invitation is checked explicitly, so an administrator cannot mint a peer or a superior and then use it.

The operator is not a tenant

The platform's own portal is the only surface that crosses company boundaries, and no tenant role can hold a permission belonging to it, even by mistake.

Authentication, tokens, backups and audit

Single sign on

SAML 2.0 against your identity provider, or Microsoft and Google directly. Assertions are signature checked, bound to your tenant, and refused on replay.

Passkeys

WebAuthn, so an employee can sign in with the device unlock they already use and there is no password to phish.

Passwords

Hashed with scrypt and a per-account salt. Never logged, never returned by any endpoint.

Sessions

Opaque server-side tokens in HTTP-only cookies, revocable, with rate limiting on sign in.

API tokens

Stored as digests, shown once at creation, scoped per endpoint family and revocable individually.

Webhooks

Signed, with a timestamp and a shared secret, and retried with backoff so a missed delivery is not a lost one.

Uploads

Content sniffed rather than trusted by extension and stored content-addressed. An uploaded file is served under a policy that denies script outright, which is the control. An SVG is also refused on the way in if it carries a construction we cannot check, and stripped of active content otherwise.

Audit

Every mutation writes an actor, an action, an entity and the detail, and the trail is append only like everything else. The action wrapper's own row also records the caller's address. The extra rows a feature writes beside it say what changed rather than where from, and a nightly job has no address to record at all.

Backups

A consistent snapshot daily, file backups kept fourteen days and volume snapshots five, restorable to a point before somebody's mistake.

Posture checks

Twenty four automated checks run daily against the live instance and are scored by severity.

Where it falls short today

The booking page promises a straight answer on anything the platform cannot do. It is a poor promise if the answers only arrive on a call, so here they are. Every line is the true state today, taken from the operations record rather than softened for this page.

Deprovisioning

There is no SCIM connector. When somebody leaves, an administrator closes the account or your system calls the API. At several thousand employees with real turnover, decide now whether that is acceptable.

One machine

A tenant runs on a single machine with a single volume. Scaling out is a migration to a networked database rather than a configuration change, so there is no multi region failover today.

Recovery point

Up to twenty four hours, which is the backup interval. That is the most data you could lose.

Recovery time

Not measured under load. A restore drill runs and most recently passed on August 6, 2026, but the drill is not yet on a stated schedule and the timing is not a commitment.

Encryption at rest

The volume is encrypted by the host. The database file itself is not separately encrypted. Vendor and carrier credentials inside it are, with AES-256-GCM.

Legal documents

All eight published documents are unreviewed drafts. They are versioned, acceptances are recorded per person per document, and every term still to be confirmed carries a marker on the page rather than reading as settled.

If any of these is a blocker rather than a note, it is better raised now than in week three of a pilot. Several of them are work we would schedule against a signed customer rather than ahead of one.

Read the legal register

Want your security reviewer on the call?

Book a walkthroughHalf an hour, one order walked the whole way through.