From 308c483618f2ebe0487d139b3c055c7cb959a108 Mon Sep 17 00:00:00 2001 From: echobt <154886644+echobt@users.noreply.github.com> Date: Sat, 19 Sep 2026 09:11:54 +0000 Subject: [PATCH 1/2] docs(bounty): align guides with chat and snapshot scoring --- bounty/index.mdx | 89 +++++++--------------------- bounty/pair-a-hotkey.mdx | 99 ++++++++++---------------------- bounty/public-api.mdx | 74 ++++++++++++++---------- bounty/report.mdx | 83 +++++++------------------- bounty/scoring.mdx | 68 ++++++++++++---------- cli/reference.mdx | 6 +- getting-started/report-a-bug.mdx | 12 ++-- 7 files changed, 162 insertions(+), 269 deletions(-) diff --git a/bounty/index.mdx b/bounty/index.mdx index 5cd8ea7..5512eee 100644 --- a/bounty/index.mdx +++ b/bounty/index.mdx @@ -1,91 +1,47 @@ --- title: "Cortex Bounty" -description: "The Cortex Bounty Challenge: pair a mining hotkey, file a report from Chat, and read every verdict on a public log" +description: "Find Cortex Bounty in Chat, link a mining hotkey, submit a useful finding, and verify published verdicts and scoring." icon: "coins" --- -Cortex Bounty is the **Cortex Bounty Challenge**, a bug bounty for miners on the Cortex subnet. You pair a mining hotkey to a Cortex account, look for a real defect in Cortex inside a marked conversation, file a report, and wait for a verdict. Every verdict that is reached is published on a log that anyone can read without signing in and without a credential. +Cortex Bounty rewards useful, reproducible vulnerability reports about Cortex. Cortex records hotkey links and adjudicates findings; the subnet reads the public findings to calculate weights. Filing a report, receiving a valid verdict and receiving an on-chain reward are separate steps. -Cortex plays three parts in the programme: it records your pairing and the session context, it adjudicates the reports that are filed, and it publishes the public transparency log. It does not set weights and it does not compute a score. The subnet reads the public endpoints and sets weights from the valid rows it finds there. +## Where to find Bounty -## The four pages of this section +Open [Cortex Chat](https://app.cortex.foundation) with a **dedicated mining account**. Bounty is a programme inside Cortex, not a separate application or a page at `/bounty` in the app. + +- **Link a hotkey:** send `/link ` in Chat and complete the signing card. +- **File a finding:** open **Settings > General > Report a bug**, then **Add to the Challenge Bounty** on the receipt when your report is eligible. +- **Read published findings:** use the [Transparency API](/bounty/public-api). Its leaderboard is a public JSON response, not a payout dashboard. + + +Linking requires prior acceptance of the research terms. The current Chat interface has no terms-acceptance screen, so a new participant may be blocked before receiving a signing card. See [Pair a hotkey](/bounty/pair-a-hotkey); onboarding is not complete for every account. + + +## Participate - Accept the terms, sign the payload the CLI prints, and link an SS58 hotkey to your mining account. + Check the prerequisites and sign a Chat card with your mining hotkey. - Mark a conversation as a miner session, file from Chat, and see what the report carries. + Submit a reproducible finding and add an eligible bug report to Bounty. - The four statuses, the gates a row has to clear, and what can never become a valid row. + Understand severity, eligibility and why a valid report is not a guaranteed payment. - The unauthenticated public endpoints, windows and paging, and how to read a zero. + Read the public status, leaderboard and reports from one consistent publication. -## Before you start - -Use a **dedicated mining** Cortex account, not your private personal account. The programme terms are explicit about why: "Conversations, logs, and the account may be read for research, to fix bugs, and to remunerate you." - - -Accepting the terms is blocking. Until the terms are accepted, pairing is refused and so is marking a conversation as a miner session. The version in force is `bounty-research-v1`, and what is stored with your acceptance is your account id, that version, and a timestamp. - - -## How it flows end to end - - - - Sign in to Cortex with an account you keep for mining. See [Accounts and sign-in](/getting-started/accounts). - - - Install the Cortex CLI and run the pairing command. The CLI prints an exact string, you sign it with your own wallet tool, and the hotkey is linked. Full procedure on [Pair a hotkey](/bounty/pair-a-hotkey). - - - Pairing prints a command to send in Chat, plus a one-time session code. Sending that command marks the conversation as a bounty-miner session and injects miner context. - - - Describe what you found in the marked conversation, then file it with the Chat report tool. See [File a report](/bounty/report). - - - A filed report is pending and private. It is not on the public endpoints, and fetching it by id answers as though it did not exist, until a verdict exists. - - - Once a verdict is recorded, the row becomes public. Anyone can read it, count it and verify it with the [Transparency API](/bounty/public-api). - - - -## What a machine decides and what a person decides - -Two different kinds of decision sit in this programme, and it is worth knowing which is which before you file. - -| Decided mechanically | Decided by judgement | -| --- | --- | -| Whether the terms are accepted, and therefore whether you may pair or mark a session at all | Whether what you found is a real, unique defect | -| Whether a hotkey is already held by another account | Which of the four statuses your report receives | -| Whether a report has enough substance to be published at all | The wording of the finding and the reasoning recorded with the verdict | -| Whether a row appears on the public endpoints, and in which window | Whether a report duplicates an earlier one, and which one it names | - -The mechanical gates are described in full on [Verdicts and scoring](/bounty/scoring). They are the usual reason a report you consider valid has not appeared on the public log. - -## What this section does not tell you - -This documentation covers the mechanics: pairing, filing, verdicts, and the public log. It does not state what a reward is worth, when a verdict will arrive, or who is eligible to take part. Those belong to the programme's own terms, the ones you accept at pairing, and they can depend on the case. Do not read an amount or a schedule into the three outcomes described on the scoring page. - -## How it fits with the other Cortex products - -Cortex Bounty is a programme rather than an application you open, so it borrows the surfaces of two products you already have. +## Privacy and rewards -- The [Cortex CLI](/cli/index) does the pairing. It is the only place the pairing command runs, and the only place the string you have to sign is printed. -- [Cortex Chat](/chat/index) is where a report is filed, from a conversation that has been marked as a miner session. The report tool is not offered in an ordinary conversation. -- The Transparency API stands on its own. It needs no account, so a third party can check a payout claim without your help. +Use an account reserved for mining: programme terms allow its conversations and logs to be used for research, fixing defects and assessing rewards. Never submit wallet secrets. The signing card needs a signature, not a seed phrase or private key. -If you have found a defect but are not a miner on the subnet, this is not your intake. Use [Report a bug](/getting-started/report-a-bug) instead. +Pending findings stay private. After adjudication, a public record contains the verdict and its justification, not the original report body or Chat transcript. A public summary appears only when staff approves it. - -Not part of this programme, and not a Cortex feature: `/miner` is not a command and never will be, there is no attestation surface here, and there is no teacher host. The subnet runs its own pipeline beyond the public log, and nothing in it is documented on this site. - +Bounty has 20% of subnet emission. Its share is not increased when another challenge is unavailable. Published report counts are not reward weights, and an unavailable scorer can leave the Bounty share unallocated to miners. The [scoring rules](/bounty/scoring) explain the additional eligibility gates. A public verdict alone is not evidence of an on-chain payment. ## Related @@ -93,5 +49,4 @@ Not part of this programme, and not a Cortex feature: `/miner` is not a command - [File a report](/bounty/report) - [Verdicts and scoring](/bounty/scoring) - [Transparency API](/bounty/public-api) -- [Install the CLI](/cli/install) - [Report a bug](/getting-started/report-a-bug) diff --git a/bounty/pair-a-hotkey.mdx b/bounty/pair-a-hotkey.mdx index 15af4ce..ffdbdee 100644 --- a/bounty/pair-a-hotkey.mdx +++ b/bounty/pair-a-hotkey.mdx @@ -1,100 +1,63 @@ --- title: "Pair a hotkey" -description: "Accept the Cortex Bounty terms and link an SS58 mining hotkey to your Cortex account by signing the payload the CLI prints" +description: "Link your mining hotkey in Cortex Chat with /link, sign the card with your wallet, and understand the current terms prerequisite." icon: "key" --- -Pairing is the first thing you do in [Cortex Bounty](/bounty/index). It links a mining hotkey to a Cortex account, so that a report filed from that account can be credited to that hotkey on the public log. Nothing else in the programme works until a hotkey is paired: the Chat report tool is not offered, and a conversation cannot be marked as a miner session. +Pairing links your mining hotkey to your Cortex account so published findings can be credited to it. Start in [Cortex Chat](https://app.cortex.foundation), not in the Cortex CLI. There is no separate Bounty application to open. -Pairing happens entirely in the terminal, with the Cortex CLI. It proves two things at once, that you control the Cortex account and that you control the hotkey, by having you sign a string the CLI prints with your own wallet tool. This page covers what you need, the exact command, what you sign, and how many hotkeys one account may hold. +## Before you start -## What you need - -- A **dedicated mining** Cortex account. Reports, conversations and logs on it may be read for research, to fix bugs, and to remunerate you, so do not use a private personal account. See [Accounts and sign-in](/getting-started/accounts). -- The Cortex CLI installed. The binary is `cortex`. See [Install the CLI](/cli/install). -- Your hotkey's SS58 address, and a wallet tool that can sign an arbitrary string with it. **btcli** and **polkadot-js** both do this. +- Use a **dedicated mining account**. Its conversations and logs may be used for research, fixing bugs and assessing rewards. Do not link a private personal account. +- Have your hotkey's SS58 address and a wallet tool that can sign a message with that hotkey. +- The account must already have accepted the current Bounty research terms. -Cortex never asks for a mnemonic. The CLI prints a string and asks for a signature over it. Nothing in this flow needs your seed phrase, your private key or a wallet file, and no Cortex surface will ever ask for one. +The current Chat interface does not provide a Bounty terms-acceptance screen. If Chat asks you to accept the terms, pairing cannot continue through this interface yet. Sending `/link` does not count as consent. You can still [report a bug](/getting-started/report-a-bug) without joining Bounty. -## Accept the terms - -The terms version in force is `bounty-research-v1`. It is shown to you at pairing, and your acceptance is stored as three things: your account id, that version, and a timestamp. +## Link in Chat -Acceptance is blocking rather than advisory. Until the terms are accepted, pairing is refused and so is marking a conversation as a miner session. You accept them as part of the pairing command, with `--accept-terms`. - -## Pair the hotkey +For an account whose terms acceptance is already recorded: - - Pass the SS58 address of the hotkey you want to link. - - ```bash - cortex bounty pair --hotkey --accept-terms - ``` - - - The CLI signs you in. If you already have an access token you can supply it to the CLI with `--token` instead of signing in. See [Sign in to the CLI](/cli/sign-in). - - - The CLI asks the challenge backend for a nonce, then prints the exact string to sign. It has four parts separated by a vertical bar: a fixed prefix, your account id, the nonce, and an expiry. + + Sign in to your mining account and send this as a Chat message, replacing the placeholder with your public hotkey address: ```text - cortex-bounty-v1|{account_id}|{nonce}|{exp} + /link ``` - Sign that string exactly as printed, byte for byte. Do not reformat it, do not trim it, and do not sign the address or a hash of your own making. - - - Use **btcli** or **polkadot-js** to sign the string with the hotkey named in the command. The signature is produced entirely on your side. + Chat displays the hotkey and the exact message to sign. Requesting a card does not link the key by itself. - - Hand the signature back to the CLI. When it is accepted, the hotkey is linked to the account and pairing is done. + + Check the address on the card. Use your wallet tool to sign the complete displayed message, without editing it, using that hotkey rather than your coldkey. - - Pairing prints two things you need in Chat: the command that marks a conversation as a miner session, and a one-time session code. Keep both. The command is a secret and must not be shared or posted anywhere. + + Paste the hexadecimal signature into the card and submit it. Wait for the linked confirmation before filing a Bounty report. -## What pairing gives you - -| What you get | What it is for | -| --- | --- | -| A linked hotkey | Reports filed from this account can be credited to this hotkey | -| An accepted terms record | Unblocks pairing and the miner session marking | -| The Chat command | Marks a conversation as a bounty-miner session. See [File a report](/bounty/report) | -| A one-time session code | An optional argument, sent in Chat straight after that command | - -The Chat command is configured by an operator, which is why the CLI prints it for you rather than this page naming it. Treat it as a credential: anyone holding it can mark a conversation. `/miner` is not that command, is not a command at all, and never will be. - -## Many hotkeys per account, one account per hotkey - -One Cortex account can hold as many hotkeys as you pair to it. Run the command again with another SS58 for each one. + +Never paste a seed phrase, mnemonic, private key or wallet file into Chat or the signing card. The card accepts only a signature. Signing happens in your wallet. + -The reverse does not hold. A hotkey belongs to exactly one account, and a second account cannot claim a hotkey that is already paired. The practical consequence is worth stating plainly: **you cannot move a hotkey between accounts by pairing it again elsewhere.** Decide which account is your mining account before you pair, because pairing is not a way to migrate one later. +## If linking is refused -## If pairing does not go through +| What you see | What to do | +| --- | --- | +| Sign-in required | Sign in to the dedicated mining account first. | +| Research terms required | Pairing is blocked until an acceptance flow is available; the signing card cannot accept terms. | +| Invalid hotkey | Check that you supplied the public SS58 address of the intended hotkey. | +| Hotkey already linked elsewhere | Use the account that owns the link, or another hotkey. Repeating `/link` does not transfer ownership. | +| Invalid, expired or already-used signature request | Send `/link` again and sign the new card's exact message with the matching hotkey. | - - - The usual cause is the terms. Pairing is refused until `bounty-research-v1` is accepted, which is what `--accept-terms` does. Run the command with that flag. - - - That hotkey is paired to another Cortex account. Nothing you can do from this account changes that, and a second claim is refused by design. Use a hotkey that is not yet paired, or sign in to the account that holds it. - - - The string has to be signed exactly as printed, and the payload carries an expiry as its last part. If that expiry has passed, run the pairing command again and sign the new payload without editing it. Check also that you signed with the hotkey named in the command rather than another key in your wallet. - - - Every Cortex failure has one shape and a stable code, and it carries a reference id that is safe to quote. See [Errors](/reference/errors). - - +One account can link multiple hotkeys; each hotkey belongs to only one account. Repeat the Chat flow for each key. Linking does not itself activate a miner conversation, submit a report or guarantee a reward. Continue with [File a report](/bounty/report). ## Related - [Cortex Bounty](/bounty/index) - [File a report](/bounty/report) - [Verdicts and scoring](/bounty/scoring) -- [Install the CLI](/cli/install) -- [Sign in to the CLI](/cli/sign-in) +- [Accounts and sign-in](/getting-started/accounts) +- [Errors](/reference/errors) diff --git a/bounty/public-api.mdx b/bounty/public-api.mdx index f5900ad..8acb2ec 100644 --- a/bounty/public-api.mdx +++ b/bounty/public-api.mdx @@ -1,12 +1,12 @@ --- title: "Transparency API" -description: "Four unauthenticated endpoints that publish every adjudicated Cortex Bounty report, with windows, paging, and how to read a zero" +description: "Read Cortex Bounty verdicts, severity and report counts through the public API, using immutable revisions for consistent pagination" icon: "globe" --- -The transparency API is how a Cortex Bounty verdict becomes checkable by anyone. It is four read-only endpoints that need no account, no credential and no cookie, and none is minted for the caller. A participant can verify their own row with it, and a third party can verify somebody else's claim without asking either side for access. +The transparency API publishes Cortex Bounty verdicts for anyone to check. Its four read-only endpoints need no account or credential. The [public leaderboard](https://api.cortex.foundation/v1/bounty/public/leaderboard) is a JSON response, not a dedicated Bounty application page. -The endpoints publish adjudicated reports only. Nothing pending appears, no conversation appears, and no account is identified. This page lists the four paths, then covers the three things that trip people up: time windows, paging, and what a zero actually means. Each path below is given relative, so prefix it with the Cortex API host for the deployment you are checking. +Only adjudicated reports appear. Pending reports, conversations and account identities stay private. Prefix the paths below with `https://api.cortex.foundation`. ## The four endpoints @@ -15,28 +15,34 @@ All four are `GET`, and all four are unauthenticated. | Path | Query parameters | What it answers | | --- | --- | --- | | `/v1/bounty/public/status` | none | Is this backend adjudicating at all? Counts, backlog, and whether an operator exists | -| `/v1/bounty/public/leaderboard` | `since`, `until` | Hotkeys ranked by valid-report count, plus counts by status. No account ids | -| `/v1/bounty/public/reports` | `hotkey`, `status`, `since`, `until`, `limit`, `cursor` | Adjudicated reports, completely enumerable | -| `/v1/bounty/public/reports/{id}` | none | One adjudicated report, or 404 if it is pending or unknown | +| `/v1/bounty/public/leaderboard` | `since`, `until`, `revision` | Hotkeys ranked by valid-report count, plus counts by status. No account ids | +| `/v1/bounty/public/reports` | `hotkey`, `status`, `since`, `until`, `limit`, `cursor`, `revision` | Published scoring reports, completely enumerable at one revision | +| `/v1/bounty/public/reports/{id}` | none | Latest adjudicated version and its publication revision, or 404 if pending or unknown | -Every response from all four carries `api_version`, which is `1` today, and `generated_at`, the moment the response was built. Every response is sent with `cache-control: no-store`, so what you read is what the log says now rather than something a cache kept. +Every response carries `api_version: 1`, `generated_at` and a decimal-string `revision`, with `cache-control: no-store`. The status, leaderboard and report list identify a publication snapshot. A report detail instead identifies the revision that published its latest version; it does not accept a historical revision filter. + +Leaderboard entries contain `hotkey`, `valid`, `valid_count`, `duplicate`, `already_fixed_not_prod`, `invalid_malicious` and `total`. `valid` and `valid_count` are equal. These are **report counts, not scores or payments**. See [Verdicts and scoring](/bounty/scoring). ## What a public row contains | Field | Meaning | | --- | --- | | `id` | The report id. A time-ordered id assigned when the report was filed | -| `hotkey` | The SS58 address the report was credited to. Never an account id | +| `hotkey` | The hotkey in canonical SS58 format 42. Never an account id | | `status` | One of the four verdicts. See [Verdicts and scoring](/bounty/scoring) | +| `severity` | `trivial`, `minor`, `major` or `critical` for a scoreable `valid` report; `null` for other verdicts | | `problem_found` | What the defect was, as recorded by the adjudicator | | `justification` | The reasoning behind the status | | `adjudicator` | An agent or service identifier. Never a person, never an email address | | `adjudicated_at` | When the verdict was recorded | | `created_at` | When the report was filed | -| `related_report_id` | Present on duplicates only, and the report it names is already public | +| `related_report_id` | Required on duplicates only; its public reference chain must end at a non-duplicate report | +| `summary` | Optional public-safe paragraph approved for publication; not the raw finding | Chat transcripts stay private. They are never on the public routes, and neither is the report body, your email address, your display name, a conversation id, a pairing code or a token of any kind. The full list is on [File a report](/bounty/report). +Legacy `valid` reports without severity are excluded from report lists and leaderboard counts until repriced. Their detail can still show `severity: null`; that historical verdict is not scoreable. Duplicate chains rooted in an unpriced report are also withheld from the scoring list. + ## Windows `since` and `until` are RFC 3339 timestamps, and they behave the same way on the leaderboard and on the reports listing. @@ -46,63 +52,69 @@ Chat transcripts stay private. They are never on the public routes, and neither - `until <= since` is **refused**. It is not answered with an empty page, and the reason is worth understanding: an empty page reads exactly like "this hotkey earned nothing". - An `adjudicated_at` value taken from a response is reusable as a bound byte for byte. It is truncated to microseconds. A `+00:00` offset needs percent-encoding in a query string, though the un-encoded form is accepted too. -## Paging the reports listing +## Revisions and pagination -The reports endpoint is the one that enumerates completely, and it is cursor-paged. +Read status first. Pass its `revision` to the leaderboard and the first report page so both read the same immutable publication snapshot. Without a revision, a first-page request reads the latest publication. ```text -/v1/bounty/public/reports?hotkey=HOTKEY&since=FROM&until=TO&limit=100 +/v1/bounty/public/reports?hotkey=HOTKEY&since=FROM&until=TO&limit=100&revision=REVISION ``` -- `limit` is clamped to **100**. Asking for more gets you 100. -- The response reports `has_more`. While it is true, send `next_cursor` back verbatim as `cursor` and read the next page. -- The cursor is opaque, and it is keyed on `adjudicated_at` and then `id`. Do not build one yourself and do not try to decode it. +- `limit` is clamped to **1 through 100**. +- While `has_more` is true, send `next_cursor` back verbatim as `cursor`, preserving the same filters. +- The opaque cursor binds the revision, filters and position. A conflicting revision or changed filters is refused; restart from page one to change the query. +- The ordering is newest `adjudicated_at` first, then `id`. New verdicts or corrections appear only in later revisions and cannot move page two of an existing walk. - `id` is assigned at filing time, not at verdict time, so ids are not in verdict order. That is exactly why the cursor exists: you cannot page this log by sorting ids. The leaderboard is **not** paged. It aggregates up to **1000** hotkeys and sets `has_more` when there are more than that. If you need a complete enumeration, walk the reports endpoint instead. The leaderboard is a summary, and the reports listing is the record. ## Reading zero correctly -This is the part to get right before you conclude anything from an empty result. A zero on the leaderboard has three different meanings, and the status endpoint is what tells them apart. +A missing leaderboard row is not proof of a zero payout. Check the status response before interpreting an empty publication. | What the status endpoint says | What it means | Is it a real zero? | | --- | --- | --- | -| `adjudication_available` is false | No operator is adjudicating | No. Nothing is being judged at all | +| `adjudication_available` is false | No operator is available to adjudicate | No. The scoring input is unavailable | | `awaiting_adjudication` above zero, nothing published | A queue exists but has not been worked | No. The verdicts have not happened yet | -| `adjudication_available` true and `awaiting_adjudication` zero | Everything filed has been judged | Yes. This is a real zero | +| `unpriced_valid` above zero | Legacy valid findings still need severity | No. The scorer refuses an unpriced publication | +| Adjudication available, no backlog or unpriced verdicts, consistent empty publication | No scoreable reports are published | A report-count zero, not evidence of an on-chain payment | -Two further facts make the reading safe. A backend that cannot answer at all fails the request; it never answers an empty list, so an empty list is always a real answer from a working backend. And `last_adjudicated_at` on the status response tells you how stale the log is, which is the difference between "nothing has happened" and "nothing has happened lately". +A failed request is not an empty publication. Never substitute an empty list for a transport, server or validation error. `last_adjudicated_at` gives the time of the latest published adjudication; it does not prove the scoring or payment pipeline is running. | Status field | Meaning | | --- | --- | -| `adjudication_available` | Whether an operator is adjudicating at all | +| `adjudication_available` | Whether an operator can adjudicate; not proof that the queue is being worked | +| `published`, verdict counts, `hotkeys` | Totals for the entire publication, not a time-filtered leaderboard | | `awaiting_adjudication` | How large the backlog is | -| `last_adjudicated_at` | How stale the log is | +| `unpriced_valid` | Repriceable legacy valid reports missing severity | +| `summarised` | Published records with a stored summary; individual summaries can still be withheld by safety checks | +| `last_adjudicated_at` | Latest published adjudication time, omitted when none exists | +| `revision` | Publication snapshot to use for subsequent reads | | `api_version` | The response contract version, `1` today | | `generated_at` | When this response was built | -## Verify one bounty end to end +## Verify a public report count - - Read `/v1/bounty/public/status`. Confirm that an operator exists and that the backlog is zero. If it is not, stop here: anything you count next is incomplete by definition. + + Read `/v1/bounty/public/status` and retain its `revision`. Check the availability, backlog and unpriced counters before interpreting the result. - Call `/v1/bounty/public/leaderboard` with the `since` and `until` bounds of the window you care about. Note the valid-report count for the hotkey you are checking. + Call `/v1/bounty/public/leaderboard` with that `revision` and the `since` and `until` bounds you need. Note the hotkey's `valid_count`. If `has_more` is true, absence from the board is inconclusive. - Call `/v1/bounty/public/reports` with the same `hotkey`, `since` and `until`, and follow `next_cursor` until `has_more` is false. Count the valid rows as you go. + Call `/v1/bounty/public/reports` with the same `revision`, `hotkey`, `since` and `until`. Follow `next_cursor` until `has_more` is false, keeping filters unchanged. Count the valid rows. - - Take an id from the walk and read `/v1/bounty/public/reports/{id}`. You get the same row, which is the one you can quote to somebody else. + + The board count and complete walk must agree at the same revision and window. Check pagination and filters on a mismatch; if it persists, treat the data as inconsistent, not as a score. - - The count from the leaderboard and the rows you walked must agree. A disagreement means the walk was truncated, so check `has_more` and page again. It does not mean the log is wrong. + + Read `/v1/bounty/public/reports/{id}` for its latest explanation. A later correction may differ from your pinned walk; use the page you retained when auditing the older snapshot. -There is no public API for anything else in Cortex. These four endpoints exist because the bounty log has to be verifiable by outsiders; they are not a general platform API, and there is no inference endpoint, no API key and no client library. See [Platform API](/reference/platform-api). +This verifies published evidence and counts, not a payment. These endpoints are not a general platform API. See [Platform API](/reference/platform-api). ## Related diff --git a/bounty/report.mdx b/bounty/report.mdx index 26d64c3..bc21e44 100644 --- a/bounty/report.mdx +++ b/bounty/report.mdx @@ -1,94 +1,53 @@ --- title: "File a report" -description: "Mark a Chat conversation as a bounty-miner session, file a report with the Chat report tool, and see what the report carries" +description: "File a reproducible Cortex finding, add an eligible bug report to Bounty, and understand which report details stay private." icon: "flag" --- -A Cortex Bounty report is filed from [Cortex Chat](/chat/index), out of the conversation in which you found the problem. The conversation itself is the evidence: you describe the defect in it, then file the report from inside it, and the report is tied to that conversation, to the hotkey you are mining with, and to the account that filed it. +File a report from your dedicated mining account after [linking a hotkey](/bounty/pair-a-hotkey). A submission is evidence for review, not a verdict or a promise of payment. If you cannot join Bounty, you can still file an ordinary [bug report](/getting-started/report-a-bug). -Two things have to be true before the report tool appears. A hotkey must be paired to the account, which is covered on [Pair a hotkey](/bounty/pair-a-hotkey), and the conversation must be marked as a bounty-miner session. This page covers the marking, the filing, what the report carries, and what stays private while a verdict is pending. - -## Mark a conversation as a miner session - -Marking is what turns an ordinary conversation into a miner session. It also injects miner context, so the assistant knows which hotkey it is working for. +## Add a bug report to Bounty - - Sign in with the dedicated mining account and start a fresh conversation in Chat. - - - Pairing printed a command to send in Chat. Send it in the composer as an ordinary message. You can send it on its own, or follow it with the one-time session code, or with the SS58 address of any hotkey already linked to the account. + + Open the account menu, then **Settings > General > Report a bug**. Give it a specific title, explain the expected and actual behaviour, and include the steps needed to reproduce it. Remove passwords, private keys and unrelated personal information from text and screenshots. - - The conversation is now a bounty-miner session and miner context has been injected. The report tool is available in it. + + Send the report and keep the ticket reference on the receipt. Follow-up questions and the team's response arrive by email; reply in that thread with any missing evidence. - - If the account holds several hotkeys, send the command again with the SS58 address of the one you want. The conversation follows the hotkey you name last. + + On the receipt, choose **Add to the Challenge Bounty** if it appears. The programme must be active and your account must have a linked hotkey. Wait for confirmation that the report was added. - -The command is a secret. It is set by an operator, the CLI prints it only to you, and anyone holding it can mark a conversation. Do not paste it into an issue, a screenshot, a support thread or a public repository. `/miner` is not that command and is not a command at all. - +The button is conditional: filing a bug report does not automatically enter it into Bounty. If the programme is paused, participation is unavailable or adding it fails, the original bug report stays filed. A report can be added only once; retrying does not create a second Bounty finding. -## File the report +If you have several linked hotkeys, this route uses the first linked hotkey; the receipt does not offer a hotkey picker. Do not assume the key from a different Chat conversation will receive the credit. -Work the problem in the conversation first. Reproduce it, narrow it down, and write out what you found in plain language, because that text is what an adjudicator will read and what the publication gates are measured against. +## Reporting from an existing miner conversation -When the finding is written up, file it with the `bounty_report` tool. It is a Chat tool and it is only offered in a conversation that has been marked as a miner session, so it will not show up in a normal thread. You can add hints alongside the body when there is something an adjudicator should know to reproduce it. +An already-enabled Bounty miner conversation can offer the `bounty_report` Chat tool. Describe the finding in that conversation and ask for it to be filed. The resulting report uses that conversation's active linked hotkey. -Write the finding out properly rather than filing a one-line note. A report whose body carries less than 24 characters of plaintext finding can never be published as a valid row, whatever an adjudicator thinks of it. See [Verdicts and scoring](/bounty/scoring). +The `/link` card only links a hotkey. It does not enable a miner conversation, and its success message does not provide a conversation-activation control. Do not expect the report tool to appear in an ordinary Chat thread after linking. Use the bug-report route when eligible; `/miner` is not an activation command. -## What a report carries - -| In the report | Where it comes from | -| --- | --- | -| The hotkey | The linked SS58 the session is mining for | -| The account id | The Cortex account that filed it | -| The session id | The conversation the report was filed from | -| A creation timestamp | Set when you file | -| The body | What you wrote up in the conversation | -| Optional hints | Anything you added for the adjudicator | - -Reports are delivered to the challenge backend, which is what adjudicates them and what publishes the verdicts. Nothing you file goes to the subnet directly. - -## While it is pending, it is private - -A filed report has no status yet. Until a verdict exists: - -- It does not appear on any of the public endpoints. It is not counted on the leaderboard, and it is not in the reports listing. -- Fetching it by its id answers 404, exactly as an id that never existed would. That is deliberate. The public log holds adjudicated rows and nothing else. -- You can still see it yourself. A signed-in participant can list their own reports, pending ones included, and that is the only way to see a pending report. - -So an empty public log is not evidence that your report was lost. It is the expected state of a report that has not been judged yet. The [Transparency API](/bounty/public-api) explains how to tell a backlog apart from a real zero. - -## What is never published +## Follow the review -The conversation is the one thing that never becomes public. **Chat transcripts stay private. They are never on the public routes.** The report body is sealed too: its length is checked as a publication gate, but the text itself is never published. +Pending reports are not listed on the public leaderboard or report log. An empty public log does not mean your submission was lost. Keep your bug-report receipt and distinguish a submission acknowledgement from an adjudicated verdict. -| A public row carries | A public row never carries | -| --- | --- | -| The report id | Your Cortex account id | -| The hotkey, as an SS58 address | Your email address | -| The status | Your display name | -| The finding recorded by the adjudicator | Chat transcripts | -| The justification for the verdict | Conversation or session ids | -| An adjudicator identifier | Pairing codes, or the Chat command | -| The verdict timestamp and the filing timestamp | IP addresses | -| A related report id, on duplicates only | Tokens of any kind, and the raw report body | +Once staff records a verdict, check the [Transparency API](/bounty/public-api). A `valid` verdict needs severity before it can contribute to scoring. Eligibility and the final allocation depend on the [scoring rules](/bounty/scoring), not just on how many reports you submitted. There is no guaranteed review deadline or payment date. -What an adjudicator writes about your report does become public, in two fields: a statement of the problem found, and the justification for the verdict. Nothing you wrote is republished verbatim. +## What stays private -## What this page cannot tell you +The original report body, Chat transcripts, account identity and email address are not part of the public transparency log. Public rows contain the hotkey, report identifier, verdict, severity when applicable, problem statement, justification and timestamps. Duplicates identify a related report. A summary is optional and requires staff approval before publication. -There is no published turnaround time for a verdict, and no queue position you can read for your own report. The status endpoint tells you whether anyone is adjudicating at all and how large the backlog is, which is the closest thing to a progress signal that exists. Rewards, eligibility and timing are set by the programme terms you accepted at pairing rather than by this documentation, and they can depend on the case. +Do not publish raw findings in a public issue merely because the verdict has become public. A public verdict does not authorize disclosure of credentials, private conversations or unpatched reproduction details. ## Related - [Cortex Bounty](/bounty/index) - [Pair a hotkey](/bounty/pair-a-hotkey) +- [Report a bug](/getting-started/report-a-bug) - [Verdicts and scoring](/bounty/scoring) - [Transparency API](/bounty/public-api) -- [Built-in tools](/chat/tools) diff --git a/bounty/scoring.mdx b/bounty/scoring.mdx index 7a69e2f..59c8f48 100644 --- a/bounty/scoring.mdx +++ b/bounty/scoring.mdx @@ -1,34 +1,44 @@ --- title: "Verdicts and scoring" -description: "The four Cortex Bounty statuses, the gates a verdict has to clear before it is published, and what can never become a valid row" +description: "Understand Cortex Bounty verdicts, severity, champion eligibility and why a valid finding does not guarantee a reward" icon: "scale-balanced" --- -Every Cortex Bounty report ends in one of four verdicts, and only one of them is a reward. This page explains what the four statuses mean, what a verdict has to carry before it can be published at all, and the list of reasons a report you consider valid never turns into a valid row on the public log. +An adjudicated Cortex Bounty report receives one of four verdicts. A `valid` finding contributes evidence toward a score; it is **not a guaranteed reward**. The public leaderboard counts reports, while the subnet applies eligibility, precision and severity rules to choose at most one champion per scoring snapshot. -It is worth being precise about who decides what. The gates below are mechanical: a verdict that does not satisfy them is refused, and no adjudicator can wave it through. The verdict itself is a judgement about your finding, made by an adjudicator working for the programme. Cortex does not compute a score here, and the reward is not decided on this site. +The adjudicator decides the finding's verdict and severity. The published evidence is the input to subnet scoring. Publishing a verdict does not establish that weights have been submitted or a payment has occurred. ## The four statuses | Status | Public? | Effect | | --- | --- | --- | | pending, no status yet | No. Its id answers 404 | None. The report has not been judged | -| `valid` | Yes | Reward | -| `duplicate` | Yes | Not a valid row. May name a related report | -| `already_fixed_not_prod` | Yes | No penalty | -| `invalid_malicious` | Yes | Penalty | +| `valid` | Yes, with severity required for scoring | Adds severity-weighted credit and counts toward precision | +| `duplicate` | Yes, with a rooted public reference | No valid credit; counts as triage noise | +| `already_fixed_not_prod` | Yes | No malicious-report deduction; counts as triage noise | +| `invalid_malicious` | Yes | Reduces net credit and precision | -Read in outcome terms, that is three possibilities and nothing in between. +## Severity and eligibility -| What you filed | What happens | +Every newly published valid finding requires a severity: + +| Severity | Scoring weight | | --- | --- | -| A valid, unique bug | Reward | -| Something already fixed and not in production | No penalty | -| Something malicious, or a problem that does not exist | Penalty | +| `trivial` | 6.25% | +| `minor` | 25% | +| `major` | 50% | +| `critical` | 100% | + +Among participating hotkeys, a contender must satisfy all of these gates: - -This documentation does not state what a reward is worth or when it arrives, because no amount and no schedule is published here. Those come from the programme terms you accepted at pairing, and they can depend on the case. Treat "reward", "no penalty" and "penalty" as the direction of the outcome, not as a figure. - +- At least **three decided reports**: valid plus malicious verdicts. +- **Nonnegative net credit**: each valid report adds 6, 25, 50 or 100 points by severity; each malicious report subtracts 100. +- **No valid report missing severity**. +- **At least 60% precision**: valid reports divided by valid plus malicious reports. +- **At most 50% triage noise**: duplicate plus already-fixed reports divided by all adjudicated reports. +- **Strictly better precision than the current candidate champion** during snapshot selection. A tie does not displace that candidate. + +Candidates are considered by descending valid count, with hotkey ordering breaking count ties. The eligible champion's score combines precision with average severity weight. Other participants receive no positive score for that snapshot, even when they have valid findings. These percentages describe scoring inputs, not a payout rate. ## What a verdict has to carry @@ -37,48 +47,46 @@ A verdict is refused unless it carries both of these, and each has to be at leas - **problem found**, a statement of what the defect actually was. - **justification**, the reasoning behind the status that was chosen. -The adjudicator recorded on the row is an agent or service identifier. It is never an email address, so a public row never names a person. Once a verdict satisfies these conditions the row becomes public, and the verdict is written to the audit chain as well. +The adjudicator recorded on the row is an agent or service identifier, not an email address. A valid verdict also needs severity. A duplicate needs a public related report, with a reference chain ending at a non-duplicate verdict; missing targets, self-links and cycles are refused. -Both of those fields are published. They are the only description of your report that anyone else can read, since the report body itself stays sealed. +The problem statement and justification are public. An optional public-safe summary may also be published after review. The raw report body and chat transcripts remain private. -## What can never become a valid row +## Why a report is not credited Use this as a checklist when a report has not appeared where you expected it. - A pending report is not public at all. Its id answers 404 until a verdict exists, and it is counted nowhere. Check the status endpoint before concluding anything: a backlog is not a verdict. See [Transparency API](/bounty/public-api). + A pending report has no public detail or leaderboard credit. It contributes only to the aggregate backlog. A backlog is not a verdict. See [Transparency API](/bounty/public-api). - A `valid` row cannot be published unless the report body holds at least **24 characters** of plaintext finding. The body stays sealed and is never published; the length is only a publication gate. A one-line note fails it. + A new `valid` verdict requires at least **24 characters** of plaintext finding. The body stays private; length is only a publication gate, not proof that a finding is substantive. The problem found and the justification each need at least **16 characters**. A verdict that does not meet that is refused rather than published, so the row stays pending. - - The oldest reports, filed before the sealed field that gate reads existed, cannot be credited. + + Historical valid findings without severity are withheld from scoring lists and counts until reviewed again. A retained source permits repricing; the historical verdict alone does not establish scoreable credit. - A `duplicate` never counts as `valid`, however good the finding is. When a duplicate names a related report, that related report must already be public, so you can go and read the one that got there first. + A `duplicate` never counts as `valid`, however good the finding is. Its related report must already be public. The full reference chain must reach a non-duplicate verdict; a chain rooted in an unpriced finding is withheld from scoring lists. One hotkey belongs to one account. A second account cannot claim a hotkey that is already paired, so a report filed from the wrong account is not credited to that hotkey. See [Pair a hotkey](/bounty/pair-a-hotkey). -## An unrecognised verdict is withheld +## Unavailable evidence is not a zero -If a row carries a status this version of the public log does not recognise, the row is withheld rather than shown. It is specifically **not** rendered as `invalid_malicious`. +The scorer requires one consistent publication revision, complete report pagination, matching aggregate counts and priced valid findings. Missing adjudication, unpriced findings or an initial unworked backlog make the scoring input unavailable. An unsupported stored verdict or severity fails the public read instead of being relabelled as a penalty. -That matters for anyone reading the log with a script. A future status will simply not appear, rather than turning up mislabelled as a penalty. A row you cannot see is never proof of a penalty, and a count that comes up short is a reason to check `has_more` on your walk, not evidence of a lost report. +An unavailable feed produces no positive Bounty score for that snapshot; it is not evidence that an individual miner performed badly. Check the [Transparency API](/bounty/public-api) before interpreting an empty leaderboard. ## How weights follow valid rows -Cortex adjudicates and publishes. It does not set weights. - -The subnet reads the public endpoints and sets weights from the valid rows it finds there. There is no separate score inside Cortex, no ranking that is not derived from the public log, and nothing hidden behind sign-in that changes the outcome. That is the whole point of publishing the log: the input to the weighting is the same document you can read. +Cortex Bounty accounts for **20% of subnet emission**. This is the challenge's allocation, not a promised amount per report. The account product publishes the evidence; the subnet calculates scores and validators independently verify the allocation before chain submission. -For the same reason, the subnet's own pipeline is outside this documentation. What happens to a valid row after the subnet reads it, including anything about epochs, is not a Cortex feature and is not described on this site. There is no attestation surface here and there is no teacher host. +A report, leaderboard entry or successful publication does not prove that this full path completed. No fixed payment amount or arrival time is guaranteed by this page. ## Related diff --git a/cli/reference.mdx b/cli/reference.mdx index b132b2c..161300f 100644 --- a/cli/reference.mdx +++ b/cli/reference.mdx @@ -1,6 +1,6 @@ --- title: "Command reference" -description: "The supported cortex command surface: global options, run and exec, sessions, auth, bounty, agents, MCP, plugins, config, utilities and maintenance." +description: "The supported cortex command surface: global options, run and exec, sessions, auth, agents, MCP, plugins, config, utilities and maintenance." icon: "book" --- @@ -148,9 +148,7 @@ Sharing, forking and rewinding are in-session actions, not subcommands. Use the ## Bounty -| Command | Description | -| --- | --- | -| `cortex bounty pair --hotkey ` | Pair a mining hotkey with your Cortex account. `--accept-terms` is required the first time, until the research terms are accepted. See [Pair a hotkey](/bounty/pair-a-hotkey). | +Hotkey linking happens in Cortex Chat with `/link `, not through a Cortex CLI pairing command. See [Pair a hotkey](/bounty/pair-a-hotkey) for the signing card and current participation prerequisites. ## Agents diff --git a/getting-started/report-a-bug.mdx b/getting-started/report-a-bug.mdx index 428c36d..912a0ca 100644 --- a/getting-started/report-a-bug.mdx +++ b/getting-started/report-a-bug.mdx @@ -9,7 +9,7 @@ Cortex takes bug reports in the product. A signed-in account opens a dialog, wri attaches a screenshot or two, and sends it. The report stays inside Cortex; nothing is copied to a public issue tracker, and there is no form to fill in somewhere else. -This page covers what to check before you file, the three places the dialog opens from, what to +This page covers what to check before you file, where the dialog opens from, what to write in each field, the screenshot rules, what Cortex sends along with your words, and where a documentation problem or a security finding goes instead. @@ -43,16 +43,14 @@ Two minutes of checking often saves the round trip. ## Open the dialog -There are three entry points, and they all open the same **Report a bug** dialog: +These entry points open the same **Report a bug** dialog: | Where | How to get there | | --- | --- | -| Sidebar footer | The **Report a bug** control beside **Settings** | | Settings | **Settings** and then **General**, at the **Report a bug** row | | The **Beta Pro offer** banner | A **Report a bug** button on the banner, while that banner is on screen | -The first two are permanent. The banner is dismissible, and dismissing it does not take the other -two away. +The Settings entry is permanent. Dismissing the banner does not remove it. ## Fill in the report @@ -121,8 +119,8 @@ guest cannot file one: a report needs an account to come back to. there rather than in the product dialog. - A suspected vulnerability is not a bug report. Cortex Bounty has its own intake and its own - scoring. + Eligible participants can add a filed report to Cortex Bounty from its receipt. Linking a + hotkey, programme availability and scoring rules determine participation and rewards. From 91719fef2c5e758c17ae16862ba2caeac689f061 Mon Sep 17 00:00:00 2001 From: echobt <154886644+echobt@users.noreply.github.com> Date: Sat, 19 Sep 2026 09:28:11 +0000 Subject: [PATCH 2/2] docs(bounty): explain explicit research terms consent --- bounty/index.mdx | 2 +- bounty/pair-a-hotkey.mdx | 24 +++++++++++++++--------- 2 files changed, 16 insertions(+), 10 deletions(-) diff --git a/bounty/index.mdx b/bounty/index.mdx index 5512eee..60754c0 100644 --- a/bounty/index.mdx +++ b/bounty/index.mdx @@ -15,7 +15,7 @@ Open [Cortex Chat](https://app.cortex.foundation) with a **dedicated mining acco - **Read published findings:** use the [Transparency API](/bounty/public-api). Its leaderboard is a public JSON response, not a payout dashboard. -Linking requires prior acceptance of the research terms. The current Chat interface has no terms-acceptance screen, so a new participant may be blocked before receiving a signing card. See [Pair a hotkey](/bounty/pair-a-hotkey); onboarding is not complete for every account. +Linking requires explicit acceptance of the current research terms. Read the terms card before accepting, then request the signing card. Sending `/link` alone does not accept anything or link a key. See [Pair a hotkey](/bounty/pair-a-hotkey), including what to do if your app does not yet show an acceptance control. ## Participate diff --git a/bounty/pair-a-hotkey.mdx b/bounty/pair-a-hotkey.mdx index ffdbdee..9b2df99 100644 --- a/bounty/pair-a-hotkey.mdx +++ b/bounty/pair-a-hotkey.mdx @@ -1,6 +1,6 @@ --- title: "Pair a hotkey" -description: "Link your mining hotkey in Cortex Chat with /link, sign the card with your wallet, and understand the current terms prerequisite." +description: "Review and accept the Bounty research terms in Chat, then link your mining hotkey by signing the /link card with your wallet." icon: "key" --- @@ -10,25 +10,28 @@ Pairing links your mining hotkey to your Cortex account so published findings ca - Use a **dedicated mining account**. Its conversations and logs may be used for research, fixing bugs and assessing rewards. Do not link a private personal account. - Have your hotkey's SS58 address and a wallet tool that can sign a message with that hotkey. -- The account must already have accepted the current Bounty research terms. +- Read the current research terms before deciding whether to participate. -The current Chat interface does not provide a Bounty terms-acceptance screen. If Chat asks you to accept the terms, pairing cannot continue through this interface yet. Sending `/link` does not count as consent. You can still [report a bug](/getting-started/report-a-bug) without joining Bounty. +Sending `/link` does not count as consent. You must explicitly accept the displayed research terms before requesting a signature. If you do not agree, cancel; you can still [report a bug](/getting-started/report-a-bug) without joining Bounty. ## Link in Chat -For an account whose terms acceptance is already recorded: - - + Sign in to your mining account and send this as a Chat message, replacing the placeholder with your public hotkey address: ```text /link ``` - Chat displays the hotkey and the exact message to sign. Requesting a card does not link the key by itself. + If the current terms are already accepted, Chat displays the signing card. Otherwise it first offers the research terms. + + + Read the displayed title, version and full terms. To participate, select **I have read and accept these terms**, then **Accept terms**. The checkbox starts unchecked. Choose **Cancel** to leave without accepting. + + After the accepted confirmation, send the same `/link` message again to request the signing card. Accepting terms does not link your key or sign anything for you. Check the address on the card. Use your wallet tool to sign the complete displayed message, without editing it, using that hotkey rather than your coldkey. @@ -47,12 +50,15 @@ Never paste a seed phrase, mnemonic, private key or wallet file into Chat or the | What you see | What to do | | --- | --- | | Sign-in required | Sign in to the dedicated mining account first. | -| Research terms required | Pairing is blocked until an acceptance flow is available; the signing card cannot accept terms. | +| Research terms required | Read the terms card and explicitly accept if you agree, then send `/link` again. | +| Terms changed or acceptance failed | Read the error and reload the current terms. A changed version needs a fresh decision; do not assume acceptance succeeded. | | Invalid hotkey | Check that you supplied the public SS58 address of the intended hotkey. | | Hotkey already linked elsewhere | Use the account that owns the link, or another hotkey. Repeating `/link` does not transfer ownership. | | Invalid, expired or already-used signature request | Send `/link` again and sign the new card's exact message with the matching hotkey. | -One account can link multiple hotkeys; each hotkey belongs to only one account. Repeat the Chat flow for each key. Linking does not itself activate a miner conversation, submit a report or guarantee a reward. Continue with [File a report](/bounty/report). +One account can link multiple hotkeys; each hotkey belongs to only one account. Repeat the Chat flow for each key. Linking does not register a miner on the subnet, submit a chain transaction, activate a miner conversation or guarantee a reward. Continue with [File a report](/bounty/report). + +If your app shows only a terms-required message without an acceptance control, that deployment cannot complete this onboarding flow yet. Do not bypass the consent check or provide a wallet secret to resolve it. ## Related