FAQs.
Plain-language answers about what Octet does and why. Looking for integration details, code, or the proof format? Switch to For developers above.
The Octet SDK runs on the device. It learns from inertial sensors and RF. It generates a proof of location from those signals, then evaluates a policy you defined against that proof, and returns a signed YES or NO with a chain of attestations behind it. No coordinates leave the device. Your verifier only needs the device's enrolled public key and the platform-attestation roots.
The basics
What is Octet?
Octet proves where a device is. An app asks a question: is this device in the United States? It gets back a yes or a no, with proof attached. The answer comes from where the device is, not from what it says. The proof is made on the device, and anyone can check it with a free tool, without asking Octet.
What problem does this solve?
The internet has a clock and no compass. Applications can prove what time it is: every server syncs to atomic clocks, every transaction carries a timestamp, and both sides accept it as fact. They cannot prove where an action occurs or where a user is. For location there are only claims: GPS can be faked with free software, a VPN hides the network address, a typed-in address says whatever was typed. Octet replaces the claim with a proof.
Location, if proven, offers a unique way to certify physical presence. A bank wants to know whether the person logging in is the account holder or a thief with the same password. The credentials are identical either way, but the thief is never in the same place as the real user. A platform wants to know whether a thousand new accounts are a thousand people or one operator. Accounts copy for free. A physical presence does not. A platform wants to know whether the law allows a trade to be executed from a given jurisdiction. That turns on the country the customer is in, and the usual way of checking (IP address) gets it wrong: geolocation databases asked about the same network address disagree by 620 kilometers on average. Each of these answers rests on a physical fact. Octet proves the fact.
Why can't apps just use GPS?
GPS tells a device where it is. It does not tell anyone else that the device is being honest. Spoofing is a consumer product category: Fake GPS Location and Fake GPS GO on Android, iAnyGo on iPhone with no jailbreak required, and dozens more. GPS is an input the device reads. It is not evidence.
What does "proof" actually mean here?
A short piece of data, signed by the device's own hardware, answering one question about one device at one moment. Alter anything in it afterwards and the check fails. It cannot be replayed. Months later, anyone can pull it out and verify it again.
Your privacy
Is this biometric?
No. Octet never reads a face, a fingerprint, or a voice. Biometrics answer who. Octet answers where. The proof says a device was at a place at a time.
Does Octet track me?
No. The app defines one question in advance: is this device outside the United States? The answer comes back yes or no. No coordinates leave the device, and none are stored anywhere, by anyone. What a proof keeps is its own record: the sealed reference, the answer, the condition of the device at the time. The answer persists. The position does not.
How can you prove a location without revealing it?
The proof carries a sealed reference to the location, made on the device. Whoever checks the proof can confirm the device committed to one place and cannot swap in another later. They cannot read the coordinates out of it. The coordinates stay on the device. The checker learns the answer to the question and nothing else.
Does Octet ask for new permissions on my phone?
No. Octet runs inside an app you chose to install and reads only what that app already has your permission to read. Nothing extra is requested.
What data does Octet store, and for how long?
Octet never holds coordinates. A proof carries a sealed reference, the answer, and the device's attestation: a record of the answer at the precision the app asked, never of your position. If an app routes proofs through Octet's servers for checking, each proof is held for at most 24 hours and then deleted. No long-term storage. No backups. Many customers never send a proof to Octet at all.
Where you'll meet it
Where will I encounter Octet?
Inside apps you already use. A trading app confirms you are in a country it can serve before opening your account. Your bank confirms a payment instruction came from where you are, not from someone on another continent holding your password. A delivery platform confirms the courier stood at your door. You see none of it. The checks run while you use the app.
What can a business use it for?
Anywhere a location claim carries money or legal weight. Keeping a regulated product out of countries where it cannot be offered. Catching the login that uses the right password from the wrong continent. Confirming a courier, an engineer, or a shipment was where the record says it was.
Does Octet decide who gets blocked?
No. Octet answers the question. The app decides what to do with the answer. We supply the signal. The app makes the decision.
Can it be fooled?
Can a VPN fool it?
No. A VPN hides a network address. The proof never looks at the network address. Hiding it changes nothing.
What if the phone is jailbroken or rooted?
The proof says so. A device whose security guarantees are broken is reported as broken, and that report is sealed into the proof. The business reading it decides what to accept. Octet describes the device honestly. It does not pretend.
How do I know a proof is genuine? Do I have to trust Octet?
Check it yourself. octet-verify is a free, open-source tool that runs on your own computer. It walks every link in the proof and prints what passed, what failed, and what it did not check. Octet's servers play no part. The hardware underneath is the same secure chip that protects Apple Pay and Google Pay. The signing key is created inside it and cannot be copied out.
How accurate is it?
Each proof states its own precision: country, region, city, or area. A proof can only claim a precision its signals support, and the claimed precision is sealed inside the proof. It cannot be inflated afterwards.
What happens when a proof can't be made?
The answer has three states: yes, no, and indeterminate. Indeterminate means the device could not produce a reliable answer, and the result says why. Octet never manufactures a yes. What the app does next (ask for another form of verification, decline, allow and log) is the app's call.
Does it need an internet connection?
Not to make a proof. Sensing, checking, and signing all happen on the device. One brief online step runs when the app is first set up. Checking a proof works offline too, once the standard reference material is downloaded.
Coverage and comparisons
Which countries does this cover?
Octet works in every country on earth.
Is blocking US users a sanctions issue?
No. Comprehensive sanctions prohibit doing business with a country at all. Restrictions on US or Singapore users are securities and financial regulation: decisions about where a product may be offered. Octet enables both kinds of policy. They are different legal regimes.
For the securities side, what matters under US law is where the purchaser is at the moment of the transaction, not where they live. Variant, a venture fund, lays out the legal reasoning in Onchain Geofencing: A New Path for Tokenized Securities.
What is the difference between the mobile and browser products?
The mobile SDK runs inside iOS and Android apps and produces hardware-signed proofs. The secure chip that makes proof possible can only be reached from a native app. Browsers cannot reach it, so the browser product does a different job: it estimates a visitor's country by machine learning from a wide variety of signals that can be accessed from the browser, returns a confidence score, and flags inconsistencies. The mobile product proves. The browser product estimates. Both have proprietary machine learning at the core.
Does this replace identity checks (KYC)?
No. Identity checks answer who. Octet answers where. Regulated businesses usually need both, side by side.
KYC is the heaviest step in any onboarding flow: documents, a selfie, a wait, and significant numbers of customers lost at every stage. What all that buys is who the customer is and where they reside. It says nothing about where the customer is at the moment of a transaction. A fully verified customer can trade from anywhere on earth, and the file in the compliance folder will not notice.
Pricing, team, and trying it
How much does it cost?
Our pricing is live and transparent at octetproof.com/pricing.
Who is behind Octet?
More on the team is at octetproof.com/team.
Can I try it?
Yes. The mobile SDK is self-serve at sdk.octetproof.com/signup. The browser product is available by request at developer@octetproof.com.
Trust
What do I have to trust, and what can I verify cryptographically?
You can verify three things cryptographically, without trusting Octet at runtime:
-
The signing key sits in hardware on a specific device. On Android we leverage Google Play Integrity that uses a hardware-backed key to attest that the device and app haven't been tampered with; on iOS, Apple App Attest that uses a hardware-backed key in the Secure Enclave to attest a genuine, unmodified version of your app is running on a legitimate Apple device. If either verifies, the signing key is non-extractable and bound to that physical device.
-
Nothing in the proof has been tampered with since it was signed. Every stage signature in our eight-stage attestation chain is replayable. If any field (the verdict, the level, the commitment, the nullifier, the attestation token) was substituted, the chain breaks.
-
The proof has not been replayed. We use nullifiers — a unique, deterministic value derived from a secret that is published when the proof is issued — so we can reject later attempts reusing the same secret by checking whether that nullifier has already been seen.
What you have to trust today:
-
The confidence pipeline that produced the verdict. The SDK is closed-source. The pipeline runs on the device; its inputs are bound into the attestation chain, so you can audit what fed the verdict. What you cannot read today is the code that combined them.
-
The platform-attestation roots. You trust Apple and Google to operate App Attest and Play Integrity as documented. If you would not run Apple Pay or Google Pay on a device, the trust does not apply.
Everything else, you verify with our independent open-source verifier.
Is this trust model going to tighten over time?
Yes. Two paths are explicit:
-
The ZK proofs fill in. A ZK backend is in development. The wire shape is fixed today so the backend can ship into existing deployments without breaking your verifier; you keep the chain you have, and your verification recipe gains one optional check.
-
Audited program hash. We are scoping a published binary hash of the released SDK, a third-party security audit, and a mechanism to bind the audited binary's hash into the proof. The downstream verifier would then check that audited code, not arbitrary code, produced the verdict.
If everything is bound into the attestation chain, why isn't the verdict itself a ZK proof?
Because the verdict is the output of a multi-stage signal pipeline and proving that pipeline ran correctly inside a single ZK circuit is, at today's prover speeds, not performance-feasible on a phone. The architecture treats the chain as a commitment to all inputs and the verdict, signed at the hardware root, plus a ZK payload where the cost is reasonable and the statement is sharp. Over time, more stages can move under ZK. The wire format does not change when they do.
Why should I trust a signed YES if I cannot read the code that produced it?
The proof gives you four cryptographic guarantees (hardware-bound, time-bound, replay-resistant, tamper-evident) and exposes every input the verdict was computed from. What it does not give you is the open code. The path to closing that gap (binary-hash publication, third-party audit, binding the audited hash into the proof) is being scoped; until then, the right framing for your risk team is that Octet is a high-integrity signal you fold into your existing decision model, not a sole authorization root.
What's inside a proof
What exactly does the SDK return?
A self-contained, serialized LocationProof, a binary artifact that an independent verifier can validate offline against your device's enrolled hardware public key and the platform attestation roots (Google for Android, Apple for iOS). No live call back to the device is required, and Octet's servers are not in the trust path.
At a high level, the proof carries three things:
-
A cryptographic commitment to the device's location at a declared precision (e.g. country, region, city, area). The verifier can confirm a claim like "this device was inside region X at time T" without ever learning the exact coordinates — only the device holds the secret needed to "open" the commitment to a specific value.
-
Hardware-rooted attestations. Each step in the proof pipeline is signed by hardware-backed keys. On Android these chain to Google's hardware-attestation root; on iOS to Apple's. The proof records which security tier was actually used (a dedicated secure element when available, otherwise the device's trusted execution environment).
-
Integrity context. A spoofing-detection assessment, freshness markers, a single-use anti-replay token, and in continuous-monitoring mode a link to the previous proof in the chain. These let the verifier confirm the proof is fresh, hasn't been replayed, and was generated from signals the SDK judged trustworthy.
The verifier does not learn the raw (latitude, longitude, altitude), which never leave the device. Instead the proof carries a commitment: a sealed cryptographic reference to the location. The verifier can confirm the device committed to one specific place and cannot later swap in a different one, but cannot read the coordinates from the commitment itself.
What is the eight-stage attestation chain doing?
Every step of the proof pipeline, from raw signal capture, through anti-spoof analysis, location commitment, and final assembly, is signed by a hardware-backed key inside the device. Each signature also binds the result of the previous step, so the whole pipeline forms a single tamper-evident chain that ends in one final signature committing to every input that produced the proof.
The eight-stage attestation chain delivers:
Tamper evidence. If anything in the proof is altered after generation, coordinates, timestamps, attestation results, anything, at least one stage signature stops verifying, and every signature downstream of that point stops verifying too. The independent verifier catches this and reports the failing stage by name. There is no "silent pass" mode.
Hardware grounding. The keys signing each stage are non-exportable and hardware-protected. On Android they live in the platform Keystore (StrongBox or TEE, depending on the device) and chain to Google's hardware-attestation root; on iOS they're guarded by the Secure Enclave and chain to Apple's App Attest infrastructure. A compromised app process cannot mint a signature without going through the secure element.
End-to-end coverage. The chain ends with a final assembly step that signs over the proof's identifying metadata along with the rolling hash of all earlier stages. That final signature is what the transport-layer signature ties to, so verification of the outer envelope implies verification of the entire pipeline.
The chain is auditable: our independent verifier walks it step by step and prints PASS / FAIL for each link in the chain, plus the linkage between them. Any post-hoc tampering produces a specific, named failure that anyone can reproduce against the published proof bytes.
What does the ProofLevel actually mean?
ProofLevel is a tiered precision-and-confidence ladder attached to every proof. A low level says something deliberately weak ("this device is somewhere on the planet, and we're confident about that"); a high level says something much stronger ("this device is inside a small volume and has stayed there continuously across multiple proofs"). Intermediate levels correspond to typical real-world claims: country-scale, region-scale, city-scale, and so on.
Two properties make that ladder trustworthy:
-
Higher levels require more signal agreement. Each rung up the ladder demands stricter consistency across the device's sensors, GNSS quality, anti-spoof checks, and (at the top) continuous-monitoring history. A proof can only claim a level its underlying signals actually support.
-
The claimed level is cryptographically bound into the proof. It travels inside a signed stage of the attestation chain, alongside the inputs that produced it. A verifier rejecting a proof whose level was tampered with is a planned check in the verification spec; today's verifier explicitly reports which checks are deferred so you always know what's been validated and what hasn't.
The numeric thresholds behind each rung are part of the SDK's policy configuration, not the proof format. That means the meaning of "city-scale confidence" is stable across releases — if we tighten the thresholds in a future SDK, older proofs continue to verify against the policy they were generated under.
Why don't you send coordinates?
-
You don't need them. The verifier needs to know whether the device satisfies your predicate. The predicate evaluates on-device. You receive the yes/no plus the commitment. The commitment is binding: the device cannot later open it to different coordinates without breaking ECDSA-P256 or stealing the hardware key.
-
Coordinates are a liability. If you don't process them, you don't store them, you don't have a GDPR exposure on them, you don't have a breach risk on them. The wire never carried them. Octet does not hold them either; the blinding factor is volatile-memory-only on the device.
What's the difference between the position commitment and the nullifier?
The commitment is a hash of coordinates plus a fresh random blinding factor. It is binding (the device cannot substitute coordinates after the fact) and hiding (no one outside the device can recover coordinates from it). It exists so future ZK proofs over the same coordinates can chain off a stable reference.
The nullifier is a per-proof identifier deterministically derived from the commitment and proof context. You record it in an anti-replay set. Two distinct genuine proofs from the same physical place at the same instant still produce different nullifiers, because the commitment is fresh-blinded per proof. So the de-dup is strictly anti-replay and does not unlink real proofs from the same location.
Verification and integration
How do I verify a proof?
Proofs are self-contained — Octet is never on the verification path. Verification works today: we ship an independent open-source verifier you run entirely on your own infrastructure, and our backend is treated as untrusted.
Use octet-verify, our independent open-source reference verifier.
A single-binary Rust CLI that walks every check in the verification spec and prints PASS / FAIL / NOT-CHECKED per item. The NOT-CHECKED lines are an intentional transparency feature: the verifier names any check the current spec version doesn't yet cover — today, rooting the attestation chain back to Google's / Apple's CA, and the ZK layer (in development) — rather than passing it silently. So a "valid" verdict always tells you exactly what was, and wasn't, validated. There are no silent passes. Drop it into CI or run it ad-hoc against a proof file or a backend-pulled proof id. Exit codes are scripting-friendly: 0 valid, 1 invalid (a check failed), 2 usage/IO/decode.
What verification gives you, today. Each PASS line corresponds to a specific guarantee — stage linkage intact, every per-stage signature checks out against the certificate chain carried in the proof, the envelope signature checks out against the enrolled key, the claimed region matches the bound inputs, the proof is fresh and unreplayed.
The ZK layer is additive. When the proving backend ships, your verifier gains one optional check on top of everything above — with no change to the proofs you are already verifying, and no change to the verification you already trust today.
Does Octet hold our verification keys or see our proofs?
Keys. Per-device signing keys are generated and sealed inside the hardware secure element on each device — StrongBox / TEE on Android, Secure Enclave on iOS — and the private half never leaves the chip. Octet has no way to sign on a device's behalf. Revocation and lifecycle are handled at the license layer (revoking a license or a per-device activation), not by manipulating device keys.
Proofs. It depends on where you point the SDK:
-
Off entirely. Leave
proofUploadUrlunset (the default). The SDK generates proofs locally and you handle transport yourself. No upload path runs. -
Octet-hosted (our demo apps). When your app sets
proofUploadUrltohttps://api.octetproof.com, each generated proof is uploaded to our backend. Proofs are held there as an ephemeral verification buffer: at most 24 hours, then permanently deleted. No long-term storage, no backups, no extraction. The buffer exists so a verifier (yours, ours, or any third party's) can pull a proof shortly after it was generated and audit it. Nothing is mined from the proof bytes server-side.
Verification path. When you run our independent open-source reference verifier on your infrastructure, Octet's backend is at most a transport-and-index buffer; it can never affect what a verifier concludes about a proof's authenticity.
What does integration look like in code?
One call. The app invokes the SDK's proof-generation method, naming the claim it wants to back up — typically a region ("is this device inside country US right now?"). The SDK reads available device signals, runs them through the anti-spoof pipeline, hardware-signs the result, and returns a serialized LocationProof together with an inline verdict.
Attach the proof bytes to your existing transaction payload. Your server verifies them locally using the recipe in the previous question. Octet is never on this path.
We supply the signal. You make the decision.
How do I write a policy?
You don't write one — you compose one from open-source predicates.
OctetPolicy is a separate, Apache-2.0-licensed library that ships predicate functions you import alongside the SDK. Each predicate takes an OctetLoc from a started SDK session and returns a structured answer to a specific question.
The v1 surface includes:
isOfacComprehensive(loc) — is the device in a country under OFAC comprehensive embargo?
isUS(loc) — is the device in the United States?
isUSState(loc, states) — is the device in one of these US states / territories?
isSingapore(loc) — is the device in Singapore?
Each predicate is implemented in both Swift and Kotlin and is async. Your code calls them; your code decides what to do with the answer (block, warn, log, route, adapt UI). Predicates answer questions, they do not enforce. That separation is deliberate: enforcement belongs in your business logic, where you can compose multiple predicates, combine them with other signals, and audit every decision against your own rules.
Because the library is open source, you can read the exact geometry behind every predicate, pin a version, fork it, or contribute new predicates against the published API.
What happens when the SDK can't generate a proof?
The verdict has three explicit states:
- YES. Predicate satisfied. Proof attached.
- NO. Predicate not satisfied. Proof still attached so you can audit the decision.
- INDETERMINATE. The SDK could not produce a reliable answer. No proof attached, and a ReasonCode accompanies the verdict so you know why.
The SDK never synthesizes a YES it cannot prove. What you do with INDETERMINATE is up to your business logic — block the transaction (recommended for high-stakes irreversible flows), step up to additional verification, route to a higher-risk lane, or allow with logging for pattern analysis.
What work does the SDK do per proof?
The work splits two ways: once per session, once per proof.
Per session. The SDK loads (or generates on first run) the device's hardware-backed signing keys and runs the platform attestation flow: Play Integrity on Android, App Attest on iOS. The resulting integrity assessment is cached for the session and bound into every proof generated within it.
Per proof. The SDK runs its anti-spoof pipeline over the latest sensor window, then performs a handful of hardware-backed signatures: ECDSA-P256 for each stage of the attestation chain, and Ed25519 for the transport envelope. All signing happens inside the secure element; nothing leaves the chip.
Both attestation services are free to use: Google's Play Integrity API has no per-request fee (a default quota of 10,000 requests per day, increasable on request), and Apple's App Attest carries no usage charge.
Adversaries and failure modes
Can someone spoof Octet by faking sensor data?
The cost of fabrication rises with each independent stream that must remain consistent.
To produce a high-level proof for a place the device is not, an attacker must clear several independent walls at once: a hardware device-integrity gate signed by a non-extractable key in the device's secure element; spoof detection; cross-modal coherence between the device's independent sensor streams; and behavioral anomaly detection. A jailbroken or compromised device is reported by the integrity gate and bound into the attestation as a reduced SecurityLevel. The bar is not "spoof one sensor." It is "fabricate a self-consistent multi-modal world, on attested hardware, without tripping any of the layers — simultaneously."
Single-sensor spoofing is cheap. Coherent multi-modal spoofing is hard. Coherent multi-modal spoofing on attested hardware is even harder.
What about rooted devices and jailbroken phones?
On a rooted or jailbroken device, data downstream of the kernel can be modified before it reaches the SDK. The architecture treats this case by reporting it, not by trying to deny it. Your policy decides which ones you accept.
How do I detect replay?
We use nullifiers — a unique, deterministic value derived from a secret that is published when the proof is issued — so we can reject later attempts reusing the same secret by checking whether that nullifier has already been seen.
For session-spanning predicates (device has been inside this region for the last 30 minutes), the previous_token_hash field links each proof to the previous one. Cross-proof verification (checking the linkage as a single audit trail rather than as standalone proofs) is on the SDK roadmap; until it ships, treat each proof as a standalone artifact and ask us about session-spanning use cases directly.
What's in the proof that helps me when fraud happens anyway?
Every input that fed the SDK's verdict is cryptographically bound into the proof. Months later, you — or your security team, or a regulator — can pull a stored proof and inspect:
Device identity context. Which hardware produced the proof, its OS version, and the platform integrity verdict (Play Integrity on Android, App Attest on iOS) at the time of generation.
The spoofing assessment. Not just the boolean verdict, but the confidence summary the SDK used to reach it.
A cryptographic commitment to the device's location. The raw coordinates aren't visible without device cooperation, but the commitment binds the SDK to exactly what was claimed — so you can confront a stored proof with later evidence (witness reports, server logs, billing records) and verify whether they agree.
All of it is hardware-signed and chain-linked, so any post-hoc tampering — by an attacker, by you, or by us — breaks verification. Your audit trail is cryptographic, not log-based, and the verifier that walks it is open-source and runs entirely on your infrastructure.
What's the offline story?
The SDK does not need cloud connectivity to generate a proof. Sensors are on-device. Predicates are on-device. Signing is on-device.
Two caveats. First, the platform-attestation flow has an online step on each platform: Android fetches a Play Integrity token, iOS produces the App Attest attestation object (once per install). Once those are in hand, the per-session assertion (iOS) and the cached integrity verdict (Android) carry the session. Second, your verifier needs the platform-attestation roots to validate the chain; those are static and can be cached.
The verifier itself runs offline. You hold the public key. You hold the platform-attestation roots. You hold the nullifier set. Octet is not on the verification path.
Privacy and compliance
How does Octet handle GDPR?
No raw coordinates leave the device. The device computes whether your predicate is satisfied and emits a yes/no proof. We never collect personal location data. There is no Octet database of user locations to query, secure, or breach. When regulators ask where you store user locations, the answer is: you don't, because the device never reveals them.
The proof itself contains the commitment (a hash, not coordinates), the level, the device attestation, and signal-derived state. None of these are personal-location records.
What does the device actually see?
Sensor streams the host app already has access to: the inertial sensors (accelerometer, gyroscope, magnetometer, barometric pressure), the platform fused-location API (position, accuracy, timestamp, velocity, satellite quality — and, on capable Android handsets, Galileo's authenticated signal where present), the device's observed Wi-Fi and cellular radio environment, and a motion-state classifier outputting STATIONARY / WALKING / DRIVING.
Raw samples are not retained. They are compressed into derived scalars (step rate, fused heading, pressure-altitude) before reaching downstream consumers.
Is the SDK reading anything I'm not telling my users about?
It reads what your host app already has permission to read. The SDK does not request additional permissions beyond what location verification needs. The permissions surface is yours — in your app's privacy disclosure, with your wording. We provide reference language but you own the customer relationship.
Why this and not the alternatives
How is this different from GeoComply, Incognia, Radar, MaxMind?
Those tools are inference layers built on OS-level GPS, IP, Wi-Fi, and cell data. They flag suspicious or inconsistent location signals. They cannot put the device on the map when the device is spoofing GPS, tunneling through a VPN, in an urban canyon, or behind network routing that masks position. They produce a confidence score, not a cryptographic proof.
Octet produces a hardware-signed yes/no against your predicate, bound to a specific device at a specific time, with the full input vector preserved in the chain for audit. The signal is verifiable, not inferred.
Why doesn't Apple or Google ship this?
-
Liability. Once Apple or Google attests that a device's reported location is a fact, that assertion becomes a witness in financial crimes, sanctions enforcement, regulated gambling decisions, insurance disputes. Both companies explicitly disclaim location accuracy in their Maps Platform Terms.
-
Architecture. The OS location stack is designed to infer position from Wi-Fi and cell-tower signals using GPS as an anchor. Without a satellite fix to calibrate them, inferences drift. Telemetry is not cryptographically bound to time, device identity, or specific events.
Octet runs in the app layer using Apple and Google's hardware primitives (Secure Enclave, StrongBox, App Attest, Play Integrity, Keystore) and produces what those primitives enable: signed proof against a developer-defined predicate.
Why does the SDK need to be in a native app and not the browser?
Because the trust comes from the Secure Enclave (iOS) or StrongBox (Android). The browser has no access to either. A browser-based location signal can be useful (server-attested over HTTPS, country-level prior, IP-vs-device variance detection) but it is not the same artifact. We ship a Browser SDK for that use case and a Device SDK for the cryptographic one. The output shapes differ; the trust levels differ. We are explicit about both.
Operational
How are keys rotated and revoked?
Each device enrolls a fresh ECDSA-P256 key at SDK initialization. The key is generated in StrongBox or the Secure Enclave and never leaves the chip. Rotation can be triggered by your server (suspect device, periodic policy), by the SDK (host-app reinstall, OS update affecting key handles), or by the platform (factory reset destroys the key, forcing re-enrollment on first use).
Revocation is a flag on your server's key registry. Proofs signed under a revoked key fail verification at step 1.
The SDK is updated. Is my key still valid?
Yes. The signing key lives in the device's secure hardware (StrongBox, TEE, or Secure Enclave), not in the SDK binary. An SDK version bump replaces application code; it does not touch the key. The handle persists across SDK updates, host-app updates, and OS updates.
Three events do invalidate the key, and the SDK detects all three and triggers a fresh enrollment automatically:
- Factory reset of the device. The platform destroys all hardware-backed keys.
- Uninstall and reinstall of the host app. On most platforms, app removal clears the app's keychain or keystore entries.
- User-initiated "clear app data" on Android, or a Keystore-affecting OS update on certain Android versions.
When the SDK fails to load an existing key, it enrolls a new one and your server is notified of the new public key as part of the next proof. Existing proofs your server has already accepted remain valid; future proofs sign under the new key. No customer-side migration is required.
Can the same proof be verified by multiple parties?
Yes. A proof verified once can be passed to additional verifiers. Each verifier independently runs the recipe with the device's public key. If the proof posts on a public chain, every verifier on that chain consumes the same artifact. The trade-off is latency and public records of timing patterns. The core product does not require blockchain. Customers verify proofs using public keys in their own infrastructure.
What's the SDK's update cadence and back-compat policy?
The wire format is versioned in sdk_version. The proof structure does not change without a version bump. Stages can be filled in (e.g. ZK backend) without changing the chain shape. Older verifiers continue to validate newer proofs at the level they understand. Newer verifiers can extract stronger guarantees from newer proofs. The contract holds across versions.