SECURITY & COMPLIANCE

What protects your maintenance data, and what we do not claim.

Industrial buyers need to know where the boundaries are. This page separates what is engineered and tested from what is planned, and it makes no certification claim of any kind.

ENGINEERED AND TESTED

Isolation that lives in the database, not in application manners.

These are working behaviours of the application today, with database-level proofs in the repository.

Implemented

Sign-in

Authentication runs through Keycloak using the authorization-code flow with PKCE. No password is handled by the application itself, and tokens are validated per request.

Implemented

Tenant isolation in PostgreSQL

Every plant's data is separated by organization_id together with row-level security set to forced mode, so the policy applies to the table owner too. The runtime role is not a superuser and cannot bypass it. Every write runs inside a transaction carrying a transaction-local plant id, and tenant references are composite foreign keys — a reference to another plant's site or machine is refused by the database.

Implemented

Capability-based authorization

Authorization checks a permission, a plant membership and a site scope — never a role name hard-coded in a screen. Seven roles ship as seed configuration with a published permission matrix. A screen is told what the caller may do rather than probing for it, and a control the caller lacks is drawn disabled with the plant's own reason.

Implemented

Conflicts are refused, not overwritten

Editing a work order, machine or part requires the version of the record it was drawn from. An edit made from a stale copy is refused with the version the plant holds now, instead of silently replacing somebody else's change.

Implemented

Idempotency

Commands, work logs and import runs require an idempotency key, so a retried request never applies twice. Offline synchronisation is idempotent per device and mutation: pushing the same report twice leaves exactly one row.

Implemented

Ledger-first inventory

Stock changes only by posting an immutable movement row. Balances are a projection the database checks against the ledger at commit, and two devices issuing the last unit are arbitrated by the database rather than by luck.

Implemented

Files kept out of the database

Documents and photos live in private object storage under non-guessable, plant-scoped keys. Uploads use short-lived presigned slots so the bytes never pass through the application, and the server verifies that the uploaded object exists and matches the expected size.

Implemented

Backup and restore, rehearsed rather than promised

A deployment is backed up in two halves at one recovery point: the PostgreSQL cluster — a plant's data, its identities and its realm together — with pgBackRest, and the object store that holds document bytes with restic. The rehearsal installs a release on a clean host, writes real data through the API, backs both halves up, destroys the stack and its volumes, restores into a fresh stack and proves the uploaded blob came back byte-identically. It then applies a real migration as an upgrade and rehearses both rollback paths, including the one it refuses on purpose. Its transcript is committed in the repository rather than summarised in a claim.

Implemented

Traceable errors

Every error response carries a stable code and a request id that is also stamped on the trace, so a screenshot from the shop floor identifies exactly one request.

STATED LIMITS

What is not protected yet — in plain terms.

We would rather you hear this from us than discover it in your own security review.

Gap

No audit log

There is no tamper-resistant audit-log table. Where a movement must be provable, the immutable ledger row is the evidence, carrying actor, timestamp, reason and the signed change. A dedicated audit family is designed but not built.

Gap

Encryption at rest depends on the environment

Traffic is HTTPS/TLS. Encryption of the database and object storage at rest is an infrastructure setting that must be enabled for the environment you run in — it is not something the application can turn on for you.

Gap

Uploaded file checks are partial

The server checks that an uploaded object exists and matches its expected size. The recorded SHA-256 is the uploading device's own assertion, not something the plant re-verified, and malware scanning is not enabled. Hidden-by-default is not the same as scanned.

Gap

Backup limits that are still real

The object snapshot is crash-consistent rather than application-quiesced. The keys that decrypt a backup are not escrowed, rotated or split by anything we ship. Nothing restores from the off-site copy on a schedule — its presence and size are checked, not its restorability. Until an off-site destination is configured, the same host is a single point of failure; and where the certificate authority is internal, it is not in the backup, so after a lost host every device has to be given the new root.

Gap

No monitoring or alerting backend

No metrics or tracing backend is deployed: the API is handed a tracing endpoint that is empty, so tracing is off and its logs carry no trace ids. Nothing pages anyone when a host misbehaves — watching it is an operator's job in this release.

Gap

SSO and MFA are capability, not configuration

Keycloak supports SAML, LDAP, Active Directory and multi-factor authentication, and the architecture is built to use them. Customer-facing SSO configuration and enforced MFA are not configured or tested in the product today.

Gap

Export, retention and deletion

There is no export route and no tenant export, retention or deletion workflow, so the data-portability and retention duties in a processing agreement cannot be fulfilled by the product yet.

Gap

No third-party assessment

No penetration test, security audit or certification has been completed. The engineering baseline is OWASP ASVS 5.0.0, used to decide what to test; deviations are recorded rather than summarised as compliance.

Gap

Release automation not proven

The automated pipeline that would run the isolation, permission and upload tests on every change exists as a workflow file but has never executed on a hosted runner. Until it does, treat release verification as local rather than industrialised.

COMPLIANCE POSITION

Where we stand on the regulations, without overstating it.

Readiness is not compliance. We describe the first and never claim the second.

Readiness

EU Cyber Resilience Act

The CRA generally applies from 11 December 2027, while the manufacturer duty to report actively exploited vulnerabilities applies from 11 September 2026 — which is why vulnerability intake and reporting readiness cannot wait for 2027. Our CRA work is an engineering readiness plan, not a conformity classification, and no CE or CRA conformity is claimed until legal classification is complete.

Readiness

NIS2

Whether a given plant or supplier falls inside NIS2 depends on its sector, size and national law, so nobody should be told they are automatically compliant. What we can do is support your programme: least privilege, capability-based access, isolation you can demonstrate, and evidence you can export from the repository.

Readiness

GDPR

In a hosted deployment the plant is normally the controller and we are the processor. The engineering checklist — minimisation, retention, pseudonymisation, support access, telemetry that excludes maintenance free text — is written and being worked through. It is an engineering input, not a legal determination, and the processing agreement is a separate document.

Alignment

Maintenance standards

The product is designed to support processes aligned with ISO 55001, ISO 9001 and ISO 45001, and with the maintenance terminology of EN 13306 and EN 15341. No certification is claimed or held. Alignment with a standard is a design intention, not a certificate.

SECURITY QUESTIONS

Ask us the awkward ones.

If your security review needs a specific answer, ask directly — we will tell you whether it is built, planned or missing.

Contact us →