diff --git a/docs/decisions/0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md b/docs/decisions/0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md new file mode 100644 index 0000000..77791e8 --- /dev/null +++ b/docs/decisions/0017-adopt-source-controlled-github-governance-and-ci-supply-chain-hardening.md @@ -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. diff --git a/docs/decisions/README.md b/docs/decisions/README.md index 02c424d..81c7f00 100644 --- a/docs/decisions/README.md +++ b/docs/decisions/README.md @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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 @@ -405,6 +445,7 @@ flowchart LR ADR_0014["ADR-0014
Typed result contracts and a scoped mypy --strict CI gate"] ADR_0015["ADR-0015
Structured JSON stderr logging with correlation IDs for uncaught errors"] ADR_0016["ADR-0016
Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key"] + ADR_0017["ADR-0017
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 @@ -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 ``` diff --git a/docs/decisions/relationships.mmd b/docs/decisions/relationships.mmd index 91fe037..f13530d 100644 --- a/docs/decisions/relationships.mmd +++ b/docs/decisions/relationships.mmd @@ -15,6 +15,7 @@ flowchart LR ADR_0014["ADR-0014
Typed result contracts and a scoped mypy --strict CI gate"] ADR_0015["ADR-0015
Structured JSON stderr logging with correlation IDs for uncaught errors"] ADR_0016["ADR-0016
Sign release artifacts with GitHub Artifact Attestation instead of a managed signing key"] + ADR_0017["ADR-0017
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 @@ -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 diff --git a/docs/decisions/relationships.svg b/docs/decisions/relationships.svg index b267074..7571a90 100644 --- a/docs/decisions/relationships.svg +++ b/docs/decisions/relationships.svg @@ -1,4 +1,4 @@ - + ADR relationship graph Vector export of ADR supersession and related-decision links. @@ -52,32 +52,39 @@ ADR-0016 Sign release artifacts with GitHu... + +ADR-0017 +Adopt source-controlled GitHub go... -ADR-0006 related ADR-0003 +ADR-0006 related ADR-0003 -ADR-0006 supersedes ADR-0003 +ADR-0006 supersedes ADR-0003 -ADR-0011 related ADR-0001 +ADR-0011 related ADR-0001 -ADR-0011 related ADR-0006 +ADR-0011 related ADR-0006 -ADR-0011 related ADR-0008 +ADR-0011 related ADR-0008 -ADR-0011 related ADR-0009 +ADR-0011 related ADR-0009 -ADR-0012 related ADR-0006 +ADR-0012 related ADR-0006 -ADR-0013 related ADR-0002 +ADR-0013 related ADR-0002 -ADR-0013 related ADR-0007 +ADR-0013 related ADR-0007 -ADR-0013 related ADR-0008 +ADR-0013 related ADR-0008 -ADR-0014 related ADR-0009 +ADR-0014 related ADR-0009 -ADR-0015 related ADR-0009 +ADR-0015 related ADR-0009 -ADR-0016 related ADR-0005 +ADR-0016 related ADR-0005 -ADR-0016 related ADR-0011 +ADR-0016 related ADR-0011 + +ADR-0017 related ADR-0005 + +ADR-0017 related ADR-0016