Skip to content

v0.5.0

Choose a tag to compare

@github-actions github-actions released this 15 Apr 17:13

Added — codesteward-graph

  • PyProjectParser — extracts depends_on edges from pyproject.toml files, supporting
    PEP 621 [project.dependencies], [project.optional-dependencies], and Poetry
    [tool.poetry.dependencies]. Scans all pyproject.toml files in the repo tree (handles
    uv workspaces and monorepos). Wired into GraphBuilder.build_graph() alongside the
    existing PackageJsonParser. The dependency query type now returns results for Python
    projects.

Fixed — codesteward-graph

  • GraphQLite: dependency query returned null package names — the query template read
    pkg.name from the target node via a traversal, but GraphQLite does not resolve target
    node properties through traversal patterns (the same limitation already worked around in
    the referential query). Rewrote the template to read target_name from edge properties.
    The same fix was applied to the semantic query's sink_name/sink_file fields.
  • GraphQLite: delete_file_nodes did not filter by $param in MATCH patterns
    $param interpolation into MATCH property patterns is unreliable in GraphQLite. The
    method was inconsistent with count_nodes/delete_repo_data which already use literal
    values via _cypher_escape. Rewrote delete_file_nodes to match. This was silently
    breaking incremental rebuilds.
  • GraphQLite: named query templates used $param in MATCH patterns — tenant/repo/filter
    isolation was unreliable in lexical, referential, semantic, and dependency
    queries. Rewrote each template as a builder function that constructs Cypher with escaped
    literal values and moves filters to WHERE clauses.
  • GraphQLite: write_augment_edge created duplicate edges on re-invocation — it used
    CREATE instead of MERGE and did not dedup by edge_id. Added a delete-before-create
    pattern so re-writing an augment edge with the same edge_id is idempotent (matches the
    upsert behavior of Neo4j and JanusGraph).
  • GraphQLite: semantic query used NOT r.sanitized — SQLite stores booleans as
    integers and NOT <int> semantics were not reliable through GraphQLite's Cypher
    translation. Changed to explicit r.sanitized = 0.
  • GraphQLite: full rebuild duplicated all edgeswrite_edges uses CREATE (not MERGE)
    for relationship creation, so consecutive full rebuilds doubled the edge count with each run.
    Added delete_repo_data(tenant_id, repo_id) to the GraphBackend ABC 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 producing guarded_by edges. Added _NON_AUTH_DECORATORS
    blocklist to the Python parser; only actual auth decorators (@login_required,
    Depends(...), etc.) now emit guard edges.
  • build_graph summary reported language: typescript for all codebases — the language
    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: false with 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
      against uv 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/amd64 locally, 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 attaches trivy-report.json +
      sbom.cdx.json to the GitHub Release.
    • Added .github/CODEOWNERS, .github/dco.yml (probot/dco), SECURITY.md,
      .licenserc.yaml, renovate.json (with pinDigests: true), and
      docs/ci-security-hardening.md.
  • Container base patched against Debian openssl CVE-2026-28390 — final stage of
    Dockerfile.mcp now runs apt-get upgrade -y on top of python:3.12-slim to pick up
    Debian security updates that lag the upstream image rebuild cadence.
  • Narrowly-scoped .trivyignore for bundled codesteward-taint binary — the upstream
    v0.1.0 binary 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=none to remove the binary and skip the suppressions.
  • Python runtime CVEs resolved — bumped locked cryptography 46.0.5 → 46.0.7
    (CVE-2026-34073, CVE-2026-39892), pygments 2.19.2 → 2.20.0 (CVE-2026-4539), and
    pytest 9.0.2 → 9.0.3 (CVE-2025-71176) via uv lock --upgrade-package.

Container image

docker pull ghcr.io/codesteward/codesteward-graph:0.5.0

Image 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