Developers  /  GeoProof Standard v1

GeoProof Protocol — Specification

Published exactly as attested in Oxyon's signed provenance record. Verify the fingerprint · raw file

Status: Draft v1.0 · Date: 2026-07 · Layer: application protocol over XYO + XL1 Package: @geo/geoproof

GeoProof is the canonical proof schema/protocol of the Oxyon ecosystem. Oxyon is the company; GeoProof is the protocol. Every Oxyon product emits and consumes GeoProof events so that observations from any product can be verified and connected by any other.

1. Design goals

  1. One proof model across all products — a presence proof from GeoPresence and a signing proof from GeoWallet are the same shape, verifiable by GeoJustice.
  2. Built on XYO, not reinventing it — GeoProof events ARE XYO payloads, carried in XYO bound witnesses. GeoProof does not define new crypto.
  3. Anchored on XL1 — proofs are batch-anchored for durable, ordered finality.
  4. Brand-correct namespace — schemas live under oxyon.geoproof.*, never the sponsor token's name. (Alpha products currently emit winlew.geo.*; §7.)
  5. Forward-compatible — versioned schemas; additive evolution.

2. Foundation: XYO + XL1 (normative references)

A GeoProof event is an XYO payload — a JSON object with a schema string and arbitrary fields; its identity is its deterministic XYO hash. Events gain trust only when bound into an XYO bound witness (network.xyo.boundwitness), which carries:

BW field Role
addresses the account(s) that authored/witnessed the payloads
payload_hashes / payload_schemas the bound payloads (tamper-evident)
previous_hashes per-address chain linkage
$signatures signatures over the BW hash by each address
$sources links this BW to prior BWs/payloads (cross-phase linkage)

Construction/validation is performed by @xyo-network/boundwitness-builder and @xyo-network/boundwitness-validator. GeoProof MUST NOT reimplement hashing or signing. (Exact package APIs drift between XYO releases — pin and verify against the version each product uses.)

3. The four-phase model (Observe · Locate · Verify · Connect)

GeoProof maps Oxyon's mission to a lifecycle:

Observe   an app records an observation        → GeoProofEvent (payload)
Locate    attach XY/context                     → event.location (GeoPoint)
   ↓      sign + bind                            → XYO bound witness (authorship)
Verify    GeoJustice judges the bound witness   → VerificationReceipt
Connect   batch-anchor to XL1; index; relate    → AnchorBatch + $sources graph
Phase Role Product Emits
Observe/Locate producer GeoWallet, GeoPresence, any app oxyon.geoproof.{event,presence,attestation}
Verify Oracle GeoJustice oxyon.geoproof.receipt
Connect anchor + index anchor service / services/geo-indexer oxyon.geoproof.anchor.batch

4. Schemas

Canonical names (versioned in the schema string, XYO-style):

Schema Meaning
oxyon.geoproof.event.v1 base envelope (producer, subject, observedAt, location?, claims?)
oxyon.geoproof.presence.v1 Proof of Presence (location required; method)
oxyon.geoproof.attestation.v1 generic signed statement about a subject
oxyon.geoproof.receipt.v1 verification verdict + trust score (GeoJustice)
oxyon.geoproof.anchor.batch.v1 set of proof hashes committed to XL1
oxyon.geoproof.supersession.v1 truth changed — new conclusion replaces old (history intact)
oxyon.geoproof.revocation.v1 statement withdrawn — no replacement (history intact)
oxyon.geoproof.rotation.v1 old key endorses new key — dual-signer BW IS the endorsement

TypeScript definitions: src/schemas.ts. Field-level contracts are the source of truth; this table is a summary.

4.1 Envelope (all events)

producer (string), subject (string — address / device id / content hash), observedAt (epoch ms UTC), location? (GeoPoint: lat, lon, accuracyM?, altM?), claims? (object). Presence narrows location to required.

4.2 Supersession

A supersession records that a prior receipt or attestation has been overtaken by new evidence. It does not delete history. The superseded record remains in the DAG exactly as it was — replay still works — but the supersession says: "given what we know now, the current conclusion is different." Required fields: supersededHash (BW hash of what is being superseded), reason (non-empty string — silent supersession is a protocol violation), effectiveAt (epoch ms), issuer (address). Optional: replacementHash (BW hash of the new statement). If no replacement exists, use Revocation instead.

4.3 Revocation

Full withdrawal: the statement is no longer valid and there is no replacement. Required: revokedHash, reason (non-empty), effectiveAt, issuer. History stays intact; the revocation is a terminus node, not an erasure.

4.4 Key Rotation

The retiring key (oldAddress) and the successor key (newAddress) must BOTH sign the carrying bound witness — the dual-signer BW IS the endorsement. A verifier must confirm: both signatures present and valid; both addresses present in bw.addresses; the rotation payload in bw.payload_hashes; the rotation has not been superseded or revoked. Reference: rotateKey(oldKey, newKey) in @geo/geoproof-reference.

4.5 Chained Attestations

XYO bound witnesses carry previous_hashes, which the SDK auto-populates with PayloadBuilder.dataHash(priorBw) when the same account builds consecutive BWs. This creates a per-identity transparency log: any gap or reordering is detectable. Applications that issue multiple receipts through the same verifier account get chaining for free. Reference: confirmed via probe in 2026-06.

5. Verification

Two layers, kept distinct:

  1. Cryptographic (who/whether-tampered) — delegated to @xyo-network/boundwitness-validator over the carrying BW: signatures valid, hashes match, chain consistent.
  2. Semantic / trust — GeoJustice applies policy: schema validity (validateEventShape), plausibility (e.g. location accuracy, velocity between presence proofs), authority allow-lists, fraud signals → a verdict and a 0..1 score, emitted as a receipt linked via $sources to the proof.

validateEventShape() in this package is structural only and never a substitute for (1).

6. Anchoring on XL1

Producers and verifiers write proofs/receipts; an anchor process periodically commits their bound-witness hashes to XL1 as oxyon.geoproof.anchor.batch (the pattern the alpha products call winlew.geo.anchor.batch.v2). network MUST come from env (never hardcoded). services/geo-indexer replays anchored batches with a floor block + atomic checkpoints to build queryable proof state.

7. Migration from winlew.geo.*

Alpha products (GeoPresence) emit winlew.geo.presence.v2, winlew.geo.presence.receipt.v1, winlew.geo.anchor.batch.v2. These predate the Oxyon brand and put the sponsor token's name on the protocol — incorrect under "Oxyon builds, WinLEW rewards." Path:

  1. Read both — canonicalizeSchema() maps legacy → canonical; consumers accept either immediately.
  2. Emit canonical — new emissions use oxyon.geoproof.*.
  3. Optionally dual-emit during transition for older indexers. No on-chain rewrite of historical proofs is needed — they remain valid XYO BWs; only the indexer's schema mapping changes.

8. Conformance

A product is GeoProof-conformant if it: (a) emits events whose schema is canonical (or maps via §7), (b) binds them in valid XYO bound witnesses, (c) passes validateEventShape for base events and the type-specific validators (validateSupersession, validateRevocation, validateKeyRotation) for Phase 1 types, (d) for verifiers, emits receipts whose verdict is EARNED via cryptographic validation (never caller-chosen), (e) for key rotation, produces a dual-signer BW with both old and new keys.

8.1 Conformance Test Vectors

packages/geoproof/vectors/v1.json contains deterministic GeoProof payloads and their canonical XYO dataHash values. Any implementation in any language uses these to verify its hashing matches the reference. Payload hashes ARE deterministic (XYO sorts and canonicalizes fields). BW hashes and signatures are NOT deterministic (random nonce). The vectors cover payload-level hashing only.

To regenerate (only when intentionally changing the hashing algorithm):

node packages/geoproof/src/vectors.gen.ts
# then bump version in vectors/v1.json and create a migration map

9. Open questions (verify before hardening)

  • Exact @xyo-network package + API versions per product (XYO moved fast during the alpha build — confirm, don't assume).
  • Whether subject should be a typed union (address | did | contentHash) vs string.
  • Receipt score model + who the authoritative verifiers are (authority allow-list).
  • XL1 anchor cadence + finalized-vs-latest read semantics for the indexer.