The delivery repository's contracts and SDK live under modules/ as mesh-delivery-contracts and mesh-delivery-sdk, their Go module paths renamed to match the folders (the TypeScript names already did), and every importer in mesh-delivery, mesh-catalog, mesh-host, mesh-tools and mesh-sdk follows in the same group: a design as it should be, one path per module, checked by the group's check building every importer. Builds: design 47 G §427, §88 Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
43 lines
1.9 KiB
Go
43 lines
1.9 KiB
Go
package holder
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
|
|
"git.novox.be/novox/mesh-delivery/modules/mesh-delivery-contracts/go/seats/meshbuilds"
|
|
)
|
|
|
|
// Reserved is the holder's check of a publish against the builder's reservation (novox/hq design 47 §381, §478, §504): it asks the
|
|
// seat mesh-builds' verb reserved with the publish's name and version, a package's name in its ecosystem, and accepts the publish
|
|
// only when that version is the one reserved and an artifact of it has the publish's digest. It reads no catalog and a publish gains
|
|
// no field. It is the Builder the holder's Check asks.
|
|
type Reserved struct {
|
|
// Ask is the runtime's request and reply over the bus (mesh-sdk stdio.Ask).
|
|
Ask func(address string, body any) (json.RawMessage, error)
|
|
}
|
|
|
|
// Address is the seat verb asked, as the manifest's `invokes` names it.
|
|
const Address = "seat:" + meshbuilds.Seat + "." + meshbuilds.VerbReserved
|
|
|
|
// Recorded answers whether name@version with digest is reserved, and why not when it is not. An answer that cannot be read is an
|
|
// error, never a yes; a refusal by the builder (a name no entry carries, a version it did not reserve) is a no that names it.
|
|
func (r Reserved) Recorded(name, version, digest string) (bool, string, error) {
|
|
raw, err := r.Ask(Address, meshbuilds.ReservedInput{Name: name, Version: version})
|
|
if err != nil {
|
|
return false, "", fmt.Errorf("%s did not answer for %s@%s: %w", Address, name, version, err)
|
|
}
|
|
var a meshbuilds.ReservedAnswer
|
|
if err := json.Unmarshal(raw, &a); err != nil || a.Version == "" {
|
|
return false, "", fmt.Errorf("%s answered no reservation for %s@%s: %s", Address, name, version, raw)
|
|
}
|
|
if a.Version != version {
|
|
return false, fmt.Sprintf("%s reserved %s for %s, not %s", a.Module, a.Version, name, version), nil
|
|
}
|
|
for _, art := range a.Artifacts {
|
|
if art.Digest == digest {
|
|
return true, "", nil
|
|
}
|
|
}
|
|
return false, fmt.Sprintf("%s reserved %s@%s for another digest than %s", a.Module, name, version, digest), nil
|
|
}
|