Open-source LIMS for medical diagnostics — ISO 15189-compliant, self-hosted, MIT-licensed.
OpenSylab is a LIMS for small to medium diagnostic laboratories that want to run a complete, ISO 15189-capable system — without enterprise license costs, without US-cloud dependencies, without a database server.
Every CREATE / UPDATE / DELETE operation on samples, orders, results, and users mandatorily creates an AuditEntry with user_id, action, entity_type, entity_id, and timestamp — directly at the database layer, not as an optional feature. No other open-source LIMS solution implements this as an inalienable foundation. Compliance here is not a module you bolt on.
Native C++ parsers for HL7 v2.5.1 (ORU^R01) and FHIR R4 Bundles (Patient, Specimen, ServiceRequest, Observation) — no separate FHIR middleware server, no Java heap, no dependency on external services. Import and export directly via the REST API.
MIT license means: no copyleft, no license-compliance bureaucracy for IT departments, no restrictions on commercial development. SQLite as an embedded database: backup = copy a file, runs on an inexpensive ARM VM, no DBA staff required. Patient data never leaves your own infrastructure.
No JVM warmup, no interpreter overhead, no framework bloat. OpenSylab runs on hardware where no Java-based LIMS would even start — relevant for edge deployments directly at the analyzer or resource-constrained on-premise environments.
PBKDF2-HMAC-SHA256 (210,000 iterations, random salt), HMAC-SHA256 JWT, TOTP/MFA (RFC 6238), RBAC across four roles (ADMIN / OPERATOR / VIEWER / CUSTOM) with auth check before JSON parse, rate-limiting on the login endpoint, TLS enforcement via --force-https.
Design philosophy: "User Competence over User Delight." Monospace data font for tabular digits, high contrast, information density that lab technicians prefer. No generic SaaS styling.
Real-time overview: samples, orders, critical results, and activity chart
Sample list with status filter, barcode scan, and soft-delete (status → ARCHIVED)
Orders by priority (NORMAL / URGENT / EMERGENCY) and status workflow
Test results with automatic flagging: NORMAL / LOW / HIGH / CRITICAL
Result entry with automatic flag calculation on deviation from the reference range
Complete ISO-15189-compliant audit trail with filtering and CSV export
Terminal Industrial Dark Mode with neon accents — activated via sudo key sequence
| Target audience | Why OpenSylab fits |
|---|---|
| Small to medium diagnostic laboratories | ISO 15189 audit trail + RBAC without enterprise license costs (LabWare, STARLIMS: from USD 100,000/year) |
| Research laboratories in university hospitals | Complete workflow (Sample → Order → Result → Audit) at clinical compliance level |
| Laboratories with data protection requirements (GDPR) | Self-hosted, no US-cloud dependency, patient data in your own infrastructure |
| IT teams without DBA staff | SQLite embedded: no database server, no connection pool, backup via file copy |
| Facilities with KIS integration | HL7 v2.5.1 + FHIR R4 native — no separate middleware server required |
OpenSylab is not suitable for: high-throughput laboratories with >100 concurrent write operations (SQLite single-writer limit), laboratories that require SaaS operation without their own IT infrastructure.
| Feature | Description |
|---|---|
| Sample management | CRUD, barcode scan (BarcodeDetector API), status workflow: REGISTERED → IN_ANALYSIS → ANALYZED → VALIDATED → ARCHIVED |
| Order management | Linked to samples, priorities (NORMAL / URGENT / EMERGENCY), status workflow, transition validation in the backend |
| Result entry | Auto-flag on input: NORMAL / LOW / HIGH / CRITICAL (margin-based: 50 % of the reference interval) — manual override possible |
| Soft-delete | Samples → ARCHIVED, orders → CANCELLED, results → REJECTED — rows are retained for the audit trail |
| Reference ranges | Per result reference_low / reference_high, flag recalculated on every update |
| Pagination | Server-side pagination on all list endpoints (limit / offset, capped at 1 000) |
| Global search | Header search bar navigates via ?q= to samples or orders |
| Migration framework | Versioned DB schema migrations with checksums, run at startup |
| OpenAPI spec | Machine-readable spec served at GET /api/v1/openapi.yaml |
| Feature | Description |
|---|---|
| Batch CSV import (samples) | RFC 4180, BOM-tolerant, 5 MB limit, per-row error tracking |
| Batch CSV import (results) | Multiline fields with correct escape state machine |
| HL7 v2.5.1 | ORU^R01 import + export via HTTP API (/api/v1/hl7/import) with complete field escaping |
| FHIR R4 | Bundle import (Patient, Specimen, ServiceRequest, Observation) + export via HTTP API |
| Audit log export | CSV export (ADMIN only) with configurable retention policy |
| Statistics | Dashboard tiles, status distribution, critical results (real-time, backend-aggregated) |
| Feature | Description |
|---|---|
| JWT authentication | HMAC-SHA256, expiry configurable via OPENSYLAB_JWT_SECRET |
| PBKDF2 password hashing | 210,000 iterations, random salt, empty-salt guard, constant-time comparison (OWASP 2023) |
| RBAC | 4 roles: ADMIN / OPERATOR / VIEWER / CUSTOM — enforced on all write endpoints, auth check before JSON parse |
| Rate-limiting | 10 attempts / 60 s per IP on /api/v1/auth/login, query-string-resistant |
| MFA (TOTP) | RFC 6238 HMAC-SHA1, ±1 time window (90 s), Google Authenticator compatible |
| LDAP | Optional LDAP authentication with local shadow account and role mapping |
| Last-admin protection | updateUser, deleteUser, assignUserRole block demotion of the last admin — transactional, no TOCTOU |
| Self-delete guard | Admin cannot deactivate themselves |
| Audit on all writes | Every CREATE / UPDATE / DELETE produces an AuditEntry with user_id, action, entity, timestamp |
| HMAC-SHA256 audit hash chain | Every audit entry carries an HMAC over its content + previous hash; chain integrity verifiable via GET /api/v1/audit/verify |
| Error sanitization | HTTP responses contain no SQLite internals |
| TLS/HTTPS | --tls-cert / --tls-key flags; --force-https prevents HTTP operation in production |
| Feature | Description |
|---|---|
| React 18 + TypeScript strict | No any types in production code, 0 TypeScript errors |
| RBAC in the UI | canWrite guards on all Create/Edit/Delete buttons; sidebar links role-dependent |
| Dark mode | Terminal-industrial aesthetic via sudo key sequence (Easter egg) |
| Responsive tables | Secondary columns hidden on tablet (md:hidden) |
| useEntityList hook | Universal paginated list hook with abort mechanism, race-condition-safe |
| MFA login flow | Two-step login: credentials → TOTP code |
| Secure logout navigation | Sidebar logout navigates immediately to /login |
| Health endpoint | GET /api/v1/health — unauthenticated, returns {"status":"ok","version":"0.9.0"} |
| Version SSOT | CMakeLists.txt → include/version.h (C++); package.json → VITE_APP_VERSION (frontend) |
| IDatabase interface | Abstraction layer for testability; Database (SQLite) and PostgreSQLDatabase both implement IDatabase |
| Metric | Value |
|---|---|
| Unit tests | 228 passing |
| TypeScript | strict mode, 0 errors |
| npm audit | 0 vulnerabilities |
| Bug hunts (v0.9.0) | 36 waves, 3 consecutive APPROVED — 28 bugs fixed across 21 files |
| Total bug hunts | 80+ waves total, 120+ bugs fixed |
- Language: C++17
- Database: SQLite3 (embedded, no external server required)
- Auth: PBKDF2-HMAC-SHA256 (passwords) · HMAC-SHA256 JWT · HMAC-SHA1 TOTP
- Cryptography: OpenSSL 3.x (EVP_MAC API)
- JSON: nlohmann/json
- Logging: spdlog
- Build: CMake 3.15+
- Framework: React 18 + TypeScript (strict mode)
- Build: Vite 7
- Routing: React Router v6
- HTTP: Axios with JWT interceptor + token-expiry guard
- Styling: Tailwind CSS 3
- Charts: Recharts
- CMake ≥ 3.15
- GCC / Clang with C++17 support
- OpenSSL
- Node.js ≥ 18
- SQLite3 (development libraries)
# 1. Repository klonen
git clone https://github.com/AurevionSec/openSylab.git
cd openSylab
# 2. Backend bauen
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build --parallel $(nproc)
# 3. Server starten (Port 9080, DB wird automatisch angelegt)
./build/bin/OpenSylab --api --api-port 9080 --db opensylab.db
# 4. Frontend bauen & starten
cd frontend
npm install
echo "VITE_API_URL=http://localhost:9080/api/v1" > .env.production
npm run build
npx serve dist --listen 5173 --singleOpen browser: http://localhost:5173
Default login: admin / admin → change password immediately!
docker compose up -dDetailed instructions: docs/DOCKER.md
| Environment variable | Default | Description |
|---|---|---|
OPENSYLAB_JWT_SECRET |
dev-secret | JWT signing key (in production: generate randomly, ≥32 chars!) |
OPENSYLAB_AUDIT_HMAC_KEY |
— | HMAC key for audit hash chain (mandatory in production, ≥32 chars; generate with openssl rand -hex 32) |
OPENSYLAB_CORS_ORIGIN |
http://localhost:5173 |
Allowed frontend origin |
OPENSYLAB_DB_PATH |
opensylab.db |
Database path |
OPENSYLAB_TLS_CERT |
— | Path to TLS certificate (PEM) |
OPENSYLAB_TLS_KEY |
— | Path to TLS key (PEM) |
# Produktionsstart mit TLS
OPENSYLAB_JWT_SECRET="$(openssl rand -hex 32)" \
OPENSYLAB_CORS_ORIGIN="https://lims.meinlabor.de" \
./build/bin/OpenSylab \
--api --api-port 9443 \
--tls-cert /etc/ssl/lims.crt \
--tls-key /etc/ssl/lims.key \
--force-https \
--db /var/lib/opensylab/lims.db┌─────────────────────────────────────────────────┐
│ Frontend (React 18 / TypeScript) │
│ http://localhost:5173 │
└──────────────────┬──────────────────────────────┘
│ HTTPS / JWT
┌──────────────────▼──────────────────────────────┐
│ REST API (C++17) │
│ Port 9080/9443 · /api/v1/* │
│ │
│ Layer 4: ApiServer (HTTP-Routing, TLS, CORS) │
│ Layer 3: JwtAuth (Token-Validierung, RBAC) │
│ Layer 2: Utils (CSV, HL7, FHIR, CLI) │
│ Layer 1: Database (SQLite3-Persistenz) │
│ Layer 0: Core (Domain-Entities) │
└──────────────────┬──────────────────────────────┘
│
┌──────────────────▼──────────────────────────────┐
│ SQLite3 (embedded) · opensylab.db │
└─────────────────────────────────────────────────┘
Layer rule: Layer N may only import Layer N-1 — no circular dependencies.
| Method | Endpoint | Description | Auth |
|---|---|---|---|
GET |
/api/v1/health |
Health check + version | — |
POST |
/api/v1/auth/login |
JWT login (+ MFA) — rate-limited | — |
GET |
/api/v1/samples |
Sample list (?q=, ?status=) |
JWT |
POST |
/api/v1/samples |
Create sample | OPERATOR+ |
PUT |
/api/v1/samples/:id |
Update sample (transition validated) | OPERATOR+ |
GET |
/api/v1/orders |
Order list | JWT |
POST |
/api/v1/orders |
Create order | OPERATOR+ |
GET |
/api/v1/results |
Result list (?flag=, ?status=) |
JWT |
POST |
/api/v1/results |
Enter result | OPERATOR+ |
GET |
/api/v1/audit |
Audit log (filtered, exportable) | ADMIN |
GET |
/api/v1/users |
User list | ADMIN |
POST |
/api/v1/hl7/import |
HL7 v2.5.1 ORU^R01 import | OPERATOR+ |
POST |
/api/v1/fhir/import |
FHIR R4 Bundle import | OPERATOR+ |
GET |
/api/v1/stats |
Dashboard statistics (backend-aggregated) | JWT |
GET |
/api/v1/audit/verify |
Verify HMAC audit hash chain integrity | ADMIN |
GET |
/api/v1/openapi.yaml |
OpenAPI 3.0 specification | — |
Full API documentation: docs/API.md
# Backend-Tests ausführen
cmake --build build && ./build/bin/opensylab_tests
# Frontend-Typprüfung
cd frontend && npx tsc --noEmit
# CI-äquivalent (mit Timeout)
timeout 60 ./build/bin/opensylab_tests228 unit tests passing — backend (C++): database, domain entities, API router, CSV import, HL7, FHIR, statistics, utils.
Further details: docs/TESTING.md
The version number has one canonical source per layer:
- C++:
CMakeLists.txt→project(VERSION x.y.z)→ generatesinclude/version.hin the build tree - Frontend:
frontend/package.json→"version"→import.meta.env.VITE_APP_VERSION
See docs/VERSIONING.md for the release process.
- Fork & branch:
git checkout -b feat/my-feature - Implement + write tests
cmake --build build && timeout 60 ./build/bin/opensylab_tests— all tests greencd frontend && npx tsc --noEmit— 0 TypeScript errors- Open a pull request
MIT — see LICENSE
Developed with Claude Code (Anthropic).
Full version history: CHANGELOG.md
Current version: 0.9.0 — architecture modernization: IDatabase interface, nlohmann/json, spdlog, migration framework, OpenAPI spec, HMAC audit hash chain, 228 tests passing.