budgets

package
v0.0.0-...-567e556 Latest Latest
Warning

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

Go to latest
Published: Nov 3, 2026 License: MIT Imports: 19 Imported by: 0

Documentation

Overview

Package budgets implements the AAuth Budgets protocol companion.

Index

Constants

View Source
const MaximumAmount int64 = 999_999_999_999_999

MaximumAmount is the 15-digit limit shared by Budget JSON values and RFC 9651 Integer members.

Variables

View Source
var ErrUsageRequest = errors.New("budgets: usage request is invalid")

ErrUsageRequest marks a usage body the endpoint rejects as invalid_request.

View Source
var ErrUsageUnsigned = errors.New("budgets: usage response is not signed")

ErrUsageUnsigned reports a usage response that carries no signature when the caller required one.

Functions

func AccountedSpend

func AccountedSpend(grant Value, consumed *ConsumptionRecord) (int64, error)

AccountedSpend is what an issuer holds against one allocation until a usage reading settles it. A missing consumption record is the full grant. A record replaces that assumption and is not added to it.

func CheckUsageResponse

func CheckUsageResponse(request UsageRequest, caller string, response UsageResponse) error

CheckUsageResponse reports whether a success body answers this request for this caller. An omitted usage object is a valid answer to a scope key.

func FormatAuthTokenRequirement

func FormatAuthTokenRequirement(value aauth.AuthTokenRequirement, reason Reason) (string, error)

FormatAuthTokenRequirement formats the Core auth-token requirement with one typed Budget reason parameter.

func FormatConsentAmount

func FormatConsentAmount(value Value) (string, error)

FormatConsentAmount renders a budget the way a Person Server shows it to a person. USD at decimals 6 becomes a dollar figure, keeping extra fraction digits when the amount is not an exact cent. Other units are the scaled number plus the unit name.

func FormatFeedback

func FormatFeedback(feedback Feedback) (string, error)

FormatFeedback emits the canonical RFC 9651 Dictionary form.

func FormatTrailer

func FormatTrailer(cost int64) (string, error)

FormatTrailer emits the cost-only AAuth-Budget trailer. A trailer must not restate a member the header carried.

func Free

func Free(ceiling, metered int64, allocations []Allocation, asOf time.Time) (int64, error)

Free is ceiling − metered − unsettled allocations. A consumption record is not an input: it refines a live allocation and does not settle it. A negative result means the ceiling is already exceeded.

func IsTokenClaimError

func IsTokenClaimError(err error) bool

IsTokenClaimError reports whether Core token verification succeeded but the Budget companion claims were malformed. Token endpoints use this distinction to return the Budgets protocol's registered invalid_budget error.

func MintAuthToken

func MintAuthToken(key jose.SigningKey, claims aauth.AuthTokenClaims, grant Value) (string, error)

MintAuthToken adds one validated Budget grant to Core Auth-token claims.

func MintResourceToken

func MintResourceToken(
	key jose.SigningKey,
	claims aauth.ResourceTokenClaims,
	offer Value,
	consumed *ConsumptionRecord,
) (string, error)

MintResourceToken adds one validated Budget offer to Core Resource-token claims. The optional consumption record reports what the Auth token presented on the answered request has consumed, so its jti is the token's presented_jti.

func SanitizeDescription

func SanitizeDescription(description string) (string, error)

SanitizeDescription removes active HTML and dangerous link schemes from a resource-supplied Markdown unit description before a consent screen renders it. The stored metadata value is unchanged; callers render the result. Numeric character references and a small set of named entities are decoded before the check, so an encoded scheme such as javascript: is not a link. Reference-style definitions are checked as well as inline links. javascript:, vbscript:, and data: are removed from those destinations.

func SettledRemaining

func SettledRemaining(feedback Feedback) (int64, error)

SettledRemaining is remaining + reserved - cost after a streamed response. Remaining is already net of the reservation, so the unspent hold returns to the grant. A header that omitted cost uses the full reservation.

func TokenCarriesClaims

func TokenCarriesClaims(compact string) (bool, error)

TokenCarriesClaims reports whether an unverified compact token names a Budget claim, including partial and case-variant forms that must route to strict Budget verification.

func TokenClaimError

func TokenClaimError(err error) error

TokenClaimError marks an error found after Core token verification while consuming Budget companion claims. Endpoints use it to return the registered invalid_budget response for composed token profiles too.

func UnsettledAmount

func UnsettledAmount(allocations []Allocation, asOf time.Time) (int64, error)

UnsettledAmount is the sum of allocations a reading at asOf has not settled.

func UsageResponseSignOptions

func UsageResponseSignOptions() signaturekey.ResponseSignOptions

UsageResponseSignOptions is the coverage of a signed usage response: @status, content-type and content-digest, bound to the request by @authority and @path under req. A Resource signs with these options and its jwks_uri key; VerifyUsageResponse requires the same coverage.

func ValidateConsumptionRecord

func ValidateConsumptionRecord(consumed *ConsumptionRecord, presentedJTI string) error

ValidateConsumptionRecord checks an optional Resource-token consumption record. A record names the Auth token presented on the request the Resource token answers, which the token carries as presented_jti.

func ValidateDeclaredValue

func ValidateDeclaredValue(declarations []UnitDeclaration, value Value) error

ValidateDeclaredValue checks that a signed offer or grant uses one declared denomination and does not exceed its advertised maximum when present.

func ValidateFeedback

func ValidateFeedback(grant Value, feedback Feedback) error

ValidateFeedback checks unsigned informational feedback against the signed Auth-token budget. An omitted unit pair remains valid because the pair is optional; a present pair must match exactly.

func ValidateFeedbackUnit

func ValidateFeedbackUnit(unit Unit) error

ValidateFeedbackUnit checks that a JSON Budget unit is representable as an RFC 9651 String in AAuth-Budget. The token object permits arbitrary UTF-8, but a metering profile that emits the response field must establish this narrower carrier before any charge.

func ValidateNarrowing

func ValidateNarrowing(offered, granted Value) error

ValidateNarrowing requires the same denomination and an amount no greater than the resource's offer.

func ValidateUnitDeclarations

func ValidateUnitDeclarations(declarations []UnitDeclaration) error

ValidateUnitDeclarations requires valid entries and one scale per unit identifier.

func VerifyResourceToken

func VerifyResourceToken(
	ctx context.Context,
	compact string,
	resolver signaturekey.KeyResolver,
	clock aauth.Clock,
) (aauth.ResourceTokenClaims, Value, *ConsumptionRecord, error)

VerifyResourceToken verifies Core trust and consumes the complete Budget companion claim set.

func VerifyUsageResponse

func VerifyUsageResponse(
	ctx context.Context,
	request *http.Request,
	status int,
	header http.Header,
	body []byte,
	resource string,
	resolver signaturekey.KeyResolver,
	clock aauth.Clock,
) (signaturekey.VerifiedResponse, error)

VerifyUsageResponse verifies a signed usage response: status, header and the exact body bytes the caller received, and request, the usage query the caller sent. The signature must cover what UsageResponseSignOptions covers and verify under a key from resource's own metadata, so a response signed by any other party, or for another request, is refused. The PS or AS that keeps the exact body and header holds a statement the resource cannot later disown.

Types

type Allocation

type Allocation struct {
	Amount               int64
	ExpiresAt            time.Time
	RevocationRecordedAt time.Time
}

Allocation is one issuer-side budget that has not necessarily been settled. RevocationRecordedAt is set only when the resource recorded the revocation. revocation_unsupported and revocation_unavailable leave it zero and settle at ExpiresAt.

func (Allocation) Settled

func (allocation Allocation) Settled(asOf time.Time) bool

Settled reports whether a usage reading at asOf releases the allocation. A recorded revocation settles at that recording time. Every other allocation settles when exp is at or before asOf. A consumption record does not settle.

