polish: wizard secure defaults, full summary, architecture SVG update

Wizard:
- Default autonomy now Supervised + workspace_only=true (was Full + false)
- print_summary shows Tunnel, Composio, Secrets, Gateway status
- run_quick_setup shows Gateway, Tunnel, Composio in summary
- Quick setup next steps include gateway command
- Removed unused AutonomyLevel import

Architecture SVG:
- Sandbox section: 'Default: Supervised + workspace-only'
- Wizard section: 'Live connection testing | Secure defaults'
- Step 3: '7 channels + live test', Step 7: '8 workspace MD files'
- Wizard output summary line listing all 9 config areas
- Footer: 8 traits, 17,800+ lines, 0 clippy warnings

README:
- Config example clarifies supervised + workspace_only are defaults

1,017 tests, 0 clippy warnings, cargo fmt clean.
This commit is contained in:
argenis de la rosa 2026-02-14 04:00:01 -05:00
parent 1fd51f1984
commit a74a774ad5
3 changed files with 88 additions and 32 deletions

View file

@ -141,8 +141,8 @@ require_pairing = true # require pairing code on first connect
allow_public_bind = false # refuse 0.0.0.0 without tunnel allow_public_bind = false # refuse 0.0.0.0 without tunnel
[autonomy] [autonomy]
level = "supervised" # "readonly", "supervised", "full" level = "supervised" # "readonly", "supervised", "full" (default: supervised)
workspace_only = true workspace_only = true # default: true — scoped to workspace
allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep"] allowed_commands = ["git", "npm", "cargo", "ls", "cat", "grep"]
forbidden_paths = ["/etc", "/root", "/proc", "/sys", "~/.ssh", "~/.gnupg", "~/.aws"] forbidden_paths = ["/etc", "/root", "/proc", "/sys", "~/.ssh", "~/.gnupg", "~/.aws"]

View file

