> ## Documentation Index
> Fetch the complete documentation index at: https://connect-docs.supertab.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Fastly

> Publish RSL license and deploy CAP enforcement on Fastly using VCL or Compute, with bot-event logging on Compute.

Supertab Connect integrates with Fastly for two purposes: serving your RSL license at `/license.xml` via your domain, and enforcing the Crawler Authentication Protocol (CAP) to protect content from unlicensed crawlers.

***

## Publishing RSL License

Your RSL license needs to be accessible at `https://yourdomain.com/license.xml`. Fastly proxies this path to the Supertab Connect origin, keeping the URL on your domain.

The configuration differs slightly between VCL and Compute services.

### VCL Service

Add a backend pointing to the Supertab Connect origin, attach it to a condition that matches the license URL, and add a VCL snippet that rewrites the short path to the full URN path.

#### Backend

Add a new host with the following configuration:

```
Name:                 supertab-connect-backend
Address:              api-connect.supertab.co
Port:                 443
TLS:                  enabled
SNI hostname:         api-connect.supertab.co
Certificate hostname: api-connect.supertab.co
Override host:        api-connect.supertab.co
```

#### Condition

Attach a request condition to `supertab-connect-backend`:

```vcl theme={null}
req.url ~ "^/merchants/systems/YOUR_WEBSITE_URN/license\.xml(\?|$)"
```

#### VCL Snippet

Add a `recv` snippet at priority 100:

```vcl theme={null}
if (req.url.path == "/license.xml") {
  set req.url = "/merchants/systems/YOUR_WEBSITE_URN/license.xml";
}
```

This rewrites the short URL before the condition runs, so the backend condition matches and the request is routed to `api-connect.supertab.co`.

Activate the new version once the backend, condition, and snippet are in place.

### Compute (Wasm) Service

For Compute services, add a backend named `supertab-connect-backend` pointing to `api-connect.supertab.co:443` with TLS enabled. The SDK handles URL rewriting and routing internally when `enableRSL: true` is set — no VCL condition or snippet is needed.

```javascript theme={null}
/// <reference types="@fastly/js-compute" />
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
import { SecretStore } from "fastly:secret-store";

const secrets = new SecretStore("supertab_config");
const merchantApiKey = await secrets.get("MERCHANT_API_KEY"); // from your Supertab Connect dashboard

addEventListener("fetch", (event) => {
  event.respondWith(
    SupertabConnect.fastlyHandleRequests(
      event.request,
      merchantApiKey,
      "supertab-connect-backend",
      {
        enableRSL: true,
        merchantSystemUrn: "YOUR_WEBSITE_URN",
      }
    )
  );
});
```

***

## CAP Enforcement

CAP validates the `Authorization: License <token>` header on crawler requests, verifying that the crawler holds a valid license before allowing access to protected content.

Depending on your existing infrastructure, choose one of two integration patterns.

| Approach                             | Description                                                                                                                             | Best for                                        |
| :----------------------------------- | :-------------------------------------------------------------------------------------------------------------------------------------- | :---------------------------------------------- |
| **Compute-native**                   | All traffic enters a Fastly Compute service; the SDK handles detection, validation, and origin routing.                                 | Greenfield projects or full Compute migrations. |
| **Service chaining (CDN → Compute)** | Your existing VCL service detects the `Authorization: License` header and chains licensed requests to a Compute service for validation. | Existing CDN services using VCL snippets.       |

### Approach 1: Compute-native

The `fastlyHandleRequests` method manages the full request lifecycle. Use a Fastly SecretStore for the API key.

```javascript theme={null}
/// <reference types="@fastly/js-compute" />
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
import { SecretStore } from "fastly:secret-store";

const secrets = new SecretStore("supertab_config");
const merchantApiKey = await secrets.get("MERCHANT_API_KEY");

addEventListener("fetch", (event) => {
  event.respondWith(
    SupertabConnect.fastlyHandleRequests(
      event.request,
      merchantApiKey,
      "origin_backend_name",
      {
        merchantSystemUrn: "YOUR_WEBSITE_URN",
        // Bot-event logging: emit one event per request to the "bot_events" endpoint
        // (see the Bot-Event Logging section below)
        analyticsEnabled: true,
        logEndpoint: "bot_events",
      }
    )
  );
});
```

Install the SDK:

```bash theme={null}
npm install @getsupertab/supertab-connect-sdk
```

#### Enforcement modes

```javascript theme={null}
import { EnforcementMode } from "@getsupertab/supertab-connect-sdk";

// DISABLED: no enforcement, signaling, or analytics — use during initial integration
SupertabConnect.fastlyHandleRequests(event.request, merchantApiKey, "origin_backend_name", {
  enforcement: EnforcementMode.DISABLED,
});

// SOFT (default): allow all traffic through but log events
SupertabConnect.fastlyHandleRequests(event.request, merchantApiKey, "origin_backend_name", {
  enforcement: EnforcementMode.SOFT,
});

// STRICT: block requests with invalid or missing license tokens
SupertabConnect.fastlyHandleRequests(event.request, merchantApiKey, "origin_backend_name", {
  enforcement: EnforcementMode.STRICT,
});
```

#### Bot detection

By default the SDK identifies known crawlers by their user agent. Pass a `botDetector` function to extend or override this logic.

```javascript theme={null}
const isBot = (request) => {
  const ua = request.headers.get("User-Agent") || "";
  return ua.includes("MyCustomBot") || ua.includes("Scraper");
};

SupertabConnect.fastlyHandleRequests(event.request, merchantApiKey, "origin_backend_name", {
  botDetector: isBot,
  enforcement: EnforcementMode.STRICT,
});
```

#### Manual verification

For fine-grained control, use `verifyAndRecord()` directly instead of `fastlyHandleRequests`.

```javascript theme={null}
const result = await supertab.verifyAndRecord({
  token: licenseToken,
  resourceUrl: request.url,
  userAgent: request.headers.get("User-Agent"),
});

if (result.valid) {
  // forward to origin
}
```

***

### Approach 2: Service Chaining (CDN → Compute)

Use this when you already have a CDN service and only want licensed requests to detour through Compute.
The CDN service does the routing via VCL snippets; the Compute service runs the SDK and then forwards to your normal origin.

#### VCL snippets — `vcl_recv` amd `vcl_pass`

To reroute RSL-licensed requests to the Compute service, add a `recv` snippet:

```vcl theme={null}
if (req.http.Authorization ~ "^License ") {
  set req.backend = F_supertab_compute_validator;
  return (pass);
}
```

Here `supertab-compute-validator` indicates the name of the host/backend that you must define in your Fastly CDN service.
It should lead to the automatically assigned Compute service's domain (e.g., `your-compute-service.edgecompute.app`)
which you will create on the next step.

Additionally, create a `pass` snippet:

```vcl theme={null}
declare local var.scheme STRING;

if (req.is_ssl) {
  set var.scheme = "https";
} else {
  set var.scheme = "http";
}

set bereq.http.X-Original-Request-Url = var.scheme "://" req.http.host req.url;
```

This ensures `X-Original-Request-Url` used to verify the `aud` claim from license token is included in the request to Compute service.
Without it CAP enforcement fails with `insufficient_scope` error as we are unable to confirm all properties required by RSL spec.

**Note**: keep the rest of your VCL flow intact so non-licensed traffic never leaves the CDN path.

#### Compute service

```javascript theme={null}
/// <reference types="@fastly/js-compute" />
import { SupertabConnect } from "@getsupertab/supertab-connect-sdk";
import { SecretStore } from "fastly:secret-store";

addEventListener("fetch", (event) => {
  event.respondWith((async () => {
    const configDict = new SecretStore("supertab_config");
    const entry = await configDict.get("MERCHANT_API_KEY");
    const merchantApiKey = entry?.plaintext() ?? "";

    return SupertabConnect.fastlyHandleRequests(
      event.request,
      merchantApiKey,
      "origin_backend_name"
    );
  })());
});
```

The Compute service requires the following configuration to work:

* A Secret Store called `supertab_config` containing `MERCHANT_API_KEY` and linked to the Compute service
* A backend for your real origin, passed as the third argument above (`origin_backend_name`)
* A Supertab backend with `stc-backend` as the name (see [VCL Service - Backend](#backend) for an example config)
* A host called `supertab-compute-validator` in the CDN service, using the Compute service's autogenerated `*.edgecompute.app` domain.

If the SDK rejects the token with an audience or scope error, check that the VCL snippet
saving the initial request URL to `X-Original-Request-Url` header is running before the request reaches Compute.

***

## Bot-Event Logging

When the SDK runs in a Compute service, it can emit one analytics event per request to a Fastly logging endpoint named `bot_events`. Supertab loads those events into your bot-traffic analytics.

### Enable analytics in the SDK

Pass the analytics options to `fastlyHandleRequests`:

```javascript theme={null}
SupertabConnect.fastlyHandleRequests(
  event.request,
  merchantApiKey,
  "origin_backend_name",
  {
    analyticsEnabled: true,
    logEndpoint: "bot_events",
    merchantSystemUrn: "YOUR_WEBSITE_URN",
  }
);
```

You can find your Merchant System URN on the **View Website Details** page of the Merchant Portal, in the same place as your API keys. If you prefer not to hardcode it, store it in your Secret Store alongside `MERCHANT_API_KEY` (e.g. as `MERCHANT_SYSTEM_URN`) and read it the same way.

### Create the S3 logging endpoint

The SDK writes events to a log streaming endpoint that must exist on your Compute service. In the Fastly dashboard, go to **Resources** → **Log streaming** → **Create endpoint** → **Amazon S3** and set:

| Setting                     | Value                                                   |
| :-------------------------- | :------------------------------------------------------ |
| **Name**                    | `bot_events`                                            |
| **Bucket name**             | `lpeu-prod-connect-bot-events`                          |
| **Path**                    | `bot-events/`                                           |
| **Domain**                  | `s3.eu-central-1.amazonaws.com` (region `eu-central-1`) |
| **Access key / Secret key** | credentials provided by Supertab                        |
| **Log format**              | **Blank**                                               |
| **Compression**             | none                                                    |
| **Period**                  | `900` seconds (15 min)                                  |

A few of these are easy to get wrong:

* The endpoint **name must be exactly `bot_events`**, matching the `logEndpoint` SDK option — otherwise the logs are silently dropped.
* The **log format must be Blank**. The SDK already writes one JSON object per line; the default (**Classic**) prepends a syslog header and corrupts every event.
* **Leave gzip compression off**, or the Supertab connector won't match the `*.log` objects.
* The **regional domain** `s3.eu-central-1.amazonaws.com` is required because the bucket is not in `us-east-1`.

Save the endpoint and activate the service version to start shipping events.