type ConsumptionRecord

type ConsumptionRecord struct {
	// contains filtered or unexported fields
}

ConsumptionRecord reports metered consumption against one prior Auth token.

func ConsumptionForPresentedGrant

func ConsumptionForPresentedGrant(jti string, grant Value, remaining int64) (ConsumptionRecord, error)

ConsumptionForPresentedGrant is the consumption record for an Auth token whose metered spend is the granted amount minus the uncommitted remainder. Remaining must be that uncommitted remainder. A figure already net of in-flight holds makes this record count those holds as consumed. The record uses the grant's scale. A caller that would restate the figure in another scale omits the record instead of calling this function.

func NewConsumptionRecord

func NewConsumptionRecord(jti string, consumed int64) (ConsumptionRecord, error)

NewConsumptionRecord validates one prior Auth-token consumption record.

func ParseConsumptionRecordJSON

func ParseConsumptionRecordJSON(raw json.RawMessage, presentedJTI string) (*ConsumptionRecord, error)

ParseConsumptionRecordJSON parses the optional budget_consumed claim, a single consumption record for the presented Auth token. A nil claim is absent.

func (ConsumptionRecord) Consumed

func (record ConsumptionRecord) Consumed() int64

Consumed returns the amount metered against the prior Auth token.

func (ConsumptionRecord) JTI

func (record ConsumptionRecord) JTI() string

JTI returns the prior Auth token identifier.

func (ConsumptionRecord) MarshalJSON

func (record ConsumptionRecord) MarshalJSON() ([]byte, error)

MarshalJSON emits the exact Budget consumption-record object.

func (*ConsumptionRecord) UnmarshalJSON

func (record *ConsumptionRecord) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts only the exact Budget consumption-record object.

type Feedback

type Feedback struct {
	// contains filtered or unexported fields
}

Feedback is the parsed AAuth-Budget response field. A fixed-price success carries cost. A refusal carries remaining and maybe required. A streamed response carries reserved and omits cost until a trailer, if any, arrives.

func ApplyTrailer

func ApplyTrailer(header Feedback, trailer []string) (Feedback, error)

ApplyTrailer merges a cost-only trailer into a header. An empty trailer leaves the header unchanged: a recipient must not treat the trailer as necessary. Any member other than cost is rejected, including members the header already carried and members this profile does not recognize. The general header rule ignores unknown members; the trailer rule allows cost and nothing else, and this function follows the trailer rule.

func NewRefusalFeedback

func NewRefusalFeedback(grant Value, remaining int64, required *int64) (Feedback, error)

NewRefusalFeedback constructs feedback for an exhausted or insufficient fixed-price request. Required is omitted when the Resource does not state a maximum cost for the refused request.

func NewReservedFeedback

func NewReservedFeedback(grant Value, remaining, reserved int64) (Feedback, error)

NewReservedFeedback constructs the header for a response whose cost is not known yet. Remaining is already net of the reservation. The header omits cost.

func NewSuccessFeedback

func NewSuccessFeedback(grant Value, cost, remaining int64) (Feedback, error)

NewSuccessFeedback constructs feedback for a completed fixed-price request.

func ParseFeedback

func ParseFeedback(values []string) (Feedback, error)

ParseFeedback parses one or more AAuth-Budget field lines as an RFC 9651 Dictionary. Unknown members are ignored.

func (Feedback) Cost

func (feedback Feedback) Cost() (int64, bool)

Cost returns the cost of this request when reported.

func (Feedback) Remaining

func (feedback Feedback) Remaining() int64

Remaining returns the balance reported for the presented Auth token.

func (Feedback) Required

func (feedback Feedback) Required() (int64, bool)

Required returns the computed maximum cost of a refused request when reported.

func (Feedback) Reserved

func (feedback Feedback) Reserved() (int64, bool)

Reserved returns the amount held for this request when the header reported it.

func (Feedback) Unit

