{
  "$schema": "https://json-schema.org/draft/2020-12/schema",
  "$id": "https://artifacts.apis.io/cotal-ai/json-schema/cotal-ai-activity-page-schema.json",
  "title": "ActivityPage",
  "x-generated": "2026-11-04",
  "x-method": "derived",
  "x-generator": "derive-json-schema.py",
  "x-source": "openapi/cotal-ai-dashboard-openapi.yml#/components/schemas/ActivityPage",
  "type": "object",
  "properties": {
    "entries": {
      "type": "array",
      "items": {
        "$ref": "#/$defs/ActivityEntry"
      }
    },
    "partial": {
      "type": "boolean"
    },
    "read": {
      "type": "integer",
      "minimum": 0,
      "maximum": 2
    },
    "of": {
      "type": "integer",
      "const": 2
    },
    "missing": {
      "type": "array",
      "items": {
        "type": "string",
        "enum": [
          "chat",
          "direct messages"
        ]
      }
    },
    "reasons": {
      "type": "object",
      "additionalProperties": {
        "type": "string"
      }
    },
    "deadlineMs": {
      "type": "integer",
      "const": 8000
    }
  },
  "required": [
    "entries",
    "partial",
    "read",
    "of",
    "missing",
    "reasons",
    "deadlineMs"
  ],
  "$defs": {
    "ActivityEntry": {
      "oneOf": [
        {
          "type": "object",
          "properties": {
            "mode": {
              "const": "chat",
              "type": "string"
            },
            "channel": {
              "type": "string"
            },
            "msg": {
              "$ref": "#/$defs/Message"
            }
          },
          "required": [
            "mode",
            "channel",
            "msg"
          ]
        },
        {
          "type": "object",
          "properties": {
            "mode": {
              "const": "unicast",
              "type": "string"
            },
            "msg": {
              "$ref": "#/$defs/Message"
            }
          },
          "required": [
            "mode",
            "msg"
          ]
        }
      ]
    },
    "Message": {
      "$ref": "#/$defs/WireCotalMessage"
    },
    "WireCotalMessage": {
      "description": "A message on the mesh (chat / direct message for now; extensible to other families).",
      "oneOf": [
        {
          "properties": {
            "channel": {
              "description": "Channel name — multicast (broadcast to everyone on the channel).",
              "type": "string"
            },
            "contextId": {
              "description": "Conversation / thread correlation id.",
              "type": "string"
            },
            "from": {
              "$ref": "#/$defs/WireEndpointRef"
            },
            "id": {
              "description": "Unique message id.",
              "type": "string"
            },
            "mentions": {
              "description": "Lowercased peer names called out within a `channel` message — a wake hint that also, on a `live` channel, routes a durable copy to each mentioned target **authorized to read that channel** (SPEC §4/§5). It never carries content outside the target's read ACL and is not a routing substitute for `channel`/`to`; the message still multicasts to the whole channel. Omitted when empty.",
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            "parts": {
              "items": {
                "$ref": "#/$defs/WirePart"
              },
              "type": "array"
            },
            "replyTo": {
              "description": "Id of the message being replied to.",
              "type": "string"
            },
            "space": {
              "type": "string"
            },
            "ts": {
              "description": "Epoch ms.",
              "type": "number"
            }
          },
          "required": [
            "channel",
            "from",
            "id",
            "parts",
            "space",
            "ts"
          ],
          "type": "object",
          "not": {
            "anyOf": [
              {
                "required": [
                  "to"
                ]
              },
              {
                "required": [
                  "toService"
                ]
              }
            ]
          }
        },
        {
          "properties": {
            "contextId": {
              "description": "Conversation / thread correlation id.",
              "type": "string"
            },
            "from": {
              "$ref": "#/$defs/WireEndpointRef"
            },
            "id": {
              "description": "Unique message id.",
              "type": "string"
            },
            "mentions": {
              "description": "Lowercased peer names called out within a `channel` message — a wake hint that also, on a `live` channel, routes a durable copy to each mentioned target **authorized to read that channel** (SPEC §4/§5). It never carries content outside the target's read ACL and is not a routing substitute for `channel`/`to`; the message still multicasts to the whole channel. Omitted when empty.",
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            "parts": {
              "items": {
                "$ref": "#/$defs/WirePart"
              },
              "type": "array"
            },
            "replyTo": {
              "description": "Id of the message being replied to.",
              "type": "string"
            },
            "space": {
              "type": "string"
            },
            "to": {
              "description": "Instance id — unicast (direct to one specific endpoint).",
              "type": "string"
            },
            "ts": {
              "description": "Epoch ms.",
              "type": "number"
            }
          },
          "required": [
            "from",
            "id",
            "parts",
            "space",
            "to",
            "ts"
          ],
          "type": "object",
          "not": {
            "anyOf": [
              {
                "required": [
                  "channel"
                ]
              },
              {
                "required": [
                  "toService"
                ]
              }
            ]
          }
        },
        {
          "properties": {
            "contextId": {
              "description": "Conversation / thread correlation id.",
              "type": "string"
            },
            "from": {
              "$ref": "#/$defs/WireEndpointRef"
            },
            "id": {
              "description": "Unique message id.",
              "type": "string"
            },
            "mentions": {
              "description": "Lowercased peer names called out within a `channel` message — a wake hint that also, on a `live` channel, routes a durable copy to each mentioned target **authorized to read that channel** (SPEC §4/§5). It never carries content outside the target's read ACL and is not a routing substitute for `channel`/`to`; the message still multicasts to the whole channel. Omitted when empty.",
              "items": {
                "type": "string"
              },
              "type": "array"
            },
            "parts": {
              "items": {
                "$ref": "#/$defs/WirePart"
              },
              "type": "array"
            },
            "replyTo": {
              "description": "Id of the message being replied to.",
              "type": "string"
            },
            "space": {
              "type": "string"
            },
            "toService": {
              "description": "Service / role — anycast (any one instance of the service receives it).",
              "type": "string"
            },
            "ts": {
              "description": "Epoch ms.",
              "type": "number"
            }
          },
          "required": [
            "from",
            "id",
            "parts",
            "space",
            "toService",
            "ts"
          ],
          "type": "object",
          "not": {
            "anyOf": [
              {
                "required": [
                  "channel"
                ]
              },
              {
                "required": [
                  "to"
                ]
              }
            ]
          }
        }
      ]
    },
    "WireEndpointRef": {
      "properties": {
        "id": {
          "type": "string"
        },
        "name": {
          "type": "string"
        },
        "role": {
          "type": "string"
        }
      },
      "required": [
        "id",
        "name"
      ],
      "type": "object"
    },
    "WireExtensionPartKind": {
      "description": "Reverse-DNS extension part kind, e.g. `com.acme.snapshot`.",
      "pattern": "^[A-Za-z0-9-]+(\\.[A-Za-z0-9-]+)+$",
      "type": "string"
    },
    "WireJsonValue": {
      "anyOf": [
        {
          "type": "null"
        },
        {
          "type": "boolean"
        },
        {
          "type": "number"
        },
        {
          "type": "string"
        },
        {
          "items": {
            "$ref": "#/$defs/WireJsonValue"
          },
          "type": "array"
        },
        {
          "additionalProperties": {
            "anyOf": [
              {
                "$ref": "#/$defs/WireJsonValue"
              },
              {
                "not": {}
              }
            ]
          },
          "type": "object"
        }
      ],
      "description": "Any JSON value (SPEC §5): `null`, a boolean, a number, a string, an array, or an object whose members are JSON values. `undefined` is not a JSON value — `JSON.stringify` omits the key carrying it — so it is excluded at the top level, where it would drop the whole `data` key; an optional member is allowed because serialization drops just that key."
    },
    "WirePart": {
      "oneOf": [
        {
          "properties": {
            "kind": {
              "const": "text",
              "type": "string"
            },
            "text": {
              "type": "string"
            }
          },
          "required": [
            "kind",
            "text"
          ],
          "type": "object"
        },
        {
          "properties": {
            "data": {
              "$ref": "#/$defs/WireJsonValue"
            },
            "kind": {
              "const": "data",
              "type": "string"
            }
          },
          "required": [
            "kind",
            "data"
          ],
          "type": "object"
        },
        {
          "description": "Reference to bytes in the space's artifact store — SPEC §5's reserved slot, now defined. Bare (not reverse-DNS) because it is Cotal's own core primitive: extension kinds wrap EXTERNAL vocabularies, core kinds are the standard's own. The full contract, the guard, and the object-store digest boundary live in `artifact.ts`.",
          "properties": {
            "digest": {
              "description": "`sha256:<hex>` over the raw bytes — the artifact's identity. The only self-verifying field.",
              "type": "string",
              "pattern": "^sha256:[0-9a-f]{64}$"
            },
            "kind": {
              "const": "artifact",
              "type": "string"
            },
            "mediaType": {
              "description": "MIME type. A publisher's claim.",
              "type": "string"
            },
            "name": {
              "description": "Human name, e.g. `coverage-report.html`. A publisher's claim, not a checked fact.",
              "type": "string"
            },
            "size": {
              "description": "Size in bytes. A publisher's claim: a receiver must never preallocate from it.",
              "type": "integer",
              "minimum": 0
            }
          },
          "required": [
            "kind",
            "name",
            "mediaType",
            "digest",
            "size"
          ],
          "type": "object"
        },
        {
          "additionalProperties": {},
          "properties": {
            "kind": {
              "$ref": "#/$defs/WireExtensionPartKind"
            }
          },
          "required": [
            "kind"
          ],
          "type": "object"
        }
      ]
    }
  }
}