mirror of
https://github.com/stablyai/orca.git
synced 2026-10-02 00:02:05 +00:00
* chore(dead-code): drop 2k lines of unreachable exports and orphan modules Ran knip across every build entry (main, preload, renderer, popout, web, cli, relay, workers, forked sidecars, config scripts) and removed what no entry graph can reach. - 11 orphan modules nothing imported, plus one test that only covered them - 159 unused exports/types, with their now-dead helpers, imports and tests Each candidate was verified against dynamic references before deletion. 42 knip hits were false positives and are kept: shared modules consumed by the mobile/ workspace, the src/shared/plugins/** public API, vendored shadcn primitives, and relay wire-protocol constants held for compatibility. Adds knip.json + `pnpm audit:dead-code` so this stays measurable. Verified: pnpm typecheck, pnpm lint, and 2081 tests across the 73 affected test files all pass. * chore(dead-code): move knip config under config/ Root-level additions are blocked by the root directory guard. Co-authored-by: Orca <help@stably.ai> --------- Co-authored-by: Orca <help@stably.ai>
86 lines
3.5 KiB
TypeScript
86 lines
3.5 KiB
TypeScript
import {
|
|
normalizePluginConsents,
|
|
normalizePluginIdList
|
|
} from '../../shared/plugins/plugin-consent-state'
|
|
import type { Store } from '../persistence'
|
|
import type { PluginService } from './plugin-service'
|
|
import type { PluginConsentRequest } from '../../shared/plugins/plugin-consent-request'
|
|
import { verifyInstructionalPluginContent } from './plugin-instructional-content-integrity'
|
|
|
|
/**
|
|
* Single write path for consent + enablement. Consent is recorded as
|
|
* (qualified key → consent fingerprint) — never a bare id — so a capability
|
|
* expansion or addition of trusted Node code requires re-consent. The desktop
|
|
* IPC handlers and the headless RPC methods both route through here.
|
|
*/
|
|
|
|
/** Records the user's consent-dialog answer. Approving stores the CURRENT
|
|
* consent fingerprint and clears any disable; declining disables so the plugin
|
|
* never re-prompts on later launches. */
|
|
export async function applyPluginConsent(input: {
|
|
store: Store
|
|
pluginService: PluginService
|
|
pluginKey: PluginConsentRequest['pluginKey']
|
|
reviewedFingerprint: PluginConsentRequest['reviewedFingerprint']
|
|
decision: PluginConsentRequest['decision']
|
|
originWebContentsId?: number
|
|
}): Promise<void> {
|
|
const { store, pluginService, pluginKey } = input
|
|
const plugin = pluginService.findValidPlugin(pluginKey)
|
|
if (!plugin) {
|
|
throw new Error(`cannot record consent for unknown plugin ${pluginKey}`)
|
|
}
|
|
// Why: a same-key install can change while the dialog is open; never apply a
|
|
// decision to capabilities or a worker trust tier the user did not review.
|
|
if (input.decision === 'approve' && plugin.consentFingerprint !== input.reviewedFingerprint) {
|
|
throw new Error(`plugin ${pluginKey} changed since its permissions were reviewed`)
|
|
}
|
|
if (input.decision === 'approve') {
|
|
// Why: IPC and serve callers can bypass the renderer dialog, so main must
|
|
// prove every instructional byte is still reviewable before enabling it.
|
|
await verifyInstructionalPluginContent(plugin)
|
|
}
|
|
const settings = store.getSettings()
|
|
const disabled = new Set(normalizePluginIdList(settings.disabledPlugins))
|
|
const consents = normalizePluginConsents(settings.pluginConsents)
|
|
if (input.decision === 'approve') {
|
|
consents[pluginKey] = plugin.consentFingerprint
|
|
disabled.delete(pluginKey)
|
|
} else {
|
|
disabled.add(pluginKey)
|
|
}
|
|
store.updateSettings(
|
|
{ disabledPlugins: [...disabled], pluginConsents: consents },
|
|
{ notifyListeners: true, originWebContentsId: input.originWebContentsId }
|
|
)
|
|
await pluginService.reconcileActivationState()
|
|
}
|
|
|
|
/** Enables/disables an already-consented plugin. Enabling never bypasses
|
|
* consent: with missing or stale consent the plugin stays pending and the
|
|
* caller must run the consent flow instead. */
|
|
export async function applyPluginEnablement(input: {
|
|
store: Store
|
|
pluginService: PluginService
|
|
pluginKey: string
|
|
enabled: boolean
|
|
originWebContentsId?: number
|
|
}): Promise<void> {
|
|
const { store, pluginService, pluginKey, enabled } = input
|
|
if (!pluginService.findValidPlugin(pluginKey)) {
|
|
throw new Error(`cannot change enablement for unknown plugin ${pluginKey}`)
|
|
}
|
|
const settings = store.getSettings()
|
|
const disabled = new Set(normalizePluginIdList(settings.disabledPlugins))
|
|
if (enabled) {
|
|
disabled.delete(pluginKey)
|
|
} else {
|
|
disabled.add(pluginKey)
|
|
}
|
|
store.updateSettings(
|
|
{ disabledPlugins: [...disabled] },
|
|
{ notifyListeners: true, originWebContentsId: input.originWebContentsId }
|
|
)
|
|
await pluginService.reconcileActivationState()
|
|
}
|