Skip to content

chore: modernization sweep — SLSA attestations, SHA-pinned actions, ruff S/B/ASYNC, coverage gate, governance#26

Merged
heznpc merged 1 commit into
mainfrom
chore/modernization-sweep-2026-05-21
May 20, 2026
Merged

chore: modernization sweep — SLSA attestations, SHA-pinned actions, ruff S/B/ASYNC, coverage gate, governance#26
heznpc merged 1 commit into
mainfrom
chore/modernization-sweep-2026-05-21

Conversation

@heznpc

@heznpc heznpc commented May 20, 2026

Copy link
Copy Markdown
Member

Summary

Implements P1+P2 items from the 2026-05-21 modernization audit. P0 was empty (no active CVEs, no leaked secrets).

CI/CD

  • cd.yml: add actions/attest-build-provenance@v3 step → SLSA build provenance attestation (sigstore-signed wheel/sdist; surfaces on PyPI as "Build attestations: verified"). Add attestations: write permission. Pass attestations: true to pypa/gh-action-pypi-publish.
  • codeql.yml: add actions language to analysis matrix → workflow files scanned alongside python source.
  • ci.yml: pytest now runs with coverage; --cov-fail-under=70 enforced via pyproject addopts (matches measured 71% baseline).

Supply chain

SHA-pinned third-party actions with # vX.Y.Z legibility comments:

Action SHA Version
softprops/action-gh-release b4309332... v3.0.0
actions/stale b5d41d4e... v10.2.0
actions/github-script 3a2844b7... v9.0.0
actions/attest-build-provenance 96278af6... v3.2.0

