Files
mesh-catalog/modules/minio/cmd/object-store/main.go
T
jschoubben 06ebd7e8cf G findings: the writers name the ask's subject from the contract; the readers take the writer whole
WriterConfig.Asked is the generated mesh-conditions contract's SubjectFindingsAsked (A-17), a reader's Findings is the
module's writer itself (A-22, A-26), and mesh-build-go's single manifest ask writes and clears its first-view-unanswered
finding through the writer with the contract's Finding (A-28). mesh-config and mesh-vault's own followers (A-28) are not
yet moved onto a views.Reader: they do not compile at mesh-sdk 24f876a.

Builds: design 47 G §687, §689, A-17, A-22, A-26, A-28

Claude-Session: https://claude.ai/code/session_01JG73KEq4zoDfM9WtYpcQgZ
2026-11-11 22:03:09 +01:00

94 lines
4.5 KiB
Go

// minio's object-store seat (novox/hq ADR 0468 §3, §8): the holder of `object-store`, serving `link`. A party that
// needs to put a document into a bucket, or get one out, asks for one short link and moves the bytes over HTTP
// itself; no document ever travels on the bus.
//
// The link is signed with the bucket's link key (issue 1594), which only reads and writes that bucket's objects,
// never with the root account. Who may have a link is judged here, at each call, from the grant file the mesh
// delivered to minio: the bucket's consumer, and whoever its `shares` name for that method.
//
// stdout is the MCP channel; what this module says, it says on stderr.
package main
import (
"context"
"fmt"
mesh "git.novox.be/novox/mesh-contracts/go/seats/meshmoduleassigner"
"os"
seat "git.novox.be/novox/mesh-contracts/health-and-repair/go/seats/meshconditions"
stdio "git.novox.be/novox/mesh-sdk/go"
"git.novox.be/novox/mesh-contracts/health-and-repair/go/clients/meshhandactsclient"
"git.novox.be/novox/mesh-sdk/go/views"
)
// Words the manifest gives this bundle (modules/minio/module.json).
const (
ConfigWord = "OBJECT_STORE_CONFIG" // the store as the machine reaches it: files/object-store.json, rendered
LinksWord = "MESH_MINIO_LINKS" // the directory of the link keys' secrets (issue 1594)
ReceivesWord = "MESH_RECEIVES" // the grant file
)
func main() {
seats := &views.Reader{Module: "minio", Acts: meshhandactsclient.Recorder{Ask: stdio.Ask}, Logf: func(f string, a ...any) { fmt.Fprintf(os.Stderr, "[object-store] "+f+"\n", a...) }}
findings, err := newFindingsWriter()
if err != nil {
fmt.Fprintf(os.Stderr, "[object-store] %v\n", err)
os.Exit(1)
}
seats.Findings = findings
seats.Follow(assignerModule, mesh.StateSeatHolders, SeatHoldersTool)
s, err := newServer(os.Getenv(ConfigWord), os.Getenv(LinksWord), os.Getenv(ReceivesWord),
func() (map[string][]byte, error) { return seats.Values(assignerModule + "." + mesh.StateSeatHolders) })
if err != nil {
fmt.Fprintf(os.Stderr, "[object-store] %v\n", err)
os.Exit(1)
}
// the runtime answers the writer's subscription only once Serve has its channel
go func() {
<-stdio.Served()
if err := findings.Start(context.Background()); err != nil {
fmt.Fprintf(os.Stderr, "[object-store] %v\n", err)
os.Exit(1)
}
}()
seats.Start(context.Background())
if err := stdio.Serve("", append(tools(s), seats.Tools("object_store")...)); err != nil {
fmt.Fprintf(os.Stderr, "[object-store] %v\n", err)
os.Exit(1)
}
}
// SeatHoldersTool is the assigner's read tool of who holds which seat, which the manifest invokes (ADR 0615).
// assignerModule is the holder of the seat mesh-module-assigner whose seat-holders view this module follows: the one name
// of it here, the same as its manifest's `consumes` and `invokes` carry (the manifest test holds them equal).
const assignerModule = "mesh-delivery-assigner"
const SeatHoldersTool = assignerModule + ".assigner_read_seat_holders"
// newFindingsWriter is this module's finding writer (design 47 G §689, A-16): it states the findings of its views reader and
// observes none of its own.
func newFindingsWriter() (*views.Writer[seat.Finding, seat.FindingCleared, seat.FindingsStated, seat.FindingsAskedEvent], error) {
return views.NewStdioWriter(views.WriterConfig[seat.Finding, seat.FindingCleared, seat.FindingsStated, seat.FindingsAskedEvent]{
Asked: seat.SubjectFindingsAsked, Module: "minio", State: stdio.State("findings"),
Observe: func(context.Context) (views.Observed[seat.Finding], error) {
return views.Observed[seat.Finding]{}, nil
}})
}
func tools(s *server) []stdio.Tool {
return []stdio.Tool{{
Name: "object-store.link",
Description: "A signed link to one object of a bucket, for one method, that lives at most ten minutes: the caller " +
"moves the bytes over HTTP to it and never over the bus. Allowed to the bucket's own consumer and to whoever the " +
"consumer's shares name for the method; the link is signed with a key that reaches that bucket's objects only.",
Input: map[string]any{
"bucket": map[string]any{"type": "string", "description": "the bucket"},
"key": map[string]any{"type": "string", "description": "the object's key"},
"method": map[string]any{"type": "string", "description": "get to read the object, put to write it"},
"seconds": map[string]any{"type": "integer", "description": "how long the link lives, 1 to 600 (default 300)"},
},
Run: func(args map[string]any) (any, error) { return s.link(stdio.CallerOf(args), args) },
}}
}