@@ -11,6 +11,7 @@ import (
1111	"github.com/diggerhq/digger/opentaco/internal/repositories" 
1212	unithandlers "github.com/diggerhq/digger/opentaco/internal/unit" 
1313	"github.com/labstack/echo/v4" 
14+ 	"gorm.io/gorm" 
1415)
1516
1617
@@ -32,9 +33,23 @@ func RegisterInternalRoutes(e *echo.Echo, deps Dependencies) {
3233		userRepo  =  repositories .NewUserRepositoryFromQueryStore (deps .QueryStore )
3334	}
3435
35- 	// Create internal group with webhook auth (with orgRepo for existence check)  
36+ 	// Create internal group with webhook auth 
3637	internal  :=  e .Group ("/internal/api" )
37- 	internal .Use (middleware .WebhookAuth (orgRepo ))
38+ 	internal .Use (middleware .WebhookAuth ())
39+ 	
40+ 	// Add org resolution middleware - resolves org name to UUID and adds to domain context 
41+ 	if  deps .QueryStore  !=  nil  {
42+ 		if  dbGetter , ok  :=  deps .QueryStore .(interface { GetDB () * gorm.DB  }); ok  {
43+ 			db  :=  dbGetter .GetDB ()
44+ 			// Create identifier resolver (infrastructure layer) 
45+ 			identifierResolver  :=  repositories .NewIdentifierResolver (db )
46+ 			// Pass interface to middleware (clean architecture!) 
47+ 			internal .Use (middleware .ResolveOrgContextMiddleware (identifierResolver ))
48+ 			log .Println ("Org context resolution middleware enabled for internal routes" )
49+ 		} else  {
50+ 			log .Println ("WARNING: QueryStore does not implement GetDB() *gorm.DB - org resolution disabled" )
51+ 		}
52+ 	}
3853
3954	// Organization and User management endpoints 
4055	if  orgRepo  !=  nil  &&  userRepo  !=  nil  {
@@ -70,50 +85,45 @@ func RegisterInternalRoutes(e *echo.Echo, deps Dependencies) {
7085		log .Println ("RBAC management endpoints registered at /internal/api/rbac" )
7186	}
7287
73- 	orgService  :=  domain .NewOrgService ()
74- 	orgScopedRepo  :=  repositories .NewOrgScopedRepository (deps .Repository , orgService )
88+ 	// For internal routes, use RBAC-wrapped repository 
89+ 	// Architecture: 
90+ 	// - Webhook secret authenticates the SYSTEM (backend orchestrator)  
91+ 	// - X-User-ID header identifies the END USER making the request 
92+ 	// - RBAC enforces what that USER can do (via repository layer) 
93+ 	// - Org scoping handled by middleware (ResolveOrgContextMiddleware) + database foreign keys 
94+ 	
95+ 	// Create identifier resolver for unit name→UUID resolution 
96+ 	var  identifierResolver  domain.IdentifierResolver 
97+ 	if  deps .QueryStore  !=  nil  {
98+ 		if  dbGetter , ok  :=  deps .QueryStore .(interface { GetDB () * gorm.DB  }); ok  {
99+ 			db  :=  dbGetter .GetDB ()
100+ 			identifierResolver  =  repositories .NewIdentifierResolver (db )
101+ 		}
102+ 	}
75103
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 
104+ 	// Create handler with org-scoped + RBAC-wrapped repository 
80105	unitHandler  :=  unithandlers .NewHandler (
81- 		domain .UnitManagement (orgScopedRepo ),
106+ 		domain .UnitManagement (deps .Repository ), // Use RBAC-wrapped repository directly 
107+ 		deps .BlobStore ,
82108		deps .RBACManager ,
83109		deps .Signer ,
84110		deps .QueryStore ,
111+ 		identifierResolver ,
85112	)
86113
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- 	}
114+ 	// Internal routes with RBAC enforcement 
115+ 	// Note: Users must have permissions assigned via /internal/api/rbac endpoints 
116+ 	internal .POST ("/units" , unitHandler .CreateUnit )
117+ 	internal .GET ("/units" , unitHandler .ListUnits )
118+ 	internal .GET ("/units/:id" , unitHandler .GetUnit )
119+ 	internal .DELETE ("/units/:id" , unitHandler .DeleteUnit )
120+ 	internal .GET ("/units/:id/download" , unitHandler .DownloadUnit )
121+ 	internal .POST ("/units/:id/upload" , unitHandler .UploadUnit )
122+ 	internal .POST ("/units/:id/lock" , unitHandler .LockUnit )
123+ 	internal .DELETE ("/units/:id/unlock" , unitHandler .UnlockUnit )
124+ 	internal .GET ("/units/:id/status" , unitHandler .GetUnitStatus )
125+ 	internal .GET ("/units/:id/versions" , unitHandler .ListVersions )
126+ 	internal .POST ("/units/:id/restore" , unitHandler .RestoreVersion )
117127
118128	// Health check for internal routes 
119129	internal .GET ("/health" , func (c  echo.Context ) error  {
@@ -153,7 +163,6 @@ func RegisterInternalRoutes(e *echo.Echo, deps Dependencies) {
153163
154164	log .Printf ("Internal routes registered at /internal/api/* with webhook authentication" )
155165}
156- 
157166// wrapWithWebhookRBAC wraps a handler with RBAC permission checking 
158167func  wrapWithWebhookRBAC (manager  * rbac.RBACManager , action  rbac.Action , resource  string ) func (echo.HandlerFunc ) echo.HandlerFunc  {
159168	return  func (next  echo.HandlerFunc ) echo.HandlerFunc  {
@@ -208,3 +217,4 @@ func wrapWithWebhookRBAC(manager *rbac.RBACManager, action rbac.Action, resource
208217		}
209218	}
210219}
220+ 
0 commit comments