{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://chris-hongye-yang.com/assets/data/linkage-hub/schema.json",
  "title": "Open Accounting–Labor Data Linkage Hub public-safe record schema",
  "description": "Generic schema for independently licensed entity inputs, generated candidate-audit rows, and separate adjudication decisions. It contains no proprietary source values.",
  "type": "object",
  "required": ["releaseVersion", "maturity", "sources", "targets", "candidates", "decisions"],
  "properties": {
    "releaseVersion": {
      "const": "0.1.0"
    },
    "maturity": {
      "const": "prototype"
    },
    "sources": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/sourceEntity"
      }
    },
    "targets": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/targetEntity"
      }
    },
    "candidates": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/candidate"
      }
    },
    "decisions": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/decision"
      }
    }
  },
  "additionalProperties": false,
  "$defs": {
    "sourceEntity": {
      "type": "object",
      "required": ["id", "name", "year"],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "description": "Source-controlled identifier. Public examples must use the SYN- prefix."
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "description": "Original entity name retained for audit."
        },
        "year": {
          "type": "integer",
          "minimum": 1900,
          "maximum": 2200
        },
        "domain": {
          "type": "string",
          "description": "Optional authorized hostname or URL signal. The reference implementation extracts and normalizes the host; public examples use reserved .example domains."
        },
        "country": {
          "type": "string",
          "minLength": 2,
          "maxLength": 3
        }
      },
      "additionalProperties": false
    },
    "targetEntity": {
      "type": "object",
      "required": ["id", "name", "year", "targetLevel"],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1
        },
        "name": {
          "type": "string",
          "minLength": 1
        },
        "year": {
          "type": "integer",
          "minimum": 1900,
          "maximum": 2200
        },
        "domain": {
          "type": "string",
          "description": "Optional authorized hostname or URL signal."
        },
        "country": {
          "type": "string",
          "minLength": 2,
          "maxLength": 3
        },
        "validFrom": {
          "type": "integer"
        },
        "validTo": {
          "type": "integer"
        },
        "parentId": {
          "type": "string"
        },
        "targetLevel": {
          "enum": ["company", "ultimate-parent", "other"]
        }
      },
      "additionalProperties": false
    },
    "candidate": {
      "type": "object",
      "required": ["sourceId", "targetId", "sourceYear", "targetLevel", "reasons", "features"],
      "properties": {
        "sourceId": {
          "type": "string"
        },
        "targetId": {
          "type": "string"
        },
        "sourceYear": {
          "type": "integer"
        },
        "targetParentId": {
          "type": "string"
        },
        "targetLevel": {
          "enum": ["company", "ultimate-parent", "other"]
        },
        "reasons": {
          "type": "array",
          "items": {
            "enum": ["normalized-name-exact", "domain-exact", "name-token-block", "authorized-identifier", "other-documented-rule"]
          },
          "minItems": 1,
          "uniqueItems": true
        },
        "features": {
          "$ref": "#/$defs/features"
        },
        "score": {
          "type": "number",
          "minimum": 0,
          "maximum": 1,
          "description": "Optional decomposed candidate score. It is not a ground-truth label or a final decision."
        },
        "candidateRank": {
          "type": "integer",
          "minimum": 1
        },
        "marginToNext": {
          "type": ["number", "null"]
        }
      },
      "additionalProperties": false
    },
    "decision": {
      "type": "object",
      "required": [
        "sourceId",
        "sourceYear",
        "decisionStatus",
        "confidenceTier",
        "reviewReason",
        "errorCategory"
      ],
      "properties": {
        "sourceId": {
          "type": "string"
        },
        "sourceYear": {
          "type": "integer"
        },
        "decisionStatus": {
          "enum": ["accepted", "rejected", "unresolved", "no-candidate"]
        },
        "acceptedTargetId": {
          "type": "string"
        },
        "acceptedTargetLevel": {
          "enum": ["company", "ultimate-parent", "other"]
        },
        "validFrom": {
          "type": "integer"
        },
        "validTo": {
          "type": "integer"
        },
        "confidenceTier": {
          "enum": ["exact", "rule-based", "fuzzy-reviewed", "unresolved", "no-candidate", "not-assigned"]
        },
        "reviewReason": {
          "type": "string",
          "minLength": 1
        },
        "errorCategory": {
          "enum": [
            "legal-name-variation",
            "abbreviation-token-loss",
            "parent-subsidiary",
            "merger-spinoff",
            "historical-name-change",
            "stale-temporal-link",
            "duplicate-source-entity",
            "common-name-collision",
            "many-to-one",
            "one-to-many",
            "geography-domain-conflict",
            "source-missingness",
            "none",
            "not-adjudicated"
          ]
        }
      },
      "allOf": [
        {
          "if": {
            "properties": {
              "decisionStatus": {
                "const": "accepted"
              }
            },
            "required": ["decisionStatus"]
          },
          "then": {
            "required": ["acceptedTargetId", "acceptedTargetLevel"]
          },
          "else": {
            "not": {
              "anyOf": [
                {
                  "required": ["acceptedTargetId"]
                },
                {
                  "required": ["acceptedTargetLevel"]
                }
              ]
            }
          }
        }
      ],
      "additionalProperties": false
    },
    "features": {
      "type": "object",
      "required": [
        "normalizedNameExact",
        "nameTokenSimilarity",
        "domainExact",
        "countryEvidence",
        "temporalEvidence"
      ],
      "properties": {
        "normalizedNameExact": {
          "type": "boolean"
        },
        "nameTokenSimilarity": {
          "type": "number",
          "minimum": 0,
          "maximum": 1
        },
        "domainExact": {
          "type": "boolean"
        },
        "countryEvidence": {
          "enum": ["match", "conflict", "missing"]
        },
        "temporalEvidence": {
          "enum": ["match", "conflict", "missing"]
        }
      },
      "additionalProperties": false
    }
  }
}
