8Regression coverage for the workspace-mode secret-scanner fix
9(P2 of the drift resolution plan): when ``run_quality_gate_on_files``
10runs from a workspace root, per-subproject ``entropy_exclusions``
11configured in ``<sp>/.option_c/octrc.json`` must apply to files in
12that subproject. Path patterns are prefixed with the subproject's
13workspace-relative path. The new ``module_self_doc`` context value
14must be honoured alongside ``test_directory`` for ``path_pattern``
15exclusions and accepted by the octrc schema validator.
19- Build a minimal workspace + subproject + manifest.
20- Plant a high-entropy string in a target Python file.
21- Verify the scanner finds it WITHOUT a config (baseline).
22- Verify the scanner skips it WITH a per-subproject ``module_self_doc``
23 exclusion when invoked from the workspace root.
24- Verify the schema validator accepts ``module_self_doc``.
31 L3 — per-assertion details
35- Tests run hermetically inside ``tmp_path``; no real workspace is touched.
36- Exclusion semantics are verified end-to-end through
37 :func:`oct.git.quality_gate.run_quality_gate_on_files`.
41- oct.git.quality_gate (run_quality_gate_on_files entry point under test)
42- oct.linter.oct_lint (_validate_octrc_schema for context validation)
45from __future__
import annotations
48from pathlib
import Path
56HIGH_ENTROPY_FILE =
'''\
58# -*- coding: utf-8 -*-
80- Strings are constants.
86# A long, high-entropy literal that would trip the entropy scanner
87# at the default code threshold of 4.5 bits/char. Mixed-case
88# alphanumerics with rare characters push entropy well above 4.5.
89HELP_BLURB = "aB3kQ9pZ2vMx7Lw5fT8r1NjY6sH4dGcPe0iVoUbXqMnRtKaCyEbWlIuFhDsAjVgZ"
94 """Build a minimal workspace at ``tmp_path/ws`` with one subproject.
96 Returns the workspace root.
98 ws_root = tmp_path /
"ws"
100 (ws_root /
".option_c_workspace.json").write_text(
105 {
"path":
"sub",
"name":
"sub"},
111 sub_root = ws_root /
"sub"
114 if subproj_octrc
is not None:
115 (sub_root /
".option_c").mkdir()
116 (sub_root /
".option_c" /
"octrc.json").write_text(
117 json.dumps(subproj_octrc),
121 target = sub_root /
"help_text.py"
122 target.write_text(HIGH_ENTROPY_FILE, encoding=
"utf-8")
127 """Without any subproject octrc, the high-entropy literal is flagged."""
129 target = ws_root /
"sub" /
"help_text.py"
131 result = run_quality_gate_on_files(
133 project_root=ws_root,
137 assert result.secrets_findings,
"expected high-entropy literal to flag"
139 "help_text.py" in finding[0]
and "high-entropy" in finding[2].lower()
140 for finding
in result.secrets_findings
141 ), result.secrets_findings
145 """Subproject's module_self_doc path_pattern is honoured at workspace scope.
147 The pattern ``help_text.py`` (subproject-relative) is prefixed with
148 ``sub/`` by the workspace merge, so the workspace-relative file
149 path ``sub/help_text.py`` matches and entropy is exempted.
153 "entropy_exclusions": [
155 "path_pattern":
"help_text.py",
156 "context":
"module_self_doc",
157 "reason":
"Self-documenting help text",
159 "exempt_entropy_only":
True,
160 "require_waiver_for_secret_patterns":
True,
167 target = ws_root /
"sub" /
"help_text.py"
169 result = run_quality_gate_on_files(
171 project_root=ws_root,
175 assert not result.secrets_findings, (
176 f
"expected no findings; got {result.secrets_findings}"
181 """The schema validator accepts the new ``module_self_doc`` context."""
184 "entropy_exclusions": [
186 "path_pattern":
"oct/cli.py",
187 "context":
"module_self_doc",
188 "reason":
"self-doc",
189 "restrictions": {
"exempt_entropy_only":
True},
194 errors = _validate_octrc_schema(cfg)
195 assert errors == [], errors
199 """Unknown ``context`` values are still rejected (regression guard)."""
202 "entropy_exclusions": [
204 "path_pattern":
"x/",
205 "context":
"totally_made_up",
211 errors = _validate_octrc_schema(cfg)
212 assert any(
"context" in e
for e
in errors), errors
test_workspace_mode_baseline_flags_high_entropy(Path tmp_path)
Path _make_workspace(Path tmp_path, dict|None subproj_octrc)
test_workspace_mode_module_self_doc_exclusion_applies(Path tmp_path)
test_octrc_schema_rejects_unknown_context()
test_octrc_schema_accepts_module_self_doc_context()