Skip to content

Axum: add optional Geo providers for local GeoIP databases and trusted CloudFront metadata #432

Open

Description

@ChristianPavilonis

Goal

Add optional native Geo providers so Axum applications can obtain geographic facts from either a local GeoIP database or trusted CloudFront metadata. Follow the explicit provider selection and startup ownership used for native AWS services, without treating Geo as a config, secret or KV store.

Track this as a separate follow-up under #391. Do not expand the AWS store-provider PR #414 to include geography.

Why this is needed

The checked native ingress work in #409 provides client-IP facts and their provenance. It does not provide visitor country or subdivision. Trusted Server's native PlatformGeo currently returns no geography, leaving jurisdiction unknown. Its intentional fail-closed auction/identity behavior is documented in IABTechLab/trusted-server#1134.

An AWS deployment region is not visitor geography. A browser language, timezone, arbitrary country header or missing TCF string is not a substitute either.

Provider contract and ownership

  • Expose typed geographic facts through the existing request/runtime composition model: at least optional country and subdivision, with provider provenance and explicit unavailable/partial/error behavior. Do not invent a country, region, city or coordinates to fill missing fields.
  • EdgeZero owns provider mechanics and checked metadata. Applications own jurisdiction classification, regulatory lists, CMP interpretation, consent and auction/identity decisions. Geography is an estimate, not proof of residency or consent.
  • Provider selection is explicit and optional. Absence remains unavailable; a configured provider must not silently switch to another source. Keep native provider dependencies default-off and preserve portable/WASM contracts.
  • Reuse existing native startup/initializer ownership and explicit runtime options or bindings patterns. No new general plugin framework is required. A selected unusable local database fails startup before readiness; an application that selects no Geo provider can still run.
flowchart TD
    Selection[Explicit native Geo selection] --> Local[Local GeoIP provider]
    Selection --> CloudFront[Optional CloudFront provider]
    IP[Checked reader IP] --> Local
    Ingress[Verified front-door metadata] --> CloudFront
    Local --> Facts[Geographic facts and provenance, or unavailable]
    CloudFront --> Facts
    Facts --> App[Application jurisdiction and consent policy]
Loading

Initial providers

Local GeoIP database

  • Resolve the checked effective reader IP, not an unconditionally selected X-Forwarded-For value or the load balancer's address.
  • Use an operator-supplied database format that can provide country and subdivision. Country-only data must retain the fact that subdivision is unknown.
  • Load and validate the database through bounded native startup preparation. Document read-only mounts, supported format, licensing, data version/freshness and explicit replacement/restart behavior.
  • Do not download a database implicitly or send visitor IPs to an external lookup service. Missing matches and unresolved reader IPs remain unavailable.

Trusted CloudFront metadata

  • Optionally consume CloudFront country and country-region headers through a checked ingress boundary, with strict parsing and explicit missing/partial behavior.
  • Require a deployment-owned, protected CloudFront-to-origin path and header provenance. Reaching the application through a trusted ALB subnet alone does not prove that a geographic header originated at CloudFront.
  • Reject or ignore spoofed, duplicate, malformed or untrusted assertions. Never trust raw geographic headers supplied directly by a client.
  • Keep CloudFront provisioning and origin access configuration in deployment guidance, not automatic SDK infrastructure mutation. Header consumption should not require AWS store providers or AWS SDK calls.

Acceptance

  • Explicit selection, default-off dependencies and provider availability have focused tests; selected invalid configuration fails before listen without local/provider fallback.
  • Local database fixtures exercise country/subdivision, IPv4/IPv6, unresolved reader IP, no match, malformed database and read-only startup.
  • CloudFront ingress fixtures exercise a verified source, direct-client spoofing, an ALB forwarding unverified headers, malformed/duplicate assertions and missing subdivision.
  • Consumers can distinguish unavailable or partial geography from a known result. In particular, US country with no state retains an unknown subdivision; the provider makes no claim about which privacy regime applies.
  • Documentation shows local-database and protected CloudFront deployments, privacy-safe diagnostics, capability limitations and the difference between geographic facts and application policy.
  • Existing adapters, native lifecycle behavior and WASM/default dependency checks remain intact. Record fixture evidence separately from any real CloudFront deployment acceptance.

Geo remains optional for general Axum hosting. A downstream profile that depends on geography must demonstrate its configured provider or retain its existing fail-closed behavior. This issue does not authorize changing Trusted Server's consent rules, adding an assumed jurisdiction, or implementing an identity database.

Related

Activity

  1. added this to the 202611 milestone on Oct 22, 2026
  2. ChristianPavilonis commented on Oct 22, 2026

    @ChristianPavilonis
    CollaboratorAuthor

    Implementation scope is split for the initial delivery. The pluggable synchronous Geo contract and protected CloudFront provider follow the reviewed specification; local databases, checked-reader-IP inputs and database lifecycle are deferred to #438. CloudFront support will not satisfy the local-database acceptance items above. Native celld remains the base of the implementation stack. Actual CloudFront/ALB deployment acceptance and Trusted Server adoption stay separate from local implementation proof.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions