Skip to main content
Release candidate. Kit 0.1.0-rc.3 was qualified on 28 October 2026 with the doubleshift API and reads by AI assistants. Install it with doubleshift, on one cache behavior first.
The kit adds two pieces to your AWS account and attaches them to the cache behavior that serves your article pages. Human requests are never sent to the composer, but they run under the kit’s cache and origin request policies: see What changes on your distribution. Rules every edge keeps are on Choose your edge.

What the kit installs

<prefix> is the template parameter NamePrefix, doubleshift by default. The template also creates the composer’s role, an origin access control, invoke permissions limited to your distribution, and two policies. It creates no distribution.

Before you start

  • Steps 1 to 3 of the Quickstart. Use a delivery key, and a logs token if you send delivery records, dedicated to this integration.
  • Your distribution ID and the cache behavior that serves your article HTML: default or its path pattern.
  • Node.js 20 or later, the AWS CLI v2, the AWS SAM CLI, and an AWS identity that can create a Lambda function and its role, CloudFront functions and policies, and update the distribution.
  • A firewall that admits the AI agents and the composer’s read, User-Agent doubleshift-edge-cloudfront/<kit version>. The kit’s waf/allow-agents.rule.json is an example AWS WAF allow rule for both, to place before your blocking rules; the kit never applies it. A rule on the User-Agent admits anyone who claims to be an agent.

What changes on your distribution

attach prints the behavior’s inventory and the diff before it writes anything. On that behavior only, it adds the origin doubleshift-composer if absent, puts the kit’s two policies in place of yours, and associates the function. It refuses, and writes nothing, when the behavior has a function on viewer request already, a function on viewer response, a Lambda@Edge on any event, or a response headers policy. Move such logic first. The 9 and the 1 are what CloudFront’s default quota of 10 headers per policy leaves. Your origin gets the origin domain as Host: the composer’s function URL needs its own, so the template refuses Host in both parameters and attach refuses a kit policy that forwards it. When your policies forward Host, cookies or other headers, attach lists what your origin would lose and applies only with --accept-policy-changes. An origin that needs the visitor’s Host or cookies is not covered. Cached copies of URLs with a query string may be fetched once more from your origin.

Install

1

Get the kit

Download the kit and check the archive’s SHA-256 before unpacking it: if the check fails, stop. Once unpacked, compare the SHA-256 of manifest.json with the one the changelog gives for kit 0.1.0-rc.3: the manifest gives the kit and edge library versions and the SHA-256 of every file. The kit is © DS Technologies, all rights reserved; its LICENSE grants doubleshift account holders the right to run it on their own distributions.
Download and check
2

Write the configuration

Set at least allowedHosts (Configuration), then check every file against the manifest and your configuration.
Configure and check
3

Deploy the template

In the AWS account of the distribution, in a region with Lambda nodejs24.x on arm64. Your account id, API key and logs token are NoEcho parameters, stored as environment variables of the composer, never in a file.
Deploy
4

Attach the kit to your distribution

With --apply, attach writes a rollback file (mode 0600, keep it private), applies the policies, waits until the distribution is Deployed, then associates the function. Before each step it reads the distribution again and stops if the behavior, its policies, the origin doubleshift-composer or the kit’s policies changed in between.
Attach

Configuration

composer/doubleshift.config.json is read once when the composer starts: a change needs sam build and sam deploy. Any other key is refused: the enriched page always goes out private, no-store. A missing or refused file makes every agent request answer 500, diagnostic adapter_config_invalid; humans are not affected. Out of scope, the composer still runs and returns your page with no call and no record.

Verify

Run the Verify and troubleshoot sequence on one article, 304 check included, then the checks specific to CloudFront:
CloudFront checks
Outcomes and fields are in the edge library reference. To send the records to doubleshift, deploy with a logs token (Delivery logs).

Limits

  • Latency. Each agent request runs one Lambda invocation that reads the page through your distribution, then calls doubleshift; the first request after a cold start of the Lambda is slower. Humans are not affected.
  • Page size. A page up to bufferMaxBytes goes out whole or as a 502, never truncated. A larger page is streamed: a break after the card can reach the agent as a complete page.
  • Compression. CloudFront does not compress the composer’s response. The composer compresses the enriched page only when it holds it whole, up to bufferMaxBytes; a larger page, and a page without a card, reach the agent uncompressed.
  • Downstream caches. CloudFront drops Vary: User-Agent: private, no-store alone protects the caches after it.
  • Cost. One Lambda invocation and one CloudFront read per agent request on the behavior, in scope or not.
  • Access. An identity of your AWS account allowed lambda:InvokeFunction on the composer can call it directly and get a card: hence the dedicated key.
  • Container. Write article:not(.a):not(.b), not article:not(.a, .b): a selector list inside :not() is refused.

Roll back

The rollback file restores the behavior in reverse order: the function first, which sends agents back to your cached page, then, once Deployed, your policies and the origin doubleshift-composer as it was before: removed if the kit added it and nothing else uses it, otherwise its own settings back. It refuses if the behavior or that origin changed outside the kit’s fields, and stops if the distribution changes between the two steps. When attach or the rollback stops, it prints the state as read: check it, run the dry run again, and keep the first rollback file (one written by a resumed --apply only restores the intermediate state).
Roll back