Files
itpp-infrastructure/audit/phase-one/findings/docs-w.md
T
root f5175f1ce0 Sync docs, audit artifacts, project notes, and VerdictTank proposal docs
- audit/phase-one + phase-two: security audit briefs, findings, credential-rotation plan, Docker-USER hardening scripts, rollback refs
- disaster-recovery/restore-test-log.md + backup-dr-audit-2026-08-10.md
- clients/ (modelortho SEO audit, ai-biz-dev competitive landscape), notes/ (tiktok strategy)
- projects/: front-desk-voice-agent, seo-visibility-checker product plan, hotnow-savannah HTML, resend-transactional-email, backup-dashboard-enhancements, code-review-graph, seo-ci-architecture
- proposals/verdicttank/: architecture v4.0, methodology, judge-pool review, consolidation reasoning, cross-check review
- docs/super-search/firecrawl-provider-strategy.md
- updates: CHANGELOG, model-chain, projects-master-readme, intelsight.io
- .gitignore: exclude nested standalone repos (seo-tool, venturebuilt)
2026-08-26 02:27:28 -04:00

19 KiB

Docs-W Findings: Documentation Audit (Phase One, Read-Only)

Auditor: Docs-W (documentation auditor) Scope: docs.itpropartner.com (live MkDocs Material site on app3) and its stale duplicate; cross-referenced against neteng-a.md, neteng-b.md, sec-b.md, sys-a.md, sys-b.md, sys-c.md. Method: Read-only SSH to app3 (152.53.241.111), filesystem inspection, HTML content extraction of every section/page and CHANGELOG. No live docs, nginx, or DNS were modified. Date: 2026-08-13


1. Site Inventory

Platform: MkDocs Material, built and copied as static HTML into two htdocs trees on app3. No .git in either served tree, so the live docs root itself carries no version history or build provenance.

Served copy: /home/docs/htdocs/docs.itpropartner.com (owned by user docs, referenced by /etc/nginx/sites-enabled/docs.itpropartner.com.conf, most recent build timestamp ~2026-08-12 19:31 local). Unserved duplicate: /home/ippadmin/htdocs/docs.itpropartner.com (root-owned, not referenced by any nginx vhost).

Access control: Since 2026-08-10, the entire site is gated by docs-auth-validator.service (JWT + email allowlist against auth2/Stack Auth). Before that date the site was open access. See section 3 (say-do gaps) for the implication.

