doubleshift-edge.v1.js, one file with no dependency, for a Cloudflare Worker: version 1.1.4,
SHA-256 d4db890cbf27a2da1977d3ba76e0585ab3bf7cc78111eaddc71019527114e9d1, served at https://api.shftd2.com/edge/doubleshift-edge.v1.js. Install it with
the quickstart; earlier versions are in the changelog.
It exports enrichWithDoubleshift(request, response, options, ctx), which returns the page to send, and
prepareOriginRequest(request, config), which drops the conditional headers from an AI agent’s GET.
config is optional: with a custom agentPattern, pass { agentPattern } with the same pattern to both
functions, or an agent the enrichment recognises still sends its conditional headers to your origin.
Options
An invalid value gives
config_invalid with its field, before anything is read, and the page goes out
unchanged. An unusable scope gives scope_invalid instead (scope).
Scope
scope is checked first, on every request. Out of scope, the Worker returns the origin’s response as
it came: no call, no record, no sending.
- Patterns: a path starting with
/, exact (/articles/geely.html) or a section ending in/*:/articles/*covers/articles,/articles/and every path under it, never/articles-other./is the home page only,/*every page. No host, query, hash, whitespace, backslash,.segment,..anywhere, malformed%sequence,//, or*elsewhere; at most 200 patterns per list. - Which pages: no
excludepattern matches and, ifincludeis set, one of its patterns does.excludealways wins;include: []takes no page. - Comparison: as routing reads the path, query, hash, trailing slash and
ASCII case ignored. The request’s own path, on any host;
canonicalOriginonly changespage_url. - In scope: routing and card eligibility decide. A path in scope does not guarantee a card.
- A scope that cannot be used never means every page: nothing is processed, and one
scope_invaliddiagnostic is written per isolate and per reason.
scope silently: download the file again and check its SHA-256.
What it does with the page
Only an AI agent’sGET answered 200 text/html is touched. Nothing reaches the agent before the
decision, taken at the first container: one call, GET /v1/fragment with format=json, X-Agent-UA and
the page’s record_id in X-DS-Record-Id, redirects not followed. page_url never carries the query
string. No container in the first 256 KiB, or within 800 ms of the origin’s headers: no call.
With a card, the enriched page loses its validators, Age, Expires, length, encoding and origin cache
directives, takes cachePolicy and adds Vary: User-Agent. Otherwise the page goes out as the origin
sent it.
invalid_card reasons: content_type, empty, too_large (over 64 KiB), read_failed, json, or the
first refused field, from payload to source.newsroom_url (card format).
Delivery records and logs
Each agent page in scope normally writes one record,event: "doubleshift_edge"; a fallback internal_error may
follow with the same record_id. Fields: version; level (info for served and no_fill, error
for configuration, body, origin, stream and internal failures, else warn); outcome; agent, the marker
found; page_url; record_id, a UUIDv7 sent in X-DS-Record-Id; ts, ISO 8601 UTC; duration_ms until
the record. After an answer: status, api_rid (its X-Request-Id), api_ms (the call alone). With a
card: brand (120 characters at most), resolution (rule, default, id or other), card_written
(the runtime took the card’s end for sending, not a network acknowledgement). reason, field, limit
and error are fixed codes.
Direct delivery logs
WithlogsToken, each record also goes to doubleshift through ctx.waitUntil, the token in
Authorization only, 10 s per attempt. A timeout, a network error or a 503 gets one more attempt 2 s
later; nothing is queued. An invalid agentPattern, logsToken or beaconUrl is checked before the
sender exists, so its record stays local; with a valid token and a usable ctx, any other
config_missing or config_invalid record is sent like the others. Records carry no article HTML or cookies, and both secrets are redacted. Contract: direct delivery logs API; which transport:
delivery logs.
Diagnostics
event: "doubleshift_edge_diag" with a kind, written through log, never sent.
A sending diagnostic
Success is silent, and so is a missing or empty token.
Your own log function
log(record) replaces console output for records and diagnostics. Forward records with every field:
record_id links a diagnostic that carries one to the page, api_rid to the delivery. Send only doubleshift_edge records
to doubleshift. With logsToken, your changes do not reach what is sent. A function that stops writing to
the console also removes the records from what Logpush exports.
