Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion spec/mcp-catalog.json
Original file line number Diff line number Diff line change
Expand Up @@ -2000,7 +2000,7 @@
},
"self_update": {
"default": null,
"description": "Self-update status for the reporting binary. The ONLY check is that the value is an object - anything else is a flat 400, 'self_update must be an object' - and nothing inside it is checked. What you send IS kept: it is merged onto this reporter's telemetry entry. But the reply is a bounded receipt (agent_id, machine, ts), not the stored entry echoed back, so nothing you sent comes back on this response and a misspelled sub-key is simply never used by anything. The one place a wrong shape shows up is a line on the SERVER's stderr, which prints binary, old_hash, new_hash and at, substituting '?' for whatever is missing - and you cannot see it. Two consequences worth planning for: that entry is an IN-MEMORY map, so everything here is gone the moment the server re-execs; and this endpoint MERGES, so omitting self_update does not clear it - the previous report's value stays on the entry. Call get_monitoring when you need to read the entry back.",
"description": "Self-update status for the reporting binary. The ONLY check is that the value is an object - anything else is a flat 400, 'self_update must be an object' - and nothing inside it is checked. What you send is kept only in this reporter's in-memory telemetry entry and emits one summary line on the SERVER's stderr, which prints binary, old_hash, new_hash and at, substituting '?' for whatever is missing. The bounded receipt does not echo it, and get_monitoring does not expose it. The entry disappears when the server re-execs, and because this endpoint MERGES, omitting self_update does not clear the previous in-memory value.",
"title": "Self Update"
},
"tokens": {
Expand Down
2 changes: 1 addition & 1 deletion spec/openapi.json
Original file line number Diff line number Diff line change
Expand Up @@ -16398,7 +16398,7 @@
"name": "ingest_telemetry",
"description": "Ingest warden telemetry (hardware/limits/tokens/cost/self_update). Answers with a bounded receipt (``agent_id``, ``machine``, ``ts``), not the stored entry echoed back — call ``get_monitoring`` when you need the rest.",
"legacy": {
"descriptor": "{\n \"description\": \"Ingest warden telemetry (hardware/limits/tokens/cost/self_update). Answers with a bounded receipt (``agent_id``, ``machine``, ``ts``), not the stored entry echoed back \\u2014 call ``get_monitoring`` when you need the rest.\",\n \"inputSchema\": {\n \"properties\": {\n \"account\": {\n \"default\": null,\n \"description\": \"Which billing account this session is drawing on. It is READ ONLY IN COMPANY WITH runtime, and the failure is worse than a dropped field: send a perfectly valid account WITHOUT runtime and the server does not merely ignore it, it CLEARS the account pairing already recorded for this entry and returns 200. A previously correct display therefore goes blank because of a report that carried the right value. A non-string value is dropped silently to empty by the same path. Always send runtime alongside account.\",\n \"title\": \"Account\"\n },\n \"account_label\": {\n \"default\": null,\n \"description\": \"Human-readable label for the account. It rides the same path as account - read only in company with runtime, dropped silently when the value is not a string - and it is HARDER to notice going wrong than account is, because the ingest response does not echo it back at all. There is no field in the reply to compare against what you sent, so a dropped label is invisible from the call site; the only way to see it is to read the monitoring view afterwards.\",\n \"title\": \"Account Label\"\n },\n \"binaries\": {\n \"default\": null,\n \"description\": \"Warden heartbeats only — the content fingerprint of the binaries this host is ACTUALLY running: an object keyed by binary name (ocwarden, ocagent, officraft) whose values are that live file's sha256 12-hex prefix. The server diffs them against the build it has embedded to derive the machine's bin_status (current / stale / absent = honest unknown), so a heartbeat that omits this leaves the machine's upgrade state unknowable rather than current. Deliberately a content hash, not a version number.\",\n \"title\": \"Binaries\"\n },\n \"claude\": {\n \"default\": null,\n \"description\": \"Warden heartbeats only — the host's local claude CLI probe. Presence-only, NEVER a secret value. All sub-fields optional: version (string — the resolved claude binary's --version first token; absent = unresolved or probe failed), cred_file (bool — ~/.claude/.credentials.json exists), sub_readable (bool — that file exists AND its claudeAiOauth.subscriptionType is non-blank, the exact readability the account-key derivation needs), keychain (bool — macOS login-keychain item present; ABSENT, not false, on non-darwin where the probe cannot answer). Send it so the roster can tell whether this host can actually run Claude.\",\n \"title\": \"Claude\",\n \"type\": \"object\"\n },\n \"command_result\": {\n \"default\": null,\n \"description\": \"Receipt for a command this reporter was asked to run. The only check is that the value is an object. Everything inside is best-effort: an unknown member id, an unknown worker, or a receipt that matches no outstanding command is written to the server's stderr and then swallowed, and the call answers 200 either way. A 200 here means the report was accepted, NOT that it was matched to anything - if you need to know the result was recorded, read the state it should have changed.\",\n \"title\": \"Command Result\"\n },\n \"cost\": {\n \"default\": null,\n \"description\": \"Accumulated cost for this session. The ONLY check is that the value is a number - there is no sign check, no unit check and no upper or lower bound, so a negative figure, a value in the wrong currency, or one off by a factor of a thousand is stored verbatim and answers 200. It becomes what the monitoring view reports, so the number is trusted exactly as far as the caller computing it.\",\n \"title\": \"Cost\"\n },\n \"effort\": {\n \"default\": null,\n \"description\": \"The reasoning-effort level this session is actually running at. The ONLY check is that the value is a string: unlike hire_member and update_member, which validate against the known effort levels, this path deliberately does NOT, so any string at all is accepted and overwrites the recorded effort. A typo is not refused, it is displayed - the monitoring view will report whatever you sent as though it were a real level.\",\n \"title\": \"Effort\"\n },\n \"hardware\": {\n \"default\": null,\n \"description\": \"Hardware readings for this machine. Nothing is validated AT INGEST: keys the schema does not declare are stored and then never read by anything, and a declared key carrying the wrong type is accepted here and only surfaces much later, on the READ side, as an entry in hardware_invalid. So a 200 from this call says nothing about whether the readings will be usable - the report and the complaint are separated by a whole round trip.\",\n \"title\": \"Hardware\"\n },\n \"machine\": {\n \"default\": null,\n \"description\": \"Which machine this telemetry is about. It is CONSULTED ONLY IF the caller's token carries no machine claim: when the token does carry one, this field is not compared, not validated and not reported on - it is simply never read, and the call answers 200 exactly as if it had been honoured. So a wrong value here is undetectable from the response, and a right value is redundant. Send it only when reporting from a caller whose token is not already bound to a machine.\",\n \"title\": \"Machine\"\n },\n \"model\": {\n \"default\": null,\n \"description\": \"The model this session is actually running. The only check is that the value is a string, and there is no allow-list - an unknown or misspelled model is stored and displayed as though real. An EMPTY string is a silent no-op: it is accepted, changes nothing, and answers 200 like any other report, so 'I reported the model' and 'the model was recorded' are not the same statement.\",\n \"title\": \"Model\"\n },\n \"rate_limits\": {\n \"default\": null,\n \"description\": \"Rate-limit state for this account. The ONLY check is that the value is an object; every key and value inside is stored unvalidated, so a misspelled key or a wrong unit is accepted and answers 200. What is stored here drives the pacing figures a reader sees, so a wrong shape does not fail loudly - it produces a confident-looking number that is not true.\",\n \"title\": \"Rate Limits\"\n },\n \"runtime\": {\n \"default\": null,\n \"title\": \"Runtime\"\n },\n \"runtimes\": {\n \"default\": null,\n \"title\": \"Runtimes\"\n },\n \"self_update\": {\n \"default\": null,\n \"description\": \"Self-update status for the reporting binary. The ONLY check is that the value is an object - anything else is a flat 400, 'self_update must be an object' - and nothing inside it is checked. What you send IS kept: it is merged onto this reporter's telemetry entry. But the reply is a bounded receipt (agent_id, machine, ts), not the stored entry echoed back, so nothing you sent comes back on this response and a misspelled sub-key is simply never used by anything. The one place a wrong shape shows up is a line on the SERVER's stderr, which prints binary, old_hash, new_hash and at, substituting '?' for whatever is missing - and you cannot see it. Two consequences worth planning for: that entry is an IN-MEMORY map, so everything here is gone the moment the server re-execs; and this endpoint MERGES, so omitting self_update does not clear it - the previous report's value stays on the entry. Call get_monitoring when you need to read the entry back.\",\n \"title\": \"Self Update\"\n },\n \"tokens\": {\n \"default\": null,\n \"description\": \"Token counters for this session. The ONLY check is that the value is an object - the shape INSIDE it is not validated at all, so a misspelled counter name, a missing field or a string where a number belongs is stored as sent and answers 200. Nothing downstream will tell you the shape was wrong; the counters simply do not add up wherever they are read.\",\n \"title\": \"Tokens\"\n }\n },\n \"additionalProperties\": false,\n \"type\": \"object\"\n },\n \"name\": \"ingest_telemetry\"\n }"
"descriptor": "{\n \"description\": \"Ingest warden telemetry (hardware/limits/tokens/cost/self_update). Answers with a bounded receipt (``agent_id``, ``machine``, ``ts``), not the stored entry echoed back \\u2014 call ``get_monitoring`` when you need the rest.\",\n \"inputSchema\": {\n \"properties\": {\n \"account\": {\n \"default\": null,\n \"description\": \"Which billing account this session is drawing on. It is READ ONLY IN COMPANY WITH runtime, and the failure is worse than a dropped field: send a perfectly valid account WITHOUT runtime and the server does not merely ignore it, it CLEARS the account pairing already recorded for this entry and returns 200. A previously correct display therefore goes blank because of a report that carried the right value. A non-string value is dropped silently to empty by the same path. Always send runtime alongside account.\",\n \"title\": \"Account\"\n },\n \"account_label\": {\n \"default\": null,\n \"description\": \"Human-readable label for the account. It rides the same path as account - read only in company with runtime, dropped silently when the value is not a string - and it is HARDER to notice going wrong than account is, because the ingest response does not echo it back at all. There is no field in the reply to compare against what you sent, so a dropped label is invisible from the call site; the only way to see it is to read the monitoring view afterwards.\",\n \"title\": \"Account Label\"\n },\n \"binaries\": {\n \"default\": null,\n \"description\": \"Warden heartbeats only — the content fingerprint of the binaries this host is ACTUALLY running: an object keyed by binary name (ocwarden, ocagent, officraft) whose values are that live file's sha256 12-hex prefix. The server diffs them against the build it has embedded to derive the machine's bin_status (current / stale / absent = honest unknown), so a heartbeat that omits this leaves the machine's upgrade state unknowable rather than current. Deliberately a content hash, not a version number.\",\n \"title\": \"Binaries\"\n },\n \"claude\": {\n \"default\": null,\n \"description\": \"Warden heartbeats only — the host's local claude CLI probe. Presence-only, NEVER a secret value. All sub-fields optional: version (string — the resolved claude binary's --version first token; absent = unresolved or probe failed), cred_file (bool — ~/.claude/.credentials.json exists), sub_readable (bool — that file exists AND its claudeAiOauth.subscriptionType is non-blank, the exact readability the account-key derivation needs), keychain (bool — macOS login-keychain item present; ABSENT, not false, on non-darwin where the probe cannot answer). Send it so the roster can tell whether this host can actually run Claude.\",\n \"title\": \"Claude\",\n \"type\": \"object\"\n },\n \"command_result\": {\n \"default\": null,\n \"description\": \"Receipt for a command this reporter was asked to run. The only check is that the value is an object. Everything inside is best-effort: an unknown member id, an unknown worker, or a receipt that matches no outstanding command is written to the server's stderr and then swallowed, and the call answers 200 either way. A 200 here means the report was accepted, NOT that it was matched to anything - if you need to know the result was recorded, read the state it should have changed.\",\n \"title\": \"Command Result\"\n },\n \"cost\": {\n \"default\": null,\n \"description\": \"Accumulated cost for this session. The ONLY check is that the value is a number - there is no sign check, no unit check and no upper or lower bound, so a negative figure, a value in the wrong currency, or one off by a factor of a thousand is stored verbatim and answers 200. It becomes what the monitoring view reports, so the number is trusted exactly as far as the caller computing it.\",\n \"title\": \"Cost\"\n },\n \"effort\": {\n \"default\": null,\n \"description\": \"The reasoning-effort level this session is actually running at. The ONLY check is that the value is a string: unlike hire_member and update_member, which validate against the known effort levels, this path deliberately does NOT, so any string at all is accepted and overwrites the recorded effort. A typo is not refused, it is displayed - the monitoring view will report whatever you sent as though it were a real level.\",\n \"title\": \"Effort\"\n },\n \"hardware\": {\n \"default\": null,\n \"description\": \"Hardware readings for this machine. Nothing is validated AT INGEST: keys the schema does not declare are stored and then never read by anything, and a declared key carrying the wrong type is accepted here and only surfaces much later, on the READ side, as an entry in hardware_invalid. So a 200 from this call says nothing about whether the readings will be usable - the report and the complaint are separated by a whole round trip.\",\n \"title\": \"Hardware\"\n },\n \"machine\": {\n \"default\": null,\n \"description\": \"Which machine this telemetry is about. It is CONSULTED ONLY IF the caller's token carries no machine claim: when the token does carry one, this field is not compared, not validated and not reported on - it is simply never read, and the call answers 200 exactly as if it had been honoured. So a wrong value here is undetectable from the response, and a right value is redundant. Send it only when reporting from a caller whose token is not already bound to a machine.\",\n \"title\": \"Machine\"\n },\n \"model\": {\n \"default\": null,\n \"description\": \"The model this session is actually running. The only check is that the value is a string, and there is no allow-list - an unknown or misspelled model is stored and displayed as though real. An EMPTY string is a silent no-op: it is accepted, changes nothing, and answers 200 like any other report, so 'I reported the model' and 'the model was recorded' are not the same statement.\",\n \"title\": \"Model\"\n },\n \"rate_limits\": {\n \"default\": null,\n \"description\": \"Rate-limit state for this account. The ONLY check is that the value is an object; every key and value inside is stored unvalidated, so a misspelled key or a wrong unit is accepted and answers 200. What is stored here drives the pacing figures a reader sees, so a wrong shape does not fail loudly - it produces a confident-looking number that is not true.\",\n \"title\": \"Rate Limits\"\n },\n \"runtime\": {\n \"default\": null,\n \"title\": \"Runtime\"\n },\n \"runtimes\": {\n \"default\": null,\n \"title\": \"Runtimes\"\n },\n \"self_update\": {\n \"default\": null,\n \"description\": \"Self-update status for the reporting binary. The ONLY check is that the value is an object - anything else is a flat 400, 'self_update must be an object' - and nothing inside it is checked. What you send is kept only in this reporter's in-memory telemetry entry and emits one summary line on the SERVER's stderr, which prints binary, old_hash, new_hash and at, substituting '?' for whatever is missing. The bounded receipt does not echo it, and get_monitoring does not expose it. The entry disappears when the server re-execs, and because this endpoint MERGES, omitting self_update does not clear the previous in-memory value.\",\n \"title\": \"Self Update\"\n },\n \"tokens\": {\n \"default\": null,\n \"description\": \"Token counters for this session. The ONLY check is that the value is an object - the shape INSIDE it is not validated at all, so a misspelled counter name, a missing field or a string where a number belongs is stored as sent and answers 200. Nothing downstream will tell you the shape was wrong; the counters simply do not add up wherever they are read.\",\n \"title\": \"Tokens\"\n }\n },\n \"additionalProperties\": false,\n \"type\": \"object\"\n },\n \"name\": \"ingest_telemetry\"\n }"
}
}
}
Expand Down
Loading