diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 00000000..b94bfe72 --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,3 @@ +# Designate an explicit repository owner for every change. More specific +# ownership rules can be added below if maintainership expands. +* @clay-good diff --git a/src/core/services/mcp-handlers/merge-oracle.test.ts b/src/core/services/mcp-handlers/merge-oracle.test.ts index e828f9c9..770c9136 100644 --- a/src/core/services/mcp-handlers/merge-oracle.test.ts +++ b/src/core/services/mcp-handlers/merge-oracle.test.ts @@ -389,6 +389,8 @@ describe('simulateMerge', () => { } }); + // This case creates six real worktrees and runs real merges. It completes well within the + // default budget on POSIX, but Git for Windows can exceed 30s on a hosted runner. it('assesses only the default diff.algorithm, and matches a real merge for it', async () => { const alg = join(root, 'alg'); execFileGitSync('git', ['init', '-q', '-b', 'main', alg]); @@ -443,7 +445,7 @@ describe('simulateMerge', () => { try { git(alg, 'merge-tree', '--write-tree', sa, sb); } catch { truth = 'textual-conflict'; } expect((await simulateMerge(alg, sa, sb)).verdict, style).toBe(truth); } - }); + }, process.platform === 'win32' ? 90_000 : 30_000); it('matches decomposed (NFD) attribute patterns and case-variant attributes files', async () => { const nfd = 'é.txt'; diff --git a/src/workflow-security.test.ts b/src/workflow-security.test.ts index feb862db..d17392eb 100644 --- a/src/workflow-security.test.ts +++ b/src/workflow-security.test.ts @@ -17,6 +17,7 @@ * 3. `run:` scripts take untrusted values through `env:`, never inline `${{ }}`. * 4. Every executed workflow declares a top-level `permissions` block. * 5. Every job declares its own `permissions` block. + * 6. Every repository path has an explicit code owner. */ import { describe, it, expect } from 'vitest'; import { readFileSync, readdirSync, existsSync } from 'node:fs'; @@ -269,6 +270,22 @@ describe('workflow security: least-privilege tokens', () => { }); }); +describe('workflow security: review ownership', () => { + it('designates a repository owner for every path', () => { + const codeowners = read(join(REPO_ROOT, '.github', 'CODEOWNERS')); + const globalRule = codeowners + .split('\n') + .map(line => line.replace(/\s+#.*$/, '').trim()) + .filter(line => line && !line.startsWith('#')) + .find(line => line.split(/\s+/)[0] === '*'); + + expect( + globalRule?.split(/\s+/).slice(1), + 'CODEOWNERS must assign every path to the repository owner so branch protection can require an accountable review.' + ).toContain('@clay-good'); + }); +}); + describe('workflow security: supply-chain automation is wired', () => { it('keeps Dependabot watching both npm and github-actions', () => { const cfg = parse(read(join(REPO_ROOT, '.github', 'dependabot.yml'))) as {