Source of truth (2026)
  • DataManagementEngineStandard/SetUp/SetupWizard.cs
  • DataManagementEngineStandard/SetUp/SetupWizardBuilder.cs
  • DataManagementEngineStandard/SetUp/SetupContext.cs
  • DataManagementEngineStandard/SetUp/SetupState.cs
  • DataManagementEngineStandard/SetUp/SetupOptions.cs
  • DataManagementEngineStandard/SetUp/SetupReport.cs
  • DataManagementEngineStandard/SetUp/ISetupStep.cs
  • DataManagementEngineStandard/SetUp/Steps/
  • DataManagementEngineStandard/SetUp/Adapters/

Overview

The Setup Framework automates the end-to-end initialization of BeepDM applications. It provides:

  • Step-based execution - Each step handles one responsibility (drivers, connections, schema, seeding)
  • Idempotency - Steps detect when work is done and skip safely
  • Checkpointing - State persisted after each step for resume after interruption
  • Cross-platform - Adapters for WinForms, WPF, Blazor, MAUI, CLI, Web API
  • Progress reporting - IProgress<PassedArgs> per-step
  • SHA-256 verified reports - Tamper-evident outcome with per-step timings

Architecture

SetupWizard (orchestrator)
├── SetupWizardBuilder (fluent configuration)
├── SetupContext (shared state)
│   ├── IDMEEditor
│   ├── SetupOptions
│   └── SetupState
├── SetupState (checkpoint)
│   ├── CompletedStepIds
│   ├── SkippedStepIds
│   ├── FailedStepId
│   └── CompletedSeederIds
├── ISetupStep[] (steps)
│   ├── DriverProvisionStep
│   ├── ConnectionConfigStep
│   ├── SchemaSetupStep
│   └── SeedingStep
└── ISetupWizardAdapter (platform bridge)
    ├── DesktopSetupWizardAdapter
    ├── WebSetupWizardAdapter
    ├── BlazorSetupWizardAdapter
    ├── MauiSetupWizardAdapter
    └── CliSetupWizardAdapter

SetupWizard

Core orchestrator that runs registered steps in sequence:

public class SetupWizard : ISetupWizard
{
    public SetupWizard(
        string wizardId,
        IEnumerable<ISetupStep> steps,
        SetupOptions options);

    // Properties
    public IReadOnlyList<ISetupStep> Steps { get; }
    public SetupState State { get; }
    public SetupOptions Options { get; }

    // Execution
    public IErrorsInfo Run(
        SetupContext context,
        IProgress<PassedArgs> progress = null);

    // Resume from checkpoint
    public IErrorsInfo Resume(
        SetupContext context,
        IProgress<PassedArgs> progress = null);

    // Report
    public SetupReport GetReport();
}

Execution Flow

  1. Load persisted checkpoint if state is empty
  2. Validate step definitions (unique IDs, valid dependencies)
  3. For each incomplete step:
    • Check dependencies are completed
    • Validate step configuration
    • Check CanSkip (idempotency)
    • Execute step
    • Mark as completed
    • Persist checkpoint
  4. Build SHA-256 verified report

SetupWizardBuilder

var wizard = new SetupWizardBuilder()
    .WithId("app-setup")
    .WithEnvironment("Development")
    .AddStep(new DriverProvisionStep(driverOpts))
    .AddStep(new ConnectionConfigStep(connOpts))
    .AddStep(new SchemaSetupStep(schemaOpts))
    .AddStep(new SeedingStep(seedingOpts))
    .Build();

SetupContext

Shared state read/written by all steps:

public class SetupContext
{
    public IDMEEditor Editor { get; set; }
    public SetupOptions Options { get; set; }
    public SetupState State { get; set; }
    public ISetupProgressReporter ProgressReporter { get; set; }

    // Step-specific data
    public Dictionary<string, object> StepData { get; set; }
}

SetupOptions

PropertyDefaultDescription
StateFilePathnullPath to persist checkpoint JSON
Environment"Production"Environment name
EnableRetrytrueRetry failed steps
MaxRetries3Max retry attempts
RetryDelayMs1000Delay between retries

SetupState

Persisted checkpoint state:

