mesh/delivery merged: source.main moved to novox/mesh-catalog@6d000647de2d
mesh/check being carried to cff1005422c1 on 6d000647de2d | from f9dcbc295723
The one bundle that did everything becomes the manager bundle, which runs long and answers the seat's ten verbs and the three acting tools, and a tools bundle of its own that answers the four reading tools and writes nothing, so they answer while the manager fails to load or stops. Both import the module's one package for the layouts of the kept data and the log entries, the key form, the entries' names and the settings with their validity; the settings file and the account with its directory stay as they are. Builds: design 39 parts §1, §2, §3, §4, §5, §6, §7, §8
77 lines
3.3 KiB
Go
77 lines
3.3 KiB
Go
package main
|
|
|
|
// The manager's store (novox/hq ADR 0183, design 39 bus-and-switch §2 to §7): licences, bindings with a generation,
|
|
// leases, what became of each login it was offered, usage readings and the audit, all in the bus's own storage
|
|
// (busstore.go). Every rule is tested on the same store over a bus kept in memory.
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
. "claude-licence-manager/internal/licences"
|
|
)
|
|
|
|
// Binding is one consumer's binding (ADR 0206, §3): the licence, kind and generation it should hold, since when, and
|
|
// why and by whom it was moved last.
|
|
type Binding struct {
|
|
Consumer string `json:"consumer"`
|
|
Licence string `json:"licence"`
|
|
// Key is the licence's key (§10), answered by the verb bindings (B25); the store keeps none.
|
|
Key string `json:"key,omitempty"`
|
|
Kind string `json:"kind,omitempty"`
|
|
Generation int64 `json:"generation"`
|
|
Since string `json:"since,omitempty"`
|
|
Why string `json:"why,omitempty"`
|
|
By string `json:"by,omitempty"`
|
|
}
|
|
|
|
// Move is what moves a binding: the licence's kind, why and by whom, and the floor a consumer's generation must pass
|
|
// (B11: the generation its node last reported); a nil Floor is none.
|
|
type Move struct {
|
|
Kind, Why, By string
|
|
Floor func(consumer string) int64
|
|
}
|
|
|
|
// floor is the floor m gives consumer.
|
|
func (m Move) floor(consumer string) int64 {
|
|
if m.Floor == nil {
|
|
return 0
|
|
}
|
|
return m.Floor(consumer)
|
|
}
|
|
|
|
// UsageRow is one usage reading.
|
|
type UsageRow struct {
|
|
Licence string `json:"licence"`
|
|
At int64 `json:"at"`
|
|
Reading UsageReading `json:"reading"`
|
|
// Raw is the vendor's answer whole, answered only when asked (§35).
|
|
Raw map[string]any `json:"raw,omitempty"`
|
|
}
|
|
|
|
// Store is what the manager keeps.
|
|
type Store interface {
|
|
Licences(ctx context.Context) ([]Licence, error)
|
|
Licence(ctx context.Context, name string) (*Licence, error)
|
|
LicenceForAccount(ctx context.Context, account string) (*Licence, error)
|
|
SaveLicence(ctx context.Context, l Licence) error
|
|
Bindings(ctx context.Context) ([]Binding, error)
|
|
Binding(ctx context.Context, consumer string) (*Binding, error)
|
|
// Bind binds (or switches) a consumer at its next generation.
|
|
Bind(ctx context.Context, consumer, licence string, m Move) (Binding, error)
|
|
Unbind(ctx context.Context, consumer string) (bool, error)
|
|
// Advance gives every consumer of a licence its next generation: what a rotation is to them.
|
|
Advance(ctx context.Context, licence string, m Move) ([]Binding, error)
|
|
// Lease takes a lease for d, or answers false while another holder's is live.
|
|
Lease(ctx context.Context, key, holder string, d time.Duration) (bool, error)
|
|
Unlease(ctx context.Context, key, holder string) error
|
|
Outcome(ctx context.Context, fingerprint string) (Outcome, error)
|
|
RecordOutcome(ctx context.Context, fingerprint, node, account string, o Outcome, why string) error
|
|
RecordUsage(ctx context.Context, licence string, at int64, r UsageReading, raw map[string]any) error
|
|
// Usage is the latest readings, newest first, of one licence or every one: at most limit, none before since (zero
|
|
// is none), the vendor's answer with raw (§35).
|
|
Usage(ctx context.Context, licence string, since time.Time, limit int, raw bool) ([]UsageRow, error)
|
|
// Audit appends one entry for an act; an error is the act failing (B20).
|
|
Audit(ctx context.Context, what string, detail map[string]any) error
|
|
}
|