# Bootstrap System API Documentation

## Overview

This document describes the internal API of the NIP Bootstrap System. This is intended for developers who want to understand or extend the bootstrap functionality.

## Architecture

```
┌─────────────────────────────────────────────────────────────┐
│                  Bootstrap Coordinator                       │
│                    (bootstrap.nim)                           │
└────────────────────┬────────────────────────────────────────┘
                     │
        ┌────────────┼────────────┬──────────────┐
        │            │            │              │
        ▼            ▼            ▼              ▼
┌──────────┐  ┌──────────┐  ┌──────────┐  ┌──────────┐
│ Recipe   │  │Download  │  │Install   │  │ Tool     │
│ Manager  │  │ Manager  │  │ Manager  │  │ Adapters │
└──────────┘  └──────────┘  └──────────┘  └──────────┘
```

## Module: recipe_parser.nim

Parses and validates KDL recipe files.

### Types

#### `PlatformArch`
```nim
type PlatformArch* = enum
  paX86_64 = "x86_64"
  paAarch64 = "aarch64"
  paArmv7 = "armv7"
```

Supported CPU architectures.

#### `RecipeBinary`
```nim
type RecipeBinary* = object
  name*: string
  url*: string
  checksum*: string      # Format: "blake2b-<hash>"
  size*: int64           # bytes
  executable*: bool
```

Represents a standalone binary file.

#### `RecipeArchive`
```nim
type RecipeArchive* = object
  name*: string
  url*: string
  checksum*: string
  size*: int64
  extractTo*: string
```

Represents a compressed archive.

#### `RecipePlatform`
```nim
type RecipePlatform* = object
  arch*: PlatformArch
  os*: string            # "linux", "bsd", etc.
  binaries*: seq[RecipeBinary]
  archives*: seq[RecipeArchive]
```

Platform-specific binaries and archives.

#### `RecipeDependency`
```nim
type RecipeDependency* = object
  name*: string
  kind*: string          # "system", "nip", "optional"
  version*: string       # Optional version requirement
  required*: bool
```

System or package dependency.

#### `RecipeInstall`
```nim
type RecipeInstall* = object
  script*: string        # Path to installation script
  verifyScript*: string  # Path to verification script
  postInstall*: string   # Optional post-install script
```

Installation script configuration.

#### `RecipeMetadata`
```nim
type RecipeMetadata* = object
  author*: string
  license*: string
  updated*: string       # ISO date
  homepage*: string
  issues*: string
```

Recipe metadata.

#### `Recipe`
```nim
type Recipe* = object
  name*: string
  version*: string
  description*: string
  toolType*: string      # "nix", "pkgsrc", "gentoo"
  platforms*: seq[RecipePlatform]
  dependencies*: seq[RecipeDependency]
  install*: RecipeInstall
  metadata*: RecipeMetadata
```

Complete recipe definition.

### Procedures

#### `parseRecipe`
```nim
proc parseRecipe*(kdlContent: string): Option[Recipe]
```

Parse a recipe from KDL string content.

**Parameters:**
- `kdlContent` - KDL recipe content as string

**Returns:**
- `Option[Recipe]` - Parsed recipe or none if parsing fails

**Example:**
```nim
let content = readFile("minimal-nix.kdl")
let recipeOpt = parseRecipe(content)
if recipeOpt.isSome():
  let recipe = recipeOpt.get()
  echo recipe.name
```

#### `parseRecipeFile`
```nim
proc parseRecipeFile*(filePath: string): Option[Recipe]
```

Parse a recipe from a file.

**Parameters:**
- `filePath` - Path to recipe file

**Returns:**
- `Option[Recipe]` - Parsed recipe or none if parsing fails

**Example:**
```nim
let recipeOpt = parseRecipeFile("recipes/nix/minimal-nix.kdl")
```

#### `validateRecipe`
```nim
proc validateRecipe*(recipe: Recipe): tuple[valid: bool, errors: seq[string]]
```

Validate a recipe structure.

**Parameters:**
- `recipe` - Recipe to validate

**Returns:**
- Tuple of (valid, errors) where valid is true if recipe is valid

**Example:**
```nim
let (valid, errors) = validateRecipe(recipe)
if not valid:
  for error in errors:
    echo "Error: ", error
```

#### `selectPlatform`
```nim
proc selectPlatform*(recipe: Recipe, targetArch: PlatformArch,
                     targetOs: string = "linux"): Option[RecipePlatform]
```

Select appropriate platform from recipe.

**Parameters:**
- `recipe` - Recipe to select from
- `targetArch` - Target architecture
- `targetOs` - Target OS (default: "linux")

**Returns:**
- `Option[RecipePlatform]` - Selected platform or none

**Example:**
```nim
let platformOpt = selectPlatform(recipe, paX86_64, "linux")
```

#### `getCurrentPlatform`
```nim
proc getCurrentPlatform*(): tuple[arch: PlatformArch, os: string]
```

Detect current system platform.

**Returns:**
- Tuple of (arch, os)

**Example:**
```nim
let (arch, os) = getCurrentPlatform()
echo "Running on: ", arch, "/", os
```

## Module: recipe_manager.nim

Manages recipe fetching, caching, and loading.

### Types

#### `RecipeManager`
```nim
type RecipeManager* = ref object
  repoUrl*: string
  localCache*: string
  recipes*: Table[string, Recipe]
  lastUpdate*: Time
```

Manages recipe repository and caching.

#### `RecipeFetchResult`
```nim
type RecipeFetchResult* = object
  success*: bool
  message*: string
  recipesUpdated*: int
```

Result of recipe fetch operation.

### Procedures

#### `newRecipeManager`
```nim
proc newRecipeManager*(repoUrl: string = DefaultRepoUrl,
                       cacheDir: string = ""): RecipeManager
```

Create a new RecipeManager.

**Parameters:**
- `repoUrl` - Git repository URL (default: NexusToolKit repo)
- `cacheDir` - Cache directory (default: XDG cache)

**Returns:**
- `RecipeManager` instance

**Example:**
```nim
let manager = newRecipeManager()
```

#### `fetchRecipes`
```nim
proc fetchRecipes*(rm: RecipeManager): RecipeFetchResult
```

Fetch or update recipes from Git repository.

**Parameters:**
- `rm` - RecipeManager instance

**Returns:**
- `RecipeFetchResult` with status and message

**Example:**
```nim
let result = manager.fetchRecipes()
if result.success:
  echo "Updated ", result.recipesUpdated, " recipes"
```

#### `loadRecipe`
```nim
proc loadRecipe*(rm: RecipeManager, toolType: string): Option[Recipe]
```

Load and parse recipe for a tool type.

**Parameters:**
- `rm` - RecipeManager instance
- `toolType` - Tool type ("nix", "pkgsrc", "gentoo")

**Returns:**
- `Option[Recipe]` - Loaded recipe or none

**Example:**
```nim
let recipeOpt = manager.loadRecipe("nix")
if recipeOpt.isSome():
  let recipe = recipeOpt.get()
  echo "Loaded: ", recipe.name
```

#### `hasRecipe`
```nim
proc hasRecipe*(rm: RecipeManager, toolType: string): bool
```

Check if recipe exists for a tool type.

**Parameters:**
- `rm` - RecipeManager instance
- `toolType` - Tool type to check

**Returns:**
- `bool` - True if recipe exists

**Example:**
```nim
if manager.hasRecipe("nix"):
  echo "Nix recipe available"
```

#### `listAvailableRecipes`
```nim
proc listAvailableRecipes*(rm: RecipeManager): seq[string]
```

List all available recipe tool types.

**Parameters:**
- `rm` - RecipeManager instance

**Returns:**
- Sequence of tool type strings

**Example:**
```nim
for toolType in manager.listAvailableRecipes():
  echo "Available: ", toolType
```

## Module: download_manager.nim

Manages file downloads with verification.

### Types

#### `DownloadResult`
```nim
type DownloadResult* = object
  success*: bool
  filePath*: string
  message*: string
  bytesDownloaded*: int64
  duration*: Duration
```

Result of download operation.

#### `DownloadManager`
```nim
type DownloadManager* = ref object
  cacheDir*: string
  maxRetries*: int
  timeout*: Duration
  client*: HttpClient
```

Manages file downloads.

### Procedures

#### `newDownloadManager`
```nim
proc newDownloadManager*(cacheDir: string = ""): DownloadManager
```

Create a new DownloadManager.

**Parameters:**
- `cacheDir` - Cache directory (default: XDG cache)

**Returns:**
- `DownloadManager` instance

**Example:**
```nim
let manager = newDownloadManager()
defer: manager.close()
```

#### `close`
```nim
proc close*(dm: DownloadManager)
```

Close the download manager and cleanup resources.

**Parameters:**
- `dm` - DownloadManager instance

**Example:**
```nim
manager.close()
```

#### `downloadFile`
```nim
proc downloadFile*(dm: DownloadManager, url: string, destPath: string,
                   expectedChecksum: string = ""): DownloadResult
```

Download a file with checksum verification.

**Parameters:**
- `dm` - DownloadManager instance
- `url` - Download URL (HTTPS)
- `destPath` - Destination file path
- `expectedChecksum` - Expected Blake2b checksum (optional)

**Returns:**
- `DownloadResult` with status and details

**Example:**
```nim
let result = manager.downloadFile(
  "https://example.com/file",
  "/tmp/file",
  "blake2b-abc123..."
)
if result.success:
  echo "Downloaded: ", result.bytesDownloaded, " bytes"
```

#### `verifyChecksum`
```nim
proc verifyChecksum*(filePath: string, expectedChecksum: string): bool
```

Verify file checksum using Blake2b.

**Parameters:**
- `filePath` - Path to file
- `expectedChecksum` - Expected checksum in format "blake2b-<hash>"

**Returns:**
- `bool` - True if checksum matches

**Example:**
```nim
if verifyChecksum("/tmp/file", "blake2b-abc123..."):
  echo "Checksum verified"
```

#### `getCachedFile`
```nim
proc getCachedFile*(dm: DownloadManager, filename: string): string
```

Get path to cached file.

**Parameters:**
- `dm` - DownloadManager instance
- `filename` - Filename

**Returns:**
- Full path to cached file

**Example:**
```nim
let path = manager.getCachedFile("nix-build")
```

## Module: installation_manager.nim

Manages tool installation and rollback.

### Types

#### `InstallState`
```nim
type InstallState* = enum
  isNotStarted = "not_started"
  isFetching = "fetching"
  isDownloading = "downloading"
  isVerifying = "verifying"
  isExtracting = "extracting"
  isInstalling = "installing"
  isVerifyingInstall = "verifying_install"
  isComplete = "complete"
  isFailed = "failed"
```

Installation state.

#### `InstallResult`
```nim
type InstallResult* = object
  success*: bool
  toolPath*: string
  version*: string
  message*: string
  errors*: seq[string]
  warnings*: seq[string]
  installTime*: Duration
```

Result of installation operation.

#### `InstallationManager`
```nim
type InstallationManager* = ref object
  toolsDir*: string
  tempDir*: string
  backupDir*: string
```

Manages tool installation.

### Procedures

#### `newInstallationManager`
```nim
proc newInstallationManager*(toolsDir: string = ""): InstallationManager
```

Create a new InstallationManager.

**Parameters:**
- `toolsDir` - Tools directory (default: XDG data)

**Returns:**
- `InstallationManager` instance

**Example:**
```nim
let manager = newInstallationManager()
```

#### `extractArchive`
```nim
proc extractArchive*(im: InstallationManager, archivePath: string,
                     destDir: string): tuple[success: bool, message: string]
```

Extract archive to destination directory.

**Parameters:**
- `im` - InstallationManager instance
- `archivePath` - Path to archive file
- `destDir` - Destination directory

**Returns:**
- Tuple of (success, message)

**Example:**
```nim
let (success, msg) = manager.extractArchive(
  "/tmp/archive.tar.xz",
  "/opt/tool"
)
```

#### `executeScript`
```nim
proc executeScript*(im: InstallationManager, scriptPath: string,
                    workDir: string, env: Table[string, string] = initTable[string, string]()):
                    tuple[success: bool, output: string]
```

Execute installation script.

**Parameters:**
- `im` - InstallationManager instance
- `scriptPath` - Path to script
- `workDir` - Working directory
- `env` - Environment variables

**Returns:**
- Tuple of (success, output)

**Example:**
```nim
let env = {"INSTALL_DIR": "/opt/tool"}.toTable
let (success, output) = manager.executeScript(
  "install.sh",
  "/opt/tool",
  env
)
```

#### `verifyInstallation`
```nim
proc verifyInstallation*(im: InstallationManager, toolType: string,
                         verifyScript: string, toolPath: string):
                         tuple[success: bool, message: string]
```

Verify tool installation.

**Parameters:**
- `im` - InstallationManager instance
- `toolType` - Tool type
- `verifyScript` - Path to verification script
- `toolPath` - Tool installation path

**Returns:**
- Tuple of (success, message)

**Example:**
```nim
let (success, msg) = manager.verifyInstallation(
  "nix",
  "verify.sh",
  "/opt/nix"
)
```

#### `backupTool`
```nim
proc backupTool*(im: InstallationManager, toolType: string): bool
```

Backup existing tool installation.

**Parameters:**
- `im` - InstallationManager instance
- `toolType` - Tool type

**Returns:**
- `bool` - True if backup succeeded

**Example:**
```nim
if manager.backupTool("nix"):
  echo "Backup created"
```