func (feedback Feedback) Unit() (Unit, bool)

Unit returns the informational denomination pair when present.

type Reason

type Reason string

Reason is one Budget-specific reason on an auth-token requirement.

const (
	ReasonBudgetExhausted    Reason = "budget-exhausted"
	ReasonInsufficientBudget Reason = "insufficient-budget"
)

func ParseAuthTokenRequirement

func ParseAuthTokenRequirement(values []string) (aauth.AuthTokenRequirement, Reason, error)

ParseAuthTokenRequirement parses the Core auth-token requirement and its required Budget reason parameter. Unrelated extension parameters remain ignored as required by the base extension model.

func ParseOptionalAuthTokenRequirement

func ParseOptionalAuthTokenRequirement(values []string) (aauth.AuthTokenRequirement, Reason, bool, error)

ParseOptionalAuthTokenRequirement parses the Core auth-token requirement and, when present, one typed Budget reason. A missing reason is the ordinary Core step-up shape; an unknown or malformed present reason fails.

func ParseReason

func ParseReason(value string) (Reason, error)

ParseReason validates a Budget-specific requirement reason.

func (Reason) String

func (reason Reason) String() string

String returns the registered reason token.

type Unit

type Unit struct {
	// contains filtered or unexported fields
}

Unit is one resource-selected Budget denomination and scale.

func NewUnit

func NewUnit(name string, decimals int64) (Unit, error)

NewUnit validates a Budget denomination and scale.

func (Unit) Decimals

func (unit Unit) Decimals() int64

Decimals returns the resource-declared scale.

func (Unit) Equal

func (unit Unit) Equal(other Unit) bool

Equal reports whether two units have the same identifier and scale.

func (Unit) Name

func (unit Unit) Name() string

Name returns the resource-declared unit identifier.

type UnitDeclaration

type UnitDeclaration struct {
	// contains filtered or unexported fields
}

UnitDeclaration is one budget_units Resource-metadata entry. Unit and scale identify the denomination. Maximum is optional in the protocol; a host may require it for a bounded pricing profile.

func FindUnitDeclaration

func FindUnitDeclaration(declarations []UnitDeclaration, unit Unit) (UnitDeclaration, bool)

FindUnitDeclaration returns the declaration for one exact denomination.

func NewBoundedUnitDeclaration

func NewBoundedUnitDeclaration(unit Unit, maximum int64, description string) (UnitDeclaration, error)

NewBoundedUnitDeclaration constructs a declaration with an advertised maximum amount for one Auth token.

func NewUnitDeclaration

func NewUnitDeclaration(unit Unit, description string) (UnitDeclaration, error)

NewUnitDeclaration constructs a declaration without an advertised maximum.

func (UnitDeclaration) Description

func (declaration UnitDeclaration) Description() string

Description returns the optional Markdown description.

func (UnitDeclaration) MarshalJSON

func (declaration UnitDeclaration) MarshalJSON() ([]byte, error)

MarshalJSON emits the flat budget_units metadata object.

func (UnitDeclaration) Maximum

func (declaration UnitDeclaration) Maximum() (int64, bool)

Maximum returns the advertised maximum when present.

func (UnitDeclaration) Unit

func (declaration UnitDeclaration) Unit() Unit

Unit returns the declared denomination and scale.

func (*UnitDeclaration) UnmarshalJSON

func (declaration *UnitDeclaration) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts one strict budget_units metadata object.

type UsageCalendar

type UsageCalendar struct {
	Day     *int64
	Week    *int64
	Month   *int64
	Year    *int64
	AllTime int64
}

UsageCalendar holds the counters a resource chose to report. AllTime is required when the usage object is present. A nil period was omitted.

type UsageRequest

type UsageRequest struct {
	Subject      string
	Tenant       string
	MissionS256  string
	PersonServer string
	JKTs         []string
}

