mirror of
https://github.com/stablyai/orca.git
synced 2026-09-22 08:02:28 +00:00
* fix(ssh): let fork-PR worktrees add their contributor remote via the relay Creating a workspace from a fork PR on an SSH host failed with "Destructive git remote operations are not allowed via exec". The relay's git.exec allowlist blocked every `remote` write subcommand, but SSH fork-PR creation has to run `git remote add <fork> <url>` on the host before it can fetch and track the contributor's branch, so the whole create aborted. Allow exactly the two shapes that flow needs -- `remote add <name> <url>` and `remote remove <name>` -- validated with the same remote-name and URL rules the relay already applies to every pushTarget-carrying RPC. Everything else (set-url, rename, prune, extra operands, flags before the action) stays blocked, and the URL must be a github.com clone/ssh URL, so no new reach is granted beyond what push/fetch already accept. `remote remove` was blocked too, which silently leaked fork remotes on SSH hosts: worktree removal swallows the cleanup error. It works again now. A host still running an older relay gets an actionable "reconnect to deploy the latest relay" message instead of the raw policy error. * test(git-exec): pin remote read/write mutation classification Misclassifying `git remote` / `remote get-url` as mutating would flush the relay and SSH provider git read caches on every remote probe, so pin both directions.
28 lines
964 B
TypeScript
28 lines
964 B
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { gitExecMutatesRepository } from './git-exec-mutation'
|
|
|
|
describe('gitExecMutatesRepository', () => {
|
|
it.each([
|
|
[['remote', 'add', 'pr-contributor-orca', 'https://github.com/contributor/orca.git']],
|
|
[['remote', 'remove', 'pr-contributor-orca']],
|
|
[['clone', '--', 'https://github.com/stablyai/orca.git', 'orca']],
|
|
[['commit', '--allow-empty', '-m', 'Initial commit']],
|
|
[['init']]
|
|
])('treats %j as mutating', (args) => {
|
|
expect(gitExecMutatesRepository(args)).toBe(true)
|
|
})
|
|
|
|
it.each([
|
|
// Why: these run on read-heavy paths; misclassifying them would flush the
|
|
// git read cache on every remote probe.
|
|
[['remote']],
|
|
[['remote', '-v']],
|
|
[['remote', 'get-url', 'origin']],
|
|
[['remote', 'show', 'origin']],
|
|
[['rev-parse', '--show-toplevel']],
|
|
[[]]
|
|
])('treats %j as read-only', (args) => {
|
|
expect(gitExecMutatesRepository(args)).toBe(false)
|
|
})
|
|
})
|