{
  "$id": "https://gryd.world/protocol/schemas/common.json",
  "$comment": "Shared field definitions for Locus Protocol v3 payloads. See SPEC.md §6.",
  "$defs": {
    "lat": { "type": "number", "minimum": -90, "maximum": 90 },
    "lng": { "type": "number", "minimum": -180, "maximum": 180 },
    "geohash": {
      "type": "string",
      "pattern": "^[0-9a-f]{15}$",
      "description": "H3 cell ID at resolution 7 (field name is historical)."
    },
    "geoIPv6": {
      "type": "string",
      "pattern": "^2001:db8:locus:[a-z]{2}:[a-z]{2}:[0-9a-f]{8}:[0-9a-f]{4}:[0-9a-f]{8}::1$",
      "description": "Geo-IPv6 address per SPEC.md §6.3."
    },
    "cityPrefix": {
      "type": "string",
      "pattern": "^2001:db8:locus:[a-z]{2}:[a-z]{2}:[0-9a-f]{8}::/32$"
    },
    "pubkey": {
      "type": "string",
      "pattern": "^(02|03)[0-9a-fA-F]{64}$",
      "description": "Compressed SEC public key, hex."
    },
    "bsvAddress": {
      "type": "string",
      "pattern": "^1[1-9A-HJ-NP-Za-km-z]{25,34}$",
      "description": "Base58check mainnet P2PKH address."
    },
    "nonce": { "type": "string", "pattern": "^[0-9a-f]{4}$" },
    "ts": { "type": "integer", "minimum": 0, "description": "Unix seconds." },
    "txid": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
    "addressPrefix": {
      "type": "string",
      "enum": ["/128", "/64", "/32", "/16", "/8", "/4", "/2", "/1"]
    },
    "pinType": { "type": "string", "enum": ["presence", "object", "agent", "imported_nft"] },
    "presenceProof": {
      "type": "object",
      "description": "Optional in v3 (SPEC.md §8).",
      "required": ["pk", "nonce", "hash", "lat", "lng", "ts"],
      "properties": {
        "pk": { "$ref": "#/$defs/pubkey" },
        "nonce": { "type": "string" },
        "hash": { "type": "string", "pattern": "^[0-9a-f]{64}$" },
        "lat": { "$ref": "#/$defs/lat" },
        "lng": { "$ref": "#/$defs/lng" },
        "ts": { "$ref": "#/$defs/ts" }
      },
      "additionalProperties": true
    }
  }
}
