Skip to content

Implement EditablePermissionRule, EditableEnvironmentVariable, and presets #111

@doomspork

Description

@doomspork

Context

UI editing types that wrap the config models with UUIDs for list identity, plus preset catalogs for quick-add functionality. These are the "form models" used by the permissions and environment variable editors.

Ported from: Fig/Sources/Models/SettingsEditorTypes.swift

What to implement

File path

  • fig-core/src/models/editable_types.rs

Rust definitions

use uuid::Uuid;
use std::collections::HashMap;

// --- Editable wrappers ---

#[derive(Debug, Clone, PartialEq)]
pub struct EditablePermissionRule {
    pub id: Uuid,
    pub rule: String,
    pub permission_type: PermissionType,
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum PermissionType {
    Allow,
    Deny,
}

impl EditablePermissionRule {
    pub fn new(rule: String, permission_type: PermissionType) -> Self {
        Self { id: Uuid::new_v4(), rule, permission_type }
    }
}

#[derive(Debug, Clone, PartialEq)]
pub struct EditableEnvironmentVariable {
    pub id: Uuid,
    pub key: String,
    pub value: String,
}

impl EditableEnvironmentVariable {
    pub fn new(key: String, value: String) -> Self {
        Self { id: Uuid::new_v4(), key, value }
    }
}

// --- Tool types for permission rules ---

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum ToolType {
    Bash,
    Read,
    Write,
    Edit,
    Grep,
    Glob,
    WebFetch,
    Notebook,
    Custom,
}

impl ToolType {
    pub fn placeholder(&self) -> &'static str {
        match self {
            Self::Bash => "Bash(*)",
            Self::Read => "Read(*)",
            Self::Write => "Write(*)",
            Self::Edit => "Edit(*)",
            Self::Grep => "Grep(*)",
            Self::Glob => "Glob(*)",
            Self::WebFetch => "WebFetch(*)",
            Self::Notebook => "NotebookEdit(*)",
            Self::Custom => "ToolName(pattern)",
        }
    }

    pub fn supports_pattern(&self) -> bool {
        !matches!(self, Self::Custom)
    }
}

// --- Permission presets ---

#[derive(Debug, Clone)]
pub struct PermissionPreset {
    pub id: &'static str,
    pub name: &'static str,
    pub description: &'static str,
    pub rules: Vec<(String, PermissionType)>,
}

pub fn permission_presets() -> Vec<PermissionPreset> {
    vec![
        PermissionPreset {
            id: "protect-env",
            name: "Protect .env files",
            description: "Deny read/write access to .env files",
            rules: vec![
                ("Read(.env*)".into(), PermissionType::Deny),
                ("Edit(.env*)".into(), PermissionType::Deny),
                ("Write(.env*)".into(), PermissionType::Deny),
            ],
        },
        PermissionPreset {
            id: "allow-npm-git",
            name: "Allow npm & git",
            description: "Allow common development commands",
            rules: vec![
                ("Bash(npm *)".into(), PermissionType::Allow),
                ("Bash(git *)".into(), PermissionType::Allow),
            ],
        },
        PermissionPreset {
            id: "read-only",
            name: "Read-only mode",
            description: "Allow reading but deny writing",
            rules: vec![
                ("Read(*)".into(), PermissionType::Allow),
                ("Write(*)".into(), PermissionType::Deny),
                ("Edit(*)".into(), PermissionType::Deny),
            ],
        },
        PermissionPreset {
            id: "read-src",
            name: "Read src/ only",
            description: "Restrict reading to src/ directory",
            rules: vec![
                ("Read(src/**)".into(), PermissionType::Allow),
            ],
        },
        PermissionPreset {
            id: "deny-curl",
            name: "Deny network access",
            description: "Block curl and wget commands",
            rules: vec![
                ("Bash(curl *)".into(), PermissionType::Deny),
                ("Bash(wget *)".into(), PermissionType::Deny),
            ],
        },
    ]
}

// --- Known environment variables ---

#[derive(Debug, Clone)]
pub struct KnownEnvironmentVariable {
    pub key: &'static str,
    pub description: &'static str,
    pub example_value: &'static str,
}

pub fn known_environment_variables() -> Vec<KnownEnvironmentVariable> {
    vec![
        KnownEnvironmentVariable {
            key: "ANTHROPIC_API_KEY",
            description: "API key for Claude",
            example_value: "sk-ant-...",
        },
        KnownEnvironmentVariable {
            key: "CLAUDE_CODE_MAX_TURNS",
            description: "Maximum conversation turns",
            example_value: "100",
        },
        KnownEnvironmentVariable {
            key: "CLAUDE_CODE_USE_BEDROCK",
            description: "Use AWS Bedrock",
            example_value: "1",
        },
        KnownEnvironmentVariable {
            key: "CLAUDE_CODE_USE_VERTEX",
            description: "Use Google Vertex AI",
            example_value: "1",
        },
        KnownEnvironmentVariable {
            key: "CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC",
            description: "Disable non-essential network traffic",
            example_value: "1",
        },
        KnownEnvironmentVariable {
            key: "HTTP_PROXY",
            description: "HTTP proxy URL",
            example_value: "http://proxy:8080",
        },
        KnownEnvironmentVariable {
            key: "HTTPS_PROXY",
            description: "HTTPS proxy URL",
            example_value: "https://proxy:8443",
        },
    ]
}

Acceptance criteria

  • EditablePermissionRule and EditableEnvironmentVariable have UUID-based identity
  • PermissionPreset provides 5+ presets with rules
  • KnownEnvironmentVariable provides 7+ known variables with descriptions
  • ToolType enum covers all Claude Code tool types
  • All types derive necessary traits for UI use

Test requirements

  • test_editable_rule_unique_ids — two rules with same text have different UUIDs
  • test_permission_presets_non_empty — all presets have at least one rule
  • test_tool_type_placeholder — all tool types return non-empty placeholders
  • test_known_env_vars — at least 7 known variables defined
  • test_preset_rules_valid_types — all preset rules have valid PermissionType

Dependencies

Requires: #93

Blocks

#112, #113

Metadata

Metadata

Assignees

No one assigned

    Labels

    epic:rust-migrationRust + Iced migration infrastructureepic:settings-editorForm-based editing of settings fieldsphase:3Phase 3 — MCP managementpriority:highMust-have for MVPtype:migrationDirect port of existing Swift functionality

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions