Security

This platform takes payments, holds guest information and runs the till. This page describes how that is protected, in specific terms — and states plainly what has not been done yet, because a security page you cannot check is a brochure.

The model in one page

Six layers, each assuming the one before it may have failed. The layer that matters most is the one you cannot bypass by writing careless code: tenant isolation is enforced inside PostgreSQL, not in application logic.

LayerWhat it does
TransportHTTPS everywhere with automatically renewed certificates; HSTS; no mixed content.
IdentityShort-lived access tokens with an httpOnly refresh cookie, TOTP two-factor for staff accounts, and step-up re-authentication on sensitive actions.
AuthorizationRole-based permissions checked on every request, with a build-time gate that fails if a route ships without an authorization guard.
Tenant isolationPostgreSQL row-level security. The tenant is set as a session variable and enforced by the database itself — not by application code that could forget.
Data at restSecrets (API client secrets, webhook secrets, MFA seeds, integration keys) are stored as encrypted envelopes under a dedicated key. The release gate refuses to pass while any plaintext or legacy-format row remains.
BackupsEncrypted database and media dumps, taken before every deploy and retained off the running container.

One restaurant cannot see another

Multi-tenant software fails in one characteristic way: a query somewhere forgets its tenant filter and returns everybody’s rows. Novaryq answers that by refusing to rely on the query. The signed-in tenant is set as a database session variable, and row-level security policies filter every table against it.

Four properties are proven against real data before every release. They are run as a self-test, on a canary tenant, and the deploy stops if any of them fails:

PropertyHow it is proven
A tenant sees only its own rowsProbed per table against a canary tenant on live data before each release.
Another tenant sees none of themThe same probe from a second tenant must return zero rows.
No tenant context means no dataA query that arrives without the tenant session variable returns nothing. It fails closed rather than falling back to “everything”.
The escape hatch is welded shutAttempting to switch strict mode off inside a session still returns zero rows — the policy does not trust a flag it can be asked to ignore.

The third property is the one to weigh: a request with no tenant context returns nothing at all. Systems that instead fall back to “no filter” are the ones that leak, and they leak silently, because nothing errors.

Card data never reaches us

The safest way to hold a card number is not to hold it. Card capture happens on the payment terminal or on the processor’s hosted page; Novaryq is handed a transaction token, the last four digits and the brand, and every later action — refund, tip adjustment, settlement — runs against that token.

What this does NOT mean: it does not mean Novaryq holds a PCI attestation of its own. Keeping the card number out of our systems is what makes our PCI scope small; the processor carries the certified part. A signed attestation and an external scan belong to go-live and are not claimed here.

Who can do what

  • Staff sign in with a PIN on the floor and a full credential in the back office; actions are attributed to the person, not the device.
  • Two-factor authentication (TOTP) is available for back-office accounts, and sensitive operations require step-up re-authentication even within a valid session.
  • Permissions are role-based and checked on every request. A build-time gate fails the release if a route ships without an authorization guard — the check cannot be forgotten quietly.
  • Voids, discounts, refunds, drawer opens and price overrides are written to an audit trail with the employee, the time and the reason.
  • Sessions expire on idle and absolutely, and every device signed into an account can be listed and revoked individually.

Secrets and data at rest

API client secrets, webhook signing secrets, two-factor seeds and integration keys are stored as encrypted envelopes under a dedicated key rather than as readable columns. The release gate counts plaintext and legacy-format rows and refuses to pass while either is above zero — so “we encrypt secrets” is a build condition, not an intention.

Outbound webhooks are signed with an HMAC over the raw request body so a receiver can prove a delivery came from us, and inbound integrations are verified the same way, failing closed in production.

Outages, backups and recovery

Terminals keep taking orders and cash through a network outage and reconcile when the connection returns; every queued mutation carries an idempotency key so a replay cannot create the same order or payment twice. Card capture requires connectivity, because approving a card the processor never saw would be inventing money.

Database and media backups are encrypted before they are written and are taken before every deploy. The recovery objectives below come from our own disaster-recovery document, which is explicit that they are targets:

Stated so you can hold us to it: scheduled off-host backups and a timed full-restore drill are on the plan and are not yet in place. Until that drill is run on production-scale data, treat the numbers above as intentions rather than commitments.

How a change reaches production

Every release passes a gate that runs on the production host before anything is deployed: schema-to-policy drift, row-level-security coverage, a frozen list of the roles allowed to bypass it, both test suites with zero skips permitted, a production posture check inside the running container, a secret scan across the candidate history, a filesystem vulnerability scan and a dependency audit. A single failure stops the deploy.

Releases are cut as signed tags by a person. Automation prepares and verifies; a human authorizes.

If something goes wrong

Report a vulnerability to security@novaryq.com. Good-faith research is welcome: test against your own tenant, do not access other businesses’ data, and give us a reasonable window before publishing. We will confirm receipt, tell you what we found, and credit you if you want the credit.

What we have not done

Everything above is a control that exists. This section is the other half of an honest security page — the things a buyer might reasonably assume, that are not true today.

Not yetWhat is true instead
No SOC 2 or ISO 27001 certificationNeither audit has been undertaken. Controls described here are real and testable; they have not been attested by a third party.
No PCI attestation of our ownCard data is handled by the processor, which keeps the card number out of our systems and our PCI scope small. A signed attestation and an external scan are part of go-live, not something already held.
No published uptime guaranteeStandard plans do not include a contractual service-level agreement. Offline-capable terminals exist precisely because no platform can promise a network.
Restore drill not yet timed on production-scale dataBackups are encrypted and taken before every deploy. The recovery objectives below are targets until a full restore has been performed and timed.