SMOODEV-1863: Route th api agents through the user JWT (like th api crm)#174
Open
brentrager wants to merge 1 commit into
Open
SMOODEV-1863: Route th api agents through the user JWT (like th api crm)#174brentrager wants to merge 1 commit into
brentrager wants to merge 1 commit into
Conversation
…i crm`) `th api agents show/update` 403'd on child orgs because the command authenticated with the org-locked M2M `client_credentials` token (`require_authed()`), and M2M tokens are intentionally bound to a single org. `th api crm` already avoids this by authenticating as the logged-in user (Supabase JWT via `UserClient::from_user_session()`), whose org membership carries cross-org (parent-org admin) access. Mirror that exactly: `th api agents` now builds a `UserClient` at the top of `cmd` and every verb (list/show/update/delete/summary/regenerate/ knowledge/mint/create/generate-config) runs on the user session. Drops the M2M `require_authed()` gate; org resolution moves to `active_org::resolve` (the arg `require_active_org` ignored anyway). `UserClient` gains `put` (set-knowledge) and `post_empty` (the no-body `regenerate-*` posts) so it covers the agent verbs' method surface — `post`'s signature is unchanged, so `th api crm` call sites are untouched. Paired with the monorepo PR (#2531) that org-locks the native agents LIST handler against M2M. They MUST land together: the monorepo PR makes M2M stricter (closing the LIST leak), this one restores + extends Brent's access (list+show+update) via his user membership. Strictly tighter M2M, never looser. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
🦋 Changeset detectedLatest commit: 28a2240 The changes in this PR will be included in the next version bump. This PR includes changesets to release 1 package
Not sure what this means? Click here to learn what changesets are. Click here if you're a maintainer who wants to add another changeset to this PR |
Contributor
Author
|
Superseded by #105 (root-cause fix at |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
th api agents show/update403 on child orgs. The command authenticated with the org-locked M2Mclient_credentialstoken (require_authed()), and M2M tokens are intentionally bound to a single org — so acting on a child org is forbidden.th api agents list"worked" only because the native Rust LIST handler didn't apply the M2M org-lock (a leak — fixed in the paired monorepo PR).th api crmnever had this problem: it authenticates as the logged-in user (Supabase JWT viaUserClient::from_user_session()), whose org membership carries cross-org (parent-org admin) access.Fix — mirror
th api crmexactlycrates/smooth-cli/src/smooai/agents.rs: build aUserClientat the top ofcmd(the same selectioncrm.rs:564etc. make) and run every verb on the user session — list/show/update/delete/summary/regenerate/knowledge/mint/create/generate-config. Drops the M2Mrequire_authed()gate; org resolution moves tocrate::active_org::resolve(therequire_active_orgclient arg was unused).crates/smooth-cli/src/smooai/user_client.rs: addput(set-knowledge) andpost_empty(the no-bodyregenerate-*posts) soUserClientcovers the agent verbs' method surface.post's signature is unchanged, so theth api crmcall sites are untouched.Auth selection (file:line)
agents.rscmd()now opens withlet client = UserClient::from_user_session().await?;— identical mechanism toth api crm(crm.rs:564,616,732…). Previouslylet client = require_authed().await?;(M2M).Tests
cargo test -p smooai-smooth-cli --bin th smooai::agents— 13 passed (thebuild_update_body/build_mint_bodybody-builder tests, unaffected by the client-selection change). The auth-selection itself is a wiring change with no unit-testable branch, and the workspace has no HTTP-mock infra; live verification is left to the human session per the pairing plan. fmt clean, clippy 0 errors.Paired PR (MUST land together)
monorepo #2531 org-locks the native agents LIST handler against M2M. That PR makes M2M stricter (closing the LIST leak); this PR restores + extends access (list+show+update) via the user session. Landing #2531 alone would 403 the currently-working master-M2M
list <child-org>. Strictly tighter M2M, never looser.🤖 Generated with Claude Code