@ -1,4 +1,4 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 920" font-family="'Segoe UI', system-ui, -apple-system, sans-serif"> <svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1100 950" font-family="'Segoe UI', system-ui, -apple-system, sans-serif">
<defs> <defs>
<filter id="shadow" x="-4%" y="-4%" width="108%" height="108%"> <filter id="shadow" x="-4%" y="-4%" width="108%" height="108%">
<feDropShadow dx="0" dy="2" stdDeviation="3" flood-opacity="0.15"/> <feDropShadow dx="0" dy="2" stdDeviation="3" flood-opacity="0.15"/>
@ -24,11 +24,11 @@
</defs> </defs>
<!-- Background --> <!-- Background -->
<rect width="1100" height="920" rx="12" fill="url(#bgGrad)"/> <rect width="1100" height="950" rx="12" fill="url(#bgGrad)"/>
<!-- Title --> <!-- Title -->
<text x="550" y="38" text-anchor="middle" fill="#e6edf3" font-size="22" font-weight="700">ZeroClaw Architecture</text> <text x="550" y="38" text-anchor="middle" fill="#e6edf3" font-size="22" font-weight="700">ZeroClaw Architecture</text>
<text x="550" y="58" text-anchor="middle" fill="#7d8590" font-size="12">Zero overhead. Zero compromise. 100% Rust. 100% Agnostic.</text> <text x="550" y="58" text-anchor="middle" fill="#7d8590" font-size="12">Zero overhead. Zero compromise. 100% Rust. 100% Agnostic. 8 pluggable traits.</text>
<!-- ═══════════ LEFT: Chat Apps ═══════════ --> <!-- ═══════════ LEFT: Chat Apps ═══════════ -->
<rect x="20" y="80" width="150" height="310" rx="10" fill="#1c2333" stroke="#3b82f6" stroke-width="1.5" filter="url(#shadow)"/> <rect x="20" y="80" width="150" height="310" rx="10" fill="#1c2333" stroke="#3b82f6" stroke-width="1.5" filter="url(#shadow)"/>
@ -240,8 +240,8 @@
<text x="695" y="652" text-anchor="middle" fill="#ef4444" font-size="9">Null byte injection blocked</text> <text x="695" y="652" text-anchor="middle" fill="#ef4444" font-size="9">Null byte injection blocked</text>
<text x="695" y="669" text-anchor="middle" fill="#ef4444" font-size="9">Symlink escape detection</text> <text x="695" y="669" text-anchor="middle" fill="#ef4444" font-size="9">Symlink escape detection</text>
<text x="695" y="686" text-anchor="middle" fill="#ef4444" font-size="9">14 system dirs + 4 dotfiles blocked</text> <text x="695" y="686" text-anchor="middle" fill="#ef4444" font-size="9">14 system dirs + 4 dotfiles blocked</text>
<text x="695" y="706" text-anchor="middle" fill="#ef4444" font-size="9">Autonomy: ReadOnly / Supervised / Full</text> <text x="695" y="706" text-anchor="middle" fill="#ef4444" font-size="9">Default: Supervised + workspace-only</text>
<text x="695" y="726" text-anchor="middle" fill="#ef4444" font-size="9">Workspace-only mode (default)</text> <text x="695" y="726" text-anchor="middle" fill="#ef4444" font-size="9">Levels: ReadOnly / Supervised / Full</text>
<!-- Arrow: Agent → Sandbox --> <!-- Arrow: Agent → Sandbox -->
<line x1="695" y1="550" x2="695" y2="570" stroke="#ef4444" stroke-width="2"/> <line x1="695" y1="550" x2="695" y2="570" stroke="#ef4444" stroke-width="2"/>
@ -259,9 +259,9 @@
<line x1="960" y1="550" x2="960" y2="570" stroke="#06b6d4" stroke-width="2"/> <line x1="960" y1="550" x2="960" y2="570" stroke="#06b6d4" stroke-width="2"/>
<!-- ═══════════ BOTTOM: Setup Wizard ═══════════ --> <!-- ═══════════ BOTTOM: Setup Wizard ═══════════ -->
<rect x="20" y="760" width="1060" height="140" rx="10" fill="#1c2333" stroke="#f472b6" stroke-width="1.5" filter="url(#shadow)"/> <rect x="20" y="760" width="1060" height="170" rx="10" fill="#1c2333" stroke="#f472b6" stroke-width="1.5" filter="url(#shadow)"/>
<text x="550" y="785" text-anchor="middle" fill="#f9a8d4" font-size="14" font-weight="700">Setup Wizard -- zeroclaw onboard (--quick for instant setup)</text> <text x="550" y="785" text-anchor="middle" fill="#f9a8d4" font-size="14" font-weight="700">Setup Wizard -- zeroclaw onboard (--quick for instant setup)</text>
<text x="550" y="802" text-anchor="middle" fill="#7d8590" font-size="10">7 steps, under 60 seconds</text> <text x="550" y="802" text-anchor="middle" fill="#7d8590" font-size="10">7 steps, under 60 seconds | Live connection testing | Secure defaults</text>
<!-- Wizard steps: 7 --> <!-- Wizard steps: 7 -->
<rect x="30" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/> <rect x="30" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/>
@ -274,7 +274,7 @@
<rect x="310" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/> <rect x="310" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/>
<text x="375" y="831" text-anchor="middle" fill="#e9d5ff" font-size="8" font-weight="600">3. Channels</text> <text x="375" y="831" text-anchor="middle" fill="#e9d5ff" font-size="8" font-weight="600">3. Channels</text>
<text x="375" y="845" text-anchor="middle" fill="#a78bfa" font-size="7">7 channels + test</text> <text x="375" y="845" text-anchor="middle" fill="#a78bfa" font-size="7">7 channels + live test</text>
<rect x="450" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/> <rect x="450" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/>
<text x="515" y="831" text-anchor="middle" fill="#e9d5ff" font-size="8" font-weight="600">4. Tunnel</text> <text x="515" y="831" text-anchor="middle" fill="#e9d5ff" font-size="8" font-weight="600">4. Tunnel</text>
@ -290,7 +290,7 @@
<rect x="870" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/> <rect x="870" y="815" width="130" height="38" rx="8" fill="#2d1f3d" stroke="#c084fc" stroke-width="1"/>
<text x="935" y="831" text-anchor="middle" fill="#e9d5ff" font-size="8" font-weight="600">7. Scaffold</text> <text x="935" y="831" text-anchor="middle" fill="#e9d5ff" font-size="8" font-weight="600">7. Scaffold</text>
<text x="935" y="845" text-anchor="middle" fill="#a78bfa" font-size="7">workspace MD files</text> <text x="935" y="845" text-anchor="middle" fill="#a78bfa" font-size="7">8 workspace MD files</text>
<!-- Step arrows --> <!-- Step arrows -->
<line x1="160" y1="834" x2="170" y2="834" stroke="#c084fc" stroke-width="1" marker-end="url(#arrowPurple)"/> <line x1="160" y1="834" x2="170" y2="834" stroke="#c084fc" stroke-width="1" marker-end="url(#arrowPurple)"/>
@ -300,10 +300,13 @@
<line x1="720" y1="834" x2="730" y2="834" stroke="#c084fc" stroke-width="1" marker-end="url(#arrowPurple)"/> <line x1="720" y1="834" x2="730" y2="834" stroke="#c084fc" stroke-width="1" marker-end="url(#arrowPurple)"/>
<line x1="860" y1="834" x2="870" y2="834" stroke="#c084fc" stroke-width="1" marker-end="url(#arrowPurple)"/> <line x1="860" y1="834" x2="870" y2="834" stroke="#c084fc" stroke-width="1" marker-end="url(#arrowPurple)"/>
<!-- Wizard output summary -->
<text x="550" y="872" text-anchor="middle" fill="#7d8590" font-size="9">Full summary: Provider, Model, Channels, Tunnel, Composio, Secrets, Gateway, Autonomy, Memory</text>
<!-- Ready badge --> <!-- Ready badge -->
<rect x="380" y="862" width="340" height="28" rx="14" fill="#166534" stroke="#4ade80" stroke-width="1"/> <rect x="380" y="888" width="340" height="28" rx="14" fill="#166534" stroke="#4ade80" stroke-width="1"/>
<text x="550" y="881" text-anchor="middle" fill="#4ade80" font-size="12" font-weight="600">Ready -- zeroclaw agent</text> <text x="550" y="907" text-anchor="middle" fill="#4ade80" font-size="12" font-weight="600">Ready -- zeroclaw agent</text>
<!-- Footer stats --> <!-- Footer stats -->
<text x="550" y="912" text-anchor="middle" fill="#7d8590" font-size="10">~3.4MB binary | &lt;10ms startup | 1,017 tests | 22+ providers | 7 channels | 5 tunnels | Encrypted secrets | Pluggable everything</text> <text x="550" y="942" text-anchor="middle" fill="#7d8590" font-size="10">~3.4MB binary | &lt;10ms startup | 1,017 tests | 22+ providers | 8 traits | 17,800+ lines of Rust | 0 clippy warnings</text>
</svg> </svg>

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 23 KiB

