Remove Anthropic API key authentication support
All checks were successful
Build App / build-windows (push) Successful in 2m28s
Build App / build-linux (push) Successful in 3m13s

API key auth only provides short-lived session tokens (8hrs or until
session restart) with no refresh mechanism, unlike OAuth which persists
via .credentials.json. Remove the non-functional API key settings UI
and all supporting code (frontend state, Tauri commands, keyring
storage, container env var injection, and fingerprint-based recreation
checks) to avoid user confusion.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-01 03:59:58 +00:00
parent 01ea581f8a
commit da078af73f
10 changed files with 11 additions and 205 deletions

View File

@@ -12,7 +12,7 @@ import { useAppState } from "./store/appState";
export default function App() {
const { checkDocker, checkImage } = useDocker();
const { checkApiKey, loadSettings } = useSettings();
const { loadSettings } = useSettings();
const { refresh } = useProjects();
const { loadVersion, checkForUpdates, startPeriodicCheck } = useUpdates();
const { sessions, activeSessionId } = useAppState(
@@ -25,7 +25,6 @@ export default function App() {
checkDocker().then((available) => {
if (available) checkImage();
});
checkApiKey();
refresh();
// Update detection

View File

@@ -1,68 +1,10 @@
import { useState } from "react";
import { useSettings } from "../../hooks/useSettings";
export default function ApiKeyInput() {
const { hasKey, saveApiKey, removeApiKey } = useSettings();
const [key, setKey] = useState("");
const [error, setError] = useState<string | null>(null);
const [saving, setSaving] = useState(false);
const handleSave = async () => {
if (!key.trim()) return;
setSaving(true);
setError(null);
try {
await saveApiKey(key.trim());
setKey("");
} catch (e) {
setError(String(e));
} finally {
setSaving(false);
}
};
return (
<div>
<label className="block text-sm font-medium mb-1">Authentication</label>
<p className="text-xs text-[var(--text-secondary)] mb-3">
Each project can use <strong>claude login</strong> (OAuth, run inside the terminal), an <strong>API key</strong>, or <strong>AWS Bedrock</strong>. Set auth mode per-project.
Each project can use <strong>claude login</strong> (OAuth, run inside the terminal) or <strong>AWS Bedrock</strong>. Set auth mode per-project.
</p>
<label className="block text-xs text-[var(--text-secondary)] mb-1 mt-3">
API Key (for projects using API key mode)
</label>
{hasKey ? (
<div className="flex items-center gap-2">
<span className="text-sm text-[var(--success)]">Key configured</span>
<button
onClick={async () => {
try { await removeApiKey(); } catch (e) { setError(String(e)); }
}}
className="text-xs text-[var(--error)] hover:underline"
>
Remove
</button>
</div>
) : (
<div className="space-y-2">
<input
type="password"
value={key}
onChange={(e) => setKey(e.target.value)}
placeholder="sk-ant-..."
className="w-full px-3 py-2 bg-[var(--bg-primary)] border border-[var(--border-color)] rounded text-sm text-[var(--text-primary)] focus:outline-none focus:border-[var(--accent)]"
onKeyDown={(e) => e.key === "Enter" && handleSave()}
/>
<button
onClick={handleSave}
disabled={saving || !key.trim()}
className="px-3 py-1.5 text-xs bg-[var(--accent)] text-white rounded hover:bg-[var(--accent-hover)] disabled:opacity-50 transition-colors"
>
{saving ? "Saving..." : "Save Key"}
</button>
</div>
)}
{error && <div className="text-xs text-[var(--error)] mt-1">{error}</div>}
</div>
);
}

View File

@@ -5,39 +5,13 @@ import * as commands from "../lib/tauri-commands";
import type { AppSettings } from "../lib/types";
export function useSettings() {
const { hasKey, setHasKey, appSettings, setAppSettings } = useAppState(
const { appSettings, setAppSettings } = useAppState(
useShallow(s => ({
hasKey: s.hasKey,
setHasKey: s.setHasKey,
appSettings: s.appSettings,
setAppSettings: s.setAppSettings,
}))
);
const checkApiKey = useCallback(async () => {
try {
const has = await commands.hasApiKey();
setHasKey(has);
return has;
} catch {
setHasKey(false);
return false;
}
}, [setHasKey]);
const saveApiKey = useCallback(
async (key: string) => {
await commands.setApiKey(key);
setHasKey(true);
},
[setHasKey],
);
const removeApiKey = useCallback(async () => {
await commands.deleteApiKey();
setHasKey(false);
}, [setHasKey]);
const loadSettings = useCallback(async () => {
try {
const settings = await commands.getSettings();
@@ -59,10 +33,6 @@ export function useSettings() {
);
return {
hasKey,
checkApiKey,
saveApiKey,
removeApiKey,
appSettings,
loadSettings,
saveSettings,

View File

@@ -26,10 +26,6 @@ export const rebuildProjectContainer = (projectId: string) =>
invoke<Project>("rebuild_project_container", { projectId });
// Settings
export const setApiKey = (key: string) =>
invoke<void>("set_api_key", { key });
export const hasApiKey = () => invoke<boolean>("has_api_key");
export const deleteApiKey = () => invoke<void>("delete_api_key");
export const getSettings = () => invoke<AppSettings>("get_settings");
export const updateSettings = (settings: AppSettings) =>
invoke<AppSettings>("update_settings", { settings });

View File

@@ -24,9 +24,6 @@ interface AppState {
setDockerAvailable: (available: boolean | null) => void;
imageExists: boolean | null;
setImageExists: (exists: boolean | null) => void;
hasKey: boolean | null;
setHasKey: (has: boolean | null) => void;
// App settings
appSettings: AppSettings | null;
setAppSettings: (settings: AppSettings) => void;
@@ -85,9 +82,6 @@ export const useAppState = create<AppState>((set) => ({
setDockerAvailable: (available) => set({ dockerAvailable: available }),
imageExists: null,
setImageExists: (exists) => set({ imageExists: exists }),
hasKey: null,
setHasKey: (has) => set({ hasKey: has }),
// App settings
appSettings: null,
setAppSettings: (settings) => set({ appSettings: settings }),