0.2.0

A ground-up rewrite. 0.1.2's public API (Ussd.Machine, the old Ussd.Decision/Ussd.Menu functions, and the mix phx.gen.ussd.state generator) is gone - there is no compatibility shim, since 0.1.2's own generator produced code that didn't run. If you have a project on 0.1.2, treat this as a new dependency rather than an upgrade.

Fixed

  • The mix phx.gen.ussd.state generator produced a before_render/1 that didn't match what 0.1.2's Ussd.Machine (removed in this release) actually called (before_render/2) - every generated state crashed. The new generators (mix ussd.gen.*) produce code that matches the current engine.
  • 0.1.2's Ussd.Decision.between/3 (removed in this release) compared USSD input as strings ("10" <= "9" is true lexicographically), silently breaking range matching once a menu had 10+ options. The new Ussd.Decisions.Between and friends compare numerically when both sides look numeric.
  • Session state (Ussd.Record in 0.1.2) had no expiry at all and was only ever cleared when a flow explicitly returned a "prompt" action, so abandoned sessions accumulated in an ETS table forever. Ussd.Cache.ETS now expires entries on a real TTL, both lazily on read and via a periodic sweep, and the engine gives its own bookkeeping a default TTL (config :ussd, :session_ttl, default 300s) so this happens automatically.
  • Ussd.Application started its GenServer directly instead of under a Supervisor, so a crash there took the whole application down with no restart. It now starts under a real one-for-one supervisor.
  • The library depended on all of Phoenix ({:phoenix, "~> 1.6.6"}) just for one generator's inflection helpers. The generators now use Macro.camelize/1 and Macro.underscore/1 from Elixir's own standard library; Phoenix is no longer a dependency at all.

Added

Feature parity with speso/laravel-ussd v3, expressed idiomatically rather than transliterated:

  • Ussd.State DSL - transition/2, back/2, paginate/2, truncate/2, terminate/0 macros compiled into the module, replacing 0.1.2's untyped Ussd.Decision.* functions.
  • Ussd.Action - one-shot, no-render decision points that chain to the next state.
  • Ussd.Pagination - use Ussd.Pagination, per_page: n plus paginate/2 pages a long listing without hand-rolled bookkeeping.
  • Truncation - truncate/2 caps how much of a screen is returned per request, with a "more" continuation key.
  • Resumable sessions - Ussd.use_continuing_state/4 (:start / :continue / :confirm) lets a redial pick back up where a dropped call left off.
  • Ussd.Configurator - shared Ussd.use_*/2 setup across entry points.
  • Localization - Ussd.Menu.trans/4 and trans_line/4 via an optional Gettext backend.
  • Ussd.Record.set_encrypted/4 and get_encrypted/4 - AES-256-GCM at rest, keyed by config :ussd, :encryption_key.
  • Six gateway response formatters - Ussd.Responses.{AfricasTalking, Speso, Nalo, Nsano, Moolre, Arkesel}.
  • Ussd.ExceptionHandler - turns an unhandled exception into a message instead of a dead session.
  • mix ussd.graph, mix ussd.lint, mix ussd.simulate - Mermaid flow diagrams, static analysis for dead ends/broken transitions/duplicate matches, and an interactive terminal simulator.
  • mix ussd.gen.{state,action,response,decision,configurator,exception_handler} generators.
  • Ussd.Test - a fluent ExUnit helper for walking a flow screen by screen and asserting on the message, session record, and context.
  • :telemetry events - [:ussd, :state, :entered] and [:ussd, :session, :terminated].
  • Pluggable Ussd.Cache behaviour, so the session store can be swapped for Redis, :cachex, Mnesia, etc. in a multi-node deployment.

0.1.2 and earlier

Initial minimal proof of concept.