Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 10 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
# PolicyChecks

[![Immutable releases](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/immutable-releases.svg)](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/immutable-releases/proof.json) [![SHA pinning](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/sha-pinning-required.svg)](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/sha-pinning-required/proof.json) [![Secret scanning](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/secret-scanning-enabled.svg)](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/secret-scanning-enabled/proof.json) [![Dependabot alerts](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/dependabot-alerts-enabled.svg)](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/dependabot-alerts-enabled/proof.json) [![Dependency graph](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/dependency-graph-enabled.svg)](https://policychecks.reponomics.org/github/reponomics/PolicyChecks/dependency-graph-enabled/proof.json)

PolicyChecks is a GitHub App-backed badge service and validation endpoint for repository settings that ordinary public badge services cannot verify. It exposes badge SVG, Shields-compatible JSON, and proof JSON endpoints for repository administration and security checks. This gives maintainers a convenient way to show that a project not only follows best practices, but that these practices are enforced policies at the repository settings level. This fills a modest gap in the badge ecosystem between excellent services like shields.io (which does not have the permissions to report on these facts) and OSSF Scorecard (which does take into account many of these same conditions, but does not expose individual setting-level endpoints).

| Check | Claim ID | Passing result | Other results |
| --- | --- | --- | --- |
| Immutable releases | `immutable-releases` | `enabled` | `disabled` or `unknown` |
| Full SHA-pinned GitHub Actions | `sha-pinning-required` | `required` | `not required` or `unknown` |
| Secret scanning | `secret-scanning-enabled` | `enabled` | `disabled` or `unknown` |
| Dependabot alerts | `dependabot-alerts-enabled` | `enabled` | `disabled` or `unknown` |
| Dependency graph | `dependency-graph-enabled` | `enabled` | `disabled` or `unknown` |
| Check | Claim ID | Passing result | Other results |
| ------------------ | --------------------------- | -------------- | --------------------------- |
| Immutable releases | `immutable-releases` | `enforced` | `not enforced` or `unknown` |
| SHA pinning | `sha-pinning-required` | `enforced` | `not enforced` or `unknown` |
| Secret scanning | `secret-scanning-enabled` | `enforced` | `not enforced` or `unknown` |
| Dependabot alerts | `dependabot-alerts-enabled` | `enforced` | `not enforced` or `unknown` |
| Dependency graph | `dependency-graph-enabled` | `enforced` | `not enforced` or `unknown` |

## Endpoints

Expand All @@ -26,7 +28,7 @@ Use the SVG endpoint for badges, the Shields-compatible JSON endpoint for badge
```markdown
[![Immutable releases](https://policychecks.reponomics.org/github/OWNER/REPO/immutable-releases.svg)](https://policychecks.reponomics.org/github/OWNER/REPO/immutable-releases/proof.json)

[![SHA-pinned actions](https://policychecks.reponomics.org/github/OWNER/REPO/sha-pinning-required.svg)](https://policychecks.reponomics.org/github/OWNER/REPO/sha-pinning-required/proof.json)
[![SHA pinning](https://policychecks.reponomics.org/github/OWNER/REPO/sha-pinning-required.svg)](https://policychecks.reponomics.org/github/OWNER/REPO/sha-pinning-required/proof.json)

[![Secret scanning](https://policychecks.reponomics.org/github/OWNER/REPO/secret-scanning-enabled.svg)](https://policychecks.reponomics.org/github/OWNER/REPO/secret-scanning-enabled/proof.json)

Expand Down
84 changes: 84 additions & 0 deletions docs/ADR/0001-policy-evidence-model.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
# ADR 0001: Policy Evidence Model

## Status

Accepted

## Context

PolicyChecks badge labels are intentionally short. They name the security posture a maintainer wants to show, not every GitHub API surface that can prove it.

Some GitHub settings can be reported directly at repository scope. Other settings may be governed by organization or enterprise policy, such as an attached code security configuration. If badge names try to encode every evidence source, they become too qualified to be useful. If proof responses hide the evidence source, users cannot tell why a badge passed, failed, or returned `unknown`.

PolicyChecks also needs to avoid fuzzy claims. It should report GitHub settings and policy surfaces, not infer posture from repository files, generated artifacts, or indirect feature availability.

## Decision

Badge labels remain user-facing and concise:

- `dependency graph`
- `secret scanning`
- `Dependabot alerts`
- `SHA pinning`

Badge result messages use policy language: `enforced`, `not enforced`, or `unknown`. GitHub-native values such as `enabled`, `disabled`, `required`, or `not_set` belong in proof details, not in public badge messages.

Proof JSON carries the qualification. Each proof result records the GitHub evidence source, the scope where the evidence was observed, and whether GitHub reported central enforcement.

For personal repositories, checks are evaluated at repository scope.

For organization repositories, checks may be satisfied by repository settings or by organization-managed policy/configuration that applies to the repository. Organization installs should request the permissions needed to inspect those policy surfaces. If an installer cannot approve those permissions, PolicyChecks should report `unknown` rather than making weaker claims under the same badge name.

Example proof evidence:

```json
{
"evidence": {
"scope": "organization",
"source": "attached_code_security_configuration",
"enforcement": "enforced"
}
}
```

## Evidence Sources

| Source | Meaning | Example |
| --- | --- | --- |
| `repository_setting` | GitHub returned a repository-level setting or repository-scoped status endpoint. | `GET /repos/{owner}/{repo}/actions/permissions` |
| `active_branch_rules` | GitHub returned active rules that apply to a repository branch. | `GET /repos/{owner}/{repo}/rules/branches/{branch}` |
| `attached_code_security_configuration` | GitHub returned a code security configuration that manages the repository. | `GET /repos/{owner}/{repo}/code-security-configuration` |
| `unavailable` | PolicyChecks could not obtain interpretable evidence. | Installation, authorization, rate-limit, or unsupported response failures |

## Evidence Scope

| Scope | Meaning |
| -------------- | ------------------------------------------------------------------ |
| `repository` | The proof comes from a repository setting/status surface. |
| `organization` | The proof comes from an organization-managed policy/configuration. |
| `enterprise` | The proof comes from an enterprise-managed policy/configuration. |
| `unknown` | GitHub did not provide a usable scope. |

## Enforcement

`enforcement` is only included when GitHub exposes enforcement status for the evidence source.

For repository-local settings, absence of `enforcement` means PolicyChecks verified the setting value but did not verify who can change it.

For attached code security configurations, `enforcement` is copied from GitHub's configuration response when available. A pass result for a centrally managed configuration means GitHub returned the configured value; enforcement status still needs to be read separately from `evidence.enforcement` and `details.configuration.enforcement`.

## Consequences

- README stays a summary; technical semantics live in ADRs and claim documentation.
- Badge names do not need org/repo qualifiers.
- Proof JSON must make the evidence source explicit.
- Claims based on generated artifacts, repository file inspection, or indirect feature availability are out of scope unless a later ADR changes this rule.
- Organization governance checks may require broader permissions than repository-only checks.

## Claim Design Rules

1. Prefer direct settings/policy endpoints over file inspection or artifact generation.
2. Keep badge names short when the same posture can be proven by repository or organization evidence.
3. Put evidence source, scope, and enforcement in proof JSON.
4. Return `unknown` when GitHub does not expose the policy surface needed for a confident result.
5. Do not publish claims whose badge label would need to be so qualified that users cannot predict what it means.
Loading
Loading