1.1 Top-level sections (12), status, and last-update evidence (from each section's CHANGELOG)

Section Claims to document Last CHANGELOG entry Age vs audit date (2026-08-13) Status
ITPP Infrastructure Server inventory, DNS, architecture, key inventory, model routing, cost controls, ops portal, backup-restore, legal, project log 2026-08-10 (Docs Auth Gate) 3 days Current
ITPP Standards Documentation templates, CI (docs-check, docs-publish) 2026-08-09 (Initial) 4 days Current
TransitPin White-label transportation portal, dispatch, driver PWA 2026-08-09 (migrate to Git); content dated 2026-07-29 4 days (changelog) / 15 days (content) Current (changelog)
VerdictTank (+ Architecture) Product review/validation platform, pricing, pipeline review 2026-08-10 (v3 proposal + architecture) 3 days Current
HomeLab Home lab infrastructure automation "2026-07" (state snapshot 2026-07-21) ~3+ weeks Stale
Scripts Operations/automation script catalog 2026-07-21 3 weeks Stale
FleetTracker360 GPS fleet tracking platform 2026-07-16 4 weeks Stale
LaunchCheck Startup validation product 2026-07-25 (Project Inception, single entry) 3 weeks, never updated since inception Stale
Shark Game Shark Attack Fantasy League 2026-07-10 5 weeks Stale
Apex Track Track event management 2026-07-10 ("Created project repository," single entry) 5 weeks, stub only Stale
BoxPilot Logistics operations platform 2026-07-10 ("Created project repository," single entry) 5 weeks, stub only Stale
OSINT Tool OSINT people search / skip tracing 2026-07-10 (Documentation migration) 5 weeks Stale

Section count: 12. Current: 4. Stale: 8.

1.2 Notable sub-pages

  • itpp-infrastructure/: Overview, Docs Auth Gate, Key Inventory, Model Chain, Cost Control Rollout (2026-07-24), Super Search CF Bypass (2026-07-21), app2 Caddyfile Audit (2026-07-21), Backup-Restore (+Architecture), Ops Portal (+Architecture), Legal (empty page, no content rendered), Project Log, Projects Master README.
  • verdicttank/: Overview, Architecture, plus markdown source files for v3.5/v3.6 architecture and a legal-framework document.
  • launchcheck/: Competitive Analysis, Business Proposal (in addition to the section root).

2. Say-Do Gap Audit (cross-referenced against neteng-a/b, sec-b, sys-a/b/c)

# Doc claim Live reality (per findings file) Severity
1 key-inventory states secrets were "Sanitized... plaintext secrets replaced with storage references" (2026-07-23) sys-a F-2: plaintext JWT_SECRET/DEEPSEEK_API_KEY/ADMIN_AI_KEY hardcoded in world-readable systemd units on Core (rally, seemytrip) and app1 (giftaroast). sys-b C2: /root/.hermes/.env on app1-bu (mode 644) holds ~20 plaintext secrets including root passwords for app1/app2/app3. sys-b C3: MySQL root password hardcoded in plaintext in two app3 scripts, one world-readable (775). Critical - the one doc whose entire purpose is to assure the org that secrets are handled safely is contradicted by the live estate in at least three independent locations.
2 ops-portal CHANGELOG (2026-07-20) publishes a line reading "Admin credentials: [old username]/[old password] -> ippadmin (password moved to Vaultwarden)" The docs site was open access (no auth gate) until 2026-08-10 per the site's own docs-auth-gate doc. This means a real historical admin credential sat in plaintext on an unauthenticated public web page for roughly three weeks. Critical - a credential exposure inside the documentation itself, not just the infrastructure.
3 docs-auth-gate describes a JWT+allowlist access-control layer protecting the whole site, implying documentation (including key-inventory and the credential above) is now access-controlled None of the six live-verified findings files enumerate or test docs-auth-validator.service/port 8099 on app3. sec-b's MFA/hardening coverage table (11 admin surfaces reviewed) does not include it. Its actual enforcement is undocumented outside its own self-description. High - an access control the org depends on for a page containing credential-adjacent content has never been independently verified by the security or network auditors.
4 projects-master-readme lists Apex Track and BoxPilot as "(PLANNED)" Both already have fully generated dedicated MkDocs sections (nav entries, CHANGELOG, "Created project repository and directory structure" stub content) on the same site. Medium - internal self-contradiction on project status, visible on two pages of the same docs tree, no external cross-reference needed.
5 itpp-infrastructure/legal is a live nav entry titled "Legal" Page renders with no content at all. Medium - a documented, linked page with nothing behind it; reads as either an abandoned stub or a missed publish step.
6 homelab documents host inventory, DNS chain, and Docker service catalog for the separate home-lab network as if it were part of the audited estate HomeLab (vm-host-01/02, QNAP, MikroTik home router) is outside the scope of neteng-a/b, sec-b, sys-a/b/c, which cover only Core/app1/app2/app3/app1-bu/wphost02. There is no live-verified findings coverage to check this section against at all. Medium - a documented area of the estate with zero Phase One audit visibility; a structural blind spot rather than a specific factual error.
7 model-chain (2026-07-24) documents the AI model fallback chain and the admin-ai virtual key's daily budget cap, implying this is a governed, protected control sys-a F-1: the LiteLLM Postgres database that stores this exact routing/budget/key configuration is never backed up (dump targets a nonexistent database name and fails silently every night). The governance the doc describes has zero disaster-recovery coverage, a fact the doc itself does not mention. High - doc describes a control without disclosing that its backing store is unprotected.
8 app2-caddyfile-audit-2026-07-21 documents a "final Caddyfile (validated)" for app2 routing UNMS, Gitea, UniFi, dns1, FleetTracker360 through Caddy neteng-a APP2-1 through APP2-5 show UniFi, UNMS, Gitea SSH, Technitium DNS, and several other app2 services are also reachable directly via Docker's UFW bypass, i.e. the "validated" Caddy-only routing picture in the doc is incomplete: the real exposure includes direct Docker-published ports the doc never mentions. High - the doc documents the intended path but is silent on (and therefore implicitly contradicts) the actual public exposure discovered live.
9 backup-restore doc describes a 30-day retention snapshot system and a documented restore API for 9 WordPress domains sys-c's live restore-test audit found zero restore tests have ever been run against this specific mechanism (only Gitea and Vaultwarden have been restore-tested estate-wide), and sys-c SYSC-10 notes this snapshot layer is local-disk-only with no offsite copy - a single point of failure the doc does not disclose. Medium - doc presents the system as complete/operational; live audit shows "backed up" without "restore-verified," which is exactly the gap Sys-C's engagement rule was written to catch.

Top 5 say-do gaps (for summary): #1, #2, #3, #7, #8 above - ranked by blast radius and the fact that each represents documentation actively asserting a safety property (secrets sanitized, admin credential rotated, access gated, budget governed, routing validated) that the independently-verified infrastructure findings show is false, incomplete, or unverifiable.


3. Split-Brain: Two Copies of docs.itpropartner.com

Finding: Two nearly-identical full copies of the docs site exist on app3:

  • /home/docs/htdocs/docs.itpropartner.com - owned by docs, referenced by the live nginx vhost, most recent build ~2026-08-12 19:31 local. This is the authoritative, served copy.
  • /home/ippadmin/htdocs/docs.itpropartner.com - owned by root, not referenced by any nginx config, most recent build ~2026-08-10 (roughly 29 hours older than the served copy).

Verification performed: file-list diff between the two trees returns zero differences (93 files each, identical filenames/paths), and index.html content is byte-identical. The only measurable difference is per-file modification time, consistently ~29 hours older on the ippadmin copy across sampled files. This confirms both are build outputs of the same MkDocs source, generated by the same pipeline at two different times, not two diverging content sources.

Root cause (most likely, not confirmed via any log evidence during this read-only audit): an early build/deploy of the docs site landed in the default ippadmin home path (the operator's own home directory, root-owned), and a later correction properly deployed to a dedicated docs system user matching the nginx vhost root. The stale copy was never cleaned up.

Risk:

  • No .git exists in either tree, so there is no audit trail proving which copy is "true" beyond nginx's own vhost pointer and file mtimes; a future config regeneration (this is a CloudPanel-managed host) or an operator mistake pointing the vhost root back at /home/ippadmin/... would silently roll the live site back ~29 hours, re-serving stale content (e.g., pre-dating the Aug 10 auth-gate documentation and VerdictTank v3 updates) with no visible error.
  • The stale copy is root-owned while every other operational convention on this host uses a dedicated service user; this is itself a hygiene deviation worth correcting regardless of the duplication.
  • There is currently no single documented deploy path (git repo -> build -> publish target) for this site, so a repeat of this duplication is only prevented by operator memory.

Recommendation (Phase Two): delete or archive /home/ippadmin/htdocs/docs.itpropartner.com, and formalize the build/publish pipeline (ITPP Standards already defines a docs-publish Gitea Actions workflow template; wire the live docs site to that pipeline with the docs htdocs path as its sole target) so there is exactly one deploy destination, git-tracked, going forward.


4. Audience Delineation: Internal vs Client vs Product/Dev

Current state: no delineation exists. All 12 sections live under one flat, undifferentiated MkDocs nav, gated by a single email allowlist behind one auth layer. Concretely mixed on the same site, one click apart:

  • Internal-only, high-sensitivity operational material: Key Inventory (SSH key fingerprints/locations), Model Chain (LiteLLM virtual key hash, budget caps), Cost Control Rollout, app2 Caddyfile audit, Ops Portal / Backup-Restore internals (including the exposed historical credential noted in gap #2 above).
  • Internal engineering process docs: ITPP Standards (CI/templates), Scripts catalog, HomeLab.
  • Product/dev documentation for ITPP's own ventures: VerdictTank, TransitPin, FleetTracker360, Apex Track, BoxPilot, OSINT Tool, LaunchCheck, Shark Game - these describe products being built for eventual external users or customers, not ITPP's own infrastructure.
  • Client-facing: none currently exists as a distinct, intentionally-scoped audience. Nothing in the current tree is written for or safe to hand to an actual paying customer of VerdictTank, FleetTracker360, or TransitPin - yet the auth gate's allowlist (g@germainebrown.com, info@itpropartner.com) suggests the site is intended for internal ITPP staff only, which conflicts with product docs plausibly needing outside readers eventually (contractors, investors, or customers).

Assessment: the site currently serves one audience (internal ITPP operators) under one login, with no mechanism to safely expose a subset of content (e.g., product architecture for a contractor, or end-user help docs for a VerdictTank customer) without also exposing Key Inventory, Model Chain, and Ops Portal internals. This is a structural risk, not just an organizational tidiness issue: the moment anyone outside the current two-person allowlist needs access to any single product doc, the only lever available is "grant them access to everything," including SSH key inventories and credential-adjacent operational docs.

Recommendation: split into three distinct trust zones (detailed in the reorg tree below) before granting any doc access to anyone outside the current internal allowlist.


5. Proposed Documentation Reorg Tree (Deliverable A.6)

Plain-English rationale first, then the tree.

Rationale:

  1. Separate the credential-adjacent operational core from everything else. Key Inventory, Model Chain, Cost Control, Ops Portal/Backup-Restore internals, and the app2 Caddyfile audit should live in a zone that is never extended to anyone outside the current internal allowlist, regardless of what else changes.
  2. Separate product/dev docs from internal ops docs, because product docs (VerdictTank, TransitPin, etc.) have a plausible future need for a wider audience (contractors, eventual customers) that internal ops docs never will.
  3. Reserve an explicit, currently-empty client-facing zone rather than pretending the current site serves that purpose. If ITPP wants client-facing documentation (e.g., a VerdictTank user guide), it should be a deliberately separate publish target (different subdomain or path with its own, lighter-weight auth model), not a corner of the internal-only site.
  4. Retire dead stubs rather than let them accumulate. Apex Track, BoxPilot, and (arguably) Shark Game and OSINT Tool have single-entry, 5-week-stale changelogs with no real content beyond "created project repository." Continuing to display them as live nav entries between actively-maintained sections misrepresents the site's currency.
  5. Fix the self-contradiction between projects-master-readme and the sections it describes by making project status ("PLANNED" / "IN DEVELOPMENT" / "LIVE") a single generated field rather than manually duplicated free text in two places.
docs.itpropartner.com/
├── internal/ [existing allowlist gate stays here, unchanged scope]
│ ├── infrastructure/ (from itpp-infrastructure, minus product-adjacent items below)
│ │ ├── overview
│ │ ├── key-inventory <- flag: rewrite "sanitized" claim or actually remediate first (gap #1)
│ │ ├── model-chain
│ │ ├── cost-control-rollout-2026-07-24
│ │ ├── app2-caddyfile-audit-2026-07-21
│ │ ├── super-search-cf-bypass
│ │ ├── ops-portal (+ architecture)
│ │ ├── backup-restore (+ architecture)
│ │ ├── docs-auth-gate
│ │ ├── project-log
│ │ └── audit/ <- NEW: link Phase One (and future Phase Two) findings for internal transparency
│ ├── standards/ (itpp-standards, unchanged)
│ ├── homelab/ (unchanged; flag as "out of Phase One audit scope" until a homelab-specific audit exists)
│ └── scripts/ (unchanged)
│
├── products/ [same or a separate, slightly wider internal+contractor gate]
│ ├── verdicttank/ (+ architecture)
│ ├── transitpin/
│ ├── fleettracker360/
│ ├── apex-track/ <- ARCHIVE unless real content is added; currently a dead stub
│ ├── boxpilot/ <- ARCHIVE unless real content is added; currently a dead stub
│ ├── osint-tool/
│ ├── launchcheck/ (+ competitive-analysis, business-proposal)
│ └── shark-game/ <- review: 5-week-stale, confirm still active before keeping live
│
├── client/ [NEW, does not exist today - separate publish target/subdomain,
│ its own lightweight auth or fully public, populated only with
│ content explicitly written for external readers]
│ └── (empty until ITPP decides which product needs a customer-facing doc set)
│
└── legal/ [NEW, single location - currently a dangling empty page under
 itpp-infrastructure; either populate with real legal/compliance
 content or remove the nav entry entirely]

What moves where:

  • itpp-infrastructure/* -> internal/infrastructure/* (unchanged content, new path only).
  • itpp-standards, homelab, scripts -> internal/* (unchanged).
  • verdicttank, transitpin, fleettracker360, apex-track, boxpilot, osint-tool, launchcheck, shark-game -> products/* (unchanged content, new path, plus an explicit staleness review for the four dead/near-dead stubs).
  • itpp-infrastructure/legal -> either populated and moved to a top-level legal/ or removed.
  • itpp-infrastructure/project-log and projects-master-readme -> reconcile into a single generated project-status view under internal/infrastructure/project-log, sourced from each project's own README/CHANGELOG status field rather than hand-maintained twice.
  • New internal/infrastructure/audit/ -> add Phase One (and future Phase Two) findings summaries so the org has one place that tracks "what the docs say" next to "what the audits found."
  • client/ -> created empty; populated only when/if ITPP commits to publishing customer-facing docs for a specific product, with its own auth model decided at that time.

What gets archived (not deleted, moved to an archive/ prefix or removed from nav):

  • apex-track and boxpilot: both are single-entry "created project repository" stubs, 5 weeks stale, indistinguishable from placeholders. Either bring them current or pull them from the live nav so the site does not imply active documentation where none exists.
  • The stale /home/ippadmin/htdocs/docs.itpropartner.com duplicate (not a doc section, but the entire stale build) should be deleted per section 3.

Summary of Evidence Sources

  • Live site content: extracted via SSH from /home/docs/htdocs/docs.itpropartner.com on app3 (152.53.241.111), CHANGELOG and index pages per section.
  • Split-brain comparison: find/diff/stat against both /home/docs/htdocs/... and /home/ippadmin/htdocs/... on app3.
  • Cross-reference findings: neteng-a.md, neteng-b.md, sec-b.md, sys-a.md, sys-b.md, sys-c.md (all read in full for this audit).
  • No configuration, DNS, nginx, or docs content was modified. All recommendations are deferred to Phase Two per the audit brief's absolute rules.