Add per-project sandbox mode and Bedrock service-tier
Some checks failed
Build App / compute-version (pull_request) Successful in 2s
Build App / build-macos (pull_request) Successful in 2m31s
Build App / build-windows (pull_request) Successful in 8m1s
Build Container / build-container (pull_request) Successful in 8m11s
Build App / build-linux (pull_request) Failing after 1m53s
Build App / create-tag (pull_request) Has been skipped
Build App / sync-to-github (pull_request) Has been skipped

Sandbox mode: new per-project toggle that turns on Claude Code's bash
sandbox inside the container. Adds `bubblewrap` and `socat` to the
Dockerfile (the two Linux deps required by the sandbox), and emits a
managed `sandbox` block into `~/.claude/settings.json` via the existing
CLAUDE_CODE_SETTINGS_JSON entrypoint merge:

- `enabled` mirrors the Triple-C toggle and is always emitted, so the
  entrypoint's recursive jq merge clears any prior on-state from the
  persisted named volume — Triple-C is authoritative.
- `enableWeakerNestedSandbox: true` because we run inside Docker without
  privileged user namespaces.
- `allowUnsandboxedCommands: false` to disable the `dangerouslyDisableSandbox`
  escape hatch — opting into the sandbox shouldn't come with a runtime
  bypass.

When sandbox is on, a SANDBOX_INSTRUCTIONS section is appended to
CLAUDE_INSTRUCTIONS so Claude can guide users through allowing extra
paths/domains, excluding `docker *`/`watchman *` from the sandbox, and
the rule that `sandbox.enabled` is owned by Triple-C. The Claude-Code
settings fingerprint includes sandbox state (only when on, to avoid
spuriously flagging existing containers for recreation on upgrade).

Bedrock service tier: new optional field on the per-project Bedrock
config. When set, exported as ANTHROPIC_BEDROCK_SERVICE_TIER (added in
Claude Code 2.1.122) and included in the Bedrock fingerprint.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-01 12:58:54 -07:00
parent 805f815876
commit 5974347913
5 changed files with 177 additions and 24 deletions

View File

@@ -60,6 +60,7 @@ export default function ProjectCard({ project }: Props) {
const [bedrockProfile, setBedrockProfile] = useState(project.bedrock_config?.aws_profile ?? "");
const [bedrockBearerToken, setBedrockBearerToken] = useState(project.bedrock_config?.aws_bearer_token ?? "");
const [bedrockModelId, setBedrockModelId] = useState(project.bedrock_config?.model_id ?? "");
const [bedrockServiceTier, setBedrockServiceTier] = useState(project.bedrock_config?.service_tier ?? "");
// Ollama local state
const [ollamaBaseUrl, setOllamaBaseUrl] = useState(project.ollama_config?.base_url ?? "http://host.docker.internal:11434");
@@ -88,6 +89,7 @@ export default function ProjectCard({ project }: Props) {
setBedrockProfile(project.bedrock_config?.aws_profile ?? "");
setBedrockBearerToken(project.bedrock_config?.aws_bearer_token ?? "");
setBedrockModelId(project.bedrock_config?.model_id ?? "");
setBedrockServiceTier(project.bedrock_config?.service_tier ?? "");
setOllamaBaseUrl(project.ollama_config?.base_url ?? "http://host.docker.internal:11434");
setOllamaModelId(project.ollama_config?.model_id ?? "");
setOpenaiCompatibleBaseUrl(project.openai_compatible_config?.base_url ?? "http://host.docker.internal:4000");
@@ -192,6 +194,7 @@ export default function ProjectCard({ project }: Props) {
aws_bearer_token: null,
model_id: null,
disable_prompt_caching: false,
service_tier: null,
};
const defaultOllamaConfig: OllamaConfig = {
@@ -339,6 +342,16 @@ export default function ProjectCard({ project }: Props) {
}
};
const handleBedrockServiceTierBlur = async () => {
try {
const current = project.bedrock_config ?? defaultBedrockConfig;
const trimmed = bedrockServiceTier.trim();
await update({ ...project, bedrock_config: { ...current, service_tier: trimmed || null } });
} catch (err) {
console.error("Failed to update Bedrock service tier:", err);
}
};
const handleOllamaBaseUrlBlur = async () => {
try {
const current = project.ollama_config ?? defaultOllamaConfig;
@@ -692,6 +705,28 @@ export default function ProjectCard({ project }: Props) {
</button>
</div>
{/* Sandbox mode toggle */}
<div className="flex items-center gap-2">
<label className="text-xs text-[var(--text-secondary)]">Sandbox mode<Tooltip text="Enables Claude Code's bash sandbox (bubblewrap-based filesystem and network isolation). Triple-C is the source of truth for the on/off state — toggling this overrides any manual /sandbox configuration in the container's settings.json on next start. Uses enableWeakerNestedSandbox since the container runs without privileged user namespaces." /></label>
<button
onClick={async () => {
try {
await update({ ...project, sandbox_mode_enabled: !project.sandbox_mode_enabled });
} catch (err) {
console.error("Failed to update sandbox mode setting:", err);
}
}}
disabled={!isStopped}
className={`px-2 py-0.5 text-xs rounded transition-colors disabled:opacity-50 ${
project.sandbox_mode_enabled
? "bg-[var(--success)] text-white"
: "bg-[var(--bg-primary)] border border-[var(--border-color)] text-[var(--text-secondary)]"
}`}
>
{project.sandbox_mode_enabled ? "ON" : "OFF"}
</button>
</div>
{/* Mission Control toggle */}
<div className="flex items-center gap-2">
<label className="text-xs text-[var(--text-secondary)]">Mission Control<Tooltip text="Enables a web dashboard for monitoring and managing Claude sessions remotely." /></label>
@@ -953,6 +988,19 @@ export default function ProjectCard({ project }: Props) {
className={inputCls}
/>
</div>
{/* Service tier */}
<div>
<label className="block text-xs text-[var(--text-secondary)] mb-0.5">Service Tier (optional)<Tooltip text="Sets ANTHROPIC_BEDROCK_SERVICE_TIER. Valid values are determined by AWS Bedrock (e.g. 'priority'). Leave blank for the account default." /></label>
<input
value={bedrockServiceTier}
onChange={(e) => setBedrockServiceTier(e.target.value)}
onBlur={handleBedrockServiceTierBlur}
placeholder="(default)"
disabled={!isStopped}
className={inputCls}
/>
</div>
</div>
);
})()}

View File

@@ -25,6 +25,7 @@ export interface Project {
ollama_config: OllamaConfig | null;
openai_compatible_config: OpenAiCompatibleConfig | null;
allow_docker_access: boolean;
sandbox_mode_enabled: boolean;
mission_control_enabled: boolean;
full_permissions: boolean;
ssh_key_path: string | null;
@@ -61,6 +62,7 @@ export interface BedrockConfig {
aws_bearer_token: string | null;
model_id: string | null;
disable_prompt_caching: boolean;
service_tier: string | null;
}
export interface OllamaConfig {