Repository navigation
This is the first release since v0.5.0 (March). It adds metered pricing, so one Lightning payment can buy a bundle of tokens that each request then draws down by actual usage. It adds Wavelength-backed invoices, so a seller can run aperture without an lnd node. It also brings the MPP (Payment HTTP Authentication Scheme) implementation up to the spec and includes a large authorization hardening pass. Several of the hardening changes refuse input that older versions accepted, so read Upgrading before rolling this out.
Highlights
Metered pricing
Aperture can now consult a price server at four points in a request's life: GetPrice quotes a bundle, ChallengeMinted books the bundle against the new credential, AuthorizeRequest admits a request and reserves an estimate, and ReportUsage debits what the upstream actually reported. When a request would overdraw the bundle, aperture mints a fresh 402 for the next one. It works with L402 tokens and with MPP charge and session credentials, and it carries streamed responses (the write deadline rolls forward while a stream flows, and an abandoned stream settles at the reservation estimate).
The release includes meterd, a reference price server driven by a JSON file of rates, and the pricesrpc interface for writing your own. Metering is opt-in per service (metered: true under the service's pricer). See docs/metering.md.
lightmeter is a production price server built on this interface for selling LLM inference by the token.
Wavelength-backed invoices
Invoices can be minted from a Wavelength wallet through the wavelengthgateway setting instead of lnd, so a seller needs no node, no channels and no inbound liquidity of their own. docs/wavelength.md is a tutorial for selling an API this way.
MPP and one challenge for both schemes
A service with auth: l402+mpp answers an unpaid request with a single 402 that carries both an L402 and a Payment challenge, and accepts either. This release lands the wire-format and session-handling conformance work, charge credentials that can be spent at most once, session top-ups that are credited at most once per payment, receipts dispatched by credential intent, and Payment challenges bound to the resource they were issued for. MPP charges and sessions are still opt-in (enablempp, enablesessions).
Authorization hardening
- Service names,
authvalues and request paths are validated, and paths are canonicalized before authorization (details under Upgrading). - Unverified L402 macaroons are removed from authenticated requests, gRPC metadata headers are handled strictly, and anonymous forwarding is only done after auth validation.
- Dynamic tokens are validated on public paths and keep their service restrictions (timeout, capabilities, constraints).
- Rate limits apply to zero-price requests, public requests are limited by verified identity, and multi-rule rate limit decisions are atomic with refunds for denied reservations.
- Freebie quota is checked and consumed atomically, and admin service mutations are serialized.
- A
Payment-Receiptis only issued for a credential that actually authenticated the request: the challenge must be one this server minted for the resource and the preimage must match its payment hash (#315). Previously a request that authenticated through L402 could carry a fabricated Payment credential and be stamped with a success receipt. - The pricer sees at most the first 64 KiB of the request body, and aperture no longer buffers the whole upload in memory to get it; the rest streams to the backend (#316). On a metered service,
modelmust therefore appear in the first 64 KiB of the body. - The TLS listeners require TLS 1.2 or newer (#317); the autocert and self-signed paths previously allowed TLS 1.0.
Smaller changes
- MPTCP listeners are disabled by default.
- The verified L402 ID is logged with the client IP.
- CORS headers are set rather than appended,
Content-Typeis allowed, and list-valued fields are merged. - Session settings in the config file are no longer overridden by flag defaults.
- The millisatoshi conversion for invoices rounds up rather than down.
Upgrading
The Upgrading section of the README lists every change that can break an existing deployment: resource-bound Payment credentials (outstanding Payment challenges are refused after the upgrade), stricter service names and auth values (startup fails on a bad one, including one stored in the database), request path validation, and tokens minted by older versions that may need to be revoked. Work through it before upgrading.
In addition:
- Database migrations. Two new migrations (
000008_mpp_session_credits,000009_mpp_consumed_charges) run automatically at startup. Back up the SQLite file or take apg_dumpfirst; each migration has a down script, but a backup is the supported way back. - MPP needs SQL storage.
enablemppis refused at startup with the etcd backend. Usesqliteorpostgres. - Go 1.26. Building from source needs Go 1.26.
- Images. The
lightninglabs/aperture:v0.6.0image is published for linux/amd64 and linux/arm64. - Free endpoints. A static
priceof 0 means the default price of 1 sat, not free (this is unchanged from earlier versions). To serve an endpoint for free, setauth: "off"on it.