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 it controls its domain. The proof is the fora.json the domain serves from the provider’s own origin. The Exchange reads that file at registration, on every check of a domain being verified and at every catalog push, so the proof keeps being renewed: a file that stops listing the Exchange stops the domain’s pushes. Publisher Onboarding describes that path through a publisher console.
The contract also carries RequestDomainVerification and ConfirmDomainVerification, for deployments that verify a domain with a challenge instead (see the contract reference).
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 generates the provider’s
fora.json(includingcatalog_contributors) and, where the provider has none, itsrsl.txt - Provider publishes those files on its own origin, which proves it controls the domain
- Exchange operator deploys the edge function to the provider’s CDN
- Exchange operator configures 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
- Publish the generated files on its own origin
- The Exchange operator handles the rest of the FORA infrastructure
Exchange Operator Responsibilities
Section titled “Exchange Operator Responsibilities”- Deploy edge function to provider’s CDN account
- Generate
fora.jsonfrom Exchange tenant config, for the provider to publish on its origin - Generate
rsl.txtfrom Exchange catalog, where the provider has none of its own - 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 - Provider publishes
fora.json, andrsl.txtif it has one, on its own origin; the edge function passes both through to it - 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 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 - Let
fora.jsonthrough: Leave/.well-known/fora.jsonto the origin, ahead of the bot check, so a refused bot can read it
Minimum Viable Decision Table
Section titled “Minimum Viable Decision Table”Request arrives at edge:
1. Path = /.well-known/fora.json or /rsl.txt? YES -> Pass through to origin
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 refuse known crawlers but cannot admit a paid request.