Make privilege first-class across intents, CLI, and docs; add root emission intent#2910
Conversation
Co-authored-by: Cursor <cursoragent@cursor.com>
…ission intent. Every intent now declares its chain origin (signed / subnet_owner / root) and a paired verify read, surfaced in the tool catalog, btcli tx help and pre-sign flow, and the generated docs. First root intent: set_subnet_emission_enabled (multi-netuid batch_all under Sudo.sudo) with a subnet_emission_enabled read and hyperparams entry, plus an active-vs-emission-enabled decision tree in the subnets guide. Co-authored-by: Cursor <cursoragent@cursor.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
🛡️ AI Review — Skeptic (security review)VERDICT: SAFE MEDIUM scrutiny: four-month-old account with high contribution volume, repository write access, substantial merged history, and no Gittensor association; branch targets main. Static analysis covered privileged-call composition, nested dispatch results, runtime and precompile changes, hotkey-swap and leasing paths, SDK wallet/address handling, CI image publication, filesystem boundaries, and dependency updates. Root intents remain wrapped in FindingsNo findings. ConclusionNo malicious behavior or security vulnerability was found in the current PR. 🔍 AI Review — Auditor (domain review)VERDICT: 👍 UNKNOWN gittensor association; established high-volume contributor with repository write access. Overlapping PRs are unrelated SDK, runtime-upgrade, and governance work. The prior blocker is fixed: The PR description is substantive, and the runtime FindingsNo findings. Prior-comment reconciliation
ConclusionThe MEV-shielded and ordinary execution paths now preserve the same root-origin invariant. The prior blocking issue is addressed and the PR is ready. 📜 Previous run (superseded)
|
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
Co-authored-by: Cursor <cursoragent@cursor.com>
…ixes, no diff Co-authored-by: Cursor <cursoragent@cursor.com>
Consolidate pending PRs into staging
… and improve site search and sidebar. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
New /docs/sdk page covers the five core primitives with their easy
constructors. Ergonomics: Wallet("cold/hot") shorthand, wallet name
strings anywhere a wallet is accepted, and key-bearing objects accepted
wherever an ss58 address parameter is expected (reads and intents).
Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
as_ss58 no longer touches private keyfiles (wallet shapes resolve via public_view); Subtensor subclasses SyncClient with a lazy loop thread so attribute inspection has no side effects; the GC finalizer can no longer deadlock on its own loop thread; the ss58 predicate is shared between executor and reads; the removed-name hint for v10 bt.subtensor is restored; Wallet slash names are validated. Co-authored-by: Cursor <cursoragent@cursor.com>
Rust: serde_with 3.21.0, rpassword 7.5.4, tracing-subscriber 0.3.20 (unpinned from =0.3.18). npm: js-yaml, svgo, minimatch, @babel/runtime in-range; postcss 8.5.10 and prismjs 1.30.0 via resolutions (pinned by next and refractor). Also declares the shiki dependency already present in the lockfile for the upcoming /code viewer. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
Treat Sudo/Proxy/Multisig inner Err as failure, share one teardown path for explicit close and GC finalizer, open+focus mobile search on ⌘K, harden set_weights shared clients, and centralize root Sudo wrapping with clearer origin docs. Also regenerate tx pages and add the /code viewer. Co-authored-by: Cursor <cursoragent@cursor.com>
…). Port the merged staging fix so published localnet manifests use smoke-tested platform digests, plus the supporting resolve/cleanup/smoke scripts from #2919 that this branch lacked. Also take the leasing weight tests' direct assert_ok! form that restores clippy. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
Co-authored-by: Cursor <cursoragent@cursor.com>
|
Resolved AI-review threads on signed-origin labeling: docs now use |
v431 is already on devnet/testnet and proposed for mainnet; this bump lets the release train redeploy and propose the follow-on SDK/docs/CI fixes. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
Bring in the staging→main promotion: localnet publication, SS58 balance precompile, leasing/hotkey-swap fixes, and dependency cleanups. Co-authored-by: Cursor <cursoragent@cursor.com> # Conflicts: # website/package.json # website/yarn.lock
…merge. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE |
| wallet = as_wallet(wallet) | ||
| intent = _coerce_addresses(intent) | ||
| built = await intent.build(self.substrate, wallet) | ||
| call = built.call if isinstance(built, BuiltCall) else built |
There was a problem hiding this comment.
[HIGH] Root intents lose their sudo wrapper when MEV-shielded
execute() wraps origin == "root" calls in Sudo.sudo, but submit_shielded() signs and encrypts the raw AdminUtils.sudo_* call. Since the CLI permits --mev-shield for any mutation, the new root intent follows this path and deterministically fails BadOrigin, despite being signed by the sudo account. Apply the same centralized wrapping invariant before fee estimation and signing, and add coverage for a shielded root intent.
| call = built.call if isinstance(built, BuiltCall) else built | |
| call = built.call if isinstance(built, BuiltCall) else built | |
| if intent.origin == "root" and not _is_sudo_call(call): | |
| call = await self.substrate.compose(generated_calls.Sudo.sudo(call=call)) |
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👎 |
Clone-upgrade failed the metadata drift gate after the staging merge and spec bump; emit _generated from a local 432 node so committed files match. Co-authored-by: Cursor <cursoragent@cursor.com>
| wallet = as_wallet(wallet) | ||
| intent = _coerce_addresses(intent) | ||
| built = await intent.build(self.substrate, wallet) | ||
| call = built.call if isinstance(built, BuiltCall) else built |
There was a problem hiding this comment.
[HIGH] Root intents lose their sudo wrapper when MEV-shielded
execute() converts every origin == "root" intent into Sudo.sudo, but submit_shielded() signs this raw inner call. For set_subnet_emission_enabled, the decrypted extrinsic therefore dispatches AdminUtils.sudo_set_subnet_emission_enabled with a signed origin and fails BadOrigin. Apply the same wrapping invariant here before fee estimation and signing, and add a shielded-root regression test.
| call = built.call if isinstance(built, BuiltCall) else built | |
| call = built.call if isinstance(built, BuiltCall) else built | |
| if intent.origin == "root" and not _is_sudo_call(call): | |
| call = await self.substrate.compose(generated_calls.Sudo.sudo(call=call)) |
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👎 |
submit_shielded skipped the root wrapping that plan/execute apply, so decrypted AdminUtils root calls failed BadOrigin under a signed origin. Co-authored-by: Cursor <cursoragent@cursor.com>
|
🔄 AI review updated — Skeptic: SAFE Auditor: 👍 |
Summary
origin(signed/subnet_owner/root) and an optional pairedverifyread, surfaced throughlist_tools()into the agent catalog (catalog/intents.json), the generatedbtcli txhelp (own "Root (chain sudo)" panel, generated "Requires:" / "Verify afterwards:" footers), the pre-sign confirmation flow, and the generated docs (Origin column + Verify section per tx page).set_subnet_emission_enabled— takes--netuids 89,127, batches atomically viaUtility.batch_all, wraps itself inSudo.sudo, and replaces the raw-only escape hatch forAdminUtils.sudo_set_subnet_emission_enabled. Paired with a newsubnet_emission_enabledread and a hyperparams-table entry so the flag shows next tosubnet_is_active.origin="root"intent must declare averifyread, and every declaredverifymust name a registered read — a privileged write can no longer ship without a way to check it.origin="subnet_owner"(verified against the runtime):set_hyperparameter,start_call,trim_subnet,set_mechanism_count,set_subnet_identity,update_symbol.bt.Subtensorentry point: one class that is the blocking client when used directly (private loop on a daemon thread, cleaned up via GC finalizer — noclose()needed) and the asyncClientwhen awaited or used withasync with. Adds module-levelbt.set_weights, re-points the v10 migration hints atSubtensor, and givesSyncClientweakref.finalize-based connection teardown.hyperparameters/subnet-emission-enabledexplainer and an "active vs emission-enabled" decision tree in the subnets guide; quickstart/migration/concepts guides rewritten aroundbt.Subtensor; site search and sidebar improvements; regenerated reference pages/catalogs. The generated Origin column now says "signed account" instead of "any signed key" (per review —signedis the dispatch-origin class, not blanket authorization).Test plan
codegen.check --coverage / --names / --units / --namespacesall green (includes the new verify-integrity gate)pytest: 952 passed, 1 skippedruff check/ruff format --check/ty checkcleangenerate.py --check: generated docs up to datebtcli tx set-subnet-emission-enabled --helprenders privilege + verify footers; catalog JSON carriesorigin/verifyMade with Cursor