{
  "asyncapi": "2.6.0",
  "info": {
    "title": "GoGuardian Extension Realtime API",
    "version": "4.0.7422.1",
    "description": "Realtime (Pusher) interface of the GoGuardian student Chrome extension,\nv4.0.7422.1, reconstructed from the minified bundles. The extension talks\nto a private Pusher deployment: cluster \"goguardian\", production app key\n4e83de4fd19694be0821. The client (pusher-js, vendored as webpack modules)\nis configured wssOnly (forceTLS + enabledTransports [\"ws\",\"wss\"]), retries\nchannel subscriptions up to 10 times with ExponentialBackoff\n(1 s → 1024 s, factor 2, jitter 0.5), permanently gives up on HTTP 403/400\nfrom the auth endpoint, and repairs channel subscriptions every 30 s\n(background/src/475-pusher-client.js, src/987-pusher-env.js).\n\nChannel authentication: every private-/presence- channel subscription\ntriggers POST https://sakura.goguardian.com/api/v1/auth/ext with header\nAuthorization: <localStorage.compRand> and params channel_name, socket_id,\nversion, protocolVersion=1, capabilities (comma-joined device-capability\nbit list), clientType=\"extension\", os, liveStateVersion=6. The full\nrequest/response is documented in the companion OpenAPI spec\n(openapi.goguardian.yaml).\n\nA SECOND Pusher client exists for the \"sender experiment\"\n(background/src/1714-sender-module.js): identical key/cluster/auth, but\nwsHost/httpHost are overridden to sender-gateway.goguardian.com (staging:\nstg-sender-gateway.goguardian.com). It mirrors the same\nprivate-subaccount / private-account / presence-session channels, acks\nshadows, and receives client-state-set copies.\n\nPERSPECTIVE NOTE: Pusher \"client events\" (client-*) are extension-to-\nextension messages relayed through Pusher — the teacher/admin dashboard\npublishes, the student extension subscribes, and vice versa. In this spec\n\"publish\" means the student extension emits the event; \"subscribe\" means\nit listens for the event (usually sent by an admin dashboard).\n\nHONEST SCOPE NOTE: there is NO GoGuardian-domain WebSocket in this\ncodebase. The only wss:// endpoints contacted are Twilio's\n(wss://global.vss.twilio.com/signaling — SDK-owned, used for the\nggt-call.<callId> video rooms) and Pusher's own; neither is documented as\nchannels here.\n"
  },
  "servers": {
    "pusher": {
      "url": "wss://ws-goguardian.pusher.com:443/app/4e83de4fd19694be0821",
      "protocol": "wss",
      "description": "Main Pusher WebSocket. pusher-js constructs this URL from the cluster\n(\"goguardian\") and app key, appending query params such as\nprotocol=7&client=js&version=<pusher-js version>&flash=false.\n"
    },
    "sender-gateway": {
      "url": "wss://sender-gateway.goguardian.com:443/app/4e83de4fd19694be0821",
      "protocol": "wss",
      "description": "Sender-experiment client only (src/1714-sender-module.js). Staging\nvariant: stg-sender-gateway.goguardian.com. Same key and auth endpoint\nas the main deployment.\n"
    }
  },
  "channels": {
    "private-subaccount.{subAccountId}": {
      "description": "Primary teacher/admin → student command channel, keyed by the\nenrolled sub-account. Both the main client and the sender-experiment\nclient subscribe (src/1048-pusher-module.js:183, src/1714:141).\n",
      "parameters": {
        "subAccountId": {
          "schema": {
            "type": "integer"
          },
          "description": "Numeric sub-account id (register.subAccountId)."
        }
      },
      "subscribe": {
        "summary": "Teacher/admin shadow and live-control events",
        "operationId": "subaccountSubscribe",
        "messages": [
          {
            "$ref": "#/components/messages/Shadow"
          },
          {
            "$ref": "#/components/messages/ForceLiveState"
          },
          {
            "$ref": "#/components/messages/RequestScreenshotResolutionIncrease"
          },
          {
            "$ref": "#/components/messages/AnnotateScreenRequest"
          },
          {
            "$ref": "#/components/messages/SetChatState"
          },
          {
            "$ref": "#/components/messages/SetOffTaskAlertsState"
          },
          {
            "$ref": "#/components/messages/RequestEntityFlushRateIncrease"
          },
          {
            "$ref": "#/components/messages/SmartMonitoring"
          }
        ]
      },
      "publish": {
        "summary": "Student acks and call state",
        "operationId": "subaccountPublish",
        "messages": [
          {
            "$ref": "#/components/messages/ShadowApplied"
          },
          {
            "$ref": "#/components/messages/ForceInitialPayload"
          },
          {
            "$ref": "#/components/messages/StateSet"
          },
          {
            "$ref": "#/components/messages/AnnotateScreenResponse"
          },
          {
            "$ref": "#/components/messages/CallState"
          },
          {
            "$ref": "#/components/messages/CallRinging"
          }
        ]
      }
    },
    "private-account.{accountId}": {
      "description": "Account-wide admin event channel (src/1048:218, src/1714:171).\n",
      "parameters": {
        "accountId": {
          "schema": {
            "type": "integer"
          },
          "description": "Numeric account id."
        }
      },
      "subscribe": {
        "summary": "Account-level admin events",
        "operationId": "accountSubscribe",
        "messages": [
          {
            "$ref": "#/components/messages/AdminPoliciesUpdated"
          }
        ]
      }
    },
    "presence-session.{sessionId}": {
      "description": "Presence channel per classroom session; member presence drives whether\nlive-state screenshots/state are sent at all (no present admins = no\nstate sends) (src/1048:131, src/1714:130).\n",
      "parameters": {
        "sessionId": {
          "schema": {
            "type": "integer"
          },
          "description": "Classroom session id."
        }
      },
      "subscribe": {
        "summary": "Presence membership events",
        "operationId": "sessionSubscribe",
        "messages": [
          {
            "$ref": "#/components/messages/MemberAdded"
          },
          {
            "$ref": "#/components/messages/MemberRemoved"
          }
        ]
      }
    },
    "private-session-instrumentation.student.{accountId}": {
      "description": "Per-student session-instrumentation channel; the student reports which\nsessions received its live-state payload. The code keys this channel\nby accountId — NOT studentId (src/1048:143-144; older READMEs that say\nstudentId are wrong).\n",
      "parameters": {
        "accountId": {
          "schema": {
            "type": "integer"
          },
          "description": "The student's account id (not student id)."
        }
      },
      "publish": {
        "summary": "Live-state delivery receipts",
        "operationId": "instrumentationPublish",
        "messages": [
          {
            "$ref": "#/components/messages/LiveStateSent"
          }
        ]
      }
    },
    "presence-call.{callId}": {
      "description": "Presence channel per teacher video/voice call (src/1048:171-174).\n",
      "parameters": {
        "callId": {
          "schema": {
            "type": "integer"
          },
          "description": "Call id."
        }
      },
      "subscribe": {
        "summary": "Call lifecycle events",
        "operationId": "callSubscribe",
        "messages": [
          {
            "$ref": "#/components/messages/MemberAdded"
          },
          {
            "$ref": "#/components/messages/MemberRemoved"
          },
          {
            "$ref": "#/components/messages/CallArchived"
          },
          {
            "$ref": "#/components/messages/CallHangup"
          }
        ]
      }
    },
    "presence-student.{accountId}-session.{sessionId}": {
      "description": "Classroom chat channel (raw/1692.js:188). Both directions: the\nextension's own chat messages and acknowledgments, plus incoming\nteacher messages and peer acknowledgments.\n",
      "parameters": {
        "accountId": {
          "schema": {
            "type": "integer"
          },
          "description": "Student account id."
        },
        "sessionId": {
          "schema": {
            "type": "integer"
          },
          "description": "Classroom session id."
        }
      },
      "publish": {
        "summary": "Outgoing chat",
        "operationId": "chatPublish",
        "messages": [
          {
            "$ref": "#/components/messages/ChatMessage"
          },
          {
            "$ref": "#/components/messages/ChatAcknowledgment"
          }
        ]
      },
      "subscribe": {
        "summary": "Incoming chat",
        "operationId": "chatSubscribe",
        "messages": [
          {
            "$ref": "#/components/messages/ChatMessage"
          },
          {
            "$ref": "#/components/messages/ChatAcknowledgment"
          }
        ]
      }
    },
    "private-mlp-subaccount.{subAccountId}": {
      "description": "ML-pipeline mode channel (sender experiment / mlPipeline feature) —\ncarries asynchronous beacon ML results back to the device\n(src/1714:96; src/1691:50-51, 109-145).\n",
      "parameters": {
        "subAccountId": {
          "schema": {
            "type": "integer"
          },
          "description": "Numeric sub-account id."
        }
      },
      "subscribe": {
        "summary": "Beacon ML results",
        "operationId": "mlpSubscribe",
        "messages": [
          {
            "$ref": "#/components/messages/BeaconSearch"
          },
          {
            "$ref": "#/components/messages/BeaconThreatsAndViolence"
          }
        ]
      }
    }
  },
  "components": {
    "messages": {
      "ShadowApplied": {
        "name": "client-shadow-applied",
        "title": "Shadow applied acknowledgment",
        "description": "Sent by the student extension after applying a shadow's state, on\nboth the main and sender-experiment clients. If the trigger is\nrefused, retried every 5 s.\n",
        "payload": {
          "type": "object",
          "required": [
            "subaccountId",
            "shadowId",
            "applied"
          ],
          "properties": {
            "subaccountId": {
              "type": "integer"
            },
            "shadowId": {
              "type": "integer"
            },
            "applied": {
              "type": "boolean",
              "enum": [
                true
              ]
            }
          }
        },
        "x-evidence": "src/1048:493-497; src/1714:229-234"
      },
      "ForceInitialPayload": {
        "name": "client-force-initial-payload",
        "title": "Force initial payload",
        "description": "Empty payload. Fired 4 s after subscribing to private-subaccount if\nno shadow has arrived yet (5 s retry), to force the admin dashboard\nto resend state.\n",
        "payload": {
          "type": "object",
          "additionalProperties": false
        },
        "x-evidence": "src/1048:503-504; src/1714:240-241"
      },
      "StateSet": {
        "name": "client-state-set",
        "title": "Live state update",
        "description": "The live-state payload (screenshots URL, tabs, lock state, idle...),\nsent on the main client trimmed to 20480 bytes and on the\nsender-experiment client untrimmed. Sent every 3 s (debounced) while\nmonitoring is active and at least one admin is present.\n",
        "payload": {
          "$ref": "#/components/schemas/LiveState"
        },
        "x-evidence": "src/1715:369 (trimmed), src/1715:410 (sender, untrimmed)"
      },
      "LiveStateSent": {
        "name": "client-live-state-sent",
        "title": "Live-state delivery receipt",
        "description": "Reports which instrumented sessions were sent the live-state payload,\nkeyed by the state's uuid id.\n",
        "payload": {
          "type": "object",
          "required": [
            "id",
            "sessionIds"
          ],
          "properties": {
            "id": {
              "type": "string",
              "description": "uuid.v4() of the sent state payload."
            },
            "sessionIds": {
              "type": "array",
              "items": {
                "type": "integer"
              }
            }
          }
        },
        "x-evidence": "src/1715:385-390"
      },
      "AnnotateScreenResponse": {
        "name": "client-annotate-screen-response",
        "title": "Annotate-screen response",
        "payload": {
          "type": "object",
          "required": [
            "requestId",
            "success"
          ],
          "properties": {
            "requestId": {
              "type": "string"
            },
            "success": {
              "type": "boolean"
            }
          }
        },
        "x-evidence": "src/1048:539-543"
      },
      "ChatMessage": {
        "name": "client-chat-message",
        "title": "Classroom chat message",
        "description": "The redux ADD_MESSAGE payload. The receiver parseInts studentId.\nContent is the message text; type is e.g. \"message\".\n",
        "payload": {
          "type": "object",
          "required": [
            "studentId",
            "sessionId",
            "messageId",
            "content",
            "type"
          ],
          "properties": {
            "studentId": {
              "type": "integer"
            },
            "sessionId": {
              "type": "integer"
            },
            "messageId": {
              "type": "string"
            },
            "content": {
              "type": "string"
            },
            "type": {
              "type": "string",
              "description": "e.g. \"message\""
            }
          }
        },
        "x-evidence": "raw/1704.js:6-18 (send); raw/1692.js:185-194 (receive); raw/1709.js:91-109"
      },
      "ChatAcknowledgment": {
        "name": "client-chat-acknowledgment",
        "title": "Chat acknowledgment",
        "payload": {
          "type": "object",
          "required": [
            "eventType",
            "messageIds",
            "sessionId",
            "studentId",
            "timestamp"
          ],
          "properties": {
            "eventType": {
              "type": "string",
              "enum": [
                "client-chat-acknowledgment"
              ]
            },
            "messageIds": {
              "type": "array",
              "items": {
                "type": "string"
              }
            },
            "sessionId": {
              "type": "integer"
            },
            "studentId": {
              "type": "integer"
            },
            "timestamp": {
              "type": "integer",
              "description": "Date.now() epoch millis."
            }
          }
        },
        "x-evidence": "raw/1704.js:20-39"
      },
      "CallState": {
        "name": "client-call-{state}",
        "title": "Outbound call state event",
        "description": "Call lifecycle state, mapped from the call state machine to the\nevent name: joined → client-call-answered; declined →\nclient-call-declined; declined_reason → client-call-declined-reason\n(adds data.reason); left → client-call-hangup; consent_pending →\nclient-call-consent-pending; permission_pending →\nclient-call-permission-pending; consent_declined →\nclient-call-consent-declined; error → client-call-error; join_pending\n→ client-call-join-pending; recording_consent_pending →\nclient-call-recording-consent-pending; recording_consent_changed →\nclient-call-recording-consent-changed.\n",
        "payload": {
          "type": "object",
          "required": [
            "participantId"
          ],
          "properties": {
            "participantId": {
              "type": "string"
            },
            "reason": {
              "type": "string",
              "description": "Only for client-call-declined-reason."
            },
            "data": {
              "type": "object",
              "description": "Additional state fields for error states."
            }
          }
        },
        "x-evidence": "raw/1051.js:60-73, 239-244"
      },
      "CallRinging": {
        "name": "client-call-ringing",
        "title": "Call ringing",
        "payload": {
          "type": "object",
          "required": [
            "participantId"
          ],
          "properties": {
            "participantId": {
              "type": "string"
            }
          }
        },
        "x-evidence": "raw/1051.js:350-353"
      },
      "Shadow": {
        "name": "client-shadow",
        "title": "Shadow state",
        "description": "The teacher/admin \"shadow\": the desired device state (lock, chat\nenablement, tab commands, lesson plan, active calls, check-ins). The\nextension applies it and acks via client-shadow-applied.\n",
        "payload": {
          "$ref": "#/components/schemas/ShadowPayload"
        },
        "x-evidence": "src/1048:326-336, 436-486"
      },
      "ForceLiveState": {
        "name": "client-force-live-state",
        "title": "Force live state resend",
        "description": "Empty payload; both clients resend the current state.",
        "payload": {
          "type": "object",
          "additionalProperties": false
        },
        "x-evidence": "src/1048:198-200; src/1714:154-156"
      },
      "RequestScreenshotResolutionIncrease": {
        "name": "client-request-screenshot-resolution-increase",
        "title": "Screenshot resolution increase request",
        "description": "Admin asks the device to raise screenshot resolution (live-state\nv4+: 1600px instead of 500px) for a bounded duration.\n",
        "payload": {
          "type": "object",
          "required": [
            "duration"
          ],
          "properties": {
            "duration": {
              "type": "integer",
              "description": "Milliseconds, capped at 60000 server/client-side."
            }
          }
        },
        "x-evidence": "src/1048:201-204, 506-515"
      },
      "AnnotateScreenRequest": {
        "name": "client-annotate-screen-request",
        "title": "Annotate screen request",
        "description": "Teacher draws an annotation dot on the student's screen; hash\nidentifies which screenshot the coordinates apply to.\n",
        "payload": {
          "type": "object",
          "required": [
            "requestId",
            "hash",
            "xPercent",
            "yPercent",
            "diameter",
            "color",
            "opacity",
            "durationMs"
          ],
          "properties": {
            "requestId": {
              "type": "string"
            },
            "hash": {
              "type": "string",
              "description": "md5 hash of the referenced screenshot."
            },
            "xPercent": {
              "type": "number"
            },
            "yPercent": {
              "type": "number"
            },
            "diameter": {
              "type": "number"
            },
            "color": {
              "type": "string",
              "description": "#rrggbb"
            },
            "opacity": {
              "type": "number"
            },
            "durationMs": {
              "type": "integer"
            }
          }
        },
        "x-evidence": "src/1048:545-556"
      },
      "SetChatState": {
        "name": "client-set-chat-state",
        "title": "Set chat state",
        "payload": {
          "type": "object",
          "required": [
            "sessionId",
            "payload"
          ],
          "properties": {
            "sessionId": {
              "type": "integer"
            },
            "payload": {
              "type": "object",
              "required": [
                "command"
              ],
              "properties": {
                "command": {
                  "type": "string",
                  "enum": [
                    "enable_chat",
                    "disable_chat"
                  ]
                }
              }
            }
          }
        },
        "x-evidence": "src/1048:338-348"
      },
      "SetOffTaskAlertsState": {
        "name": "client-set-off-task-alerts-state",
        "title": "Set off-task alerts state",
        "payload": {
          "type": "object",
          "required": [
            "sessionId",
            "payload"
          ],
          "properties": {
            "sessionId": {
              "type": "integer"
            },
            "payload": {
              "type": "object",
              "required": [
                "enabled"
              ],
              "properties": {
                "enabled": {
                  "type": "boolean"
                }
              }
            }
          }
        },
        "x-evidence": "src/1048:353-358"
      },
      "RequestEntityFlushRateIncrease": {
        "name": "client-request-entity-flush-rate-increase",
        "title": "Entity flush rate increase request",
        "description": "Admin-only (verified via Pusher event metadata user_id prefix\n\"admin:\"): raise the surveillance entity flush rate to the fast\ninterval (1 s) for a bounded duration.\n",
        "payload": {
          "type": "object",
          "required": [
            "duration"
          ],
          "properties": {
            "duration": {
              "type": "integer",
              "description": "Milliseconds, capped at 60000."
            }
          }
        },
        "x-evidence": "src/1048:516-531"
      },
      "SmartMonitoring": {
        "name": "client-smart-monitoring",
        "title": "Smart monitoring override",
        "description": "Off-task-alerts override event. PAYLOAD UNVERIFIED — the handler is\nbound in raw/1725.js:130-135 but its fields were not inspected.\n",
        "payload": {
          "type": "object",
          "additionalProperties": true
        },
        "x-evidence": "raw/1725.js:130-135"
      },
      "MemberAdded": {
        "name": "pusher:member_added",
        "title": "Presence member added",
        "description": "Presence metadata for classroom sessions and calls. Admin members\nhave info.type \"admin\"; the member id is \"admin:<...>:<adminId>\" and\nthe extension reads the admin id via id.split(\":\")[2]. For calls,\nmember.info carries type, aid, sid, callParticipantId.\n",
        "payload": {
          "type": "object",
          "required": [
            "id",
            "info"
          ],
          "properties": {
            "id": {
              "type": "string"
            },
            "info": {
              "type": "object",
              "properties": {
                "type": {
                  "type": "string",
                  "description": "\"admin\" for admins."
                },
                "liveStateVersion": {
                  "type": "integer"
                },
                "aid": {
                  "type": "string"
                },
                "sid": {
                  "type": "string"
                },
                "callParticipantId": {
                  "type": "string"
                }
              }
            }
          }
        },
        "x-evidence": "src/1048:241-254 (session), src/1048:281-317 (call)"
      },
      "MemberRemoved": {
        "name": "pusher:member_removed",
        "title": "Presence member removed",
        "payload": {
          "type": "object",
          "required": [
            "id",
            "info"
          ],
          "properties": {
            "id": {
              "type": "string"
            },
            "info": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "x-evidence": "src/1048:241-254; src/1048:281-317"
      },
      "AdminPoliciesUpdated": {
        "name": "admin-policies-updated",
        "title": "Admin policies updated",
        "description": "Signals that admin policies changed; the extension re-fetches\nGET https://snat.goguardian.com/api/v1/ext/policy.\n",
        "payload": {
          "type": "object",
          "additionalProperties": true
        },
        "x-evidence": "src/1048:222-225"
      },
      "CallArchived": {
        "name": "call-archived",
        "title": "Call archived",
        "description": "Server event on presence-call; removes the joined call.",
        "payload": {
          "type": "object",
          "additionalProperties": true
        },
        "x-evidence": "src/1048:281-317"
      },
      "CallHangup": {
        "name": "client-call-hangup",
        "title": "Call hangup (received)",
        "description": "Received on presence-call when the peer hangs up.",
        "payload": {
          "type": "object",
          "additionalProperties": true
        },
        "x-evidence": "src/1048:281-317"
      },
      "BeaconSearch": {
        "name": "beacon-search",
        "title": "Beacon ML search result",
        "description": "Asynchronous self-harm (SSH) ML result delivered in MLP mode. The\nextension acknowledges via POST ml-endpoint /device-notifications/v1/ack.\n",
        "payload": {
          "type": "object",
          "required": [
            "type",
            "ack_id",
            "data"
          ],
          "properties": {
            "type": {
              "type": "string"
            },
            "ack_id": {
              "type": "string"
            },
            "data": {
              "type": "object",
              "required": [
                "seqId"
              ],
              "properties": {
                "seqId": {
                  "type": "integer",
                  "description": "Surveillance entity seq id the result applies to."
                }
              }
            }
          }
        },
        "x-evidence": "src/1691:50-51, 64-75, 109-145"
      },
      "BeaconThreatsAndViolence": {
        "name": "beacon-threats-and-violence",
        "title": "Beacon ML threats-and-violence result",
        "description": "Same envelope as beacon-search, TV category.",
        "payload": {
          "type": "object",
          "required": [
            "type",
            "ack_id",
            "data"
          ],
          "properties": {
            "type": {
              "type": "string"
            },
            "ack_id": {
              "type": "string"
            },
            "data": {
              "type": "object",
              "required": [
                "seqId"
              ],
              "properties": {
                "seqId": {
                  "type": "integer"
                }
              }
            }
          }
        },
        "x-evidence": "src/1691:50-51, 64-75, 109-145"
      }
    },
    "schemas": {
      "LiveState": {
        "type": "object",
        "description": "The live-state payload sent every 3 s (task \"sendStateData\",\ndebounced 250 ms / maxWait 1 s; deduped unless unchanged within 20 s\nfor liveStateVersion >= 2; skipped entirely when no admins are\npresent). When the encoded size exceeds PAYLOAD_MAX_SIZE = 20480\nbytes, the payload is trimmed: tabs are sorted by URL length\ndescending, titles are truncated at 128 chars with \"...\", URLs are\nbyte-safe truncated (module 1718), and inactive tabs are dropped\nentirely until it fits.\n",
        "required": [
          "accountId",
          "subaccountId",
          "orgId",
          "monitoringRestricted",
          "imageUrl",
          "locked",
          "resolvedConflict",
          "os",
          "winAppConnected",
          "idle",
          "time",
          "id"
        ],
        "properties": {
          "accountId": {
            "type": "integer"
          },
          "subaccountId": {
            "type": "integer"
          },
          "orgId": {
            "type": "integer"
          },
          "monitoringRestricted": {
            "type": "boolean",
            "description": "true when admin.monitorEnabled is false."
          },
          "imageUrl": {
            "type": "string",
            "description": "Uploaded /v1/snapshots URL (empty when restricted)."
          },
          "locked": {
            "type": "boolean"
          },
          "lessonPlanId": {
            "type": "integer"
          },
          "lessonPlanSessionId": {
            "type": "integer"
          },
          "lessonPlanAdminId": {
            "type": "integer"
          },
          "lessonPlanAdminName": {
            "type": "string"
          },
          "resolvedConflict": {
            "type": "boolean"
          },
          "apps": {
            "type": "array",
            "description": "Windows native-app list (empty off Windows).",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "tabs": {
            "type": "object",
            "description": "Map keyed by string tabId.",
            "additionalProperties": {
              "type": "object",
              "required": [
                "id",
                "title",
                "url",
                "active",
                "faviconUrl",
                "lastActiveMs",
                "isFocused"
              ],
              "properties": {
                "id": {
                  "type": "integer"
                },
                "title": {
                  "type": "string"
                },
                "url": {
                  "type": "string"
                },
                "active": {
                  "type": "boolean"
                },
                "faviconUrl": {
                  "type": "string"
                },
                "lastActiveMs": {
                  "type": "integer"
                },
                "isFocused": {
                  "type": "boolean"
                },
                "videos": {
                  "type": "array",
                  "description": "YouTube video metadata; item shape unverified.",
                  "items": {
                    "type": "object",
                    "additionalProperties": true
                  }
                }
              }
            }
          },
          "taskiness": {
            "type": "object",
            "description": "offTaskAlerts.taskiness[activeTabId] or {}.",
            "additionalProperties": true
          },
          "os": {
            "type": "string",
            "description": "platform.getPlatform() string."
          },
          "winAppConnected": {
            "type": "boolean",
            "description": "Windows native messaging port connected."
          },
          "idle": {
            "type": "object",
            "required": [
              "currentState",
              "durationMs"
            ],
            "properties": {
              "currentState": {
                "type": "string"
              },
              "durationMs": {
                "type": "integer"
              }
            }
          },
          "time": {
            "type": "integer",
            "description": "Math.floor(Date.now()/1000) — epoch seconds."
          },
          "id": {
            "type": "string",
            "description": "uuid.v4()."
          }
        },
        "x-evidence": "src/1715:221-279, 281-318 (trim), 365-368; src/336:25"
      },
      "ShadowPayload": {
        "type": "object",
        "description": "The admin shadow: desired device state. Applied by the extension and\nacked with client-shadow-applied.\n",
        "required": [
          "shadowId"
        ],
        "properties": {
          "shadowId": {
            "type": "integer"
          },
          "chatEnabled": {
            "type": "object",
            "description": "Session object gating chat; shape from reducer.",
            "additionalProperties": true
          },
          "locked": {
            "type": "boolean"
          },
          "lockMessage": {
            "type": "string"
          },
          "lockSessionId": {
            "type": "integer"
          },
          "tabCommands": {
            "type": "array",
            "items": {
              "type": "object",
              "required": [
                "type",
                "applied",
                "shadowId"
              ],
              "properties": {
                "type": {
                  "type": "string",
                  "enum": [
                    "openTab",
                    "closeTab",
                    "focusTab",
                    "unfocusTab",
                    "closeApp",
                    "checkIn",
                    "setActiveTab"
                  ]
                },
                "applied": {
                  "type": "boolean"
                },
                "shadowId": {
                  "type": "integer"
                },
                "expiresAt": {
                  "type": "integer",
                  "description": "Epoch seconds."
                },
                "url": {
                  "type": "string",
                  "description": "For openTab."
                },
                "tabId": {
                  "type": "integer",
                  "description": "For closeTab/setActiveTab."
                },
                "isFocused": {
                  "type": "boolean",
                  "description": "For openTab (focus-lock)."
                },
                "lessonPlanId": {
                  "type": "integer"
                }
              }
            }
          },
          "focusSessionId": {
            "type": "integer"
          },
          "lessonPlanShadowId": {
            "type": "integer"
          },
          "lessonPlanId": {
            "type": "integer"
          },
          "lessonPlanSessionId": {
            "type": "integer"
          },
          "lessonPlanAdminId": {
            "type": "integer"
          },
          "lessonPlanAdminName": {
            "type": "string"
          },
          "resolvedConflict": {
            "type": "boolean"
          },
          "activeCalls": {
            "type": "array",
            "description": "Active calls; observed fields: callId, callType (\"1:1\"|\"group\"|\n\"presentation\"), videoBackend (\"twilio\"), participantId,\nacknowledged, forceRinging. Full item schema unverified (reducer\n877 not read).\n",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          },
          "checkIns": {
            "type": "array",
            "description": "Check-in assignments; item schema unverified (reducer 834 not read).",
            "items": {
              "type": "object",
              "additionalProperties": true
            }
          }
        },
        "x-evidence": "src/1048:436-486; raw/1051.js (observed call fields)"
      }
    }
  }
}