Documentation
¶
Overview ¶
Package contributor implements the core of the Unstable Build contributor program: domain types, storage-agnostic stores and a deterministic allocation engine.
The package is intentionally free of provider dependencies (no cloud, payment or identity SDKs) so that the entire allocation logic is public and independently auditable. Monetary amounts are always integer cents; credits are allocation weights, never currency.
Index ¶
- Constants
- Variables
- func ActiveCredits(awards []Award, m Month) (map[string]int64, error)
- func ComputeRound(p Program, m Month, receipts []Receipt, awards []Award, ...) (Round, []Obligation, error)
- func DueDate(p Program, m Month) time.Time
- func ObligationID(m Month, account string) string
- func PoolShareCents(poolBps int, netReceiptsCents int64) int64
- func VerifyRound(s Statement) error
- type Adjustment
- type AdjustmentKind
- type Award
- type AwardStatus
- type AwardStore
- type Entitlement
- type Ledger
- type Month
- type Obligation
- type ObligationEvent
- type ObligationState
- type ObligationStore
- type Participant
- type ParticipantStatus
- type ParticipantStore
- type Program
- type ProgramStore
- type Receipt
- type ReceiptStore
- type Round
- type RoundStore
- type Split
- type Statement
Constants ¶
const CalculationVersion = 1
CalculationVersion is the version of the allocation engine implemented by this package. Programs pin the calculation version they were published against; ComputeRound refuses to run on a mismatch.
Variables ¶
var ErrRoundClosed = errors.New("round already closed")
ErrRoundClosed is returned by Ledger.CloseRound when the month has already been closed.
Functions ¶
func ActiveCredits ¶
ActiveCredits resolves the active credits per account for month m from approved awards. An award is active in m when Activation <= m < Expiration. Awards that are not approved are ignored; approved awards that fail validation are an error.
func ComputeRound ¶
func ComputeRound( p Program, m Month, receipts []Receipt, awards []Award, carryforwardCents int64, ) (Round, []Obligation, error)
ComputeRound computes the allocation round for month m from frozen inputs: the effective program, the month's covered receipts, the approved awards and the balance carried forward from the previous round. It returns the Round and the obligations it produces, in ObligationEarned state. It persists nothing and reads no clocks: closing is the caller's responsibility.
When the pool is not positive or no credits are active, the round carries its pool forward through Round.UnallocatedCents and produces no obligations.
func DueDate ¶
DueDate returns when obligations of round m become due under policy p: PayoutDueDays days after the end of the calendar quarter containing m.
func ObligationID ¶
ObligationID returns the deterministic identifier of the obligation for month m and the given account. Determinism makes payment instructions idempotent.
func PoolShareCents ¶
PoolShareCents returns the pool contribution of the given net receipts under a pool share expressed in basis points. The result is truncated toward zero; sub-cent remainders stay with the operator, never the pool.
func VerifyRound ¶
VerifyRound recomputes the allocation of a closed round from its frozen inputs and returns an error describing the first discrepancy found, or nil if the round's published results are reproducible.
Types ¶
type Adjustment ¶
type Adjustment struct {
// Kind is the deduction category.
Kind AdjustmentKind
// AmountCents is the deducted amount in cents. Always non-negative;
// it is subtracted from the gross.
AmountCents int64
// Description optionally explains the adjustment.
Description string
}
Adjustment is a single deduction from a receipt's gross amount.
type AdjustmentKind ¶
type AdjustmentKind string
AdjustmentKind enumerates the permitted deductions from a receipt's gross amount. Only enumerated kinds may reduce the covered pool base.
const ( // AdjustmentTax covers sales tax, VAT and similar collected taxes. AdjustmentTax AdjustmentKind = "tax" // AdjustmentRefund covers refunds and chargebacks. AdjustmentRefund AdjustmentKind = "refund" // AdjustmentPassThrough covers amounts collected on behalf of third // parties that are not program revenue. AdjustmentPassThrough AdjustmentKind = "pass-through" )
type Award ¶
type Award struct {
// ID is the award's identifier, assigned by the store on creation.
ID string
// Splits assigns the award's credits to one or more recipients.
Splits []Split
// Activation is the first round in which the credits are active.
Activation Month
// Expiration is the first round in which the credits are no longer
// active (exclusive bound), normally derived from the policy's
// credit duration via Program.ExpirationMonth.
Expiration Month
// Evidence lists public URLs backing the award, e.g. merged pull
// requests. At least one is required.
Evidence []string
// Description summarizes the contribution being awarded.
Description string
// PolicyVersion is the Program.Version under which the award was
// proposed.
PolicyVersion string
// Status is the award's review status.
Status AwardStatus
// ProposedBy identifies who proposed the award.
ProposedBy string
// ProposedAt is when the award was proposed.
ProposedAt time.Time
// DecidedBy identifies who approved or rejected the award.
DecidedBy string
// DecidedAt is when the award was approved or rejected.
DecidedAt time.Time
// DecisionNote optionally explains the decision.
DecisionNote string
CreatedAt time.Time
UpdatedAt time.Time
}
Award is an explicit grant of credits for a contribution, always backed by public evidence (e.g. merged pull request URLs). Awards are never auto-computed from activity metrics.
func (Award) ActiveIn ¶
ActiveIn reports whether the award's credits are active in month m, i.e. Activation <= m < Expiration.
func (Award) TotalCredits ¶
TotalCredits returns the sum of the award's split credits.
type AwardStatus ¶
type AwardStatus string
AwardStatus is the review status of an Award.
const ( // AwardProposed awards are pending review and carry no weight. AwardProposed AwardStatus = "proposed" // AwardApproved awards contribute active credits between their // activation and expiration months. AwardApproved AwardStatus = "approved" // AwardRejected awards were reviewed and declined. AwardRejected AwardStatus = "rejected" )
type AwardStore ¶
type AwardStore interface {
// CreateAward stores a new award and returns its assigned ID.
CreateAward(context.Context, Award) (string, error)
// GetAward returns the award with the given ID.
GetAward(ctx context.Context, id string) (Award, error)
// SetAward overwrites the award identified by Award.ID.
SetAward(context.Context, Award) error
// ListAwards lists awards with the given status, or all awards if
// status is empty.
ListAwards(ctx context.Context, status AwardStatus) (
iterator.Iterator[Award], error)
}
AwardStore persists Awards.
func NewDocumentAwardStore ¶
func NewDocumentAwardStore(db document.Service) AwardStore
NewDocumentAwardStore returns an AwardStore backed by db.
type Entitlement ¶
type Entitlement struct {
// Account is the participant's account reference.
Account string
// Credits is the participant's active credits in the round —
// a frozen input of the calculation.
Credits int64
// AmountCents is the resulting entitlement in cents.
AmountCents int64
}
Entitlement is one participant's share of a round's pool.
func Allocate ¶
func Allocate(poolCents int64, credits map[string]int64) ([]Entitlement, error)
Allocate splits poolCents among accounts proportionally to their credits: amount_i = poolCents × credits_i / Σcredits, rounded with the largest-remainder method so that the allocated total always equals poolCents exactly. Entitlements are returned ordered by account.
A zero credit total yields no entitlements: the caller carries the pool forward. A zero pool yields zero-amount entitlements that still record each account's credits.
type Ledger ¶
type Ledger struct {
Programs ProgramStore
Awards AwardStore
Receipts ReceiptStore
Rounds RoundStore
Obligations ObligationStore
}
Ledger orchestrates the contributor program stores: it assembles the frozen inputs of a round from the stores, delegates the calculation to the pure engine and persists the results. It contains no allocation logic of its own.
func (Ledger) CloseRound ¶
func (l Ledger) CloseRound( ctx context.Context, m Month, closedAt time.Time, closedBy string, ) (Round, error)
CloseRound freezes month m: it computes the round from the effective program, the month's receipts, the approved awards and the previous round's carryforward, then persists the round and its obligations in ObligationEarned state. It returns ErrRoundClosed if m was already closed. Closing out of order is rejected; a closed round is never modified.
type Month ¶
type Month string
Month identifies a monthly allocation round in "YYYY-MM" form. The representation sorts lexicographically in chronological order, which makes it usable directly in document store filters.
func ParseMonth ¶
ParseMonth parses a Month in "YYYY-MM" form.
func (Month) Add ¶
Add returns the Month n months after m. Negative values of n are permitted and move backwards in time.
type Obligation ¶
type Obligation struct {
// Account is the recipient participant's account reference.
Account string
// Month is the round that produced the obligation.
Month Month
// AmountCents is the gross amount owed in cents.
AmountCents int64
// Currency is the ISO 4217 currency code.
Currency string
// DueDate is when the obligation becomes due under the payment
// timetable.
DueDate time.Time
// State is the current lifecycle state.
State ObligationState
// ProviderTransferRef is an opaque reference to the payout
// provider's transfer, set once a transfer is initiated.
ProviderTransferRef string
// History records every state transition.
History []ObligationEvent
CreatedAt time.Time
UpdatedAt time.Time
}
Obligation is a payable resulting from a closed round's entitlement. Its identity is derived from the round month and recipient account (see ObligationID), which also serves as the idempotency key for provider transfers.
func (Obligation) ID ¶
func (o Obligation) ID() string
ID returns the obligation's deterministic identifier.
func (Obligation) Transition ¶
func (o Obligation) Transition( to ObligationState, at time.Time, note string, ) (Obligation, error)
Transition returns a copy of the obligation moved to state, recording the transition in History. It returns an error if the transition is not legal.
type ObligationEvent ¶
type ObligationEvent struct {
From ObligationState
To ObligationState
At time.Time
Note string
}
ObligationEvent records one state transition for audit purposes.
type ObligationState ¶
type ObligationState string
ObligationState is the lifecycle state of an Obligation. States label where the amount stands; no state implies funds are reserved.
const ( // ObligationEstimated is a running estimate for a round that has not // closed yet. Estimates are never persisted as obligations. ObligationEstimated ObligationState = "estimated" // ObligationEarned means the round closed and the entitlement is // final, but not yet due under the payment timetable. ObligationEarned ObligationState = "earned" // ObligationOwed means the obligation is due for payment. ObligationOwed ObligationState = "owed" // ObligationInitiated means a provider transfer was created. ObligationInitiated ObligationState = "initiated" // ObligationSettled means the transfer completed. ObligationSettled ObligationState = "settled" )
type ObligationStore ¶
type ObligationStore interface {
// CreateObligation stores a new obligation. It returns
// document.ErrAlreadyExists if it was already created.
CreateObligation(context.Context, Obligation) error
// GetObligation returns the obligation for month m and account.
GetObligation(ctx context.Context, m Month, account string) (
Obligation, error)
// SetObligation overwrites the obligation record.
SetObligation(context.Context, Obligation) error
// ListAccountObligations lists all obligations of an account.
ListAccountObligations(ctx context.Context, account string) (
iterator.Iterator[Obligation], error)
// ListStateObligations lists all obligations in the given state.
ListStateObligations(ctx context.Context, state ObligationState) (
iterator.Iterator[Obligation], error)
}
ObligationStore persists Obligations, keyed by ObligationID.
func NewDocumentObligationStore ¶
func NewDocumentObligationStore(db document.Service) ObligationStore
NewDocumentObligationStore returns an ObligationStore backed by db.
type Participant ¶
type Participant struct {
// Account is an opaque reference to the participant's user account
// in the embedding system. It is the Participant's identity.
Account string
// GitHubHandle is the participant's public GitHub username.
GitHubHandle string
// AgreementVersion is the contributor agreement version accepted at
// enrollment.
AgreementVersion string
// AgreementAcceptedAt is when the agreement was accepted.
AgreementAcceptedAt time.Time
// AgreementEvidence is an opaque reference to evidence of the
// acceptance, e.g. a request audit log entry.
AgreementEvidence string
// Status is the participant's eligibility status.
Status ParticipantStatus
// PayoutProviderRef is an opaque reference to the participant's
// account at the payout provider. Empty until payment onboarding
// completes; enrollment never requires it.
PayoutProviderRef string
// PayoutReady reports whether the payout provider accepted the
// participant's onboarding and transfers can be initiated.
PayoutReady bool
CreatedAt time.Time
UpdatedAt time.Time
}
Participant is an enrolled contributor. Public recognition (the GitHub handle) is kept separate from private payee identity: this type carries only an opaque payout provider reference, never banking details.
func (Participant) Validate ¶
func (p Participant) Validate() error
Validate returns an error if the Participant is missing required fields.
type ParticipantStatus ¶
type ParticipantStatus string
ParticipantStatus is the eligibility status of a Participant.
const ( // ParticipantEligible participants receive entitlements in rounds. ParticipantEligible ParticipantStatus = "eligible" // ParticipantSuspended participants are temporarily excluded from // payouts, e.g. pending compliance review. ParticipantSuspended ParticipantStatus = "suspended" // ParticipantWithdrawn participants have left the program. ParticipantWithdrawn ParticipantStatus = "withdrawn" )
type ParticipantStore ¶
type ParticipantStore interface {
// CreateParticipant stores a new participant. It returns
// document.ErrAlreadyExists if the account is already enrolled.
CreateParticipant(context.Context, Participant) error
// GetParticipant returns the participant with the given account.
GetParticipant(ctx context.Context, account string) (Participant, error)
// SetParticipant overwrites the participant record.
SetParticipant(context.Context, Participant) error
// ListParticipants lists all participants.
ListParticipants(context.Context) (iterator.Iterator[Participant], error)
}
ParticipantStore persists Participants, keyed by account reference.
func NewDocumentParticipantStore ¶
func NewDocumentParticipantStore(db document.Service) ParticipantStore
NewDocumentParticipantStore returns a ParticipantStore backed by db.
type Program ¶
type Program struct {
// Version identifies this policy revision, e.g. "2026-01".
Version string
// Currency is the ISO 4217 currency code all receipts, pools and
// obligations are denominated in, e.g. "usd".
Currency string
// PoolBps is the share of covered net receipts allocated to the
// monthly pool, in basis points (2000 = 20%).
PoolBps int
// CoveredReceipts is a human-readable definition of which receipts
// are covered by the program.
CoveredReceipts string
// CreditDurationRounds is the number of monthly rounds an awarded
// credit stays active, counted from its activation month.
CreditDurationRounds int
// PaymentTimetable is a human-readable description of when earned
// entitlements become owed and are paid out.
PaymentTimetable string
// PayoutDueDays is the number of days after the end of the calendar
// quarter containing a round in which its obligations become due.
PayoutDueDays int
// CalculationVersion is the allocation engine version this policy
// was published against. Rounds refuse to close if it does not match
// the engine's CalculationVersion.
CalculationVersion int
// EffectiveFrom is the first month this policy applies to.
EffectiveFrom Month
CreatedAt time.Time
UpdatedAt time.Time
}
Program is a versioned policy of the contributor program. A Program is immutable once published: policy changes are new Program versions with a later EffectiveFrom month.
func (Program) ExpirationMonth ¶
ExpirationMonth returns the first month in which a credit activated in the given month is no longer active under this policy.
type ProgramStore ¶
type ProgramStore interface {
// PutProgram stores the program, keyed by Program.Version.
PutProgram(context.Context, Program) error
// GetProgram returns the program with the given version.
GetProgram(ctx context.Context, version string) (Program, error)
// ProgramFor returns the policy in effect for month m: the program
// with the latest EffectiveFrom that is not after m. It returns
// document.ErrNotFound if no program is effective.
ProgramFor(ctx context.Context, m Month) (Program, error)
// ListPrograms lists all program versions.
ListPrograms(context.Context) (iterator.Iterator[Program], error)
}
ProgramStore persists Program policy versions.
func NewDocumentProgramStore ¶
func NewDocumentProgramStore(db document.Service) ProgramStore
NewDocumentProgramStore returns a ProgramStore backed by db.
type Receipt ¶
type Receipt struct {
// Source is the opaque, unique reference to the originating billing
// record (e.g. an invoice identifier). It is the Receipt's identity.
Source string
// Month is the round the receipt is attributed to.
Month Month
// GrossCents is the gross amount in cents.
GrossCents int64
// Adjustments enumerates deductions from the gross amount.
Adjustments []Adjustment
// Currency is the ISO 4217 currency code, e.g. "usd". It must match
// the program currency for the receipt to be covered.
Currency string
// Evidence is an opaque reference to supporting documentation.
Evidence string
CreatedAt time.Time
UpdatedAt time.Time
}
Receipt records covered revenue attributed to a month. Receipts are imported from the billing system with an opaque source reference that doubles as their identity, making imports idempotent.
type ReceiptStore ¶
type ReceiptStore interface {
// CreateReceipt stores a new receipt. It returns
// document.ErrAlreadyExists if a receipt with the same source was
// already imported.
CreateReceipt(context.Context, Receipt) error
// GetReceipt returns the receipt with the given source reference.
GetReceipt(ctx context.Context, source string) (Receipt, error)
// ListMonthReceipts lists the receipts attributed to month m.
ListMonthReceipts(ctx context.Context, m Month) (
iterator.Iterator[Receipt], error)
}
ReceiptStore persists Receipts, keyed by source reference so that imports are idempotent.
func NewDocumentReceiptStore ¶
func NewDocumentReceiptStore(db document.Service) ReceiptStore
NewDocumentReceiptStore returns a ReceiptStore backed by db.
type Round ¶
type Round struct {
// Month identifies the round.
Month Month
// PolicyVersion is the Program.Version applied.
PolicyVersion string
// CalculationVersion is the engine version used to compute the
// round.
CalculationVersion int
// Currency is the program currency the round is denominated in.
Currency string
// NetReceiptsCents is the sum of covered net receipts of the month.
NetReceiptsCents int64
// CarryforwardCents is the unallocated balance carried in from the
// previous round.
CarryforwardCents int64
// PoolCents is the allocatable pool:
// CarryforwardCents + NetReceiptsCents × PoolBps / 10000.
PoolCents int64
// TotalCredits is the allocation denominator: the sum of all active
// credits in the round.
TotalCredits int64
// Entitlements are the per-participant results, ordered by account.
Entitlements []Entitlement
// UnallocatedCents is the part of the pool not allocated in this
// round; it is carried forward into the next round. It is the whole
// pool when TotalCredits is zero and zero otherwise.
UnallocatedCents int64
// ClosedAt is when the round was closed.
ClosedAt time.Time
// ClosedBy identifies who closed the round.
ClosedBy string
CreatedAt time.Time
UpdatedAt time.Time
}
Round is a closed monthly allocation. All inputs are frozen at closing time so the calculation can be reproduced and verified independently (see VerifyRound). A closed Round is immutable: corrections are new events (e.g. adjustment receipts in a later round), never edits.
func (Round) AllocatedCents ¶
AllocatedCents returns the sum of the round's entitlement amounts.
type RoundStore ¶
type RoundStore interface {
// CreateRound stores a closed round. It returns
// document.ErrAlreadyExists if the month is already closed.
CreateRound(context.Context, Round) error
// GetRound returns the closed round for month m.
GetRound(ctx context.Context, m Month) (Round, error)
// ListRounds lists all closed rounds.
ListRounds(context.Context) (iterator.Iterator[Round], error)
}
RoundStore persists closed Rounds, keyed by month. Rounds are immutable: the interface deliberately offers no update operation.
func NewDocumentRoundStore ¶
func NewDocumentRoundStore(db document.Service) RoundStore
NewDocumentRoundStore returns a RoundStore backed by db.
type Split ¶
type Split struct {
// Account is the recipient participant's account reference.
Account string
// Credits is the credit quantity assigned to the recipient.
// Credits are allocation weights, not currency.
Credits int64
}
Split assigns a share of an Award's credits to one recipient.