@@ -18,6 +18,7 @@ import {
1818 removeDirSync ,
1919 stripRedundantNodejsCompatFlags ,
2020} from "@cloudflare/workers-utils" ;
21+ import SCRIPT_ACCESS_IDENTITY from "worker:access/access-identity" ;
2122import SCRIPT_DEV_CONTROL from "worker:core/dev-control" ;
2223import SCRIPT_ENTRY from "worker:core/entry" ;
2324import OUTBOUND_WORKER from "worker:core/outbound" ;
@@ -308,6 +309,10 @@ function getDevControlBindings(
308309 return Array . from ( bindings . values ( ) ) ;
309310}
310311
312+ function getAccessIdentityServiceName ( workerIndex : number ) {
313+ return `access-identity:${ workerIndex } ` ;
314+ }
315+
311316function getOutboundInterceptorName ( workerIndex : number ) {
312317 return `outbound:${ workerIndex } ` ;
313318}
@@ -653,6 +658,14 @@ export const CORE_PLUGIN: Plugin = {
653658 . filter ( ( consumer ) => consumer . streaming )
654659 . map < ServiceDesignator > ( getTailServiceDesignator ) ,
655660 containerEngine : getContainerEngine ( sharedOptions . containerEngine ) ,
661+ ...( dev ?. access
662+ ? {
663+ accessBlobHeader : CoreHeaders . ACCESS_BLOB ,
664+ accessBindingService : {
665+ name : getAccessIdentityServiceName ( workerIndex ) ,
666+ } ,
667+ }
668+ : { } ) ,
656669 } ,
657670 } ) ;
658671
@@ -710,6 +723,26 @@ export const CORE_PLUGIN: Plugin = {
710723 } ) ;
711724 }
712725
726+ // Access identity binding worker for ctx.access.getIdentity()
727+ if ( dev ?. access ) {
728+ services . push ( {
729+ name : getAccessIdentityServiceName ( workerIndex ) ,
730+ worker : {
731+ modules : [
732+ {
733+ name : "index.js" ,
734+ esModule : SCRIPT_ACCESS_IDENTITY ( ) ,
735+ } ,
736+ ] ,
737+ compatibilityDate : "2025-01-01" ,
738+ compatibilityFlags : [
739+ "experimental" ,
740+ "service_binding_extra_handlers" ,
741+ ] ,
742+ } ,
743+ } ) ;
744+ }
745+
713746 return { services, extensions } ;
714747 } ,
715748} ;
@@ -857,6 +890,31 @@ export function getGlobalServices({
857890 data : encoder . encode ( sharedOptions . unsafeProxySharedSecret ) ,
858891 } ) ;
859892 }
893+ // Inject per-worker Cloudflare Access blob bindings into the entry worker.
894+ // Each worker with dev.access gets its own blob keyed by worker name so the
895+ // entry worker can pick the correct one after routing.
896+ for ( const workerOpt of allWorkerOpts ?? [ ] ) {
897+ const accessOpts = workerOpt . dev ?. access ;
898+ if ( accessOpts ) {
899+ const accessBlob : {
900+ app_aud : string ;
901+ jwt_claims ?: Record < string , unknown > ;
902+ } = { app_aud : accessOpts . aud } ;
903+ if ( accessOpts . identity ) {
904+ accessBlob . jwt_claims = accessOpts . identity ;
905+ }
906+ serviceEntryBindings . push ( {
907+ name : CoreBindings . JSON_ACCESS_BLOB_PREFIX + workerOpt . config . name ,
908+ json : JSON . stringify ( accessBlob ) ,
909+ } ) ;
910+ }
911+ }
912+ // Pass the first worker's raw name so the entry worker can look up its
913+ // access blob when no route matches (the fallback is always the first worker).
914+ serviceEntryBindings . push ( {
915+ name : CoreBindings . TEXT_FALLBACK_WORKER_NAME ,
916+ text : workerNames [ 0 ] ?? "" ,
917+ } ) ;
860918 const services : Service [ ] = [
861919 {
862920 name : SERVICE_LOOPBACK ,
0 commit comments