mirror of
https://github.com/stablyai/orca.git
synced 2026-10-01 00:02:10 +00:00
On Linux with no keyring, Electron falls back to the `basic_text` backend, which "encrypts" with a hardcoded password. `isEncryptionAvailable()` returns true for it, so Orca reported those secrets as sealed. They are not. The obvious fix — returning false for basic_text — is wrong and would have been a credential regression: `decryptWithStatus()` skips decryption entirely when encryption is unavailable, so every already-stored secret would read back empty. Sealing genuinely works on basic_text and must keep working. So capability and trust are now separate questions. `isEncryptionAvailable()` still answers "can this host seal and unseal", and `describeProtectionGap()` (renamed from `describeUnavailable`) answers "is my data actually protected", covering both no-sealing and weak-sealing. That method had no production caller — the port documented a promise nothing kept. `reportSecretProtectionGap()` now reads it at startup. A user-visible surface is follow-up; this at least stops the silence. Adds a bootstrap wiring guard over all nine host port installs. The no-op defaults are correct for a renderer-less host and silently wrong for the desktop, and a dropped or reordered install fails no existing test. Verified in both directions: it fails when an install is removed, and when one moves after the runtime is constructed.
61 lines
2.4 KiB
TypeScript
61 lines
2.4 KiB
TypeScript
import { describe, expect, it } from 'vitest'
|
|
import { getWorktreeWatcherRemoval, setWorktreeWatcherRemoval } from './worktree-watcher-removal'
|
|
|
|
/**
|
|
* Why: the port's default is inert by design — a host with no renderer has no watchers
|
|
* to close. That is correct for orcad and silently wrong for the desktop, where an
|
|
* uninstalled port means worktree removal stops releasing the directory and Windows
|
|
* fails the delete on a locked file. The default is indistinguishable from a working
|
|
* install at the call site, so it gets asserted here.
|
|
*/
|
|
describe('WorktreeWatcherRemoval port', () => {
|
|
const METHODS = [
|
|
'closeLocal',
|
|
'restoreLocal',
|
|
'forgetLocal',
|
|
'closeRemote',
|
|
'restoreRemote',
|
|
'forgetRemote'
|
|
] as const
|
|
|
|
it('defaults to inert so a renderer-less host is honest, not broken', async () => {
|
|
setWorktreeWatcherRemoval(null)
|
|
const inert = getWorktreeWatcherRemoval()
|
|
for (const method of METHODS) {
|
|
await expect(
|
|
Promise.resolve(inert[method]('repo::/tmp/w', '/tmp/w' as never))
|
|
).resolves.not.toThrow()
|
|
}
|
|
})
|
|
|
|
it('routes every method to the installed binding', async () => {
|
|
const calls: string[] = []
|
|
setWorktreeWatcherRemoval({
|
|
closeLocal: async () => void calls.push('closeLocal'),
|
|
restoreLocal: async () => void calls.push('restoreLocal'),
|
|
forgetLocal: () => void calls.push('forgetLocal'),
|
|
closeRemote: async () => void calls.push('closeRemote'),
|
|
restoreRemote: async () => void calls.push('restoreRemote'),
|
|
forgetRemote: () => void calls.push('forgetRemote')
|
|
})
|
|
for (const method of METHODS) {
|
|
await getWorktreeWatcherRemoval()[method]('conn', '/tmp/w' as never)
|
|
}
|
|
expect(calls).toEqual([...METHODS])
|
|
setWorktreeWatcherRemoval(null)
|
|
})
|
|
|
|
it('exposes a desktop binding that delegates rather than stubbing', async () => {
|
|
// Why import lazily: filesystem-watcher pulls electron, so it must not load in the
|
|
// inert-default case above.
|
|
const { desktopWorktreeWatcherRemoval } = await import('./filesystem-watcher')
|
|
for (const method of METHODS) {
|
|
expect(typeof desktopWorktreeWatcherRemoval[method], method).toBe('function')
|
|
// An inert stub is an empty arrow; a real delegation is not.
|
|
expect(desktopWorktreeWatcherRemoval[method].toString(), method).not.toMatch(
|
|
/^\s*(async )?\(\s*\)\s*=>\s*\{?\s*\}?\s*$/
|
|
)
|
|
}
|
|
})
|
|
})
|