Skip to content

tech-debt: three separate hardcoded-value detectors have drifted (pipeline-scripts, autobot-infrastructure, pre-commit hook) #14371

Description

@mrveiss

Found while working #14316 (pipeline-scripts/detect-hardcoded-values.sh never scanned shell scripts).

Problem

There are three independent implementations of "detect hardcoded values" in this repo:

  1. pipeline-scripts/detect-hardcoded-values.sh — used by .github/workflows/ssot-coverage.yml (CI, non-required check). Fixed in bug(ci): the hardcoded-value detector never scans shell scripts, which is where hardcoded accounts and paths actually live #14316 to also scan *.sh/*.yml/*.yaml and to broaden its account rule.
  2. autobot-infrastructure/shared/scripts/detect-hardcoded-values.sh — a second copy with its own SSOT IP/port/model mapping tables, its own exclude list, and its own scan functions (scan_ssot_ips, scan_ssot_ports, scan_ssot_models, scan_urls). It references $PROJECT_ROOT/src and $PROJECT_ROOT/backend, directory names that do not exist in this repo (the real trees are autobot-backend, autobot-frontend/src, etc.), and it is not invoked by any workflow or pre-commit hook — dormant and, on the evidence of the path mismatch, has been dormant long enough to drift out of sync with the repo layout. bug(ci): the hardcoded-value detector never scans shell scripts, which is where hardcoded accounts and paths actually live #14316 added it to pipeline-scripts/detect-hardcoded-values.sh's exclude list (as an SSOT-definition file, matching how ssot_mappings.py is already excluded) so its own literal IP table isn't flagged as a violation — that is the only change made to it.
  3. autobot-infrastructure/shared/scripts/hooks/pre-commit-hardcoded-values — a THIRD implementation, wired as the actual detect-hardcoded-values pre-commit hook (.pre-commit-config.yaml, types: [python, ts, vue]). This is the one that actually blocks commits today.

Three forks of the same concept is exactly the pattern feedback_consolidate_never_fork exists to catch. Each has its own pattern list, its own exclude list, and (based on #14316's findings) each has independently missed things the others catch.

Suggested next step

Measure which of the three is closest to canonical (the pre-commit hook is the one with actual enforcement power, so it's the strongest candidate), then either:

Do not delete #2 without first confirming (measure, don't assume) that nothing depends on it being present on disk even though nothing invokes it — e.g. documentation referencing its path.

Refs #14316

Activity

  1. github-actions commented on Aug 16, 2026

    @github-actions
    Contributor

    👋 Auto-triage could not confidently classify this issue (prose matched 5 skill areas; too ambiguous to label). Could a maintainer add the appropriate labels (frontend, backend, infrastructure, docs, testing and good-first-issue, intermediate, advanced)?

  2. mrveiss commented on Aug 23, 2026

    @mrveiss
    OwnerAuthor

    Delivered in #14883 as part of the CI-guard cluster.

    The three detectors are collapsed into one rule set (scripts/lib/hardcoded-value-rules.sh) carrying the union of all three — the PR body has the full per-rule table showing which canonical rule now covers each, including detector 1's PORT_PATTERN, which was declared and never referenced by any scan function. The dormant autobot-infrastructure/shared/scripts/detect-hardcoded-values.sh is retired: nothing invoked it, and its only references were in HARDCODING_PREVENTION.md under a path prefix that never existed. Docs repointed.

    Two thin entry points read the shared rules — the CI tree scanner and the pre-commit hook — differing only in where the lines come from and what they do with the verdict.

    Measurement worth recording: running the merged rules over the tree found 1977 findings where the CI detector reported 0. Every one was already true; the rules that would have found them lived in a fork nothing invoked, or in a hook that only ever sees staged files. They are recorded in pipeline-scripts/hardcoded_values_baseline.txt, which only ever shrinks and is audited by a new blocking CI step.

    Discovered while doing it and filed rather than dropped: #14884 (8 hook tests that cannot run), #14885 (verify-generated-types self-skipping on autobot_shared-only changes).

  3. mrveiss commented on Aug 23, 2026

    @mrveiss
    OwnerAuthor

    Rebased onto d70a1f99e after #14877 (35f48ba92) touched the one overlapping file. Resolved as a union of capabilities: the fail-loud abort idiom travels to where the retired detector's logic went, while the ssot-config.sh dependency deliberately does not — it set -a-loads the master .env and exports AUTOBOT_REDIS_PASSWORD, and the consolidated detector prints matched source lines into a public CI log. Reasoning recorded in scripts/lib/hardcoded-value-rules.sh, not left to be re-derived.

    Reading #14877's three new guards turned up a reach gap, filed as #14891: shell_lib_sources_resolve_test.py walks *.sh only, so all 16 extensionless hooks under autobot-infrastructure/shared/scripts/hooks/ sit outside it, two of them with live || true-class defects.

  4. mrveiss commented on Aug 23, 2026

    @mrveiss
    OwnerAuthor

    Delivered and merged.

    Verified in base after merge:

    scripts/lib/hardcoded-value-rules.sh          PRESENT
    pipeline-scripts/check_baseline_no_growth.sh  PRESENT
    pipeline-scripts/hardcoded_values_baseline.txt PRESENT
    scripts/lib/git-scope.sh                      PRESENT
    

    Union preserved — rules a survivor-pick would have deleted:

    Rule Existed only in Now
    VM IP, any fourth octet CI scanner kept wide; the hook's narrow (19|2[0-5]) did not win
    Ports 8443 / 5432 / 9090 CI scanner's PORT_PATTERN — declared and never grep'd wired in for the first time
    Per-value SSOT key suggestions, generic model regex, hardcoded-URL rule dormant fork carried
    Account identity (User=, chown, sudoers) CI scanner carried
    offset=0 as WARNING not VIOLATION hook severity preserved

    scripts/lib/hardcoded_value_rules_test.py fails by name per former detector, so a substitution cannot pass as a merge.

    One HIGH finding was raised in review and fixed before merge, not deferred. The baseline suppressing 1977 findings had no anti-growth check: a PR could hardcode a value and append a matching baseline line in the same commit, and ssot-coverage would report ssot_violations=0. check_baseline_no_growth.sh now diffs the baseline against the base ref and fails on any new key or increased count, failing closed on an unresolvable base, an unreadable baseline, or a parse error. Mutation-proved in a scratch repo both directions — growth red, shrinkage green.

    A real credential exposure was found and fixed while doing it. Two postgresql://user:pass@host/db values were already sitting in the generated baseline, a tracked file that also reaches public CI output. One shared _hv_redact_userinfo now serves both the DSN and URL rules; scheme and host survive so findings stay actionable. Verified in base: zero user:pass@ patterns remain, and the baseline totals are unchanged at 1434 lines / 1977 — the redaction dropped no finding.

    Also fixed: api-wiring — a required check — omitted autobot_shared/**/*.py from its path filter while audit_api_wiring.py imports two modules from that tree, so it reported green over an audit that never ran (#12986).

    #14181 was deliberately not closed by this PR — measured at 8/10 on one criterion with the remainder blocked by epic #7442. Follow-ups filed: #14884, #14885, #14891.

  5. mrveiss commented on Aug 23, 2026

    @mrveiss
    OwnerAuthor

    Post-merge follow-up: the blocking stale-baseline audit shipped in #14883 red-lined Dev_new_gui on the very next merge (#14890). Symptom fixed by #14910; root cause and a concrete removal-only --prune-baseline proposal filed as #14912. My design decision, measured at ~8% of the repo (776 of 9510 tracked files) able to trigger it.

  6. added a commit that references this issue on Aug 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions