Compare commits

..

2 Commits

Author SHA1 Message Date
01ea581f8a Fix type inference error for api_key after removing ApiKey auth mode
All checks were successful
Build App / build-linux (push) Successful in 2m42s
Build App / build-windows (push) Successful in 2m44s
Both match arms now return None, so Rust needs an explicit type
annotation for the Option<String>.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:15:50 +00:00
552aaebf16 Simplify auth modes to Anthropic and Bedrock, fix Windows taskbar icon
Some checks failed
Build App / build-linux (push) Failing after 1m40s
Build App / build-windows (push) Failing after 1m43s
Replace the three auth modes (Login, API Key, Bedrock) with two
(Anthropic, Bedrock). The Anthropic mode uses OAuth via `claude login`
inside the terminal, which generates and stores its own API key in the
persistent config volume. The separate API Key mode is removed because
Claude Code now requires interactive approval of externally-provided
keys, making the injected ANTHROPIC_API_KEY approach unreliable.

Old projects stored as "login" or "api_key" are automatically migrated
to "anthropic" via serde aliases.

Also fix the Windows taskbar icon showing as a black square by loading
icon.png instead of icon.ico for the runtime window icon.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-01 03:10:57 +00:00
7 changed files with 15 additions and 31 deletions

View File

@@ -47,8 +47,7 @@ Triple-C is a cross-platform desktop application that sandboxes Claude Code insi
Each project can independently use one of: Each project can independently use one of:
- **`/login`** (OAuth): User runs `claude login` inside the terminal. Token persisted in the config volume. - **Anthropic** (OAuth): User runs `claude login` inside the terminal on first use. Token persisted in the config volume across restarts and resets.
- **API Key**: Stored in the OS keychain, injected as `ANTHROPIC_API_KEY` env var.
- **AWS Bedrock**: Per-project AWS credentials (static keys, profile, or bearer token). - **AWS Bedrock**: Per-project AWS credentials (static keys, profile, or bearer token).
### Container Spawning (Sibling Containers) ### Container Spawning (Sibling Containers)

View File

@@ -125,13 +125,8 @@ pub async fn start_project_container(
let image_name = container_config::resolve_image_name(&settings.image_source, &settings.custom_image_name); let image_name = container_config::resolve_image_name(&settings.image_source, &settings.custom_image_name);
// Get API key only if auth mode requires it // Get API key only if auth mode requires it
let api_key = match project.auth_mode { let api_key: Option<String> = match project.auth_mode {
AuthMode::ApiKey => { AuthMode::Anthropic => {
let key = secure::get_api_key()?
.ok_or_else(|| "No API key configured. Please set your Anthropic API key in Settings.".to_string())?;
Some(key)
}
AuthMode::Login => {
None None
} }
AuthMode::Bedrock => { AuthMode::Bedrock => {

View File

@@ -43,7 +43,7 @@ pub fn run() {
exec_manager: ExecSessionManager::new(), exec_manager: ExecSessionManager::new(),
}) })
.setup(|app| { .setup(|app| {
match tauri::image::Image::from_bytes(include_bytes!("../icons/icon.ico")) { match tauri::image::Image::from_bytes(include_bytes!("../icons/icon.png")) {
Ok(icon) => { Ok(icon) => {
if let Some(window) = app.get_webview_window("main") { if let Some(window) = app.get_webview_window("main") {
let _ = window.set_icon(icon); let _ = window.set_icon(icon);

View File

@@ -46,20 +46,21 @@ pub enum ProjectStatus {
} }
/// How the project authenticates with Claude. /// How the project authenticates with Claude.
/// - `Login`: User runs `claude login` inside the container (OAuth, persisted via config volume) /// - `Anthropic`: User runs `claude login` inside the container (OAuth via Anthropic Console,
/// - `ApiKey`: Uses the API key stored in the OS keychain /// persisted in the config volume)
/// - `Bedrock`: Uses AWS Bedrock with per-project AWS credentials /// - `Bedrock`: Uses AWS Bedrock with per-project AWS credentials
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
#[serde(rename_all = "snake_case")] #[serde(rename_all = "snake_case")]
pub enum AuthMode { pub enum AuthMode {
Login, /// Backward compat: old projects stored as "login" or "api_key" map to Anthropic.
ApiKey, #[serde(alias = "login", alias = "api_key")]
Anthropic,
Bedrock, Bedrock,
} }
impl Default for AuthMode { impl Default for AuthMode {
fn default() -> Self { fn default() -> Self {
Self::Login Self::Anthropic
} }
} }

View File

@@ -47,7 +47,7 @@ const mockProject: Project = {
paths: [{ host_path: "/home/user/project", mount_name: "project" }], paths: [{ host_path: "/home/user/project", mount_name: "project" }],
container_id: null, container_id: null,
status: "stopped", status: "stopped",
auth_mode: "login", auth_mode: "anthropic",
bedrock_config: null, bedrock_config: null,
allow_docker_access: false, allow_docker_access: false,
ssh_key_path: null, ssh_key_path: null,

View File

@@ -267,26 +267,15 @@ export default function ProjectCard({ project }: Props) {
<div className="flex items-center gap-1 text-xs"> <div className="flex items-center gap-1 text-xs">
<span className="text-[var(--text-secondary)] mr-1">Auth:</span> <span className="text-[var(--text-secondary)] mr-1">Auth:</span>
<button <button
onClick={(e) => { e.stopPropagation(); handleAuthModeChange("login"); }} onClick={(e) => { e.stopPropagation(); handleAuthModeChange("anthropic"); }}
disabled={!isStopped} disabled={!isStopped}
className={`px-2 py-0.5 rounded transition-colors ${ className={`px-2 py-0.5 rounded transition-colors ${
project.auth_mode === "login" project.auth_mode === "anthropic"
? "bg-[var(--accent)] text-white" ? "bg-[var(--accent)] text-white"
: "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]" : "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]"
} disabled:opacity-50`} } disabled:opacity-50`}
> >
/login Anthropic
</button>
<button
onClick={(e) => { e.stopPropagation(); handleAuthModeChange("api_key"); }}
disabled={!isStopped}
className={`px-2 py-0.5 rounded transition-colors ${
project.auth_mode === "api_key"
? "bg-[var(--accent)] text-white"
: "text-[var(--text-secondary)] hover:text-[var(--text-primary)] hover:bg-[var(--bg-primary)]"
} disabled:opacity-50`}
>
API key
</button> </button>
<button <button
onClick={(e) => { e.stopPropagation(); handleAuthModeChange("bedrock"); }} onClick={(e) => { e.stopPropagation(); handleAuthModeChange("bedrock"); }}

View File

@@ -34,7 +34,7 @@ export type ProjectStatus =
| "stopping" | "stopping"
| "error"; | "error";
export type AuthMode = "login" | "api_key" | "bedrock"; export type AuthMode = "anthropic" | "bedrock";
export type BedrockAuthMethod = "static_credentials" | "profile" | "bearer_token"; export type BedrockAuthMethod = "static_credentials" | "profile" | "bearer_token";