payout

package
v1.801.490 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 6, 2026 License: Apache-2.0 Imports: 6 Imported by: 0

Documentation

Overview

Package payout is what the referral, affiliate and author programs ask of the money plane, and it is a QUESTION: what has this org spent? That read is the qualify signal / accrual base. It was three byte-identical commerce.go copies; extracted here so the commerce binding lives exactly ONCE.

IT NO LONGER DEPOSITS. It carried a Deposit — the ONE money-in primitive all three programs shared — which is how a GET on three surfaces came to mint platform credit. Earnings are PAYABLES now: each program ACCRUES and RECORDS what is owed, and a human settles it out of band. Platform credit is issued only by an admin grant (apps/admin/core.ApplyGrant). TestSeamIsReadOnly fails if a write returns.

It used to ask over HTTP, and it never once got an answer

This was an *http.Client aimed at GET /v1/billing/usage/rollup, sent through the commerce transport with the admin service token. That transport does not reach a network when commerce is co-resident: it dispatches the request back into this binary's own router BY PATH, and /v1/billing/usage/rollup is registered nowhere here — commerce's own api.Route() bundle is behind //go:build cloud and is never compiled in. So the read was a 404 wearing an upstream failure's clothes. Split into per-app binaries it failed differently and worse: the base URL is empty in every process but commerce's, so the client reported itself "not configured" and answered ZERO. Referrals qualified nobody, affiliates accrued nothing, authors were paid nothing — silently, for as long as that shape shipped.

It asks the ledger BY NAME now (plane.FinanceSpend). There is no URL, no service token and nothing for a deployment to configure, so there is no configuration that can be wrong.

Commerce is an INTERFACE so each program's store/handler logic stays testable with a fake ledger; Client is the ONE production binding. A program keeps its own narrow (unexported-method) seam and a thin adapter delegating to Client — Go package-scoped interface methods can't cross packages, and the adapter is where a program still names its own grant tag.

Index

Constants

This section is empty.

Variables

View Source
var ErrNoLedger = errors.New("payout: this deployment runs no commerce")

ErrNoLedger reports that this deployment runs no commerce at all, so there is no spend to read and none to accrue against.

It is the ONLY absence a program may act on, and it is the ROUTER'S word (cloud.ErrNoPeer), never an inference from a failed call. The predicate it replaces asked whether a base URL and a token were set — two things that do not exist for a peer reached by name, and which were unset in every process but one, which is how "no commerce here" and "commerce is right there and I cannot spell its address" became the same silent zero.

Functions

This section is empty.

Types

type Client

type Client struct{}

Client is the production commerce binding: the ledger, asked by name over the internal plane. It holds no address and no credential, because reaching a peer takes neither.

func NewClient

func NewClient() *Client

NewClient builds the production binding. It takes no arguments: a peer is reached through zip.SocketPath(name), so there was never an address to supply.

func (*Client) SpendCents

func (c *Client) SpendCents(ctx context.Context, org string) (int64, error)

SpendCents reads the org's month-to-date metered consumption from the process that owns the ledger.

The ORG rides the call — cloud.For states the tenant for a read with no request behind it — because a caller that could name the org in an argument could accrue a commission against another tenant's spend. There is no `user`: the figure was always the org's, and the rollup's `user` parameter was the org's own name sent back to it.

ABSENCE IS THE ROUTER'S WORD. cloud.ErrNoPeer becomes ErrNoLedger, and only that means there is honestly nothing to read. Every other error is an OUTAGE and is returned as one: a dead ledger read as a zero is a program that quietly stops paying people.

type Commerce

type Commerce interface {
	// SpendCents is the org's month-to-date metered consumption — the qualify
	// signal / commission accrual base (spend × the program's rate).
	SpendCents(ctx context.Context, org string) (int64, error)
}

Commerce is the ONE thing an attributed-credit program asks of the money plane, and it is a QUESTION: what has this org spent? Client below is the ONE production binding. There is no write method, by design.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL