Context
The scoped NyxId chat endpoints under /api/scopes/{scopeId}/nyxid-chat/... currently rely on route shape alone and do not consistently enforce the shared authenticated scope guard before operating inside a requested scope.
This is not a new regression from the current branch. The same route shape and bare-actorId resolution already exist on dev, but PR #452 / issue #348 replace the old store-shaped contract with explicit registry command/query/admission ports, so the fix should use the new ports rather than IGAgentActorStore.
Problem
- scoped NyxId chat endpoints are mounted under
/api/scopes/... but create/list/delete do not apply AevatarScopeAccessGuard
stream / approve currently require a bearer token and registry admission, but still need caller-scope validation before target admission
- callers who know a valid
actorId can potentially target a conversation outside the authenticated caller scope if the route scope is not checked first
- registry admission proves target ownership for
(scopeId, resource, operation); it does not by itself prove the caller is authorized to use that scopeId
Desired fix
Apply the shared scope guard to NyxID scoped chat endpoints and require conversation ownership validation through the scope resource admission port before target operations.
Acceptance criteria
- scoped NyxID chat endpoints reject mismatched authenticated scopes via
AevatarScopeAccessGuard
- create/list/delete validate caller scope before performing registry command/query or side effects
stream / approve validate caller scope before IScopeResourceAdmissionPort.AuthorizeTargetAsync
stream / approve / delete validate (scopeId, ScopeResourceKind.GAgentActor, NyxIdChatServiceDefaults.GAgentTypeName, actorId, operation) through IScopeResourceAdmissionPort
- bare
actorId is no longer sufficient to access a conversation across scopes
- targeted endpoint coverage exists for scope mismatch and unregistered conversation paths
Context
The scoped NyxId chat endpoints under
/api/scopes/{scopeId}/nyxid-chat/...currently rely on route shape alone and do not consistently enforce the shared authenticated scope guard before operating inside a requested scope.This is not a new regression from the current branch. The same route shape and bare-
actorIdresolution already exist ondev, but PR #452 / issue #348 replace the old store-shaped contract with explicit registry command/query/admission ports, so the fix should use the new ports rather thanIGAgentActorStore.Problem
/api/scopes/...but create/list/delete do not applyAevatarScopeAccessGuardstream/approvecurrently require a bearer token and registry admission, but still need caller-scope validation before target admissionactorIdcan potentially target a conversation outside the authenticated caller scope if the route scope is not checked first(scopeId, resource, operation); it does not by itself prove the caller is authorized to use thatscopeIdDesired fix
Apply the shared scope guard to NyxID scoped chat endpoints and require conversation ownership validation through the scope resource admission port before target operations.
Acceptance criteria
AevatarScopeAccessGuardstream/approvevalidate caller scope beforeIScopeResourceAdmissionPort.AuthorizeTargetAsyncstream/approve/deletevalidate(scopeId, ScopeResourceKind.GAgentActor, NyxIdChatServiceDefaults.GAgentTypeName, actorId, operation)throughIScopeResourceAdmissionPortactorIdis no longer sufficient to access a conversation across scopes