Repository navigation
Enable ruff security, logging and debugging rules (S, T20, LOG, G, DTZ, ERA, TD, FIX, EXE) - #785
Merged
Merged
Conversation
anth-volk
added this pull request to stack #755
October 13, 2026 17:53
anth-volk
force-pushed
the
ruff-security-logging
branch
3 times, most recently
from
October 14, 2026 17:29
403cbc2 to
ab3ad4d
Compare
anth-volk
force-pushed
the
ruff-security-logging
branch
3 times, most recently
from
October 14, 2026 20:04
d0d50d7 to
76c2cde
Compare
anth-volk
force-pushed
the
ruff-security-logging
branch
6 times, most recently
from
October 15, 2026 16:06
a388172 to
94de8a7
Compare
anth-volk
force-pushed
the
ruff-security-logging
branch
4 times, most recently
from
October 16, 2026 05:01
f92c311 to
ba82c0b
Compare
Pass logging arguments instead of f-strings (G004); each message renders to the same text. Name the economy-comparison router's logger after its module rather than its file path (LOG002). Log the gateway's auth misconfiguration with logger.exception and a fixed message (G201): the traceback already ends with the exception and its message, which the old call also repeated in the message. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
policyengine.py parses policy period keys with strptime and no zone, so its ParameterValue dates are naive, and the executor's period parsing and the tests that compare against those dates must stay naive too. Mark each kept naive datetime with a reasoned DTZ suppression, and route the policy tests' expected dates through one helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The deployed-service test suite in authenticated_tests is a pytest suite that the tests glob misses, so give it the same test exemptions. Elsewhere, drop the asserts that only narrowed types: the SPM selection check now returns the hash and scenario it has already proved present, and the qualification runner closes over a non-optional runtime. The gateway image smoke raises RuntimeError when its report is incomplete, as the executor's static-file smoke does, and the fake model output raises AssertionError explicitly when the adapter asks for a mode other than JSON. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every print the rule finds belongs to a command-line script or a Modal local entrypoint, whose stdout is its output, so keep each print. Files with one to three prints mark each with a reasoned suppression; the routing-state publisher and the policyengine package updater send their output through one small helper that holds the only print. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Each test module that runs repository scripts now does so through one helper that holds the only subprocess call, with reasoned suppressions: the scripts are repository-owned, their arguments are built by the tests, and bash and uv come from PATH as they do in the workflows. Resolving the executables in Python instead could pick a different binary, because subprocess searches the child's PATH, and some tests run scripts with an empty environment. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Build the GCP metadata request inline from its constant http URL, with the same Metadata-Flavor header, so S310 can see the scheme. Keep every other finding with a reasoned suppression: - S105/S106: fake tokens in tests (one module constant per test module where a value repeats), and names or fingerprints that only look like secrets. - S108: the executor's fixed data directories inside the Modal container, and a lookup path the tests' fakes only pass along. - S110: add S110 to the existing reasoned BLE001 suppressions. - S102: the image tests execute repository-owned app source as Modal's /root/app.py. - S301: the SPM tests round-trip errors they built or raised. - S310: the Hub API request URL is built from the HF_ENDPOINT base and quoted path parts. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Select DTZ, ERA, EXE, FIX, G, LOG, S, T20 and TD. The earlier commits on this branch fixed or suppressed, with a reason, every finding outside the shared scripts/rules tool. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
sim.quality.ruff-lint now lists DTZ, ERA, EXE, FIX, G, LOG, S, T20 and TD. The authenticated_tests exemption gets its own rule, since a ruff per-file-ignore rule names one pattern. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The shared scripts/rules tool takes the Public API's group 6 fixes: explicit checks instead of asserts, and reasoned suppressions for its git and shellcheck subprocess calls, prints and calendar dates. The rendered rules page picks up the tool's new hash. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#743 and #744 landed on main after this stack branched. Group 6, which this PR enables, flags their new code; each fix follows this PR's conventions: - T201: the routing publisher's new commands report through its _report helper, the package updater's dispatch check through _write_result, and the sentinel CLI gets one _report helper that holds its only print. - S603/S607: the deployment-asset tests route #744's new bash calls through _run_bash, which now takes cwd; the rollback tests and the package-update helper tests get one helper each that holds the only subprocess call, with reasoned suppressions. - S310: the sentinel's HTTP helper opens the deployed entrypoint or the test auth issuer URL that the workflow passes; reasoned suppressions. - S106: a fake bearer token in the sentinel tests. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#795 landed on main after this stack branched. S110, which this PR enables, flags the try-except-pass in its _cancel_call, which now holds the best-effort cancel loop this PR suppressed; like the other reasoned BLE001 suppressions, it gains S110. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#791 landed on main after this stack branched. S105, which this PR enables, flags two values that only look like secrets, and each keeps a reasoned suppression: the redaction pattern for secret-looking key names in the Stage 12 failure-cause module, and the fake database password its tests check redaction removes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#758 landed on main after this stack branched. S603, which this PR enables, flags the two new deployment tests that run the Cloud Run deploy script directly to check permission enforcement defaults and rejections. They carry the same reasoned suppression as the existing direct run of that script. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#781 landed on main after this stack branched. Group 6, which this PR enables, flags two of its additions: - S110: the Modal app's stage-duration telemetry swallows a failed set_context, so its suppression adds S110 beside BLE001, as the call attributes helper above it does; - DTZ001: the contract test that the job record rejects a naive time builds that naive time on purpose, so it carries a reasoned suppression. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
anth-volk
force-pushed
the
ruff-security-logging
branch
from
October 16, 2026 05:12
ba82c0b to
fa3df58
Compare
…e scripts A ruff per-file-ignores entry switches rules off for whole files. That is now acceptable where it's the norm: tests, CI/CD scripts under .github, and command-line scripts (under a scripts directory, or modules run through if __name__ == "__main__"). Everywhere else a kept finding still needs an inline suppression with its reason. The rules guard already requires a per-file-ignore rule for every entry. It now also expands each entry's pattern the way ruff does (globset syntax, and a slash-less pattern also matches file names) and fails when the pattern covers any other file, is negated, or matches nothing. scripts/rules/file_exceptions.py holds the definitions, and the registry doc describes the policy. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Tests, CI/CD scripts and command-line scripts now take their deliberate group 6 exceptions as registered per-file-ignores, each code chosen from the suppressions those files already carried: - tests and the deployed-service tests: S102, S105, S106, S108, S301, S603, S607, DTZ001 and DTZ007, added to their existing exemptions; - .github: T201; - scripts directories: DTZ011, S603, S607 and T201; - programs under src (the Modal deployment utilities, and the OpenAPI and Stage 12 infrastructure commands): S310 and T201. That removes 75 inline codes from 44 files. Application code keeps its inline suppressions and reasons. Comments only: no code changes. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Fixes #784
Same-Repository Draft PR Check
PolicyEngine/policyengine-sim-api, not a personal fork.Summary
Phase 1 step 1.8, group 6: security, logging and debugging leftovers. Bottom of the stack since #783 merged.
ruff.tomlgainsS,T20,LOG,G,DTZ,ERA,TD,FIXandEXE. Every finding is fixed (one commit per family), covered by a file-level exception in tests, CI/CD scripts or command-line scripts, or kept inline with a reason in application code.ERA,TD,FIXandEXEhad no findings.per-file-ignoresentry is now allowed only for tests (testsorauthenticated_testsdirectories), CI/CD scripts (.github) and command-line scripts (ascriptsdirectory, or a module run throughif __name__ == "__main__":).Enforcement: the rules guard already required a registered rule for every entry. Now it also expands each entry's pattern the way ruff does and fails when the pattern covers any other file, is negated, or matches nothing. Ruff's
*also matches/, and a pattern also matches a bare file name; the check follows both.Where it lives:
scripts/rules/file_exceptions.py.docs/engineering/skills/rules-registry.mdhas a new "File-level exceptions" section.Codes, from the suppressions those files already carried:
.github/****/scripts/**src: the Modal deployment utilities, and the entry and gateway OpenAPI and Stage 12 infrastructure commandsEffect: this removes 75 inline codes from 44 files. Each of the five branches up to Register weighted-microdata rules, weight the builder tests, and check change weights and household counts #807 differs from its previous version in project Python only by
noqacomments; a script checked each file line by line.Registry: three new rules:
sim.quality.ci-cd-scripts-ruff-exemptions,sim.quality.command-line-scripts-ruff-exemptionsandsim.quality.src-programs-ruff-exemptions.logger.exception("Gateway auth misconfigured"). Before, it logged "Gateway auth misconfigured: Gateway auth misconfigured: set GATEWAY_AUTH_ISSUER …", repeating the message; the traceback still ends with the fullRuntimeErrormessage. The 503 response is unchanged.simulation.pyusesgetLogger(__name__)instead ofgetLogger(__file__).RuntimeErrorwith a message instead of failing a bareassert. The smoke script and the integration test only check the exit code.%sarguments with identical text (G004).spm.py(4): the asserts couldn't fail, because_require_complete_selectionalready raisesValueErrorwhen either value is missing. It now returns them, so nothing new is raised and Pydantic validators still seeValueError.stage12_qualification.py: the closure captures a non-optional runtime instead of asserting it.fixtures/: raisesAssertionErrorexplicitly, as the repo's other fakes do.authenticated_tests: this is the deployed-service pytest suite (run bysimulation-deploy.reusable.yml), which the**/tests/**glob didn't match. It gets the same exemptions as**/tests/**, registered assim.quality.deployed-tests-ruff-exemptions.-O..githuband the programs undersrcare covered by file-level exceptions. The Modal local entrypoints (smoke_app.py,v2_static_runtime_files_smoke.py) and the executor's import-timegenerate_openapi.pydon't run through__main__, so they keep an inline reason.update_version_registry.py(22 prints) and.github/scripts/update_policyengine_package.pyroute output through one helper. No application code had a debug print._run_bashintest_modal_scripts.py(32 calls). Tests and scripts are covered by file-level exceptions; the one call in application code keeps an inline reason. Executables still come from the child'sPATH, since several tests pass their ownenv.ParameterValuedates and its own period parsing. The 11 naive test dates go through one_naive_policy_datehelper.Requestinline, with identical URL, headers and method.execrepository-owned app source, and tests that pickle objects they built./tmp/policyengine-datapaths;HF_ENDPOINTand quoted path parts.S110: eachtry/except/passalready carried a reasonedBLE001suppression from group 5, which now listsS110too.simulation.py,simulation_runtime.py,stage12_qualification.pyandupdate_version_registry.py, and in the shared contract, observability and fastapi libraries.src/modal/app.pychanges only in comments.sim.quality.ruff-lintnow lists the nine families. The rules tool is synced from the Public API's group 6 (Enable ruff security, logging and debugging rules (S, T20, LOG, G, DTZ, ERA, TD, FIX, EXE) policyengine-api#3915), and both copies gain the same file-level exception check (file_exceptions.pyis identical in both).Testing
Suites: at this branch's tip after today's restack onto
main, all seven passed:The file-level exceptions change touches project code only in
noqacomments, so the suites weren't re-run for it.For the file-level exceptions change, at each tip from Enable ruff security, logging and debugging rules (S, T20, LOG, G, DTZ, ERA, TD, FIX, EXE) #785 to Register weighted-microdata rules, weight the builder tests, and check change weights and household counts #807:
ruff checkandruff format --check(0.15.22) are clean repo-wide;ci-scriptsguard and the rules tool unittests pass, including six new tests for the check;mainto Register weighted-microdata rules, weight the builder tests, and check change weights and household counts #807.Negative check: pointing an exception at
projects/*/src/**fails the guard and names the application files it would cover.Lint at the top of the stack: the new rules-tool code also passes the stack top's
select = ["ALL"].Integration smoke tests: these need real Modal, so they were only collected.
CI/CD: no workflow changed, and no environment variable was added or rewired.
CI: this is now the lowest unmerged PR in the stack, so its full CI runs.
🤖 Generated with Claude Code