From 2bb4cd16936e68e4ba16d8d1e36fd5a749d2daad Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:27:24 -0300 Subject: [PATCH 01/20] security: require CodeQL governance check Signed-off-by: Vitor Mattos --- governance.config.json | 3 +++ 1 file changed, 3 insertions(+) diff --git a/governance.config.json b/governance.config.json index 45087e5..09b3fde 100644 --- a/governance.config.json +++ b/governance.config.json @@ -73,6 +73,9 @@ }, { "context": "TypeScript" + }, + { + "context": "CodeQL" } ], "strict_required_status_checks_policy": true, From 4d4046766b929cbfe0ca99bbedb1424bd777914f Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:27:27 -0300 Subject: [PATCH 02/20] fix: run governance action without runtime installs Signed-off-by: Vitor Mattos --- action.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/action.yml b/action.yml index a7cd0f6..a66c55c 100644 --- a/action.yml +++ b/action.yml @@ -28,15 +28,6 @@ runs: node-version: 24 package-manager-cache: false - - name: Install governance dependencies - shell: bash - working-directory: ${{ github.action_path }} - run: npm install --ignore-scripts - - - name: Build governance CLI - shell: bash - working-directory: ${{ github.action_path }} - run: npm run build - name: Reconcile rulesets shell: bash @@ -56,4 +47,4 @@ runs: args+=(--apply) fi - node dist/cli.js "${args[@]}" + node src/cli.ts "${args[@]}" From 3cefa9421ac1381218a06abade346dc7d1728bcb Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:27:31 -0300 Subject: [PATCH 03/20] fix: run governance action without runtime installs Signed-off-by: Vitor Mattos --- discover/action.yml | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/discover/action.yml b/discover/action.yml index c35da19..c333795 100644 --- a/discover/action.yml +++ b/discover/action.yml @@ -26,15 +26,6 @@ runs: node-version: 24 package-manager-cache: false - - name: Install governance dependencies - shell: bash - working-directory: ${{ github.action_path }}/.. - run: npm install --ignore-scripts - - - name: Build governance CLI - shell: bash - working-directory: ${{ github.action_path }}/.. - run: npm run build - name: Discover repositories id: discover @@ -44,5 +35,5 @@ runs: ORGANIZATION: ${{ inputs.organization }} working-directory: ${{ github.action_path }}/.. run: | - repositories="$(node dist/discover-repositories.js "$ORGANIZATION")" + repositories="$(node src/discover-repositories.ts "$ORGANIZATION")" echo "repositories=$repositories" >> "$GITHUB_OUTPUT" From 69b77d3a3da26c752af0562da89cac8dff60e343 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:27:50 -0300 Subject: [PATCH 04/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/cli-runner.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/cli-runner.ts b/src/cli-runner.ts index 27c59c6..dd60c8e 100644 --- a/src/cli-runner.ts +++ b/src/cli-runner.ts @@ -5,14 +5,14 @@ import { loadGovernanceConfig, resolveRepositoryRulesets, type GovernanceConfig, -} from './config.js'; -import type { GovernanceClient } from './governance.js'; +} from './config.ts'; +import type { GovernanceClient } from './governance.ts'; import { planOrganization, planRepository, syncOrganization, syncRepository, -} from './governance.js'; +} from './governance.ts'; export type CliEnvironment = { GITHUB_TOKEN?: string | undefined; From 42ff1058e0fe26d31435c1a4213bfcc5adb942cf Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:27:53 -0300 Subject: [PATCH 05/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/cli.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/cli.ts b/src/cli.ts index 384fcb5..6aa6a7e 100644 --- a/src/cli.ts +++ b/src/cli.ts @@ -3,8 +3,8 @@ // SPDX-FileCopyrightText: 2026 LibreCode coop and contributors // SPDX-License-Identifier: AGPL-3.0-or-later -import { runCli } from './cli-runner.js'; -import { GitHubClient } from './github-client.js'; +import { runCli } from './cli-runner.ts'; +import { GitHubClient } from './github-client.ts'; const code = await runCli( process.argv.slice(2), From 4c648a1f63259186aefe670a2f81aed10c199321 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:27:56 -0300 Subject: [PATCH 06/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/config-validation.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/config-validation.ts b/src/config-validation.ts index cf00119..ffcd266 100644 --- a/src/config-validation.ts +++ b/src/config-validation.ts @@ -5,12 +5,12 @@ import type { BypassActor, RepositoryRuleset, RulesetRule, -} from './types.js'; +} from './types.ts'; import type { ConditionalGovernanceConfig, GovernanceConfig, RepositoryGovernanceConfig, -} from './config.js'; +} from './config.ts'; export function validateGovernanceConfig(value: unknown): GovernanceConfig { const root = expectRecord(value, '$'); From 1679c8a1c385651a5969d1a3de02d4d61e36aa23 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:28:00 -0300 Subject: [PATCH 07/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/config.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/config.ts b/src/config.ts index 23c58a6..d82fb73 100644 --- a/src/config.ts +++ b/src/config.ts @@ -5,12 +5,12 @@ import { readFile } from 'node:fs/promises'; import type { BypassActor, RepositoryRuleset, -} from './types.js'; +} from './types.ts'; import type { GitHubContentProbe, RepositoryMetadata, -} from './repository-classifier.js'; -import { validateGovernanceConfig } from './config-validation.js'; +} from './repository-classifier.ts'; +import { validateGovernanceConfig } from './config-validation.ts'; export type RepositoryGovernanceConfig = { policies?: string[]; From 6082df6a5573699ff86d6d29e8bbece754fc41eb Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:28:02 -0300 Subject: [PATCH 08/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/discover-repositories.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/discover-repositories.ts b/src/discover-repositories.ts index 85c349e..8c7e4b9 100644 --- a/src/discover-repositories.ts +++ b/src/discover-repositories.ts @@ -3,7 +3,7 @@ // SPDX-FileCopyrightText: 2026 LibreCode coop and contributors // SPDX-License-Identifier: AGPL-3.0-or-later -import { discoverPublicRepositories } from './repository-discovery.js'; +import { discoverPublicRepositories } from './repository-discovery.ts'; const organization = process.argv[2]; From 1b98af1ad38353e9074c2f5e7777fcafd96bf218 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:28:05 -0300 Subject: [PATCH 09/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/github-client.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/github-client.ts b/src/github-client.ts index d0c47bf..0bd1b11 100644 --- a/src/github-client.ts +++ b/src/github-client.ts @@ -4,16 +4,16 @@ import type { RepositoryMetadata, GitHubContentProbe, -} from './repository-classifier.js'; +} from './repository-classifier.ts'; import type { ExistingRepositoryRuleset, RepositoryRulesetClient, -} from './ruleset-reconciler.js'; +} from './ruleset-reconciler.ts'; import type { BypassActor, RepositoryRuleset, RulesetRule, -} from './types.js'; +} from './types.ts'; type FetchLike = typeof fetch; From 77d3938bdc6df6fdefde1ecd7ca6d9ea32db01c5 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:28:08 -0300 Subject: [PATCH 10/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/governance.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/governance.ts b/src/governance.ts index 175e6c8..3eec353 100644 --- a/src/governance.ts +++ b/src/governance.ts @@ -6,12 +6,12 @@ import { reconcileRepositoryRulesets, type RepositoryRulesetClient, type RulesetChange, -} from './ruleset-reconciler.js'; +} from './ruleset-reconciler.ts'; import type { GitHubContentProbe, RepositoryMetadata, -} from './repository-classifier.js'; -import type { RepositoryRuleset } from './types.js'; +} from './repository-classifier.ts'; +import type { RepositoryRuleset } from './types.ts'; export interface GovernanceClient extends GitHubContentProbe, From de39ff9ac8c4266b4145286eb8cd81e91185cd1e Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:28:13 -0300 Subject: [PATCH 11/20] refactor: use source TypeScript imports at runtime Signed-off-by: Vitor Mattos --- src/ruleset-normalizer.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/ruleset-normalizer.ts b/src/ruleset-normalizer.ts index 7307ffa..c6f335f 100644 --- a/src/ruleset-normalizer.ts +++ b/src/ruleset-normalizer.ts @@ -1,7 +1,7 @@ // SPDX-FileCopyrightText: 2026 LibreCode coop and contributors // SPDX-License-Identifier: AGPL-3.0-or-later -import type { RepositoryRuleset, RulesetRule } from './types.js'; +import type { RepositoryRuleset, RulesetRule } from './types.ts'; function normalizeRule(rule: RulesetRule): RulesetRule { if (rule.type === 'pull_request') { From 29c6dedecf2c62213dbfc221cb96b444c17ff1fc Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:28:38 -0300 Subject: [PATCH 12/20] build: rewrite TypeScript import extensions Signed-off-by: Vitor Mattos --- tsconfig.json | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tsconfig.json b/tsconfig.json index 03b35e7..487400e 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -12,7 +12,8 @@ "skipLibCheck": true, "types": [ "node" - ] + ], + "rewriteRelativeImportExtensions": true }, "include": [ "src/**/*.ts", From bb461729ea7edf827bd128dd163c7a103b4dbe78 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:28:40 -0300 Subject: [PATCH 13/20] security: define governance code owners Signed-off-by: Vitor Mattos --- .github/CODEOWNERS | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 .github/CODEOWNERS diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..a9112e9 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,10 @@ +# SPDX-FileCopyrightText: 2026 LibreCode coop and contributors +# SPDX-License-Identifier: AGPL-3.0-or-later + +.github/workflows/** @vitormattos +.github/dependabot.yml @vitormattos +governance.config.json @vitormattos +action.yml @vitormattos +discover/action.yml @vitormattos +SECURITY.md @vitormattos +docs/** @vitormattos From a6162cde4e6a9c0dd5358e169f26cff62736d854 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:29:05 -0300 Subject: [PATCH 14/20] test: verify dependency-free action runtime Signed-off-by: Vitor Mattos --- .github/workflows/typescript.yml | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/.github/workflows/typescript.yml b/.github/workflows/typescript.yml index 4c4b3e1..2cd6360 100644 --- a/.github/workflows/typescript.yml +++ b/.github/workflows/typescript.yml @@ -29,6 +29,23 @@ jobs: node-version: 24 package-manager-cache: false + - name: Verify native TypeScript action runtime + shell: bash + run: | + set +e + output="$(node src/cli.ts 2>&1)" + status=$? + set -e + test "$status" -eq 2 + grep -F "Specify exactly one of --org OWNER or --repo OWNER/REPO" <<< "$output" + + set +e + output="$(node src/discover-repositories.ts 2>&1)" + status=$? + set -e + test "$status" -eq 2 + grep -F "Usage: discover-repositories ORGANIZATION" <<< "$output" + - name: Install dependencies run: npm install --ignore-scripts From b7ef94f958ab2c74ba40eb08fcd7a8c1b9bd6132 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:30:49 -0300 Subject: [PATCH 15/20] fix: complete native TypeScript imports Signed-off-by: Vitor Mattos --- src/ruleset-reconciler.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/ruleset-reconciler.ts b/src/ruleset-reconciler.ts index e75e57a..71f231f 100644 --- a/src/ruleset-reconciler.ts +++ b/src/ruleset-reconciler.ts @@ -1,8 +1,8 @@ // SPDX-FileCopyrightText: 2026 LibreCode coop and contributors // SPDX-License-Identifier: AGPL-3.0-or-later -import type { RepositoryRuleset } from './types.js'; -import { rulesetsEqual } from './ruleset-normalizer.js'; +import type { RepositoryRuleset } from './types.ts'; +import { rulesetsEqual } from './ruleset-normalizer.ts'; export type ExistingRepositoryRuleset = RepositoryRuleset & { id: number; From 5fb558bf4351e577b5e02d15453438d40f87109d Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:30:52 -0300 Subject: [PATCH 16/20] fix: complete native TypeScript imports Signed-off-by: Vitor Mattos --- src/validate-release.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/validate-release.ts b/src/validate-release.ts index ea3814f..bdbb32c 100644 --- a/src/validate-release.ts +++ b/src/validate-release.ts @@ -5,7 +5,7 @@ import { execFileSync } from 'node:child_process'; import { readFile } from 'node:fs/promises'; -import { validateRelease } from './release-validator.js'; +import { validateRelease } from './release-validator.ts'; const requestedVersion = process.argv[2]; From 7dbe686174e668ecc0ccfd9155069e7c06aab247 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:31:58 -0300 Subject: [PATCH 17/20] test: expose native runtime smoke diagnostics Signed-off-by: Vitor Mattos --- .github/workflows/typescript.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/typescript.yml b/.github/workflows/typescript.yml index 2cd6360..110c61e 100644 --- a/.github/workflows/typescript.yml +++ b/.github/workflows/typescript.yml @@ -36,6 +36,7 @@ jobs: output="$(node src/cli.ts 2>&1)" status=$? set -e + printf 'cli status=%s\n%s\n' "$status" "$output" test "$status" -eq 2 grep -F "Specify exactly one of --org OWNER or --repo OWNER/REPO" <<< "$output" @@ -43,6 +44,7 @@ jobs: output="$(node src/discover-repositories.ts 2>&1)" status=$? set -e + printf 'discover status=%s\n%s\n' "$status" "$output" test "$status" -eq 2 grep -F "Usage: discover-repositories ORGANIZATION" <<< "$output" From bf879199193696e45e3122be96dbe935ad7bf67c Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:33:00 -0300 Subject: [PATCH 18/20] chore: keep repository-local governance fixture unchanged Signed-off-by: Vitor Mattos --- governance.config.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/governance.config.json b/governance.config.json index 09b3fde..45087e5 100644 --- a/governance.config.json +++ b/governance.config.json @@ -73,9 +73,6 @@ }, { "context": "TypeScript" - }, - { - "context": "CodeQL" } ], "strict_required_status_checks_policy": true, From 636c8ef6ae034358abf38970ab2ca150404a197e Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:33:54 -0300 Subject: [PATCH 19/20] refactor: use erasable TypeScript constructor fields Signed-off-by: Vitor Mattos --- src/github-client.ts | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/github-client.ts b/src/github-client.ts index 0bd1b11..ffdcd97 100644 --- a/src/github-client.ts +++ b/src/github-client.ts @@ -34,11 +34,19 @@ type RulesetSummary = { export class GitHubClient implements GitHubContentProbe, RepositoryRulesetClient { + private readonly token: string; + private readonly fetchImpl: FetchLike; + private readonly apiUrl: string; + constructor( - private readonly token: string, - private readonly fetchImpl: FetchLike = fetch, - private readonly apiUrl = 'https://api.github.com', - ) {} + token: string, + fetchImpl: FetchLike = fetch, + apiUrl = 'https://api.github.com', + ) { + this.token = token; + this.fetchImpl = fetchImpl; + this.apiUrl = apiUrl; + } async getRepository( owner: string, From 9090020831870f2313c7fccd3e8fcd67c1995a17 Mon Sep 17 00:00:00 2001 From: Vitor Mattos Date: Sun, 20 Sep 2026 20:35:31 -0300 Subject: [PATCH 20/20] test: keep native runtime smoke check concise Signed-off-by: Vitor Mattos --- .github/workflows/typescript.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/.github/workflows/typescript.yml b/.github/workflows/typescript.yml index 110c61e..2cd6360 100644 --- a/.github/workflows/typescript.yml +++ b/.github/workflows/typescript.yml @@ -36,7 +36,6 @@ jobs: output="$(node src/cli.ts 2>&1)" status=$? set -e - printf 'cli status=%s\n%s\n' "$status" "$output" test "$status" -eq 2 grep -F "Specify exactly one of --org OWNER or --repo OWNER/REPO" <<< "$output" @@ -44,7 +43,6 @@ jobs: output="$(node src/discover-repositories.ts 2>&1)" status=$? set -e - printf 'discover status=%s\n%s\n' "$status" "$output" test "$status" -eq 2 grep -F "Usage: discover-repositories ORGANIZATION" <<< "$output"