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
- One proof model across all products — a presence proof from GeoPresence and a signing proof from GeoWallet are the same shape, verifiable by GeoJustice.
- Built on XYO, not reinventing it — GeoProof events ARE XYO payloads, carried in XYO bound witnesses. GeoProof does not define new crypto.
- Anchored on XL1 — proofs are batch-anchored for durable, ordered finality.
- Brand-correct namespace — schemas live under
oxyon.geoproof.*, never the sponsor token's name. (Alpha products currently emitwinlew.geo.*; §7.) - 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-builderand@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:
- Cryptographic (who/whether-tampered) — delegated to
@xyo-network/boundwitness-validatorover the carrying BW: signatures valid, hashes match, chain consistent. - Semantic / trust — GeoJustice applies policy: schema validity
(
validateEventShape), plausibility (e.g. location accuracy, velocity between presence proofs), authority allow-lists, fraud signals → averdictand a0..1score, emitted as areceiptlinked via$sourcesto 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:
- Read both —
canonicalizeSchema()maps legacy → canonical; consumers accept either immediately. - Emit canonical — new emissions use
oxyon.geoproof.*. - 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-networkpackage + API versions per product (XYO moved fast during the alpha build — confirm, don't assume). - Whether
subjectshould 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.