The hardware and bandwidth for this mirror is donated by dogado GmbH, the Webhosting and Full Service-Cloud Provider. Check out our Wordpress Tutorial.
If you wish to report a bug, or if you are interested in having us mirror your free-software or open-source project, please feel free to contact us at mirror[@]dogado.de.

regulog

R-CMD-check Codecov

Tamper-Evident Audit Logging for Regulated Environments

Every analytical action taken in a consequential R environment should be documented — who did it, what they did, when, and why. In practice, almost none of it is.

regulog fills that gap. It records every action, change, note, and decision into a tamper-evident, hash-chained audit trail stored as newline-delimited JSON. Every entry is attributed to a named user, time-stamped in UTC, and linked to the previous entry via SHA-256 — so any modification after the fact, however subtle, is detectable by verify_log().

Works for regulated pharmaceutical environments (21 CFR Part 11, EU Annex 11), internal data pipelines, multi-user Shiny applications, and any context where accountability and traceability matter.

Installation

# Install from GitHub
pak::pak("repro-stats/regulog")

Quick start

library(regulog)

# Initialise a session
log <- regulog_init(
  app     = "primary-analysis",
  version = "1.0.0",
  user    = "analyst",
  path    = "logs/audit.rlog"
)

# Log actions, changes, and decisions
log_action(log,
  action = "data_read",
  object = "adsl.sas7bdat",
  reason = "Reading ADSL for primary efficacy analysis"
)

log_change(log,
  object = "alpha",
  field  = "value",
  before = "0.05",
  after  = "0.025",
  reason = "Updated per protocol amendment 2"
)

log_note(log,
  "Outlier in subject 01-042 retained per SAP section 8.3 —
   discussed with medical monitor 2026-06-20"
)

# Log data reads, scoped to a block — read() is logged automatically
with_log(log, {
  adsl <- read(haven::read_sas, "data/adsl.sas7bdat")
  adae <- read(haven::read_sas, "data/adae.sas7bdat")
})

# Apply an electronic signature
log_signature(log,
  "I certify this analysis is accurate and complete per SAP version 2.0")

# Verify tamper integrity
verify_log(log)
#> regulog: Log intact: 5 entries, chain unbroken

# Query the log
filter_log(log, type = "SIGNATURE")
filter_log(log, action = "data_read", from = "2026-06-01")

# Export for submission
export_audit_trail(log, format = "csv", signed = TRUE,
                   path = "outputs/audit_trail.csv")

Key functions

Function Purpose
regulog_init() Initialise an audit logging session
log_action() Log a discrete action
log_change() Log a before/after field change
log_note() Log a free-text annotation or analytical decision
log_signature() Apply an electronic signature
rl_read() Explicit, logged read of any data source
with_log() Scoped convenience: read() calls inside the block log automatically
verify_log() Verify SHA-256 hash chain integrity
filter_log() Query entries by type, user, action, or date
export_audit_trail() Export to CSV or JSON, with optional signing
regulog_shiny_init() Initialise inside a Shiny server function
regulog_observer() Auto-log Shiny reactive input events

The hash chain

Each entry hash is SHA-256 of all entry fields plus the prior hash:

h_0 = SHA256("GENESIS" | app | version | timestamp)
h_n = SHA256(entry_id | timestamp | app | version | user | type |
             <payload fields> | h_{n-1})

Any modification to any field in any entry breaks the chain from that point forward. verify_log() recomputes every hash and reports the first broken link — and works offline from the .rlog file, without an active R session.

Entry types

Type Created by Purpose
ACTION log_action() Discrete events: reads, runs, approvals
CHANGE log_change() Before/after field modifications
NOTE log_note() Decisions and free-text rationale
SIGNATURE log_signature() Named, dated, meaningful sign-off

Validation

Deploying any software in a regulated environment requires documented evidence that it is installed correctly, operates as specified, and performs reliably under real-world conditions. This is the IQ/OQ/PQ qualification process required under 21 CFR Part 11, EU Annex 11, and GAMP 5 before a tool can be used in GxP workflows.

regulog ships pre-written, executable qualification protocols. Instead of authoring validation documents from scratch — a process that typically takes weeks of internal effort — your team runs three commands and receives a complete, signed qualification record:

source(system.file("validation/IQ_regulog.R", package = "regulog"))
source(system.file("validation/OQ_regulog.R", package = "regulog"))
source(system.file("validation/PQ_regulog.R", package = "regulog"))

Each protocol is self-contained and produces a pass/fail summary against explicit acceptance criteria:

Protocol What it covers Tests
IQ — Installation Qualification R version, package installation, dependency integrity, file system access 10
OQ — Operational Qualification All 21 CFR §11.10 requirements: hash chain, tamper detection, user attribution, timestamps, export, signatures 26
PQ — Performance Qualification End-to-end clinical workflows: data review, regulatory export, multi-user sessions, 500-entry load test, inspector query simulation 7

Protocols are version-controlled alongside the package and updated with every release that affects qualified behaviour.

The qualification record produced by each run — including the platform, R version, date, and pass/fail status — can be retained as documented evidence of system qualification in your validated environment.

Regulatory coverage

Regulation Clause Coverage
21 CFR Part 11 §11.10(e) Hash-chained, time-stamped, user-attributed entries
21 CFR Part 11 §11.10(b) export_audit_trail() CSV and JSON
21 CFR Part 11 §11.100 log_signature() signer identity
21 CFR Part 11 §11.200 Signature components: identity, timestamp, meaning
EU Annex 11 Clause 9 Date, time, user, action on every entry
EU Annex 11 Clause 11 verify_log() periodic integrity evaluation

These binaries (installable software) and packages are in development.
They may not be fully stable and should be used with caution. We make no claims about them.
Health stats visible at Monitor.