public class SetupState
{
    public string WizardId { get; set; }
    public List<string> CompletedStepIds { get; set; }
    public List<string> SkippedStepIds { get; set; }
    public string FailedStepId { get; set; }
    public List<string> CompletedSeederIds { get; set; }
    public DateTimeOffset? StartedAt { get; set; }
    public DateTimeOffset? LastUpdatedAt { get; set; }

    public bool IsStepCompleted(string stepId);
    public bool IsStepSkipped(string stepId);
}

Built-in Steps

ISetupStep Interface

public interface ISetupStep
{
    string StepId { get; }
    string StepName { get; }
    string Description { get; }
    IReadOnlyList<string> DependsOn { get; }

    // Validation
    IErrorsInfo Validate(SetupContext context);

    // Idempotency check
    bool CanSkip(SetupContext context);

    // Execution
    IErrorsInfo Execute(
        SetupContext context,
        IProgress<PassedArgs> progress);
}

DriverProvisionStep

Downloads and installs required drivers from NuGet or local sources.

public class DriverProvisionStep : ISetupStep
{
    public DriverProvisionStep(DriverProvisionStepOptions options);

    // Options
    public string PackageName { get; set; }
    public string Version { get; set; }
    public string Source { get; set; } // "nuget" or "local"
    public string LocalPath { get; set; }
}

ConnectionConfigStep

Configures data connections with validation and testing.

public class ConnectionConfigStep : ISetupStep
{
    public ConnectionConfigStep(ConnectionConfigStepOptions options);

    // Options
    public ConnectionProperties ConnectionProperties { get; set; }
    public bool TestConnection { get; set; } = true;
    public bool OpenConnection { get; set; } = false;
}

SchemaSetupStep

Creates database schema based on entity definitions.

public class SchemaSetupStep : ISetupStep
{
    public SchemaSetupStep(SchemaSetupStepOptions options);

    // Options
    public List<Type> EntityTypes { get; set; }
    public List<EntityStructure> EntityStructures { get; set; }
    public bool DropExisting { get; set; } = false;
    public bool ValidateSchema { get; set; } = true;
}

SeedingStep

Populates initial data from seeders.

public class SeedingStep : ISetupStep
{
    public SeedingStep(SeedingStepOptions options);

    // Options
    public ISeederRegistry Registry { get; set; }
    public List<string> SeederIds { get; set; }
    public bool ClearExisting { get; set; } = false;
}

Platform Adapters

Bridge between wizard and platform-specific UI/runtime:

AdapterPlatformUI Pattern
DesktopSetupWizardAdapterWinForms / WPFProgress dialog, message boxes
ConsoleSetupWizardAdapterCLI / ShellConsole output, progress bars
WebApiSetupWizardAdapterASP.NET CoreAPI endpoints, SignalR
BlazorServerSetupWizardAdapterBlazor ServerComponent-based progress, SignalR
BlazorWasmSetupWizardAdapterBlazor WASMClient-side component progress
MauiSetupWizardAdapter.NET MAUIMobile/desktop native UI

ISetupWizardAdapter Interface

public interface ISetupWizardAdapter
{
    Task<SetupReport> RunAsync(SetupWizard wizard, SetupContext context);
    void OnStepStart(string stepId, string stepName, int stepNumber, int total);
    void OnStepComplete(string stepId, bool succeeded, string message);
    void OnWizardComplete(SetupReport report);
}

// Adapter status tracking
public enum SetupAdapterStatus { NotStarted, Running, Completed, Failed }

ISetupProgressReporter

public interface ISetupProgressReporter
{
    void ReportStepStart(string stepId, string stepName, int stepNumber, int total);
    void ReportStepProgress(string stepId, string message, int percentComplete);
    void ReportStepComplete(string stepId, bool succeeded, TimeSpan elapsed);
    void ReportWizardComplete(SetupReport report);
}

SetupWizardFactory

public interface ISetupWizardFactory
{
    (ISetupWizard wizard, SetupContext context) CreateDefault(IDMEEditor editor);
    (ISetupWizard wizard, SetupContext context) Create(IDMEEditor editor,
        Action<SetupWizardBuilder> configure);
}

// Default factory: returns empty wizard (applications register custom factory)
public class DefaultSetupWizardFactory : ISetupWizardFactory
{
    public (ISetupWizard wizard, SetupContext context) CreateDefault(IDMEEditor editor)
    {
        var options = new SetupOptions();
        var context = new SetupContext { Editor = editor, Options = options };
        var wizard = new SetupWizardBuilder().WithId("default-setup")
            .WithOptions(options).Build();
        return (wizard, context);
    }
}

Seeding Subsystem

public interface ISeeder
{
    string SeederId { get; }
    string SeederName { get; }
    int Priority { get; }
    IErrorsInfo Seed(SetupContext context, IProgress<PassedArgs> progress);
}

public interface ISeederRegistry
{
    void Register(ISeeder seeder);
    IReadOnlyList<ISeeder> GetOrderedSeeders();
}

public class SeederRegistry : ISeederRegistry
{
    public void Register(ISeeder seeder);
    public IReadOnlyList<ISeeder> GetOrderedSeeders(); // By Priority, then name
}

// Base classes for common seeding patterns
public abstract class SeederBase : ISeeder { /* Priority=0, default impl */ }
public abstract class ReferenceDataSeederBase : SeederBase { /* Static ref data */ }

Seed Execution

var registry = new SeederRegistry();
registry.Register(new CustomerSeeder());
registry.Register(new ProductSeeder());

var step = new SeedingStep(new SeedingStepOptions { Registry = registry });
var result = step.Execute(context, progress);

Checkpointing & Resume

The framework automatically checkpoints state after each step:

// State file (JSON)
{
  "wizardId": "app-setup",
  "completedStepIds": ["driver-provision", "connection-config"],
  "skippedStepIds": [],
  "failedStepId": null,
  "completedSeederIds": [],
  "startedAt": "2024-01-15T10:30:00Z",
  "lastUpdatedAt": "2024-01-15T10:35:00Z"
}

Resume After Failure

// First run — fails at schema setup
var result1 = wizard.Run(context);
// State persisted with FailedStepId = "schema-setup"

// Fix the issue, then resume
var result2 = wizard.Resume(context);
// Loads checkpoint, skips completed steps, continues from schema-setup

Report Verification

var report = wizard.GetReport();
Console.WriteLine($"Success: {report.Succeeded}");
Console.WriteLine($"Duration: {report.FinishedAt - report.StartedAt}");
Console.WriteLine($"SHA-256: {report.ContentHash}");

foreach (var step in report.StepResults)
{
    Console.WriteLine($"  {step.StepName}: " +
        $"{(step.Succeeded ? "OK" : "FAIL")} " +
        $"({step.Elapsed.TotalSeconds:F1}s)");
}

Usage Examples

Desktop Application (WinForms)

var editor = new DMEEditor();
var connProps = new ConnectionProperties
{
    ConnectionName = "ProductDB",
    DatabaseType = DataSourceType.SqlLite,
    ConnectionString = "Data Source=./products.db"
};

var wizard = new SetupWizardBuilder()
    .WithId("product-app-setup")
    .WithEnvironment("Development")
    .AddStep(new DriverProvisionStep(new DriverProvisionStepOptions
    {
        PackageName = "TheTechIdea.Beep.DataSources.SQLite"
    }))
    .AddStep(new ConnectionConfigStep(new ConnectionConfigStepOptions
    {
        ConnectionProperties = connProps,
        OpenConnection = true
    }))
    .AddStep(new SchemaSetupStep(new SchemaSetupStepOptions
    {
        EntityTypes = new[] { typeof(Product), typeof(Category) }
    }))
    .AddStep(new SeedingStep(new SeedingStepOptions
    {
        Registry = seederRegistry
    }))
    .Build();

var adapter = new DesktopSetupWizardAdapter(
    onProgress: args => progressLabel.Text = args.Messege,
    onComplete: report => MessageBox.Show(
        report.Succeeded ? "Setup OK" : "Setup failed"));

var context = new SetupContext
{
    Editor = editor,
    Options = new SetupOptions
    {
        StateFilePath = "./setup-checkpoint.json"
    }
};

var report = await adapter.RunAsync(wizard, context);

Web API

[ApiController]
[Route("api/[controller]")]
public class SetupController : ControllerBase
{
    [HttpPost]
    public async Task<IActionResult> RunSetup()
    {
        var wizard = /* build wizard */;
        var adapter = new WebSetupWizardAdapter(
            hubContext: _hubContext);

        var context = new SetupContext { Editor = _editor };
        var report = await adapter.RunAsync(wizard, context);

        return Ok(new
        {
            Success = report.Succeeded,
            Steps = report.StepResults.Select(s => new
            {
                s.StepName,
                s.Succeeded,
                s.Elapsed
            })
        });
    }
}

CLI Application

var adapter = new CliSetupWizardAdapter(
    console: Console.Out,
    showProgressBar: true);

var report = await adapter.RunAsync(wizard, context);

if (report.Succeeded)
    Console.WriteLine("Setup completed successfully!");
else
    Console.WriteLine($"Setup failed at: {report.StepResults.Last(s => !s.Succeeded).StepName}");

Custom Step

public class CustomConfigStep : ISetupStep
{
    public string StepId => "custom-config";
    public string StepName => "Custom Configuration";
    public string Description => "Applies custom app settings";
    public IReadOnlyList<string> DependsOn => new[] { "connection-config" };

    public IErrorsInfo Validate(SetupContext context)
    {
        if (context.Editor == null)
            return new ErrorsInfo { Flag = Errors.Failed, Message = "Editor required" };
        return new ErrorsInfo { Flag = Errors.Ok };
    }

    public bool CanSkip(SetupContext context)
    {
        // Check if already configured
        return File.Exists("./custom-config.json");
    }

    public IErrorsInfo Execute(SetupContext context, IProgress<PassedArgs> progress)
    {
        // Apply custom configuration
        File.WriteAllText("./custom-config.json", "{}");
        progress?.Report(new PassedArgs { Messege = "Custom config applied" });
        return new ErrorsInfo { Flag = Errors.Ok };
    }
}

Full API Reference

Step Options — Complete Properties

DriverProvisionStepOptions

PropertyTypeDescription
PackageNamestringDriver package name to install
Versionstring?Specific NuGet version; null → latest stable
NuGetSourcesIList<string>Additional NuGet feed URLs
AppInstallPathstring?Override install path; null → assemblyHandler default

ConnectionConfigStepOptions

PropertyTypeDefault
ConnectionPropertiesConnectionPropertiesrequired
TestConnectionbooltrue
OpenConnectionboolfalse

SchemaSetupStepOptions

PropertyTypeDefault
EntityTypesList<Type>null — use Discovery
EntityStructuresList<EntityStructure>null
DropExistingboolfalse
ValidateSchemabooltrue

SeedingStepOptions

PropertyTypeDefault
RegistryISeederRegistryrequired
SeederIdsList<string>null — all registered
ClearExistingboolfalse

SetupReport & SetupStepResult

public class SetupReport
{
    public string WizardId { get; set; }                     // From builder
    public string RunId { get; set; } = Guid.NewGuid()       // Unique run ID
    public bool Succeeded { get; set; }                      // All steps OK
    public IReadOnlyList<SetupStepResult> StepResults { get; set; }
    public DateTimeOffset StartedAt { get; set; }
    public DateTimeOffset FinishedAt { get; set; }
    public TimeSpan TotalElapsed => FinishedAt - StartedAt;  // Computed
    public string ContentHash { get; set; }                  // SHA-256 of StepResults
    public string RollbackReportJson { get; set; }           // Phase 6
    public string DryRunReportJson { get; set; }             // Phase 3/8
    public string Environment { get; set; }                  // Target environment
}

public class SetupStepResult
{
    public string StepId { get; set; }
    public string StepName { get; set; }
    public bool Succeeded { get; set; }
    public bool Skipped { get; set; }
    public string Message { get; set; }
    public TimeSpan Elapsed { get; set; }
    public DateTimeOffset ExecutedAt { get; set; }
}

ISetupWizard & ISetupWizardAdapter — Complete

public interface ISetupWizard
{
    IReadOnlyList<ISetupStep> Steps { get; }
    SetupState State { get; }
    SetupOptions Options { get; }

    IErrorsInfo Run(SetupContext context, IProgress<PassedArgs> progress = null);
    IErrorsInfo Resume(SetupContext context, IProgress<PassedArgs> progress = null);
    SetupReport GetReport();
}

public interface ISetupWizardAdapter
{
    Task<SetupReport> RunAsync(SetupWizard wizard, SetupContext context);
    void OnStepStart(string stepId, string stepName, int stepNumber, int total);
    void OnStepComplete(string stepId, bool succeeded, string message);
    void OnWizardComplete(SetupReport report);
}

public enum SetupAdapterStatus { NotStarted, Running, Completed, Failed }

public interface ISetupProgressReporter
{
    void ReportStepStart(string stepId, string stepName, int stepNumber, int total);
    void ReportStepProgress(string stepId, string message, int percentComplete);
    void ReportStepComplete(string stepId, bool succeeded, TimeSpan elapsed);
    void ReportWizardComplete(SetupReport report);
}

public interface ISetupWizardFactory
{
    (ISetupWizard wizard, SetupContext context) CreateDefault(IDMEEditor editor);
    (ISetupWizard wizard, SetupContext context) Create(
        IDMEEditor editor, Action<SetupWizardBuilder> configure);
}

SetupWizardBuilder — Complete API

public class SetupWizardBuilder
{
    public SetupWizardBuilder WithId(string wizardId);
    public SetupWizardBuilder WithEnvironment(string environment);
    public SetupWizardBuilder WithOptions(SetupOptions options);
    public SetupWizardBuilder AddStep(ISetupStep step);
    public SetupWizardBuilder AddSteps(IEnumerable<ISetupStep> steps);
    public SetupWizardBuilder WithSteps(params ISetupStep[] steps);
    public SetupWizard Build();
}

Source File Map (30 files)

CategoryFileContent
CoreSetupWizard.csOrchestrator: Run, Resume, checkpoint loop, validation
SetupWizardBuilder.csFluent builder: WithId, WithEnvironment, AddStep, Build
DefaultSetupWizardFactory.csEmpty default factory (apps replace)
ISetupWizardFactory.csFactory contract
InterfacesISetupWizard.csWizard contract: Run, Resume, GetReport
ISetupStep.csStep contract: Validate, CanSkip, Execute
ISetupWizardAdapter.csPlatform adapter contract
ISetupProgressReporter.csProgress reporting contract
ISetupWizardFactory.csFactory contract (duplicate listing)
Adapters/SetupAdapterStatus.csNotStarted, Running, Completed, Failed
Context/StateSetupContext.csShared state: Editor, Options, State, StepData
SetupState.csCheckpoint: step IDs, seeders, timestamps
SetupOptions.csStateFilePath, retry, environment
ReportSetupReport.csReport + StepResult: hash, dry-run, rollback
— (nested)SetupStepResult: per-step timing
StepsSteps/DriverProvisionStep.csNuGet/local driver install
Steps/DriverProvisionStepOptions.csPackageName, Version, NuGetSources, AppInstallPath
Steps/ConnectionConfigStep.csConnection save + test + open
Steps/ConnectionConfigStepOptions.csConnectionProperties, TestConnection, OpenConnection
Steps/SchemaSetupStep.csEntity discovery, DDL generation, validation
Steps/SchemaSetupStepOptions.csEntityTypes, DropExisting, ValidateSchema
Steps/SeedingStep.csSeed data population
Steps/SeedingStepOptions.csRegistry, SeederIds, ClearExisting
AdaptersAdapters/DesktopSetupWizardAdapter.csWinForms/WPF: progress dialog, message boxes
Adapters/ConsoleSetupWizardAdapter.csCLI: console output, progress bars
Adapters/WebApiSetupWizardAdapter.csASP.NET Core: API endpoints, SignalR
Adapters/BlazorServerSetupWizardAdapter.csBlazor Server: component progress, SignalR
Adapters/BlazorWasmSetupWizardAdapter.csBlazor WASM: client-side progress
Adapters/MauiSetupWizardAdapter.cs.NET MAUI: native UI
Adapters/SetupAdapterStatus.csAdapter status enum
SeedingSeeding/ISeeder.csSeeder contract: SeederId, Priority, Seed
Seeding/ISeederRegistry.csRegistry contract: Register, GetOrderedSeeders
Seeding/SeederRegistry.csConcrete: priority-sorted registration
Seeding/SeederBase.csAbstract base: Priority=0 default
Seeding/ReferenceDataSeederBase.csStatic reference data base