tokenauth

package
v0.1.66 Latest Latest
Warning

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

Go to latest
Published: Jul 24, 2026 License: Apache-2.0 Imports: 13 Imported by: 0

Documentation

Overview

Package tokenauth contains small, cgo-free authorization data structures for token minting.

It is intentionally not a product policy engine. Product runtimes provide verified gate evidence, runtime measurement evidence, and optional budget storage. This package compiles a simple JSON policy and turns a mint request into an authorization decision that token services can consume.

Budget semantics: AuthorizeMint enforces the policy's budget rule only when the caller supplies a BudgetStore — a nil store means "budget enforcement happens elsewhere" and the budget_available check passes unconditionally. Deployments that want in-process enforcement use MemoryBudgetStore (single process) or implement BudgetStore over shared storage; any store error denies issuance (fail-closed).

Index

Constants

View Source
const (
	ModeDevelopment = "development"
	ModeProduction  = "production"

	AssuranceVerified = "verified"
)
View Source
const (
	// BucketSourceClaim pins bucket_id to a verified gate claim
	// (bucket_claim names which one). This is the default whenever
	// bucket_claim is set.
	BucketSourceClaim = "claim"
	// BucketSourceCaller declares that the service calling AuthorizeMint
	// derives and vouches for bucket_id itself (e.g. a salted source hash).
	// Production policies must opt in explicitly: a bucket key the far end
	// of the request gets to choose turns the budget into decoration.
	BucketSourceCaller = "caller"
)

Bucket provenance: who is trusted to name the budget bucket for a gate.

View Source
const AuthorizationVersion = uint32(1)

AuthorizationVersion is the wire version; bump on breaking changes.

View Source
const DefaultAuthorizationTTLSecs = uint64(60)

DefaultAuthorizationTTLSecs is the authorization lifetime when the attester does not override.

Variables

View Source
var ErrBudgetExceeded = errors.New("issuance budget exceeded for this bucket in the current window")

ErrBudgetExceeded is returned by Reserve when granting the request would exceed the budget limit for the current window.

Functions

func VerifyPolicySidecar added in v0.1.7

func VerifyPolicySidecar(policyJSON []byte, sidecar string, trustedPubs [][32]byte) error

VerifyPolicySidecar checks the sidecar signature over the exact policy bytes against any of the trusted operator keys. An empty trusted set means sidecar verification is not configured and always passes, matching the reference semantics.

Types

type AttesterSigner added in v0.1.7

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

AttesterSigner holds the attester's FAEST-128f key. The seed-to-key derivation is Go-specific (SHAKE256, like transparency.LogSigner); published keys and signatures are wire-compatible with the reference.

func NewAttesterSigner added in v0.1.7

func NewAttesterSigner(seed []byte) (*AttesterSigner, error)

NewAttesterSigner derives the attester key pair from a 32-byte seed.

func (*AttesterSigner) Public added in v0.1.7

func (s *AttesterSigner) Public() [32]byte

Public returns the 32-byte attester verification key.

func (*AttesterSigner) Sign added in v0.1.7

func (s *AttesterSigner) Sign(auth *IssuanceAuthorization, rho []byte) error

Sign fills auth.Sig (and the encoded JSON fields) over the canonical bytes. rho is the FAEST signer randomness (nil selects deterministic).

type BudgetRule

type BudgetRule struct {
	Limit         int `json:"limit"`
	WindowSeconds int `json:"window_seconds"`
}

type BudgetStore

type BudgetStore interface {
	Reserve(key string, amount int, limit int, window time.Duration, now time.Time) error
}

type Check

type Check struct {
	Name   string `json:"name"`
	Pass   bool   `json:"pass"`
	Detail string `json:"detail,omitempty"`
}

type Defaults

type Defaults struct {
	AllowSoftwareWitness bool `json:"allow_software_witness"`
	MaxBatch             int  `json:"max_batch"`
	AuthorizationTTL     int  `json:"authorization_ttl_seconds"`
}

type Eligibility

type Eligibility struct {
	GateKind  GateKind          `json:"gate_kind"`
	BucketID  string            `json:"bucket_id"`
	Assurance string            `json:"assurance"`
	Claims    map[string]string `json:"claims,omitempty"`
}

type GateKind added in v0.1.3

type GateKind string
const (
	GateTEE   GateKind = "tee"
	GateEmail GateKind = "email"
)

type GateRule added in v0.1.3

type GateRule struct {
	Enabled     bool   `json:"enabled"`
	BucketClaim string `json:"bucket_claim,omitempty"`
	// BucketSource states where bucket_id comes from: "claim" (must match
	// the verified claim named by bucket_claim) or "caller" (the calling
	// service derives it). Production compilation fails if a gate used by
	// an enabled token family declares neither.
	BucketSource string   `json:"bucket_source,omitempty"`
	AddressClaim string   `json:"address_claim,omitempty"`
	AllowedHosts []string `json:"allowed_hosts,omitempty"`
}

type IssuanceAuthorization added in v0.1.7

type IssuanceAuthorization struct {
	Version     uint32 `json:"version"`
	BindingHex  string `json:"binding"`
	RateLimitID []byte `json:"-"`
	PolicyLabel string `json:"policy_label"`
	MaxBatch    uint32 `json:"max_batch"`
	Exp         uint64 `json:"exp"`
	Iat         uint64 `json:"iat"`
	Sig         []byte `json:"-"`

	RateLimitIDB64 string `json:"rate_limit_id"`
	SigB64         string `json:"sig"`
}

IssuanceAuthorization is the signed payload authorizing one blind-sign batch. The issuer learns only RateLimitID (a keyed hash), never the raw measurement. JSON field encodings match the reference (hex binding, standard-base64 rate_limit_id and sig).

func (*IssuanceAuthorization) Normalize added in v0.1.7

func (a *IssuanceAuthorization) Normalize() error

Normalize fills the raw fields from their encoded JSON forms (call after unmarshalling) and vice versa (call before marshalling).

func (*IssuanceAuthorization) SignedBytes added in v0.1.7

func (a *IssuanceAuthorization) SignedBytes() ([]byte, error)

SignedBytes is the canonical byte string the attester signs (everything except sig), byte-identical to the reference layout.

func (*IssuanceAuthorization) Verify added in v0.1.7

func (a *IssuanceAuthorization) Verify(attesterPub [32]byte, now uint64) error

Verify checks the wire version, batch bound, expiry, and the attester's FAEST-128f signature.

type MeasurementRule

type MeasurementRule struct {
	ValueX string   `json:"value_x"`
	Allow  []string `json:"allow"`
}

type MemoryBudgetStore

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

MemoryBudgetStore is the reference BudgetStore: an in-memory, window-bucketed counter transpiled from the eat-pass InMemoryRateLimiter (core/src/ratelimit.rs). It is process-local — a multi-replica issuer must back the interface with a shared store instead — and it exists so the budget path has a working, tested implementation and so demos and single-process products need not write one.

Failure semantics match the reference: any Reserve error means the caller must deny issuance (AuthorizeMint fails the budget_available check), so a shared-store implementation that cannot reach its backend must return an error, never assume quota is available.

func NewMemoryBudgetStore

func NewMemoryBudgetStore() *MemoryBudgetStore

NewMemoryBudgetStore returns an empty in-memory budget store.

func (*MemoryBudgetStore) Prune

func (m *MemoryBudgetStore) Prune(now time.Time)

