@@ -250,12 +250,32 @@ func RegisterRoutes(e *echo.Echo, deps Dependencies) {
250250 // Unwrapped repository is used for signed URL operations (pre-authorized, no RBAC checks needed)
251251 // Create identifier resolver for org resolution
252252 var tfeIdentifierResolver domain.IdentifierResolver
253+ var runRepo domain.TFERunRepository
254+ var planRepo domain.TFEPlanRepository
255+ var configVerRepo domain.TFEConfigurationVersionRepository
256+
253257 if deps .QueryStore != nil {
254258 if db := repositories .GetDBFromQueryStore (deps .QueryStore ); db != nil {
255259 tfeIdentifierResolver = repositories .NewIdentifierResolver (db )
260+ // Create TFE repositories for runs, plans, and configuration versions
261+ runRepo = repositories .NewTFERunRepository (db )
262+ planRepo = repositories .NewTFEPlanRepository (db )
263+ configVerRepo = repositories .NewTFEConfigurationVersionRepository (db )
264+ log .Println ("TFE repositories initialized successfully" )
256265 }
257266 }
258- tfeHandler := tfe .NewTFETokenHandler (authHandler , deps .Repository , deps .UnwrappedRepository , deps .BlobStore , deps .RBACManager , tfeIdentifierResolver )
267+
268+ tfeHandler := tfe .NewTFETokenHandler (
269+ authHandler ,
270+ deps .Repository ,
271+ deps .UnwrappedRepository ,
272+ deps .BlobStore ,
273+ deps .RBACManager ,
274+ tfeIdentifierResolver ,
275+ runRepo ,
276+ planRepo ,
277+ configVerRepo ,
278+ )
259279
260280 // Create protected TFE group - opaque tokens only
261281 tfeGroup := e .Group ("/tfe/api/v2" )
@@ -276,7 +296,24 @@ func RegisterRoutes(e *echo.Echo, deps Dependencies) {
276296 tfeGroup .POST ("/workspaces/:workspace_id/state-versions" , tfeHandler .CreateStateVersion )
277297 tfeGroup .GET ("/state-versions/:id" , tfeHandler .ShowStateVersion )
278298
279- tfeGroup .GET ("/plans/:planID/logs/:blobId" , tfeHandler .GetPlanLogs )
299+ // Configuration version routes
300+ tfeGroup .POST ("/workspaces/:workspace_name/configuration-versions" , tfeHandler .CreateConfigurationVersions )
301+ tfeGroup .GET ("/configuration-versions/:id" , tfeHandler .GetConfigurationVersion )
302+
303+ // Run routes
304+ tfeGroup .POST ("/runs" , tfeHandler .CreateRun )
305+ tfeGroup .GET ("/runs/:id" , tfeHandler .GetRun )
306+ tfeGroup .POST ("/runs/:id/actions/apply" , tfeHandler .ApplyRun )
307+ tfeGroup .GET ("/runs/:id/policy-checks" , tfeHandler .GetPolicyChecks )
308+ tfeGroup .GET ("/runs/:id/task-stages" , tfeHandler .GetTaskStages )
309+ tfeGroup .GET ("/runs/:id/cost-estimates" , tfeHandler .GetCostEstimates )
310+ tfeGroup .GET ("/runs/:id/run-events" , tfeHandler .GetRunEvents )
311+
312+ // Plan routes
313+ tfeGroup .GET ("/plans/:id" , tfeHandler .GetPlan )
314+
315+ // Apply routes
316+ tfeGroup .GET ("/applies/:id" , tfeHandler .GetApply )
280317
281318 // Upload endpoints exempt from auth middleware (Terraform doesn't send auth headers)
282319 // Security: These validate lock ownership and have RBAC checks in handlers
@@ -287,6 +324,14 @@ func RegisterRoutes(e *echo.Echo, deps Dependencies) {
287324 tfeSignedUrlsGroup .PUT ("/state-versions/:id/upload" , tfeHandler .UploadStateVersion )
288325 tfeSignedUrlsGroup .PUT ("/state-versions/:id/json-upload" , tfeHandler .UploadJSONStateOutputs )
289326 tfeSignedUrlsGroup .PUT ("/configuration-versions/:id/upload" , tfeHandler .UploadConfigurationArchive )
327+
328+ // Plan log streaming - token-based auth (token embedded in path, not query string)
329+ // Security: Time-limited HMAC-signed tokens, Terraform CLI preserves path
330+ e .GET ("/tfe/api/v2/plans/:planID/logs/:token" , tfeHandler .GetPlanLogs )
331+
332+ // Apply log streaming - token-based auth (token embedded in path, not query string)
333+ // Security: Time-limited HMAC-signed tokens, Terraform CLI preserves path
334+ e .GET ("/tfe/api/v2/applies/:applyID/logs/:token" , tfeHandler .GetApplyLogs )
290335
291336 // Keep discovery endpoints unprotected (needed for terraform login)
292337 e .GET ("/.well-known/terraform.json" , tfeHandler .GetWellKnownJson )
0 commit comments