@@ -32,9 +32,22 @@ func RegisterInternalRoutes(e *echo.Echo, deps Dependencies) {
3232		userRepo  =  repositories .NewUserRepositoryFromQueryStore (deps .QueryStore )
3333	}
3434
35- 	// Create internal group with webhook auth (with orgRepo for existence check)  
35+ 	// Create internal group with webhook auth 
3636	internal  :=  e .Group ("/internal/api" )
37- 	internal .Use (middleware .WebhookAuth (orgRepo ))
37+ 	internal .Use (middleware .WebhookAuth ())
38+ 	
39+ 	// Add org resolution middleware - resolves org name to UUID and adds to domain context 
40+ 	if  deps .QueryStore  !=  nil  {
41+ 		if  db  :=  repositories .GetDBFromQueryStore (deps .QueryStore ); db  !=  nil  {
42+ 			// Create identifier resolver (infrastructure layer) 
43+ 			identifierResolver  :=  repositories .NewIdentifierResolver (db )
44+ 			// Pass interface to middleware (clean architecture!) 
45+ 			internal .Use (middleware .ResolveOrgContextMiddleware (identifierResolver ))
46+ 			log .Println ("Org context resolution middleware enabled for internal routes" )
47+ 		} else  {
48+ 			log .Println ("WARNING: QueryStore does not implement GetDB() *gorm.DB - org resolution disabled" )
49+ 		}
50+ 	}
3851
3952	// Organization and User management endpoints 
4053	if  orgRepo  !=  nil  &&  userRepo  !=  nil  {
@@ -70,50 +83,44 @@ func RegisterInternalRoutes(e *echo.Echo, deps Dependencies) {
7083		log .Println ("RBAC management endpoints registered at /internal/api/rbac" )
7184	}
7285
73- 	orgService  :=  domain .NewOrgService ()
74- 	orgScopedRepo  :=  repositories .NewOrgScopedRepository (deps .Repository , orgService )
86+ 	// For internal routes, use RBAC-wrapped repository 
87+ 	// Architecture: 
88+ 	// - Webhook secret authenticates the SYSTEM (backend orchestrator)  
89+ 	// - X-User-ID header identifies the END USER making the request 
90+ 	// - RBAC enforces what that USER can do (via repository layer) 
91+ 	// - Org scoping handled by middleware (ResolveOrgContextMiddleware) + database foreign keys 
92+ 	
93+ 	// Create identifier resolver for unit name→UUID resolution 
94+ 	var  identifierResolver  domain.IdentifierResolver 
95+ 	if  deps .QueryStore  !=  nil  {
96+ 		if  db  :=  repositories .GetDBFromQueryStore (deps .QueryStore ); db  !=  nil  {
97+ 			identifierResolver  =  repositories .NewIdentifierResolver (db )
98+ 		}
99+ 	}
75100
76- 	// Create handler with org-scoped repository 
77- 	// The repository will automatically: 
78- 	// - Filter List() to org namespace 
79- 	// - Validate all operations belong to user's org 
101+ 	// Create handler with org-scoped + RBAC-wrapped repository 
80102	unitHandler  :=  unithandlers .NewHandler (
81- 		domain .UnitManagement (orgScopedRepo ),
103+ 		domain .UnitManagement (deps .Repository ), // Use RBAC-wrapped repository directly 
104+ 		deps .BlobStore ,
82105		deps .RBACManager ,
83106		deps .Signer ,
84107		deps .QueryStore ,
108+ 		identifierResolver ,
85109	)
86110
87- 
88- 
89- 
90- 	if  deps .RBACManager  !=  nil  {
91- 		// With RBAC - apply RBAC permission checks 
92- 		// Org scoping is automatic via orgScopedRepository 
93- 		internal .POST ("/units" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitWrite , "*" )(unitHandler .CreateUnit ))
94- 		internal .GET ("/units" , unitHandler .ListUnits ) // Automatically filters by org 
95- 		internal .GET ("/units/:id" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitRead , "{id}" )(unitHandler .GetUnit ))
96- 		internal .DELETE ("/units/:id" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitDelete , "{id}" )(unitHandler .DeleteUnit ))
97- 		internal .GET ("/units/:id/download" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitRead , "{id}" )(unitHandler .DownloadUnit ))
98- 		internal .POST ("/units/:id/upload" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitWrite , "{id}" )(unitHandler .UploadUnit ))
99- 		internal .POST ("/units/:id/lock" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitLock , "{id}" )(unitHandler .LockUnit ))
100- 		internal .DELETE ("/units/:id/unlock" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitLock , "{id}" )(unitHandler .UnlockUnit ))
101- 		internal .GET ("/units/:id/status" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitRead , "{id}" )(unitHandler .GetUnitStatus ))
102- 		internal .GET ("/units/:id/versions" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitRead , "{id}" )(unitHandler .ListVersions ))
103- 		internal .POST ("/units/:id/restore" , wrapWithWebhookRBAC (deps .RBACManager , rbac .ActionUnitWrite , "{id}" )(unitHandler .RestoreVersion ))
104- 	} else  {
105- 		internal .POST ("/units" , unitHandler .CreateUnit )
106- 		internal .GET ("/units" , unitHandler .ListUnits )
107- 		internal .GET ("/units/:id" , unitHandler .GetUnit )
108- 		internal .DELETE ("/units/:id" , unitHandler .DeleteUnit )
109- 		internal .GET ("/units/:id/download" , unitHandler .DownloadUnit )
110- 		internal .POST ("/units/:id/upload" , unitHandler .UploadUnit )
111- 		internal .POST ("/units/:id/lock" , unitHandler .LockUnit )
112- 		internal .DELETE ("/units/:id/unlock" , unitHandler .UnlockUnit )
113- 		internal .GET ("/units/:id/status" , unitHandler .GetUnitStatus )
114- 		internal .GET ("/units/:id/versions" , unitHandler .ListVersions )
115- 		internal .POST ("/units/:id/restore" , unitHandler .RestoreVersion )
116- 	}
111+ 	// Internal routes with RBAC enforcement 
112+ 	// Note: Users must have permissions assigned via /internal/api/rbac endpoints 
113+ 	internal .POST ("/units" , unitHandler .CreateUnit )
114+ 	internal .GET ("/units" , unitHandler .ListUnits )
115+ 	internal .GET ("/units/:id" , unitHandler .GetUnit )
116+ 	internal .DELETE ("/units/:id" , unitHandler .DeleteUnit )
117+ 	internal .GET ("/units/:id/download" , unitHandler .DownloadUnit )
118+ 	internal .POST ("/units/:id/upload" , unitHandler .UploadUnit )
119+ 	internal .POST ("/units/:id/lock" , unitHandler .LockUnit )
120+ 	internal .DELETE ("/units/:id/unlock" , unitHandler .UnlockUnit )
121+ 	internal .GET ("/units/:id/status" , unitHandler .GetUnitStatus )
122+ 	internal .GET ("/units/:id/versions" , unitHandler .ListVersions )
123+ 	internal .POST ("/units/:id/restore" , unitHandler .RestoreVersion )
117124
118125	// Health check for internal routes 
119126	internal .GET ("/health" , func (c  echo.Context ) error  {
@@ -153,7 +160,6 @@ func RegisterInternalRoutes(e *echo.Echo, deps Dependencies) {
153160
154161	log .Printf ("Internal routes registered at /internal/api/* with webhook authentication" )
155162}
156- 
157163// wrapWithWebhookRBAC wraps a handler with RBAC permission checking 
158164func  wrapWithWebhookRBAC (manager  * rbac.RBACManager , action  rbac.Action , resource  string ) func (echo.HandlerFunc ) echo.HandlerFunc  {
159165	return  func (next  echo.HandlerFunc ) echo.HandlerFunc  {
@@ -208,3 +214,4 @@ func wrapWithWebhookRBAC(manager *rbac.RBACManager, action rbac.Action, resource
208214		}
209215	}
210216}
217+ 
0 commit comments