Skip to content

oss-baseline@v1

A minimal OSS-hygiene baseline — the documents and conventions most open-source repositories are expected to follow. Adopt it with:

extends:
- alint://bundled/oss-baseline@v1

Defaults are deliberately non-blocking (info for community-doc recommendations, warning for missing README/LICENSE, error for unambiguous bugs like committed merge markers or bidi controls). Upgrade severity in your own config when you’re ready to enforce.

An open-source repo should have a README at the root.

An open-source repo should declare a license at the root.

LICENSE file is suspiciously short; paste the full license text rather than a stub.

README is very short; add a brief description and at least a usage / install section.

Consider adding a SECURITY.md so vulnerability reporters know where to disclose.

SECURITY.md is suspiciously short; describe how to report vulnerabilities and the supported-versions policy.

Consider configuring Dependabot or Renovate to keep dependencies and actions up to date.

Consider adding a CODEOWNERS file so PR reviews are auto-routed.

CODEOWNERS exists but appears empty; add at least one ownership rule (e.g. * @org/team).

Consider adding a CODE_OF_CONDUCT.md.

Most OSS repos should have a .gitignore to keep build artefacts and secrets out of git.

Merge-conflict markers must not be committed.

Unicode bidi override characters are a code-review hazard; reject.

The full ruleset definition is committed at crates/alint-dsl/rulesets/v1/oss-baseline.yml in the alint repo (the snapshot below is generated verbatim from that file).

