Legacy industrial historians were architected in the 1980s around an assumption that stopped being true twenty years ago: disk storage was scarce and expensive.

To survive on 1980s spinning media, proprietary systems like the OSIsoft / AVEVA PI System introduced two compromises that regulated biopharma plants have been paying for ever since:

  1. Lossy “Swinging Door” (CompDev) archive compression, which discards raw sensor readings and replaces them with straight-line approximations—risking blunted UV280 chromatography peaks on a purification skid or concealed thermal transients during GMP batch review.
  2. Per-tag and per-seat licensing tiers paired with fragile Windows DCOM plumbing, which forces automation teams to ration which shop-floor parameters get archived and locks historical batch data inside proprietary binary .dat files.

On the other side of the aisle, generic open-source time-series stacks (vanilla InfluxDB, Prometheus, or raw TimescaleDB) fail the moment an FDA or EMA inspector asks for 21 CFR Part 11 §11.10(e) Write-Once-Read-Many (WORM) audit trails, §11.200 dual-challenge electronic signatures, ISA-95 hierarchical asset context, ISA-88 batch and excursion Event Frames, OPC signal quality (quality >= 192) filtering, and discrete (LOCF) versus continuous (LINEAR) interpolation.

We built GxPHistorian (github.com/saram-io/gxp-historian) to close that gap. It is an MIT-licensed, 4-Pillar open-source industrial time-series historian and asset framework engineered from the database kernel up for 21 CFR Part 11, EU GMP Annex 11, and ISPE GAMP 5 (Second Edition).


1. The 4-Pillar Architecture: Separating Immutable Telemetry from Mutable Control

A regulated industrial historian has to solve two fundamentally opposite database workloads at the same time:

  • High-frequency append-only telemetry (1 Hz to 10 Hz across tens of thousands of tags), which must be ingested without lock contention, compressed losslessly, and aggregated over decades of batch history.
  • Transactional relational control state (ISA-95 asset trees, tag engineering catalogs, ISA-88 Event Frame state transitions, and 21 CFR Part 11 WORM audit logs), which requires strict ACID transactions, foreign-key integrity, and kernel-level triggers.

Forcing high-frequency telemetry into a row-oriented relational engine creates B-tree index bloat and VACUUM stalls. Conversely, storing mutable Event Frames and Part 11 audit trails inside a columnar OLAP engine triggers expensive ALTER TABLE ... UPDATE/DELETE part rewrites.

GxPHistorian decouples these workloads into four specialized pillars bridged in real time via an in-memory ClickHouse FLAT dictionary:

┌────────────────────────────────────────────────────────────────────────────┐
│                      GxPHistorian 4-Pillar Architecture                    │
├────────────────────────────────────────────────────────────────────────────┤
│                                                                            │
│  PILLAR 1: Multi-Protocol Edge Collector (edge-collector)                  │
│  ┌────────────────────────────────────┐   ┌─────────────────────────────┐  │
│  │ OPC UA (:4840), S7comm (:102),     │   │ Stage 1 Exception Deadband  │  │
│  │ BACnet/IP (:47808 COV) & MS/TP,    │──▶│ Filter (ExcDev / ExcMax)    │  │
│  │ Modbus TCP/RTU, HART, RS-232,      │   │ + 1,000,000-Sample Disk WAL │  │
│  │ Zero-DCOM Windows OPC DA, Watchdir │   │ (/var/lib/telegraf/buffer)  │  │
│  └────────────────────────────────────┘   └──────────────┬──────────────┘  │
│                                                          │                 │
│                                           HTTP JSONEachRow (:8125)         │
│                                                          ▼                 │
│  PILLAR 2: Immutable Telemetry Archive    PILLAR 3: Part 11 Control Plane  │
│  (clickhouse-archive — ClickHouse 24.8)   (postgres-control + FastAPI)     │
│  ┌────────────────────────────────────┐   ┌─────────────────────────────┐  │
│  │ pi_historian.sensor_data           │   │ PostgreSQL 16 (ltree,       │  │
│  │ MergeTree partitioned by YYYYMM    │   │ btree_gist, pgcrypto)       │  │
│  │ Codecs: Delta + DoubleDelta +      │   │ • ISA-95 Asset Hierarchy    │  │
│  │ Gorilla + T64 + ZSTD(1)            │   │ • Tag Catalog & Limits      │  │
│  │ (1.5–2.5 bytes/sample, 100% raw)   │   │ • ISA-88 Event Frames       │  │
│  ├────────────────────────────────────┤   │ • PL/pgSQL WORM Triggers    │  │
│  │ pi_historian.sensor_rollup_1m      │   │ • SHA-256 Audit Hash Chain  │  │
│  │ AggregatingMergeTree               │   │ • §11.200 HMAC E-Signatures │  │
│  │ Strictly WHERE quality >= 192      │   ├─────────────────────────────┤  │
│  ├────────────────────────────────────┤   │ FastAPI + Pydantic AI + MCP │  │
│  │ pi_historian.pg_asset_tags         │◀──│ v_clickhouse_tag_dict sync  │  │
│  │ In-Memory FLAT Dictionary (5–15s)  │   │ LTTB, DataLink & AI CoPilot │  │
│  └─────────────────┬──────────────────┘   └──────────────┬──────────────┘  │
│                    │                                     │                 │
│                    └──────────────────┬──────────────────┘                 │
│                                       ▼                                    │
│  PILLAR 4: Operator HMI, Excel DataLink & Enterprise Lakehouse             │
│  ┌──────────────────────┐ ┌────────────────────────┐ ┌──────────────────┐  │
│  │ Grafana OSS 11.2 HMI │ │ Excel DataLink Client  │ │ Zero-ETL Parquet │  │
│  │ Asset-Relative LTTB  │ │ xlwings UDFs + Native  │ │ PyArrow Snappy   │  │
│  │ Trends + EF Overlays │ │ Power Query CSV Stream │ │ + S3 WORM Tier   │  │
│  └──────────────────────┘ └────────────────────────┘ └──────────────────┘  │
└────────────────────────────────────────────────────────────────────────────┘

Container & Port Matrix

All five core services launch via a single orchestrated docker-compose.yml stack with deterministic healthchecks:

Container Name Architectural Role Internal Port Host Port (.env) Core Technology Stack
edge-collector Pillar 1: Multi-Protocol Collector, Stage 1 Deadband & Disk WAL 8080 8080 InfluxData Telegraf 1.32 Alpine + Python 3.12
clickhouse-archive Pillar 2: Lossless Time-Series Archive & 1-Minute Rollup Engine 8123 / 9000 8125 / 9005 ClickHouse Server 24.8 LTS (Apache-2.0)
postgres-control Pillar 3: ISA-95 Asset Hierarchy & 21 CFR Part 11 WORM Audit Log 5432 5435 PostgreSQL 16 (ltree, btree_gist, pgcrypto)
historian-api Pillar 3: GxP REST API, Event Frame Engine, DataLink & AI/MCP 8000 8020 FastAPI, Psycopg 3, ClickHouse Connect, PyArrow, Pydantic AI, FastMCP
grafana-vision Pillar 4: Pre-Provisioned Bioreactor & Cleanroom Operator HMI 3000 3020 Grafana OSS 11.2 + ClickHouse & PostgreSQL Datasources

2. 1-to-1 Parity with the OSIsoft / AVEVA PI System

Migrating off a legacy historian fails if process engineers lose their Excel batch reports or operators lose their asset-relative trend displays. Every subsystem in GxPHistorian maps directly to its familiar OSIsoft / AVEVA PI System counterpart:

Legacy OSIsoft / AVEVA PI Component GxPHistorian Open-Source Equivalent Key Technical & Regulatory Capabilities
PI Data Archive (Swinging Door CompDev) ClickHouse 24.8 LTS (pi_historian.sensor_data) 100% mathematically lossless Delta, DoubleDelta, Gorilla & T64 + ZSTD(1) compression (1.5–2.5 B/sample) + real-time 1m AggregatingMergeTree rollups (WHERE quality >= 192).
PI Asset Framework (PI AF) PostgreSQL 16 ltree + ClickHouse FLAT Dictionary ISA-95 Enterprise.Site.Area.Unit paths indexed via GiST and synchronized into ClickHouse RAM (pg_asset_tags) every 5–15 seconds for O(1) metadata enrichment.
PI Event Frames (EF) PostgreSQL event_frames + FastAPI State Machine Automated ISA-88 batch & excursion capture (peak_val, avg_val, min_val, sample_count over quality >= 192) with §11.200 dual-challenge HMAC-SHA256 electronic signatures.
PI Interface Node & PI Buffer Subsystem Telegraf 1.32 Disk WAL + Python Edge Workers In-memory Stage 1 Exception/Deadband filtering (ExcDev & ExcMax) + 1,000,000-metric disk store-and-forward WAL (/var/lib/telegraf/buffer) across 10 industrial protocols.
PI Vision (PlotValues Trends & Overlays) Grafana OSS 11.2 + ClickHouse LTTB Asset-relative (${asset_path}) operator HMI with native largestTriangleThreeBuckets peak preservation, Event Frame shaded bands, and live Part 11 WORM audit table.
PI DataLink (Excel PISampDat / PIAdvCalcDat) FastAPI DataLink CSV/JSON + xlwings UDFs Drop-in =GXPHISTORIAN_SAMPLED(), =GXPHISTORIAN_PLOT_VALUES(), and =GXPHISTORIAN_EVENT_SUMMARY() Excel functions plus zero-macro Power Query CSV streams enforcing LINEAR vs. LOCF interpolation.
PI Integrator for Business Analytics FastAPI + PyArrow Zero-ETL Exporter Single-call POST /api/v1/lakehouse/export-parquet generating Snappy-compressed Apache Parquet files enriched with ISA-95 asset paths and engineering units.
AVEVA Industrial AI Assistant / PI Web API Pydantic AI Co-Pilot & gxphistorian-mcp Server Typed ISA-88 Excursion Investigator (DeviationInvestigationBrief, WHERE quality >= 192), Part 11 human-in-the-loop ApprovalRequired tag provisioning, and 6-tool FastMCP server.

3. The Compression Math: Why Lossy Swinging Door Is Obsolete

In a legacy PI System, data reduction happens in two stages:

  1. Stage 1 (Exception Reporting at the Interface Node): Suppresses stationary ADC electrical jitter within an exception deadband (ExcDev) until a meaningful change occurs or the heartbeat timer (ExcMax) expires.
  2. Stage 2 (Swinging Door Compression at the Archive): Discards actual emitted points that fall within a sloped parallelogram (CompDev), storing only inflection points.

Stage 1 makes physical sense—recording 24-bit ADC thermal noise when a bioreactor hold temperature sits at 37.00°C wastes network bandwidth. Stage 2 (CompDev), however, permanently alters the original measurement record. If CompDev is misconfigured on a tangential flow filtration (TFF) transmembrane pressure sensor or a chromatography UV280 detector, sharp transient spikes are smoothed away before they ever hit disk. Under ALCOA+ Original and Accurate record principles, throwing away emitted primary data to save a few bytes is an unnecessary regulatory risk.

GxPHistorian retains Stage 1 Exception Deadband filtering (ExcDev / ExcMax) at the Purdue Level 2.5 edge (edge-collector)—and sets exc_dev = 0.0 for at-line PAT analyzers so every discrete assay is captured—while replacing Stage 2 with 100% mathematically lossless columnar codecs in ClickHouse (init-clickhouse/01_telemetry_core.sql):

CREATE TABLE IF NOT EXISTS pi_historian.sensor_data
(
    tag_id UInt32 CODEC(Delta, ZSTD(1)),
    ts DateTime64(3, 'UTC') CODEC(DoubleDelta, ZSTD(1)),
    val Float64 CODEC(Gorilla, ZSTD(1)),
    str_val LowCardinality(String) DEFAULT '' CODEC(ZSTD(1)),
    quality UInt8 DEFAULT 192 CODEC(T64, ZSTD(1)),
    status_code UInt16 DEFAULT 0 CODEC(T64, ZSTD(1))
)
ENGINE = MergeTree()
PARTITION BY toYYYYMM(ts)
ORDER BY (tag_id, ts);

Because rows are physically sorted on disk by (tag_id, ts):

  • DoubleDelta on ts (DateTime64(3, 'UTC')): At regular 1 Hz polling intervals, the second derivative of the timestamp is 0, compressing an 8-byte millisecond timestamp to 1–2 bits before ZSTD(1).
  • Gorilla XOR on val (Float64): Facebook’s Gorilla XOR floating-point codec XORs consecutive IEEE 754 values for the same tag_id, storing only the changed mantissa bits.
  • T64 bit-transposition on quality and status_code: Since OPC Good quality (192) is constant across >99.9% of samples, bit-transposition plus ZSTD(1) reduces the quality column to near-zero overhead.

An uncompressed 25-byte telemetry row plus its 1-minute AggregatingMergeTree rollup state compresses to B_eff ≈ 1.5 to 2.5 bytes per sample:

Annual Disk per Tag (at 1 Hz) = 86,400 samples/day × 365.25 days × B_eff × (1 - R_deadband)

Even for a 25,000-tag commercial GMP facility, 10 years of online hot NVMe storage is remarkably small:

Operating Scenario Effective Sample Rate (1 - R_deadband) Bytes / Tag / Day Annual Storage / Tag 10-Year Hot Storage (25,000 Tags)
Worst-Case Continuous (exc_dev = 0, 100% 1 Hz) 1.00 Hz (0% suppression) 216 KB/day 78.9 MB/yr 19.7 TB
Conservative GMP Bioprocess Mix (50% suppression) 0.50 Hz average 108 KB/day 39.5 MB/yr 9.86 TB
Typical GMP Plant Mix (70% deadband suppression) 0.30 Hz average 64.8 KB/day 23.7 MB/yr 5.92 TB

After 10 years on local enterprise NVMe RAID-1, ClickHouse’s native multi-volume TTL ts + INTERVAL 10 YEAR TO VOLUME 'cold_worm_s3' zero-copy tiering moves aged partitions to 15-year S3 / MinIO Object Lock (Compliance Mode) storage to satisfy FDA 21 CFR 211.180 and EU GMP Chapter 4 retention rules.


4. Database-Kernel 21 CFR Part 11 WORM & Cryptographic Hash Chaining

FDA and EMA data integrity auditors no longer accept “trust the web application” as a control for electronic batch records. If an audit log is written only by Python or Node.js middleware, anyone with a database credential—or a bug in an ORM migration—can mutate a tag limit or delete an audit row without leaving a trace.

GxPHistorian enforces 21 CFR Part 11 and EU GMP Annex 11 directly inside the PostgreSQL 16 database kernel (init-postgres/01_control_plane_part11.sql):

1. Mandatory Session Attribution (21 CFR §11.10(e))

Every INSERT, UPDATE, or DELETE on asset_templates, assets, tags, and event_frames is intercepted by the PL/pgSQL trigger function fn_enforce_part11_audit(). Before executing any DML statement, the transaction must bind app.actor_id and app.change_reason via SET LOCAL (populated from X-Actor-Id and X-Change-Reason HTTP headers on historian-api). Any unattributed SQL mutation immediately aborts the transaction:

-- Enforce mandatory 21 CFR Part 11 attribution context
v_actor  := NULLIF(current_setting('app.actor_id', true), '');
v_reason := NULLIF(current_setting('app.change_reason', true), '');

IF v_actor IS NULL OR v_reason IS NULL THEN
    RAISE EXCEPTION '21 CFR Part 11 Violation: app.actor_id and app.change_reason are mandatory';
END IF;

2. Unconditional WORM Audit Triggers

The part11_audit_log table attaches both row-level and statement-level triggers (trg_worm_part11_audit_log_row and trg_worm_part11_audit_log_stmt) executing fn_prevent_audit_tampering(). Any UPDATE, DELETE, or TRUNCATE against part11_audit_log unconditionally raises 21 CFR Part 11 WORM Violation: Audit trail records are immutable—blocking tampering even by PostgreSQL superusers.

3. Cryptographic SHA-256 Hash Chaining (ALCOA+ Original & Enduring)

Every audit row locks the table in EXCLUSIVE MODE to serialize chain order and computes a pgcrypto SHA-256 digest linking the prior row’s hash starting from GENESIS_0000000000000000:

row_hash = SHA256(prev_hash || recorded_at || actor_id || operation || coalesce(new_payload, ''))

At any point during an inspection, QA can verify end-to-end cryptographic integrity from genesis via GET /api/v1/audit-trail/verify:

{
  "chain_valid": true,
  "verified_records": 220,
  "genesis_anchor": "GENESIS_0000000000000000",
  "broken_links": []
}

4. Dual-Challenge Electronic Signatures (§11.50, §11.70, §11.200)

Signing an ISA-88 Event Frame (POST /api/v1/event-frames/{event_id}/sign) requires a live dual-component challenge (user_id + password) verified against pgcrypto bcrypt hashes in PostgreSQL users. Upon verification, the control plane computes a non-repudiable HMAC-SHA256 signature digest over (event_id, user_id, signature_meaning, signed_at), binds the signature to the Event Frame, and records the execution in part11_audit_log.


5. Signal Quality Discipline (quality >= 192) and Step vs. Continuous Interpolation

Two subtle data-integrity bugs routinely corrupt custom historian implementations in biopharma:

Bug 1: Bad-Quality Sensor Faults Corrupting Batch Rollups

When a Pt100 RTD probe experiences a wire break or a pH probe is pulled during Clean-in-Place (CIP), PLCs frequently transmit sentinel fault values (-999.0 or 9999.0) tagged with OPC quality 0 (Bad) or 64 (Uncertain).

  • If you discard quality < 192 before ingestion, maintenance engineers lose the diagnostic evidence of when the wire broke.
  • If you include quality < 192 in your rollups, a single 1-second 9999.0 fault ruins the batch’s 1-minute average and triggers false excursion KPIs.

GxPHistorian archives all raw diagnostic states (192 = Good, 64 = Uncertain, 0 = Bad) in pi_historian.sensor_data, while strictly enforcing WHERE quality >= 192 across the 1-minute AggregatingMergeTree materialized view (mv_sensor_rollup_1m), ClickHouse largestTriangleThreeBuckets (LTTB) trend queries, Event Frame KPI calculations, and Excel DataLink exports.

Bug 2: Linear Interpolation of Discrete Equipment States

Continuous analog measurements (BR201_TEMP_PV, BR201_PH_PV, where is_step_tag = false) change smoothly over time and should be interpolated linearly (LINEAR) between archived timestamps. Discrete integer state tags (BR201_AGIT_STATE where 0 = Off, 1 = Low, 2 = High, or ISA-88 phase state tags where is_step_tag = true) jump instantaneously. Linearly interpolating a discrete tag between 1 and 2 synthesizes a non-existent state of 1.5.

GxPHistorian stores is_step_tag in PostgreSQL tags, syncs it into ClickHouse RAM (pi_historian.pg_asset_tags), and automatically dispatches:

  • Continuous tags (is_step_tag = false): ClickHouse time-weighted linear interpolation (WITH FILL STEP ... INTERPOLATE).
  • Discrete step tags (is_step_tag = true): Last Observation Carried Forward (LOCF_STEP) so integer equipment states never produce fractional artifacts in Grafana or Excel DataLink (=GXPHISTORIAN_SAMPLED()).

6. Deterministic AI Orchestration: Pydantic AI Co-Pilot & gxphistorian-mcp

Allowing a large language model to calculate time-series averages, interpolate timestamps in its context window, or execute electronic signatures would violate both GAMP 5 and ALCOA+ Accurate principles.

GxPHistorian implements an explicit architectural boundary in app/gxp_ai_agent.py (built on Pydantic AI) and app/mcp_server.py (built on FastMCP):

Core GxP AI Rule: AI proposes, queries, and correlates; deterministic ClickHouse and PostgreSQL execute, filter (WHERE quality >= 192), interpolate (LINEAR vs. LOCF_STEP), and audit (SHA-256 WORM chain).

1. Automated ISA-88 Excursion Pre-Investigation (gxp_deviation_investigator_agent)

When an Event Frame opens—for example, BR201_TEMP_PV_High_Limit_Excursion on BioCorp.Fremont.USP.Bioreactor_201—the investigator agent assembles a strictly typed DeviationInvestigationBrief Pydantic model (POST /api/v1/ai/event-frames/{event_id}/investigate):

  • Sibling Tag Correlation: Queries deterministic ClickHouse min_val, avg_val, max_val, good_sample_count (quality >= 192), and bad_quality_sample_count (quality < 192) across all tags attached to the same ISA-95 asset (BR201_TEMP_PV, BR201_PH_PV, BR201_AGIT_STATE).
  • Capabilities on Demand (defer_loading=True): Dynamically loads the part11-forensics capability to verify the PostgreSQL SHA-256 audit hash chain (verify_part11_hash_chain), inspect recent attributed changes (part11_audit_log), and run diagnose_opc_signal_quality to classify whether the event is a true critical_process_excursion, a sensor_or_signal_fault (quality < 192), or an intentional setpoint_or_recipe_transition.

2. Human-in-the-Loop Tag Onboarding (gxp_copilot_agent + ApprovalRequired)

When an automation engineer asks to onboard a new instrument (POST /api/v1/ai/copilot/propose-tag), gxp_copilot_agent loads the brownfield-onboarding capability (defer_loading=True), searches the 35+ biopharma equipment playbooks, validates engineering limits via args_validator (triggering ModelRetry if low_limit >= high_limit or if a step tag specifies a non-zero deadband), and raises Pydantic AI’s ApprovalRequired (DeferredToolRequests).

No database write occurs until a human engineer reviews the staged BrownfieldOnboardingPlan and commits it with explicit X-Actor-Id and X-Change-Reason headers. Furthermore, AI agents have zero tool access to POST /api/v1/event-frames/{event_id}/sign—electronic signatures remain strictly human-only under 21 CFR §11.200.

3. Model Context Protocol Server (gxphistorian-mcp)

For external agent ecosystems (Claude Desktop, Cursor, Antigravity, or GxPChat), app/mcp_server.py exposes six read-only deterministic tools and three URI resources:

  • mcp_browse_assets — Browse the ISA-95 ltree asset hierarchy and tag catalog.
  • mcp_get_lttb_plot_values — Fetch peak-preserving ClickHouse LTTB downsampled trends (WHERE quality >= 192).
  • mcp_get_sampled_values — Fetch interpolated time-series (LINEAR vs. LOCF_STEP).
  • mcp_list_event_frames — Query ISA-88 batch and excursion Event Frames and §11.200 signature status.
  • mcp_verify_part11_audit_chain — Execute live SHA-256 WORM hash-chain verification from GENESIS.
  • mcp_investigate_event_frame — Generate a deterministic DeviationInvestigationBrief for any Event Frame UUID.

7. 35+ Biopharma Equipment Playbooks & The 8-Document GAMP 5 Validation Binder

Software alone does not qualify a GMP plant. Two field-engineering deliverables ship directly inside the repository and on gxphistorian.com:

Visual Field-Engineering Playbooks for 35+ GMP Instruments

