{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://www.feranor.com/pqc/schemas/audit-record.schema.json",
  "title": "Feranor PQC Sidecar, a record of the audit journal",
  "description": "One line of the audit journal (Sidecar:AuditJournal), a JSON Lines file in UTF-8: a start, begin, operation or stop record, hash-chained. The members appear in this order, hash always last: the hash is the SHA-256, in lowercase hexadecimal, of the line up to ,\"hash\": followed by }. A member without a value is left out. New members may be added in a minor version; none is removed or changes meaning within a major version.",
  "type": "object",
  "additionalProperties": false,
  "required": [
    "seq",
    "at",
    "kind",
    "previous",
    "hash"
  ],
  "properties": {
    "seq": {
      "type": "integer",
      "minimum": 1,
      "description": "The record's number, from 1, continued across restarts."
    },
    "at": {
      "type": "string",
      "format": "date-time",
      "description": "When the record was made, UTC."
    },
    "kind": {
      "type": "string",
      "enum": [
        "start",
        "begin",
        "operation",
        "stop"
      ],
      "description": "start: before the sidecar listens. begin: before an operation runs. operation: once it is answered. stop: once the sidecar has stopped."
    },
    "version": {
      "type": "string",
      "description": "The sidecar's version (start records)."
    },
    "endpoint": {
      "type": "string",
      "description": "Where the sidecar listens, a Unix socket path or an address and port (start records)."
    },
    "operation": {
      "type": "string",
      "enum": [
        "encrypt",
        "decrypt",
        "sign",
        "verify",
        "inspect"
      ],
      "description": "The operation (begin and operation records)."
    },
    "flags": {
      "type": "string",
      "description": "The query flags set to true (sign, requireSignature, detached), separated by commas."
    },
    "status": {
      "type": "integer",
      "description": "The HTTP status the client got; 499 when the client went away (operation records)."
    },
    "code": {
      "$ref": "#/$defs/problemCode"
    },
    "aborted": {
      "const": true,
      "description": "Present, true, when the answer was cut short after it had started."
    },
    "inputSize": {
      "type": "integer",
      "minimum": 0,
      "description": "The size the request announced, in bytes."
    },
    "durationMs": {
      "type": "number",
      "minimum": 0,
      "description": "How long the operation took, in milliseconds."
    },
    "client": {
      "type": "string",
      "description": "Who asked: the client's address on TCP; on the Unix socket, \"unix socket, uid U, gid G, pid P\" from the Linux kernel, or \"unix socket\"."
    },
    "requestId": {
      "type": "string",
      "description": "The request's identifier, also in the logs and traces."
    },
    "signer": {
      "type": "string",
      "description": "The signer's subject, as Feranor-Signer reported it."
    },
    "signerThumbprint": {
      "type": "string",
      "description": "As Feranor-Signer-Thumbprint reported it."
    },
    "signatureAlgorithm": {
      "type": "string",
      "description": "As Feranor-Signature-Algorithm reported it."
    },
    "coSigner": {
      "type": "string",
      "description": "The classical co-signer's subject, as Feranor-Co-Signer reported it."
    },
    "coSignatureAlgorithm": {
      "type": "string",
      "description": "As Feranor-Co-Signature-Algorithm reported it."
    },
    "hybrid": {
      "type": "string",
      "enum": [
        "true",
        "false"
      ],
      "description": "As Feranor-Hybrid reported it."
    },
    "signed": {
      "type": "string",
      "enum": [
        "true",
        "false"
      ],
      "description": "As Feranor-Signed reported it."
    },
    "previous": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "The hash of the record before, sixty-four zeros for the first."
    },
    "hash": {
      "type": "string",
      "pattern": "^[0-9a-f]{64}$",
      "description": "The SHA-256 of this record, as described above."
    }
  },
  "allOf": [
    {
      "if": {
        "properties": {
          "kind": {
            "const": "start"
          }
        }
      },
      "then": {
        "required": [
          "version",
          "endpoint"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "kind": {
            "const": "begin"
          }
        }
      },
      "then": {
        "required": [
          "operation",
          "client",
          "requestId"
        ]
      }
    },
    {
      "if": {
        "properties": {
          "kind": {
            "const": "operation"
          }
        }
      },
      "then": {
        "required": [
          "operation",
          "status",
          "durationMs",
          "client",
          "requestId"
        ]
      }
    }
  ],
  "$defs": {
    "problemCode": {
      "type": "string",
      "enum": [
        "invalid-request",
        "invalid-input",
        "payload-too-large",
        "recipient-not-found",
        "authentication-failed",
        "signature-invalid",
        "signature-required",
        "algorithm-not-allowed",
        "key-store-unavailable",
        "audit-journal-unavailable"
      ],
      "description": "The stable error code of the answer, as in the API's problem details."
    }
  }
}
