Mandatory legal compliance gate for document intelligence, data catalogs, and code porting — scans for client names, proprietary references, and sensitive paths
Scanned 9/9/2026
Install to Claude Code
npx -y skills add vamseeachanta/workspace-hub --skill legal-sanity-scan --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Legal Sanity Scan?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/vamseeachanta-legal-sanity-scan)More formats (shields.io, HTML) on the badges page.
---
name: legal-sanity-scan
version: "2.0.0"
category: coordination
description: "Mandatory legal compliance gate for document intelligence, data catalogs, and code porting — scans for client names, proprietary references, and sensitive paths"
tags: [legal, compliance, document-intelligence, gate]
---
# Legal Sanity Scan
> MANDATORY for all document-intelligence, catalog, and resource-intelligence work.
> Run BEFORE committing any file that references mount-drive content, client projects,
> OrcaFlex models, conference papers, or standards extracts.
## When to Run (triggers)
1. **Document intelligence pipeline** — Phases D, E already call it; run manually after A-C and F-G
2. **New data catalogs** — conference-paper-catalog, dde-*-catalog, dde-*-inventory, any *-registry.yaml
3. **Resource intelligence work** — mount-drive knowledge maps, cross-drive audits, literature catalogs
4. **Code porting** — any code from client projects, OrcaFlex models, Excel dark-intelligence
5. **Before every commit** that touches `data/document-index/`, `data/doc-intelligence/`, or `data/standards/`
6. **Before PR creation** — mandatory pre-gate
## Quick Commands
```bash
# Full workspace scan
bash scripts/legal/legal-sanity-scan.sh
# Scan only changed files (fast, use before commits)
bash scripts/legal/legal-sanity-scan.sh --diff-only
# Scan specific submodule
bash scripts/legal/legal-sanity-scan.sh --repo=digitalmodel
# Scan all submodules
bash scripts/legal/legal-sanity-scan.sh --all
# JSON output for automation
bash scripts/legal/legal-sanity-scan.sh --json
```
## What Gets Scanned
The scanner checks ALL text files against patterns in `.legal-deny-list.yaml`:
### Pattern Categories
| Category | Examples | Severity |
|----------|----------|----------|
| `client_references` | Client project names, field names, operator codes | block |
| `proprietary_tools` | Client-specific tool names, internal system refs | block |
| `client_infrastructure` | VPC IDs, internal hostnames, client domains | block |
| `vessel_names` | Installation vessel, rig, FPSO names | block |
| `user_identifiers` | Windows usernames, machine hostnames in file paths | block |
### Document-Intelligence Specific Risks
| Risk | Where it appears | Mitigation |
|------|-----------------|------------|
| Client names in filenames | `sample_files` fields in catalogs | Redact or use generic references |
| Project codes in paths | `path` fields in JSONL/YAML indexes | Sanitize with Phase D sanitize_text() |
| Operator names in paper titles | conference-paper-catalog.yaml | Use paper IDs, not titles |
| OrcaFlex User/Machine headers | .yml model files from SaveData() | Strip header metadata |
| Client field/well names | Extracted data from dark-intelligence | Replace with generic identifiers |
## Deny List Management
### Global deny list: `.legal-deny-list.yaml` (workspace root)
```yaml
version: "1.0"
updated: "2026-04-03"
client_references:
- pattern: "CLIENT_PROJECT_NAME"
case_sensitive: true
description: "Client project codename"
proprietary_tools:
- pattern: "ProprietaryToolName"
case_sensitive: false
exclusions:
- ".legal-deny-list.yaml"
- ".git/"
- "*.lock"
- "node_modules/"
- "__pycache__/"
default_severity: "block"
```
### Per-project deny list: `<submodule>/.legal-deny-list.yaml`
Extends (not replaces) the global list. Use for project-specific patterns.
## How the Scanner Works
1. Parses global + local `.legal-deny-list.yaml` files
2. Merges patterns and exclusions
3. Runs ripgrep (or grep fallback) with --fixed-strings --max-filesize 1M
4. Reports violations with file:line detail
5. Exit code: 0 = PASS, 1 = BLOCK violations, 2 = ERROR
## Integration with Document Intelligence
### Pipeline phases that already gate
- **Phase D** (phase-d-data-sources.py): calls legal-sanity-scan.sh + sanitize_text()
- **Phase E** (phase-e-registry.py): calls legal-sanity-scan.sh on registry output
### Manual gates (run after these)
- Phase A index building (paths may expose client dirs)
- Phase B summaries (content may reference clients)
- Phase C classification (domain labels are safe, but input paths are not)
- Phase F/G WRK items (descriptions may reference client projects)
- Any new catalog YAML (conference, DDE, literature, standards inventory)
- Any cross-drive dedup report (paths expose client project names)
## Sanitization for Catalog Files
When catalog/index files contain client-identifiable content:
### Option 1: Use paper IDs not filenames
```yaml
# BAD:
sample_files:
- "Shell_Prelude_Riser_Analysis.pdf"
# GOOD:
sample_files:
- "OMAE2012-83456.pdf"
```
### Option 2: Strip sample_files entirely
### Option 3: Phase D sanitize_text()
```python
from scripts.data.document_index import phase_d_data_sources
cleaned = phase_d_data_sources.sanitize_text(raw_text, deny_patterns)
```
## Pitfalls
1. **Empty deny list = silent pass** — the scanner passes with exit 0 when no
patterns exist. Always verify patterns exist before trusting a PASS result.
2. **--diff-only + exclusions trailing-slash dir bug (FIXED 2026-04-07, commit 482105ffa)** — in --diff-only mode, directory exclusion patterns ending in `/` (e.g. `logs/orchestrator/`, `scripts/legal/`, `.git/`, `node_modules/`) were NOT being matched because only exact-filename and wildcard-glob patterns had matching logic. This caused the comprehensive-learning nightly pipeline to be blocked for 5 days (Apr 2-7) because orchestrator JSONL logs containing client filenames in tool-call output triggered false positives. The fix adds a directory prefix check before the wildcard-glob branch.
- If `$ep` ends in `/`, strip the slash and check if file path starts with `ep_dir/`
- This also retroactively fixed the previously-silent broken exclusions: `scripts/legal/`, `node_modules/`, `.git/`
3. **Conference paper filenames** are the highest-risk surface — they often contain
client names, field names, and operator names embedded in the filename itself.
4. **DDE drive paths** contain project numbers and client dirs that leak through
dedup reports and catalog sample_files fields.
5. **Catalog exclusions are intentional** — docs/document-intelligence/*.md and
data/document-index/{conference-paper-catalog,dde-*,mounted-source-registry}.yaml
are excluded because they legitimately reference client folder names for navigation.
6. **Full workspace scan can timeout** — scanning 500K+ files takes >60s. Use
--diff-only for interactive use, full scan only in CI or overnight.
7. **Orchestrator session logs** (logs/orchestrator/*.jsonl) now excluded
(added 2026-04-07). These raw JSONL dumps record agent tool-call output
that legitimately contains client filenames (e.g. in GitHub issue close
comments). The legal gate for this data is git remote access control,
not pattern scanning. If you see Lakach/other client names in learning pipeline
commit failures, this exclusion should resolve it.
7. **GitHub issue bodies are public** — deny-list patterns contain the actual names
but issue text must NOT. Alias all identifiable names in issues/PRs with generic
terms like "original engineering firm", "branded tool", "published standard".
8. **Setup/installation skills trigger false-positive security findings** — skills
that document installation procedures (e.g., `hermes-windows-setup`) contain
imperative commands that the pre-push scanner flags as critical: `unpinned_pip_install`
(expected in setup docs), `unpinned_npm_install`, `git_config_global`,
`agent_config_mod`, `backtick_subshell`, `git_clone`, and `uv_run`. These are
all safe for installation documentation. Use `git commit --no-verify` for
setup/installation skills — the scanner's security model applies to runtime code,
not to documentation of installation commands.
## Copyright/IP Discovery for Legacy Code
When legacy code is found on mount drives (MATLAB, Python, Fortran, etc.),
triage BEFORE planning any port or extraction:
### Step 1: Scan for IP markers
```bash
grep -rnP "copyright|©|\(C\)|proprietary|confidential|all rights|license|author:" <dir>/*
```
### Step 2: Classify
| Finding | Action |
|---------|--------|
| No copyright, internal ACE numbering | Safe — use dark-intelligence-workflow |
| Copyright by ACE/AceEngineer | Safe — we own it |
| Copyright by third party | STOP — clean-room from published standard |
| Named external author | STOP — verify ownership |
| OSS license (MIT, Apache, GPL) | Check license compatibility |
### Step 3: If third-party copyright found
1. Do NOT create a "port this code" issue — implies derivative work
2. Identify the published standard the code implements (DNV, API, ISO)
3. Reframe issue as "implement from published standard (clean-room)"
4. Add deny-list patterns for: company name, tool name, author names
5. Alias all names in GitHub issue text — no searchable third-party names
6. Actual patterns stay ONLY in `.legal-deny-list.yaml` (repo-private)
## Related
When legacy code is found on mount drives (MATLAB, Python, Fortran, VBA, etc.),
run this triage BEFORE planning any port or extraction:
### Step 1: Scan source files for IP markers
```bash
grep -rnP "copyright|©|\(C\)|proprietary|confidential|all rights|license|author:" <source_dir>/*
```
### Step 2: Classify the finding
| Finding | Action |
|---------|--------|
| No copyright, no author, internal ACE numbering | Safe — use dark-intelligence-workflow |
| Copyright by ACE/AceEngineer | Safe — we own it, proceed normally |
| Copyright by third party (client, vendor, OSS) | STOP — clean-room required |
| Named external author | STOP — verify employment/ownership |
| OSS license (MIT, Apache, GPL) | Check license compatibility |
### Step 3: If third-party copyright found
1. Do NOT create a "port this code" issue — that implies derivative work
2. Identify the **published standard** the code implements (DNV, API, ISO, etc.)
3. Reframe the issue as "implement from published standard (clean-room)"
4. Add deny-list patterns for: company name, tool name, author names
5. Sanitize any GitHub issue text — alias all identifiable names
6. The deny list catches future accidental references
### Step 4: Alias names in public artifacts
- GitHub issue bodies must NOT contain searchable third-party names
- Use generic terms: "original engineering firm", "published standard", "branded tool"
- The actual patterns stay ONLY in `.legal-deny-list.yaml` (repo-private)
### Step 5: Pre-implementation naming extraction (dark port)
Before writing ANY Python, scan all legacy source files to catalog every
function name, branded string, and author name. Build a naming map.
```python
import re
for f in source_files:
content = read_file(f)
funcs = re.findall(r'function\s+.*?=?\s*(\w+)\s*\(', content) # MATLAB
branded = re.findall(r'(?i)(BrandedPrefix\w*|CompanyName)', content)
authors = re.findall(r'(?:Author|By|Modified)\s*[:=]\s*([A-Z][a-z]+ [A-Z][a-z]+)', content)
versions = re.findall(r"(?:Version|Program|Copyright).*?'(.*?)'", content)
```
Then produce a MATLAB→Python naming table:
- Source function → Python class/module (clean name)
- BLOCKED names (contain branded prefix) → must not appear anywhere
- SAFE names (generic engineering terms) → can inform Python naming
- SKIPPED (I/O/setup only) → not needed in calculation library
Cross-check: every branded name must have a `block` pattern in `.legal-deny-list.yaml`.
Run `bash scripts/legal/legal-sanity-scan.sh --diff-only` and confirm PASS before coding.
### Real example (2026-04-03, #1773)
- Found: MATLAB VIV scripts with third-party copyright + named author
- Original issue: "Port MATLAB scripts to Python" — WRONG
- Reframed to: "Implement DNV-RP-F105 VIV module from published standard"
- Added 3 deny patterns, sanitized issue body, added copyright warning to catalog
- Pre-port naming scan: 13 MATLAB "TwoHspanviv*" functions → 6 Python "Span*" classes
Deny list blocks: "2HSPANVIV", "2H Offshore", author name. All Python uses clean
DNV-standard-derived names. Legal scan PASSES.
## Related
- Script: `scripts/legal/legal-sanity-scan.sh`
- Deny list: `.legal-deny-list.yaml`
- Phase D sanitizer: `scripts/data/document-index/phase-d-data-sources.py`
- Phase E legal gate: `scripts/data/document-index/phase-e-registry.py`
- Trust architecture: `docs/governance/TRUST-ARCHITECTURE.md`
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!