UsageRequest is the JSON body of a signed usage query. At most one of Subject, Tenant, and MissionS256 is set. JKTs may accompany that scope key or stand alone. PersonServer is the ps member an Access Server sends with a scope key; a Person Server omits it.

func ParseUsageRequest

func ParseUsageRequest(data []byte) (UsageRequest, error)

ParseUsageRequest accepts one strict usage-request object.

func (UsageRequest) HasScope

func (request UsageRequest) HasScope() bool

HasScope reports whether the request names sub, tenant, or mission_s256.

func (UsageRequest) MarshalJSON

func (request UsageRequest) MarshalJSON() ([]byte, error)

type UsageResponse

type UsageResponse struct {
	AsOf        int64
	Audience    string
	Unit        Unit
	Subject     string
	Tenant      string
	MissionS256 string
	Usage       *UsageCalendar
	JKTs        map[string]int64
	JKTsPresent bool
}

UsageResponse is one usage-endpoint success body.

func ParseUsageResponse

func ParseUsageResponse(data []byte) (UsageResponse, error)

ParseUsageResponse accepts one strict usage success body.

func PostUsage

func PostUsage(
	ctx context.Context,
	endpoint string,
	key jose.SigningKey,
	caller string,
	discoveryDocument string,
	clock aauth.Clock,
	request UsageRequest,
	client *http.Client,
) (UsageResponse, error)

PostUsage sends one signed usage query and parses the success body. It does not check a response signature; PostUsageChecked does. A nil client refuses redirects.

type UsageResult

type UsageResult struct {
	Response  UsageResponse
	Signed    bool
	ExactBody []byte
	Header    http.Header
}

UsageResult is a checked usage answer. Signed reports a verified resource signature. ExactBody and Header are the bytes and fields as received, so a caller can retain a signed statement as evidence.

func PostUsageChecked

func PostUsageChecked(
	ctx context.Context,
	endpoint string,
	key jose.SigningKey,
	caller string,
	discoveryDocument string,
	clock aauth.Clock,
	request UsageRequest,
	check UsageSignatureCheck,
) (UsageResult, error)

PostUsageChecked sends one signed usage query, as PostUsage does, and verifies the response signature per check before parsing the body.

type UsageSignatureCheck

type UsageSignatureCheck struct {
	Resource         string
	KeyResolver      signaturekey.KeyResolver
	RequireSignature bool
	Client           *http.Client
}

UsageSignatureCheck tells PostUsageChecked how to treat the resource's response signature. Resource is the resource identifier whose usage_endpoint is called, and KeyResolver resolves its jwks_uri keys. Signing is RECOMMENDED rather than REQUIRED, so an unsigned response is read and reported as unsigned unless RequireSignature is set. A response that carries a signature which does not verify is always refused. Client defaults to one that refuses redirects.

type Value

type Value struct {
	// contains filtered or unexported fields
}

Value is one non-negative Budget amount in a resource-selected unit.

func NewValue

func NewValue(amount int64, unit Unit) (Value, error)

NewValue validates a Budget amount and denomination.

func ParseValueJSON

func ParseValueJSON(data []byte) (Value, error)

ParseValueJSON parses exactly one strict Budget object.

func VerifyAuthToken

func VerifyAuthToken(
	ctx context.Context,
	compact string,
	resolver signaturekey.KeyResolver,
	clock aauth.Clock,
) (aauth.AuthTokenClaims, Value, error)

VerifyAuthToken verifies Core trust and consumes the complete Budget companion claim set.

func (Value) Amount

func (value Value) Amount() int64

Amount returns the integer Budget amount in Unit().Decimals() scale.

func (Value) MarshalJSON

func (value Value) MarshalJSON() ([]byte, error)

MarshalJSON emits the exact Budget object.

func (Value) Unit

func (value Value) Unit() Unit

Unit returns the Budget denomination and scale.

func (*Value) UnmarshalJSON

func (value *Value) UnmarshalJSON(data []byte) error

UnmarshalJSON accepts only the exact Budget object.

Jump to

Keyboard shortcuts

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