classDiagram

    namespace api {
        class ApiClassesTBD
    }

    namespace cmd {
        class CMDClassesTBD
    }

    namespace db {
        class DBClassesTBD {
            +startDB()
        }
    }
    

    Actor ..|> Node
    Orchestrator ..|> Node
    ID ..|> NodeID
    Graph ..|> Node
    namespace dms {
        class Capability
        class NodeID {
            +models.ID.UUID id
            +models.ID.CID cid
            ----
            +String peerID
            +String DID
            
        }
        class Node {
            +NodeID id
            +models.Mailbox mailbox
            +models.Graph graph
            ----            
            +db.LocalDatabaseCollector db
            +dms.Capability registeredCapability
            +dms.Capability availableCapability
            +Map[dms.Job.JobID]dms.Capability lockedCapabilities
            +dms.CapabilityComparator preferences
            +Slice[jobs.AllocationID] allocations

            +Actor.sendMessage(String, telemetry.Message)
            +getAllocations() Slice[jobs.AllocationID]
            +getAllocationStatus(jobs.AllocationID) String
            +routeToAllocation(jobs.AllocationID)

            +benchmarkCapability() dms.Capability
            +lockCapability(jobs.Pod, dms.Capability)
            +startAllocation(orchestrator.Invocation)
        }
        class Network
        class PriceInformation
        class TimeInformation
    }

    namespace executor {
        class Executor {
            <<interface>>
            +IsInstalled() bool
            +Start(*ExecutionRequest) error
            +Run(*ExecutionRequest) *ExecutionResult, error
            +Wait(executionID) <-chan *ExecutionResult, <-chan error
            +Cancel(executionID)
            +GetLogStream(executionID) Reader, error
        }
    }
    namespace docker {
        class Docker {
            -handlers
            -client *Client
            +ID string

            -doWait(er <-chan *ExecutionResult, e <-chan error, eh *executionHandler)
            -newDockerExecutionContainer(er *ExecutionRequest) string, error
            -containerLabels(jobID string, executionID string) map[string]string

            +IsInstalled() bool
            +Start(*ExecutionRequest) error
            +Run(*ExecutionRequest) *ExecutionResult, error
            +Wait(executionID) <-chan *ExecutionResult, <-chan error
            +Cancel(executionID)
            +Cleanup() error
            +GetLogStream(request LogStreamRequest) ReadCloser, error
            +FindRunningContainer(jobID string, executionID string) string, error
        }

        class EngineSpec-D {
            +Image string
            +Entrypoint []string
            +Cmd []string
            +Environment []string
            +WorkingDirectory string

            +Validate() error
        }

        class Client-D {
            -client *client.Client
            -removeContainers(filterz filters.Args) error
            -removeContainers(filterz filters.Args) error

            +IsInstalled() bool
            +CreateContainer(cfg container.Config, hostConfig *container.HostConfig, netowrkConfig *network.NetworkingConfig, platform *v1.Plarform, name string) string, error
            *StartContainer(m *firecracker.Machine) error
            +InspectContainer(id string) types.ContainerJSON, error
            +FollowLogs(id string) Reader, Reader, error
            +WaitContainer(containerID string) <-chan conainerContainerWaitOKBody, <-chan error
            +StopContainer(containerID string, timeout time.Duration) error
            +RemoveContainer(containerID string) error
            +RemoveObjectsWithLabel(label string, value string) error
            +GetOutputStream(containerID string, since string, follow bool) Reader, error
            +FindContainer(label string, value string) string, error
            +PullImage(name string) string, error
        }

        class DockerEngineBuilder {
            -eb *SpecConfig

            +WithEntrypoint(e... string) *DockerEngineBuilder
            +WithCmd(c... string) *DockerEngineBuilder
            +WithEnvironment(e... string) *DockerEngineBuilder
            +WithWorkingDirectory(w string) *DockerEngineBuilder
            +Build() *SpecConfig
        }

        class executionHandler-D {
            -client *Client
            -jobID string
            -executionID string
            -containerID string
            -resultsDir string
            -activeCh <-chan bool
            -waitCh <-chan bool
            -running *atomic.bool
            -result *models.ExecutionResult

            +ID string

            -active() bool
            -run()
            -kill() error
            -destroy(timeout time.Duration) error
            -outputStream(request LogStreamRequest) ReadCloser, error
        }
    }
    namespace firecracker {
        class Firecracker {
            -handlers
            -client
            +ID

            -doWait(er <-chan *ExecutionResult, e <-chan error, eh *executionHandler)
            -newFirecrackerExecutionVM(er *ExecutionRequest) *firecracker.Machine, error
            -generateSocketPath(jobID string, executionID string) string

            +IsInstalled() bool
            +Start(*ExecutionRequest) error
            +Run(*ExecutionRequest) *ExecutionResult, error
            +Wait(executionID) <-chan *ExecutionResult, <-chan error
            +Cancel(executionID)
            +Cleanup() error
            +FindRunningVM(jobID string, executionID string) *firecracker.Machine, error
        }

        class EngineSpec-F {
            +KernelImage string
            +Initrd string
            +KernelArgs string
            +RootFileSystem string
            +MMDSMessage string

            +Validate() error
        }

        class Client-F {
            +IsInstalled() bool
            +CreateVM(cfg firecracker.Config) *firecracker.Machine, error
            *StartVM(m *firecracker.Machine) error
            +ShutdownVM(m *firecracker.Machine) error
            +Destroy(m *firecracker.Machine, timeout time.Duration) error
            +FindVM(socketPath string) *firecracker.Machine, error
        }

        class FirecrackerEngineBuilder {
            -eb *SpecConfig

            +WithRootFileSystem(e string) *FirecrackerEngineBuilder
            +WithKernelImage(e string) *FirecrackerEngineBuilder
            +WithKernelArgs(e string) *FirecrackerEngineBuilder
            +WithMMDSMessage(e string) *FirecrackerEngineBuilder
            +Build() *SpecConfig
        }

        class executionHandler-F {
            -client *Client
            -executionID string
            -machine *firecracker.Machine
            -resultsDir string
            -activeCh <-chan bool
            -waitCh <-chan bool
            -running *atomic.bool
            -result *models.ExecutionResult

            +ID string
            +jobID string

            -active() bool
            -run()
            -kill() error
            -destroy(timeout time.Duration) error
        }
    }
    Firecracker ..|> Executor
    Docker ..|> Executor
    %% note for Executor "implemented executors:\ndocker\nfirecracker"

    namespace internal {
        class InternalClassesTBD
    }

    Actor ..|> Allocation
    ID ..|> AllocationID
    namespace jobs {
        class AllocationID {
            +models.ID.UUID UUID
            +String CID
        }
        class Allocation {
            +AllocationID id
            +jobs.Job.JobID jobID
            +nodeID nodeID
            +models.ID source
            +models.Mailbox mailbox

            +start()
            +sendMessage(telemetry.Message)
            +register()
        }
        class Job {
            +models.ID id
            +Slice[models.SpecConfig] inputs
            +Slice[models.SpecConfig] outputs
            +dms.Capability requiredCapability %% tyep marked for change
            +Slice[jobs.jobLink] children

            getPods() Slice[jobs.Pod]
        }
        class JobLink {
            +models.SpecConfig relationProperties
            +jobs.Job relatedJob

            +validateRelations()
        }
        class Pod {
            +models.ID id
            +dms.Capabililty podCapabilitly %% type marked for change 
            +Slice[jobs.Job] jobs 

            +combineCapabilities() dms.Capability
        }
    }

    namespace models {
        class Actor { 
            +models.ID id
            +models.Mailbox mailbox

            +processMessage() telemetry.Message
            +sendMessage(String, telemetry.Message)
            
        }
        class Channel { %% marked for change
            +any channel
            +String name
            +String metadata 
        }
        class Graph { %% marked for change

        }
        class ID {
            +String UUID
            +String CID

            +generateUUID() UUID
            +generateCID() CID
        }
        class Mailbox {
            +network.p2p p2p
            +network.gossipsub gossibsub
            +Slice[Channel] channels %% subject to change
            +receiveMessage()
            +handleMessage()
            +triggerBehaviour()
            +getKnownTopics()
            +getSubscribedTopics()
            +subscribeToTopic()
            +unsubscribeFromTopic()

        }
        class SpecConfig
    }

    namespace network {
        class Network {
            <<interface>>
            +Init()
            +Start()
            +Stop()
            +Ping()
            +Advertise()
            +Unadvertise()
            +Publish()
            +Subscribe()
            +Stat()
        }

        class P2P {
            +Host host.Host
            +DHT *dht.IpfsDHT
            +PS peerstore.Peerstore
            -peers []peer.AddrInfo
            -config Libp2pConfig

            +Init()
            +Start()
            +Stop()
            +Ping()
            +Stat()
        }

        class DHT {
            +Advertise()
            +Unadvertise()
        }

        class Gossipsub{
            +Publish()
            +Subscribe()
        }

        %% class Other


        class Messaging {
            <<interface>>
            +New()
            +Send()
            +ReceiveHandler()
            +Close()
        }

    }
    %% note for Other "Other is meant to represent another network/transport implementation"
    P2P ..|> Network
    DHT ..|> P2P
    Gossipsub ..|> P2P
    P2P ..|> Messaging
    %% Other ..|> Network


    namespace orchestrator {
        class Bid {
            +BidRequest BidRequest 
            +jobs.JobID jobID 
            +models.ID bidder
            +PriceBid priceBid 
            +TimeBid timeBid
            +int timeout
            +bool validOffer
            +bool resourcesLockedUntilTimeout 
        }
        class PriceBid {
            +String priceBidType 
            +String currency
            +String perTimeUnit
            +bool perResult
            +Float amount
        }
        class TimeBid {
            +String timeBidType
            +String units
            +int duration
            +int timeStart
            +int timeFinish
        }
        class BidRequest {
            +models.ID id
            +jobs.Pod pod
            +models.ID requestor
            +models.ResourceRequirements resourceRequirements
            +models.CapabilityComparator comparator
        }
        class CapabilityComparator 
        class CapabilityComparison 
        class Invocation {
            +models.ID source
            +jobs.Pod pod
            +tokenomics.Contract contract
        }
        class Orchestrator {
            <<interface>>
            +publishBidRequest(dms.Node, orchestrator.BidRequest, dms.NodeID, ..String)
            +compare(dms.Capability, dms.Capability) orchestrator.CapabilitlyComparison %% marked for change (types and parameters)
            +acceptJob(dms.CapabilityComparison, dms.CapabilityComparator) bool %% marked for change (types and parameters)
            +sendBid(dms.Node, orchestrator.BidRequest)
            +selectBestBid(dms.Node, orchestrator.BidRequest) orchestrator.Bid
            +sendJobRequest(dms.Node, jobs.Pod, dms.NodeID)
            +sendInvocation(dms.Node, jobs.Invocation, dms.NodeId)
            +orchestrateJob(dms.Node, jobs.Job)
        }
    }
    namespace plugins {
        class PlubinsClassesTBD
    }

    namespace storage {
        class StorageProvider
        class StorageVolume
        class VolumeController
    }

    namespace telemetry {
        class Collector
        class Event
        class Observable
        class Message
        class Heartbeat
    }

    namespace tokenomics {
        class Contract
        class ContractProof
    }

    namespace utils {
        class UtilsClassesTBD
    }