Metadata-Version: 2.4
Name: ghostaudit
Version: 1.1.0
Summary: Tamper-evident workspace auditing — security, SOC 2, HIPAA, AI provenance. Merkle-sealed findings with encrypted evidence capsules.
Author: GhostLogic LLC
License: Apache-2.0
Project-URL: Homepage, https://ghostlogic.com
Project-URL: Repository, https://github.com/adam-scott-thomas/workspace-tools
Project-URL: Issues, https://github.com/adam-scott-thomas/workspace-tools/issues
Project-URL: Verification, https://ghostlogic.com/verify
Keywords: audit,security,soc2,hipaa,compliance,provenance,merkle,forensic,sarif
Classifier: Development Status :: 4 - Beta
Classifier: Environment :: Console
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: System Administrators
Classifier: License :: OSI Approved :: Apache Software License
Classifier: Operating System :: OS Independent
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Security
Classifier: Topic :: Software Development :: Quality Assurance
Classifier: Topic :: System :: Monitoring
Requires-Python: >=3.10
Description-Content-Type: text/markdown
License-File: LICENSE
Provides-Extra: capsule
Requires-Dist: cryptography>=42.0; extra == "capsule"
Dynamic: license-file

# Workspace Audit Toolkit

Automated filesystem auditing for multi-project workspaces. Hashes files, tracks changes, generates per-project AUDIT.md files, and versions everything.

## Quick Start

```bash
# Run a full audit (inventory + index + diff)
python tools/audit/run_audit.py --mode full --workspace /path/to/workspace

# Run the daily pipeline (hash → compare → audit or sleep)
python tools/audit/run_audit.py --mode daily --workspace /path/to/workspace

# Just update project audits
python tools/audit/run_audit.py --mode update_audits --workspace /path/to/workspace

# Preview audit changes without writing
python tools/audit/update_audits.py --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` | SHA256 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):

```json
{
  "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:

1. Each sub-component gets its own `{component}/AUDIT.md`
2. The parent gets a summary `AUDIT.md` with a component table
3. Add directories to `force_audit_subdirs` in 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)

```bat
@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)

```bash
# 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 workspace-audit as a GitHub Action to get findings as GitHub Code Scanning alerts in your pull requests and repository Security tab.

### Basic usage

```yaml
- uses: adam-scott-thomas/workspace-audit@v1
  with:
    profiles: 'security'
    fail-on: 'CRITICAL'
    upload-sarif: 'true'
```

### Full workflow example

```yaml
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/workspace-audit@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 — stdlib only
