{
  "lexicon": 1,
  "id": "dev.atlocally.tap",
  "defs": {
    "main": {
      "type": "procedure",
      "description": "Verify a tap and issue a presence proof. Requires an AT Protocol service auth token bound to aud={platform-did} and lxm=dev.atlocally.tap.",
      "input": {
        "encoding": "application/json",
        "schema": {
          "type": "object",
          "required": ["uid", "ctr", "cmac"],
          "properties": {
            "uid": {
              "type": "string",
              "description": "Tag UID (14 hex chars)."
            },
            "ctr": {
              "type": "integer",
              "description": "Tap counter."
            },
            "cmac": {
              "type": "string",
              "description": "Truncated AES-CMAC (16 hex chars)."
            }
          }
        }
      },
      "output": {
        "encoding": "application/json",
        "schema": {
          "type": "object",
          "required": ["proof", "did", "location", "tappedAt"],
          "properties": {
            "proof": {
              "type": "string",
              "description": "Presence proof JWT (ES256-signed)."
            },
            "did": {
              "type": "string",
              "format": "did",
              "description": "Visitor DID verified from the service auth token."
            },
            "location": {
              "type": "ref",
              "ref": "dev.atlocally.defs#locationView"
            },
            "tappedAt": {
              "type": "string",
              "format": "datetime",
              "description": "ISO 8601 tap timestamp (server-set)."
            }
          }
        }
      },
      "errors": [
        { "name": "InvalidCmac", "description": "CMAC verification failed." },
        { "name": "UnknownTag", "description": "Tag UID is not registered." },
        { "name": "StaleCounter", "description": "Counter is below the high-water mark window." },
        { "name": "Replay", "description": "Counter has already been seen." },
        { "name": "RateLimitExceeded" }
      ]
    }
  }
}
