Skip to content

scripts: harden check_invariants.py invariant-5/6 regex heuristics (deferred) #66

Description

@countercheck

Source: codebase audit, 2026-06-11 (audit finding F12, Tier 3)
Severity: Low
Category: Lint robustness (acknowledged tradeoff)

Problem

`scripts/check_invariants.py` uses regex heuristics to enforce two invariants:

  • Invariant 5 (lines 321–324): `STMT_RE = re.compile(r"(INSERT\s+INTO|UPDATE)\b[^;]?\bparent_question_id\b[^;]?;", ...)` — requires a `;` terminator, so SQL built dynamically (f-strings, template loops) could escape the check.
  • Invariant 6 (lines 392–439): uses a 300-character lookback window (`GUARD_WINDOW = 300`) to verify `pii_risk` appears near a `value_text` projection. A `pii_risk` mention in an unrelated CASE within window could give a false negative.

Status

Acknowledged tradeoff — the regex-vs-AST decision was made deliberately at lint inception. The lint is defense-in-depth (the actual invariants are enforced by dbt singular tests and migration grants); the regex catches the common case and stays maintainable.

This issue exists as a tracking pointer in case a real bypass is observed in the future. Not actionable today.

When to revisit

  • A bug ships where one of the regex heuristics missed a real violation.
  • The codebase grows enough that dynamic SQL becomes common (currently rare).
  • A dependency like `sqlfluff` or `sqlglot` matures to the point where AST-based linting is cheap.

Why `question` label

This isn't a refactor with an owner — it's a deferred concern with an explicit "wontfix unless triggered" stance.

Metadata

Metadata

Assignees

No one assigned

    Labels

    questionFurther information is requested

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions