Skip to content
prod e051e98
Browse

8 · Deep codebase audit

Objective — run a deeper codebase audit while staging is live and the stakes are low: project structure, composer security audit, Git hygiene, FVDUT storage persistence, secret + debug-code scans (with the word-boundary fix for dd()), storage-tracked-file triage, CodeCanyon frontend anti-patterns, and an optional schema audit — so every finding caught here is one that doesn’t surface in production.

Staging is the right moment for a thorough codebase audit: the app is deployed and verifiable, but no real users depend on it. Work top to bottom; most findings become backlog items, a few are real fixes you redeploy.

Where this page sits in the phase:

flowchart LR
Staging[Staging deploy live] --> Deep[Deep pass on this page]
Deep --> Backlog[Most findings → backlog]
Deep --> Fix[Few fixes → redeploy]
Deep --> P10[Phase 10 static audit re-verify]

Confirm the standard Laravel layout, the artisan version, and the vault .gitignore.

  1. List the standard directories and the vault ignore.

    Terminal window
    ls -la app/ config/ database/ public/ resources/ routes/ storage/
    ls -la artisan composer.json package.json .env.example
    php artisan --version
    cat Admin-Local/1-Project/2-ProjectVault/.gitignore # expect `*` and `!.gitignore`
    # Expected: all standard dirs/files exist; Laravel version prints; vault ignores all but itself
    • ✅ All standard directories/files exist, Laravel version prints, and the vault .gitignore ignores everything but itself.

Surface known vulnerabilities in dependencies, fix the urgent ones, and re-verify.

  1. Run the audit.

    Terminal window
    composer audit
    # Expected: a list of advisories (or "No security vulnerability advisories found")
    • ✅ The audit output is reviewed against the severity table.
  2. Fix and re-verify the urgent advisories.

    Terminal window
    composer update vendor/package && composer audit # fix + re-verify
    git add composer.json composer.lock && git commit -m "Security: update packages for vulnerability fixes"
    # Expected: re-audit shows the fixed advisory gone; the lockfile change is committed
    • ✅ Critical/High advisories are resolved and the lockfile change is committed.

Triage by severity:

SeverityAction
CriticalUpdate immediately
HighUpdate before launch
MediumUpdate soon
LowTrack for next release

Confirm secrets and heavy trees never entered history.

  1. Scan history for vendor/, node_modules/, and .env.

    Terminal window
    git log --all --full-history -- vendor/ | head -5 # expect empty
    git log --all --full-history -- node_modules/ | head -5 # expect empty
    git log --all --full-history -- .env | head -5 # expect empty
    git log --all --full-history -- ".env.*" | head -5 # expect empty (except .env.example)
    # Expected: all four scans return empty (apart from .env.example)
    • vendor/, node_modules/, and .env are absent from Git history.

FVDUT = Files, Vendors, Directories, Uploads, Temp — folders that must survive a release swap via shared_dirs.

  1. Confirm shared_dirs covers storage + uploads, and symlinks are present.

    Terminal window
    grep -A10 "shared_dirs" deploy.php # expect `storage` + any custom upload dirs
    ls -la public/ | grep "^l" # local symlinks present
    ssh <staging-alias> "ls -la ~/domains/staging.yourapp.com/deploy/current/public/ | grep '^l'"
    # Expected: shared_dirs lists storage + uploads; symlinks present locally and on the server
    • shared_dirs persists storage + uploads and symlinks are present on both ends.

Scan app code for hardcoded credentials and leftover debug calls.

  1. Scan for secrets, debug code, and confirm APP_DEBUG=false.

    Terminal window
    grep -rn "password\s*=" --include="*.php" app/ config/ | grep -v ".env\|example\|fake\|test" | head
    grep -rn "api_key\|apikey\|secret_key" --include="*.php" app/ config/ | grep -v ".env\|example" | head
    grep -rn "://.*:.*@" --include="*.php" app/ config/ | head # credentials in URLs
    # Debug code — word-boundary regex so `->add(` does NOT false-positive on `dd(`
    grep -rnE "(^|[^a-zA-Z_>])(dd|dump|var_dump|print_r)\(" --include="*.php" app/ | head
    grep -rn "console.log" resources/js/ | head
    ssh <staging-alias> "grep APP_DEBUG ~/domains/staging.yourapp.com/deploy/shared/.env" # expect false
    # Expected: no hardcoded secrets, no real debug calls in shipped paths, APP_DEBUG=false
    • ✅ No hardcoded secrets, no debug code in staging paths, and APP_DEBUG=false.

A related noise source is the server log itself when you scan it for real errors:

Files committed under storage/ are ambiguous: Deployer replaces storage/ with a symlink to shared/storage/, so tracked files never reach the running app — but vendor packages often write runtime config to storage_path('<file>'), and deleting those breaks the package silently. This scan is investigation only; the default action for every file is KEEP.

  1. List tracked storage/ files and search for their references.

    Terminal window
    git ls-files storage/ | grep -vE '\.gitkeep$|\.gitignore$|^storage/installed$'
    # For each suspect, search reads AND writes across vendor/packages/app:
    # B=$(basename <FILE>)
    # grep -rnE "$B|storage_path.*$B|file_put_contents.*$B|->put\(.*$B" vendor/ packages/ app/ config/ routes/
    # Expected: a list of suspect files; default action for each is KEEP
    • ✅ Each tracked storage/ file is triaged (default KEEP) using the reference table.

Classify each suspect:

Reference found inAction
vendor/ or packages/KEEP + add to shared_files
app/ / config/ / project codeKEEP + shared_files (or move out of storage/)
NowhereDefault KEEP; remove only if certain it has no vendor origin — and log it
UncertainKEEP + shared_files

None block a deploy; all are worth logging as VENDOR/Frontend backlog items.

  1. Scan for global SDKs, unguarded charts, duplicate includes, and double-registered service workers.

    Terminal window
    # Global third-party SDKs that should be route-scoped
    grep -rln "js.stripe.com\|paypal.com/sdk\|checkout.razorpay.com" resources/views/layouts/ resources/views/components/ 2>/dev/null
    # Charts (check for empty-state guards)
    grep -rln "ApexCharts\|Chart.js\|echarts\|chartist" resources/views/ 2>/dev/null
    # Duplicate framework includes
    grep -rcn "@livewireScripts\|livewire.min.js" resources/views/ 2>/dev/null
    # Service worker double-registration
    grep -rn "serviceWorker.register" resources/views/ public/ 2>/dev/null
    # Expected: hits become VENDOR/Frontend backlog items (none block the deploy)
    • ✅ Any anti-pattern hits are logged as VENDOR/Frontend backlog items.

Fixes: scope payment SDKs to checkout via @stack('scripts'); guard charts with @if($data->count()) + a “no data” fallback; keep @livewireScripts in the root layout only; register the service worker once.

Inspect the staging schema with Atlas or a free tool and categorize tables so you know what’s safe to touch.

  1. Inspect and categorize the staging tables.

    With Atlas or a free tool (mysqldump --no-data, TablePlus, DBeaver), inspect the staging schema and categorize tables.

    • ✅ Tables are categorized so you know what’s safe to modify.

Category rules:

CategoryExamplesRule
Core vendorusers, settings, paymentsNEVER modify
Plugin / featureai_*, chat_*, blog_*Check vendor docs first
Laravel systemmigrations, jobs, cacheNEVER modify
Custom (_zaj)users_zaj, custom_*Yours — safe to modify

9. Database performance baseline (optional)

Section titled “9. Database performance baseline (optional)”

Capture a DB performance baseline and surface obvious slow queries / N+1 patterns before any real traffic arrives — every slow path caught here is one you don’t debug live.

  1. Check the slow query log and threshold.

    Terminal window
    ssh <staging-alias> "mysql -e \"SHOW VARIABLES LIKE 'slow_query_log%'; SHOW VARIABLES LIKE 'long_query_time';\""
    ssh <staging-alias> "tail -100 /var/log/mysql/mysql-slow.log 2>/dev/null \
    || echo 'Slow query log not accessible on shared hosting — use EXPLAIN on hot queries instead'"
    # Expected: the log's on/off state + threshold, or a fallback note for shared hosting
    • ✅ You know whether the slow query log is available.
  2. EXPLAIN a hot query and list the largest tables.

    Terminal window
    ssh <staging-alias> "mysql DB_NAME -e \"EXPLAIN SELECT * FROM HOT_TABLE WHERE HOT_COL = 1 LIMIT 10;\""
    ssh <staging-alias> "mysql -e \"SELECT table_name, table_rows FROM information_schema.tables \
    WHERE table_schema=DATABASE() ORDER BY table_rows DESC LIMIT 10;\""
    # Expected: hot table uses an index (`key` is not NULL); top tables are recorded
    • ✅ Hot tables use indexes and the heaviest tables are recorded.

If Debugbar or Telescope is installed on staging, hit the dashboard and two or three list pages as an authenticated user and record: no single query > 1s, no N+1 pattern, hot tables show key used in EXPLAIN, and average page query count is reasonable.

Record in ProjectLog (DATABASE/Performance): homepage query count ___, dashboard query count ___, slowest observed query ___ ms.

Commit any real fixes found above and redeploy.

  1. Commit and redeploy the audit fixes.

    Terminal window
    git add . && git commit -m "Audit: investigation fixes — <describe>"
    git push origin staging && dep deploy staging
    # Expected: fixes committed, pushed, and redeployed to staging
    • ✅ Any audit fixes are committed and redeployed.

Do not mark this step done until every box below is checked.

  • 🤖 Structure + audit — structure verified; composer audit clean of Critical/High.
  • 🤖 Git history cleanvendor/, node_modules/, .env absent from Git history.
  • 🤖 Storage persistsshared_dirs persists storage + uploads; symlinks present on server.
  • 🤖 No secrets / debug — no hardcoded secrets; no debug code in staging paths; APP_DEBUG=false.
  • 🤖 Triage + anti-patternsstorage/-tracked files triaged (default KEEP); frontend anti-patterns logged.
  • 🤖 Fixes redeployed — any fixes committed and redeployed.