// Package compose is the controller's composition of a machine, as a function over a plain input (novox/hq ADR 0453 // clause 3, ADR 0446 clause 4): what the rest of the mesh offers and holds, the private network's generator, one // node's resolution and, in the issues after, its rendering and its declaration. // // **It never allocates, makes, writes, logs or raises.** The controller composes with a store behind it; this // package is its Reading and Foreseeing modes over data. Everything the controller reads from its store is a field of // Input, and everything a send would make or record (a port, a credential, a seat passed on, a node left out) is // returned for the caller to act on, never done. Input is never changed by a call. No field holds a secret value // the composition needs: sealed values are optional inputs, and without them the composition uses stand-ins named // foreseen. The logic is the controller's, ported from mesh-controller cmd/mesh-controller at commit // 6c2a8d62100cb7d491f8eb9a623e1eeea5ec0de1 (plan.go, network.go, holdings.go, seat_pass.go), in the same order, with the // same refusals in the same words, so that a comparison node for node is a fair one. // // It imports the standard library and mesh-sdk's own packages only. package compose import ( "encoding/json" "errors" "fmt" "sort" "strings" "git.novox.be/novox/mesh-sdk/go/catalogue" ) // Input is everything the composition reads. Each field is what one read of the controller's inventory answers, named // beside it; the controller's adapter fills it from its stores and the assigner from the mesh's facts and buckets // (ADR 0446 clause 2). type Input struct { // Catalogue is the shelf: every module's manifest by name (inv.Catalogue), as it is to be composed. A recorded // module kept at the build a machine runs (keepRecorded) is that node's Kept, applied to its own resolution only. Catalogue map[string]catalogue.Manifest // Nodes is every node the mesh has (inv.Nodes and inv.Overlays together, one row per node). Nodes []Node // Holdings is every seat whose holder is on record (inv.Holdings). Holdings []catalogue.Held // Licences is every licence the mesh holds, with the machines that use it (open.Licences); none for a mesh with no // licence. Licences []Licence // OverlayCIDR is the range the mesh allocates from when no tunnel was adopted, as genesis was told it (the // controller's OverlayCIDRVar); empty means DefaultOverlayCIDR. The package reads no environment. OverlayCIDR string // Tunnels is, by node name, the found tunnel whose key is the node's overlay key (inv.Tunnels). Tunnels map[string]FoundTunnel // Adopted is the hub's found tunnel and the hub's name, whether or not the hub took it (inv.AdoptedTunnel); nil // when no hub has one. Adopted *AdoptedTunnel // CarriedPeers is every peer of the adopted tunnel (inv.CarriedPeers). CarriedPeers []CarriedPeer // Joining is the nodes that hold a live enrolment token (inv.NodesWithALiveToken). Joining []string // Credentials is how each pair credential a node takes from elsewhere stands, never its value (what inv.SecretFor, // SharedSecretFor and GivenPairSecret would answer): held, to be made by the next send, only a person's to give, or // refused. A need with no entry here is one the next send would make. Credentials []Credential // Built is every repository the mesh has built (the keys of inv.Held): what tells a reference recorded with an address // from an image a module runs straight from a public registry. Built []string // OperatorExport is every operator-sealed secret in the mesh, for a module that keeps them (inv.OperatorExport): sealed // values the composition carries without opening. Nil when the mesh has no operator key. OperatorExport *catalogue.KeptExport // Issued is the credentials made for the consumers of each provider (inv.SecretsFrom): one row for each pair credential // that exists, by the provider node it is for. The grants a provider must create are read from these, so a credential not // made yet has no grant until the send that makes it. Issued []Issued // OwnSecrets is the own secrets held on each machine (the module_secret rows): who made each, and the key it is sealed to. // Their sealed values are optional. OwnSecrets []OwnSecretRow // KeptCoreBoxes is the vault's box last kept for each core credential on each machine (inv.KeptCoreBoxes). KeptCoreBoxes []CoreBox // BusUsers is the bus's user list as the controller composes it from the bus records and the hashes it holds (composeBusUsers), // for the machine that runs the bus: names and hashes, never passwords. Empty when the Input does not carry it, and then // the composition uses a stand-in, named foreseen. BusMissing are the users left out of it for want of a credential. BusUsers string BusMissing []string // BusMinted are the bus users the mesh has minted a password hash for (inv.BusUserHash): `.` for a module and // `provisioner.` for a machine's provisioner client. BusMinted []string // BusMemberships is, by node, the membership sealed to it for the bus the mesh is moving to (inv.BusMemberships). BusMemberships map[string]string // Authority is the mesh's own certificate (identity.EstablishAuthority), public. Optional. Authority string // CurrentBuilds is, by module, the commit of the build the mesh holds for it (inv.CurrentBuilds, the commit it was built from); // BuildIDs the build made from a commit of a module (inv.BuildOf), by module then commit. Read only to name the builds a // declaration carries to a node-engine that reads them. CurrentBuilds map[string]string BuildIDs map[string]map[string]string } // Issued is one pair credential made for a consumer of a provider (inv.Secret): ForProvider is its copy sealed to the // provider, optional. type Issued struct { Provision string Consumer string ConsumerModule string Local string Provider string ForProvider string } // OwnSecretRow is one own secret held on a machine: Origin is `made` (the mesh generated it) or `accepted` (a person gave it), // SealedTo the sealing key it is sealed to, and Sealed its value sealed to that key, optional. type OwnSecretRow struct { Node string Module string Name string Origin string SealedTo string Sealed string } // CoreBox is the vault's box for one core credential of one machine, as last kept (inv.CoreBox). type CoreBox struct { Node string Module string Name string Generation int SealedTo string Box json.RawMessage } // Node is one node of the mesh and what the composition reads about it. type Node struct { Name string // Place is where it is on the private network (inv.Overlays). Place Place // Assigned is the modules assigned to it, in the order the controller reads them (inv.Assigned). Assigned []string // Capabilities are the ones present on it (inv.ProfileOf). Capabilities map[string]bool // PublicDomain is the domain it composes its routed names under (inv.PublicDomainOf). PublicDomain string // Account, AccountHome, AgentAccount and AgentAccountHome are its operator and agent logins (inv.NodeByName). Account, AccountHome, AgentAccount, AgentAccountHome string // Adopted is whether it is adopted rather than converged. Adopted bool // Pins is the provider each provision was pinned to for it (inv.PinsFor). Pins map[string]catalogue.Chosen // Bound is where each of its consumers of a provision that keeps data was last sent (inv.BindingsFor), by consumer // module and provision. Bound map[string]map[string]catalogue.Chosen // Settings is its settings layers by module (inv.SettingsFor); a module with none is absent. Settings map[string][]catalogue.Layer // Ports is the machine port each module's software port was given on it (inv.PortsFor), by module then port. Ports map[string]map[int]int // SealingKey is the public key its secrets are sealed to (inv.SealingKeyOf); empty when it has none. A public key, so // nothing secret. SealingKey string // Taken is the modules taken on it, for an adopted node (inv.Taken). Taken []string // OutwardLinks are the links it reported as facing outside it (inv.OutwardLinksOf). OutwardLinks []string // Networks are the networks it reported being attached to, as link and network (inv.MachineOf); NetworksSaid is whether // its node-engine said any at all, which is not the same as saying none. Networks []catalogue.AttachedNetwork NetworksSaid bool // ServingKey is the key the machine serves with, which a certificate is issued for (identity.ServingKeyOf); empty when it has // never reported one. Certificate is the certificate the mesh issued for its internal name, public and optional. ServingKey string Certificate string // Sequence, Epoch and Generation are what the declaration is sent under (inv.Sequence, SentEpoch, SentGeneration): the order // against every other send to the node, the lease epoch and the assignment generation it was last sent. Zero is not sent. Sequence int64 Epoch uint64 Generation int64 // ReadsModules says its node-engine reads a module per resource and a build per module (inv.ReadsModules, issue 1145); only // then are they sent. SentBuilds is the build of each module it was last sent, by module to commit, and SentKnown whether // that is known at all (inv.SentBuilds); Runs is what each of its assignments runs (inv.AssignmentRuns), by module. ReadsModules bool SentBuilds map[string]string SentKnown bool Runs map[string]Run // Kept is, by module, the manifest of a recorded or core module kept at the build this machine runs (plan.go keepRecorded: // the caller reads it with recordedKept and ManifestAt), and KeptBuilds the commit of that build. They apply to this node's // own resolution only, never to another node's, and a declaration carries the kept commit for the module. Kept map[string]catalogue.Manifest KeptBuilds map[string]string // Contract is the contract of its node-engine's newest statement (inv.HealthOf); Stated is whether it ever stated one. Contract int Stated bool } // Place is where a node is, as its placement says (inv.Overlay). type Place struct { Key string Endpoint string Site string Hub bool Address string } // Reachable says whether the node can be dialled. func (p Place) Reachable() bool { return strings.TrimSpace(p.Endpoint) != "" } // Tunnel is a tunnel found on a node (inv.Tunnel). type Tunnel struct { Interface string Unit string Config string Port int MTU int // Address is the interface's own address with its prefix length, Range the network that prefix names. Address string Range string PublicKey string Peers []TunnelPeer } // TunnelPeer is one peer of a found tunnel. type TunnelPeer struct { PublicKey string Address string } // FoundTunnel is a node's tunnel and whether the node is adopted (inv.FoundTunnel). type FoundTunnel struct { Tunnel NodeAdopted bool } // AdoptedTunnel is the hub's tunnel, the hub's name, and whether the hub's overlay key is the tunnel's, which is // whether the private network took the tunnel over. type AdoptedTunnel struct { Tunnel Tunnel Hub string Adopted bool } // CarriedPeer is a peer of the adopted tunnel (inv.CarriedPeer). type CarriedPeer struct { PublicKey string Address string EnrolledAs string Named string } // Licence is one licence the mesh holds: its name, what a consumer may know of it, and the machines and modules // that use it. type Licence struct { Name string Serves map[string]any Holders []Holder // Keys is, by holder, the licence's key sealed to that holder's machine (held.KeyFor), empty where the mesh holds none: // the plaintext was discarded when it was supplied. Optional: nil means not given, and the composition uses a stand-in named // foreseen; given (even empty), a holder with no entry is one the mesh holds no key for. Keys map[Holder]string // Manager is the holder of a refreshable-grant licence that manages it (held.ManagerOf); the zero Holder when none. Manager Holder } // Holder is a module on a node that uses a licence. type Holder struct { Node string Module string } // ErrNoSuchNode is what the controller's inventory answers for a node it does not have. var ErrNoSuchNode = errors.New("no node of that name") // node is the node of that name, or the refusal the controller's inventory gives for one it does not have. func (in Input) node(name string) (Node, error) { for _, n := range in.Nodes { if n.Name == name { return n, nil } } return Node{}, fmt.Errorf("%w: %s", ErrNoSuchNode, name) } // sorted is the nodes by name, the order the controller reads them in. func (in Input) sorted() []Node { out := append([]Node(nil), in.Nodes...) sort.Slice(out, func(i, j int) bool { return out[i].Name < out[j].Name }) return out } // CredentialState is how one pair credential stands. type CredentialState string const ( // CredentialHeld is a credential held for both ends as they stand now. Sealed, when given, is the consumer's copy; a held // credential with no value is composed with a stand-in, named foreseen. CredentialHeld CredentialState = "held" // CredentialWouldMake is a credential none is held for: the next send makes it, and the composition uses a stand-in, // named foreseen. It is also what a need with no entry is. CredentialWouldMake CredentialState = "would-make" // CredentialNotGiven is a credential only a person gives (novox/hq ADR 0337 clause 4) that nobody has given, or that was given // under a key one end no longer has: the consumer still resolves, without it. Why is the controller's words for it. CredentialNotGiven CredentialState = "not-given" // CredentialRefused is a credential the send would refuse to make, for the reason Why gives in the controller's words: a // value a person gave sealed to a key the machine no longer has, a machine with no sealing key. CredentialRefused CredentialState = "refused" ) // Credential is the state of one pair credential, by the ends it joins: the provision, the consumer's node and module, the // provider's node, and the local name where a module keeps several (inv.Secret's key). type Credential struct { Provision string Consumer string ConsumerModule string Provider string Local string State CredentialState // Sealed is the consumer's copy as it is sealed to the consumer's key; optional, and only the controller's adapter passes it. Sealed string // Why is the words of a CredentialNotGiven or CredentialRefused. Why string } // Run is the build an assignment names: the commit it is of and the build made from it (chain.Ref). type Run struct { Commit string Build string }