# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Overview

NginxDome is a set of three dynamic Nginx modules written in C that integrate DataDome's bot protection API into Nginx. The modules compile against the Nginx source tree and are loaded as `.so` files at runtime.

Current module version: `2.51.0` (defined as `MODULE_VERSION` in `ngx_http_data_dome_auth_module.c`).

## Local Development

**Requirement:** Export the DataDome server-side key before running:
```bash
export DATADOME_SERVER_SIDE_KEY=datadome_serverside_key
```

**Run with Docker Compose:**
```bash
docker-compose up
curl -v localhost:8182 -A BLOCKUA
```

**Build the Docker image directly (specify Nginx version):**
```bash
docker build . --build-arg NGINX_VERSION=1.26 --tag nginx-datadome
```

**Build modules manually** (requires Nginx to be installed; the script auto-detects the Nginx version and reuses its compile flags):
```bash
./.github/scripts/build.sh
```

There are no unit tests in this repository. End-to-end tests run in CI via Postman collections against a deployed CloudRun service.

## Versioning and Release

When bumping the version, two files must be kept in sync — the CI `validate_version` job enforces this:
1. `#define MODULE_VERSION "X.Y.Z"` in `ngx_http_data_dome_auth_module.c`
2. The top entry in `CHANGELOG.md`

Releasing is triggered by pushing a semver tag (e.g., `2.51.0`). The CD pipeline packages the source files into a `.tar.gz` archive (no compiled binaries), uploads it to GitHub Releases, and syncs it to S3 buckets (both preprod and prod).

PR titles must follow the Conventional Commits specification (enforced by `lint_pr.yml`).

## Architecture

### Three Nginx Modules

**`ngx_http_data_dome_auth_module.c`** — The request-gating module. It runs in Nginx's `NGX_HTTP_ACCESS_PHASE` and intercepts every incoming request:
1. Issues an internal Nginx subrequest to the DataDome API location (configured via `data_dome_auth`).
2. Parses the `X-DataDomeResponse` response header to decide whether to pass, block, redirect, or challenge the request.
3. Applies response headers from the API back to the client via `X-DataDome-headers` (response headers) and `X-DataDome-request-headers` (mutates request headers for upstream).
4. Supports a *learning mode* (`data_dome_auth learning`) that always passes requests while still calling the API.
5. Optionally restores the `Referer` header from a `dd_referrer` query parameter when `data_dome_auth_enable_referrer_restoration` is on.

Key directives: `data_dome_auth`, `data_dome_auth_set`, `data_dome_auth_uri_regex`, `data_dome_auth_uri_regex_exclusion`, `data_dome_auth_pass_internal_redirect`, `data_dome_auth_enable_referrer_restoration`.

Nginx variables exposed: `$data_dome_auth_is_uri_regex_matched`, `$data_dome_module_version`.

**`ngx_http_data_dome_shield_module.c`** — The payload-building module. It exposes a large set of `$data_dome_*` Nginx variables that extract, truncate, and URL-encode HTTP request fields. These variables are assembled into the POST body (`$data_dome_request_body`) that is sent to the DataDome Protection API.

The canonical list of API payload fields is defined in the static `ngx_http_data_dome_params[]` array (Key, UserAgent, IP, Port, ClientID, Host, Referer, Request, Protocol, HeadersList, SecFetch*, JA3, JA4, Signature*, etc.).

The module identifies the client either via the `datadome` cookie (default) or the `X-DataDome-ClientID` request header (session-by-header mode).

Key directives: `data_dome_shield_key`, `data_dome_shield_cookie`, `data_dome_shield_set_param`, `data_dome_shield_debug_params`.

**`ngx_http_data_dome_upstream_dynamic_servers_module.c`** — A DNS-resolving upstream module. Provides the `dd_server` directive (used inside an `upstream {}` block) that periodically re-resolves the DataDome API hostname so that IP changes are picked up without reloading Nginx.

### How the Modules Interact

The `nginx.conf.template` shows the wiring:
- All three `.so` modules are loaded at the top.
- An `upstream datadome` block uses `dd_server` to resolve `$DATADOME_ENDPOINT:443`.
- The server block enables `data_dome_auth @datadome` globally.
- A named location `@datadome` uses `data_dome_shield_key` and `proxy_body $data_dome_request_body` to POST to the DataDome API.

### Static File Exclusion

By default, the auth module skips requests whose URI matches a built-in regex covering common static asset extensions (images, fonts, CSS, JS, video, audio). This default exclusion can be overridden with `data_dome_auth_uri_regex_exclusion`.

### Build System

The `config` file is the Nginx module build descriptor. It registers all three modules and supports three linking modes: `DYNAMIC` (`.so` files), `ADDON` (built into Nginx), and static. PCRE is required for URI regex filtering.

The `deb.patch`, `deb-dynamic.patch`, and `nginx.spec.patch` files are patches for packaging Nginx with the DataDome module for Debian/Ubuntu and RPM-based distributions.

## Environment Variables (Docker Compose / Runtime)

| Variable | Default | Description |
|---|---|---|
| `DATADOME_SERVER_SIDE_KEY` | *(required)* | DataDome server-side API key |
| `DATADOME_ENDPOINT` | `api.datadome.co` | DataDome API hostname |
| `DATADOME_NGINX_PROXY_PASS` | `https://datadome/validate-request/` | Full proxy_pass URL for the API |
| `DATADOME_TIMEOUT` | `1000` | Connect/read timeout in milliseconds |
| `DATADOME_ENABLE_REFERRER_RESTORATION` | `off` | Enable `dd_referrer` query param handling |

At runtime, `envsubst` replaces these placeholders in `nginx.conf.template` before Nginx starts.

Setting the environment variable `DATADOME_NGX_LOG_ERR` changes the log level for missing/unexpected API responses from `WARN` to `ERR`.
