{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://golfsga.com/sga-ois/schema/0.1/bay-certificate.schema.json",
  "title": "SGA-OIS bay certificate",
  "description": "SGA's signed assertion that a bay met a certification tier. It asserts a TIER and nothing more: what the tier REQUIRES lives in the bundle, so raising a floor does not mean reissuing every certificate in the field. It is deliberately not a feature key -- a credential that unlocks capability creates an incentive to crack it, while one that asserts a fact the platform re-derives at ingest does not. The authoritative check is server-side; this exists so an operator finds out at the bay while a cable is still reachable.",
  "type": "object",
  "required": [
    "sga_kind",
    "bay_id",
    "tier",
    "issued_at",
    "expires_at"
  ],
  "additionalProperties": false,
  "properties": {
    "sga_kind": {
      "const": "bay-certificate",
      "description": "Document type discriminator. Always bay-certificate."
    },
    "bay_id": {
      "$ref": "common.schema.json#/$defs/sgaId",
      "description": "The room this is a claim about. An engine MUST refuse a certificate issued to a different bay. That catches the accident and the casual copy; it does not stop a determined one, and detection of that is server-side."
    },
    "facility_id": {
      "$ref": "common.schema.json#/$defs/sgaId"
    },
    "tier": {
      "type": "string",
      "maxLength": 32,
      "description": "The named tier, resolved against the bundle's tier catalog. A tier the bundle does not define enforces nothing."
    },
    "issued_at": {
      "$ref": "common.schema.json#/$defs/timestamp"
    },
    "expires_at": {
      "$ref": "common.schema.json#/$defs/timestamp",
      "description": "REQUIRED. A credential that never lapses is one nobody has to re-earn. What happens AROUND this date -- how much grace, and the reminder schedule -- is policy and lives in the bundle's lapse_policy, so SGA can change it without reissuing every certificate in the field."
    },
    "profile_hash": {
      "$ref": "common.schema.json#/$defs/digest",
      "description": "The bay profile this was issued against, so a later profile can be compared with the one certification actually saw."
    },
    "certified_devices": {
      "type": "array",
      "description": "The equipment that EARNED the tier, as certification found it. This is what makes a certified bay's level stable rather than something that moves with whatever is plugged in: the question at round start is not whether some device meets the floor, it is whether the equipment that earned this certification is still present, still attesting and still on conforming firmware. A guest's device joining is not a shortfall of any kind.",
      "items": {
        "type": "object",
        "required": [
          "device_id",
          "attestation_tier"
        ],
        "additionalProperties": false,
        "properties": {
          "device_id": {
            "$ref": "common.schema.json#/$defs/sgaId"
          },
          "model": {
            "$ref": "common.schema.json#/$defs/modelName",
            "description": "Model exactly as it appears in that device's capability descriptor. Matching is exact: a certificate names the equipment that was actually assessed, not a family it resembles."
          },
          "attestation_tier": {
            "$ref": "common.schema.json#/$defs/attestationTier"
          },
          "firmware_digest": {
            "$ref": "common.schema.json#/$defs/digest",
            "description": "Pins the build that was assessed. A firmware change is the ordinary way a trust chain breaks with nobody touching hardware, so a changed digest is a shortfall even at an unchanged attestation tier."
          },
          "calibration_expires_at": {
            "$ref": "common.schema.json#/$defs/timestamp",
            "description": "The lapse nobody causes. MUST be warned about in advance -- announcing it on the day it happens is announcing it too late to book a technician."
          }
        },
        "patternProperties": {
          "^x-[a-z0-9_-]+\\.": {}
        }
      }
    },
    "issuer_key_id": {
      "type": "string",
      "maxLength": 64,
      "description": "Identifies the SGA signing key, so a verifier can select the right public key and so keys can be rotated without invalidating certificates already in the field."
    },
    "signature": {
      "$ref": "common.schema.json#/$defs/signature"
    }
  },
  "patternProperties": {
    "^x-[a-z0-9_-]+\\.": {}
  }
}
