# Git Audit Report — IT Pro Partner Gitea Organization **Date:** 2026-08-08 **Auditor:** Hermes Agent (automated) **Scope:** git.itpropartner.com / ippadmin (all 42 remote repos + 59 local clones in `/root/projects/`) --- ## Summary Verdict **The Gitea organization suffers from repo sprawl, weak hygiene, and live secrets in history.** Of 42 remote repos, 32 are single-commit documentation stubs. Only 3–4 repos show active development. The `itpp-infrastructure/docs/` folder is a flat grab-bag and needs structured nesting. 23 local-only repos lack any off-server backup. Credentials are embedded in plaintext across at least 2 repos (`scripts`, `hermes-recovery`). Consolidation, cleanup, and a hygiene push are overdue. --- ## Quick Answers to User's Two Questions ### 1. Should `itpp-infrastructure/docs/` have more nested folders? **Yes, absolutely.** The current structure is: ``` docs/ backup-restore/ ← already nested (good) legal/ ← already nested (good) ops-portal/ ← already nested (good) app2-caddyfile-audit-2026-07-21.md ← flat client-katie-watts-design.md ← flat cost-control-rollout-2026-07-24.md ← flat git-audit-2026-08-07.md ← flat infrastructure-gap-assessment-2026-08-04.md ← flat key-inventory.md ← flat mattermost-replacement-analysis.md ← flat model-chain.md ← flat project-log.md ← flat projects-master-readme.md ← flat super-search-cf-bypass.md ← flat super-search-enhancement-plan.md ← flat uptime-kuma-monitoring-plan.md ← flat ``` **14 flat files is too many.** Recommended restructuring: ``` docs/ audit/ ← git-audit reports, gap assessments backup-restore/ ← (existing, keep) clients/ ← client-katie-watts-design.md infrastructure/ ← model-chain.md, cost-control-rollout, caddyfile-audit, key-inventory legal/ ← (existing, keep) monitoring/ ← uptime-kuma-monitoring-plan.md ops-portal/ ← (existing, keep) projects/ ← project-log.md, projects-master-readme.md super-search/ ← cf-bypass, enhancement-plan mattermost-replacement-analysis.md ← leave at top level (one-off) ``` This gives every file a clear home without over-nesting. ### 2. Are there too many top-level repos? Should they be consolidated? **Yes — 42 repos is far too many for the actual workload.** Here's the breakdown: | Category | Count | Action | |----------|-------|--------| | Active development repos | 3–4 | Keep (`itpp-infrastructure`, `hermes-skills`, `scripts`, `homelab`) | | Single-commit documentation stubs | 32 | Consolidate into fewer repos | | Empty repos | 1 | Delete (`auth` — no commits, no content) | | MCP stub repos | 5 | Merge into one `mcp-catalog` repo | | Duplicate/stale repos | 2 | Resolve (`itpp-infra` vs `itpp-infrastructure`, `cartmylist-repo` vs `cartmylist`) | | Local-only (unbacked) | 23 | Push to Gitea or archive | **Recommended consolidation:** 1. **Merge 4 MCP stubs** (`mcp-browser`, `mcp-email`, `mcp-filesystem`, `mcp-git`) into `mcp-servers/` as subdirectories 2. **Merge related business ideas** into a `project-ideas` monorepo: - `apex-track`, `boxpilot`, `digital-signage`, `fleettracker360`, `gift-a-roast`, `hudu`, `launchcheck`, `mooresunnydaze`, `nvr-shield`, `osint-tool`, `shark-game`, `startup-studio`, `track-a-flock`, `personal-assistant` 3. **Merge related operational repos**: `disaster-recovery` + `backup-restore` → `disaster-recovery/` with `backup-restore/` subdir 4. **Merge website/docs stubs**: `itpropartner-website`, `content-creation-pipeline`, `ops-portal` → subdirectories in `itpp-infrastructure` 5. **Resolve** `itpp-infra` (stale, SSH-only, 1 commit) → archive; use `itpp-infrastructure` as primary 6. **Delete** `auth` (empty repo with `auth.db` — never committed) 7. **Keep as-is**: `itpp-infrastructure`, `hermes-skills`, `hermes-recovery`, `scripts`, `homelab`, `dre`, `verdicttank`, `voipsimplicity`, `voipsimplicity-manual`, `forefront-wireless-portal`, `super-search-business`, `model-fallback`, `unifi`, `unms`, `pipeline`, `super-search` **Target:** ~15–20 repos instead of 42. --- ## Detailed Findings ### Step 1 — Full Inventory | Metric | Count | |--------|-------| | Remote repos on Gitea | 42 | | Local clones in `/root/projects/` | 59 | | On Gitea AND cloned locally | 36 | | On Gitea but NOT cloned locally | 6 | | Cloned locally but NOT on Gitea | 23 | | Public repos | 30 | | Private repos | 12 | | Repos using `master` as default branch | 30 | | Repos using `main` as default branch | 9 | | Other (HEAD/detached) | 20 | **Repos on Gitea but not cloned locally:** `cartmylist`, `mcp-browser`, `mcp-email`, `mcp-filesystem`, `mcp-git`, `super-search` **Local-only repos (no remote — no off-server backup):** `assistant`, `auth`, `capabilities`, `hear-read`, `intelsight`, `intelsight-landing`, `internal`, `mockup`, `my-itpropartner-portal`, `ops`, `ops-v2-portal`, `osint`, `proposals`, `pry`, `research-search-mcp`, `schedule`, `shonuff`, `shonuff-caller`, `static`, `status`, `voice-previews`, `itpp-infra`, `cartmylist-repo` ### Step 2 — Per-Repo Deep Scan #### Hygiene Check: `.gitignore` and `README.md` | Status | Count | |--------|-------| | Has `.gitignore` | 8 of 59 (13.6%) | | Has `README.md` | 56 of 59 (94.9%) | **Repos missing `.gitignore`:** 51 repos. This is the single biggest hygiene gap. **Repos missing `README.md`:** `cartmylist-repo`, `voipsimplicity-manual`, `auth` #### Repos with Dirty Working Trees | Repo | Dirty Files | Severity | |------|-------------|----------| | `hermes-skills` | 33 | **HIGH** — cache artifacts not committed | | `hermes-recovery` | 26 | **HIGH** — uncommitted recovery scripts | | `voipsimplicity-manual` | 11 | **MEDIUM** | | `research-search-mcp` | 10 | **MEDIUM** | | `auth` | 9 | **MEDIUM** | | `digital-signage` | 6 | **LOW** | | `itpp-infra` | 5 | **LOW** | | `pipeline` | 5 | **LOW** | | `disaster-recovery` | 4 | **LOW** | | `mooresunnydaze` | 4 | **LOW** | | `verdicttank` | 4 | **LOW** | | `itpp-infrastructure` | 3 | **LOW** | **13 repos** have uncommitted changes. `hermes-skills` (33 files) and `hermes-recovery` (26 files) are the worst offenders. ### Step 3 — Secrets Scan **CRITICAL findings in 2 repos:** #### `scripts` — 10 potential secrets Real, hardcoded credentials found in Windows provisioning scripts: ``` +Password="[REDACTED]" +Password="[REDACTED]" +Password="[REDACTED]" +Username="ippadmin" +Username="liberty-admin" ``` These are active Windows admin credentials embedded in PowerShell unattend scripts. **This is a data breach risk.** If these repos ever go public or are cloned outside ITPP infrastructure, client credentials are exposed. #### `hermes-recovery` — 8 potential secrets Includes the Gitea API token used for this audit: ``` +TOKEN="[REDACTED]" +TELEGRAM_BOT_TOKEN="[REDACTED]" +password="***" +token = "[REDACTED]" ``` The Gitea token itself is committed. This means `hermes-recovery` as a public repo exposes admin credentials. #### `hermes-skills` — 15 potential hits Most are false positives (example values, `process.env.` references, placeholder text). One real hit: a Comfy CLI API key in a SKILL.md. ### Step 4 — Structural Checks #### Remote URL Audit | Remote Type | Count | Action | |-------------|-------|--------| | HTTPS to Gitea | 36 | OK | | GitHub (upstream) | 1 | OK (`msp-claude-skills`) | | SSH to Gitea | 2 | **FIX** — `itpp-infra`, `cartmylist-repo` | | No remote | 23 | **FIX** — local-only, no backup | `itpp-infra` uses `git@git.itpropartner.com:ippadmin/itpp-infra.git` (SSH) — this repo has no corresponding HTTPS clone and appears to be a stale/abandoned repo (1 commit, 5 dirty files). `cartmylist-repo` (local) vs `cartmylist` (Gitea) is a naming mismatch. The local clone has an SSH remote to what is likely a different repo. #### Branch Naming - **30 repos use `master`** — industry standard is now `main` - **9 repos use `main`** - **20 repos have detached HEAD or no commits** **Branch mismatch:** `itpp-infrastructure` has `main` locally but `master` on Gitea. This means the remote may have both branches. #### Large Files | Repo | File | Size | |------|------|------| | `hermes-skills` | `.hub/index-cache/hermes-index.json` | 38.9 MB | | `hermes-skills` | `.curator_backups/2026-07-12T15-48-44Z/skills.tar.gz` | 2.7 MB | Both are cache artifacts that should be in `.gitignore`, not tracked. #### Public vs Private **30 of 42 repos (71%) are public.** This is a concern because: - `scripts` contains client admin passwords — **public** - `hermes-recovery` contains Gitea admin token — **public** - Many repos with sensitive infrastructure details are public ### Step 5 — Commit Quality #### Commit Message Quality | Pattern | Count | Assessment | |---------|-------|------------| | `Initial commit — YYYY-MM-DD` | 16 | Poor — conveys nothing | | `Update YYYY-MM-DD — root` | 5 | Meaningless | | `Initial: ` | 8 | Barely adequate | | Descriptive conventional commits | 4 | Good (`homelab`, `verdicttank`, `forefront-wireless-portal`) | **32 repos have only 1 commit** — these are documentation stubs, not developed projects. #### Active vs Abandoned | Status | Criteria | Repos | |--------|----------|-------| | **Active** | 3+ commits, recent activity | `itpp-infrastructure` (52), `scripts` (11), `homelab` (6), `forefront-wireless-portal` (5), `dre` (4), `verdicttank` (4), `personal-assistant` (3), `super-search-business` (3), `voipsimplicity` (3) | | **Stub** | 1–2 commits, last push July 2025 | 32 repos | | **Abandoned** | No commits or stale >3 months | `itpp-infra`, `auth`, `cartmylist-repo` | ### Step 6 — Local-Only Repos 23 repos in `/root/projects/` have no remote. Breakdown: | Category | Repos | Action | |----------|-------|--------| | Uncommitted stubs (0 commits) | 17 | Push to Gitea or archive | | Has commits, no remote | 1 (`shonuff-caller`) | Push to Gitea | | Stale noise | 5 | Archive and delete (`auth`, `itpp-infra`, `cartmylist-repo`, etc.) | The 17 repos with 0 commits and only detached HEAD are effectively just directories with a `.git` folder — not real repos. They should be either pushed as proper repos or archived. --- ## Prioritized Action Plan ### 🔴 Immediate (This Week) | # | Action | Severity | |---|--------|----------| | 1 | **Rotate all credentials exposed in `scripts` repo** — Windows passwords, Gitea token, Telegram bot token. Then purge from Git history with `git filter-branch` or `bfg-repo-cleaner` | **CRITICAL** | | 2 | **Rotate Gitea API token** in `hermes-recovery` — it's publicly visible. Generate new token, update all consumers, purge old from history | **CRITICAL** | | 3 | **Make `scripts` and `hermes-recovery` PRIVATE** — they contain live credentials visible to anyone | **CRITICAL** | | 4 | **Add `.gitignore` to all 51 repos missing one** — start with the active repos first | **HIGH** | | 5 | **Commit or stash all dirty working trees** — 13 repos have uncommitted work at risk of loss | **HIGH** | ### 🟡 Short-Term (This Month) | # | Action | Severity | |---|--------|----------| | 6 | **Reorganize `itpp-infrastructure/docs/`** into nested folders (audit/, clients/, infrastructure/, monitoring/, projects/, super-search/) | **MEDIUM** | | 7 | **Consolidate 4 MCP repos into `mcp-servers/`** as subdirectories — delete empty stubs after merge | **MEDIUM** | | 8 | **Merge 14 single-commit business idea repos** into a `project-ideas` monorepo | **MEDIUM** | | 9 | **Delete `auth`** (empty repo, 0 commits) | **MEDIUM** | | 10 | **Resolve `itpp-infra` vs `itpp-infrastructure`** — archive `itpp-infra`, standardize on `itpp-infrastructure` | **MEDIUM** | | 11 | **Add `.gitignore` entries to `hermes-skills`** for `.hub/`, `.curator_backups/` | **MEDIUM** | | 12 | **Rename `master` → `main` on repos where it matters** (at minimum `itpp-infrastructure` to fix branch mismatch) | **LOW** | ### 🔵 Pre-Public / Pre-Open-Source | # | Action | Severity | |---|--------|----------| | 13 | **Audit all 30 public repos** — ensure no private infrastructure details, client names, IPs, or credentials are exposed | **HIGH** | | 14 | **Decide public/private policy** — which repos genuinely need to be public? Currently 71% are public. | **MEDIUM** | | 15 | **Push 23 local-only repos to Gitea** or archive them. No code living only on a single server. | **HIGH** | | 16 | **Clean commit history** — rebase repos with "Update YYYY-MM-DD — root" messages into meaningful commits | **LOW** | --- ## Template: Standard `.gitignore` For any new or cleaned repo, use: ```gitignore # OS .DS_Store Thumbs.db # IDE .vscode/ .idea/ *.swp *.swo # Python __pycache__/ *.py[cod] *.egg-info/ .venv/ venv/ # Node node_modules/ # Secrets — NEVER commit these .env .env.* *.pem *.key credentials.json *.token # Cache / generated .hub/ .curator_backups/ *.tar.gz *.zip # Data *.db *.sqlite *.sqlite3 ``` --- ## Appendix: Full Repo Inventory ### Active Repos (keep as standalone) | Repo | Commits | Last Commit | Branch | `.gitignore` | Assessment | |------|---------|-------------|--------|-------------|------------| | `itpp-infrastructure` | 52 | 2026-08-07 | main/master mismatch | YES | **Primary hub** — healthy | | `hermes-skills` | 1 | 2026-07-15 | master | NO | Active mirror, 13.6MB | | `hermes-recovery` | 1 | 2026-07-15 | master | YES | Critical backup kit | | `scripts` | 11 | 2026-07-25 | master | NO | Active, **has secrets** | | `homelab` | 6 | 2026-07-24 | main | NO | Active, good commits | | `dre` | 4 | 2026-07-25 | master | NO | Active development | | `verdicttank` | 4 | 2026-08-07 | main | NO | Active, good commits | | `forefront-wireless-portal` | 5 | 2026-07-25 | master | NO | Active, good commits | | `super-search-business` | 3 | 2026-07-25 | main | NO | Active | | `voipsimplicity` | 3 | 2026-07-24 | master | NO | Active client work | | `voipsimplicity-manual` | 1 | 2026-08-05 | master | NO | Active client work | ### Stub Repos (consolidate) All 32 repos below are single-commit documentation stubs with no ongoing development. Consolidate into `project-ideas/` monorepo or relevant parent repo: `apex-track`, `backup-restore`, `boxpilot`, `content-creation-pipeline`, `digital-signage`, `disaster-recovery`, `fleettracker360`, `gift-a-roast`, `hudu`, `itpropartner-website`, `launchcheck`, `mcp-browser`, `mcp-email`, `mcp-filesystem`, `mcp-git`, `mcp-servers`, `model-fallback`, `mooresunnydaze`, `nvr-shield`, `ops-portal`, `osint-tool`, `personal-assistant`, `pipeline`, `shark-game`, `startup-studio`, `super-search`, `track-a-flock`, `unifi`, `unms`, `cartmylist` ### To Delete or Archive | Repo | Reason | |------|--------| | `auth` | Empty (0 commits, 0 content) | | `itpp-infra` | Stale duplicate of `itpp-infrastructure`, SSH-only remote, 1 commit | | `cartmylist-repo` | Local clone with SSH remote, mismatched name (real one is `cartmylist` on Gitea) | ### Local-Only (push or archive) `assistant`, `auth`, `capabilities`, `hear-read`, `intelsight`, `intelsight-landing`, `internal`, `mockup`, `my-itpropartner-portal`, `ops`, `ops-v2-portal`, `osint`, `proposals`, `pry`, `research-search-mcp`, `schedule`, `shonuff`, `shonuff-caller`, `static`, `status`, `voice-previews` --- *Report generated by Hermes Agent git-audit workflow. Next audit recommended: 2026-11-08.*