Files
zeekay 1943f1c093 Hanzo Commerce
Multi-tenant commerce and billing: orders, subscriptions, invoices, plans,
usage metering and a credit ledger. One Go binary. MIT OR Apache-2.0.

Claude-Session: https://claude.ai/code/session_01SAtaDFm8VDiWrhYHNNtxMw
2026-09-23 21:52:16 -07:00

92 lines
2.7 KiB
Go

package contributor
import (
"time"
"github.com/hanzoai/commerce/datastore"
"github.com/hanzoai/commerce/models/mixin"
"github.com/hanzoai/commerce/util/json"
"github.com/hanzoai/commerce/util/val"
"github.com/hanzoai/orm"
. "github.com/hanzoai/commerce/types"
)
func init() { orm.Register[SBOMEntry]("sbom-entry") }
// SBOMEntry represents a software component in the platform's bill of materials.
// Each entry tracks the component's identity, its contributors, and the
// revenue attributed to it based on bot/agent usage.
type SBOMEntry struct {
mixin.Model[SBOMEntry]
// Component identity
Component string `json:"component"` // Package name (e.g., "@hanzo/bot")
Repo string `json:"repo"` // GitHub repo (e.g., "hanzoai/bot")
Version string `json:"version"` // Current version
License string `json:"license"` // License type (MIT, Apache-2.0, etc.)
TotalLines int64 `json:"totalLines"` // Total lines of code
// Contributor breakdown from git blame
// [{"login":"user","email":"[email protected]","lines":500,"percent":12.5}]
Authors []SBOMAuthor `json:"authors,omitempty" datastore:"-"`
Authors_ string `json:"-" datastore:",noindex"`
// Revenue attribution
UsageCount int64 `json:"usageCount"` // Times used in billing period
RevenuePercent float64 `json:"revenuePercent"` // % of total platform revenue attributed
// Scan metadata
LastScanned time.Time `json:"lastScanned"`
ScanCommit string `json:"scanCommit"` // Git commit hash of last scan
Metadata Map `json:"metadata,omitempty" datastore:"-"`
Metadata_ string `json:"-" datastore:",noindex"`
}
// SBOMAuthor is a contributor entry from git blame analysis.
type SBOMAuthor struct {
Login string `json:"login"`
Email string `json:"email"`
Name string `json:"name,omitempty"`
Lines int64 `json:"lines"`
Percent float64 `json:"percent"` // Percentage of component authored
}
func (s *SBOMEntry) Load(ps []datastore.Property) (err error) {
if err = datastore.LoadStruct(s, ps); err != nil {
return err
}
if len(s.Authors_) > 0 {
err = json.DecodeBytes([]byte(s.Authors_), &s.Authors)
if err != nil {
return err
}
}
if len(s.Metadata_) > 0 {
err = json.DecodeBytes([]byte(s.Metadata_), &s.Metadata)
}
return err
}
func (s *SBOMEntry) Save() (ps []datastore.Property, err error) {
s.Authors_ = string(json.EncodeBytes(&s.Authors))
s.Metadata_ = string(json.EncodeBytes(&s.Metadata))
return datastore.SaveStruct(s)
}
func (s *SBOMEntry) Validator() *val.Validator {
return nil
}
func NewSBOM(db *datastore.Datastore) *SBOMEntry {
s := new(SBOMEntry)
s.Init(db)
s.Parent = db.NewKey("synckey", "", 1, nil)
return s
}
func QuerySBOM(db *datastore.Datastore) datastore.Query {
return db.Query("sbom-entry")
}