返回技能列表

implement-audit-trail

pjt222
更新于 Yesterday
2 次查看
17
2
17
在 GitHub 上查看
aidesigndata

关于

This skill helps developers implement audit trail functionality in R projects for regulated environments like healthcare and pharmaceuticals. It provides tools for logging, provenance tracking, electronic signatures, and data integrity checks to meet 21 CFR Part 11 compliance requirements. Use it when you need tamper-evident analysis logs, detailed tracking of who did what and when, or electronic records compliance for regulatory submissions.

快速安装

Claude Code

推荐
主要方式
npx skills add pjt222/agent-almanac -a claude-code
插件命令备选方式
/plugin add https://github.com/pjt222/agent-almanac
Git 克隆备选方式
git clone https://github.com/pjt222/agent-almanac.git ~/.claude/skills/implement-audit-trail

在 Claude Code 中复制并粘贴此命令以安装该技能

技能文档

Implement Audit Trail

Add audit trail capabilities to R projects for regulatory compliance.

When Use

  • R analysis needs electronic records compliance (21 CFR Part 11)
  • Track who did what, when, why in analysis
  • Implement data provenance tracking
  • Create tamper-evident analysis logs

Inputs

  • Required: R project with data processing or analysis scripts
  • Required: Regulatory requirements (which audit trail elements mandatory)
  • Optional: Existing logging infrastructure
  • Optional: Electronic signature requirements

Steps

Step 1: Set Up Structured Logging

Create R/audit_log.R:

#' Initialize audit log for a session
#'
#' @param log_dir Directory for audit log files
#' @param analyst Name of the analyst
#' @return Path to the created log file
init_audit_log <- function(log_dir = "audit_logs", analyst = Sys.info()["user"]) {
  dir.create(log_dir, showWarnings = FALSE, recursive = TRUE)

  log_file <- file.path(log_dir, sprintf(
    "audit_%s_%s.jsonl",
    format(Sys.time(), "%Y%m%d_%H%M%S"),
    analyst
  ))

  entry <- list(
    timestamp = format(Sys.time(), "%Y-%m-%dT%H:%M:%S%z"),
    event = "SESSION_START",
    analyst = analyst,
    r_version = R.version.string,
    platform = .Platform$OS.type,
    working_directory = getwd(),
    session_id = paste0(Sys.getpid(), "-", format(Sys.time(), "%Y%m%d%H%M%S"))
  )

  write(jsonlite::toJSON(entry, auto_unbox = TRUE), log_file, append = TRUE)
  options(audit_log_file = log_file, audit_session_id = entry$session_id)

  log_file
}

#' Log an audit event
#'
#' @param event Event type (DATA_IMPORT, TRANSFORM, ANALYSIS, EXPORT, etc.)
#' @param description Human-readable description
#' @param details Named list of additional details
log_audit_event <- function(event, description, details = list()) {
  log_file <- getOption("audit_log_file")
  if (is.null(log_file)) stop("Audit log not initialized. Call init_audit_log() first.")

  entry <- list(
    timestamp = format(Sys.time(), "%Y-%m-%dT%H:%M:%S%z"),
    event = event,
    description = description,
    session_id = getOption("audit_session_id"),
    details = details
  )

  write(jsonlite::toJSON(entry, auto_unbox = TRUE), log_file, append = TRUE)
}

Got: R/audit_log.R created with init_audit_log() + log_audit_event() functions. Calling init_audit_log() creates audit_logs/ directory + timestamped JSONL file. Each log entry = single JSON line with timestamp, event, analyst, session_id fields.

If fail: jsonlite::toJSON() fails? Ensure jsonlite package installed. Log directory can't be created? Check file system permissions. Timestamps lack timezone? Verify %z supported on platform.

Step 2: Add Data Integrity Checks

