{
  "title": "Rightshold Diagnostics",
  "about": "Diagnostics is the help-desk mirror in agent form: precall troubleshooting and conformance support, assembled as one derived-at-read-time index over the troubleshooting facts the platform already publishes. Six topics, each grounded in the module that owns its facts. Three cover a failed or puzzling pre-call check — the request itself (the two catalog errors a malformed check returns, carried verbatim from the error catalog), the integrity outcomes (unchanged, changed, unreachable, not registered — what each means and what to do next), and the scan, flags and collisions the rest of the answer carries. Two cover conformance support — reading a failed check from its own detail against the published checklist, and the verifier conformance vectors, whose altered copies are labeled with the checks that must fail. The sixth is the error catalog itself, the support backbone every answer's code resolves against. Every topic names the keyless checks an agent can run to diagnose the problem itself, the outcome signals those checks can return, and the next step for each. This index stores nothing, runs no probe or check of its own, and creates no record: the checks it names are the owning modules' existing routes. A pre-call answer is evidence to decide from — never a finding that a tool is safe — and a conformance result is reported by the deployment itself. There is no human help desk, ticket system, support inbox or chat here, and none is claimed: support is this self-serve, deterministic, machine-readable form.",
  "method": "rightshold-diagnostics-v1",
  "rules": "Topics: the fixed set — precall-request, precall-integrity, precall-scan-and-flags, conformance-failures, conformance-vectors, error-catalog — in that order; a name outside the set is not a diagnostic topic and has no entry. Every fact on a topic is one its owning module already publishes: the pre-call answer's outcome shapes and notes, the URL and tool rules behind its two request errors, the conformance checklist (version, checks, and what each check proves), the verifier vectors' published description, and error-catalog entries carried verbatim (typical status, retryable, action). The conformance check count derives from the published checklist and the catalog size from the catalog itself. Conformance runs are computed live and stored nowhere, so no run count exists or is shown; no pre-call call is counted either (the check is keyless and unrecorded). Nothing is stored: every read recomputes from the owning modules' documents and catalog.",
  "totals": {
    "topics": 6,
    "conformance_checks": 12,
    "error_codes": 481
  },
  "topics": [
    {
      "id": "precall-request",
      "name": "Precall: the request itself",
      "kind": "precall troubleshooting",
      "about": "When a pre-call check does not run at all, the refusal is one of two catalog errors, and the fix is in the request. The check takes the MCP server's URL and, optionally, one tool name to focus the answer on. The URL must be https — http is accepted only for a loopback address — and a URL naming a private, link-local or reserved address is not fetched. The tool name, when one is sent, must be a tool name of 200 characters or fewer. Both errors carry what to send instead, verbatim in the record below and at the error catalog.",
      "entry_points": {
        "precall": "https://www.rightshold.com/v1/security/precall",
        "errors": "https://www.rightshold.com/v1/errors",
        "spec": "https://www.rightshold.com/security/spec"
      },
      "checks": [
        "GET /v1/security/precall?url=<the MCP server's https URL> — the check itself; add &tool=<tool name> to focus the answer on one tool.",
        "GET /v1/errors/invalid_server_url and GET /v1/errors/invalid_precall — the two refusals, with their typical status and the action each names."
      ],
      "outcomes": [
        {
          "signal": "invalid_server_url (422)",
          "meaning": "The url was missing or malformed, was not https (http is accepted only for a loopback address), or named a private, link-local or reserved address, which this service does not fetch.",
          "next_step": "Send the remote MCP server's https URL (http only for a loopback address). URLs naming — or resolving to — private, link-local or reserved addresses are not fetched."
        },
        {
          "signal": "invalid_precall (422)",
          "meaning": "The request reached the check but the tool focus was not usable: a tool name must be a string of 200 characters or fewer.",
          "next_step": "Send ?url=<the MCP server's https URL> and optionally ?tool=<a tool name of 200 characters or fewer>."
        }
      ],
      "record": {
        "error_codes": [
          {
            "code": "invalid_server_url",
            "typical_status": 422,
            "retryable": false,
            "action": "Send the remote MCP server's https URL (http only for a loopback address). URLs naming — or resolving to — private, link-local or reserved addresses are not fetched."
          },
          {
            "code": "invalid_precall",
            "typical_status": 422,
            "retryable": false,
            "action": "Send ?url=<the MCP server's https URL> and optionally ?tool=<a tool name of 200 characters or fewer>."
          }
        ],
        "https_required": true,
        "tool_max_characters": 200
      },
      "record_url": "https://www.rightshold.com/diagnostics/precall-request"
    },
    {
      "id": "precall-integrity",
      "name": "Precall: integrity outcomes",
      "kind": "precall troubleshooting",
      "about": "A pre-call answer's integrity block compares the tool definitions a server serves now with the fingerprint recorded earlier, and reports exactly one of four statuses. Unchanged is the only status that says the definitions match the record — and it is not a finding that a tool is safe. Changed carries a plain diff of how the definitions differ. Unreachable means the server could not be probed for this check, so nothing can be said about its current definitions — it is never reported as unchanged. Not registered means the server was probed for this answer only: there is no recorded fingerprint to compare against, the fingerprint in the answer is what it serves now, computed for the answer and not stored, and checking a server does not register it.",
      "entry_points": {
        "precall": "https://www.rightshold.com/v1/security/precall",
        "external_servers": "https://www.rightshold.com/v1/store/external",
        "definition_changes": "https://www.rightshold.com/v1/security/changes"
      },
      "checks": [
        "GET /v1/security/precall?url=<server URL> — read integrity.status, integrity.detail and, when present, integrity.diff.",
        "GET /v1/security/changes — the definition-change feed the integrity check feeds, for what changed and when.",
        "GET /v1/store/external — the registry record a registered server's fingerprint and history live on."
      ],
      "outcomes": [
        {
          "signal": "unchanged",
          "meaning": "The definitions the server serves now match the fingerprint recorded earlier.",
          "next_step": "Read the rest of the answer before relying on the tool — the scan, the standing flags and the review aggregate are separate evidence, and unchanged is not a finding that a tool is safe."
        },
        {
          "signal": "changed",
          "meaning": "The definitions differ from the record; the answer's diff says how.",
          "next_step": "Read the diff in the answer and the definition-change feed, then decide from the new definitions — re-run the pre-call check after any fix so the answer reflects what the server serves now."
        },
        {
          "signal": "unreachable",
          "meaning": "The server could not be probed for this check, so nothing can be said about its current definitions.",
          "next_step": "Check the URL and that the server is up, then run the pre-call check again; the tool focus in such an answer rests on the last recorded definitions, and says so."
        },
        {
          "signal": "not_registered",
          "meaning": "The server is not in the registry, so there is no recorded fingerprint and no history to read; it was probed for this answer only.",
          "next_step": "Decide from this answer's fresh probe and scan, or register the server (POST /v1/store/external) so later checks compare against a recorded fingerprint. If the URL redirected, register the destination directly — the answer names it as the effective URL."
        }
      ],
      "record": {
        "statuses": [
          "unchanged",
          "changed",
          "unreachable",
          "not_registered"
        ],
        "note": "An integrity check compares the tool definitions a server serves now with the fingerprint recorded earlier. \"Unchanged\" means the definitions match what was recorded — it is not a finding that a tool is safe. \"Changed\" means the definitions differ from the record; the diff says how. \"Unreachable\" means the server could not be probed for this check, so nothing can be said about its current definitions."
      },
      "record_url": "https://www.rightshold.com/diagnostics/precall-integrity"
    },
    {
      "id": "precall-scan-and-flags",
      "name": "Precall: scan, flags and collisions",
      "kind": "precall troubleshooting",
      "about": "The rest of a pre-call answer: a fresh scan of the definitions the server serves now for content a reader cannot see (clean, flagged with the findings, or not run when the server could not be probed); the standing-flag status from the permanent flags registry (standing flags recorded against the server, or none recorded — the absence of a record, not a finding that the server is safe); tool-name collision (shadowing) warnings when another registered server offers the same tool name with a different definition — a fact about names, not an accusation against any server; the review aggregate from KYA-verified agents, bound to the fingerprint version each review was written against; and, when a tool name is given, whether that tool is offered and on what basis that is said.",
      "entry_points": {
        "precall": "https://www.rightshold.com/v1/security/precall",
        "flags": "https://www.rightshold.com/v1/security/flags",
        "scan_text": "https://www.rightshold.com/v1/security/scan-text"
      },
      "checks": [
        "GET /v1/security/precall?url=<server URL>&tool=<tool name> — read scan.status and findings, flags.status and standing flag ids, shadowing_warnings, and tool_focus.offered with its basis.",
        "GET /v1/security/flags — the permanent flags registry, for the evidence behind a standing flag.",
        "POST /v1/security/scan-text — the same invisible-text scan, run on text an agent names."
      ],
      "outcomes": [
        {
          "signal": "scan flagged",
          "meaning": "The definitions served now contain content a reader cannot see; the findings name the fields, the classes and the evidence. The check reports the findings; it does not record them — flags are created when content is submitted to, pulled into, or refreshed in the registry.",
          "next_step": "Read the findings before relying on the tool, and read the flagged definitions themselves at the server — the excerpt is evidence, and the decision is the caller's."
        },
        {
          "signal": "scan clean",
          "meaning": "No deterministic invisible-content findings in the definitions served now.",
          "next_step": "Treat it as one part of the answer, not the whole answer: a clean scan is not a finding that the tools are safe."
        },
        {
          "signal": "scan not_run",
          "meaning": "The server could not be probed, so its current definitions were not scanned.",
          "next_step": "Fix the reachability first (see the integrity outcome in the same answer), then re-run the pre-call check so the scan runs on what the server serves."
        },
        {
          "signal": "standing_flags",
          "meaning": "Standing security flags are recorded against this server in the permanent registry; the answer carries their ids.",
          "next_step": "Read the flags at GET /v1/security/flags before relying on the server — a flag records that invisible content was found in a submission; read the evidence."
        },
        {
          "signal": "no_standing_flags",
          "meaning": "No standing security flags are recorded against this server.",
          "next_step": "Read it as the absence of a record, not a finding that the server is safe; weigh the rest of the answer."
        },
        {
          "signal": "shadowing warning",
          "meaning": "Another registered server offers the same tool name with a different definition.",
          "next_step": "Confirm which server the call will actually reach — the name alone does not identify the definition — before calling the tool."
        },
        {
          "signal": "tool not offered",
          "meaning": "The named tool is not among the definitions behind the tool focus; when the server could not be probed, offered is null and the basis says the focus could not be determined.",
          "next_step": "Check the tool name against the definitions the answer rests on (the basis names them), or drop the tool focus to read the server's whole answer."
        }
      ],
      "record": {
        "scan_statuses": [
          "clean",
          "flagged",
          "not_run"
        ],
        "flag_statuses": [
          "no_standing_flags",
          "standing_flags"
        ],
        "note": "A pre-call check is evidence gathered at one moment: what the server served when probed, what the registry recorded before, and what verified agents have reported. It is not a guarantee that a tool is safe, honest or lawful to use — it is the record to decide from."
      },
      "record_url": "https://www.rightshold.com/diagnostics/precall-scan-and-flags"
    },
    {
      "id": "conformance-failures",
      "name": "Conformance: reading a failed check",
      "kind": "conformance support",
      "about": "Conformance is the public black-box checklist a deployment runs against its own public surface. Every check names the exact request it makes, so anyone can re-run any check independently; a check that cannot even be attempted is a failure with the reason in its detail, never a silent skip. A deployment is Rightshold Certified only while every check passes, and the result is reported by the deployment itself — stated as such in the answer. Runs are computed live and are not stored: there is no conformance run record, so this topic carries the checklist itself — its version and its checks, each with what it proves — and never a count of runs.",
      "entry_points": {
        "page": "https://www.rightshold.com/conformance",
        "api": "https://www.rightshold.com/v1/conformance",
        "badge": "https://www.rightshold.com/conformance/badge.svg"
      },
      "checks": [
        "Discovery documents: The manifest, the OpenAPI description and the agent entry point (llms.txt) are all served, so an agent that has never heard of Rightshold can bootstrap from a bare URL.",
        "Agent card: The well-known agent card names the platform and its endpoints, so crawlers and agent frameworks can identify the deployment.",
        "MCP initialize: The MCP endpoint answers a protocol initialize and identifies itself as the Rightshold server with a supported protocol version.",
        "MCP core tools: tools/list exposes the core rights, identity and ledger tools an agent integration depends on (ask_rightshold, check_license, kya_lookup, verify_rights_manifest, ledger_verify).",
        "KYA configuration: The open RS-KYA standard's levels (L0–L2) are published at the well-known configuration and at /v1/kya, so relying parties can read the level definitions from the deployment itself.",
        "Issuer keys published: The keys that sign registration certificates and ledger blocks are published with their status, so signatures can be verified without trusting the deployment.",
        "JWKS published: The JSON Web Key Set behind kya+jwt tokens is served, so tokens can be verified offline.",
        "Honest pricing document: The machine-readable pricing lists every line with its planned price, states that nothing is charged during the preview, and names placement, grades and verdicts as never for sale.",
        "Ledger head served: The public append-only ledger answers with its signed head block, so history is inspectable from the outside.",
        "Published rate limits: The limits are published at /v1/limits and every API response carries its remaining budget, so agents can pace themselves instead of guessing.",
        "Ask answers deterministically: A plain-English rights question gets a deterministic license verdict (permitted, prohibited, needs_review or not_documented) — the decision agents actually rely on.",
        "A2A endpoint: The A2A (Agent2Agent) endpoint the agent card names as its url answers message/send with a completed task carrying the structured result, and tasks/get returns the same task — so A2A-native agents can work with the deployment, not just read its card."
      ],
      "outcomes": [
        {
          "signal": "a check fails",
          "meaning": "The check's detail names the exact request it made, the status it got back, and what was missing or different — that detail is the diagnosis.",
          "next_step": "Re-run the exact request the detail names against the deployment, fix what it shows on the deployment's own surface, then run GET /v1/conformance again — the MCP check_conformance tool runs the same checklist against a deployment an agent names (https only; http only for localhost)."
        },
        {
          "signal": "a check cannot be attempted",
          "meaning": "A network error or timeout while running a check is reported as a failure with the reason in the detail.",
          "next_step": "Read the reason in the detail, confirm the deployment answers at its public base URL, and re-run the checklist."
        },
        {
          "signal": "not_certified",
          "meaning": "At least one check failed, so the deployment is not Rightshold Certified at that moment; the summary counts pass, fail and skip across the checklist.",
          "next_step": "Work the failing checks from their details — certification is the state where every check passes, and it is read from a fresh run, not stored."
        }
      ],
      "record": {
        "checklist_version": "2026-10-12",
        "checks": 12,
        "checklist": [
          {
            "id": "discovery-documents",
            "label": "Discovery documents",
            "proves": "The manifest, the OpenAPI description and the agent entry point (llms.txt) are all served, so an agent that has never heard of Rightshold can bootstrap from a bare URL."
          },
          {
            "id": "agent-card",
            "label": "Agent card",
            "proves": "The well-known agent card names the platform and its endpoints, so crawlers and agent frameworks can identify the deployment."
          },
          {
            "id": "mcp-initialize",
            "label": "MCP initialize",
            "proves": "The MCP endpoint answers a protocol initialize and identifies itself as the Rightshold server with a supported protocol version."
          },
          {
            "id": "mcp-core-tools",
            "label": "MCP core tools",
            "proves": "tools/list exposes the core rights, identity and ledger tools an agent integration depends on (ask_rightshold, check_license, kya_lookup, verify_rights_manifest, ledger_verify)."
          },
          {
            "id": "kya-configuration",
            "label": "KYA configuration",
            "proves": "The open RS-KYA standard's levels (L0–L2) are published at the well-known configuration and at /v1/kya, so relying parties can read the level definitions from the deployment itself."
          },
          {
            "id": "issuer-keys",
            "label": "Issuer keys published",
            "proves": "The keys that sign registration certificates and ledger blocks are published with their status, so signatures can be verified without trusting the deployment."
          },
          {
            "id": "jwks",
            "label": "JWKS published",
            "proves": "The JSON Web Key Set behind kya+jwt tokens is served, so tokens can be verified offline."
          },
          {
            "id": "pricing-honest",
            "label": "Honest pricing document",
            "proves": "The machine-readable pricing lists every line with its planned price, states that nothing is charged during the preview, and names placement, grades and verdicts as never for sale."
          },
          {
            "id": "ledger-head",
            "label": "Ledger head served",
            "proves": "The public append-only ledger answers with its signed head block, so history is inspectable from the outside."
          },
          {
            "id": "rate-limit-transparency",
            "label": "Published rate limits",
            "proves": "The limits are published at /v1/limits and every API response carries its remaining budget, so agents can pace themselves instead of guessing."
          },
          {
            "id": "ask-answers",
            "label": "Ask answers deterministically",
            "proves": "A plain-English rights question gets a deterministic license verdict (permitted, prohibited, needs_review or not_documented) — the decision agents actually rely on."
          },
          {
            "id": "a2a-endpoint",
            "label": "A2A endpoint",
            "proves": "The A2A (Agent2Agent) endpoint the agent card names as its url answers message/send with a completed task carrying the structured result, and tasks/get returns the same task — so A2A-native agents can work with the deployment, not just read its card."
          }
        ],
        "runs_stored": false,
        "self_reported": true
      },
      "record_url": "https://www.rightshold.com/diagnostics/conformance-failures"
    },
    {
      "id": "conformance-vectors",
      "name": "Conformance: verifier vectors",
      "kind": "conformance support",
      "about": "The ledger's verification rules are published as conformance vectors: a small reference chain that is built and signed correctly, published with its key set and the exact outcomes a correct verifier must reproduce — head height and hash, entry and Merkle hashes — plus copies with one thing altered: an entry changed after sealing, a Merkle root its entries do not produce, a corrupted block signature, a chain with its head missing, a manifest whose body hash disagrees with its signed statement. Each altered copy is labeled with the checks that must fail, so a verifier that passes the good chain and misses an altered one has located its own defect. The vectors are static, signed content, served byte for byte as published, and the standalone Python verifier runs them with its --conformance mode.",
      "entry_points": {
        "vectors": "https://www.rightshold.com/v1/conformance/vectors",
        "verifier": "https://www.rightshold.com/cli/verify-ledger.py",
        "page": "https://www.rightshold.com/conformance"
      },
      "checks": [
        "GET /v1/conformance/vectors — the reference chain, its key set, the expected outcomes, and the altered copies with the checks that must fail for each.",
        "python3 verify-ledger.py --conformance — the independent verifier run against the vectors (the verifier is served at /cli/verify-ledger.py)."
      ],
      "outcomes": [
        {
          "signal": "the good chain does not verify",
          "meaning": "A correct verifier reproduces the published outcomes for the reference chain — head height and hash, entry and Merkle hashes — from the published key set alone.",
          "next_step": "Compare the verifier's computed head, entry and Merkle hashes against the expected outcomes in the vectors, in that order; the first mismatch locates where the verifier's reading of the rules diverges."
        },
        {
          "signal": "an altered copy passes",
          "meaning": "Each altered copy is labeled with the checks that must fail for it; a verifier that passes one is missing the check its label names.",
          "next_step": "Read the altered copy's label, implement or repair the named check in the verifier, and re-run the vectors until the good chain passes and every altered copy fails on its labeled checks."
        }
      ],
      "record": {
        "served_byte_for_byte": true,
        "altered_copies_labeled": true,
        "verifier_mode": "--conformance"
      },
      "record_url": "https://www.rightshold.com/diagnostics/conformance-vectors"
    },
    {
      "id": "error-catalog",
      "name": "The error catalog",
      "kind": "support backbone",
      "about": "Every error the API returns carries a stable code, and the catalog gives each code its typical HTTP status, whether retrying can help, and what an agent should do next — so an agent branches on the code instead of parsing prose. The catalog is served whole and per code. The codes a pre-call or registration attempt most often meets are carried in this topic's record, verbatim from the catalog: the two pre-call request errors, the unreachable-server error (the one retryable error among them — the server could not be probed and nothing was registered), and the redirected-URL error (register the destination directly). This diagnostics surface adds one code of its own, for a topic name outside the set.",
      "entry_points": {
        "catalog": "https://www.rightshold.com/v1/errors",
        "one_code": "https://www.rightshold.com/v1/errors/{code}",
        "diagnostics": "https://www.rightshold.com/v1/diagnostics"
      },
      "checks": [
        "GET /v1/errors — the whole catalog: every code with its typical status, retryable flag and action.",
        "GET /v1/errors/<code> — one code's entry, for the exact error an answer carried."
      ],
      "outcomes": [
        {
          "signal": "retryable: true",
          "meaning": "The catalog says retrying can help — the failure is a state that can change (a server that could not be probed, a record not yet sealed).",
          "next_step": "Follow the code's action, then retry the original request; do not change the request's meaning to make the error go away."
        },
        {
          "signal": "retryable: false",
          "meaning": "Retrying the same request cannot help: the request itself, or a fact it names, has to change.",
          "next_step": "Make the change the code's action names — a corrected URL, a registered destination, a field within its stated shape — then send the corrected request."
        },
        {
          "signal": "diagnostic_not_found (404)",
          "meaning": "No diagnostic topic exists under that name: the topics are the fixed set listed at GET /v1/diagnostics.",
          "next_step": "List the topics at GET /v1/diagnostics and read the one that matches the failure in hand."
        }
      ],
      "record": {
        "catalog_codes": 481,
        "relevant_codes": [
          {
            "code": "invalid_server_url",
            "typical_status": 422,
            "retryable": false,
            "action": "Send the remote MCP server's https URL (http only for a loopback address). URLs naming — or resolving to — private, link-local or reserved addresses are not fetched."
          },
          {
            "code": "invalid_precall",
            "typical_status": 422,
            "retryable": false,
            "action": "Send ?url=<the MCP server's https URL> and optionally ?tool=<a tool name of 200 characters or fewer>."
          },
          {
            "code": "server_unreachable",
            "typical_status": 422,
            "retryable": true,
            "action": "The server could not be probed (MCP initialize and tools/list); nothing was registered. Check the URL and that the server is up, then retry."
          },
          {
            "code": "server_redirected",
            "typical_status": 422,
            "retryable": false,
            "action": "The URL redirects to another address; a redirecting URL is not registered, because the record would name one address while another server's definitions fill it. Register the destination URL directly."
          },
          {
            "code": "diagnostic_not_found",
            "typical_status": 404,
            "retryable": false,
            "action": "Check the diagnostic topic id; list or search first."
          }
        ]
      },
      "record_url": "https://www.rightshold.com/diagnostics/error-catalog"
    }
  ],
  "note": "Start from the signal in hand: a refusal's error code resolves at GET /v1/errors/<code>; an integrity, scan or flag signal resolves against the precall topics; a failed conformance check resolves against the checklist topic, and a verifier that disagrees with the published outcomes resolves against the vectors. There is no human help desk or ticket system here — the support is that each of those signals carries its own diagnosis and next step, in the open, re-runnable by the agent itself."
}