# alint://bundled/oss-baseline@v1
#
# A minimal OSS-hygiene baseline — the documents and conventions
# most open-source repositories are expected to follow. Adopt it
# with:
#
# extends:
# - alint://bundled/oss-baseline@v1
#
# Defaults are deliberately non-blocking (`info` for community-doc
# recommendations, `warning` for missing README/LICENSE, `error` for
# unambiguous bugs like committed merge markers or bidi controls).
# Upgrade severity in your own config when you're ready to enforce.
version: 1
rules:
# --- Required top-level documents ---------------------------------
- id: oss-readme-exists
kind: file_exists
paths: ["README.md", "README", "README.rst"]
root_only: true
level: warning
message: "An open-source repo should have a README at the root."
policy_url: "https://opensource.guide/starting-a-project/#writing-a-readme"
# v0.9.18: case-variation broadening — `LICENSE.TXT` (uppercase
# extension) is dotnet/runtime's canonical filename and was rejected
# before. `LICENSE.rst` covers Python projects that ship the license
# in reST. `COPYING.md` / `COPYING.txt` cover less common variants
# surfaced across the case-study corpus. Filesystem globs are
# case-sensitive on most platforms; the brace expansion enumerates
# the case-variants explicitly.
- id: oss-license-exists
kind: file_exists
paths:
- "LICENSE"
- "LICENSE.{md,txt,TXT,rst}"
- "LICENSE-APACHE"
- "LICENSE-MIT"
- "LICENSE-BSD"
- "LICENSE-MPL"
- "COPYING"
- "COPYING.{md,txt}"
root_only: true
level: warning
message: "An open-source repo should declare a license at the root."
policy_url: "https://opensource.guide/legal/#which-open-source-license-is-appropriate-for-my-project"
- id: oss-license-non-empty
# A zero-byte LICENSE passes `oss-license-exists` while
# providing zero legal guidance. 200 bytes is a safely
# permissive floor — the shortest common OSS license
# (MIT) runs about 1 KiB once you include the copyright
# notice. Path list mirrors `oss-license-exists` so both
# rules check the same set.
kind: file_min_size
paths:
- "LICENSE"
- "LICENSE.{md,txt,TXT,rst}"
- "LICENSE-APACHE"
- "LICENSE-MIT"
- "LICENSE-BSD"
- "LICENSE-MPL"
- "COPYING"
- "COPYING.{md,txt}"
min_bytes: 200
level: info
message: "LICENSE file is suspiciously short; paste the full license text rather than a stub."
- id: oss-readme-non-stub
# Catches the classic "# Project\n\nTODO\n" README. Three
# lines is intentionally gentle — passes for most real
# READMEs without nagging early-stage repos.
kind: file_min_lines
paths: ["README.md", "README", "README.rst"]
min_lines: 3
level: info
message: "README is very short; add a brief description and at least a usage / install section."
- id: oss-security-policy-exists
kind: file_exists
paths: ["SECURITY.md", ".github/SECURITY.md", "docs/SECURITY.md"]
level: info
message: "Consider adding a SECURITY.md so vulnerability reporters know where to disclose."
policy_url: "https://docs.github.com/en/code-security/getting-started/adding-a-security-policy-to-your-repository"
- id: oss-security-policy-non-empty
# Mirrors OpenSSF Scorecard's Security-Policy check: the file
# has to actually contain reporting guidance, not be a stub.
# 200 bytes is the same floor we use for LICENSE.
kind: file_min_size
paths: ["SECURITY.md", ".github/SECURITY.md", "docs/SECURITY.md"]
min_bytes: 200
level: info
message: "SECURITY.md is suspiciously short; describe how to report vulnerabilities and the supported-versions policy."
policy_url: "https://github.com/ossf/scorecard/blob/main/docs/checks.md#security-policy"
- id: oss-dependency-update-tool
# OpenSSF Scorecard's Dependency-Update-Tool check. Either
# Dependabot or Renovate satisfies it; both are config-only
# (no extra Rust deps, no engine work). The wide path list
# covers every blessed location each tool reads.
kind: file_exists
paths:
- ".github/dependabot.yml"
- ".github/dependabot.yaml"
- "renovate.json"
- "renovate.json5"
- ".renovaterc"
- ".renovaterc.json"
- ".github/renovate.json"
- ".github/renovate.json5"
level: info
message: "Consider configuring Dependabot or Renovate to keep dependencies and actions up to date."
policy_url: "https://github.com/ossf/scorecard/blob/main/docs/checks.md#dependency-update-tool"
- id: oss-codeowners-exists
# OpenSSF Scorecard's Code-Review signal. Branch-protection
# itself is GitHub-API state alint can't see, but a CODEOWNERS
# file is the on-disk piece — it auto-routes review requests
# and signals review expectations to contributors.
kind: file_exists
paths: ["CODEOWNERS", ".github/CODEOWNERS", "docs/CODEOWNERS"]
level: info
message: "Consider adding a CODEOWNERS file so PR reviews are auto-routed."
policy_url: "https://github.com/ossf/scorecard/blob/main/docs/checks.md#code-review"
- id: oss-codeowners-non-empty
# Catches the empty / placeholder CODEOWNERS that satisfies
# Scorecard's existence check while doing nothing useful.
# 10 bytes is the smallest meaningful pattern + owner pair.
kind: file_min_size
paths: ["CODEOWNERS", ".github/CODEOWNERS", "docs/CODEOWNERS"]
min_bytes: 10
level: info
message: "CODEOWNERS exists but appears empty; add at least one ownership rule (e.g. `* @org/team`)."
- id: oss-code-of-conduct-exists
kind: file_exists
paths: ["CODE_OF_CONDUCT.md", ".github/CODE_OF_CONDUCT.md", "docs/CODE_OF_CONDUCT.md"]
level: info
message: "Consider adding a CODE_OF_CONDUCT.md."
policy_url: "https://www.contributor-covenant.org/"
- id: oss-gitignore-exists
kind: file_exists
paths: .gitignore
root_only: true
level: info
message: "Most OSS repos should have a .gitignore to keep build artefacts and secrets out of git."
# --- Unambiguous bugs (errors) -----------------------------------
- id: oss-no-merge-conflict-markers
kind: no_merge_conflict_markers
paths:
include: ["**/*.md", "**/*.txt", "**/*.toml", "**/*.yml", "**/*.yaml", "**/*.json"]
level: error
message: "Merge-conflict markers must not be committed."
- id: oss-no-bidi-controls
# Trojan Source (CVE-2021-42574): bidirectional override characters
# can make source code read differently from how it executes.
kind: no_bidi_controls
paths:
include: ["**/*.md", "**/*.txt", "**/*.toml", "**/*.yml", "**/*.yaml", "**/*.json"]
level: error
message: "Unicode bidi override characters are a code-review hazard; reject."
policy_url: "https://trojansource.codes/"
# --- Hygiene (info-level, auto-fixable) --------------------------
- id: oss-final-newline
kind: final_newline
paths: ["**/*.md", "**/*.txt", "**/*.toml", "**/*.yml", "**/*.yaml"]
level: info
fix:
file_append_final_newline: {}
- id: oss-no-trailing-whitespace
kind: no_trailing_whitespace
paths: ["**/*.md", "**/*.txt", "**/*.toml", "**/*.yml", "**/*.yaml"]
level: info
fix:
file_trim_trailing_whitespace: {}