Add MCP proxy Agent Identity#1265
Conversation
|
Note Reviews pausedIt looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the Use the following commands to manage reviews:
Use the checkboxes below for quick actions:
📝 WalkthroughWalkthroughThis PR introduces an org-global scope catalog and env-scoped agent identity management on top of Thunder. It adds scope CRUD APIs and storage, agent identity group/role/assignment/agent-picker endpoints, Thunder client extensions for member/scope operations, MCP proxy identity-security validation and policy emission, generated OpenAPI/client artifacts, RBAC permissions, a DB migration, dependency wiring, and deployment/e2e scope updates. ChangesBackend Agent-Identity Security Feature
Estimated code review effort: 5 (Critical) | ~120 minutes Sequence Diagram(s)sequenceDiagram
participant Client
participant AgentIdentityController
participant EnvThunderResolver
participant EnvIdentityClient
participant ScopeRepository
Client->>AgentIdentityController: CreateRole(name, scopes)
AgentIdentityController->>ScopeRepository: validateScopesInCatalog(scopes)
ScopeRepository-->>AgentIdentityController: catalog scopes
AgentIdentityController->>EnvThunderResolver: ResolveIdentity(org, env)
EnvThunderResolver-->>AgentIdentityController: EnvIdentityClient
AgentIdentityController->>EnvIdentityClient: EnsureScopeResourceServer(scopes)
EnvIdentityClient-->>AgentIdentityController: resourceServerID
AgentIdentityController->>EnvIdentityClient: CreateRole + AddRolePermissions
EnvIdentityClient-->>AgentIdentityController: role created
AgentIdentityController-->>Client: 201 Created
sequenceDiagram
participant Client
participant MCPProxyService
participant ScopeRepository
participant GatewayRepository
Client->>MCPProxyService: Create/Update(proxyConfig)
MCPProxyService->>MCPProxyService: validateMCPEnvironments(env)
MCPProxyService->>ScopeRepository: load org scope catalog
ScopeRepository-->>MCPProxyService: known scopes
MCPProxyService->>GatewayRepository: resolve active gateway
GatewayRepository-->>MCPProxyService: gateway manifest or none
MCPProxyService->>MCPProxyService: gatewayHasMCPIdentityPolicies(mcp-auth, mcp-authz)
MCPProxyService-->>Client: validation result / persisted config
Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
e18a4cc to
b95c2ab
Compare
There was a problem hiding this comment.
Actionable comments posted: 6
🧹 Nitpick comments (4)
agent-manager-service/docs/api_v1_openapi.yaml (1)
9548-10095: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚖️ Poor tradeoffGeneric
objectschemas for Thunder passthrough responses reduce client type safety.Most agent-identity group/role/member/assignment responses use an untyped
type: objectschema instead of a concrete schema, unlike the rest of the API surface. This appears to be an intentional passthrough design (per the linked design doc), so I'm not flagging it as a defect, but consider adding at least minimal typed schemas for the more commonly consumed responses (e.g., group/role list/detail) in a follow-up once the Thunder response shapes stabilize, to improve generated console/client type safety.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-manager-service/docs/api_v1_openapi.yaml` around lines 9548 - 10095, The agent-identity Thunder passthrough responses are still modeled as generic object types, which limits generated client/console type safety. Add minimally typed response schemas for the commonly used group and role list/detail endpoints in the OpenAPI spec, and wire them into the relevant operations such as listAgentIdentityGroups, getAgentIdentityGroup, listAgentIdentityRoles, and getAgentIdentityRole. Keep the passthrough design intact where needed, but replace the broad object responses with concrete schemas wherever the Thunder shape is stable enough.console/apps/web-ui/public/config.js (1)
27-32: 📐 Maintainability & Code Quality | 🔵 TrivialScope allowlist duplicated across 4+ config surfaces.
This scope string is now duplicated verbatim in
config.js, bothdocker-compose.ymlservice blocks, and bothvalues.yamlkeys (plus a differently-formatted copy intest/e2e/framework/auth.go). Every future scope addition/removal must be replicated correctly everywhere, or environments will silently diverge in RBAC coverage.Consider generating this list from a single source of truth (e.g., derive from
rbac/permissions.goat build/deploy time) rather than hand-maintaining N copies.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@console/apps/web-ui/public/config.js` around lines 27 - 32, The scope allowlist is duplicated in the config and will drift across environments, so replace the hand-maintained string in the scopes configuration with a single source of truth generated from the canonical permissions definition. Update the logic around the scopes field in config.js to derive the list from rbac/permissions.go (or an equivalent shared generator) so docker, Helm, and test configs consume the same emitted set instead of separately copied scope strings.agent-manager-service/services/scope_service_unit_test.go (1)
32-100: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick winMissing coverage for
Createconflict/success andUpdatepaths.Existing tests cover name validation and
Delete, butCreate's duplicate-conflict branch (Lines 75-76 inscope_service.go) andUpdate(success/not-found) are untested. Given the TOCTOU concern flagged inscope_service.go, a test assertingCreatereturnsutils.ErrConflictfor an existing name would help lock in the intended behavior.As per path instructions: "Write service unit tests in
services/<service>_unit_test.go... assert the service's own logic withassert.ErrorIs/assert.NotErrorIsfor sentinels."🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-manager-service/services/scope_service_unit_test.go` around lines 32 - 100, Add unit coverage in ScopeService tests for the missing Create duplicate-conflict path and the Update flow. In the ScopeService.Create test cases, mock ScopeRepositoryMock.GetByName to return an existing scope and assert the result is utils.ErrConflict; also add a successful Create case that verifies the repository write path is reached. Add ScopeService.Update tests for both a successful update and the not-found branch by mocking ScopeRepositoryMock accordingly, and use assert.ErrorIs/assert.NoError to validate the service’s own sentinel behavior.Source: Path instructions
agent-manager-service/db_migrations/029_create_scopes.go (1)
36-38: 🚀 Performance & Scalability | 🔵 Trivial | 💤 Low valueRedundant index on
org_name.The
uq_scopes_org_nameunique constraint on(org_name, name)already backs an index whose leading column isorg_name, soidx_scopes_orgis likely redundant and only adds write overhead.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-manager-service/db_migrations/029_create_scopes.go` around lines 36 - 38, The scopes migration defines a redundant index on org_name because the uq_scopes_org_name unique constraint already creates a supporting index with org_name as the leading column. Update the migration in the scopes table creation block to remove idx_scopes_org and keep only the unique constraint, so the schema avoids unnecessary write overhead while preserving lookup support via the existing constraint-backed index.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@agent-manager-service/clients/thundersvc/identity_client.go`:
- Around line 925-1016: The `EnsureScopeResourceServer` path has a TOCTOU race:
concurrent callers can both miss the existing `amp-scopes` server and create
duplicates, and the same pattern exists when creating missing scope permissions.
Fix this by serializing the ensure logic per Thunder org/env +
`scopeResourceServerIdentifier` key, similar to `envThunderResolver.Resolve`’s
`singleflight` usage, so only one caller performs the create path at a time.
Keep the lock/singleflight only around the check-and-create decision, and avoid
holding it across network I/O longer than needed; the goal is to make
`findResourceServerID`/create and `listResourceServerPermissions`/create
effectively single-writer per key.
In `@agent-manager-service/controllers/agent_identity_controller.go`:
- Around line 311-327: `GetGroupRoles` and `GetRoleAssignments` are missing the
same not-found mapping used by the other single-resource handlers, so a missing
group/role currently becomes a generic 500. Update the error handling in
`agentIdentityController.GetGroupRoles` and
`agentIdentityController.GetRoleAssignments` to check
`thundersvc.IsNotFound(err)` before the fallback, and return a 404 with the
existing not-found response when that condition matches; keep the current 500
path for all other errors.
- Around line 650-668: The repository error is being discarded in
validateScopesInCatalog, which hides the real failure cause from
c.scopeRepo.List. Update the error handling in
agentIdentityController.validateScopesInCatalog to preserve the original error
by wrapping it with context instead of returning a generic error, so downstream
logs/debugging keep the DB/timeout details while still indicating scope catalog
loading failed.
In `@agent-manager-service/repositories/scope_repository.go`:
- Around line 74-82: Update scopeRepository.Update to mirror
scopeRepository.Delete by checking the RowsAffected from the
r.db.WithContext(ctx).Model(&models.Scope{}).Updates(...) call; if it is 0,
return the not-found sentinel mapped from gorm.ErrRecordNotFound (using
errors.Is for sentinel handling). Keep wrapping unexpected database errors with
context via fmt.Errorf, and preserve the existing Update method behavior for
successful writes.
In `@agent-manager-service/services/mcp_proxy_service.go`:
- Around line 855-862: ToolScopeBindings are being validated and persisted even
for environments without identity security, so add a guard in the
ToolScopeBindings handling path in mcp_proxy_service.go to reject these bindings
unless identity security is enabled. Update the validation logic in the
environment processing flow around the existing tool binding checks to return an
invalid-input error when identity/security is not configured, and apply the same
rule consistently in the related binding-check and persistence paths referenced
by the existing environment validation and save/update helpers. Use the existing
environment and binding symbols in this flow (such as ToolScopeBindings, envID,
and the surrounding environment validation functions) to keep the restriction
enforced everywhere bindings could otherwise be accepted.
In `@agent-manager-service/services/scope_service.go`:
- Around line 97-100: The reload step in the scope update flow is returning a
generic wrapped error instead of mapping a missing row to
utils.ErrScopeNotFound, so update the GetByName reload path in scope_service.go
to detect gorm.ErrRecordNotFound and return the same not-found error used
earlier in the method. Keep the existing context from the reload after
s.repo.Update, but ensure the retry/race case produces the 404-mapped
utils.ErrScopeNotFound rather than a 500-style failure.
---
Nitpick comments:
In `@agent-manager-service/db_migrations/029_create_scopes.go`:
- Around line 36-38: The scopes migration defines a redundant index on org_name
because the uq_scopes_org_name unique constraint already creates a supporting
index with org_name as the leading column. Update the migration in the scopes
table creation block to remove idx_scopes_org and keep only the unique
constraint, so the schema avoids unnecessary write overhead while preserving
lookup support via the existing constraint-backed index.
In `@agent-manager-service/docs/api_v1_openapi.yaml`:
- Around line 9548-10095: The agent-identity Thunder passthrough responses are
still modeled as generic object types, which limits generated client/console
type safety. Add minimally typed response schemas for the commonly used group
and role list/detail endpoints in the OpenAPI spec, and wire them into the
relevant operations such as listAgentIdentityGroups, getAgentIdentityGroup,
listAgentIdentityRoles, and getAgentIdentityRole. Keep the passthrough design
intact where needed, but replace the broad object responses with concrete
schemas wherever the Thunder shape is stable enough.
In `@agent-manager-service/services/scope_service_unit_test.go`:
- Around line 32-100: Add unit coverage in ScopeService tests for the missing
Create duplicate-conflict path and the Update flow. In the ScopeService.Create
test cases, mock ScopeRepositoryMock.GetByName to return an existing scope and
assert the result is utils.ErrConflict; also add a successful Create case that
verifies the repository write path is reached. Add ScopeService.Update tests for
both a successful update and the not-found branch by mocking ScopeRepositoryMock
accordingly, and use assert.ErrorIs/assert.NoError to validate the service’s own
sentinel behavior.
In `@console/apps/web-ui/public/config.js`:
- Around line 27-32: The scope allowlist is duplicated in the config and will
drift across environments, so replace the hand-maintained string in the scopes
configuration with a single source of truth generated from the canonical
permissions definition. Update the logic around the scopes field in config.js to
derive the list from rbac/permissions.go (or an equivalent shared generator) so
docker, Helm, and test configs consume the same emitted set instead of
separately copied scope strings.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 0c868bcc-3d43-46b2-9474-83815128d72b
📒 Files selected for processing (64)
agent-manager-service/api/agent_identity_routes.goagent-manager-service/api/app.goagent-manager-service/api/scope_routes.goagent-manager-service/clients/clientmocks/env_identity_client_mock.goagent-manager-service/clients/clientmocks/env_thunder_resolver_fake.goagent-manager-service/clients/thundersvc/env_resolver.goagent-manager-service/clients/thundersvc/identity_client.goagent-manager-service/clients/thundersvc/identity_client_test.goagent-manager-service/clients/thundersvc/identity_types.goagent-manager-service/controllers/agent_identity_controller.goagent-manager-service/controllers/agent_identity_controller_unit_test.goagent-manager-service/controllers/scope_controller.goagent-manager-service/db_migrations/029_create_scopes.goagent-manager-service/db_migrations/migration_list.goagent-manager-service/docs/api_v1_openapi.yamlagent-manager-service/models/llm_provider.goagent-manager-service/models/mcp_proxy.goagent-manager-service/models/scope.goagent-manager-service/rbac/permissions.goagent-manager-service/rbac/predefined_roles.goagent-manager-service/repositories/agent_thunder_client_repository.goagent-manager-service/repositories/repomocks/agent_thunder_client_repository_mock.goagent-manager-service/repositories/repomocks/scope_repository_mock.goagent-manager-service/repositories/scope_repository.goagent-manager-service/services/mcp_proxy_deployment.goagent-manager-service/services/mcp_proxy_deployment_test.goagent-manager-service/services/mcp_proxy_service.goagent-manager-service/services/mcp_proxy_service_unit_test.goagent-manager-service/services/scope_service.goagent-manager-service/services/scope_service_unit_test.goagent-manager-service/spec/api_agent_identity.goagent-manager-service/spec/api_scopes.goagent-manager-service/spec/client.goagent-manager-service/spec/model_agent_identity_agent_list_response.goagent-manager-service/spec/model_agent_identity_agent_response.goagent-manager-service/spec/model_agent_identity_assignments_request.goagent-manager-service/spec/model_agent_identity_assignments_request_assignments_inner.goagent-manager-service/spec/model_agent_identity_group_request.goagent-manager-service/spec/model_agent_identity_members_request.goagent-manager-service/spec/model_agent_identity_role_request.goagent-manager-service/spec/model_identity_security.goagent-manager-service/spec/model_mcp_environment_config.goagent-manager-service/spec/model_mcp_proxy_request.goagent-manager-service/spec/model_mcp_proxy_response.goagent-manager-service/spec/model_mcp_tool_scope_binding.goagent-manager-service/spec/model_scope_list_response.goagent-manager-service/spec/model_scope_request.goagent-manager-service/spec/model_scope_response.goagent-manager-service/spec/model_scope_update_request.goagent-manager-service/spec/model_security_config.goagent-manager-service/utils/constants.goagent-manager-service/utils/errors.goagent-manager-service/wiring/params.goagent-manager-service/wiring/wire.goagent-manager-service/wiring/wire_gen.goconsole/apps/web-ui/public/config.jsdeployments/docker-compose.ymldeployments/helm-charts/wso2-agent-manager/values.yamldeployments/helm-charts/wso2-amp-thunder-extension/values.yamldocs/superpowers/plans/2026-07-07-mcp-proxy-agent-identity-security.mddocs/superpowers/plans/2026-07-07-preflight-notes.mddocs/superpowers/specs/2026-07-06-mcp-proxy-agent-identity-security-design.mddocs/superpowers/specs/2026-07-07-env-thunder-grant-verification.mdtest/e2e/framework/auth.go
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
agent-manager-service/services/scope_service_unit_test.go (1)
92-103: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick winMap
repo.Deletenot-found toutils.ErrScopeNotFound
agent-manager-service/repositories/scope_repository.goreturnsgorm.ErrRecordNotFoundwhenDeleteaffects zero rows, butscopeService.Deleteforwards that error unchanged.DeleteScopeonly translatesutils.ErrScopeNotFound, so a concurrent delete still becomes a 500 instead of a 404. Mirror theUpdatemapping and add a unit test for the delete-after-get race.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-manager-service/services/scope_service_unit_test.go` around lines 92 - 103, scopeService.Delete currently lets a repo-level not-found escape as gorm.ErrRecordNotFound instead of utils.ErrScopeNotFound, so map the delete path the same way Update does. In scope_service.go, update Delete to translate the repository not-found from Delete (and any delete-after-get race handled through DeleteScope) into utils.ErrScopeNotFound before returning. Add or extend a unit test alongside TestScopeService_Delete_MissingScopeNotFound to cover the case where GetByName succeeds but repo.Delete returns not found, using the scopeService.Delete and DeleteScope flow to verify the mapping.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In `@agent-manager-service/services/scope_service_unit_test.go`:
- Around line 92-103: scopeService.Delete currently lets a repo-level not-found
escape as gorm.ErrRecordNotFound instead of utils.ErrScopeNotFound, so map the
delete path the same way Update does. In scope_service.go, update Delete to
translate the repository not-found from Delete (and any delete-after-get race
handled through DeleteScope) into utils.ErrScopeNotFound before returning. Add
or extend a unit test alongside TestScopeService_Delete_MissingScopeNotFound to
cover the case where GetByName succeeds but repo.Delete returns not found, using
the scopeService.Delete and DeleteScope flow to verify the mapping.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: 9b6bf8a1-cf2f-4977-a1c9-ec8ebed6e585
📒 Files selected for processing (10)
agent-manager-service/clients/thundersvc/identity_merge.goagent-manager-service/clients/thundersvc/identity_merge_test.goagent-manager-service/controllers/agent_identity_controller.goagent-manager-service/controllers/agent_identity_controller_unit_test.goagent-manager-service/controllers/identity_controller.goagent-manager-service/repositories/scope_repository.goagent-manager-service/services/mcp_proxy_service.goagent-manager-service/services/mcp_proxy_service_unit_test.goagent-manager-service/services/scope_service.goagent-manager-service/services/scope_service_unit_test.go
✅ Files skipped from review due to trivial changes (1)
- agent-manager-service/clients/thundersvc/identity_merge_test.go
🚧 Files skipped from review as they are similar to previous changes (5)
- agent-manager-service/repositories/scope_repository.go
- agent-manager-service/controllers/agent_identity_controller.go
- agent-manager-service/services/mcp_proxy_service_unit_test.go
- agent-manager-service/services/scope_service.go
- agent-manager-service/services/mcp_proxy_service.go
505ea84 to
d1280f3
Compare
Thunder's PUT /roles/{id} and /groups/{id} are full replaces, so the
per-field payload construction in the role/group update handlers
silently dropped unset fields (ouId, permissions, name). Route all four
handlers through shared NewRoleReplace/NewGroupReplace helpers that carry
the current ouId and permissions and preserve name/description when the
body omits them.
Also reject duplicate MCP tool-scope bindings for the same tool in
validateMCPEnvironments, and map scope-catalog Update misses to
not-found and Create duplicate-key races to conflict instead of 500.
Serialize EnsureScopeResourceServer's check-then-create paths to avoid duplicate Thunder resource servers under concurrent calls, map GetGroupRoles/GetRoleAssignments not-found to 404, log the swallowed scope catalog load error, and reject persisted tool scope bindings when identity security isn't enabled.
d1280f3 to
0d3f210
Compare
register-amp-resources.sh was missing scope, agent-identity, agent-kind, profile and the mcp-server/agent api-key-manage actions; the Helm 60-amp-resource-server.sh was missing scope and agent-identity. Add them so both scripts register the full 104-permission catalog from rbac, and add scope/agent-identity to the default roles in 61-amp-default-roles.sh to match rbac/predefined_roles.go. Fix the stale permission counts.
Resolve conflicts from upstream's org_name -> ou_id migration: - Renumber our migration029 (create scopes) to migration031; upstream now owns 029 (add ou_id) and 030 (swap constraints to ou_id) - Migrate agent-identity picker to ou_id: FindByOrgAndEnvironment -> FindByOuAndEnvironment, ListAgents resolves ouID via OUIDFromRequest - Re-wire ProvideEnvThunderResolver for AgentIdentityController (upstream de-wired it; our controller is a new production consumer) - Regenerate wire, repository mocks, and CLI client
There was a problem hiding this comment.
Caution
Some comments are outside the diff and can’t be posted inline due to platform limitations.
⚠️ Outside diff range comments (1)
agent-manager-service/repositories/repomocks/agent_thunder_client_repository_mock.go (1)
1-1: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick winAdd the Apache license header to this generated mock. The file starts with the moq comment only; prepend the standard Apache header so it matches the repository requirement.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@agent-manager-service/repositories/repomocks/agent_thunder_client_repository_mock.go` at line 1, Add the standard Apache license header to the generated mock so the file begins with the repository’s required copyright/license block before the moq-generated comment; update the top of agent_thunder_client_repository_mock.go accordingly and keep the existing generated marker intact.Source: Coding guidelines
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Outside diff comments:
In
`@agent-manager-service/repositories/repomocks/agent_thunder_client_repository_mock.go`:
- Line 1: Add the standard Apache license header to the generated mock so the
file begins with the repository’s required copyright/license block before the
moq-generated comment; update the top of agent_thunder_client_repository_mock.go
accordingly and keep the existing generated marker intact.
ℹ️ Review info
⚙️ Run configuration
Configuration used: Path: .coderabbit.yaml
Review profile: CHILL
Plan: Pro
Run ID: d6af2171-32fb-43fc-8839-f0fe1bab0117
⛔ Files ignored due to path filters (1)
cli/pkg/clients/amsvc/gen/types.gen.gois excluded by!**/gen/**
📒 Files selected for processing (14)
agent-manager-service/controllers/agent_identity_controller.goagent-manager-service/controllers/agent_identity_controller_unit_test.goagent-manager-service/db_migrations/031_create_scopes.goagent-manager-service/db_migrations/migration_list.goagent-manager-service/docs/api_v1_openapi.yamlagent-manager-service/repositories/agent_thunder_client_repository.goagent-manager-service/repositories/repomocks/agent_thunder_client_repository_mock.goagent-manager-service/services/mcp_proxy_deployment.goagent-manager-service/services/mcp_proxy_service.goagent-manager-service/wiring/wire.goagent-manager-service/wiring/wire_gen.goconsole/apps/web-ui/public/config.jsdeployments/docker-compose.ymldeployments/helm-charts/wso2-agent-manager/values.yaml
💤 Files with no reviewable changes (5)
- agent-manager-service/wiring/wire.go
- deployments/docker-compose.yml
- deployments/helm-charts/wso2-agent-manager/values.yaml
- agent-manager-service/wiring/wire_gen.go
- console/apps/web-ui/public/config.js
🚧 Files skipped from review as they are similar to previous changes (5)
- agent-manager-service/services/mcp_proxy_deployment.go
- agent-manager-service/controllers/agent_identity_controller_unit_test.go
- agent-manager-service/services/mcp_proxy_service.go
- agent-manager-service/controllers/agent_identity_controller.go
- agent-manager-service/docs/api_v1_openapi.yaml
Purpose
Adds the Agent Identity security foundation for MCP proxies: an org-global scope catalog and the per-environment tool→scope binding model that the gateway
mcp-auth/mcp-authzpolicies and env-Thunder grant management will build on.This PR covers Phase 0 (preconditions) and Phase 1 (backend scope catalog) only. Console UI (Phase 2) and E2E (Phase 3) are tracked separately and are not in this PR.
Goals
Approach
029_create_scopes— newscopestable (org_name,name,description, timestamps) with a(org_name, name)uniqueness constraint and an org index.models.ScopeandScopeRepository(List/GetByName/Create/Update/Delete) with amoq-generated mock.docs/api_v1_openapi.yamladdsGET/POST /orgs/{orgName}/scopesandPUT/DELETE /orgs/{orgName}/scopes/{scopeName};spec/regenerated viamake spec.ScopeServicevalidates the scope-name grammar^[A-Za-z0-9:._\-]{1,256}$, rejects duplicates (ErrConflict), and blocks deletion while any MCP proxy environment tool binding references the scope (paginated catalog scan).HandleFuncWithValidationAndAuthz.scope:create/read/update/deletepermissions, granted to Admin/AI Lead (full) and Developer/Platform Engineer (read).MCPToolScopeBindingandToolScopeBindingsfields added to the MCP proxy config (flat + per-environment), consumed by the delete-guard binding scan.docs/superpowers/.User stories
As an org admin/AI lead, I can define and manage a catalog of scopes for my organization so that (in later phases) MCP proxy tools can be bound to scopes and enforced per environment.
Release note
Add an org-global scope catalog API for MCP proxy Agent Identity security (backend foundation).
Documentation
N/A — backend foundation only; user-facing documentation will accompany the console (Phase 2) work.
Training
N/A — no training-content impact.
Certification
N/A — no impact on certification exams.
Marketing
N/A — foundational backend change, not independently promoted.
Automation tests
Security checks
Samples
N/A.
Related PRs
Builds on the merged MCP proxy UX revamp (PR #1258). Follow-up PRs will add gateway
mcp-auth/mcp-authzemission, env-Thunder scope resource-server + grant passthrough, and the console UI.Migrations (if applicable)
Adds migration
029_create_scopes. Runmake dev-migrate(or the standard migration path) before starting the service. Tested against the local PostgreSQL dev database.Test environment
Learning
Spiked the env-Thunder grant model against a live environment to confirm the resource-server / role / group grant shapes and that agents must request scopes in the token request (Thunder filters to entitlements). Findings recorded under
docs/superpowers/specs/.Summary by CodeRabbit
New Features
Bug Fixes