| name | enterprise-readiness |
| description | Assess and enhance software projects for enterprise-grade security, quality, and automation. This skill should be used when evaluating projects for production readiness, implementing supply chain security (SLSA, signing, SBOMs), hardening CI/CD pipelines, establishing quality gates, reviewing code or PRs, writing documentation (ADRs, changelogs, migration guides), or pursuing OpenSSF Best Practices Badge. Aligned with OpenSSF Scorecard, Best Practices Badge (all levels), SLSA, and S2C2F. By Netresearch. |
Enterprise Readiness Assessment
When to Use
- Evaluating projects for production/enterprise readiness
- Implementing supply chain security (SLSA, signing, SBOMs)
- Hardening CI/CD pipelines
- Establishing quality gates
- Pursuing OpenSSF Best Practices Badge (Passing/Silver/Gold)
- Reviewing code or PRs for quality
- Writing ADRs, changelogs, or migration guides
- Configuring Git hooks or CI pipelines
MANDATORY Requirements
CRITICAL: The following are NOT optional. Every project MUST have ALL of these. Do not skip any.
README Badges (MANDATORY)
Every project README.md MUST display these badges at the top, in this order:
<!-- Row 1: CI/Quality -->
[](https://github.com/ORG/REPO/actions/workflows/ci.yml)
[](https://codecov.io/gh/ORG/REPO)
<!-- Row 2: Security (MANDATORY) -->
[](https://securityscorecards.dev/viewer/?uri=github.com/ORG/REPO)
[](https://www.bestpractices.dev/projects/PROJECT_ID)
| Badge | URL Pattern | MANDATORY |
|---|
| CI Status | github.com/ORG/REPO/actions/workflows/ci.yml/badge.svg | YES |
| Codecov | codecov.io/gh/ORG/REPO/graph/badge.svg | YES |
| OpenSSF Scorecard | api.securityscorecards.dev/projects/github.com/ORG/REPO/badge | YES |
| OpenSSF Best Practices | www.bestpractices.dev/projects/PROJECT_ID/badge | YES |
CI/CD Workflows (MANDATORY)
Every GitHub project MUST have these workflows in .github/workflows/:
| Workflow | File | Purpose | MANDATORY |
|---|
| CI | ci.yml | Build, test, lint | YES |
| CodeQL | codeql.yml | Security scanning | YES |
| Scorecard | scorecard.yml | OpenSSF Scorecard | YES |
| Dependency Review | dependency-review.yml | PR CVE check | YES |
CI Must Include (MANDATORY)
| Requirement | Implementation | MANDATORY |
|---|
| Coverage upload | codecov/codecov-action after tests | YES |
| Security audit | composer audit / npm audit / govulncheck | YES |
| SHA-pinned actions | All actions use full SHA with version comment | YES |
Supply Chain Security (MANDATORY for Releases)
Supply chain security controls MUST block releases when violated.
| Control | Implementation | Blocks Release? |
|---|
| SLSA Provenance | slsa-github-generator workflow | YES - no release without attestation |
| Signed Tags | git tag -s before gh release create | YES - unsigned tags rejected |
| SBOM Generation | anchore/sbom-action or cyclonedx | YES - SBOM required for compliance |
| Dependency Audit | composer audit / npm audit fails CI | YES - CVEs block merge |
Release Workflow Order (MANDATORY)
Supply chain artifacts MUST be generated in this order:
1. CI passes (tests, lint, security audit)
↓
2. Create SIGNED tag locally: git tag -s vX.Y.Z
↓
3. Push signed tag: git push origin vX.Y.Z
↓
4. Create release on existing tag: gh release create vX.Y.Z
↓
5. SLSA provenance workflow triggers (workflow_run)
↓
6. Provenance attestation uploaded to release
↓
7. SBOM generated and uploaded
NEVER use gh release create without a pre-existing signed tag - this creates unsigned tags.
CI Integration for Supply Chain
Add to .github/workflows/release.yml:
- name: Security Audit
run: |
composer audit --format=plain || exit 1
npm audit --audit-level=high || exit 1
- name: Generate SBOM
uses: anchore/sbom-action@v0
with:
artifact-name: sbom.spdx.json
output-file: sbom.spdx.json
- name: Upload SBOM to release
run: gh release upload ${{ github.ref_name }} sbom.spdx.json
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Verification of Supply Chain Artifacts
Before announcing a release, verify:
See references/slsa-provenance.md for detailed SLSA implementation guide.
OpenSSF Registration (MANDATORY)
- Register at bestpractices.dev: https://www.bestpractices.dev/en/projects/new
- Note the Project ID assigned after registration
- Add badge to README with correct PROJECT_ID
- Run Scorecard workflow to generate initial score
Codecov Setup (MANDATORY)
- Enable Codecov for the repository at codecov.io
- Collect coverage from ALL test suites (not just unit tests):
| Test Suite | Coverage Command | Output File | MANDATORY |
|---|
| Unit | phpunit -c UnitTests.xml --coverage-clover | .Build/coverage/unit.xml | YES |
| Integration | phpunit -c IntegrationTests.xml --coverage-clover | .Build/coverage/integration.xml | YES |
| E2E | phpunit -c E2ETests.xml --coverage-clover | .Build/coverage/e2e.xml | YES |
| Functional | phpunit -c FunctionalTests.xml --coverage-clover | .Build/coverage/functional.xml | YES |
| JavaScript | npm run test:coverage | coverage/lcov.info | YES (if JS exists) |
- Upload ALL coverage files to Codecov:
- uses: codecov/codecov-action@SHA
with:
token: ${{ secrets.CODECOV_TOKEN }}
files: .Build/coverage/unit.xml,.Build/coverage/integration.xml,.Build/coverage/e2e.xml,coverage/lcov.info
fail_ci_if_error: false
CODECOV_TOKEN (MANDATORY)
Never rely on tokenless uploads. They fail for protected branches and are unreliable.
| Requirement | Implementation | Why |
|---|
| Token in secrets | Add CODECOV_TOKEN to repo or org secrets | Authentication |
| Token in workflow | token: ${{ secrets.CODECOV_TOKEN }} | Required for protected branches |
| Org-level secret | Preferred for consistency across repos | Single point of management |
Failure without token:
Upload failed: {"message":"Token required because branch is protected"}
Get token from: https://app.codecov.io/gh/ORG/REPO/settings
Add as org secret (recommended):
gh secret set CODECOV_TOKEN --org netresearch --visibility all
gh secret set CODECOV_TOKEN --repo OWNER/REPO
JavaScript Coverage (MANDATORY for projects with JS/TS)
When a project contains JavaScript or TypeScript files:
-
vitest.config.js MUST include lcov reporter for Codecov:
coverage: {
provider: 'v8',
reporter: ['text', 'json', 'html', 'lcov'],
reportsDirectory: 'coverage',
}
-
CI workflow MUST include JavaScript test job:
- uses: actions/setup-node@SHA
with:
node-version: '22'
- run: npm install
- run: npm run test:coverage
-
Codecov upload MUST include coverage/lcov.info
Verification Checklist
Before marking enterprise-readiness complete, verify ALL:
If any badge shows "unknown", "invalid", or placeholder ID - FIX IT. Do not proceed.
OpenSSF Scorecard Optimization Playbook
Proven playbook to raise OpenSSF Scorecard from ~6.8 to ~9.0. Applied successfully on t3x-rte_ckeditor_image.
Check-by-Check Guide
| Check | Quick Fix | Impact |
|---|
| Token-Permissions | Move all write perms from workflow-level to job-level | 0→10 |
| Branch-Protection | Set required_approving_review_count: 1 + auto-approve + protect release branches | 0→8 |
| Code-Review | Automatic after Branch-Protection fix | 5→10 |
| Security-Policy | Private vulnerability reporting + coordinated disclosure | 4→10 |
| Pinned-Dependencies | SHA-pin all actions (except SLSA generator — see below) | 8→10 |
| Fuzzing | Not practical for PHP/TYPO3 — skip | 0 (accept) |
| CII-Best-Practices | Complete questionnaire at bestpractices.dev | 2→6+ |
Token-Permissions (0→10)
The scorecard flags ANY write permission at the workflow-level. Fix: declare permissions: contents: read (or permissions: {}) at workflow-level, move all write to job-level.
permissions:
contents: read
jobs:
deploy:
permissions:
contents: write
steps: ...
permissions:
contents: read
pull-requests: write
Common violators: pr-quality.yml, release-labeler.yml, create-release.yml.
Branch-Protection (0→8) for Solo Maintainers
Solo-dev projects need required_approving_review_count >= 1 but can't wait for human reviewers. Solution: auto-approve workflow + ruleset.
Default branch ruleset:
gh api repos/OWNER/REPO/rulesets/RULESET_ID -X PUT --input - <<'EOF'
{
"rules": [{
"type": "pull_request",
"parameters": {
"required_approving_review_count": 1,
"dismiss_stale_reviews_on_push": true,
"require_code_owner_review": false,
"require_last_push_approval": true,
"required_review_thread_resolution": true
}
}]
}
EOF
Release branch ruleset (e.g., TYPO3_*, release/*):
gh api repos/OWNER/REPO/rulesets -X POST --input - <<'EOF'
{
"name": "release-branches",
"enforcement": "active",
"target": "branch",
"conditions": {"ref_name": {"include": ["refs/heads/TYPO3_*"], "exclude": []}},
"rules": [
{"type": "deletion"},
{"type": "non_fast_forward"},
{"type": "pull_request", "parameters": {
"required_approving_review_count": 1,
"dismiss_stale_reviews_on_push": true,
"require_code_owner_review": false,
"require_last_push_approval": true,
"required_review_thread_resolution": true,
"allowed_merge_methods": ["merge"]
}},
{"type": "required_status_checks", "parameters": {
"required_status_checks": [{"context": "Build ✓", "integration_id": 15368}],
"strict_required_status_checks_policy": true
}}
]
}
EOF
Also enable enforce_admins via legacy API (scorecard reads this separately from rulesets):
gh api repos/OWNER/REPO/branches/main/protection/enforce_admins -X POST
Pair with pr-quality.yml auto-approve workflow (see github-project skill) that approves non-fork PRs via github-actions[bot].
Codeowner review incompatibility: require_code_owner_review: true is incompatible with bot auto-approve workflows. github-actions[bot] (GITHUB_TOKEN) is not a codeowner — its APPROVED review does not satisfy the codeowner requirement, permanently blocking all PRs. Verified on t3x-rte_ckeditor_image#629. Keep this false when using auto-approve.
Unresolved review threads: required_review_thread_resolution: true will block merge if automated reviewers (Gemini Code Assist, Copilot) leave unresolved threads. Resolve via:
gh api graphql -f query='mutation { resolveReviewThread(input: {threadId: "PRRT_xxx"}) { thread { isResolved } } }'
Remaining scorecard warnings (unfixable for solo maintainer):
required approving review count is 1 — scorecard wants >= 2, impractical without human reviewers
codeowners review is not required — incompatible with bot auto-approve (see above)
Security-Policy (4→10)
The scorecard requires SECURITY.md with:
- Link to private reporting mechanism (not public issues!)
- Response timeline (e.g., 48h acknowledgment, 7d fix)
- Coordinated disclosure process
Template:
## Reporting a Vulnerability
**Please do NOT report security vulnerabilities through public GitHub issues.**
Instead, use [GitHub's private vulnerability reporting](https://github.com/ORG/REPO/security/advisories/new).
We will acknowledge receipt within 48 hours and aim to provide a fix
within 7 days for critical vulnerabilities.
## Coordinated Disclosure
After a fix is released, we will:
1. Publish a GitHub Security Advisory
2. Credit the reporter (unless anonymity is requested)
3. Include the fix in the next release with a CVE identifier if applicable
Enable private vulnerability reporting:
gh api repos/OWNER/REPO/private-vulnerability-reporting -X PUT
SLSA Generator Pinning Exception
The slsa-framework/slsa-github-generator reusable workflow cannot be SHA-pinned. It MUST use @vX.Y.Z tags — the slsa-verifier needs the tag to verify trusted builder identity. This is a known GitHub Actions limitation tracked as slsa-verifier#12.
Accept this as an unavoidable Pinned-Dependencies gap (score stays at 8, not 10).
Checks Not Worth Fixing
| Check | Why Skip |
|---|
| Fuzzing (0) | OSS-Fuzz doesn't support PHP/TYPO3; ROI too low |
| Packaging (-1) | TER publishing isn't detected as a packaging workflow |
| Signed-Releases (-1) | Detection issue — SLSA provenance exists but isn't recognized |
Assessment Workflow
- Discovery: Identify platform (GitHub/GitLab), languages, existing CI/CD
- Scoring: Apply checklists from references based on stack
- Badge Assessment: Check OpenSSF criteria status
- Gap Analysis: List missing controls by severity
- Implementation: Apply fixes using scripts and templates
- Verification: Re-score and compare (see Post-Implementation Verification)
Post-Implementation Verification
MANDATORY: After implementing improvements, re-assess the project to verify gains.
Re-Scoring Workflow
- Record baseline score before making changes (save output)
- Implement improvements following gap analysis priorities
- Re-run full assessment using same criteria
- Compare scores and document delta
Verification Checklist
| Check | Before | After | Delta |
|---|
| OpenSSF Scorecard | _/10 | _/10 | +_ |
| Best Practices Badge | Level | Level | Upgrade? |
| Coverage % | _% | _% | +_% |
| Enterprise Score | _/100 | _/100 | +_ |
Expected Outcomes
| Implementation | Expected Score Impact |
|---|
| Add CI/CD workflows | +10-15 pts |
| Enable Codecov | +5-10 pts |
| Add CodeQL/Scorecard | +10-15 pts |
| SLSA provenance | +5-10 pts |
| Documentation (SECURITY.md, etc.) | +5-10 pts |
Verification Commands
scorecard --repo=github.com/ORG/REPO --format=json
If score did not improve as expected, investigate:
- Did CI workflows run successfully?
- Are badges pointing to correct repository?
- Did changes merge to default branch (required for Scorecard)?
Continuous Improvement
Enterprise readiness is not a one-time achievement. Maintain scores over time.
Scheduled Re-Assessment
| Frequency | Scope | Trigger |
|---|
| Weekly | Badge status check | Automated (CI) |
| Monthly | Scorecard re-run | Scheduled workflow |
| Quarterly | Full enterprise assessment | Manual or milestone |
| Per-release | Supply chain verification | Release workflow |
Automated Monitoring
Add badge health check to CI:
name: Badge Health Check
on:
schedule:
- cron: '0 6 * * 1'
workflow_dispatch:
jobs:
check-badges:
runs-on: ubuntu-latest
steps:
- name: Check Codecov
run: |
BADGE_URL="https://codecov.io/gh/${{ github.repository }}/graph/badge.svg"
curl -sL "$BADGE_URL" | grep -q "unknown" && echo "::warning::Codecov badge shows unknown" || true
- name: Check Scorecard
run: |
SCORE=$(curl -s "https://api.securityscorecards.dev/projects/github.com/${{ github.repository }}" | jq -r '.score // "N/A"')
echo "Current Scorecard: $SCORE/10"
if [ "$SCORE" != "N/A" ] && [ "$(echo "$SCORE < 7" | bc -l)" = "1" ]; then
echo "::warning::Scorecard dropped below 7.0"
fi
Regression Detection
Watch for these warning signs:
| Signal | Detection | Response |
|---|
| Scorecard drop > 1pt | Weekly check | Investigate changed checks |
| Badge shows "unknown" | CI check | Verify token/configuration |
| CVE in dependency | Dependabot/Renovate | Priority update PR |
| Failed security scan | CI workflow | Block release until fixed |
| Coverage drop > 5% | PR check | Require coverage recovery |
Dependency Update Cadence
| Update Type | Frequency | Automation |
|---|
| Security patches | Immediate | Auto-merge if tests pass |
| Minor updates | Weekly | Renovate/Dependabot PR |
| Major updates | Monthly review | Manual approval required |
Dependency CVE Workflow
When assessing enterprise readiness, always run dependency audit as part of discovery:
composer audit
npm audit
pip-audit
govulncheck ./...
CVE Handling Best Practice
Separate dependency updates from code changes:
| PR Type | Content | Why |
|---|
| Code changes | Business logic, bug fixes, features | Reviewable, testable in isolation |
| Dependency updates | composer update, version bumps | Clear diff, easy rollback if issues |
Real-world example from t3x-cowriter review:
- Found 4 CVEs during enterprise assessment
- CVE fixes required
composer update typo3/cms-core typo3/cms-backend
- Kept separate from code fixes (JS bug, AGENTS.md updates) for clean PR history
CVE Severity Response
| Severity | Response Time | Action |
|---|
| CRITICAL | Immediate | Hotfix PR, expedited review |
| HIGH | 24-48 hours | Priority PR, security review |
| MEDIUM | 1 week | Normal PR cycle |
| LOW | Next release | Batch with other updates |
CI Integration
Add dependency audit to CI pipeline:
- name: Security audit
run: composer audit --format=plain
Reference Files (Load Based on Stack)
| Reference | When to Load |
|---|
references/general.md | Always (universal 60 pts) |
references/github.md | GitHub-hosted projects (40 pts) |
references/go.md | Go projects (20 pts) |
references/openssf-badge-silver.md | Pursuing Silver badge |
references/openssf-badge-gold.md | Pursuing Gold badge |
Quality & Process References (Language-Agnostic)
| Reference | When to Load |
|---|
references/code-review.md | Code review, PR quality checks |
references/documentation.md | ADRs, API docs, migration guides, changelogs |
references/ci-patterns.md | CI/CD pipelines, Git hooks, quality gates |
Explicit Content Triggers
When reviewing PRs or code, load references/code-review.md for the comprehensive checklist covering test resource management, state mutation, defensive enum handling, documentation accuracy, and defensive code coverage.
When writing ADRs (Architecture Decision Records), load references/documentation.md for templates, file organization, and required sections (Context, Decision, Consequences, Alternatives).
When writing changelogs or release notes, load references/documentation.md for Keep a Changelog format and conventional commit mapping.
When writing API documentation or migration guides, load references/documentation.md for structure patterns and completeness checklists.
When configuring CI/CD pipelines, load references/ci-patterns.md for comprehensive pipeline structure, job ordering, and quality gates.
When setting up Git hooks (pre-commit/pre-push), load references/ci-patterns.md for the hook division strategy and Lefthook configuration.
When enforcing coverage thresholds, load references/ci-patterns.md for threshold tables and enforcement patterns.
When handling signed commits with rebase-only merge, load references/ci-patterns.md for the local fast-forward merge workflow.
Implementation Guides
| Guide | Purpose |
|---|
references/quick-start-guide.md | Getting started |
references/dco-implementation.md | DCO enforcement |
references/signed-releases.md | Cosign/GPG signing |
references/reproducible-builds.md | Deterministic builds |
references/security-hardening.md | TLS, headers, validation |
references/solo-maintainer-guide.md | N/A criteria justification |
references/branch-coverage.md | Gold 80% branch coverage |
Automation Scripts
| Script | Purpose |
|---|
scripts/verify-badge-criteria.sh | Verify OpenSSF badge criteria |
scripts/check-coverage-threshold.sh | Statement coverage check |
scripts/check-branch-coverage.sh | Branch coverage (Gold) |
scripts/add-spdx-headers.sh | Add SPDX headers (Gold) |
scripts/verify-signed-tags.sh | Tag signature verification |
scripts/verify-review-requirements.sh | PR review requirements |
Document Templates
Templates in assets/templates/:
GOVERNANCE.md - Project governance (Silver)
ARCHITECTURE.md - Technical docs (Silver)
CODE_OF_CONDUCT.md - Contributor Covenant v3.0
SECURITY_AUDIT.md - Security audit (Gold)
BADGE_EXCEPTIONS.md - N/A justifications
CI Workflow Templates
GitHub Actions workflows in assets/workflows/:
| Workflow | Purpose |
|---|
scorecard.yml | OpenSSF Scorecard security analysis |
codeql.yml | Semantic code security scanning |
dependency-review.yml | PR dependency CVE/license check |
slsa-provenance.yml | SLSA Level 3 build attestation |
dco-check.yml | Developer Certificate of Origin |
Copy workflows to .github/workflows/ and pin action versions with SHA hashes.
Scoring Interpretation
| Score | Grade | Status |
|---|
| 90-100 | A | Enterprise Ready |
| 80-89 | B | Production Ready |
| 70-79 | C | Development Ready |
| 60-69 | D | Basic |
| <60 | F | Not Ready |
Code Review Quick Checklist
Before approving PRs, verify (see references/code-review.md for details):
Critical Rules
- NEVER interpolate
${{ github.event.* }} in run: blocks (script injection)
- NEVER guess action versions - always fetch from GitHub API
- ALWAYS use SHA pins for actions with version comments
- ALWAYS verify commit hashes against official tags
Related Skills
| Skill | Purpose |
|---|
go-development | Go code patterns, Makefile interface, testing |
github-project | Repository setup, branch protection, auto-merge |
security-audit | Deep security audits (OWASP, XXE, SQLi) |
git-workflow | Git branching, commits, PR workflows |
Resources
Contributing: Improvements to this skill should be submitted to the source repository:
https://github.com/netresearch/enterprise-readiness-skill