OpenSSF Scorecard posture
Apothem's OpenSSF Scorecard target and the evidence surfaces used to keep the score improving.
Apothem targets the maximum OpenSSF Scorecard score while keeping the public facade honest about what Scorecard can and cannot infer from a new single-maintainer repository. This document enumerates each check, the evidence surface that backs it, and the control that keeps the posture current.
The live score is at the Scorecard viewer; the badge is in the README header.
Per-check evidence matrix
| Check | Evidence surface | Notes |
|---|---|---|
| Binary-Artifacts | binary-artifacts-sweep.md | Zero executable binaries tracked in source; generated distribution archives stay in dist/. |
| Branch-Protection | branch-protection-ruleset.md | main is protected before public release promotion; force-pushes and deletions are blocked after the fresh release commit lands. |
| CI-Tests | .github/workflows/ci.yml | Pytest matrix, ruff, mypy, Trivy, docs build, and packaging smoke checks. |
| CII-Best-Practices | OpenSSF Best Practices registration | Requires maintainer-side registration at the OpenSSF Best Practices site; this cannot be completed by repository files alone. |
| Code-Review | Branch protection + CODEOWNERS | Pull requests are required for main for everyone except repository admins, and branch protection requires 0 approving reviews while the project has one maintainer (see branch-protection-ruleset.md); Scorecard history remains limited until reviewed PRs exist. |
| Contributors | AUTHORS | A new solo-maintainer project cannot manufacture multi-organization contribution history; this improves naturally as contributors join. |
| Dangerous-Workflow | Workflow audit | No pull_request_target; Actions are SHA-pinned and scoped with explicit permissions. |
| Dependency-Update-Tool | .github/dependabot.yml | Dependabot proposes grouped weekly updates for the GitHub Actions pins, the website, the vsce packager lockfile, the hash-locked CI pip and the pre-commit hooks, and monthly updates for the channel-smoke lockfile; Dependabot security updates cover every detected manifest except the CI dependency and tool closures in scripts/ci/, which scripts/dev/refresh_ci_locks.py regenerates when an alert names a locked package. .gitattributes keeps this one file in GitHub source archives, which a scan in the action's default archive mode reads; the Scorecard workflow runs in git mode and reads it from the clone. |
| Fuzzing | tests/property/ | Hypothesis property tests exercise parser and frontmatter invariants; upstream Scorecard may not credit Hypothesis as a fuzzer integration. |
| License | LICENSE | MIT license at repository root. |
| Maintained | Git history | Current release commit and active workflow cadence demonstrate maintenance; very new repositories may receive an age warning. |
| Packaging | .github/workflows/ | Release, Pages, and npmjs.com workflows producing the sdist, wheel, SBOM, SLSA provenance, and Sigstore signatures. |
| Pinned-Dependencies | Workflow audit + hash-locked requirements | Actions are SHA-pinned; release tooling, the CI pip upgrade, the CI project and test dependencies and the CI tools (ruff, bandit, pip-audit, pip-licenses, pre-commit) install with --require-hashes. The project, test and tool installs read the nine locks in scripts/ci/; the pip upgrade and the release tooling each read a lock of their own, and the package itself is installed by --no-deps -e .. |
| SAST | .github/workflows/codeql.yml | CodeQL security-extended queries across Python and Actions. |
| Security-Policy | SECURITY.md | Coordinated-disclosure policy, supported-version matrix, and response timeline. |
| Signed-Releases | .github/workflows/release.yml | Sigstore keyless signatures, SLSA provenance, SBOM, checksums, and release artifacts. |
| Token-Permissions | Workflow audit | Workflows default to read-only permissions; write scopes are job-local and tied to deployment/package operations. |
| Vulnerabilities | .github/workflows/pip-audit.yml + .github/workflows/dependency-review.yml | Weekly vulnerability scan and CI scan with SARIF upload; the dependency-review gate blocks pull requests that introduce vulnerable or disallowed-license dependencies. The check itself looks up the dependencies it finds in the repository's manifests in OSV, so pip-audit.yml asks OSV too (pip-audit -s osv) and a finding there matches a finding in the check. |
Score interpretation
Scorecard scores each check on a 0-10 scale and the overall score is a weighted mean. Controls that depend on repository history, third-party registration, or contributor diversity are tracked explicitly instead of overclaimed. Drift on any file-controlled check triggers immediate remediation.
The Scorecard workflow runs the action with file_mode: git, so Scorecard reads a clone of the repository. Source archives leave out .github/ (export-ignore in .gitattributes), so the action's default archive mode would hide the workflows from Dangerous-Workflow, Token-Permissions, Pinned-Dependencies, and Packaging.
Pinned-Dependencies stays below 10 by design, for two reasons. The SLSA generator is referenced by its release tag, the sole exception to SHA pinning, because its provenance is anchored on that tag. The evals workflow installs the Claude Code CLI with npm install --global at a version chosen per run. The Python installs Scorecard scans in workflows are hash-locked, local installs of the package itself or wheels built in the same run.
Refresh cadence
- Per-push: Scorecard workflow re-runs on every push to
main. - Weekly: Mondays 02:30 UTC — catches changes in upstream-scoring methodology + new vulnerabilities disclosed against existing pinned deps.
- Per-release: Before public promotion, the maintainer verifies the live Scorecard viewer surface and records any platform-state limits.
References
- OpenSSF Scorecard — upstream project
- Scorecard checks reference — per-check semantics
ossf/scorecard-action— GitHub Actions wrapper- SLSA framework — supply-chain levels (apothem ships at SLSA-3)