#' Compute and log data hash for integrity verification
#'
#' @param data Data frame to hash
#' @param label Descriptive label for the dataset
#' @return SHA-256 hash string
hash_data <- function(data, label = "dataset") {
  hash_value <- digest::digest(data, algo = "sha256")

  log_audit_event("DATA_HASH", sprintf("Hash computed for %s", label), list(
    hash_algorithm = "sha256",
    hash_value = hash_value,
    nrow = nrow(data),
    ncol = ncol(data),
    columns = names(data)
  ))

  hash_value
}

#' Verify data integrity against a recorded hash
#'
#' @param data Data frame to verify
#' @param expected_hash Previously recorded hash
#' @return Logical indicating whether data matches
verify_data_integrity <- function(data, expected_hash) {
  current_hash <- digest::digest(data, algo = "sha256")
  match <- identical(current_hash, expected_hash)

  log_audit_event("DATA_VERIFY",
    sprintf("Data integrity check: %s", ifelse(match, "PASS", "FAIL")),
    list(expected = expected_hash, actual = current_hash))

  if (!match) warning("Data integrity check FAILED")
  match
}

Got: hash_data() returns SHA-256 hash string + logs DATA_HASH event. verify_data_integrity() compares current data vs stored hash + logs DATA_VERIFY event with PASS or FAIL status.

If fail: digest::digest() not found? Install digest package. Hashes don't match for identical data? Check column order + data types consistent between hashing + verification.

Step 3: Track Data Transformations

#' Wrap a data transformation with audit logging
#'
#' @param data Input data frame
#' @param transform_fn Function to apply
#' @param description Description of the transformation
#' @return Transformed data frame
audited_transform <- function(data, transform_fn, description) {
  input_hash <- digest::digest(data, algo = "sha256")
  input_dim <- dim(data)

  result <- transform_fn(data)

  output_hash <- digest::digest(result, algo = "sha256")
  output_dim <- dim(result)

  log_audit_event("DATA_TRANSFORM", description, list(
    input_hash = input_hash,
    input_rows = input_dim[1],
    input_cols = input_dim[2],
    output_hash = output_hash,
    output_rows = output_dim[1],
    output_cols = output_dim[2]
  ))

  result
}

Got: audited_transform() wraps any transformation function, logs input dimensions + hash, output dimensions + hash, transformation description as DATA_TRANSFORM event.

If fail: Transform function errors? Audit event not logged. Wrap transform in tryCatch() to log both successes + failures. Ensure transform function accepts + returns data frame.

Step 4: Log Session Environment

#' Log complete session information for reproducibility
log_session_info <- function() {
  si <- sessionInfo()

  log_audit_event("SESSION_INFO", "Complete session environment recorded", list(
    r_version = si$R.version$version.string,
    platform = si$platform,
    locale = Sys.getlocale(),
    base_packages = si$basePkgs,
    attached_packages = sapply(si$otherPkgs, function(p) paste(p$Package, p$Version)),
    renv_lockfile_hash = if (file.exists("renv.lock")) {
      digest::digest(file = "renv.lock", algo = "sha256")
    } else NA
  ))
}

Got: SESSION_INFO event logged with R version, platform, locale, attached packages + versions, renv lockfile hash (if applicable).

If fail: sessionInfo() returns incomplete package info? Ensure all packages loaded via library() before calling log_session_info(). renv lockfile hash = NA if project doesn't use renv.

Step 5: Implement in Analysis Scripts

# 01_analysis.R
library(jsonlite)
library(digest)

# Start audit trail
log_file <- init_audit_log(analyst = "Philipp Thoss")

# Import data with audit
raw_data <- read.csv("data/raw/study_data.csv")
raw_hash <- hash_data(raw_data, "raw study data")

# Transform with audit
clean_data <- audited_transform(raw_data, function(d) {
  d |>
    dplyr::filter(!is.na(primary_endpoint)) |>
    dplyr::mutate(bmi = weight / (height/100)^2)
}, "Remove missing endpoints, calculate BMI")

# Run analysis
log_audit_event("ANALYSIS_START", "Primary efficacy analysis")
model <- lm(primary_endpoint ~ treatment + age + sex, data = clean_data)
log_audit_event("ANALYSIS_COMPLETE", "Primary efficacy analysis", list(
  model_class = class(model),
  formula = deparse(formula(model)),
  n_observations = nobs(model)
))

# Log session
log_session_info()

Got: Analysis scripts init audit log at start, log each data import, transformation, analysis step, record session info at end. JSONL log file captures complete provenance chain.

If fail: init_audit_log() missing? Ensure R/audit_log.R sourced or package loaded. Events missing from log? Verify log_audit_event() called after every significant operation.

Step 6: Git-Based Change Control

Complement application-level audit trail with git:

# Use signed commits for non-repudiation
git config commit.gpgsign true

# Descriptive commit messages referencing change control
git commit -m "CHG-042: Add BMI calculation to data processing

Per change request CHG-042, approved by [Name] on [Date].
Validation impact assessment: Low risk - additional derived variable."

Got: Git commits signed (GPG) + use descriptive messages referencing change control IDs. Combination of application-level JSONL audit trail + git history provides complete change control record.

If fail: GPG signing fails? Configure signing key with git config --global user.signingkey KEY_ID. Key not set up? Follow gpg --gen-key to create one.

Checks

  • Audit log captures all required events (start, data access, transforms, analysis, export)
  • Timestamps use ISO 8601 format with timezone
  • Data hashes enable integrity verification
  • Session information recorded
  • Logs append-only (no deletion or modification)
  • Analyst identity captured for each session
  • Log format machine-readable (JSONL)

Pitfalls

  • Logging too much: Focus on regulated events. Don't log every variable assignment.
  • Mutable logs: Audit logs must be append-only. Use JSONL (one JSON object per line).
  • Missing timestamps: Every event needs timestamp with timezone.
  • No session context: Each log entry should reference session for correlation.
  • Forgetting to initialize: Scripts must call init_audit_log() before any analysis.

See Also

  • setup-gxp-r-project - project structure for validated environments
  • write-validation-documentation - validation protocols + reports
  • validate-statistical-output - output verification methodology
  • configure-git-repository - version control as part of change control

GitHub 仓库

pjt222/agent-almanac
路径: i18n/caveman/skills/implement-audit-trail
0
agentsagentskillsai-assisted-developmentclaude-codeskillsteams

相关推荐技能

content-collections

Content Collections 是一个 TypeScript 优先的构建工具,可将本地 Markdown/MDX 文件转换为类型安全的数据集合。它专为构建博客、文档站和内容密集型 Vite+React 应用而设计,提供基于 Zod 的自动模式验证。该工具涵盖从 Vite 插件配置、MDX 编译到生产环境部署的完整工作流。

查看技能

polymarket

这个Claude Skill为开发者提供完整的Polymarket预测市场开发支持,涵盖API调用、交易执行和市场数据分析。关键特性包括实时WebSocket数据流,可监控实时交易、订单和市场动态。开发者可用它构建预测市场应用、实施交易策略并集成实时市场预测功能。

查看技能

creating-opencode-plugins

该Skill帮助开发者创建OpenCode插件,用于接入命令、文件、LSP等25+种事件。它提供了插件结构、事件API规范和JavaScript/TypeScript实现模式,适合需要拦截操作、扩展功能或自定义事件处理的场景。开发者可通过它快速构建响应式模块来增强OpenCode AI助手的能力。

查看技能

sglang

SGLang是一个专为LLM设计的高性能推理框架,特别适用于需要结构化输出的场景。它通过RadixAttention前缀缓存技术,在处理JSON、正则表达式、工具调用等具有重复前缀的复杂工作流时,能实现极速生成。如果你正在构建智能体或多轮对话系统,并追求远超vLLM的推理性能,SGLang是理想选择。

查看技能