Skip to content

[Subissue 1/7] Core Configuration Infrastructure #35

@josecelano

Description

@josecelano

Overview

Implement core configuration infrastructure in the domain layer with pure configuration value objects, business validation rules, and explicit error handling.

Parent EPIC: #34 - Implement Create Environment Command
Related: Full Specification | Roadmap Task 1.5

Key Architecture Points

  • Configuration uses SshCredentialsConfig (distinct from adapters::ssh::SshCredentials)
  • Converts config strings to domain types (Username, PathBuf)
  • JSON Schema validation is optional - can defer to focus on domain validation first
  • All errors implement .help() methods (tiered help system pattern)

Goals

  • Create configuration value objects that convert to existing domain types

    • EnvironmentCreationConfig with to_environment_params() method
    • SshCredentialsConfig (config layer) distinct from adapters::ssh::SshCredentials
    • Convert string username to shared::Username type
    • Convert string paths to PathBuf
    • Use existing EnvironmentName::new() validation
  • Configuration validation

    • Primary validation via domain layer (EnvironmentName, Username, file existence)
    • Follow existing error handling patterns with thiserror and .help() methods
    • Optional: Secondary validation via JSON Schema
  • Add comprehensive unit tests

    • Test conversion to Environment::new() parameters
    • Test Username type conversion from string
    • Test compatibility with repository.save(&environment.into_any())
    • Test invalid username and environment name handling

Module Structure

src/domain/config/
├── mod.rs                    # Module exports
├── environment_config.rs     # EnvironmentCreationConfig value object
├── ssh_credentials_config.rs # SshCredentialsConfig value object
├── errors.rs                 # ConfigValidationError enum with .help()
├── schema.rs                 # Optional: JSON Schema validation
└── validation.rs             # Optional: Domain validation helpers

Key Types

EnvironmentCreationConfig

pub struct EnvironmentCreationConfig {
    pub environment: EnvironmentSection,
    pub ssh_credentials: SshCredentialsConfig,
}

impl EnvironmentCreationConfig {
    pub fn to_environment_params(self) 
        -> Result<(EnvironmentName, SshCredentials, u16), CreateConfigError> {
        // Convert to existing domain types
    }
}

SshCredentialsConfig

pub struct SshCredentialsConfig {
    pub private_key_path: String,
    pub public_key_path: String,
    #[serde(default = "default_ssh_username")]
    pub username: String,
    #[serde(default = "default_ssh_port")]
    pub port: u16,
}

Error Types with .help()

#[derive(Debug, Error)]
pub enum CreateConfigError {
    #[error("Invalid environment name")]
    InvalidEnvironmentName(#[source] EnvironmentNameError),
    
    #[error("Invalid SSH username")]
    InvalidUsername(#[source] UsernameError),
    
    // ... other variants
}

impl CreateConfigError {
    pub fn help(&self) -> &'static str {
        // Detailed troubleshooting guidance
    }
}

Acceptance Criteria

  • EnvironmentCreationConfig deserializes from JSON
  • to_environment_params() converts to domain types successfully
  • Invalid environment names rejected with clear errors
  • Invalid usernames rejected with clear errors
  • SSH key file validation (existence checks)
  • All errors implement .help() with detailed guidance
  • Unit tests cover all conversion and validation scenarios
  • Integration with existing Environment::new() verified

Dependencies

[dependencies]
serde = { version = "1.0", features = ["derive"] }
thiserror = "1.0"

# Optional (can defer):
jsonschema = "0.21"  # JSON Schema validation
serde_json = "1.0"   # JSON Schema handling

Estimated Time

2-3 hours

Notes

  • JSON Schema validation is optional enhancement - domain validation is primary
  • Focus on type-safe conversion from config strings to domain types
  • Maintain clean separation: config layer vs domain/adapters layer
  • All error messages must be actionable with .help() methods

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions