{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://veydrin.codeberg.page/protocols/vcn-protocol/vcn-packet-v1.4.schema.json",
  "title": "VCN packet envelope (v1.4)",
  "description": "A signed VCN packet. Every field except signature and transit is covered by the emitter's Ed25519 signature over the canonical form defined in the VCN Protocol Spec.",
  "type": "object",
  "required": [
    "vcn_version",
    "source_app",
    "source_node",
    "packet_id",
    "packet_type",
    "area_tag",
    "timestamp",
    "ttl",
    "payload",
    "signature"
  ],
  "properties": {
    "vcn_version": { "type": "string", "const": "1.0" },
    "source_app": {
      "type": "string",
      "description": "Registered lowercase application slug from the source_app registry (for example melisae, eluvorim).",
      "pattern": "^[a-z][a-z0-9]*$",
      "maxLength": 64
    },
    "source_node": {
      "type": "string",
      "description": "Base64-URL Ed25519 public key, 43 characters, no padding.",
      "pattern": "^[A-Za-z0-9_-]{43}$"
    },
    "packet_id": {
      "type": "string",
      "description": "UUID v4, unique per packet.",
      "pattern": "^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$"
    },
    "packet_type": {
      "type": "string",
      "description": "Application-defined type mapped to a delivery handler. Forwarding is independent of type.",
      "minLength": 1,
      "maxLength": 64
    },
    "area_tag": {
      "type": "string",
      "description": "Routing tag: a geohash cell, a named area, or a channel such as _dm, _org_{slug}, or _sync_{id}.",
      "pattern": "^[a-z0-9_-]{1,64}$"
    },
    "timestamp": {
      "type": "integer",
      "description": "Unix milliseconds UTC at emission.",
      "minimum": 0
    },
    "ttl": {
      "type": "integer",
      "description": "Original hop budget and time-to-live in hours. Immutable and signed.",
      "minimum": 0,
      "maximum": 720
    },
    "clock_asserted": {
      "type": "boolean",
      "description": "Whether the emitter vouches for timestamp (v1.4). Absent on pre-v1.4 packets."
    },
    "enc_key": {
      "type": ["string", "null"],
      "description": "Sender's Base64-URL X25519 public key (43 characters, no padding), or null.",
      "pattern": "^[A-Za-z0-9_-]{43}$"
    },
    "location": {
      "type": "object",
      "properties": {
        "geohash": { "type": "string" },
        "geohash_precision": { "type": "integer" },
        "coords_available": { "type": "boolean" }
      },
      "additionalProperties": true
    },
    "deep_link": { "type": ["string", "null"] },
    "payload": { "type": "object" },
    "transit": {
      "type": "object",
      "description": "Mutable, unsigned per-hop state (v1.4). Excluded from the canonical form.",
      "required": ["hops_remaining", "elapsed_ms"],
      "properties": {
        "hops_remaining": { "type": "integer", "minimum": 0 },
        "elapsed_ms": { "type": "integer", "minimum": 0 },
        "prev_node": { "type": "string", "pattern": "^[A-Za-z0-9_-]{43}$" }
      },
      "additionalProperties": false
    },
    "signature": {
      "type": "string",
      "description": "Base64-URL Ed25519 signature, 86 characters, no padding.",
      "pattern": "^[A-Za-z0-9_-]{86}$"
    }
  },
  "additionalProperties": false
}
