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
33 changes: 31 additions & 2 deletions config/README.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -175,8 +175,17 @@ REST API.
standing push right.

| Integration ids 56611 (codacy), 827041 (gitar-bot), 254 (codecov), 2740 (renovate), 57789 (advanced-security), 1561, 85455, 946600
| R1/R4 removals, advanced-security needs no bypass, the last three are
unresolved (owner decision O5).
| R1/R4 removals, advanced-security needs no bypass. Re-swept 2026-09-20 across
all 453 repos: no active ruleset grants bypass to any uninstalled app. 1561 and
85455 have no matching app in either estate; both survive only on ONE disabled
repo ruleset (`anvomidaviser/Optimus-Branch`), which also still grants `always`
bypass to RepositoryRole 2 (maintain) and keeps `code_coverage` /
`required_deployments` / `copilot_code_review` — the exact set §7.3 retired, so
that stale ruleset should be deleted rather than re-enabled. 946600 = Codex MCP
(GitHub), on 67 repo rulesets (17 hyperpolymath, 50 metadatastician); owner
decision O5 stays open.
Note `123` (codecov PR gate) was never a bypass actor — it only ever appears as
a jtv-lang required-check context, which is the §11.3 hand-typed-context bug.
|===

Kept: `deletion`, `non_fast_forward`, `required_signatures`, `pull_request`
Expand Down Expand Up @@ -279,3 +288,23 @@ because 300 repos carrying a harmless `PROV-` is not worth 300 API writes.
. tag ruleset
. verifier: identity rule, phantom contexts = 0, live ≡ canonical
. allowlist — *tail of the sweep only*

== Tailscale and GitHub

There is no Tailscale GitHub App: `GET https://api.github.com/apps/tailscale` returns
404, and Tailscale's own integration for GitHub is the
`tailscale/github-action` Action plus a Tailscale OAuth client. So "install Tailscale
as an app on the org" is not an action that exists; the estate equivalent is:

1. `tailscale/github-action@*` is on the Actions allowlist (both
`config/settings/actions-allowlist.json` and
`rhodium-standard-repositories/actions-allowlist/allowed-actions.json`).
2. `.github/workflows/tailscale-connect-reusable.yml` in this repo provides the
connect job; `metadatastician/.github` carries the org-level copy so repos can
`uses: metadatastician/.github/.github/workflows/...@main`.
3. Secrets `TS_OAUTH_CLIENT_ID` / `TS_OAUTH_SECRET` are created by the owner: org-level
for metadatastician (Settings → Secrets and variables → Actions), per-repository for
the `hyperpolymath` account, which has no org-level secrets on the free plan.
4. Repos that need tailnet reachability opt in per workflow. Nothing here changes CI
for repos that do not call it, which is deliberate: a connect step without the
secrets fails the job.
Original file line number Diff line number Diff line change
Expand Up @@ -145,8 +145,6 @@ impl ComplianceCheck for TestCoverageCheck {

// Check for coverage configuration
let coverage_configs = [
"codecov.yml",
".codecov.yml",
"coveralls.yml",
".coveragerc",
"coverage.json",
Expand Down Expand Up @@ -177,7 +175,7 @@ impl ComplianceCheck for TestCoverageCheck {
if let Ok(entries) = std::fs::read_dir(full_path) {
for entry in entries.flatten() {
if let Ok(content) = std::fs::read_to_string(entry.path()) {
if content.contains("coverage") || content.contains("codecov") {
if content.contains("coverage") {
has_coverage = true;
break;
}
Expand Down Expand Up @@ -210,7 +208,7 @@ impl ComplianceCheck for TestCoverageCheck {
tier: self.tier(),
passed: false,
message: "Tests found but no coverage configuration".to_string(),
details: Some("Add coverage reporting (codecov, coveralls, etc.)".to_string()),
details: Some("Add coverage reporting (tarpaulin, llvm-cov, coverage.py, etc.)".to_string()),
})
} else {
Ok(CheckResult {
Expand All @@ -226,7 +224,7 @@ impl ComplianceCheck for TestCoverageCheck {

async fn check_remote(&self, contents: &RepoContents) -> Result<CheckResult> {
let test_patterns = ["test", "tests", "spec", "__tests__"];
let coverage_patterns = ["codecov", "coverage", "coveralls"];
let coverage_patterns = ["coverage", "coveralls"];

let has_tests = contents.files.iter().any(|f| {
let path_lower = f.path.to_lowercase();
Expand Down
Loading