v0.5.0
Added — codesteward-graph
PyProjectParser— extractsdepends_onedges frompyproject.tomlfiles, supporting
PEP 621[project.dependencies],[project.optional-dependencies], and Poetry
[tool.poetry.dependencies]. Scans allpyproject.tomlfiles in the repo tree (handles
uv workspaces and monorepos). Wired intoGraphBuilder.build_graph()alongside the
existingPackageJsonParser. Thedependencyquery type now returns results for Python
projects.
Fixed — codesteward-graph
- GraphQLite:
dependencyquery returned null package names — the query template read
pkg.namefrom the target node via a traversal, but GraphQLite does not resolve target
node properties through traversal patterns (the same limitation already worked around in
thereferentialquery). Rewrote the template to readtarget_namefrom edge properties.
The same fix was applied to thesemanticquery'ssink_name/sink_filefields. - GraphQLite:
delete_file_nodesdid not filter by$paramin MATCH patterns —
$paraminterpolation into MATCH property patterns is unreliable in GraphQLite. The
method was inconsistent withcount_nodes/delete_repo_datawhich already use literal
values via_cypher_escape. Rewrotedelete_file_nodesto match. This was silently
breaking incremental rebuilds. - GraphQLite: named query templates used
$paramin MATCH patterns — tenant/repo/filter
isolation was unreliable inlexical,referential,semantic, anddependency
queries. Rewrote each template as a builder function that constructs Cypher with escaped
literal values and moves filters to WHERE clauses. - GraphQLite:
write_augment_edgecreated duplicate edges on re-invocation — it used
CREATEinstead ofMERGEand did not dedup byedge_id. Added a delete-before-create
pattern so re-writing an augment edge with the sameedge_idis idempotent (matches the
upsert behavior of Neo4j and JanusGraph). - GraphQLite:
semanticquery usedNOT r.sanitized— SQLite stores booleans as
integers andNOT <int>semantics were not reliable through GraphQLite's Cypher
translation. Changed to explicitr.sanitized = 0. - GraphQLite: full rebuild duplicated all edges —
write_edgesusesCREATE(notMERGE)
for relationship creation, so consecutive full rebuilds doubled the edge count with each run.
Addeddelete_repo_data(tenant_id, repo_id)to theGraphBackendABC and all three
implementations (Neo4j, JanusGraph, GraphQLite).GraphBuilder.build_graph()now clears
existing repo data before every full (non-incremental) rebuild. - Cross-file CALLS resolution 0% on codebases with shared method names —
_resolve_call_targets()marked all ambiguous names (e.g.parse, defined in 13+ parsers)
as unresolvable. Added same-file disambiguation: when a callee name is globally ambiguous,
resolve to the definition in the caller's own file. This recovers intra-file method calls
that were previously left as unresolved external nodes. - GUARDED_BY edges emitted for non-auth Python decorators —
@property,
@staticmethod,@abstractmethod,@dataclass,@pytest.fixture, and ~30 other standard
Python decorators were incorrectly producingguarded_byedges. Added_NON_AUTH_DECORATORS
blocklist to the Python parser; only actual auth decorators (@login_required,
Depends(...), etc.) now emit guard edges. build_graphsummary reportedlanguage: typescriptfor all codebases — thelanguage
parameter defaulted to"typescript"and was echoed into the summary unchanged. Added
_detect_dominant_language()which counts file-node languages and returns the most common
one. The summary now reflects the actual codebase language.
Security / CI
- CI/CD security hardening — introduced a comprehensive CI pipeline based on the
OpenSSF / SLSA guidance:- Every job now runs behind
step-security/harden-runner(audit mode) and uses
persist-credentials: falsewith scoped permissions. - New checks: Semgrep (p/python, p/security-audit, p/owasp-top-ten, p/docker),
Hadolint, zizmor (GitHub Actions static analysis, with ref-pin policy in
.github/zizmor.yml), CodeQL security-extended (push-to-main),pip-audit
againstuv export --frozen, Trivy container scan that gates the release,
dependency-review on PRs, conventional commits, license headers
(skywalking-eyes, check-only), markdown-lint, OpenSSF Scorecard, and a
weekly scheduled scan workflow (CodeQL, pip-audit, Trivy image, gitleaks). - Release workflow now builds
linux/amd64locally, scans with Trivy (HIGH/CRITICAL
gate), pushes multi-arch with SLSA provenance (provenance: mode=max) and SBOM,
signs with cosign keyless via GitHub OIDC, and attachestrivy-report.json+
sbom.cdx.jsonto the GitHub Release. - Added
.github/CODEOWNERS,.github/dco.yml(probot/dco),SECURITY.md,
.licenserc.yaml,renovate.json(withpinDigests: true), and
docs/ci-security-hardening.md.
- Every job now runs behind
- Container base patched against Debian openssl CVE-2026-28390 — final stage of
Dockerfile.mcpnow runsapt-get upgrade -yon top ofpython:3.12-slimto pick up
Debian security updates that lag the upstream image rebuild cadence. - Narrowly-scoped
.trivyignorefor bundledcodesteward-taintbinary — the upstream
v0.1.0binary was built with Go 1.22.12 and inherits nine Go stdlib CVEs that cannot be
fixed from this repo. Documented each suppression with a TODO to drop once upstream ships
a Go ≥ 1.26.2 rebuild. Operators who do not need taint analysis can
--build-arg TAINT_VERSION=noneto remove the binary and skip the suppressions. - Python runtime CVEs resolved — bumped locked
cryptography46.0.5 → 46.0.7
(CVE-2026-34073, CVE-2026-39892),pygments2.19.2 → 2.20.0 (CVE-2026-4539), and
pytest9.0.2 → 9.0.3 (CVE-2025-71176) viauv lock --upgrade-package.
Container image
docker pull ghcr.io/codesteward/codesteward-graph:0.5.0Image is signed with cosign keyless via GitHub OIDC.
Verify with:
cosign verify ghcr.io/codesteward/codesteward-graph:0.5.0 \
--certificate-identity-regexp 'https://github.com/Codesteward/codesteward/.*' \
--certificate-oidc-issuer https://token.actions.githubusercontent.com