All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
[v0.1.1] - 2026-10-27
Added
- Spark DSL Compile-Time Verifiers:
VerifyCustomerRelationship: Validates at compile time that the relationship configured viacustomer_relationshipactually exists on the resource.VerifyCustomerIdAttribute: Validates at compile time that customcustomer_id_attributetypes are string-compatible (:stringor:ci_string).
Fixed
- Router and Igniter Option Consistency:
- Standardized
customer_resourceoption acrossAshBilling.Plug,AshBilling.WebhookSync,Mix.Tasks.AshBilling.Install, and all documentation. - Added transparent backwards-compatible normalization for
:resourceinAshBilling.PlugandAshBilling.WebhookSync.
- Standardized
- Test Resources and Multi-Version CI Stability:
- Pruned unsupported actions on
AshBilling.Test.WebhookEventto ensure clean compile-time validation underAsh.DataLayer.Etsacross Elixir 1.17 and 1.18. - Refactored live Stripe integration test suites to provision dynamic test customers on Stripe instead of relying on static accounts.
- Pruned unsupported actions on
[v0.1.0] - 2026-10-26
Initial release of ash_billing: Declarative billing, subscription, and payment extensions for the Ash Framework.
Added
- Spark DSL Extensions:
AshBilling.Resource: Configures customer resources (customer_id_attribute,provider).AshBilling.Subscription: Injects subscription attributes (provider_subscription_id,status,price_id,current_period_end,trial_ends_at,cancel_at_period_end) and calculations (active?,on_trial?).AshBilling.WebhookEvent: Database-backed resource extension for cluster-wide webhook deduplication.
- Stripe Provider:
AshBilling.create_customer/2: Generates Stripe customer records with metadata.AshBilling.create_checkout_session/2: Creates Stripe Checkout sessions with pre-filled customer email, metadata, and success/cancel URLs.AshBilling.create_portal_session/2: Generates Stripe Customer Billing Portal sessions with defensive configuration checks.AshBilling.cancel_subscription/2andAshBilling.resume_subscription/2: Subscription cancellation and period-end resumption.AshBilling.swap_plan/3: Plan upgrades and downgrades with automatic proration and multi-item resolution.AshBilling.update_quantity/3: Per-seat quantity scaling with automatic item resolution.
- Secure Webhook Plug:
AshBilling.Plug: Endpoint with constant-time HMAC-SHA256 signature verification and replay attack protection.- HTTP 500 retry protocol: Responds with status 500 on database synchronization failure to trigger Stripe automatic exponential retries.
- Multi-node deduplication strategies: in-memory ETS (
:memory) and database-backed Ash resource (:resource).
- Resilient Webhook Synchronization (
AshBilling.WebhookSync):- Polymorphic extraction for customer IDs and pricing objects (supporting both string IDs and expanded Stripe maps).
- Exception-safe UNIX timestamp conversions (
DateTime.from_unix/2). - Idempotent concurrency race resolution: automatic update fallback when duplicate creation arrives concurrently.
- Native Ash Policies:
AshBilling.Checks.Subscribed: Policy check that verifies if the actor has an active subscription or ongoing trial.AshBilling.Checks.HasPrice: Policy check restricting access to specified price tiers.
- Developer Diagnostics & Tooling:
AshBilling.check_configuration/1andAshBilling.verify_configuration!/1: Pre-flight diagnostics for API keys, secrets, and registered resources.- Automated installer task:
mix igniter.install ash_billing(Mix.Tasks.Igniter.Install.AshBilling). - Standard
:telemetryspans across checkout, billing portal, webhook ingestion, and database synchronization. - Built-in Spark cheat sheets and ExDoc documentation.
- Multi-version CI matrix across Elixir 1.17, 1.18 and Erlang/OTP 26, 27.
- Weekly Canary CI workflow testing against
ash-project/ash@mainandash-project/spark@main.