{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "urn:bitunlock:schema:entitlement:v1",
  "title": "BitUnlock entitlement document v1",
  "description": "The content of the canonical service-signed entitlement Nostr event (kind 30078, d tag bitunlock:entitlement:v1:<fulfillmentId>): a durable, offline-verifiable receipt that a buyer pubkey owns a completed purchase, bound to the settled Lightning payment hashes.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "schemaVersion",
    "protocolVersion",
    "accessPolicy",
    "status",
    "tenantId",
    "sellerPubkey",
    "productCoordinate",
    "buyerPubkey",
    "orderId",
    "fulfillmentId",
    "claimEpoch",
    "paymentHashes",
    "issuedAt"
  ],
  "properties": {
    "schemaVersion": {
      "const": 1
    },
    "protocolVersion": {
      "const": "seller-unlock-service-v1"
    },
    "accessPolicy": {
      "description": "'perpetual-v1' never lapses. A term-v1 object is checkable offline via expiresAt. Revocation is never embedded here — mutating a signed event's content would invalidate its own signature — so a relying party must combine this field with a live entitlement-status check to learn about seller-initiated revocation.",
      "oneOf": [
        {
          "const": "perpetual-v1"
        },
        {
          "type": "object",
          "additionalProperties": false,
          "required": [
            "kind",
            "expiresAt"
          ],
          "properties": {
            "kind": {
              "const": "term-v1"
            },
            "expiresAt": {
              "type": "integer",
              "minimum": 1
            },
            "renewalOfFulfillmentId": {
              "type": "string",
              "minLength": 12,
              "maxLength": 96
            }
          }
        }
      ]
    },
    "status": {
      "const": "active"
    },
    "tenantId": {
      "type": "string",
      "minLength": 12,
      "maxLength": 96
    },
    "sellerPubkey": {
      "$ref": "#/$defs/hex64"
    },
    "productCoordinate": {
      "type": "string",
      "pattern": "^30078:[0-9a-f]{64}:.+$"
    },
    "buyerPubkey": {
      "$ref": "#/$defs/hex64"
    },
    "orderId": {
      "type": "string",
      "minLength": 1,
      "maxLength": 128,
      "pattern": "^order_[A-Za-z0-9_-]{12,80}$"
    },
    "fulfillmentId": {
      "type": "string",
      "minLength": 12,
      "maxLength": 96
    },
    "claimEpoch": {
      "type": "integer",
      "minimum": 0
    },
    "paymentHashes": {
      "type": "array",
      "minItems": 1,
      "maxItems": 8,
      "items": {
        "$ref": "#/$defs/hex64"
      }
    },
    "issuedAt": {
      "type": "integer",
      "minimum": 1
    }
  },
  "$defs": {
    "hex64": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$"
    }
  }
}
