From 685ac9476e06b05294d0b1960fa847e5ca601bad Mon Sep 17 00:00:00 2001 From: Neil <4138956+nwparker@users.noreply.github.com> Date: Wed, 12 Aug 2026 23:24:31 -0700 Subject: [PATCH] type(store): mark pending SSH readoptions readonly Widen pendingSshRepoReadoptions, recordSshRepoReadoptions, and the merge/reconcile helpers to readonly so a reused pending queue cannot be mutated in place after a no-op catalog reconcile. Co-authored-by: Orca --- .../src/components/sidebar/add-remote-host-ssh-actions.ts | 4 ++-- src/renderer/src/store/slices/repos.ts | 4 ++-- src/renderer/src/store/slices/superseded-ssh-repo-rows.ts | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/src/renderer/src/components/sidebar/add-remote-host-ssh-actions.ts b/src/renderer/src/components/sidebar/add-remote-host-ssh-actions.ts index 7ad8c6f5f86..6b585156749 100644 --- a/src/renderer/src/components/sidebar/add-remote-host-ssh-actions.ts +++ b/src/renderer/src/components/sidebar/add-remote-host-ssh-actions.ts @@ -43,7 +43,7 @@ export async function saveNewSshHostFromForm({ }: { form: EditingTarget ssh: SshApi - recordSshRepoReadoptions: (readoptions: SshRepoReadoption[]) => void + recordSshRepoReadoptions: (readoptions: readonly SshRepoReadoption[]) => void setSshTargetsMetadata: (targets: SshTarget[]) => void recordFeatureInteraction: (feature: 'ssh') => void }): Promise<'saved' | 'validation-failed' | 'failed'> { @@ -170,7 +170,7 @@ export async function addAllSshConfigHostsToOrca({ recordFeatureInteraction }: { ssh: SshApi - recordSshRepoReadoptions: (readoptions: SshRepoReadoption[]) => void + recordSshRepoReadoptions: (readoptions: readonly SshRepoReadoption[]) => void setSshTargetsMetadata: (targets: SshTarget[]) => void recordFeatureInteraction: (feature: 'ssh') => void }): Promise<{ kind: 'added'; count: number } | { kind: 'already-synced' } | { kind: 'failed' }> { diff --git a/src/renderer/src/store/slices/repos.ts b/src/renderer/src/store/slices/repos.ts index d5bd49f5a95..fd96ad3e572 100644 --- a/src/renderer/src/store/slices/repos.ts +++ b/src/renderer/src/store/slices/repos.ts @@ -1781,8 +1781,8 @@ export type RepoSlice = { activeRepoId: string | null // Monotonic sequence so overlapping catalog fetches can drop stale same-host results (#7020). reposFetchGeneration: number - pendingSshRepoReadoptions: SshRepoReadoption[] - recordSshRepoReadoptions: (readoptions: SshRepoReadoption[]) => void + pendingSshRepoReadoptions: readonly SshRepoReadoption[] + recordSshRepoReadoptions: (readoptions: readonly SshRepoReadoption[]) => void fetchRepos: (options?: RuntimeCatalogFetchOptions) => Promise fetchReposForAllHosts: (options?: AllHostCatalogFetchOptions) => Promise awaitLocalRepoCatalogSettlement: () => Promise diff --git a/src/renderer/src/store/slices/superseded-ssh-repo-rows.ts b/src/renderer/src/store/slices/superseded-ssh-repo-rows.ts index 4b20cfa6edf..c18e0f6e5af 100644 --- a/src/renderer/src/store/slices/superseded-ssh-repo-rows.ts +++ b/src/renderer/src/store/slices/superseded-ssh-repo-rows.ts @@ -4,7 +4,7 @@ import { getRepoExecutionHostId, toSshExecutionHostId } from '../../../../shared export type SshRepoReconciliation = { repos: readonly Repo[] - pendingReadoptions: SshRepoReadoption[] + pendingReadoptions: readonly SshRepoReadoption[] } function repoBelongsToTarget(repo: Repo, targetId: string): boolean { @@ -69,7 +69,7 @@ export function reconcileReadoptedSshRepoRows( export function mergeSshRepoReadoptions( pending: readonly SshRepoReadoption[], incoming: readonly SshRepoReadoption[] -): SshRepoReadoption[] { +): readonly SshRepoReadoption[] { const repoIdsByMigration = new Map>() for (const readoption of [...pending, ...incoming]) { const key = `${readoption.oldTargetId}\0${readoption.newTargetId}`