Deployment Models
Three deployment models cover the full provider spectrum: enterprise providers with Exchange operator relationships, mid-market providers with technical teams, and long-tail providers on CMS platforms. Each model provides the same protocol compliance but with different operational trade-offs.
Provider Onboarding: Domain Verification (v1.0)
Section titled “Provider Onboarding: Domain Verification (v1.0)”Before any deployment model, the provider must prove domain ownership via ACME HTTP-01 style verification. This is handled by fora-cli:
- Provider runs
fora-cli verify --domain techcrunch.com --exchange exchange.ssp-alpha.com - CLI calls
RequestDomainVerification— Exchange returns a challenge token - CLI places the token at
{domain}/.well-known/fora-verify/{token}(the edge function can auto-serve this from KV store) - CLI calls
ConfirmDomainVerification— Exchange fetches the challenge URL to verify domain control - If verified: Exchange accepts subsequent operations (signing key registration, catalog pushes) for this domain
The Exchange also checks fora.json to verify it is listed as an authorized exchange for this provider — providing double protection.
catalog_contributors in fora.json
Section titled “catalog_contributors in fora.json”Providers can authorize third parties (verification vendors, enrichment services) to push resource metadata on their behalf. This is declared in fora.json:
{ "ver": "1.0", "provider": "techcrunch.com", "catalog_contributors": [ { "domain": "gumgum.com", "relationship": "verifier" } ], "exchanges": [...]}The Exchange validates incoming CatalogService.PushResources requests against this list — unauthorized pushers are rejected.
Model 1: Exchange-Managed (Recommended, Enterprise)
Section titled “Model 1: Exchange-Managed (Recommended, Enterprise)”The Exchange operator deploys and maintains the FORA edge function on the provider’s CDN on their behalf. This is the Prebid Server model — “we handle everything.”
How It Works
Section titled “How It Works”- Provider signs a contract with the Exchange operator and grants CDN access (e.g., AWS IAM role for CloudFront, Cloudflare API token for Workers)
- Exchange operator runs domain verification on behalf of the provider (
fora-cli verify) - Exchange operator deploys the edge function to the provider’s CDN
- Exchange operator configures:
fora.json(includingcatalog_contributors),rsl.txtgeneration from the Exchange, bot detection rules - Exchange operator maintains, updates, and monitors the edge function on an ongoing basis
Provider Actions
Section titled “Provider Actions”- Sign contract with Exchange operator
- Grant CDN role/access to the Exchange operator
- Nothing else — the Exchange operator handles all FORA infrastructure
Exchange Operator Responsibilities
Section titled “Exchange Operator Responsibilities”- Deploy edge function to provider’s CDN account
- Generate and serve
fora.jsonfrom Exchange tenant config - Generate and serve
rsl.txtfrom Exchange catalog - Configure bot detection rules (User-Agent matching, behavioral signals)
- Rotate signing keys on schedule (default: 90 days)
- Monitor edge function health, latency, and error rates
- Push updates when the protocol evolves
When to Use
Section titled “When to Use”- Enterprise providers with Exchange operator relationships (news organizations, media companies)
- Providers who don’t have CDN engineering expertise
- Any provider who wants the “just works” experience
Model 2: Self-Service (Mid-Market)
Section titled “Model 2: Self-Service (Mid-Market)”The provider deploys the edge function themselves using tooling provided by FORA.
How It Works
Section titled “How It Works”- Provider installs the FORA deployment package
- One command deploys the edge function to their CDN:
Terminal window npx @fora/edge-deploy --cdn cloudfront --exchange exchange.ssp.com - Edge function pulls
fora.jsonandrsl.txtfrom the Exchange, caches in KV/edge storage - Provider manages their own CDN access and can customize bot detection rules
Supported CDNs
Section titled “Supported CDNs”| CDN | Deploy Method | KV Support | Full Feature Set |
|---|---|---|---|
| CloudFront | Lambda@Edge via Terraform/CLI | DynamoDB or S3 | Yes |
| Cloudflare | Workers via Wrangler | Workers KV | Yes |
| Fastly | Compute@Edge via CLI | KV Store | Yes |
| Akamai | Not supported | EdgeKV | No |
| Vercel | Edge Functions via CLI | KV | Yes |
| Generic | Reverse proxy config | External KV | Partial |
When to Use
Section titled “When to Use”- Mid-market providers with technical teams
- Providers who operate their own CDN infrastructure
- Providers who want control over their edge configuration
Model 3: CMS Plugin (Long Tail, Community-Built)
Section titled “Model 3: CMS Plugin (Long Tail, Community-Built)”A CMS plugin (WordPress, Drupal, Ghost, Django) that integrates with the FORA protocol at the application layer. The plugin does NOT deploy an edge function — CMS platforms cannot control CDN configuration.
What the Plugin Does
Section titled “What the Plugin Does”- Auto-generates
rsl.txtfrom the CMS content structure - Pushes content metadata to the Exchange via
CatalogService.PushResources - Adds
/.well-known/fora.jsonresponse via CMS routing
What the Plugin Does NOT Do
Section titled “What the Plugin Does NOT Do”- Deploy an edge function (CMS cannot control CDN)
- Enforce signed URL verification at the edge
- Block unauthorized bots at the CDN layer
Without edge enforcement, the CMS plugin model relies on the Exchange and protocol-compliant agents to respect rsl.txt terms. This is the “honor system” tier.
CMS Platform Support
Section titled “CMS Platform Support”| CMS | Language | Plugin Type | Proto Support |
|---|---|---|---|
| WordPress | PHP | WP Plugin | via buf.build PHP plugin |
| Drupal | PHP | Drupal Module | via buf.build PHP plugin |
| Django | Python | Django App | via buf.build Python plugin |
| Ghost | JavaScript | Ghost Integration | via buf.build TypeScript plugin |
| Contentful | TypeScript | Contentful App | via buf.build TypeScript plugin |
| Strapi | TypeScript | Strapi Plugin | via buf.build TypeScript plugin |
Example: WordPress Plugin Flow
Section titled “Example: WordPress Plugin Flow”Content published in WordPress -> Plugin hook fires (publish_post) -> Extract: title, word count, URL path, categories -> Compute: estimated_quantity = word_count * 1.32 -> Pre-check each entry with helpers.ValidateResourceEntry (advisory; the Exchange re-runs it) -> Build PushResourcesRequest (caller_id) with the SDK's catalog client, which stamps ver, refuses a non-bare-domain exchange, and signs it (RFC 9421) -> POST to Exchange CatalogService.PushResources -> Exchange adds/updates catalog entryEdge Function Minimum Viable Functionality
Section titled “Edge Function Minimum Viable Functionality”For CDNs with limited compute capabilities, the edge function can be reduced to a minimal feature set:
- Signed URL verification: verify the Ed25519 signature over the canonical URL — valid? pass through : return 403. A CloudFront distribution verifies its RSA signed URLs natively, so there the function skips this step.
- Bot detection: Check
User-Agentfor known AI crawler strings — match? return 403 withX-Content-Rulesheader - Serve
fora.json: Return/.well-known/fora.jsoninline or proxied from the Exchange
Minimum Viable Decision Table
Section titled “Minimum Viable Decision Table”Request arrives at edge:
1. Path = /.well-known/fora.json? YES -> Return inline fora.json (or proxy from Exchange)
2. Has signed URL params (sig, exp)? YES -> Verify signature Valid + not expired? -> Pass through to origin Invalid or expired? -> 403 Forbidden
3. User-Agent matches known AI crawler pattern? YES -> 403 Forbidden + X-Content-Rules header
4. Default -> Pass through to origin (non-bot, non-protected)Step 1 needs a runtime that can run code: Cloudflare Workers and Fastly Compute verify the signature themselves, and a CloudFront distribution verifies its own RSA signed URLs without any function at all. A declarative rule language — Fastly VCL, Akamai Property Manager — cannot verify a signature, so it can serve fora.json and refuse known crawlers but cannot admit a paid request.