Skip to content

[Subissue 1/7] Core Configuration Infrastructure #35

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

Fields

No fields configured for issues without a type.

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions