## pdp_sdk_metrics_demo

Live demo services that emit real `pp_auth.rollout.would_deny` metrics to Datadog
by running actual PDP auth checks through `MigrationAuthorizationBackend`.

[PP Auth Rollout - Would Deny Analysis dashboard](https://sonymusic-pde.datadoghq.com/dashboard/s6j-76w-52y?fromUser=true&refresh_mode=paused&from_ts=1779840259865&to_ts=1779841069865&live=false)

---

## Quick start

```bash
awsume dev
cp .env.example .env   # fill in DD keys + Auth0 creds
make up
make logs
```

### DD Creds

Either set the DD keys in `.env` or pdp-sdk will attempt to fetch them from SecretsManager. Only
the `dev` account allows reading the `DD_API` and `DD_APP` keys.

---

## Services

### `flask_demo_service` — Flask

Wires up `MigrationAuthorizationBackend` following the `ows-product-digital` pattern:
`flask_logger` + `flask_request` + `owsrequest.ows_client` getters.

| Method   | Path            | Auth action          |
|----------|-----------------|----------------------|
| `GET`    | `/health`       | —                    |
| `GET`    | `/catalog/<id>` | `read` / `catalog`   |
| `GET`    | `/catalog/`     | `list` / `catalog`   |
| `GET`    | `/content/<id>` | `read` / `content`   |
| `GET`    | `/release/<id>` | `read` / `release`   |
| `DELETE` | `/release/<id>` | `delete` / `release` |

---

### `fastapi_demo_service` — FastAPI

Wires up `MigrationAuthorizationBackend` following the `ows-product-staging` pattern:

- `CorrelationIdMiddleware` + `RequestContextMiddleware` from `owscontext`
- `CurrentRequestMiddleware` stores the Starlette `Request` in a `ContextVar` so the
  `extra_tags_getter` lambda reads the matched route template (not raw path) at call time
- Authorization backend initialised once in the `lifespan` context manager

| Method   | Path                 | Auth action               |
|----------|----------------------|---------------------------|
| `GET`    | `/health`            | —                         |
| `GET`    | `/bulk-session/`     | `list` / `bulk_session`   |
| `POST`   | `/bulk-session/`     | `create` / `bulk_session` |
| `GET`    | `/bulk-session/{id}` | `read` / `bulk_session`   |
| `PATCH`  | `/bulk-session/{id}` | `update` / `bulk_session` |
| `DELETE` | `/bulk-session/{id}` | `delete` / `bulk_session` |
| `GET`    | `/media/{id}`        | `read` / `media`          |
| `GET`    | `/track/{id}`        | `read` / `track`          |
| `DELETE` | `/track/{id}`        | `delete` / `track`        |

---

### `traffic_gen` — Traffic generator

Drives traffic to both services using plain `requests`. Fetches **one real Auth0 JWT at
startup** (password grant, same as `jwtauth.testing.utils.generate_bearer_jwt_token`),
then loops with a realistic token mix:

| Token variant | Share | Expected metric reason          |
|---------------|-------|---------------------------------|
| Real JWT      | 90%   | real PDP decision               |
| Fake token    | 5%    | `unauthenticated` / `pp_denied` |
| No header     | 5%    | `unauthenticated`               |

If Auth0 credentials are omitted it degrades gracefully — runs with fake/no-auth tokens only.

---

## Prerequisites

- Access to the private PyPI at `https://pypi.theorchard.io/pypi/`
  (for `python-pdp-sdk`, `owsclient`, `owsrequest`, `owslogger`, `owscontext`)

---

## Environment variables

| Variable                | Default                | Description                                      |
|-------------------------|------------------------|--------------------------------------------------|
| `DD_API_KEY`            | —                      | Datadog API key (required for metrics)           |
| `DD_ENV`                | `qa`                   | Environment used for SecretsManager lookup       |
| `FLASK_SERVICE_NAME`    | `flask-demo-service`   | Flask service name / `service_name` metric tag   |
| `FASTAPI_SERVICE_NAME`  | `fastapi-demo-service` | FastAPI service name / `service_name` metric tag |
| `ENVIRONMENT`           | `dev`                  | `environment` metric tag                         |
| `TENANT_UUID`           | (see `.env.example`)   | Tenant used for all demo auth checks             |
| `TENANT_TYPE`           | `account`              | Tenant type used for all demo auth checks        |
| `AUTH0_USERNAME`        | —                      | Auth0 test user                                  |
| `AUTH0_PASSWORD`        | —                      | Auth0 test user password                         |
| `AUTH0_CLIENT_ID`       | —                      | Auth0 application client ID                      |
| `AUTH0_CLIENT_SECRET`   | —                      | Auth0 application client secret                  |
| `LOOP_INTERVAL_SECONDS` | `2`                    | Seconds between traffic-gen request bursts       |
| `REQUESTS_PER_LOOP`     | `5`                    | Requests per burst                               |

---

## Makefile targets

```bash
make up            # build + start all three containers
make down          # stop + remove containers
make logs          # stream all container logs
make logs-flask    # Flask service logs only
make logs-fastapi  # FastAPI service logs only
make logs-traffic  # traffic-gen logs ([service] METHOD path [token=real|fake|none] → status)
```
