Skip to content

Migrate seller from Lambda@Edge to native CloudFront + WAF x402 monetization#30

Draft
arditti wants to merge 9 commits into
aws-samples:mainfrom
arditti:feat/native-waf-x402-monetization
Draft

Migrate seller from Lambda@Edge to native CloudFront + WAF x402 monetization#30
arditti wants to merge 9 commits into
aws-samples:mainfrom
arditti:feat/native-waf-x402-monetization

Conversation

@arditti

@arditti arditti commented Jun 15, 2026

Copy link
Copy Markdown

Replace Lambda@Edge payment verifier with native CloudFront + WAF x402 monetization

AWS WAF AI traffic monetization is now GA. This PR migrates seller-infrastructure/
off the custom Lambda@Edge verifier and onto a WAF WebACL with MonetizationConfig +
per-route Monetize rules — charging AI bots for content natively at the edge, no Lambda.

Changes

  • Remove the cloudfront.experimental.EdgeFunction payment verifier and lib/lambda-edge/.
  • Add a CLOUDFRONT-scoped WebACL: Bot Control v6 (detect), human-allow (humans free),
    free discovery (/mcp/*, /.well-known/*), and per-tier Monetize rules reproducing
    the original prices ($0.001–$0.01, Base Sepolia USDC) off a $0.001 base × PriceMultiplier.
  • Attach the WebACL to the distribution; drop the L@E origin-request policy.
  • Unit tests for the pricing/rule builder + CDK assertions for the migrated stack.
  • Migration doc at docs/native-waf-x402-migration.md.

✅ Validated end-to-end on a live deploy

Deployed to a real AWS account (us-east-1) and ran the full flow against the GA capability:

  • WebACL with MonetizationConfig + Monetize actions deploys via CloudFormation and
    attaches to the distribution (confirmed via get-web-acl).
  • Bot → monetized path → HTTP 402 with the correct x402 challenge (amount 10000 =
    $0.01 for the dataset tier ×10, correct payee, Base Sepolia USDC, x402Version: 2).
  • Human → 200 (human-allow); discovery path → not monetized.
  • Real EIP-3009 payment → 200 + content → on-chain settlement on Base Sepolia:
    payer −0.010000 USDC, seller +0.010000 USDC. 🎉

🐛 Bug found & fixed by the live deploy

The first deploy served 200 (free) for everything — no 402. Root cause: the
ByteMatchStatement.SearchString was double-base64-encoded (the builder base64'd the
prefix, and CloudFormation base64's it again), so rules searched for the literal text
L2RhdGFzZXQ= and never matched — every request fell through to the default Allow. Fixed
to emit the plain URI prefix (CFN does the single encoding the WAF API needs) +
regression test. Unit tests alone had baked in the bug; only the live deploy caught it.

Spec compliance

Checked against the AWS WAF AI traffic monetization docs
(getting started,
pricing):
MonetizationConfig shape matches; Chain=BASE_SEPOLIA + CurrencyMode=TEST valid;
base price ≥ the $0.001 minimum (≤3 dp); Monetize terminating + bot-gated;
PriceMultiplier 1–100 integer-as-string.

IaC support status / gating

The Monetize action + MonetizationConfig are in the CloudFormation
AWS::WAFv2::WebACL schema and deploy correctly (verified end-to-end above). The
typed CDK L2/L1 props are not in aws-cdk-lib yet (latest checked: 2.260.0 — no
monetization typings), so this PR sets the fields via the L1 addPropertyOverride escape
hatch, which emits exactly the CFN that deploys today. When the typed CDK props ship, the
override can be simplified to native props with no behavioral change. Marked draft
pending that cosmetic follow-up and maintainer review; functionally it is validated and
deployable now.

arditti added 9 commits June 15, 2026 09:15
Update seller-infrastructure README/bin description, docs/API.md,
docs/TROUBLESHOOTING.md, QUICKSTART.md, and payer-infrastructure
observability dashboards + IAM comments to describe the CloudFront +
AWS WAF native x402 monetization architecture (Bot Control v6,
human-allow, free discovery, per-tier Monetize + MonetizationConfig)
that replaced the Lambda@Edge payment verifier.
AWS WAF AI traffic monetization requires the base price to be >= $0.001
USDC with at most 3 decimal places (per the getting-started + pricing
docs). The previous $0.0005 base violated both the minimum and the
3-decimal rule. Rebase to a $0.001 base and re-derive integer tier
multipliers from the original prices (market x2, tutorial x3, research
x5, dataset x10); the sub-minimum weather price floors to the base (x1).
Update tests + docs and add a base-price compliance assertion.

Ref: https://docs.aws.amazon.com/waf/latest/developerguide/waf-ai-traffic-monetization-pricing.html
…ending

The AWS WAF AI traffic monetization capability is generally available
(configurable via the WAF console and API today). Only the
MonetizationConfig / Monetize fields in the released CloudFormation /
CDK / SDK (and Terraform AWS provider) are still pending, expected to
follow shortly. Reword comments/docs accordingly: the L1
addPropertyOverride (or commented HCL) is the supported way to set these
fields until the typed props land — not a 'preview'/'inert' workaround.
A live deploy proved the ByteMatchStatement SearchString was being
double-base64-encoded: the builder base64'd the prefix AND CloudFormation
base64's it again, so the deployed rule searched for the literal text
'L2RhdGFzZXQ=' and never matched. Every request fell through to the
default Allow and no 402 was ever issued.

Fix: emit the plain URI prefix (e.g. '/dataset'); CloudFormation does the
single base64 encoding the WAF API requires. Add a regression test
asserting plain SearchString.

Verified end-to-end on a live deploy (account 638769857148, us-east-1):
bot -> 402 challenge (/bin/zsh.01 dataset tier, correct payee) -> EIP-3009
payment -> 200 + content -> on-chain settlement of 0.01 USDC on Base
Sepolia (payer -0.01, seller +0.01).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant