{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://allkard.com/schema/v1.json",
  "title": "kard.json (allkard/1.0)",
  "description": "Structured metadata for a .kard archive member. Witness fields are authoritative; verifiers MUST NOT assume a fixed witness host.",
  "type": "object",
  "additionalProperties": false,
  "required": ["format", "id", "class", "title", "issued_at", "front", "back", "custody", "witness"],
  "properties": {
    "format": {
      "description": "Specification revision implemented by this document.",
      "const": "allkard/1.0"
    },
    "id": {
      "description": "Stable identifier for this issuance. A transfer is a new document with a new id.",
      "type": "string",
      "format": "uuid"
    },
    "class": {
      "description": "memory cards are non-transferable personal records. provenance cards are transferable and carry an append-only chain of custody.",
      "enum": ["memory", "provenance"]
    },
    "title": {
      "type": "string",
      "minLength": 1,
      "maxLength": 160
    },
    "summary": {
      "type": "string",
      "minLength": 1,
      "maxLength": 600
    },
    "issued_at": {
      "description": "UTC timestamp of this issuance.",
      "type": "string",
      "format": "date-time"
    },
    "front": {
      "type": "object",
      "additionalProperties": false,
      "required": ["material_tier", "patina_level", "hero_asset"],
      "properties": {
        "material_tier": {
          "description": "Physical or rendered finish of the card face.",
          "enum": ["core", "alloy", "prism", "apex"]
        },
        "patina_level": {
          "description": "Wear or age, from untouched (0) to fully patinated (10).",
          "type": "integer",
          "minimum": 0,
          "maximum": 10
        },
        "hero_asset": {
          "$ref": "#/$defs/assetPath"
        },
        "logo_asset": {
          "$ref": "#/$defs/assetPath"
        },
        "inscription": {
          "type": "string",
          "minLength": 1,
          "maxLength": 280
        },
        "edition": {
          "type": "object",
          "additionalProperties": false,
          "required": ["label", "number", "of"],
          "properties": {
            "label": {
              "type": "string",
              "minLength": 1,
              "maxLength": 80
            },
            "number": {
              "type": "integer",
              "minimum": 1
            },
            "of": {
              "type": "integer",
              "minimum": 1
            }
          }
        }
      }
    },
    "back": {
      "type": "object",
      "additionalProperties": false,
      "required": ["chapters"],
      "properties": {
        "presence": {
          "description": "Short attestation of where and how the card was present.",
          "type": "object",
          "additionalProperties": false,
          "required": ["kind", "statement", "attested_at"],
          "properties": {
            "kind": {
              "enum": ["witnessed", "self", "device"]
            },
            "statement": {
              "type": "string",
              "minLength": 1,
              "maxLength": 600
            },
            "place": {
              "type": "string",
              "minLength": 1,
              "maxLength": 160
            },
            "attestor": {
              "type": "string",
              "minLength": 1,
              "maxLength": 160
            },
            "attested_at": {
              "type": "string",
              "format": "date-time"
            }
          }
        },
        "chapters": {
          "description": "Append-only narrative. sequence must be contiguous starting at 1. Earlier chapters are retained in later issuances.",
          "type": "array",
          "maxItems": 100,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["id", "sequence", "occurred_at", "title"],
            "properties": {
              "id": {
                "type": "string",
                "pattern": "^[a-z0-9][a-z0-9_-]{0,63}$"
              },
              "sequence": {
                "type": "integer",
                "minimum": 1
              },
              "occurred_at": {
                "type": "string",
                "format": "date-time"
              },
              "title": {
                "type": "string",
                "minLength": 1,
                "maxLength": 160
              },
              "body": {
                "type": "string",
                "minLength": 1,
                "maxLength": 2000
              },
              "asset": {
                "$ref": "#/$defs/assetPath"
              }
            }
          }
        },
        "provenance_chain": {
          "description": "Append-only custody log. Required for class provenance and forbidden for class memory. epoch equals the zero-based index.",
          "type": "array",
          "minItems": 1,
          "maxItems": 1000,
          "items": {
            "type": "object",
            "additionalProperties": false,
            "required": ["epoch", "holder", "acquired_at"],
            "properties": {
              "epoch": {
                "type": "integer",
                "minimum": 0
              },
              "holder": {
                "type": "string",
                "minLength": 1,
                "maxLength": 200
              },
              "acquired_at": {
                "type": "string",
                "format": "date-time"
              },
              "note": {
                "type": "string",
                "minLength": 1,
                "maxLength": 500
              }
            }
          }
        }
      }
    },
    "custody": {
      "type": "object",
      "additionalProperties": false,
      "required": ["transferable", "transfer_epoch", "holder"],
      "properties": {
        "transferable": {
          "type": "boolean"
        },
        "transfer_epoch": {
          "description": "Monotonic issuance counter. Memory cards are fixed at 0. Provenance cards equal the last provenance_chain epoch.",
          "type": "integer",
          "minimum": 0
        },
        "holder": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "status_endpoint": {
          "description": "HTTPS endpoint returning JSON { current_epoch: integer }. Compared with transfer_epoch when a verifier opts into an online check.",
          "type": "string",
          "pattern": "^https://[^\\s]+$",
          "maxLength": 500
        }
      }
    },
    "witness": {
      "description": "The authority that signed this issuance. Keys are discovered from witness.keys_discovery, never from a hardcoded host.",
      "type": "object",
      "additionalProperties": false,
      "required": ["authority", "key_id", "keys_discovery", "signed_at"],
      "properties": {
        "authority": {
          "description": "HTTPS origin of the witness (host may be hierarchical, e.g. a regional or franchise node). Empty path only; used to bind keys_discovery.",
          "type": "string",
          "pattern": "^https://[^\\s/]+$",
          "maxLength": 200
        },
        "key_id": {
          "type": "string",
          "pattern": "^[A-Za-z0-9._:-]{1,128}$"
        },
        "keys_discovery": {
          "description": "Absolute URL of the witness public-key document. The path must be /.well-known/witness-keys.json.",
          "type": "string",
          "pattern": "^https://[^\\s]+$",
          "maxLength": 500
        },
        "signed_at": {
          "type": "string",
          "format": "date-time"
        }
      }
    }
  },
  "allOf": [
    {
      "if": {
        "required": ["class"],
        "properties": {
          "class": { "const": "memory" }
        }
      },
      "then": {
        "properties": {
          "custody": {
            "type": "object",
            "properties": {
              "transferable": { "const": false },
              "transfer_epoch": { "const": 0 }
            }
          },
          "back": {
            "type": "object",
            "properties": {
              "provenance_chain": false
            }
          }
        }
      }
    },
    {
      "if": {
        "required": ["class"],
        "properties": {
          "class": { "const": "provenance" }
        }
      },
      "then": {
        "properties": {
          "custody": {
            "type": "object",
            "properties": {
              "transferable": { "const": true }
            }
          },
          "back": {
            "type": "object",
            "required": ["provenance_chain"],
            "properties": {
              "provenance_chain": {
                "type": "array",
                "minItems": 1
              }
            }
          }
        }
      }
    }
  ],
  "$defs": {
    "assetPath": {
      "description": "Archive-relative media path. Dot segments are additionally rejected by the SDK.",
      "type": "string",
      "pattern": "^assets/[a-zA-Z0-9_./-]+$",
      "minLength": 8,
      "maxLength": 240
    }
  }
}
