chore: public-release audit#45
Conversation
The Claude review workflows (claude.yml, claude-code-review.yml) triggered on every PR via ANTHROPIC_API_KEY. On a public repo, drive-by PRs can burn that budget; the template should not ship with opinionated review tooling bound to one provider. renovate.json adds a packageRule disabling dhi.io/** Docker lookups. Renovate cannot introspect dhi.io without credentials, which was causing the "Action Required: Fix Renovate Configuration" failure that blocked all dependency PRs. DHI image pins are now maintained manually after docker-pull verification.
The three release workflows (release.yml, create-release.yml, patch-release.yml) ship intentionally stubbed so the template repo itself does not publish artifacts. The previous TODO comments were ambiguous ("Replace PLACEHOLDER" without saying where, mixing the stub state with real config).
Rewrite the top-of-file block in each workflow to spell out the exact unstub steps (swap the trigger, delete the stub guard, follow docs/release-playbook.md for required secrets). No behavior change — the files remain inert until a fork owner unstubs them.
Fresh pip-audit flagged two new transitive CVEs: - lxml 6.0.2 (via cyclonedx-bom) — CVE-2026-41066, fixed in 6.1.0 - python-dotenv 1.2.1 (via pydantic-settings) — CVE-2026-28684, fixed in 1.2.2 Both pinned at the project level following the existing pattern for cryptography and python-multipart. Direct deps (fastapi, mcp, pydantic, pydantic-settings) and dev/security tooling (ruff, ty, pytest-asyncio, pytest-cov, bandit, pip-audit, cyclonedx-bom) all bumped to current fix-floors to close out the open Renovate backlog in a single pass. The ty bump (0.0.1a18 floor -> 0.0.32 actual) surfaced two pre-existing type issues in the test suite: - test_mcp.py used hasattr(item, "text") which ty cannot narrow; switch to isinstance(item, TextContent) from mcp.types - test_settings.py used a # type: ignore comment ty did not recognize; switch to Settings.model_validate({...}) which is typed end-to-end After these fixes pip-audit reports 0 vulnerabilities and task check passes cleanly. The stale CVE-2025-71176 comment on the pytest pin was also removed since the pin has long since outrun that advisory.
Getting the template ready to ship as a public repo: - README rewritten for a public audience: reframe DHI as free-with-Docker-Hub-account (it went GA-free in late 2025, not a paid SKU), add a "For fork maintainers" section spelling out the DOCKERHUB_USERNAME/TOKEN and GitHub App release secrets, link the existing release playbook and contribution guide, fix a stale "safety" tool mention that was never actually wired up. - SECURITY.md casing: stackloklabs -> StacklokLabs (the lowercase URL 404s). - CONTRIBUTING.md added: setup steps, task check, Conventional Commits + DCO sign-off, pointer to the org-level Code of Conduct in StacklokLabs/.github. - Taskfile.yml: task run was invoking "python -m src.mcp_template_py" while the Dockerfile and README use "python -m mcp_template_py". Align the Taskfile so "task run" actually works without the src. prefix.
| # Requires a GitHub App token (secrets MCP_RELEASE_WORKFLOW_APP_ID and | ||
| # MCP_RELEASE_WORKFLOW_APP_KEY). The default GITHUB_TOKEN cannot fire | ||
| # downstream workflows on tag push — GitHub explicitly blocks that to prevent | ||
| # infinite workflow recursion. |
There was a problem hiding this comment.
TIL: This was the reason for blocking PAT to trigger downstream workflows. 🤗
There was a problem hiding this comment.
Yep — GITHUB_TOKEN is intentionally barred from triggering downstream workflows to prevent infinite-loop footguns. The GitHub App token dance is the sanctioned escape hatch. 🫠
| uv run pytest --cov=src/mcp_template_py | ||
| ``` | ||
|
|
||
| ## For Fork Maintainers |
There was a problem hiding this comment.
Should we reword "Fork"? I don't think creating a new repo from template repo is a real "Fork"ing.
From claude:
❯ Is creating a new repo from github repo template a fork'ing ?
⏺ No — creating a repo from a template is not a fork.
Key differences:
- Template: new repo starts with a clean history (single initial commit), no link to the source, independent from the start.
- Fork: preserves full git history, stays linked to upstream, and can send/receive PRs via that link.
Use a template when you want a starting point; use a fork when you want to contribute back or track upstream. There was a problem hiding this comment.
Good catch — fixed in 14d28a6. Renamed the section to "When Using This Template" and switched the workflow comments to "in your own repo" so the language covers both the template-copy case (common) and the actual-fork case (contribute-back).
Per review feedback from @glageju on #45: creating a new repo from a GitHub template is not a fork — template copies have no upstream link and start from a clean history. Rename the README section to "When Using This Template" and use "your own repo" / "your copy" in the release workflow comments so the language covers both template consumers (the common case) and actual forks (the contribute-back case).
Prepares the repo to flip from internal to public as a reusable MCP server template.
Summary
lxml>=6.1.0(CVE-2026-41066) andpython-dotenv>=1.2.2(CVE-2026-28684) following the existing pattern forcryptography/python-multipart.pip-auditnow reports 0 vulnerabilities.packageRuledisablingdhi.io/**Docker lookups, which was causing the "Action Required: Fix Renovate Configuration" issue (Action Required: Fix Renovate Configuration #39).claude.yml/claude-code-review.ymlreview workflows so a public fork does not burnANTHROPIC_API_KEYon drive-by PRs.docs/release-playbook.md.SECURITY.mdcasing fixed. NewCONTRIBUTING.mdwith setup + Conventional Commits + DCO sign-off, pointing to the org-level Code of Conduct inStacklokLabs/.github.task runnow usespython -m mcp_template_py(matching the Dockerfile and README) instead of the brokenpython -m src.mcp_template_py.tyupgrade surfaced two pre-existing narrowing issues in the test suite (fixed: switched toisinstance(item, TextContent)andSettings.model_validate).Test plan
task checkpasses locally (lint, format, typecheck, 11 tests pass / 3 integration skipped, bandit 0 issues, pip-audit 0 vulns)pip-audit --ignore-vuln CVE-2026-4539reportsNo known vulnerabilities foundtask runworks end-to-endtask composebuilds against DHI (requiresdocker login dhi.io)After merge
Separate cleanup (will handle after this lands):
mcp,fastmcp,python,template,model-context-protocol