The documentation portal (gxphistorian.com/docs) provides step-by-step physical pinouts (RJ45 T568B, M12 D/X/A-Coded, DB9 RS-232/MPI, Phoenix RS-485, 4–20 mA HART), gateway part numbers (Moxa NPort, Advantech ADAM, LOYTEC BACnet, Helmholz S7), HMI click-paths, and copy-paste tag provisioning commands across:

  • Single-Use & Stainless USP Bioreactors: Cytiva Xcellerex™ XDR-50 to XDR-2000 (Figurate™ Automation / Emerson DeltaV™ / Rockwell PlantPAx®), Sartorius Biostat® STR & Ambr® 15/250, Thermo HyPerforma™ S.U.B., Eppendorf BioFlo® / DASGIP®.
  • Downstream Purification (Chromatography & TFF): Cytiva ÄKTA process™ / ready™ / readyflux™ (UNICORN™ 7 OPC UA/DA with LTTB UV280 peak preservation), Sartorius Sartoflow®, MilliporeSigma Mobius® / Cogent®.
  • At-Line PAT & In-Line Spectroscopy: Nova BioProfile® FLEX2, Beckman Vi-CELL™ BLU, Roche Cedex® Bio HT, Endress+Hauser Kaiser Raman Rxn2/4 (exc_dev = 0), Hamilton Arc® intelligent probes.
  • Cell & Gene Therapy (CAR-T) & mRNA-LNP: Miltenyi CliniMACS Prodigy®, Cytiva Sefia™ & Sepax™ C-Pro, Precision NanoSystems NanoAssemblr™, Planer Kryo 560 Controlled-Rate Freezers (COI_ID Event Frames).
  • Aseptic Fill-Finish, Lyophilization, EMS & QC Serial: SP Scientific / Telstar freeze dryers, SKAN isolators, PMS LasAir® III particle counters, Veolia Sievers® M9 TOC, BINDER stability chambers (ClickHouse Mean Kinetic Temperature SQL), Fedegari / Getinge autoclaves (F₀ lethality SQL), and Mettler Toledo XPR / Sartorius Cubis® II balances via RS-232 MT-SICS and SHA-256 watch-folders (replacing OSIsoft PI UFL).

Turnkey 8-Document GAMP 5 & FDA CSA Validation Binder

Every release includes an executable pytest Installation and Operational Qualification (IQ/OQ) suite (17/17 automated checks covering URS-001 through URS-017) that writes timestamped cryptographic test evidence to oq_execution_results.json and compiles a print-ready 8-Document Commercial GMP Validation Binder (inspect the live HTML binder here):

  1. VMP-GXPHISTORIAN-2026-001 — Validation Master Plan (GAMP 5 2nd Ed. & FDA CSA lifecycle).
  2. URS-GXPHISTORIAN-2026-002 — User Requirements Specification (URS-001 to URS-017).
  3. FDS-GXPHISTORIAN-2026-003 — Functional & Design Specification (4-Pillar schemas, codecs, and triggers).
  4. FRA-GXPHISTORIAN-2026-004 — FDA CSA Functional Risk Assessment.
  5. SOUP-GXPHISTORIAN-2026-005 — SOUP / OSS Vendor Qualification Dossier (pinned @sha256 container image digests).
  6. IQOQ-GXPHISTORIAN-2026-006 — Executed IQ/OQ Verification Report (17/17 Passed).
  7. RTM-GXPHISTORIAN-2026-007 — Bidirectional Requirements Traceability Matrix (URS ↔ FDS ↔ FRA ↔ IQ/OQ).
  8. VSR-GXPHISTORIAN-2026-008 — Validation Summary Report & QA Release Sign-Off.

8. Getting Started in 60 Seconds

You can launch the entire 5-service GxP stack—complete with a deterministic multi-protocol biopharma plant simulator (BioCorp.Fremont.USP.Bioreactor_201 and BioCorp.Fremont.Cleanroom.Suite_A), ClickHouse 24.8 LTS, PostgreSQL 16 WORM triggers, FastAPI control plane, and pre-provisioned Grafana Vision HMI—in three commands:

git clone https://github.com/saram-io/gxp-historian.git
cd gxp-historian

# 1. Launch all 5 GxP services (Edge WAL, ClickHouse, PG16, FastAPI, Grafana)
cp .env.example .env && docker compose up -d --build

# 2. Verify cryptographic SHA-256 WORM audit hash chain from GENESIS
curl -s http://localhost:8020/api/v1/audit-trail/verify | jq .

# 3. Execute the 17-test GAMP 5 / FDA CSA IQ & OQ qualification suite
.venv/bin/pytest -v

Explore GxPHistorian