# CLAUDE.md — graphql-router

This file provides guidance for AI assistants working in the graphql-router repository.

## Project Overview

**graphql-router** is the Apollo Federation gateway for the Orchard Insights platform, built with Apollo Router (Rust). It composes 17 federated GraphQL subgraphs into a single supergraph endpoint, handling query routing, authentication enforcement, and telemetry. All frontend GraphQL queries pass through this router.

## Essential Commands

```bash
# Development
make dev                    # Run with hot-reload (requires config-local.yaml + supergraph.graphql)
make run                    # Alias for dev

# Build
make build                  # cargo build
make install                # cargo install --locked --path .

# Testing
make test                   # cargo test
make lint-test              # cargo clippy + cargo test
make ci-lint-test           # Docker-based linting and testing (CI)
make test-docker            # Docker-based test execution

# Linting & Formatting
make clippy                 # cargo clippy (warnings as errors)
make lint                   # Alias for clippy
make fmt                    # cargo fmt (rustfmt)
make check                  # cargo check (fast compile check)

# Supergraph
make supergraph             # Recompose federation supergraph from all subgraphs

# Cleanup
make clean                  # cargo clean
```

## Setup

1. Install Rust 1.94 (pinned in `rust-toolchain.toml`)
2. Install Apollo Rover CLI: `curl -sSL https://rover.apollo.dev/nix/latest | sh`
3. Create `config-local.yaml` (copy from `config-qa.yaml` and adjust URLs)
4. Run `make supergraph` to generate `supergraph.graphql`
5. Run `make dev` to start with hot-reload

## Architecture

### Tech Stack

| Layer | Technology |
|-------|-----------|
| Language | Rust 1.94 (pinned via rust-toolchain.toml) |
| Router Framework | Apollo Router 2.12.1 |
| Federation | Apollo Federation 2.0.3 |
| Async Runtime | Tokio 1.47 (full features) |
| HTTP Middleware | Tower 0.5 (full features) |
| Serialization | serde + serde_json |
| Logging | tracing 0.1 |
| Error Handling | anyhow 1.0 |
| Schema Generation | schemars 1.2 |

### Project Structure

```
src/
├── main.rs                          # Entry point (minimal — registers plugins)
└── plugins/                         # Custom Apollo Router plugins
    ├── mod.rs                       # Plugin module registry
    ├── require_apollo_client_name.rs # Enforce client name header
    └── auth_enforcement/            # Multi-layered auth validation
        ├── mod.rs                   # Plugin entry + registration
        ├── configuration.rs         # Rule configuration types
        ├── auth_result.rs           # Ok/Warning/Block result enum
        ├── check_auth.rs            # Main auth checking logic
        ├── apollo_client_info.rs    # Client header extraction
        └── token/                   # Token parsers
            ├── bearer/              # Bearer JWT token parsing
            │   ├── mod.rs
            │   └── header.rs
            └── hmac/                # HMAC signature validation
                ├── mod.rs
                ├── header.rs
                ├── check.rs
                └── configuration.rs

scripts/
├── generate-supergraph.sh   # Introspect all subgraphs + compose supergraph
├── dev.sh                   # Development runner
└── run.sh                   # Production runner (ENV-based config selection)

config-qa.yaml               # QA environment config
config-uat.yaml              # UAT environment config
config-prod.yaml             # Production environment config
```

### Federation Subgraphs (17)

```
abacus, account, analytics, audience, content-review, collaborator,
distribution, knowledge, knowledge-search, neighbouring-rights,
participant, product, publishing, sr-delivery, tax-payment, user
```

Subgraph URLs are defined in environment-specific YAML configs. The supergraph is composed via `rover supergraph compose`.

## Custom Plugins

### 1. Require Apollo Client Name

**Registration**: `theorchard.require_apollo_client_name`

Enforces the `Apollographql-Client-Name` header on all requests (required for Apollo Studio field usage tracking). Returns 400 if missing.

**Configuration**:
```yaml
theorchard.require_apollo_client_name:
  enabled: true|false
```

### 2. Auth Enforcement

**Registration**: `pde.auth_enforcement`

Multi-layered authorization validation with configurable enforcement levels (Ok/Warning/Block).

**Supported token types**:
- **Bearer**: `Bearer <jwt-token>` — parsed but not fully validated (JWT validation TODO)
- **HMAC**: `sender/recipient:sha1hash` — validates recipient matches "graphql-router"

**Configuration**:
```yaml
pde.auth_enforcement:
  enabled: true|false
  rules:
    malformed_auth: Ok|Warning|Block
    missing_auth: Ok|Warning|Block
    multiple_auth: Ok|Warning|Block
    unknown_auth: Ok|Warning|Block
    hmac:
      hmac_use: Ok|Warning|Block
      recipient_mismatch: Ok|Warning|Block
```

**Result priority**: `Ok < Warning < Block` — `take_most_blocking()` combines multiple checks.

## Adding a New Subgraph

1. Service must expose a valid Apollo Federation schema
2. Add subgraph entry to `scripts/generate-supergraph.sh` (name + URL)
3. Run `make supergraph` to recompose
4. Add subgraph URL to all config files (`config-qa.yaml`, `config-uat.yaml`, `config-prod.yaml`)
5. Test locally with `make dev`

## Router Configuration

Key settings in environment configs:

```yaml
supergraph:
  listen: "0.0.0.0:4000"
  path: /graphql
  query_planning:
    cache:
      in_memory:
        limit: 1024

headers:
  all:
    request:
      - propagate: matching ".*"
      - remove: matching "^x-datadog-.*$"

traffic_shaping:
  router: { timeout: 65s }
  all: { timeout: 65s }

telemetry:
  exporters:
    tracing:
      otlp:
        enabled: true
        protocol: http
```

## Environment Variables

| Variable | Purpose |
|----------|---------|
| `Environment` | `qa` / `uat` / `prod` (selects config file) |
| `PORT` | Server port (default 4000) |
| `APOLLO_ROUTER_LOG` | Log level |
| Subgraph URL overrides | Per-subgraph URL environment variables |

## Testing

- **Unit tests**: Embedded in Rust modules via `#[cfg(test)]` blocks
- **Mock implementations**: `MockHMACChecker` for testing auth logic
- **Trait-based testing**: `HMACChecker` trait allows injection of test doubles
- **CI**: `make ci-lint-test` runs clippy + tests in Docker

## Docker

Multi-stage build:
- `base` — Debian 12, installs protobuf, creates non-root user
- `build` — Installs Rust, compiles release binary
- `dev` — Binary + Rover CLI + supergraph generation
- `test` — Clippy + cargo test (CI)
- `deploy` — Binary + environment configs + run.sh

## CI/CD (Jenkins)

1. Compliance checks
2. Unit tests + Clippy (via `make ci-lint-test`)
3. SAST security scanning
4. Sonar scan (master only)
5. Docker build + ECR push
6. Deploy to QA → UAT → Prod (conditional)
7. Trivy image scanning
8. Slack notification to `#graphql` channel
