Skip to main content

Breaking changes

Unreleased - Billing State wallet summary​

BillingState now requires the nullable wallet_balance field. User-scoped views return available_balance and outstanding_balance; account-scoped views return null. There is no legacy response shape, opt-in expansion, parallel v2 endpoint, or fallback Wallet request.

TypeScript and Python integrations must upgrade to SDK 0.3.0 together with the service deployment. Python generated models now accept and preserve unknown fields instead of rejecting additive contract changes. Known fields remain validated, and the server remains responsible for enforcing request contracts.

Required action: regenerate or upgrade clients, update Billing State fixtures, read the compact balance from wallet_balance, and handle account scope as an explicit null. Continue calling the full Wallet endpoint only when grant or conversion diagnostics are required.

Unreleased - brand-neutral technical contracts​

This release keeps the Vluna name at distribution, SDK, and integration boundaries while removing it from domain and protocol contracts. Package names, service domains, VLUNA_* environment variables, the vlunactl binary, and the vluna.* MCP tool namespace are unchanged. There are no legacy aliases or dual reads for the renamed identifiers below.

Browser return parameters​

  • vluna_checkout_id -> billing_checkout_id
  • vluna_checkout_result -> billing_checkout_result
  • vluna_subscription_id -> billing_subscription_id
  • vluna_subscription_management_result -> billing_subscription_management_result

Applications must update return URL handling atomically with the service deploy. Checkout and subscription-management URLs signed by the previous build are no longer valid because their signing domains changed.

Payment-provider metadata​

Provider-owned correlation data now uses billing-domain names:

  • vluna_realm_id -> billing_realm_id
  • vluna_catalog_product_id -> billing_catalog_product_id
  • vluna_catalog_price_id -> billing_catalog_price_id
  • vluna_checkout_id -> billing_checkout_id
  • vluna_context -> billing_checkout_context
  • vluna_operation_id -> billing_operation_id
  • vluna_change_policy -> billing_change_policy
  • vluna_anchor_policy -> billing_anchor_policy
  • vluna_scheduled_plan_change -> billing_scheduled_plan_change
  • vluna_keep_current_anchor -> billing_keep_current_anchor
  • vluna_billing_account_id -> billing_account_id
  • vluna_principal_id -> principal_id
  • vluna_billing_invoice_id -> billing_invoice_id
  • vluna_invoice_number -> invoice_number
  • vluna_billing_invoice_line_id -> billing_invoice_line_id
  • vluna_billing_invoice_adjustment_id -> billing_invoice_adjustment_id

Existing Stripe or Paddle objects carrying the old keys are not discovered by the new build. Reset development provider data, or migrate provider metadata before deployment; otherwise catalog bootstrap can create parallel objects and provider-operation replay detection can miss earlier mutations.

API schemas, Cloud identifiers, and SDK boundaries​

  • Contract pricing terms now require schema=billing/contract_pricing:v2. Existing development terms must be replaced.
  • Cloud catalog bootstrap identifiers changed from vluna_cloud_* plan and bundle keys to cloud_*, from vluna-cloud-plan to cloud-plan, from vluna.gated_events to platform.gated_events, and from source=vluna_pricing_page to source=pricing_page.
  • The Cloud pricing seed file is now 0002_seed_cloud_pricing.yaml instead of 0002_seed_vluna_cloud_pricing.yaml.

SDK package and integration identities remain branded and are not part of this technical-contract rename:

  • TypeScript retains VlunaAIServiceClient, VlunaAIBearerClient, VlunaAIConfig, and VlunaAIError.
  • Python retains VlunaAIConfig and VlunaAIError; its ServiceClient and BearerClient class names remain unchanged.
  • Adapter templates retain branded config, plugin, logger, context, and sentinel identifiers.
  • The Web console keeps the vluna.dev.s2s_credential local-storage namespace.

Regenerate clients from the current OpenAPI documents. Existing Cloud bootstrap data must also be reset or migrated before applying the renamed seed identifiers.

