{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://openeik.org/schemas/0.1/proposed/drawings/signoff.schema.json",
  "$comment": "Proposed for OpenEik 0.2: Part XIV, drawings. Written by hand from the outline of Part XIV, not generated: tools/generate-schemas.mjs keeps this folder and lists none of it in index.json. In 0.1 the file is a kept file; a validator holds it to this schema only when asked for the proposal (@openeik/tools: proposals [\"drawings\"]).",
  "title": "Sign-off",
  "description": "One signer's action on one revision: drawings/issued/<drawing>/signoffs/<n>.json (Part XIV, 14.2, proposed for 0.2), <n> s- and the first 12 hexadecimal digits of the envelope's hash. A DSSE envelope whose payload is an in-toto Statement v1 (statement.schema.json) about the digests of drawing.svg and revision.json, signed over DSSE's pre-authentication encoding; for each signature an RFC 3161 time-stamp token whose message imprint is the SHA-256 of the signature's bytes; and the legal tier's container, where there is one. A signature made with a passkey carries the WebAuthn data its signature covers (XIV.14.7, rule 9).",
  "type": "object",
  "properties": {
    "format": {
      "const": "openeik-drawing-signoff/0.1"
    },
    "envelope": {
      "description": "A DSSE envelope.",
      "type": "object",
      "properties": {
        "payloadType": {
          "const": "application/vnd.in-toto+json"
        },
        "payload": {
          "description": "The statement's JSON, in base64.",
          "$ref": "defs.schema.json#/$defs/base64"
        },
        "signatures": {
          "type": "array",
          "minItems": 1,
          "maxItems": 20,
          "items": {
            "$ref": "#/$defs/signature"
          }
        }
      },
      "required": [
        "payloadType",
        "payload",
        "signatures"
      ],
      "x-eik-closed": true
    },
    "timestamps": {
      "description": "For each signature, an RFC 3161 time-stamp token, base64 of its DER, whose message imprint is the SHA-256 of the signature's bytes (XIV.14.7, rule 8).",
      "type": "array",
      "minItems": 1,
      "maxItems": 20,
      "items": {
        "type": "object",
        "properties": {
          "keyid": {
            "type": "string",
            "minLength": 1,
            "maxLength": 80
          },
          "token": {
            "$ref": "defs.schema.json#/$defs/base64"
          }
        },
        "required": [
          "keyid",
          "token"
        ],
        "x-eik-closed": true
      }
    },
    "legal": {
      "description": "The legal tier's container (XIV.14.6), an asset.",
      "type": "object",
      "properties": {
        "asset": {
          "$ref": "defs.schema.json#/$defs/asset"
        },
        "sha256": {
          "$ref": "defs.schema.json#/$defs/hash"
        }
      },
      "required": [
        "asset",
        "sha256"
      ],
      "x-eik-closed": true
    }
  },
  "required": [
    "format",
    "envelope",
    "timestamps"
  ],
  "x-eik-closed": true,
  "$defs": {
    "signature": {
      "description": "A signature over DSSE's pre-authentication encoding, by a key of the signer's record. With webauthn, a passkey signed: sig covers authenticatorData and the SHA-256 of clientDataJSON, both in base64url.",
      "type": "object",
      "properties": {
        "keyid": {
          "type": "string",
          "minLength": 1,
          "maxLength": 80
        },
        "sig": {
          "$ref": "defs.schema.json#/$defs/base64"
        },
        "webauthn": {
          "type": "object",
          "properties": {
            "authenticatorData": {
              "$ref": "defs.schema.json#/$defs/base64url"
            },
            "clientDataJSON": {
              "$ref": "defs.schema.json#/$defs/base64url"
            }
          },
          "required": [
            "authenticatorData",
            "clientDataJSON"
          ],
          "x-eik-closed": true
        }
      },
      "required": [
        "keyid",
        "sig"
      ],
      "x-eik-closed": true
    }
  }
}
