Security & audit

Your shop's data is not near anybody else's

Many shops run on JewellerGen. Not one of them can see anything belonging to another, and that is not a promise resting on one careful piece of code — it is checked in four independent places, each of which refuses on its own if the others were ever wrong.

Four layers

Not one guard, four

Any one of these would be the usual answer. Having all four means a mistake in one does not become an incident, because the next one still refuses.

1 · Every record is stamped

Every record stored — every tag, bill, customer and rate — is stamped with the shop it belongs to, and nothing can be written without that stamp. Two shops can both run a tag number A-1001 and the system knows they are different pieces.

2 · The database refuses on its own

The database enforces the separation itself, underneath the application, and it is not the application's to switch off. A request that does not say which shop it is for gets back nothing at all — not everyone's data.

3 · Every read is narrowed

Every read is narrowed to your shop automatically, on every single query, rather than each screen being trusted to remember. A record that does not name a shop is refused before it ever reaches the database.

4 · It comes from your sign-in

Which shop a request belongs to is taken only from your signed-in session — never from a web address, a form field, or anything else a browser can be made to send. If it cannot be established, the request is refused rather than guessed.

A small detail that matters. Asking for a record that belongs to another shop returns not found, never forbidden. A "forbidden" confirms the record exists, and confirming existence is itself a leak.
Branch access

Within a shop, branch means branch

A chain's second store is not a filter on a dropdown. Staff are allocated to branches, and the allocation travels in the signed session token where it cannot be edited by the browser.

  • Empty means none. A user with no branch allocation has no access at all — never "all branches", which is the default that quietly grants everything.
  • Validated per request. The branch the screen is working in is checked against the allocation on every call, and a value outside it is refused.
  • Checked before every document. Creating, confirming or settling anything asserts that this user may transact at this branch.
  • Fixed at creation. A document's branch is set when it is created and is never editable afterwards.
  • Transfers only. Stock moves across a branch boundary through a transfer, with a dispatch and a receipt at either end, and nothing else.

Roles and permissions

Seven role bundles ship ready to use, and the permission registry beneath them can be cut as finely as you need.

  • Owner — everything, including the rate board and the thresholds
  • Manager — approvals, transfers, adjustments, reports
  • Salesperson — sell, estimate, look up, take old gold in
  • Cashier — tenders, day end, cash register
  • Valuer — testing, buyback valuation, appraisals
  • Stock keeper — receive, tag, transfer, count
  • Accountant — reports, exports, statutory filings

Permissions are per action, not per screen, so "may sell" and "may discount beyond 5%" are separate answers.

Audit

Two logs, because they answer different questions

One records what changed and who changed it. The other records how a document moved through its states. Keeping them apart means neither is too noisy to read.

  • Change log — field-level, written asynchronously so it never slows the counter down.
  • Status history — written in the same transaction as the change it describes, so it can never disagree with the document.
  • History panel on every detail screen, readable by a manager without a support ticket.
  • Approvals recorded with the rule, the threshold, the approver and the reason.
  • Interface log for every external call, one row per attempt, with request, response and timing.

Alerts on the things worth watching

High-value activity should reach a person while it is still happening, not appear in a monthly report.

  • A discount or price override above your threshold
  • A stock adjustment, or a piece marked lost
  • A tag reprint — the quiet route to a duplicate piece
  • A buyback above a value threshold
  • Any activity outside your trading hours

Each is a rule you configure, delivered where you want it, and each has a matching monitoring report.

Your data

Held carefully, and yours to take

Encrypted in transit and at rest

HTTPS throughout, and document attachments and stored secrets encrypted at rest.

Personal data masked in logs

PAN, Aadhaar, Emirates ID and contact details are masked wherever they would otherwise reach a log file.

Sessions that expire

Short-lived access tokens with a rotating refresh, session timeout, and a login rate limit that survives being behind a proxy.

Exports, always

Every blotter and report to CSV, XLSX or PDF; bulk export of items, customers, vendors and rates; ledger export for your accounts package.

Customer rights

Export or erase an individual customer's data on request, with retention policies you set.

Deployment choices

Run it as our hosted service, or take the same container stack and run it on your own infrastructure.

The stack

Three moving parts, on purpose

JewellerGen is one application, one database and a web server. It calls no sibling services, so there is no other system whose outage becomes your outage.

  • One application — Java 21 on Spring Boot, a single deployable, with virtual threads so a modest server handles a busy Saturday.
  • One database — PostgreSQL, enforcing the separation described above, with a schema history that is checked on every start-up.
  • One web server — nginx in front, serving the interface and proxying the API.
  • No shared dependency — it issues its own tokens, owns its own users and sends its own messages. Nothing else has to be running.

Money and weight are exact

Every weight, rate, price and tax amount is held as an exact decimal, never as a floating-point number. Weights are three decimal places in grams, fineness one decimal place in parts per thousand, money two decimal places. A gram that goes missing to rounding is a gram that goes missing.

Nothing untranslated reaches a screen

Every visible string is a translated key with an entry in all three language catalogues, and a missing key fails the build. A counter screen cannot show a raw identifier to a customer, because such a build never ships.

What we are not claiming. JewellerGen does not currently hold an ISO 27001 or SOC 2 certification, and we are not going to imply one with a badge. The controls above are what is built. If you need a specific attestation for your own compliance, ask — we would rather discuss a real timeline than a logo.

Bring your hardest question

Separation, backups, hosting region, exit plan, who at our end can see what. We will answer them on the call and put it in writing.