First-party actions/*, github/codeql-action/*, and pypa/gh-action-pypi-publish@release/v1 keep tag pinning per publisher guidance.

Language/runtime

  • Dev deps now have major bounds: ruff>=0.15,<1, mypy>=2,<3, pytest>=8,<10, pytest-asyncio>=1,<2. Surprise majors no longer turn CI red overnight.
  • Add pytest-cov>=6,<8 + [tool.coverage] config.
  • Extend ruff rules with B (bugbear), S (bandit subset), ASYNC, RUF, SIM. tests/ per-file-ignore for S101 (pytest uses assert).
  • server.py: replace EN DASH with hyphen-minus in greet field description (RUF001 fix).

Governance

  • .github/CODEOWNERS — solo-dev auto-assign.
  • .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml with scope checks for template clones.
  • .github/PULL_REQUEST_TEMPLATE.md.
  • .python-version (3.13) for pyenv/uv users.

Security docs

  • SECURITY.md documents the full feature set + GitHub repo-side toggles. Links to private vuln reporting.
  • CHANGELOG.md: clarify [Unreleased] is informational; canonical log is GitHub Releases auto-notes.

GitHub repo-side toggles (already applied; not in this diff)

  • secret_scanning: enabled
  • secret_scanning_push_protection: enabled
  • dependabot_security_updates: enabled
  • vulnerability_alerts: enabled
  • Branch protection on main: required checks = security, licenses, test (3.11/3.12/3.13); no PR review requirement; admin override allowed
  • allow_auto_merge: true; delete_branch_on_merge: true

Test plan

  • ruff check . passes (new rules included)
  • ruff format --check . passes
  • mypy src/ passes (strict)
  • pytest passes 17/17, coverage 70.64% (above threshold)
  • CI green on all 3 Python matrix versions
  • CodeQL analyze (python) + analyze (actions) green

…uff S/B/ASYNC, coverage gate, governance

Implements P1+P2 items from the 2026-05-21 modernization audit. P0 was
empty (no active CVEs, no leaked secrets).

CI/CD
- cd.yml: add actions/attest-build-provenance@v3 (SLSA build provenance,
  sigstore-signed wheel/sdist; surfaces on PyPI as 'Build attestations:
  verified'). Add `attestations: write` permission. Pass `attestations: true`
  to pypa/gh-action-pypi-publish.
- codeql.yml: add `actions` language to the analysis matrix so workflow
  files are scanned alongside python sources.
- ci.yml: pytest now runs with coverage (--cov-fail-under=70 enforced via
  pyproject addopts; matches measured 71% baseline).

Supply chain
- SHA-pin third-party actions with `# vX.Y.Z` legibility comments:
  softprops/action-gh-release@v3.0.0, actions/stale@v10.2.0,
  actions/github-script@v9.0.0, actions/attest-build-provenance@v3.2.0.
- First-party actions/* + github/codeql-action/* + pypa/* keep tag pinning
  per publisher guidance.

Language/runtime
- pyproject.toml: dev deps now have major bounds (ruff>=0.15,<1, mypy>=2,<3,
  pytest>=8,<10, pytest-asyncio>=1,<2). Prevents surprise breaking releases.
- Add pytest-cov>=6,<8 and [tool.coverage] config.
- Extend ruff rule set: B (bugbear), S (bandit subset), ASYNC, RUF, SIM —
  with per-file-ignore S101 for tests/ (pytest's primary API is assert).
- server.py: replace EN DASH with hyphen-minus in `greet` field description
  (ruff RUF001 fix).

Governance
- Add .github/CODEOWNERS (solo-dev auto-assign).
- Add .github/ISSUE_TEMPLATE/{bug_report,feature_request,config}.yml with
  scope checks aimed at template clones.
- Add .github/PULL_REQUEST_TEMPLATE.md.
- Add .python-version (3.13) for pyenv/uv users.

Security docs
- SECURITY.md: document the full feature set including the GitHub repo-side
  toggles that are now enabled (secret scanning + push protection + Dependabot
  security updates + branch protection on main). Link to private vuln reporting.
- CHANGELOG.md: clarify [Unreleased] is informational; canonical log is
  GitHub Releases auto-notes.

GitHub repo-side toggles (applied via gh api, not in this diff):
- secret_scanning: enabled
- secret_scanning_push_protection: enabled
- dependabot_security_updates: enabled
- vulnerability_alerts: enabled
- branch protection on main: required checks = security, licenses,
  test (3.11/3.12/3.13); no PR review requirement; admin override allowed
- allow_auto_merge: true; delete_branch_on_merge: true

Local CI green: ruff (with new rules) clean, ruff format clean,
mypy strict clean, pytest 17/17 with 70.64% coverage.
@heznpc heznpc enabled auto-merge (squash) May 20, 2026 23:23
@heznpc heznpc merged commit 01ed305 into main May 20, 2026
7 checks passed
@heznpc heznpc deleted the chore/modernization-sweep-2026-05-21 branch May 20, 2026 23:23
@github-advanced-security

Copy link
Copy Markdown

You are seeing this message because GitHub Code Scanning has recently been set up for this repository, or this pull request contains the workflow file for the Code Scanning tool.

What Enabling Code Scanning Means:

  • The 'Security' tab will display more code scanning analysis results (e.g., for the default branch).
  • Depending on your configuration and choice of analysis tool, future pull requests will be annotated with code scanning analysis results.
  • You will be able to see the analysis results for the pull request's branch on this overview once the scans have completed and the checks have passed.

For more information about GitHub Code Scanning, check out the documentation.

heznpc added a commit that referenced this pull request May 21, 2026
Adversarial second-pass on commits 01ed305 (PR #26) and ec7045d (PR #27),
both reported as "done / tests pass / CI green". Two Critical findings.

[C1] CodeQL `analyze (actions)` open alert
- Rule: `actions/missing-workflow-permissions`
- File: .github/workflows/cd.yml
- Message: "Actions job or workflow does not limit the permissions of the
  GITHUB_TOKEN."
- Detected by the CodeQL `actions` language matrix that PR #26 itself added.
  PR #26 introduced top-level permissions on most workflows but missed
  cd.yml and setup.yml. The 5 required CI checks didn't include CodeQL,
  so the alert landed silently after merge.
- Fix: add `permissions: contents: read` at workflow top level in cd.yml
  and setup.yml. Jobs continue to opt into the writes they need
  (contents:write / id-token:write / attestations:write for publish;
  issues:write for setup).

[C2] `ok()` and `err()` Response Helpers — dead code marketed as feature
- server.py:41 and server.py:47 defined ok() / err() helpers.
- Zero references anywhere in src/ or tests/ (`grep -rn "\\bok(\\|\\berr("` =
  only the definitions + the introductory comment).
- Coverage report confirmed: server.py:43-44, 49 uncovered.
- README.md:32 and README.ko.md:30 marketed these as "Response Helpers —
  ok() and err() for consistent tool responses" in the "What You Get"
  list — i.e. a public feature claim with no backing code usage.
- The bundled `greet` tool returns plain `str` — the README's marketed
  pattern doesn't match the bundled example.
- FastMCP's idiom is `return value` / `raise on error`; ok/err helpers
  are a raw-MCP-without-FastMCP relic that actively teach the wrong
  pattern.
- Fix: delete ok() / err() / their introductory comment. Replace the
  Tools-section banner comment with one line documenting the actual
  FastMCP idiom. Remove the "Response Helpers" bullet from README.md
  and README.ko.md.

Why this matters beyond cosmetics: a starter is a teaching artifact.
False "What You Get" entries silently propagate the wrong pattern to
every clone. The dead helpers were also reachable code surface that
CodeQL has to scan but no test exercises.

Verification
- All 7 workflows now have top-level `permissions:` (verified via
  `awk` scan of column-1 `permissions:` line).
- ruff / ruff format / mypy strict / pytest 17/17 all clean.
- Coverage 72.12% (improved from 70.64% — uncovered dead code removed).

Out-of-scope for this PR (will be raised as Major findings for user
decision):
- tests/test_tools.py has no `test_greet_registered_on_server` despite
  test_server_info.py and test_code_review.py both having that pattern.
- server_info.py wheel-install fallback path (lines 41-42, 52-56) is 0%
  covered; test only exercises the dev/source-tree read-pyproject path.
- src/my_mcp_server/tools/greet.py defines a `register()` that's never
  called by server.py — fully dead modular example.
- SECURITY.md "branch protection on main" claim is starter-side only;
  clones inherit nothing.
- 4 Dependabot PRs (#28, #29, #30, #31) opened today — #28 is
  attest-build-provenance v3.2.0 → v4.1.0, making our 6-hour-old SHA
  pin already one major behind.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants