On an adapter with no geo provider the jurisdiction is always Unknown, and Unknown fails closed on both Edge Cookie creation and the server-side auction. So neither of those can run, and there is no configuration that lets an operator say what to assume.
Both halves are documented on their own, and the Axum adapter's own source puts them together in a comment (crates/trusted-server-adapter-axum/src/app.rs:156-159, which says a no-op geo leaves the jurisdiction Unknown and fails the auction consent gate closed). We could not find an operator-facing page that does.
The chain, at 0f8b44dc0
The Axum adapter's geo lookup always returns None (crates/trusted-server-adapter-axum/src/platform.rs:189-193), which docs/guide/architecture.md:59 states as a limitation. Spin injects NullGeo (crates/trusted-server-adapter-spin/src/platform.rs:747), whose lookup returns Ok(None) (:766-772), and that wiring sits outside every #[cfg], so it applies to the real runtime as well. Spin is described as production-capable at architecture.md:68 and its limitations do not mention geo.
With no geo, detect_jurisdiction returns Unknown (consent/jurisdiction.rs:48-51, and its own test no_geo_returns_unknown).
Unknown then fails closed twice:
// consent/mod.rs:590-591
// Fail-closed: block EC creation as a precaution.
jurisdiction::Jurisdiction::Unknown => false,
// consent/mod.rs:341-350
let requires_tcf_purpose1 = ctx.gdpr_applies
|| matches!(
ctx.jurisdiction,
jurisdiction::Jurisdiction::Gdpr | jurisdiction::Jurisdiction::Unknown
);
if !requires_tcf_purpose1 {
return true;
}
effective_tcf(ctx).is_some_and(|tcf| tcf.has_purpose_consent(1))
}
Observed on an Axum deployment across fifteen publisher sites, every request logged should_run_auction=false with consent_allows_auction=false, until a TCF consent cookie was supplied, after which nine slots filled on one page. So on one of these adapters the server-side auction never runs unless a TCF consent string granting purpose 1 reaches it, which in practice means a consent management platform in front of it.
Neither fail-closed rule is wrong. edge-cookies.md:119 and :125 state the Edge Cookie one as the design, and the auction gate's own doc comment says only a known non-GDPR jurisdiction with no EU TCF signal is freely allowed. The gap is that nothing tells an operator that choosing an adapter without a geo source means neither will run.
The question
Should there be a way for an operator to declare the jurisdiction to assume when no geo source is available?
We ask because we have built one in our own pull requests and would rather you saw the shape before it arrives than after.
In #1045 the assumed jurisdiction is the jurisdiction: on the top node of the rules tree in the compiled-in permission policy file, beside the permission baseline for the same visitor, so one file states the policy for both. detect_jurisdiction returns that value when there is no geo instead of Unknown, and it is carried into the consent context that the auction gate reads, so both subsystems see the same declaration. A deployment that runs an Edge Cookie provider without a geo provider must also set [geo] assume_single_jurisdiction = true, checked at startup, so serving one jurisdiction is an explicit operator decision rather than an accident of the defaults. With the shipped policy file's jurisdiction: gdpr at the top the auction gate still requires TCF purpose 1, by the deployer's own declaration, and a deployer whose file names a non-regulated jurisdiction there gets the auction without it. #779 and #781 are the issues that specified it.
So the design question is whether that shape, a declared assumed jurisdiction read in one place by both subsystems and an explicit acknowledgment that it is being relied on, is the one you want. If it is not, we would rather change ours than land it and argue.
Scope notes
The Spin half is read from source and not run, because on main the Spin adapter answers every request except the health probe with a 503 (#1101), so the condition cannot be observed there yet.
No branch is offered here beyond the pull request already open.
Written with AI assistance. The chain above was checked against the source at 0f8b44dc0, the description of our own change against the head of #1045, and the auction behavior was observed on an Axum deployment. Worth a human review before acting on it.
On an adapter with no geo provider the jurisdiction is always
Unknown, andUnknownfails closed on both Edge Cookie creation and the server-side auction. So neither of those can run, and there is no configuration that lets an operator say what to assume.Both halves are documented on their own, and the Axum adapter's own source puts them together in a comment (
crates/trusted-server-adapter-axum/src/app.rs:156-159, which says a no-op geo leaves the jurisdiction Unknown and fails the auction consent gate closed). We could not find an operator-facing page that does.The chain, at
0f8b44dc0The Axum adapter's geo lookup always returns
None(crates/trusted-server-adapter-axum/src/platform.rs:189-193), whichdocs/guide/architecture.md:59states as a limitation. Spin injectsNullGeo(crates/trusted-server-adapter-spin/src/platform.rs:747), whose lookup returnsOk(None)(:766-772), and that wiring sits outside every#[cfg], so it applies to the real runtime as well. Spin is described as production-capable atarchitecture.md:68and its limitations do not mention geo.With no geo,
detect_jurisdictionreturnsUnknown(consent/jurisdiction.rs:48-51, and its own testno_geo_returns_unknown).Unknownthen fails closed twice:Observed on an Axum deployment across fifteen publisher sites, every request logged
should_run_auction=falsewithconsent_allows_auction=false, until a TCF consent cookie was supplied, after which nine slots filled on one page. So on one of these adapters the server-side auction never runs unless a TCF consent string granting purpose 1 reaches it, which in practice means a consent management platform in front of it.Neither fail-closed rule is wrong.
edge-cookies.md:119and:125state the Edge Cookie one as the design, and the auction gate's own doc comment says only a known non-GDPR jurisdiction with no EU TCF signal is freely allowed. The gap is that nothing tells an operator that choosing an adapter without a geo source means neither will run.The question
Should there be a way for an operator to declare the jurisdiction to assume when no geo source is available?
We ask because we have built one in our own pull requests and would rather you saw the shape before it arrives than after.
In #1045 the assumed jurisdiction is the
jurisdiction:on the top node of therulestree in the compiled-in permission policy file, beside the permission baseline for the same visitor, so one file states the policy for both.detect_jurisdictionreturns that value when there is no geo instead ofUnknown, and it is carried into the consent context that the auction gate reads, so both subsystems see the same declaration. A deployment that runs an Edge Cookie provider without a geo provider must also set[geo] assume_single_jurisdiction = true, checked at startup, so serving one jurisdiction is an explicit operator decision rather than an accident of the defaults. With the shipped policy file'sjurisdiction: gdprat the top the auction gate still requires TCF purpose 1, by the deployer's own declaration, and a deployer whose file names a non-regulated jurisdiction there gets the auction without it. #779 and #781 are the issues that specified it.So the design question is whether that shape, a declared assumed jurisdiction read in one place by both subsystems and an explicit acknowledgment that it is being relied on, is the one you want. If it is not, we would rather change ours than land it and argue.
Scope notes
The Spin half is read from source and not run, because on
mainthe Spin adapter answers every request except the health probe with a 503 (#1101), so the condition cannot be observed there yet.No branch is offered here beyond the pull request already open.
Written with AI assistance. The chain above was checked against the source at
0f8b44dc0, the description of our own change against the head of #1045, and the auction behavior was observed on an Axum deployment. Worth a human review before acting on it.