Prune drops counters for windows that ended before now (housekeeping, mirrors the reference's prune_before).

func (*MemoryBudgetStore) Reserve

func (m *MemoryBudgetStore) Reserve(key string, amount, limit int, window time.Duration, now time.Time) error

Reserve consumes amount permits for key in the window containing now. Windows are epoch-aligned (now / window), matching the reference's epoch bucketing; a non-positive window degenerates to one second.

type MintConstraints

type MintConstraints struct {
	TokenFamily TokenFamily `json:"token_family"`
	Count       int         `json:"count"`
	KeyVersion  uint32      `json:"key_version"`
	BindingB64  string      `json:"binding_b64"`
	BudgetKey   string      `json:"budget_key"`
	Origin      string      `json:"origin,omitempty"`
	Address     string      `json:"address,omitempty"`
	ExpiresAt   int64       `json:"expires_at"`
}

type MintDecision

type MintDecision struct {
	Allow       bool            `json:"allow"`
	Reason      string          `json:"reason"`
	Checks      []Check         `json:"checks"`
	Constraints MintConstraints `json:"constraints,omitempty"`
}

type MintRequest

type MintRequest struct {
	Subject     Subject       `json:"subject"`
	Eligibility []Eligibility `json:"eligibility"`
	TokenFamily TokenFamily   `json:"token_family"`
	Count       int           `json:"count"`
	KeyVersion  uint32        `json:"key_version"`
	Origin      string        `json:"origin,omitempty"`
	Address     string        `json:"address,omitempty"`
	Binding     []byte        `json:"-"`
}

type Policy

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

func Compile

func Compile(src Source) (*Policy, error)

func CompileJSON

func CompileJSON(raw []byte) (*Policy, error)

func (*Policy) AuthorizeMint

func (p *Policy) AuthorizeMint(req MintRequest, budgets BudgetStore, now time.Time) MintDecision

func (*Policy) Mode

func (p *Policy) Mode() string

type PolicySigner added in v0.1.7

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

PolicySigner holds an operator's FAEST-128f policy-signing key (Go-specific SHAKE256 seed derivation; wire-compatible signatures).

func NewPolicySigner added in v0.1.7

func NewPolicySigner(seed []byte) (*PolicySigner, error)

NewPolicySigner derives the operator key pair from a 32-byte seed.

func (*PolicySigner) Public added in v0.1.7

func (s *PolicySigner) Public() [32]byte

Public returns the 32-byte verification key operators publish.

func (*PolicySigner) SignPolicy added in v0.1.7

func (s *PolicySigner) SignPolicy(policyJSON, rho []byte) (string, error)

SignPolicy checks that policyJSON compiles, then returns the sidecar content: a standard-base64 FAEST-128f signature over the exact bytes. rho is the FAEST signer randomness (nil selects deterministic).

type Source

type Source struct {
	Version       int                   `json:"version"`
	Mode          string                `json:"mode"`
	Defaults      Defaults              `json:"defaults"`
	TokenFamilies map[string]TokenRule  `json:"token_families"`
	Gates         map[string]GateRule   `json:"gates"`
	Measurements  []MeasurementRule     `json:"measurements,omitempty"`
	Budgets       map[string]BudgetRule `json:"budgets"`
}

type Subject

type Subject struct {
	ValueX   string            `json:"value_x,omitempty"`
	Platform string            `json:"platform,omitempty"`
	Runtime  string            `json:"runtime,omitempty"`
	Claims   map[string]string `json:"claims,omitempty"`
}

type TokenFamily

type TokenFamily string
const (
	TokenBurn            TokenFamily = "burn"
	TokenPrivateIdentity TokenFamily = "private_identity"
	TokenPolicyEmail     TokenFamily = "policy_email"
)

type TokenRule

type TokenRule struct {
	Enabled              bool     `json:"enabled"`
	AllowedGates         []string `json:"allowed_gates"`
	AllowedOrigins       []string `json:"allowed_origins,omitempty"`
	BudgetGroup          string   `json:"budget_group"`
	MaxBatch             int      `json:"max_batch,omitempty"`
	RequiresAddressClaim bool     `json:"requires_address_claim,omitempty"`
	RequiresAttestation  bool     `json:"requires_attestation,omitempty"`
	RequiresOrigin       bool     `json:"requires_origin,omitempty"`
}

Jump to

Keyboard shortcuts

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