856 lines
17 KiB
Markdown
856 lines
17 KiB
Markdown
# 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
|