# `CfBouncer`
[🔗](https://github.com/egze/cf_bouncer/blob/main/lib/cf_bouncer.ex#L1)

Generates a Cloudflare WAF block rule from your Phoenix router, endpoint
sockets, and static paths, then syncs it via the Rulesets API.

## Configuration

    # config/config.exs
    config :cf_bouncer,
      router: MyAppWeb.Router,
      endpoint: MyAppWeb.Endpoint,
      static_module: MyAppWeb,
      rule_description: "[CfBouncer] Block non-allowlisted paths",
      extra_paths: ["/cf-fonts/"]

    # config/runtime.exs
    config :cf_bouncer,
      zone_id: System.get_env("CLOUDFLARE_ZONE_ID"),
      api_token: System.get_env("CLOUDFLARE_API_TOKEN")

## Usage

All public functions accept a keyword list of options instead of reading
application config directly, making this library usable without being a
supervised OTP app.

    opts = [
      router: MyAppWeb.Router,
      endpoint: MyAppWeb.Endpoint,
      static_module: MyAppWeb,
      extra_paths: ["/cf-fonts/"],
      zone_id: "your-zone-id",
      api_token: "your-api-token",
      rule_description: "[CfBouncer] Block non-allowlisted paths"
    ]

    CfBouncer.build_expression(opts)
    CfBouncer.sync(opts)

# `build_expression`

Builds the WAF expression string from configured routes, sockets, and static paths.

## Options

  * `:router` — Phoenix router module (required)
  * `:endpoint` — Phoenix endpoint module (required)
  * `:static_module` — module with `static_paths/0` (required)
  * `:extra_paths` — additional path prefixes to allow (default: `[]`)

# `sync`

Syncs the WAF rule to Cloudflare. Creates the rule if it doesn't exist,
updates it if the expression changed, or skips if already up to date.

Accepts all options from `build_expression/1` plus:

  * `:zone_id` — Cloudflare zone ID (required)
  * `:api_token` — Cloudflare API token (required)
  * `:rule_description` — description for the WAF rule (required)
  * `:force` — push even if unchanged (default: `false`)

Returns `:created`, `:updated`, or `:up_to_date`.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
