fix(managed-runtime): secure auth and lifecycle control across runtimes (#437)

* feat: add OpenCode server authentication with auto-generated passwords

* fix(auth): separate user env and managed OpenCode password state

* fix(auth): enforce env precedence and managed password rotation across runtimes

* fix(vscode): rotate managed auth on startup and harden webview proxy

* build: add dev icons and config for Tauri desktop development

* fix(runtime): start managed OpenCode via CLI and expose active API port

* fix(managed-runtime): control OpenCode lifecycle and surface secure diagnostics

* docs: remove VS Code plugin test runbook
This commit is contained in:
Iuliia Ivashko
2026-02-17 18:01:57 +02:00
committed by GitHub
parent 58b27fa621
commit 138772e66e
22 changed files with 717 additions and 88 deletions
@@ -91,6 +91,19 @@ export const VSCodeLayout: React.FC = () => {
return sessions.find((session) => session.id === currentSessionId)?.title || 'Session';
}, [currentSessionId, sessions]);
const newSessionDraftOpen = useSessionStore((state) => Boolean(state.newSessionDraft?.open));
const isSyncingMessages = useSessionStore((state) => state.isSyncing);
const hasActiveSessionWork = useSessionStore((state) => {
const statuses = state.sessionStatus;
if (!statuses || statuses.size === 0) {
return false;
}
for (const status of statuses.values()) {
if (status?.type === 'busy' || status?.type === 'retry') {
return true;
}
}
return false;
});
const openNewSessionDraft = useSessionStore((state) => state.openNewSessionDraft);
const [connectionStatus, setConnectionStatus] = React.useState<'connecting' | 'connected' | 'error' | 'disconnected'>(
() => (typeof window !== 'undefined'
@@ -129,10 +142,37 @@ export const VSCodeLayout: React.FC = () => {
return;
}
if (!currentSessionId && !newSessionDraftOpen && currentView === 'chat') {
setCurrentView('sessions');
if (currentView !== 'chat') {
return;
}
}, [currentSessionId, newSessionDraftOpen, currentView, viewMode]);
if (currentSessionId || newSessionDraftOpen || isSyncingMessages || hasActiveSessionWork) {
return;
}
const timeoutId = window.setTimeout(() => {
const state = useSessionStore.getState();
const stillNoSession = !state.currentSessionId;
const draftStillClosed = !state.newSessionDraft?.open;
const stillSyncing = state.isSyncing;
const stillActiveWork = (() => {
const statuses = state.sessionStatus;
if (!statuses || statuses.size === 0) return false;
for (const status of statuses.values()) {
if (status?.type === 'busy' || status?.type === 'retry') return true;
}
return false;
})();
if (stillNoSession && draftStillClosed && !stillSyncing && !stillActiveWork) {
setCurrentView('sessions');
}
}, 900);
return () => {
window.clearTimeout(timeoutId);
};
}, [currentSessionId, newSessionDraftOpen, currentView, viewMode, isSyncingMessages, hasActiveSessionWork]);
const handleBackToSessions = React.useCallback(() => {
setCurrentView('sessions');