Skip to main content

Breaking changes

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.