Skip to content
Merged
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
---
id: ADR-0017
title: Adopt source-controlled GitHub governance and CI supply-chain hardening
status: accepted
date: 2026-09-06
locale: en
decision_makers:
- YangSeungHyun
related:
- ADR-0005
- ADR-0016
affected_paths:
- .github/CODEOWNERS
- .github/dependabot.yml
- .github/labeler.yml
- .github/labels.yml
- .github/ISSUE_TEMPLATE/
- .github/workflows/test.yml
- .github/workflows/release.yml
- pyproject.toml
- scripts/export_dev_requirements.py
- tests/unit/test_github_governance.py
- SECURITY.md
tags:
- github
- governance
- supply-chain
- ci
- security
retrospective: false
---

# Adopt source-controlled GitHub governance and CI supply-chain hardening

## Context and Problem Statement

The repository became public on 2026-08-29 and shipped v1.0.0/v1.0.1, but the
day-to-day contributor mechanics that keep a growing issue/PR queue navigable
for a single maintainer were never built out. Labels were the GitHub defaults,
issue templates were legacy Markdown, and there was no Dependabot, no
CODEOWNERS, no path-based auto-labeler, no lint job, and no dependency/security
scan. A prior audit also queried only the classic branch-protection endpoint
and wrongly concluded the repo was unprotected; the repository ruleset API
showed active branch/tag rulesets since 2026-09-02, but their required
status-check names can drift whenever the CI matrix changes.

## Decision Drivers

* One maintainer and one repository: automation must pay for itself without
assuming a team that does not exist yet.
* CI was already mature (multi-OS pytest matrix, coverage floor, scoped mypy
--strict, drift gates, pr-title-check, harness-parity) but had no lint and no
dependency/security scan.
* harness-parity ran a remote `curl | bash` installer -- a supply-chain risk.
* Every "not now" item must carry a written trigger, not a vague "later".

## Considered Options

* Keep hand-triage only -- does not scale past a handful of issues.
* Adopt GitHub-native automation as code (labels, labeler, Dependabot, Issue
Forms) plus lint + dependency-audit CI gates, and sync the ruleset's required
checks to the CI matrix -- chosen.
* Add heavy automation now (mandatory CODEOWNERS review, stale bot, org-wide
rulesets) -- deferred behind explicit preconditions.

## Decision Outcome

Chosen option: **source-controlled GitHub governance + CI supply-chain
hardening**, because it lets issues/PRs self-organize and keeps required checks
honest without over-automating a one-maintainer repository.

* Path-based auto-labeler mapping changed-file globs to `area:*` labels, plus a
source-controlled label taxonomy (`.github/labels.yml`) synced live without
deleting unrelated labels.
* Dependabot for pip and github-actions only, weekly, grouped, targeting
`develop`.
* Structured Issue Forms for bug and feature reports, with `config.yml` routing
questions to Discussions and vulnerabilities to `SECURITY.md`.
* Fast CI gates: ruff lint and `pip-audit --strict`; the Python floor moved from
3.9 to 3.10.
* Supply-chain hardening: the Antigravity `curl | bash` installer was replaced
with a versioned SHA-512-verified artifact; release Actions were pinned to
commit SHAs; the PR-title shell expression injection was removed.
* Branch ruleset `22101891` required checks were synced to the new matrix
(Python 3.10 x3 + `lint` + `dependency-audit` added; Python 3.9 removed) and
re-verified through the effective-rules API.
* A dormant CODEOWNERS was drafted but not wired to required review. Live
Discussions, Dependabot security updates/alerts, secret scanning + push
protection, and private vulnerability reporting were enabled.

## Consequences

* Good: new issues/PRs arrive pre-labeled; dependency bumps arrive as routine,
reviewable PRs; CI fails fast on lint and known vulnerabilities; protected
branches can no longer be silently blocked by a stale required-check name.
* Bad: ruleset required checks are GitHub-side settings that cannot live fully
in code, so a future CI job rename still requires a manual ruleset sync; the
trigger for a read-only verification script is recorded in `improvements.md`.

## Confirmation

pytest (562 passed) plus branch coverage, ruff check, scoped mypy --strict,
`sync_version.py --check`, and `verify_examples.py --check` all passed. The
ruleset and effective-rules APIs confirm the new required checks are active for
`develop`.

## Revisit Triggers

* A second qualified maintainer appears -> enable CODEOWNERS required review.
* A second repository repeats the same operations -> org-level rulesets,
reusable workflows, audit export, and taxonomy.
* A real abandoned-issue backlog accumulates -> stale bot.
* CI check-name drift recurs -> ruleset-as-code or a read-only verification
script.
43 changes: 43 additions & 0 deletions docs/decisions/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
- [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md)
- [ADR-0015 — Structured JSON stderr logging with correlation IDs for uncaught errors](0015-structured-json-stderr-logging-with-correlation-ids-for-uncaught-errors.md)
- [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md)
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### Superseded
- [ADR-0003 — Localize only index.py's generated strings, not agent-composed text](0003-localize-only-index-py-s-generated-strings-not-agent-composed-text.md)
Expand All @@ -38,6 +39,9 @@
- [ADR-0008 — Deterministic CHECK policy exceptions: schema-validated, annotate-only, never suppress](0008-check-exceptions-annotate-only.md)
- [ADR-0013 — Two-stage ReDoS defense for CHECK's author-supplied constraint regexes](0013-two-stage-redos-defense-for-check-s-author-supplied-constraint-regexes.md)

### ci
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### cli
- [ADR-0009 — --json is a documented no-op; CLI output is always JSON](0009-json-flag-always-json-contract.md)

Expand Down Expand Up @@ -75,9 +79,13 @@
### git-flow
- [ADR-0005 — Adopt Git Flow with direct-tag release automation](0005-adopt-git-flow-with-direct-tag-release-automation.md)

### github
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### governance
- [ADR-0008 — Deterministic CHECK policy exceptions: schema-validated, annotate-only, never suppress](0008-check-exceptions-annotate-only.md)
- [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md)
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### graph
- [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md)
Expand Down Expand Up @@ -115,9 +123,11 @@
### security
- [ADR-0013 — Two-stage ReDoS defense for CHECK's author-supplied constraint regexes](0013-two-stage-redos-defense-for-check-s-author-supplied-constraint-regexes.md)
- [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md)
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### supply-chain
- [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md)
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### typing
- [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md)
Expand Down Expand Up @@ -148,17 +158,34 @@
### `.claude-plugin/plugin.json`
- [ADR-0004 — Adapter packaging: manifest-only directories, install-time symlinks, verified formats](0004-adapter-packaging-manifest-only-directories-install-time-symlinks-verified-formats.md)

### `.github/CODEOWNERS`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `.github/ISSUE_TEMPLATE/`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `.github/PULL_REQUEST_TEMPLATE.md`
- [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md)

### `.github/dependabot.yml`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `.github/labeler.yml`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `.github/labels.yml`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `.github/workflows/`
- [ADR-0005 — Adopt Git Flow with direct-tag release automation](0005-adopt-git-flow-with-direct-tag-release-automation.md)

### `.github/workflows/release.yml`
- [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md)
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `.github/workflows/test.yml`
- [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md)
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `.gitignore`
- [ADR-0004 — Adapter packaging: manifest-only directories, install-time symlinks, verified formats](0004-adapter-packaging-manifest-only-directories-install-time-symlinks-verified-formats.md)
Expand All @@ -178,6 +205,7 @@
### `SECURITY.md`
- [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md)
- [ADR-0016 — Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key](0016-sign-release-artifacts-with-github-artifact-attestation-instead-of-a-managed-signing-key.md)
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `adapters/`
- [ADR-0004 — Adapter packaging: manifest-only directories, install-time symlinks, verified formats](0004-adapter-packaging-manifest-only-directories-install-time-symlinks-verified-formats.md)
Expand All @@ -200,6 +228,12 @@
### `project-roadmap.md`
- [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md)

### `pyproject.toml`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `scripts/export_dev_requirements.py`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `scripts/sync_version.py`
- [ADR-0005 — Adopt Git Flow with direct-tag release automation](0005-adopt-git-flow-with-direct-tag-release-automation.md)

Expand Down Expand Up @@ -334,6 +368,9 @@
### `tests/unit/test_contracts.py`
- [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md)

### `tests/unit/test_github_governance.py`
- [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)

### `tests/unit/test_graph_command.py`
- [ADR-0011 — Expose ADR relationships as Mermaid and SVG navigation artifacts](0011-adr-relationship-graph-public-readiness.md)

Expand All @@ -348,6 +385,7 @@

## Chronological (newest first)

- 2026-09-06 — [ADR-0017 — Adopt source-controlled GitHub governance and CI supply-chain hardening](0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md)
- 2026-09-01 — [ADR-0012 — Atomic writes and cross-platform directory locking for CREATE, EXCEPTION, and SUPERSEDE](0012-atomic-writes-and-cross-platform-directory-locking-for-create-exception-and-supersede.md)
- 2026-09-01 — [ADR-0013 — Two-stage ReDoS defense for CHECK's author-supplied constraint regexes](0013-two-stage-redos-defense-for-check-s-author-supplied-constraint-regexes.md)
- 2026-09-01 — [ADR-0014 — Typed result contracts and a scoped mypy --strict CI gate](0014-typed-result-contracts-and-a-scoped-mypy-strict-ci-gate.md)
Expand Down Expand Up @@ -386,6 +424,8 @@
- ADR-0015 "Structured JSON stderr logging with correlation IDs for uncaught errors" related to: ADR-0009 "--json is a documented no-op; CLI output is always JSON"
- ADR-0016 "Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key" related to: ADR-0005 "Adopt Git Flow with direct-tag release automation"
- ADR-0016 "Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key" related to: ADR-0011 "Expose ADR relationships as Mermaid and SVG navigation artifacts"
- ADR-0017 "Adopt source-controlled GitHub governance and CI supply-chain hardening" related to: ADR-0005 "Adopt Git Flow with direct-tag release automation"
- ADR-0017 "Adopt source-controlled GitHub governance and CI supply-chain hardening" related to: ADR-0016 "Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key"

```mermaid
flowchart LR
Expand All @@ -405,6 +445,7 @@ flowchart LR
ADR_0014["ADR-0014<br/>Typed result contracts and a scoped mypy --strict CI gate"]
ADR_0015["ADR-0015<br/>Structured JSON stderr logging with correlation IDs for uncaught errors"]
ADR_0016["ADR-0016<br/>Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key"]
ADR_0017["ADR-0017<br/>Adopt source-controlled GitHub governance and CI supply-chain hardening"]
ADR_0006 -.->|related| ADR_0003
ADR_0006 -->|supersedes| ADR_0003
ADR_0011 -.->|related| ADR_0001
Expand All @@ -419,4 +460,6 @@ flowchart LR
ADR_0015 -.->|related| ADR_0009
ADR_0016 -.->|related| ADR_0005
ADR_0016 -.->|related| ADR_0011
ADR_0017 -.->|related| ADR_0005
ADR_0017 -.->|related| ADR_0016
```
3 changes: 3 additions & 0 deletions docs/decisions/relationships.mmd
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ flowchart LR
ADR_0014["ADR-0014<br/>Typed result contracts and a scoped mypy --strict CI gate"]
ADR_0015["ADR-0015<br/>Structured JSON stderr logging with correlation IDs for uncaught errors"]
ADR_0016["ADR-0016<br/>Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key"]
ADR_0017["ADR-0017<br/>Adopt source-controlled GitHub governance and CI supply-chain hardening"]
ADR_0006 -.->|related| ADR_0003
ADR_0006 -->|supersedes| ADR_0003
ADR_0011 -.->|related| ADR_0001
Expand All @@ -29,3 +30,5 @@ flowchart LR
ADR_0015 -.->|related| ADR_0009
ADR_0016 -.->|related| ADR_0005
ADR_0016 -.->|related| ADR_0011
ADR_0017 -.->|related| ADR_0005
ADR_0017 -.->|related| ADR_0016
Loading
Loading