Main reverted G's half merge (#189, reverted by8afc3ebin #191) and then took the reader release's S1-S5, which copied G's code. G's form holds where they differ (process_bus.go, seats.go, state.go and their tests); the release's kept names stay so main's callers keep building: SeatViewPrefix beside SeatReadPrefix, and QueueInvoke's empty strings on not-ok (with its test TestQueueInvoke). The tree differs from G's headf30dee54only by those and the release's two tests (objects cap option, seat states and stream kinds). Builds: design 47 G (the milestone's sdk part, as atf30dee54) Claude-Session: https://claude.ai/code/session_01NcbgfGKaxw984XyAPfLm4h
116 lines
4.9 KiB
Go
116 lines
4.9 KiB
Go
package approval
|
|
|
|
import (
|
|
"encoding/json"
|
|
"time"
|
|
|
|
"git.novox.be/novox/mesh-sdk/go/operatorask"
|
|
)
|
|
|
|
// What the gate reads beyond itself crosses in the gate's own terms, its caller translating from the generated contracts
|
|
// (design 47 G lead answers A-219, A-224, A-228): the operator channel (Channel), the catalog's entries (Entry, through
|
|
// Catalog), the finding writer (FindingWriter) and the seat holders (Deps.Holder). No form of a generated contract is
|
|
// copied here: what the router keeps whole (an ask, a warrant) the gate holds as the bytes it was given.
|
|
|
|
// Channel is the operator channel as the gate reaches it (A-219, A-228): operatorchannelclient implements it over the
|
|
// generated types, keeping each ask in the gate's own state under the marked module's name.
|
|
type Channel interface {
|
|
// Ask checks the ask, keeps it in the gate's state as a Kept and publishes it under module's name, at the level
|
|
// approve, to the operator (design 46 7-approval-mark §10).
|
|
Ask(module string, a Ask) error
|
|
// Record is the router's record of module's ask id, read under module's own name; nil while the router holds none
|
|
// (design 47 G §700).
|
|
Record(module, id string) (*Record, error)
|
|
// Claim takes the warrant once (design 46 7-approval-mark §14, §15): it holds it to the ask kept, checks that the
|
|
// chosen option binds act and marks the kept ask acted, then calls run; act's run happens only when it answers
|
|
// Claimed. A warrant already taken answers ClaimDone, one that does not hold ClaimRefused with why.
|
|
Claim(module string, w Warrant, act operatorask.Act, run func()) (Claim, error)
|
|
// Cancel takes module's ask back.
|
|
Cancel(module, id string) error
|
|
// Decided is the subject the router's `decided` for module is heard on.
|
|
Decided(module string) string
|
|
// Seat is the seat an ask is raised on, whose holder must be there for a marked call to be asked (§19).
|
|
Seat() string
|
|
}
|
|
|
|
// Claim is what came of a warrant handed to Channel.Claim.
|
|
type Claim string
|
|
|
|
const (
|
|
Claimed Claim = "acted"
|
|
ClaimRefused Claim = "refused"
|
|
ClaimDone Claim = "already acted on"
|
|
// ClaimEnded is a warrant of an ask that ended without a choice.
|
|
ClaimEnded Claim = "ended without a choice"
|
|
)
|
|
|
|
// Ask is an ask the gate raises: two options, each binding the act's digest (design 46 7-approval-mark §10, §11).
|
|
type Ask struct {
|
|
ID, About, Headline, Explanation, Expires, OnExpiry string
|
|
Options []Option
|
|
}
|
|
|
|
// Option is one option of an ask.
|
|
type Option struct{ ID, Label, Does, Binds string }
|
|
|
|
// Record is the router's record of an ask as the gate reads it.
|
|
type Record struct {
|
|
State, Answer, Opened, Expires string
|
|
OfferedOn []string
|
|
Warrant *Warrant
|
|
}
|
|
|
|
// Warrant is a person's choice as the gate reads it; Whole is the warrant as the router recorded it, which Claim holds to
|
|
// the kept ask.
|
|
type Warrant struct {
|
|
Ask, Asker, Option, Channel, At string
|
|
Whole json.RawMessage
|
|
}
|
|
|
|
// Kept is one ask as its asker keeps it (design 46 7-approval-mark §13): the ask, beside it the act the ask binds, the
|
|
// call's whole arguments, and whether the act's run was recorded in the hand-act log. A is the ask's form and W the
|
|
// warrant's: operatorchannelclient's Kept is Kept of the generated contract's, the gate's of the bytes kept (A-228).
|
|
type Kept[A, W any] struct {
|
|
Ask A `json:"ask"`
|
|
Asked time.Time `json:"asked"`
|
|
Acted bool `json:"acted,omitempty"`
|
|
Ended string `json:"ended,omitempty"`
|
|
Answer *W `json:"answer,omitempty"`
|
|
// Act is the act the ask's options bind, as its asker digested it.
|
|
Act operatorask.Act `json:"act,omitempty"`
|
|
// Arguments are the asked call's arguments whole.
|
|
Arguments json.RawMessage `json:"arguments,omitempty"`
|
|
// Recorded says the act's run is in the hand-act log (`mesh-hand-acts.warranted` answered).
|
|
Recorded bool `json:"recorded,omitempty"`
|
|
}
|
|
|
|
// kept is the gate's own reading of a Kept: the ask and the warrant as the bytes kept, so a write back keeps them whole.
|
|
type kept = Kept[json.RawMessage, json.RawMessage]
|
|
|
|
// HeadlineLength is the longest headline the router takes, in characters; operatorchannelclient re-exports it.
|
|
const HeadlineLength = 60
|
|
|
|
// Entry is a module's entry in the catalog as the marks are read from it (design 46 7-approval-mark §5): its module, the
|
|
// build's fingerprint, the seat verbs it serves as `<seat>.<verb>`, and its manifest.
|
|
type Entry struct {
|
|
Module, Fingerprint string
|
|
Serves []string
|
|
Manifest json.RawMessage
|
|
}
|
|
|
|
// formatTime is a time as the router's records carry it: RFC 3339 to the nanosecond; the zero time is empty.
|
|
func formatTime(t time.Time) string {
|
|
if t.IsZero() {
|
|
return ""
|
|
}
|
|
return t.Format(time.RFC3339Nano)
|
|
}
|
|
|
|
// parseTime reads such a time; empty is the zero time.
|
|
func parseTime(s string) (time.Time, error) {
|
|
if s == "" {
|
|
return time.Time{}, nil
|
|
}
|
|
return time.Parse(time.RFC3339Nano, s)
|
|
}
|