Before After
Before After

View file

@ -3,7 +3,6 @@ use crate::config::{
IMessageConfig, MatrixConfig, MemoryConfig, ObservabilityConfig, RuntimeConfig, SecretsConfig, IMessageConfig, MatrixConfig, MemoryConfig, ObservabilityConfig, RuntimeConfig, SecretsConfig,
SlackConfig, TelegramConfig, WebhookConfig, SlackConfig, TelegramConfig, WebhookConfig,
}; };
use crate::security::AutonomyLevel;
use anyhow::{Context, Result}; use anyhow::{Context, Result};
use console::style; use console::style;
use dialoguer::{Confirm, Input, Select}; use dialoguer::{Confirm, Input, Select};
@ -77,7 +76,7 @@ pub fn run_wizard() -> Result<Config> {
scaffold_workspace(&workspace_dir, &project_ctx)?; scaffold_workspace(&workspace_dir, &project_ctx)?;
// ── Build config ── // ── Build config ──
// Defaults: SQLite memory, full autonomy, full computer access, native runtime // Defaults: SQLite memory, supervised autonomy, workspace-scoped, native runtime
let config = Config { let config = Config {
workspace_dir: workspace_dir.clone(), workspace_dir: workspace_dir.clone(),
config_path: config_path.clone(), config_path: config_path.clone(),
@ -90,11 +89,7 @@ pub fn run_wizard() -> Result<Config> {
default_model: Some(model), default_model: Some(model),
default_temperature: 0.7, default_temperature: 0.7,
observability: ObservabilityConfig::default(), observability: ObservabilityConfig::default(),
autonomy: AutonomyConfig { autonomy: AutonomyConfig::default(),
level: AutonomyLevel::Full,
workspace_only: false,
..AutonomyConfig::default()
},
runtime: RuntimeConfig::default(), runtime: RuntimeConfig::default(),
heartbeat: HeartbeatConfig::default(), heartbeat: HeartbeatConfig::default(),
channels_config, channels_config,
@ -106,9 +101,9 @@ pub fn run_wizard() -> Result<Config> {
}; };
println!( println!(
" {} Security: {} | Full computer access", " {} Security: {} | workspace-scoped",
style("").green().bold(), style("").green().bold(),
style("Full Autonomy").green() style("Supervised").green()
); );
println!( println!(
" {} Memory: {} (auto-save: on)", " {} Memory: {} (auto-save: on)",
@ -188,11 +183,7 @@ pub fn run_quick_setup(api_key: Option<&str>, provider: Option<&str>) -> Result<
default_model: Some(model.clone()), default_model: Some(model.clone()),
default_temperature: 0.7, default_temperature: 0.7,
observability: ObservabilityConfig::default(), observability: ObservabilityConfig::default(),
autonomy: AutonomyConfig { autonomy: AutonomyConfig::default(),
level: AutonomyLevel::Full,
workspace_only: false,
..AutonomyConfig::default()
},
runtime: RuntimeConfig::default(), runtime: RuntimeConfig::default(),
heartbeat: HeartbeatConfig::default(), heartbeat: HeartbeatConfig::default(),
channels_config: ChannelsConfig::default(), channels_config: ChannelsConfig::default(),
@ -241,7 +232,7 @@ pub fn run_quick_setup(api_key: Option<&str>, provider: Option<&str>) -> Result<
println!( println!(
" {} Security: {}", " {} Security: {}",
style("").green().bold(), style("").green().bold(),
style("Full Autonomy").green() style("Supervised (workspace-scoped)").green()
); );
println!( println!(
" {} Memory: {}", " {} Memory: {}",
@ -253,6 +244,21 @@ pub fn run_quick_setup(api_key: Option<&str>, provider: Option<&str>) -> Result<
style("").green().bold(), style("").green().bold(),
style("encrypted").green() style("encrypted").green()
); );
println!(
" {} Gateway: {}",
style("").green().bold(),
style("pairing required (127.0.0.1:8080)").green()
);
println!(
" {} Tunnel: {}",
style("").green().bold(),
style("none (local only)").dim()
);
println!(
" {} Composio: {}",
style("").green().bold(),
style("disabled (sovereign mode)").dim()
);
println!(); println!();
println!( println!(
" {} {}", " {} {}",
@ -260,13 +266,16 @@ pub fn run_quick_setup(api_key: Option<&str>, provider: Option<&str>) -> Result<
style(config_path.display()).green() style(config_path.display()).green()
); );
println!(); println!();
println!(" Next steps:"); println!(" {}", style("Next steps:").white().bold());
if api_key.is_none() { if api_key.is_none() {
println!(" 1. Set your API key: export OPENROUTER_API_KEY=\"sk-...\""); println!(" 1. Set your API key: export OPENROUTER_API_KEY=\"sk-...\"");
println!(" 2. Or edit: ~/.zeroclaw/config.toml"); println!(" 2. Or edit: ~/.zeroclaw/config.toml");
println!(" 3. Run: zeroclaw agent -m \"Hello!\""); println!(" 3. Chat: zeroclaw agent -m \"Hello!\"");
println!(" 4. Gateway: zeroclaw gateway");
} else { } else {
println!(" Run: zeroclaw agent -m \"Hello!\""); println!(" 1. Chat: zeroclaw agent -m \"Hello!\"");
println!(" 2. Gateway: zeroclaw gateway");
println!(" 3. Status: zeroclaw status --verbose");
} }
println!(); println!();
@ -1828,6 +1837,50 @@ fn print_summary(config: &Config) {
} }
); );
// Tunnel
println!(
" {} Tunnel: {}",
style("🌐").cyan(),
if config.tunnel.provider == "none" || config.tunnel.provider.is_empty() {
"none (local only)".to_string()
} else {
config.tunnel.provider.clone()
}
);
// Composio
println!(
" {} Composio: {}",
style("🔗").cyan(),
if config.composio.enabled {
style("enabled (1000+ OAuth apps)").green().to_string()
} else {
"disabled (sovereign mode)".to_string()
}
);
// Secrets
println!(
" {} Secrets: {}",
style("🔒").cyan(),
if config.secrets.encrypt {
style("encrypted").green().to_string()
} else {
style("plaintext").yellow().to_string()
}
);
// Gateway
println!(
" {} Gateway: {}",
style("🚪").cyan(),
if config.gateway.require_pairing {
"pairing required (secure)"
} else {
"pairing disabled"
}
);
println!(); println!();
println!(" {}", style("Next steps:").white().bold()); println!(" {}", style("Next steps:").white().bold());
println!(); println!();