Set it up · Why it's different · How it works · Networks · Grading · Showcase · Docs
Warning
Alpha — expect bugs and breaking changes. standdown is pre-1.0 and under active development: the API may shift between minor versions and edge cases are still being found. Because it makes revenue-affecting decisions, pin your version, verify it against your own integration with the conformance grader, and please report anything that misbehaves.
Your extension shouldn't steal the sale.
standdowndetects existing affiliate attribution, suppresses competing activation, and proves the decision was made locally — never on a server.
standdown is a zero-runtime-dependency TypeScript library for extension
developers who need to detect existing affiliate attribution, suppress competing
activation, and prove that suppression decisions were made locally and
deterministically. Built and maintained by Dupe.
Hand the whole integration to your coding agent — that's the supported path. standdown makes revenue-affecting decisions across your extension's code, so the fastest and safest way in is to let a coding agent do the work: it reads your codebase, gates every place attribution fires, bundles, and grades the result. Paste this into your agent — Claude Code, Codex, Cursor, opencode, Copilot — pointed at your extension's repo:
Set up standdown — the open-source affiliate stand-down library (npm package
`standdown`, source https://github.com/dupe-com/standdown) — in this browser
extension, so it stops hijacking affiliate attribution a partner already owns.
Then grade and verify it. Read and follow, end to end, the official guide at
https://raw.githubusercontent.com/dupe-com/standdown/main/AGENTS.md — it detects
whether this is a fresh install or a migration of existing stand-down logic and
branches accordingly. When you're done, report my conformance grade and keep
fixing until it's an A or better.
That single prompt runs the whole loop — install, adapter choice, gating,
bundling, and grading — and auto-switches to the shadow-mode
migration path if your extension already has its own stand-down
logic. The steps live in one place, AGENTS.md, so every agent
follows the same playbook.
Use a capable model. This reasons about revenue-affecting control flow across an unfamiliar codebase — run it on a frontier coding model (Claude Opus, GPT-5.5, or equivalent). Lighter models miss firing points and mis-handle the
degradedgate; if you must use one, review the gating diff by hand and always run the grader.
On Claude Code? Install the plugin once — no checkout — and get typed commands:
/plugin marketplace add dupe-com/standdown
/plugin install standdown@dupe
Then run /standdown:setup in your extension's repo (or /standdown:adopt
for a migration, /standdown:showcase to publish your grade).
The plugin also auto-triggers when you just say "add standdown to my extension."
Prefer a single skill, without the plugin?
Curl the skill straight into your personal skills — the slash command matches the folder you install it into:
mkdir -p ~/.claude/skills/standdown && curl -fsSL \
https://raw.githubusercontent.com/dupe-com/standdown/main/skills/setup/SKILL.md \
-o ~/.claude/skills/standdown/SKILL.mdRestart Claude Code, then run /standdown. (Swap skills/setup for skills/adopt
or skills/showcase to grab the others.) The skill pulls the live
AGENTS.md playbook itself, so it stays current.
Wiring it by hand instead? The full manual walkthrough and complete API
reference — the five published surfaces, self-exemption, per-host disable, signed
refresh, the standdown/url helper, interop — live in INSTALL.md.
Affiliate stand-down is easy to claim and hard to prove. standdown is built so
the guarantees are structural — enforced by the type system and the architecture,
not by a promise in a blog post.
- 🔒 Decisions never leave the device. No network call participates in a stand-down decision, ever. The decision path is a pure function of local signals and bundled policies.
- 🛡️ User data can't leak into a decision — by construction.
Signalsis a closed type: identity, accounts, balances, email, and login state are structurally unable to enter it. - ⚖️ Fails toward standing down. Ambiguity, storage errors, or a malformed policy all resolve to suppress. The library never hijacks a sale by accident.
- 🎯 Detects attribution the way networks actually set it. Landing params, redirect-chain hops, first-party cookie names (never values), and referrer/initiator classification — across eight verified network packs.
🅰️ It grades itself, F→A+, and hands you a shareable card when you pass — with an inert-code guard so "disciplined" can't be faked by shipping nothing.- 📦 Zero runtime dependencies. Ships ESM + CJS + types. MV3, with a content-script path for Safari and reduced-permission contexts.
standdown answers one question, locally: does someone already own the affiliate
attribution on this page, so my extension should stay quiet? It returns a
Decision — it never redirects, blocks, or fires anything itself. You own the
side effects; you gate them on decision.standDown.
For each navigation it inspects local signals only and matches them against bundled, per-network policy packs:
- Landing params — the query params networks stamp on a click-through
(
cjevent,irgwc,ranSiteID,awc,sscid, eBay'smkcid/campid, …). - Redirect-chain hops — tracker domains a click passed through (LinkSynergy,
prf.hn,awin1.com, the universal fingerprint set), when the adapter can see them. - First-party cookie names — attribution cookies a prior click dropped
(
lsclick_mid,sscid,im_ref, …). Names only, never values. - Referrer / initiator — whether the navigation came from your own site (a self-owned click) or a third party.
A small state machine turns those into a decision: if a competitor's attribution is present, it stands down for the policy's duration; if the signal is yours (a declared self-param), it doesn't stand you down against your own click. Every decision is deterministic, appended to a local audit log, and made without a network call.
Two integration shapes:
| When | Playbook | |
|---|---|---|
| Greenfield | Your extension has no stand-down logic yet | Gate each affiliate firing point on decision.standDown. Follow AGENTS.md. |
| Brownfield | Your extension already has homegrown attribution/stand-down logic (params, cookies, a disable list) | Migrate that decision path onto standdown in shadow mode first — run both in parallel and prove they agree before cutover, so no live commission is risked. Follow ADOPTING.md. |
Each bundled pack implements a network's stand-down expectations — the detection signals it sets, the suppression behavior it asks for, and how long it lasts — so you don't have to reverse-engineer them. Eight verified packs ship enabled by default: seven named networks, plus a universal redirect-fingerprint set.
The eighth verified pack is a universal set of publisher-contributed redirect fingerprints (piedotorg/standdown-domains). Two more experimental packs (Sovrn/Skimlinks, Partnerize) are inferred from domain knowledge and stay opt-in until you verify them. See the full pack table and citations in POLICIES.md.
Network names and logos identify the stand-down policies each pack implements. They don't imply endorsement, partnership, or certification by these networks.
Unit tests prove the library's decisions in isolation. The audit/
harness proves the thing they can't: whether a real integration actually stands
down instead of hijacking existing attribution. Two graders:
-
conformanceGrade(start here) — deterministic and browser-free. It drives the policy set your extension bundles through the real decision engine over every network's attribution and control scenarios and scores F→A+. This is the number to report, and the correct sensor for any real host extension.bun install && bun run build # build the lib the grader imports (dist/ is gitignored) cd audit && npm install DISABLE_HOSTS="ebay.com,homedepot.com" npx tsx grade/conformance.ts # standdown conformance grade: A+ (100/100)
The bare command grades the bundled
allPolicies; if you ship a custom or subset set, addPOLICY_PACK=/abs/path/to/your/policies.tsso it grades what you actually bundle. -
grade.ts(in-browser) — loads an unpacked extension into a real browser and watches for the testexts'/aff/:net?actor=redirect. A real host extension that activates by painting UI usually scores C (inert) here — that means "wrong sensor," not "dead code." Adaptgrade/host-extension-probe.tsto sense your extension's own surface.
The rubric has an inert cap: an extension that never activates even when
activation is allowed can't score above a C, so "disciplined stand-down" can't
be faked with dead code. The harness is opt-in — not part of the npm package, not
on the required CI path. See audit/README.md.
On a passing grade, both graders print a shareable card — a terminal card, a
copy-paste social snippet, and a self-contained standdown-grade.svg written to
your working directory that you can post anywhere:
Graded A/A+? Add your extension to the showcase — a wall of
fame where every badge is reproduced by CI (a submission declares its policy
inputs; CI re-runs the grader and regenerates the card, so nothing can be faked).
The badge is tiered: a config-verified entry earns an A, and verifying the
live published extension unlocks A+. One prompt opens the PR — see
showcase/README.md.
The seven invariants standdown holds — the structural guarantees behind the pitch.
- I1: Client-side decisions only. No network call participates in a stand-down decision. Refresh may update the already-applied local policy bundle asynchronously, but decisions use local state synchronously.
- I2: No user profiling. Signals are a closed type and exclude user identity, accounts, balances, emails, login state, and tester-differentiating data.
- I3: Fail toward standing down. Unknown, ambiguous, malformed, or storage error states suppress activation.
- I4: Monotone remote updates. Signed refresh bundles may only broaden detection or lengthen durations and may not edit activation rules.
- I5: Audit log on by default. Decisions and refresh outcomes are locally auditable.
- I6: No remote code. Policies are data. No eval, remote scripts, or dynamic code loading.
- I7: Deterministic and loggable. Given the same local signals, policies, state, and clock, decisions are reproducible.
| Doc | What's in it |
|---|---|
| INSTALL.md | Manual install + full API: adapters, quickstarts, self-exemption, per-host disable, signed refresh, interop |
| AGENTS.md | The consumer playbook an AI agent follows (greenfield) |
| ADOPTING.md | Brownfield migration: move existing stand-down logic onto the library in shadow mode |
| POLICIES.md | Every network pack, its signals, and citations |
| SPEC.md | The behavioral spec and invariants |
| audit/ | The conformance graders |
| SHOWCASE.md · showcase/ | "Graded with standdown" wall of fame + how to add yours (CI-verified) |
| examples/mv3-extension · examples/content-extension | Minimal working integrations |
Releases are cut by tagging a version with npm run release; CI then publishes
over npm Trusted Publishing (OIDC), with no stored token. See
RELEASING.md.