The first-party Web console now consumes the renamed callback parameters while continuing to use the branded SDK symbols.

Runtime identifiers​

  • VLUNA_PLANE remains the configuration variable, but its OSS/Enterprise default value is now runtime instead of vluna.
  • Migration session settings are now app.runtime_schema, app.runtime_password, and app.runtime_role.
  • Platform tokens with legacy token_use=vluna are rejected. Reissue legacy tokens; platform, plt, and apt remain the recognized token-use values.
  • The legacy apt token derivation salt changed to the neutral apt-token domain, so previously issued apt tokens must also be reissued.
  • Non-production DAT and MCP fallback signing seeds changed; restart local clients and issue new development session tokens after upgrading.

Unreleased - exact rational rating and caller-owned runtime references​

This release is intentionally destructive. It does not accept legacy Gate or meter-price fields, and it does not migrate legacy pricing, residual, lease, or Budget-reference data. Rebuild affected development data and regenerate clients from the current OpenAPI documents.

Meter prices and rating​

  • Meter revenue is now the exact rate unit_price_xusd / unit_quantity_minor; provider cost is unit_cost_xusd / cost_unit_quantity_minor. Both complete pairs are required.
  • unit_quantity_minor and cost_unit_quantity_minor are quote/reference quantities and mathematical divisors, not billing blocks.
  • Per-line rounding modes and legacy residual-bucket behavior were removed. Rating uses integer_rational_floor_v1 with remainder state separated by billing user, meter, pricing kind, and resolved rate identity.
  • Meter-price effective_at is server managed. A no-op round trip preserves it; a material rate change advances it. Clients cannot choose it.
  • Gate commit lines are discriminated by rating_status. Ops rated records use rating_algorithm/cost_rating_algorithm plus nullable rate fields. Both surfaces expose explicit missing snapshots instead of synthetic zero rates.
  • client_unit_price_xusd is no longer accepted on Gate meter lines. Use client_pricing_etag when sending an advisory client expectation.
  • CurrencyAmounts guarantees only xusd as a named property. Other currency codes, including usd, are dynamic keys.

Required action: update meter-price writes with both exact rate pairs, remove rounding/block assumptions, narrow Gate lines by rating_status, inspect Ops rating algorithms before reading rate fields, and regenerate SDK/OpenAPI types.

Contract pricing v2​

kind=pricing contract terms must use schema=billing/contract_pricing:v2 and exact rational fixed, multiplier, or delta adjustments. The embedded meter_code must equal term_key; arbitrary legacy pricing JSON is rejected with 422.

Required action: replace old contract pricing values instead of migrating them.

Gate leases​

  • Public Gate authorization credentials and IDs were replaced by the single opaque lease reference.
  • Authorize accepts optional caller-owned lease; when omitted, it generates the reference returned to commit.
  • Gate authorization has no separate cleanup operation. Authorize reserves no funds, quota, or other consumable resource, so failed work needs no compensation request.
  • Internal lease UUIDs remain an implementation detail.

Required action: pass lease from authorize to commit, or choose a unique one-time operation reference yourself. If work fails or produces no usage, finish without another Gate request; do not store public generated credentials.

Budget references​

  • Budget creation accepts optional caller-owned budget and returns both budget_id and budget.
  • Authorize and direct ingest select a Budget with budget; legacy Gate budget_id input is rejected.
  • Budget management endpoints and operational responses continue to use budget_id where an internal ID is appropriate.

Required action: choose and carry an external budget reference in runtime flows, or use the generated value returned by Budget creation. Do not rename management URL parameters.

Entitlement diagnostics and default assignment​

  • ENTITLEMENT.REQUIRED and ENTITLEMENT.DENIED error envelopes include the rejected resource in meta.
  • New and reactivated billing users must receive the realm's active default plan assignment in the provisioning transaction. A missing/inactive default plan fails provisioning with SERVER.CONFIG rather than leaving a partial user.