#### `rollback`
```nim
proc rollback*(im: InstallationManager, toolType: string): bool
```

Rollback failed installation.

**Parameters:**
- `im` - InstallationManager instance
- `toolType` - Tool type

**Returns:**
- `bool` - True if rollback succeeded

**Example:**
```nim
if not installSuccess:
  discard manager.rollback("nix")
```

## Module: bootstrap.nim

Main bootstrap coordinator.

### Types

#### `BuildToolType`
```nim
type BuildToolType* = enum
  bttNix = "nix"
  bttPkgsrc = "pkgsrc"
  bttGentoo = "gentoo"
```

Supported build tool types.

#### `BootstrapResult`
```nim
type BootstrapResult* = object
  success*: bool
  toolPath*: string
  message*: string
  errors*: seq[string]
  warnings*: seq[string]
```

Result of bootstrap operation.

### Procedures

#### `isToolInstalled`
```nim
proc isToolInstalled*(toolType: BuildToolType): bool
```

Check if a build tool is installed in NIP's directory.

**Parameters:**
- `toolType` - Tool type to check

**Returns:**
- `bool` - True if installed

**Example:**
```nim
if isToolInstalled(bttNix):
  echo "Nix is installed"
```

#### `isSystemToolAvailable`
```nim
proc isSystemToolAvailable*(toolType: BuildToolType): bool
```

Check if tool is available on the system.

**Parameters:**
- `toolType` - Tool type to check

**Returns:**
- `bool` - True if available

**Example:**
```nim
if isSystemToolAvailable(bttNix):
  echo "Nix is available on system"
```

#### `handleMissingTool`
```nim
proc handleMissingTool*(toolType: BuildToolType, autoBootstrap: bool = false): bool
```

Handle missing build tool - prompt user or auto-bootstrap.

**Parameters:**
- `toolType` - Tool type
- `autoBootstrap` - Auto-install without prompting

**Returns:**
- `bool` - True if tool is now available

**Example:**
```nim
if not isToolInstalled(bttNix):
  if handleMissingTool(bttNix, autoBootstrap = true):
    echo "Nix installed successfully"
```

#### `installMinimalTools`
```nim
proc installMinimalTools*(toolType: BuildToolType): BootstrapResult
```

Install minimal build tools for the specified type.

**Parameters:**
- `toolType` - Tool type to install

**Returns:**
- `BootstrapResult` with status and details

**Example:**
```nim
let result = installMinimalTools(bttNix)
if result.success:
  echo "Installed to: ", result.toolPath
```

## Usage Examples

### Complete Installation Flow

```nim
import nimpak/build/[bootstrap, recipe_manager, download_manager, installation_manager]

# Initialize managers
let recipeManager = newRecipeManager()
let downloadManager = newDownloadManager()
let installManager = newInstallationManager()
defer: downloadManager.close()

# Fetch recipes
let fetchResult = recipeManager.fetchRecipes()
if not fetchResult.success:
  echo "Failed to fetch recipes"
  quit(1)

# Load recipe
let recipeOpt = recipeManager.loadRecipe("nix")
if recipeOpt.isNone():
  echo "Recipe not found"
  quit(1)

let recipe = recipeOpt.get()

# Select platform
let (arch, os) = getCurrentPlatform()
let platformOpt = selectPlatform(recipe, arch, os)
if platformOpt.isNone():
  echo "Platform not supported"
  quit(1)

let platform = platformOpt.get()

# Download binaries
for binary in platform.binaries:
  let destPath = downloadManager.getCachedFile(binary.name)
  let result = downloadManager.downloadFile(binary.url, destPath, binary.checksum)
  if not result.success:
    echo "Download failed: ", result.message
    quit(1)

# Install
let toolDir = "/opt/nix"
let env = {"INSTALL_DIR": toolDir}.toTable
let (success, output) = installManager.executeScript(
  recipe.install.script,
  toolDir,
  env
)

if success:
  echo "Installation successful"
else:
  echo "Installation failed: ", output
```

## Error Handling

All procedures that can fail return either:
- `Option[T]` - Use `isSome()` and `get()` to check and extract
- `tuple[success: bool, ...]` - Check `success` field
- `Result` object with `success` field

Always check return values and handle errors appropriately.

## Thread Safety

The bootstrap system is not thread-safe. Do not use the same manager instances from multiple threads.

## See Also

- [Bootstrap Guide](bootstrap-guide.md) - User documentation
- [Recipe Authoring Guide](../recipes/AUTHORING-GUIDE.md) - Creating recipes
- [Source Build Guide](source-build-guide.md) - Building from source
