Tamper-evident workspace auditing — security, SOC 2, HIPAA, AI provenance. Merkle-sealed findings with encrypted evidence capsules.
Project description
GhostAudit
English · 中文 · 日本語 · 한국어 · Русский · Deutsch
Tamper-evident filesystem auditing for multi-project workspaces. Hashes every file with SHA-256, tracks changes across runs, generates a per-project AUDIT.md, and seals findings in a Merkle tree. Optional encrypted evidence capsules for SOC 2, HIPAA, and AI-provenance workflows.
Stdlib-only core. No pip dependencies unless you enable encrypted capsules.
Quick Start
pip install ghostaudit
# Run a full audit (inventory + index + diff)
ghostaudit --mode full --workspace /path/to/workspace
# Run the daily pipeline (hash → compare → audit or sleep)
ghostaudit --mode daily --workspace /path/to/workspace
# Just update project audits
ghostaudit --mode update_audits --workspace /path/to/workspace
# Preview audit changes without writing
python -m workspace_audit.update_audits --workspace /path/to/workspace --dry-run
Tools
| Tool | Purpose |
|---|---|
run_audit.py |
Orchestrator — runs any mode via --mode flag |
daily_audit.py |
Daily runner — hash, compare, full audit or sleep |
hash_manifest.py |
SHA-256 hashes every file, compares to previous manifest |
generate_inventory.py |
Scans workspace, classifies items, detects secrets |
build_index.py |
Generates consolidated AUDIT_INDEX.md from all data |
diff_audits.py |
Compares current vs previous snapshots, tracks changes |
update_audits.py |
Auto-generates and versions per-project AUDIT.md files |
Modes
run_audit.py --mode <mode>
| Mode | What it does |
|---|---|
full |
inventory → index → diff |
daily |
hash → compare → if changes: full + update_audits + daily report; if no changes: sleep |
inventory_only |
Just scan filesystem metadata |
index_only |
Regenerate AUDIT_INDEX.md from existing data |
diff_only |
Compare current to previous snapshot |
hash_only |
Hash files and compare to previous manifest |
update_audits |
Generate/update per-project AUDIT.md files |
Pipeline Flow
daily_audit.py
├── hash_manifest.py → audit/manifests/{timestamp}.json
│ └── compare → audit/manifests/latest_result.json
│
├── [if changes detected]
│ ├── generate_inventory.py → audit/inventory.json
│ ├── build_index.py → administration/AUDIT_INDEX.md
│ ├── diff_audits.py → audit/history/diffs/{timestamp}.json
│ ├── update_audits.py → {project}/AUDIT.md (versioned)
│ └── daily report → audit/daily/{date}.md
│
└── [if no changes]
└── log "no_changes" → audit/daily/daily_log.jsonl
Configuration
Create audit.config.json in your workspace root (optional — all settings have defaults):
{
"owner": "auto",
"composite_projects": ["my-monorepo"],
"force_audit_subdirs": ["legacy-api", "worker"],
"skip_dirs": [
"node_modules", ".git", "target", ".next", "dist", "__pycache__",
".pytest_cache", "venv", ".venv", "vendor", ".mypy_cache"
],
"admin_dir": "administration",
"audit_dir": "audit",
"version_audits": true,
"generate_sub_audits": true
}
| Setting | Default | Description |
|---|---|---|
owner |
"auto" |
Owner name in AUDIT.md. "auto" reads from git config user.name |
composite_projects |
[] |
Projects that should always be treated as composite (per-subdir audits) |
force_audit_subdirs |
[] |
Subdirectory names to audit even if they don't have build configs |
skip_dirs |
(see above) | Directories to skip when scanning |
admin_dir |
"administration" |
Where to write AUDIT_INDEX.md |
audit_dir |
"audit" |
Where to write inventory, manifests, and history |
version_audits |
true |
Archive old AUDIT.md before overwriting |
generate_sub_audits |
true |
Generate per-component audits for composite projects |
Composite Projects
Projects with 2+ subdirectories containing build configs (package.json, Cargo.toml, etc.) are automatically detected as composite. For each composite project:
- Each sub-component gets its own
{component}/AUDIT.md - The parent gets a summary
AUDIT.mdwith a component table - Add directories to
force_audit_subdirsin config if they lack standard build configs
Versioning
When version_audits is true (default), the old AUDIT.md is archived to {project}/audits/AUDIT-{date}.md before being overwritten. Same-day re-runs are detected and don't create duplicate archives.
Scheduling (Windows)
@echo off
cd /d C:\path\to\workspace
python tools\audit\daily_audit.py --workspace C:\path\to\workspace >> audit\daily\scheduler.log 2>&1
schtasks /create /tn "WorkspaceAudit" /tr "C:\path\to\schedule_daily.bat" /sc daily /st 04:00 /f
Scheduling (Linux/macOS)
# crontab -e
0 4 * * * cd /path/to/workspace && python tools/audit/daily_audit.py >> audit/daily/scheduler.log 2>&1
Output Structure
workspace/
├── audit/
│ ├── inventory.json # Current inventory
│ ├── inventory_summary.json # Rollup stats
│ ├── findings.json # Tracked findings
│ ├── manifests/ # Hash manifests
│ │ ├── {timestamp}.json
│ │ └── latest_result.json # Last comparison result
│ ├── history/
│ │ ├── inventory/ # Historical snapshots
│ │ ├── findings/
│ │ └── diffs/ # Change reports
│ └── daily/
│ ├── {date}.md # Daily reports
│ ├── daily_log.jsonl # Run log
│ └── scheduler.log # Cron/scheduler output
├── administration/
│ └── AUDIT_INDEX.md # Consolidated index
├── project-a/
│ ├── AUDIT.md # Auto-generated audit
│ └── audits/
│ └── AUDIT-2026-03-22.md # Versioned archive
└── audit.config.json # Configuration (optional)
GitHub Action
Use GhostAudit as a GitHub Action to get findings as GitHub Code Scanning alerts in pull requests and the repository Security tab.
Basic usage
- uses: adam-scott-thomas/ghostaudit@v1
with:
profiles: 'security'
fail-on: 'CRITICAL'
upload-sarif: 'true'
Full workflow example
name: Workspace Audit
on:
push:
branches: [main, master]
pull_request:
branches: [main, master]
schedule:
- cron: '0 4 * * *'
permissions:
security-events: write
contents: read
jobs:
audit:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Run Workspace Audit
id: audit
uses: adam-scott-thomas/ghostaudit@v1
with:
profiles: 'security,soc2'
fail-on: 'CRITICAL'
upload-sarif: 'true'
- name: Print summary
run: |
echo "Findings: ${{ steps.audit.outputs.findings-count }}"
echo "Critical: ${{ steps.audit.outputs.critical-count }}"
echo "High: ${{ steps.audit.outputs.high-count }}"
Inputs
| Input | Default | Description |
|---|---|---|
profiles |
security |
Comma-separated audit profiles (security, feature, soc2, quality) |
project |
(all) | Specific project to audit |
format |
sarif |
Output format (sarif, json, csv, markdown) |
fail-on |
never |
Fail if findings at this severity or above (CRITICAL, HIGH, MEDIUM, LOW, never) |
upload-sarif |
true |
Upload SARIF to GitHub Code Scanning |
python-version |
3.12 |
Python version to use |
Outputs
| Output | Description |
|---|---|
findings-count |
Total number of findings |
critical-count |
Number of CRITICAL findings |
high-count |
Number of HIGH findings |
sarif-file |
Path to SARIF output file |
report-file |
Path to report output file |
SARIF integration
When upload-sarif is true (the default), findings are uploaded to GitHub Code Scanning via the github/codeql-action/upload-sarif action. This requires the security-events: write permission. Findings appear in the repository's Security tab and as annotations on pull requests.
Requirements
- Python 3.10+
- Git (for owner detection and git status checks)
- No pip dependencies for the core — stdlib only
cryptography>=42.0only if you enable encrypted evidence capsules (pip install ghostaudit[capsule])
License
GhostAudit is licensed under the PolyForm Shield License 1.0.0. This is a source-available commercial-restrictive license. You may use, modify, and redistribute GhostAudit for any purpose, including internal enterprise use, except to build a product or service that competes with GhostAudit or with a product GhostLogic LLC provides using GhostAudit. See LICENSE for the full terms.
Copyright GhostLogic LLC.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file ghostaudit-1.2.0.tar.gz.
File metadata
- Download URL: ghostaudit-1.2.0.tar.gz
- Upload date:
- Size: 115.1 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
fe13034131e1721afdc8da481e441ede88f6f54d72301eb33eae21b364eb99c6
|
|
| MD5 |
bd7e153832a5e40470c1f3c6f5349cae
|
|
| BLAKE2b-256 |
5cbc886e5a3e9375bc0b975381dc2c9fe97a6bee892de8c204437a5f8c928f34
|
File details
Details for the file ghostaudit-1.2.0-py3-none-any.whl.
File metadata
- Download URL: ghostaudit-1.2.0-py3-none-any.whl
- Upload date:
- Size: 131.2 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.2.0 CPython/3.12.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
a4a901eef651f3bfedccf5cdd948d1b402ef42689c097bf1759c294f336d0528
|
|
| MD5 |
72199908fd282d54e616cb4166ff2f31
|
|
| BLAKE2b-256 |
35e7b85268c0681e4c2b226bb07a5f0540500b89f185618f3bfbbab35e5b9cd2
|