{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://heartcortex.ai/schemas/1.0/common.schema.json",
  "title": "HEART shared definitions",
  "$defs": {
    "privacyLevel": {
      "enum": [
        "public",
        "internal",
        "private",
        "never-share"
      ]
    },
    "messageLevel": {
      "description": "Levels a message may carry. never-share data never appears in a message, so it is not a valid value here.",
      "enum": [
        "public",
        "internal",
        "private"
      ]
    },
    "status": {
      "enum": [
        "healthy",
        "degraded",
        "failing",
        "unknown"
      ]
    },
    "severity": {
      "enum": [
        "info",
        "warning",
        "error",
        "critical"
      ]
    },
    "risk": {
      "enum": [
        "read",
        "write",
        "destructive"
      ]
    },
    "systemId": {
      "description": "Reverse-DNS identifier of the system, rooted in a domain the owner controls.",
      "type": "string",
      "pattern": "^[a-z0-9]+(\\.[a-z0-9-]+)+$",
      "maxLength": 200
    },
    "instanceId": {
      "description": "Non-identifying instance label. It must not encode a user or device identity.",
      "type": "string",
      "pattern": "^[A-Za-z0-9._-]{1,64}$"
    },
    "alias": {
      "description": "Short name used in Gateway paths. Unique per Gateway. It has no dot, so it can never be mistaken for a systemId.",
      "type": "string",
      "pattern": "^[a-z0-9][a-z0-9-]{0,62}$"
    },
    "capabilityName": {
      "description": "Same character set as MCP tool names, so capabilities map to tools unchanged.",
      "type": "string",
      "pattern": "^[A-Za-z0-9_.-]{1,128}$"
    },
    "timestamp": {
      "type": "string",
      "format": "date-time"
    },
    "uuid": {
      "type": "string",
      "format": "uuid"
    },
    "ext": {
      "description": "Vendor extensions. Keys are reverse-DNS names. Unclassified extension fields are treated as private.",
      "type": "object",
      "propertyNames": {
        "pattern": "^[a-z0-9]+(\\.[a-z0-9-]+)+$"
      }
    },
    "system": {
      "type": "object",
      "required": [
        "id",
        "name",
        "version"
      ],
      "properties": {
        "id": {
          "$ref": "#/$defs/systemId"
        },
        "name": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200
        },
        "version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 64
        },
        "instance": {
          "$ref": "#/$defs/instanceId"
        },
        "alias": {
          "$ref": "#/$defs/alias"
        },
        "owner": {
          "type": "string",
          "maxLength": 200
        }
      }
    },
    "messageType": {
      "description": "Standard heart.* types, or a reverse-DNS custom type with at least two dots.",
      "anyOf": [
        {
          "enum": [
            "heart.card",
            "heart.pulse",
            "heart.rhythm",
            "heart.arrhythmia",
            "heart.action",
            "heart.receipt",
            "heart.evolution",
            "heart.component",
            "heart.property",
            "heart.config",
            "heart.metric",
            "heart.log",
            "heart.diagnostic",
            "heart.lifecycle",
            "heart.software",
            "heart.update",
            "heart.artifact",
            "heart.schedule",
            "heart.control",
            "heart.rule",
            "heart.consent",
            "heart.policy",
            "heart.aipolicy",
            "heart.memory",
            "heart.lesson",
            "heart.audit",
            "heart.security",
            "heart.platform",
            "heart.peer",
            "heart.fleet",
            "heart.custom",
            "heart.core",
            "heart.proposal",
            "heart.trial",
            "heart.brain",
            "heart.usage",
            "heart.export",
            "heart.grant"
          ]
        },
        {
          "type": "string",
          "pattern": "^(?!heart\\.)[a-z0-9]+(\\.[a-z0-9-]+){2,}$"
        }
      ]
    },
    "module": {
      "enum": [
        "inventory",
        "properties",
        "config",
        "telemetry",
        "diagnostics",
        "lifecycle",
        "software",
        "artifacts",
        "schedules",
        "control",
        "privacy",
        "ai",
        "memory",
        "evolving",
        "security",
        "platform",
        "provisioning",
        "peers",
        "batch",
        "fleet",
        "custom",
        "native",
        "core",
        "brain",
        "presence",
        "access"
      ]
    },
    "sha256": {
      "type": "string",
      "pattern": "^[a-f0-9]{64}$"
    },
    "presence": {
      "description": "Proof that a person approved this exact Action digest (API Standard 6.3).",
      "type": "object",
      "required": [
        "method",
        "digest",
        "proof"
      ],
      "properties": {
        "method": {
          "description": "webauthn: a passkey assertion. ciba: an OpenID CIBA result. device-button: not accepted until its format is defined (vendor extension only). remote-site: a decision signed by a monitor site the device pinned at registration; weaker than webauthn, and not accepted for physical Actions unless the owner set remoteSitePhysical (Part 6, Section 3.2). fleet: an approval a HEART Gateway signs for one system, after one person approved a whole fleet command at the Gateway (API Standard 13.3); accepted only with the Gateway key the system pinned, and for a physical Action only if the owner set fleetPhysical.",
          "enum": [
            "webauthn",
            "ciba",
            "device-button",
            "remote-site",
            "fleet"
          ]
        },
        "digest": {
          "$ref": "#/$defs/sha256",
          "description": "The Action's digest; for method fleet, the fleet digest."
        },
        "proof": {
          "description": "webauthn: base64url of the JSON object {credentialId, authenticatorData, clientDataJSON, signature}, each base64url, where the WebAuthn challenge is the raw 32 digest bytes. ciba: the CIBA ID token. remote-site: base64url of the JSON object {actionId, digest, decision, at, signature}, where signature is the site's Ed25519 signature (base64url) over the RFC 8785 JSON of {actionId, digest, decision, at}; the device verifies it with the pinned key and refuses it if 'at' is more than 300 s old. device-button: defined by the vendor. fleet: base64url of the JSON object {fleet, system, actionId, approvedBy, at, signature}, where fleet is the object whose RFC 8785 JSON digest is the fleet digest ({command, operation, arguments, physical, selector, targets, rollout}), and signature is the Gateway's Ed25519 signature (base64url) over the RFC 8785 JSON of {actionId, approvedBy, at, fleetDigest, system}; the system refuses it if 'at' is more than 300 s old.",
          "type": "string",
          "minLength": 1,
          "maxLength": 1048576
        }
      },
      "additionalProperties": false
    },
    "actionId": {
      "description": "A UUID the client chooses for the Action its request may create (API Standard 6.3, rule 1). The system uses it as the Action's id, so the client can compute the digest before sending, and a person can prove presence for it in the same request. A reused actionId is refused with 409 conflict. Required when presence is sent with a request.",
      "$ref": "#/$defs/uuid"
    },
    "check": {
      "description": "A test the Core can run on its own signals, such as 'overshoot of room.temperature below 5 % within 5400 s' (Core Standard, Section 7.3).",
      "type": "object",
      "required": [
        "signal",
        "op",
        "value"
      ],
      "additionalProperties": false,
      "properties": {
        "signal": {
          "description": "A signal or property name from the System Map.",
          "type": "string"
        },
        "feature": {
          "description": "Which statistic of the signal to test. Default: value (its latest sample).",
          "$ref": "#/$defs/statistic",
          "default": "value"
        },
        "op": {
          "enum": [
            "<",
            "<=",
            ">",
            ">=",
            "==",
            "!="
          ]
        },
        "value": {
          "type": "number"
        },
        "withinSec": {
          "description": "expect: the check must have held by this many seconds after the last step. undoIf: the check is watched for this long after the last step; the Trial is not kept before the longest undoIf withinSec has passed.",
          "type": "integer",
          "minimum": 1,
          "maximum": 604800
        },
        "windowSec": {
          "description": "The statistic covers the last windowSec seconds, but never samples from before the step being judged. Default: everything since that step (expect) or since the Trial started (undoIf). Ignored for value.",
          "type": "integer",
          "minimum": 1,
          "maximum": 604800
        }
      }
    },
    "changeEnvelope": {
      "description": "How far an automatic change may go (Core Standard, Section 7.4). It only narrows an allowlist entry. An argument it does not name MUST NOT change automatically.",
      "type": "object",
      "required": [
        "arguments"
      ],
      "additionalProperties": false,
      "properties": {
        "arguments": {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": {
            "type": "object",
            "required": [
              "min",
              "max"
            ],
            "additionalProperties": false,
            "properties": {
              "min": {
                "type": "number"
              },
              "max": {
                "type": "number"
              },
              "maxStep": {
                "description": "Largest change of this argument in one step.",
                "type": "number",
                "exclusiveMinimum": 0
              }
            }
          }
        },
        "maxPerDay": {
          "description": "Most automatic Trials on this target in any rolling 24 hours.",
          "type": "integer",
          "minimum": 0
        },
        "cooldownSec": {
          "description": "Least time from the end of one automatic Trial on this target to the start of the next.",
          "type": "integer",
          "minimum": 0
        }
      }
    },
    "feature": {
      "description": "A summary of one signal over a window: what a Consultation sends instead of raw samples.",
      "type": "object",
      "required": [
        "signal",
        "windowSec",
        "stats"
      ],
      "additionalProperties": false,
      "properties": {
        "signal": {
          "type": "string"
        },
        "unit": {
          "description": "Unit of the signal (UCUM). min, max, mean, stddev and value are in this unit, trend in this unit per minute, overshoot in %, count in events.",
          "type": "string"
        },
        "windowSec": {
          "type": "integer",
          "minimum": 1
        },
        "stats": {
          "type": "object",
          "minProperties": 1,
          "additionalProperties": false,
          "properties": {
            "value": {
              "type": "number"
            },
            "min": {
              "type": "number"
            },
            "max": {
              "type": "number"
            },
            "mean": {
              "type": "number"
            },
            "stddev": {
              "type": "number"
            },
            "trend": {
              "type": "number"
            },
            "overshoot": {
              "type": "number"
            },
            "count": {
              "type": "number"
            }
          },
          "propertyNames": {
            "$ref": "#/$defs/statistic"
          }
        },
        "privacy": {
          "description": "The privacy level of the signal it summarises. The Valve treats the feature at this level; absent means internal.",
          "$ref": "#/$defs/messageLevel"
        }
      }
    },
    "statistic": {
      "description": "The one list of signal statistics (Core Standard, Section 7.2), used by checks, features and signal-table derivations. value: the latest sample. min, max, mean, stddev: over the window. trend: change in signal units per minute, by least squares over the window. overshoot: how far the signal went past its setpoint, as a percentage of the last setpoint step (unit %). count: how many events were reported for the signal in the window.",
      "enum": [
        "value",
        "min",
        "max",
        "mean",
        "stddev",
        "trend",
        "overshoot",
        "count"
      ]
    },
    "digestInput": {
      "description": "What an Action digest covers: SHA-256 over the RFC 8785 (JCS) JSON of this object, written as 64 lower-case hex characters. 'plan' and 'restore' are present only for the first Action of a Trial (Core Standard, Section 7.5), so approving it approves every step and the undo.",
      "type": "object",
      "required": [
        "system",
        "id",
        "operation",
        "arguments",
        "physical"
      ],
      "additionalProperties": false,
      "properties": {
        "system": {
          "$ref": "#/$defs/systemId"
        },
        "id": {
          "$ref": "#/$defs/uuid"
        },
        "operation": {
          "description": "The capability name, or 'METHOD /path' for an operation.",
          "type": "string"
        },
        "arguments": {
          "type": "object"
        },
        "physical": {
          "type": "boolean"
        },
        "plan": {
          "description": "Every step's arguments, in order.",
          "type": "array",
          "items": {
            "type": "object"
          }
        },
        "restore": {
          "description": "The values the undo will set.",
          "type": "object"
        }
      }
    },
    "confidence": {
      "description": "How sure the author is. low: a guess worth checking. medium: likely. high: well supported by the evidence given.",
      "enum": [
        "low",
        "medium",
        "high"
      ]
    },
    "area": {
      "description": "Where an Autonomy Level applies (Part 2, Section 6): a component ID from the Card, or a standard area.",
      "anyOf": [
        {
          "enum": [
            "power",
            "connectivity",
            "storage",
            "performance",
            "software",
            "ai",
            "sensors",
            "actuators",
            "data",
            "security"
          ]
        },
        {
          "type": "string",
          "pattern": "^[a-z0-9][a-z0-9._-]{0,63}$"
        }
      ]
    },
    "tier": {
      "description": "Where an answer or Proposal came from (Core Standard, Section 5). reflex: compiled rules and Playbooks. recall: matching against the API Index and System Map. local: a model in the system's own Model Slot. gateway: a model on a nearby HEART Gateway. cloud: a large model reached over the network. fleet: a fleet service that learns from many systems' outcomes.",
      "enum": [
        "reflex",
        "recall",
        "local",
        "gateway",
        "cloud",
        "fleet"
      ]
    },
    "brainModel": {
      "type": "object",
      "additionalProperties": false,
      "required": [
        "id",
        "version"
      ],
      "properties": {
        "id": {
          "type": "string",
          "minLength": 1,
          "maxLength": 200,
          "description": "The model, as the Command Center names it, such as provider/model."
        },
        "version": {
          "type": "string",
          "minLength": 1,
          "maxLength": 100,
          "description": "Its exact version. A new version is a new model: it needs its own place in a lease."
        },
        "sha256": {
          "$ref": "common.schema.json#/$defs/sha256",
          "description": "For a model on the device itself: the hash of its file. Required for local models (API Standard 7.4 rule 6)."
        },
        "local": {
          "type": "boolean",
          "default": false,
          "description": "true for a model that runs on the device itself."
        }
      }
    },
    "brainUse": {
      "enum": [
        "explain",
        "serve",
        "propose",
        "plan",
        "chat"
      ],
      "description": "What a brain may be used for: explain alerts, serve plain-language requests, propose changes, plan (missions, routes, schedules, each still checked as Proposals), or chat with a person."
    },
    "brainSignature": {
      "description": "The Command Center's signature on one brain answer (API Standard 7.4 rule 5, D36). Ed25519, with the key the device pinned, over the RFC 8785 JSON of {system, lease, requestDigest, answerDigest, model, at}. The device rejects an answer whose signature, system, request, lease, model or use does not check out.",
      "type": "object",
      "additionalProperties": false,
      "required": [
        "lease",
        "requestDigest",
        "answerDigest",
        "model",
        "at",
        "signature"
      ],
      "properties": {
        "lease": {
          "$ref": "#/$defs/uuid",
          "description": "The lease the answer was given under."
        },
        "requestDigest": {
          "$ref": "#/$defs/sha256",
          "description": "SHA-256 of the RFC 8785 JSON of the request the device sent."
        },
        "answerDigest": {
          "$ref": "#/$defs/sha256",
          "description": "SHA-256 of the RFC 8785 JSON of the answer, without this signed object."
        },
        "model": {
          "$ref": "#/$defs/brainModel"
        },
        "at": {
          "$ref": "#/$defs/timestamp"
        },
        "signature": {
          "type": "string",
          "pattern": "^[A-Za-z0-9_-]{86}$",
          "description": "base64url, no padding, of the 64-byte Ed25519 signature."
        }
      },
      "x-heart-privacy": "internal"
    }
  }
}
