# HawkEx

HawkEx is an Elixir toolkit for SaaS billing infrastructure. It provides
Ecto schemas and service modules for plans, subscriptions, entitlements,
audit logging, CSV exports, and lightweight operational queries.
The library is designed to live inside a Phoenix application. Your app owns
the account schema, payment provider integration, authentication, and usage
tracking. HawkEx owns the durable billing records and the small APIs needed
to answer common questions such as "does this account have access?" and
"what is left on this plan?"
## Features
* Plan and subscription records with trial, active, past due, and canceled states.
* Entitlement checks for boolean and limit-based features.
* Optional PubSub events for subscription lifecycle changes.
* Audit log records for billing events and application-defined actions.
* Synchronous CSV exports and optional async exports through Oban.
* Pluggable CSV storage, with local disk and S3 adapters.
* Shared pagination helpers for dashboard-style views.
## Dashboard
You can use [hawk_ex_dashboard](https://github.com/Null-logic-0/hawk_ex_dashboard)
alongside HawkEx to add an admin-facing Phoenix dashboard. It provides a UI for
viewing and managing subscriptions, entitlements, audit logs, CSV exports, and
related operational data powered by this library.
## Installation
Add `hawk_ex` to your dependencies:
```elixir
def deps do
[
{:hawk_ex, "~> 0.1.0"}
]
end
```
Then copy the migrations:
```sh
mix hawk_ex.install
mix ecto.migrate
```
## Configuration
At minimum, configure the Ecto repo and the schema that represents the
billable account in your application:
```elixir
config :hawk_ex,
repo: MyApp.Repo,
account_schema: MyApp.Accounts.Organization
```
Optional integrations:
```elixir
config :hawk_ex,
pubsub: MyApp.PubSub,
oban: Oban,
csv_storage: {HawkEx.CSV.Storage.Local, path: "priv/exports"}
```
For S3-backed CSV exports:
```elixir
config :hawk_ex,
csv_storage: {HawkEx.CSV.Storage.S3,
bucket: "my-app-exports",
prefix: "exports/"}
```
## Entitlements
Use the top-level `HawkEx` module for the most common access checks:
```elixir
if HawkEx.allowed?(account, :export_csv) do
export_csv()
end
case HawkEx.remaining(account, :api_calls) do
:unlimited -> allow_request()
count when count > 0 -> allow_request()
_ -> deny_request()
end
```
`remaining/2` returns the limit configured on the account's current plan. It
does not count usage. Your application should store and subtract usage for
metered features.
## Billing
Subscriptions are managed through `HawkEx.Billing`:
```elixir
{:ok, subscription} = HawkEx.Billing.subscribe(account, :pro)
{:ok, canceled} = HawkEx.Billing.cancel(account)
{:ok, changed} = HawkEx.Billing.change_plan(account, :enterprise)
```
HawkEx keeps canceled subscriptions for history. New subscriptions create new
records, while `change_plan/2` updates the active subscription in place in the
current release.
## CSV Exports
Small exports can be generated synchronously:
```elixir
{:ok, csv, row_count} = HawkEx.CSV.export(account, :subscriptions)
```
Async exports require Oban to be installed and configured:
```elixir
{:ok, export} = HawkEx.CSV.export_async(account, :audit_logs)
```
Custom exports implement the `HawkEx.CSV.Formatter` behaviour.
## Audit Logs
Record application actions with:
```elixir
HawkEx.Audit.track(current_user, "settings.updated", organization)
```
When PubSub is configured, HawkEx also records its own subscription lifecycle
events through the audit listener.
## Documentation
Generate local documentation with:
```sh
mix docs
```
Published package documentation will be available on HexDocs after release.
## Contributing
Contributions are welcome. Please keep changes focused, include tests for new
or changed behavior, and run the checks before opening a pull request:
```sh
mix format
mix test
mix docs
```
For larger changes, open an issue or discussion first so the design can be
aligned before implementation.
## License
HawkEx is released under the MIT License. See [LICENSE](LICENSE) for details.