@@ -593,26 +593,6 @@ export async function approveDevicePairing(
593593 scope : roleMismatchScope ,
594594 } ;
595595 }
596- const requestedOperatorScopes = requestedScopes . filter ( ( scope ) =>
597- scope . startsWith ( OPERATOR_SCOPE_PREFIX ) ,
598- ) ;
599- if ( requestedOperatorScopes . length > 0 ) {
600- if ( ! options ?. callerScopes ) {
601- return {
602- status : "forbidden" ,
603- reason : "caller-scopes-required" ,
604- scope : requestedOperatorScopes [ 0 ] ,
605- } ;
606- }
607- const missingScope = resolveMissingRequestedScope ( {
608- role : OPERATOR_ROLE ,
609- requestedScopes : requestedOperatorScopes ,
610- allowedScopes : options . callerScopes ,
611- } ) ;
612- if ( missingScope ) {
613- return { status : "forbidden" , reason : "caller-missing-scope" , scope : missingScope } ;
614- }
615- }
616596 const now = Date . now ( ) ;
617597 const existing = state . pairedByDeviceId [ pending . deviceId ] ;
618598 const roles = mergeRoles ( existing ?. roles , existing ?. role , pending . roles , pending . role ) ;
@@ -621,6 +601,7 @@ export async function approveDevicePairing(
621601 pending . scopes ,
622602 ) ;
623603 const tokens = existing ?. tokens ? { ...existing . tokens } : { } ;
604+ const nextTokenScopesByRole = new Map < string , string [ ] > ( ) ;
624605 for ( const roleForToken of requestedRoles ) {
625606 const existingToken = tokens [ roleForToken ] ;
626607 const nextScopes = resolveApprovedTokenScopes ( {
@@ -630,13 +611,34 @@ export async function approveDevicePairing(
630611 approvedScopes,
631612 existing,
632613 } ) ;
633- const now = Date . now ( ) ;
614+ nextTokenScopesByRole . set ( roleForToken , nextScopes ) ;
615+ if ( roleForToken === OPERATOR_ROLE && nextScopes . length > 0 ) {
616+ if ( ! options ?. callerScopes ) {
617+ return {
618+ status : "forbidden" ,
619+ reason : "caller-scopes-required" ,
620+ scope : nextScopes [ 0 ] ,
621+ } ;
622+ }
623+ const missingScope = resolveMissingRequestedScope ( {
624+ role : OPERATOR_ROLE ,
625+ requestedScopes : nextScopes ,
626+ allowedScopes : options . callerScopes ,
627+ } ) ;
628+ if ( missingScope ) {
629+ return { status : "forbidden" , reason : "caller-missing-scope" , scope : missingScope } ;
630+ }
631+ }
632+ }
633+ for ( const [ roleForToken , nextScopes ] of nextTokenScopesByRole ) {
634+ const existingToken = tokens [ roleForToken ] ;
635+ const tokenNow = Date . now ( ) ;
634636 tokens [ roleForToken ] = {
635637 token : newToken ( ) ,
636638 role : roleForToken ,
637639 scopes : nextScopes ,
638- createdAtMs : existingToken ?. createdAtMs ?? now ,
639- rotatedAtMs : existingToken ? now : undefined ,
640+ createdAtMs : existingToken ?. createdAtMs ?? tokenNow ,
641+ rotatedAtMs : existingToken ? tokenNow : undefined ,
640642 revokedAtMs : undefined ,
641643 lastUsedAtMs : existingToken ?. lastUsedAtMs ,
642644 } ;
0 commit comments