# Path Resolution API\n\nThis document describes the path resolution system used throughout the provisioning infrastructure for discovering configurations, extensions, and\nresolving workspace paths.\n\n## Overview\n\nThe path resolution system provides a hierarchical and configurable mechanism for:\n\n- Configuration file discovery and loading\n- Extension discovery (providers, task services, clusters)\n- Workspace and project path management\n- Environment variable interpolation\n- Cross-platform path handling\n\n## Configuration Resolution Hierarchy\n\nThe system follows a specific hierarchy for loading configuration files:\n\n```\n1. System defaults      (config.defaults.toml)\n2. User configuration   (config.user.toml)\n3. Project configuration (config.project.toml)\n4. Infrastructure config (infra/config.toml)\n5. Environment config   (config.{env}.toml)\n6. Runtime overrides    (CLI arguments, ENV vars)\n```\n\n### Configuration Search Paths\n\nThe system searches for configuration files in these locations:\n\n```\n# Default search paths (in order)\n/usr/local/provisioning/config.defaults.toml\n$HOME/.config/provisioning/config.user.toml\n$PWD/config.project.toml\n$PROVISIONING_KLOUD_PATH/config.infra.toml\n$PWD/config.{PROVISIONING_ENV}.toml\n```\n\n## Path Resolution API\n\n### Core Functions\n\n#### `resolve-config-path(pattern: string, search_paths: list<string>) -> string`\n\nResolves configuration file paths using the search hierarchy.\n\n**Parameters:**\n\n- `pattern`: File pattern to search for (for example, "config.*.toml")\n- `search_paths`: Additional paths to search (optional)\n\n**Returns:**\n\n- Full path to the first matching configuration file\n- Empty string if no file found\n\n**Example:**\n\n```\nuse path-resolution.nu *\nlet config_path = (resolve-config-path "config.user.toml" [])\n# Returns: "/home/user/.config/provisioning/config.user.toml"\n```\n\n#### `resolve-extension-path(type: string, name: string) -> record`\n\nDiscovers extension paths (providers, taskservs, clusters).\n\n**Parameters:**\n\n- `type`: Extension type ("provider", "taskserv", "cluster")\n- `name`: Extension name (for example, "upcloud", "kubernetes", "buildkit")\n\n**Returns:**\n\n```\n{\n    base_path: "/usr/local/provisioning/providers/upcloud",\n    schemas_path: "/usr/local/provisioning/providers/upcloud/schemas",\n    nulib_path: "/usr/local/provisioning/providers/upcloud/nulib",\n    templates_path: "/usr/local/provisioning/providers/upcloud/templates",\n    exists: true\n}\n```\n\n#### `resolve-workspace-paths() -> record`\n\nGets current workspace path configuration.\n\n**Returns:**\n\n```\n{\n    base: "/usr/local/provisioning",\n    current_infra: "/workspace/infra/production",\n    kloud_path: "/workspace/kloud",\n    providers: "/usr/local/provisioning/providers",\n    taskservs: "/usr/local/provisioning/taskservs",\n    clusters: "/usr/local/provisioning/cluster",\n    extensions: "/workspace/extensions"\n}\n```\n\n### Path Interpolation\n\nThe system supports variable interpolation in configuration paths:\n\n#### Supported Variables\n\n- `{{paths.base}}` - Base provisioning path\n- `{{paths.kloud}}` - Current kloud path\n- `{{env.HOME}}` - User home directory\n- `{{env.PWD}}` - Current working directory\n- `{{now.date}}` - Current date (YYYY-MM-DD)\n- `{{now.time}}` - Current time (HH:MM:SS)\n- `{{git.branch}}` - Current git branch\n- `{{git.commit}}` - Current git commit hash\n\n#### `interpolate-path(template: string, context: record) -> string`\n\nInterpolates variables in path templates.\n\n**Parameters:**\n\n- `template`: Path template with variables\n- `context`: Variable context record\n\n**Example:**\n\n```\nlet template = "{{paths.base}}/infra/{{env.USER}}/{{git.branch}}"\nlet result = (interpolate-path $template {\n    paths: { base: "/usr/local/provisioning" },\n    env: { USER: "admin" },\n    git: { branch: "main" }\n})\n# Returns: "/usr/local/provisioning/infra/admin/main"\n```\n\n## Extension Discovery API\n\n### Provider Discovery\n\n#### `discover-providers() -> list<record>`\n\nDiscovers all available providers.\n\n**Returns:**\n\n```\n[\n    {\n        name: "upcloud",\n        path: "/usr/local/provisioning/providers/upcloud",\n        type: "provider",\n        version: "1.2.0",\n        enabled: true,\n        has_schemas: true,\n        has_nulib: true,\n        has_templates: true\n    },\n    {\n        name: "aws",\n        path: "/usr/local/provisioning/providers/aws",\n        type: "provider",\n        version: "2.1.0",\n        enabled: true,\n        has_schemas: true,\n        has_nulib: true,\n        has_templates: true\n    }\n]\n```\n\n#### `get-provider-config(name: string) -> record`\n\nGets provider-specific configuration and paths.\n\n**Parameters:**\n\n- `name`: Provider name\n\n**Returns:**\n\n```\n{\n    name: "upcloud",\n    base_path: "/usr/local/provisioning/providers/upcloud",\n    config: {\n        api_url: "https://api.upcloud.com/1.3",\n        auth_method: "basic",\n        interface: "API"\n    },\n    paths: {\n        schemas: "/usr/local/provisioning/providers/upcloud/schemas",\n        nulib: "/usr/local/provisioning/providers/upcloud/nulib",\n        templates: "/usr/local/provisioning/providers/upcloud/templates"\n    },\n    metadata: {\n        version: "1.2.0",\n        description: "UpCloud provider for server provisioning"\n    }\n}\n```\n\n### Task Service Discovery\n\n#### `discover-taskservs() -> list<record>`\n\nDiscovers all available task services.\n\n**Returns:**\n\n```\n[\n    {\n        name: "kubernetes",\n        path: "/usr/local/provisioning/taskservs/kubernetes",\n        type: "taskserv",\n        category: "orchestration",\n        version: "1.28.0",\n        enabled: true\n    },\n    {\n        name: "cilium",\n        path: "/usr/local/provisioning/taskservs/cilium",\n        type: "taskserv",\n        category: "networking",\n        version: "1.14.0",\n        enabled: true\n    }\n]\n```\n\n#### `get-taskserv-config(name: string) -> record`\n\nGets task service configuration and version information.\n\n**Parameters:**\n\n- `name`: Task service name\n\n**Returns:**\n\n```\n{\n    name: "kubernetes",\n    path: "/usr/local/provisioning/taskservs/kubernetes",\n    version: {\n        current: "1.28.0",\n        available: "1.28.2",\n        update_available: true,\n        source: "github",\n        release_url: "https://github.com/kubernetes/kubernetes/releases"\n    },\n    config: {\n        category: "orchestration",\n        dependencies: ["containerd"],\n        supports_versions: ["1.26.x", "1.27.x", "1.28.x"]\n    }\n}\n```\n\n### Cluster Discovery\n\n#### `discover-clusters() -> list<record>`\n\nDiscovers all available cluster configurations.\n\n**Returns:**\n\n```\n[\n    {\n        name: "buildkit",\n        path: "/usr/local/provisioning/cluster/buildkit",\n        type: "cluster",\n        category: "build",\n        components: ["buildkit", "registry", "storage"],\n        enabled: true\n    }\n]\n```\n\n## Environment Management API\n\n### Environment Detection\n\n#### `detect-environment() -> string`\n\nAutomatically detects the current environment based on:\n\n1. `PROVISIONING_ENV` environment variable\n2. Git branch patterns (main → prod, develop → dev, etc.)\n3. Directory structure analysis\n4. Configuration file presence\n\n**Returns:**\n\n- Environment name string (dev, test, prod, etc.)\n\n#### `get-environment-config(env: string) -> record`\n\nGets environment-specific configuration.\n\n**Parameters:**\n\n- `env`: Environment name\n\n**Returns:**\n\n```\n{\n    name: "production",\n    paths: {\n        base: "/opt/provisioning",\n        kloud: "/data/kloud",\n        logs: "/var/log/provisioning"\n    },\n    providers: {\n        default: "upcloud",\n        allowed: ["upcloud", "aws"]\n    },\n    features: {\n        debug: false,\n        telemetry: true,\n        rollback: true\n    }\n}\n```\n\n### Environment Switching\n\n#### `switch-environment(env: string, validate: bool = true) -> null`\n\nSwitches to a different environment and updates path resolution.\n\n**Parameters:**\n\n- `env`: Target environment name\n- `validate`: Whether to validate environment configuration\n\n**Effects:**\n\n- Updates `PROVISIONING_ENV` environment variable\n- Reconfigures path resolution for new environment\n- Validates environment configuration if requested\n\n## Workspace Management API\n\n### Workspace Discovery\n\n#### `discover-workspaces() -> list<record>`\n\nDiscovers available workspaces and infrastructure directories.\n\n**Returns:**\n\n```\n[\n    {\n        name: "production",\n        path: "/workspace/infra/production",\n        type: "infrastructure",\n        provider: "upcloud",\n        settings: "settings.ncl",\n        valid: true\n    },\n    {\n        name: "development",\n        path: "/workspace/infra/development",\n        type: "infrastructure",\n        provider: "local",\n        settings: "dev-settings.ncl",\n        valid: true\n    }\n]\n```\n\n#### `set-current-workspace(path: string) -> null`\n\nSets the current workspace for path resolution.\n\n**Parameters:**\n\n- `path`: Workspace directory path\n\n**Effects:**\n\n- Updates `CURRENT_INFRA_PATH` environment variable\n- Reconfigures workspace-relative path resolution\n\n### Project Structure Analysis\n\n#### `analyze-project-structure(path: string = $PWD) -> record`\n\nAnalyzes project structure and identifies components.\n\n**Parameters:**\n\n- `path`: Project root path (defaults to current directory)\n\n**Returns:**\n\n```\n{\n    root: "/workspace/project",\n    type: "provisioning_workspace",\n    components: {\n        providers: [\n            { name: "upcloud", path: "providers/upcloud" },\n            { name: "aws", path: "providers/aws" }\n        ],\n        taskservs: [\n            { name: "kubernetes", path: "taskservs/kubernetes" },\n            { name: "cilium", path: "taskservs/cilium" }\n        ],\n        clusters: [\n            { name: "buildkit", path: "cluster/buildkit" }\n        ],\n        infrastructure: [\n            { name: "production", path: "infra/production" },\n            { name: "staging", path: "infra/staging" }\n        ]\n    },\n    config_files: [\n        "config.defaults.toml",\n        "config.user.toml",\n        "config.prod.toml"\n    ]\n}\n```\n\n## Caching and Performance\n\n### Path Caching\n\nThe path resolution system includes intelligent caching:\n\n#### `cache-paths(duration: duration = 5 min) -> null`\n\nEnables path caching for the specified duration.\n\n**Parameters:**\n\n- `duration`: Cache validity duration\n\n#### `invalidate-path-cache() -> null`\n\nInvalidates the path resolution cache.\n\n#### `get-cache-stats() -> record`\n\nGets path resolution cache statistics.\n\n**Returns:**\n\n```\n{\n    enabled: true,\n    size: 150,\n    hit_rate: 0.85,\n    last_invalidated: "2025-09-26T10:00:00Z"\n}\n```\n\n## Cross-Platform Compatibility\n\n### Path Normalization\n\n#### `normalize-path(path: string) -> string`\n\nNormalizes paths for cross-platform compatibility.\n\n**Parameters:**\n\n- `path`: Input path (may contain mixed separators)\n\n**Returns:**\n\n- Normalized path using platform-appropriate separators\n\n**Example:**\n\n```\n# On Windows\nnormalize-path "path/to/file" # Returns: "path\to\file"\n\n# On Unix\nnormalize-path "path\to\file" # Returns: "path/to/file"\n```\n\n#### `join-paths(segments: list<string>) -> string`\n\nSafely joins path segments using platform separators.\n\n**Parameters:**\n\n- `segments`: List of path segments\n\n**Returns:**\n\n- Joined path string\n\n## Configuration Validation API\n\n### Path Validation\n\n#### `validate-paths(config: record) -> record`\n\nValidates all paths in configuration.\n\n**Parameters:**\n\n- `config`: Configuration record\n\n**Returns:**\n\n```\n{\n    valid: true,\n    errors: [],\n    warnings: [\n        { path: "paths.extensions", message: "Path does not exist" }\n    ],\n    checks_performed: 15\n}\n```\n\n#### `validate-extension-structure(type: string, path: string) -> record`\n\nValidates extension directory structure.\n\n**Parameters:**\n\n- `type`: Extension type (provider, taskserv, cluster)\n- `path`: Extension base path\n\n**Returns:**\n\n```\n{\n    valid: true,\n    required_files: [\n        { file: "manifest.toml", exists: true },\n        { file: "schemas/main.ncl", exists: true },\n        { file: "nulib/mod.nu", exists: true }\n    ],\n    optional_files: [\n        { file: "templates/server.j2", exists: false }\n    ]\n}\n```\n\n## Command-Line Interface\n\n### Path Resolution Commands\n\nThe path resolution API is exposed via Nushell commands:\n\n```\n# Show current path configuration\nprovisioning show paths\n\n# Discover available extensions\nprovisioning discover providers\nprovisioning discover taskservs\nprovisioning discover clusters\n\n# Validate path configuration\nprovisioning validate paths\n\n# Switch environments\nprovisioning env switch prod\n\n# Set workspace\nprovisioning workspace set /path/to/infra\n```\n\n## Integration Examples\n\n### Python Integration\n\n```\nimport subprocess\nimport json\n\nclass PathResolver:\n    def __init__(self, provisioning_path="/usr/local/bin/provisioning"):\n        self.cmd = provisioning_path\n\n    def get_paths(self):\n        result = subprocess.run([\n            "nu", "-c", f"use {self.cmd} *; show-config --section=paths --format=json"\n        ], capture_output=True, text=True)\n        return json.loads(result.stdout)\n\n    def discover_providers(self):\n        result = subprocess.run([\n            "nu", "-c", f"use {self.cmd} *; discover providers --format=json"\n        ], capture_output=True, text=True)\n        return json.loads(result.stdout)\n\n# Usage\nresolver = PathResolver()\npaths = resolver.get_paths()\nproviders = resolver.discover_providers()\n```\n\n### JavaScript/Node.js Integration\n\n```\nconst { exec } = require('child_process');\nconst util = require('util');\nconst execAsync = util.promisify(exec);\n\nclass PathResolver {\n  constructor(provisioningPath = '/usr/local/bin/provisioning') {\n    this.cmd = provisioningPath;\n  }\n\n  async getPaths() {\n    const { stdout } = await execAsync(\n      `nu -c "use ${this.cmd} *; show-config --section=paths --format=json"`\n    );\n    return JSON.parse(stdout);\n  }\n\n  async discoverExtensions(type) {\n    const { stdout } = await execAsync(\n      `nu -c "use ${this.cmd} *; discover ${type} --format=json"`\n    );\n    return JSON.parse(stdout);\n  }\n}\n\n// Usage\nconst resolver = new PathResolver();\nconst paths = await resolver.getPaths();\nconst providers = await resolver.discoverExtensions('providers');\n```\n\n## Error Handling\n\n### Common Error Scenarios\n\n1. **Configuration File Not Found**\n\n   ```nushell\n   Error: Configuration file not found in search paths\n   Searched: ["/usr/local/provisioning/config.defaults.toml", ...]\n   ```\n\n1. **Extension Not Found**\n\n   ```nushell\n   Error: Provider 'missing-provider' not found\n   Available providers: ["upcloud", "aws", "local"]\n   ```\n\n2. **Invalid Path Template**\n\n   ```nushell\n   Error: Invalid template variable: {{invalid.var}}\n   Valid variables: ["paths.*", "env.*", "now.*", "git.*"]\n   ```\n\n3. **Environment Not Found**\n\n   ```nushell\n   Error: Environment 'staging' not configured\n   Available environments: ["dev", "test", "prod"]\n   ```\n\n### Error Recovery\n\nThe system provides graceful fallbacks:\n\n- Missing configuration files use system defaults\n- Invalid paths fall back to safe defaults\n- Extension discovery continues if some paths are inaccessible\n- Environment detection falls back to 'local' if detection fails\n\n## Performance Considerations\n\n### Best Practices\n\n1. **Use Path Caching**: Enable caching for frequently accessed paths\n2. **Batch Discovery**: Discover all extensions at once rather than individually\n3. **Lazy Loading**: Load extension configurations only when needed\n4. **Environment Detection**: Cache environment detection results\n\n### Monitoring\n\nMonitor path resolution performance:\n\n```\n# Get resolution statistics\nprovisioning debug path-stats\n\n# Monitor cache performance\nprovisioning debug cache-stats\n\n# Profile path resolution\nprovisioning debug profile-paths\n```\n\n## Security Considerations\n\n### Path Traversal Protection\n\nThe system includes protections against path traversal attacks:\n\n- All paths are normalized and validated\n- Relative paths are resolved within safe boundaries\n- Symlinks are validated before following\n\n### Access Control\n\nPath resolution respects file system permissions:\n\n- Configuration files require read access\n- Extension directories require read/execute access\n- Workspace directories may require write access for operations\n\nThis path resolution API provides a comprehensive and flexible system for managing the complex path requirements of multi-provider, multi-environment\ninfrastructure provisioning.
