Documentation
¶
Overview ¶
Package ossaccrual is the payout-accrual ledger for the SBOM-driven OSS developer payout system. Each OSSAccrual is one append-only ledger line: a slice of one org's spend attributed to one OSS package, ready to be paid to that package's upstream maintainers.
It is the persistent counterpart to the pure ossattr.Attribute math: when an org's usage is recorded, the accrual engine computes the capped, weighted, pro-rata split and writes one OSSAccrual per package. The ledger is the provable thing — "Hanzo owes pkg:golang/.../gin $X.XX, accrued across these transactions" — independent of whether the money has been disbursed yet.
Invariants:
- Append-only: accruals are never mutated to change an amount; the running total is the SUM of accrual lines for a package. Disbursement is a separate Payout referencing the lines it settles (Status transitions pending -> settled record the payout, they do not rewrite the amount).
- Idempotent: IdempotencyKey = ossattr.AccrualID(org, txn, purl) makes the same (org, spend-transaction, package) accrue exactly once, even on retries — mirroring commerce's tag-deduped usage recording.
- Tenant-scoped to the SPENDING org's namespace? No — accruals are a PLATFORM liability (Hanzo -> OSS), so they live in the platform/system namespace, aggregated across all paying orgs. SpendOrg records who the spend came from for audit, but the payable is global.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
Types ¶
type OSSAccrual ¶
type OSSAccrual struct {
mixin.Model[OSSAccrual]
// Package identity (PURL is the canonical key joining to SBOM + resolver).
PURL string `json:"purl"`
Name string `json:"name,omitempty"`
Ecosystem string `json:"ecosystem,omitempty"`
Version string `json:"version,omitempty"`
Scope Scope `json:"scope,omitempty"`
// Attribution provenance — everything needed to recompute this line.
SpendOrg string `json:"spendOrg"` // org whose spend produced this
SpendUser string `json:"spendUser,omitempty"`
SourceTxnID string `json:"sourceTxnId"` // the usage transaction
SpendCents currency.Cents `json:"spendCents"` // the org's charge this line derives from
PoolFraction float64 `json:"poolFraction"` // effective (<=0.25) pool fraction
Weight float64 `json:"weight"` // package weight used
// The accrued amount owed to this package.
Currency currency.Type `json:"currency"`
Amount currency.Cents `json:"amount"`
Status Status `json:"status" orm:"default:pending"`
// PayoutId links the line to the disbursement that settles it (set when
// Status -> queued/settled). Empty while pending/held.
PayoutId string `json:"payoutId,omitempty"`
// Resolved maintainer target snapshot (denormalized from the resolver at
// accrual time so the ledger is self-contained for audit). Empty -> held.
FundingTarget string `json:"fundingTarget,omitempty"` // e.g. "github_sponsors:gin-gonic"
FundingKind string `json:"fundingKind,omitempty"` // github_sponsors|opencollective|...
// IdempotencyKey = ossattr.AccrualID(spendOrg, sourceTxnId, purl).
IdempotencyKey string `json:"idempotencyKey"`
Test bool `json:"test"`
Metadata Map `json:"metadata,omitempty" datastore:"-"`
Metadata_ string `json:"-" datastore:",noindex"`
}
OSSAccrual is one accrual ledger line.
func New ¶
func New(db *datastore.Datastore) *OSSAccrual
func (*OSSAccrual) Defaults ¶
func (a *OSSAccrual) Defaults()
func (*OSSAccrual) Validator ¶
func (a *OSSAccrual) Validator() *val.Validator
type Scope ¶
type Scope string
Scope mirrors ossattr.Scope (direct | transitive) for the line's audit trail.
type Status ¶
type Status string
Status is the lifecycle of an accrual line.
const ( // Pending: accrued, not yet included in a payout. Pending Status = "pending" // Held: accrued but the maintainer/funding target is unresolved; the // amount waits in the held pool until resolution. Held Status = "held" // Queued: included in a payout batch that is being disbursed. Queued Status = "queued" // Settled: the referenced payout has paid out. Settled Status = "settled" )