@bpinhosilva/agent-orchestrator 1.0.0-alpha.30 → 1.0.0-alpha.31

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,10 @@
1
+ # [1.0.0-alpha.31](https://github.com/bpinhosilva/agent-orchestrator/compare/v1.0.0-alpha.30...v1.0.0-alpha.31) (2026-04-06)
2
+
3
+
4
+ ### Features
5
+
6
+ * add environment variable setup and JWT refresh secret handling ([c9dfd05](https://github.com/bpinhosilva/agent-orchestrator/commit/c9dfd05070dfc4bc0e34e3853d0efe85d84d404a))
7
+
1
8
  # [1.0.0-alpha.30](https://github.com/bpinhosilva/agent-orchestrator/compare/v1.0.0-alpha.29...v1.0.0-alpha.30) (2026-04-05)
2
9
 
3
10
 
@@ -93,6 +93,7 @@ __decorate([
93
93
  __metadata("design:returntype", void 0)
94
94
  ], AgentsController.prototype, "remove", null);
95
95
  __decorate([
96
+ (0, roles_decorator_1.Roles)(user_entity_1.UserRole.ADMIN),
96
97
  (0, common_1.Post)('process'),
97
98
  (0, common_1.HttpCode)(common_1.HttpStatus.OK),
98
99
  openapi.ApiResponse({ status: common_1.HttpStatus.OK, type: Object }),
@@ -102,6 +103,7 @@ __decorate([
102
103
  __metadata("design:returntype", Promise)
103
104
  ], AgentsController.prototype, "processText", null);
104
105
  __decorate([
106
+ (0, roles_decorator_1.Roles)(user_entity_1.UserRole.ADMIN),
105
107
  (0, common_1.Post)('probe'),
106
108
  (0, common_1.HttpCode)(common_1.HttpStatus.OK),
107
109
  openapi.ApiResponse({ status: common_1.HttpStatus.OK, type: Object }),
@@ -97,7 +97,7 @@ let AuthService = class AuthService {
97
97
  };
98
98
  const token = this.jwtService.sign(payload, {
99
99
  expiresIn: this.refreshTokenExpiresIn,
100
- secret: this.configService.get('JWT_SECRET'),
100
+ secret: this.configService.get('JWT_REFRESH_SECRET'),
101
101
  algorithm: 'HS256',
102
102
  });
103
103
  const hashedToken = await bcrypt.hash(token, 10);
@@ -114,7 +114,7 @@ let AuthService = class AuthService {
114
114
  async validateRefreshToken(token) {
115
115
  try {
116
116
  const payload = this.jwtService.verify(token, {
117
- secret: this.configService.get('JWT_SECRET'),
117
+ secret: this.configService.get('JWT_REFRESH_SECRET'),
118
118
  algorithms: ['HS256'],
119
119
  });
120
120
  if (payload.type !== 'refresh') {
@@ -244,7 +244,7 @@ let AuthService = class AuthService {
244
244
  async revokeRefreshToken(token) {
245
245
  try {
246
246
  const payload = this.jwtService.verify(token, {
247
- secret: this.configService.get('JWT_SECRET'),
247
+ secret: this.configService.get('JWT_REFRESH_SECRET'),
248
248
  algorithms: ['HS256'],
249
249
  });
250
250
  if (payload.sub) {
@@ -11,6 +11,7 @@ export declare class JwtStrategy extends JwtStrategy_base {
11
11
  validate(payload: {
12
12
  email: string;
13
13
  sub: string;
14
+ type?: string;
14
15
  }): Promise<import("../../users/avatar.constants").SerializedUser>;
15
16
  }
16
17
  export {};
@@ -37,6 +37,9 @@ let JwtStrategy = class JwtStrategy extends (0, passport_1.PassportStrategy)(pas
37
37
  this.authService = authService;
38
38
  }
39
39
  async validate(payload) {
40
+ if (payload.type === 'refresh') {
41
+ throw new common_1.UnauthorizedException('Invalid token type');
42
+ }
40
43
  const user = await this.authService.validateUser(payload.sub);
41
44
  if (!user) {
42
45
  throw new common_1.UnauthorizedException();
package/dist/cli/index.js CHANGED
@@ -466,7 +466,7 @@ async function resolveProviderKey(provider, providedKey, interactive) {
466
466
  ]);
467
467
  return keyResponse.key;
468
468
  }
469
- function buildEnvContent(currentEnv, basicConfig, databaseUrl, geminiKey, anthropicKey, jwtSecret) {
469
+ function buildEnvContent(currentEnv, basicConfig, databaseUrl, geminiKey, anthropicKey, jwtSecret, jwtRefreshSecret) {
470
470
  const envValues = {
471
471
  ...currentEnv,
472
472
  NODE_ENV: 'production',
@@ -475,6 +475,7 @@ function buildEnvContent(currentEnv, basicConfig, databaseUrl, geminiKey, anthro
475
475
  DB_LOGGING: `${basicConfig.dbLogging}`,
476
476
  CHECK_PENDING_MIGRATIONS_ON_STARTUP: currentEnv.CHECK_PENDING_MIGRATIONS_ON_STARTUP || 'true',
477
477
  JWT_SECRET: jwtSecret,
478
+ JWT_REFRESH_SECRET: jwtRefreshSecret,
478
479
  };
479
480
  if (databaseUrl) {
480
481
  envValues.DATABASE_URL = databaseUrl;
@@ -615,8 +616,11 @@ async function handleSetup(options) {
615
616
  const jwtSecret = options.regenerateJwtSecret || !currentEnv.JWT_SECRET
616
617
  ? crypto.randomBytes(32).toString('hex')
617
618
  : currentEnv.JWT_SECRET;
619
+ const jwtRefreshSecret = options.regenerateJwtSecret || !currentEnv.JWT_REFRESH_SECRET
620
+ ? crypto.randomBytes(32).toString('hex')
621
+ : currentEnv.JWT_REFRESH_SECRET;
618
622
  console.log('Generating configuration...');
619
- const envContent = buildEnvContent(currentEnv, basicConfig, databaseUrl, geminiKey, anthropicKey, jwtSecret);
623
+ const envContent = buildEnvContent(currentEnv, basicConfig, databaseUrl, geminiKey, anthropicKey, jwtSecret, jwtRefreshSecret);
620
624
  writePrivateFile(exports.ENV_PATH, envContent);
621
625
  console.log(`Configuration saved to ${exports.ENV_PATH} with mode 600.`);
622
626
  const { hasPending, isEmpty } = await (0, migration_state_1.checkPendingMigrations)({
@@ -40,6 +40,7 @@ exports.envValidationSchema = Joi.object({
40
40
  DATABASE_URL: Joi.string().optional(),
41
41
  DB_TYPE: Joi.string().valid('postgres', 'sqlite').optional(),
42
42
  JWT_SECRET: Joi.string().min(32).required(),
43
+ JWT_REFRESH_SECRET: Joi.string().min(32).required(),
43
44
  GEMINI_API_KEY: Joi.string().optional(),
44
45
  ANTHROPIC_API_KEY: Joi.string().optional(),
45
46
  DB_LOGGING: Joi.boolean().default(false),
@@ -1,12 +1,18 @@
1
1
  import { CommentsService } from './comments.service';
2
2
  import { CreateCommentDto } from './dto/create-comment.dto';
3
3
  import { UpdateCommentDto } from './dto/update-comment.dto';
4
+ import { User } from '../users/entities/user.entity';
5
+ import { ProjectsService } from '../projects/projects.service';
6
+ import { TasksService } from './tasks.service';
4
7
  export declare class CommentsController {
5
8
  private readonly commentsService;
6
- constructor(commentsService: CommentsService);
7
- create(taskId: string, createCommentDto: CreateCommentDto): Promise<import("./entities/comment.entity").TaskComment | null>;
8
- findAll(taskId: string): Promise<import("./entities/comment.entity").TaskComment[]>;
9
- findOne(taskId: string, id: string): Promise<import("./entities/comment.entity").TaskComment>;
10
- remove(taskId: string, id: string): Promise<void>;
11
- update(taskId: string, id: string, updateCommentDto: UpdateCommentDto): Promise<import("./entities/comment.entity").TaskComment>;
9
+ private readonly projectsService;
10
+ private readonly tasksService;
11
+ constructor(commentsService: CommentsService, projectsService: ProjectsService, tasksService: TasksService);
12
+ private verifyTaskAccess;
13
+ create(taskId: string, createCommentDto: CreateCommentDto, user: User): Promise<import("./entities/comment.entity").TaskComment | null>;
14
+ findAll(taskId: string, user: User): Promise<import("./entities/comment.entity").TaskComment[]>;
15
+ findOne(taskId: string, id: string, user: User): Promise<import("./entities/comment.entity").TaskComment>;
16
+ remove(taskId: string, id: string, user: User): Promise<void>;
17
+ update(taskId: string, id: string, updateCommentDto: UpdateCommentDto, user: User): Promise<import("./entities/comment.entity").TaskComment>;
12
18
  }
@@ -18,24 +18,41 @@ const common_1 = require("@nestjs/common");
18
18
  const comments_service_1 = require("./comments.service");
19
19
  const create_comment_dto_1 = require("./dto/create-comment.dto");
20
20
  const update_comment_dto_1 = require("./dto/update-comment.dto");
21
+ const current_user_decorator_1 = require("../auth/decorators/current-user.decorator");
22
+ const user_entity_1 = require("../users/entities/user.entity");
23
+ const projects_service_1 = require("../projects/projects.service");
24
+ const tasks_service_1 = require("./tasks.service");
21
25
  let CommentsController = class CommentsController {
22
26
  commentsService;
23
- constructor(commentsService) {
27
+ projectsService;
28
+ tasksService;
29
+ constructor(commentsService, projectsService, tasksService) {
24
30
  this.commentsService = commentsService;
31
+ this.projectsService = projectsService;
32
+ this.tasksService = tasksService;
25
33
  }
26
- create(taskId, createCommentDto) {
34
+ async verifyTaskAccess(taskId, user) {
35
+ const task = await this.tasksService.findOne(taskId);
36
+ await this.projectsService.findOne(task.project?.id || task.projectId, user);
37
+ }
38
+ async create(taskId, createCommentDto, user) {
39
+ await this.verifyTaskAccess(taskId, user);
27
40
  return this.commentsService.create(taskId, createCommentDto);
28
41
  }
29
- findAll(taskId) {
42
+ async findAll(taskId, user) {
43
+ await this.verifyTaskAccess(taskId, user);
30
44
  return this.commentsService.findAllByTask(taskId);
31
45
  }
32
- findOne(taskId, id) {
46
+ async findOne(taskId, id, user) {
47
+ await this.verifyTaskAccess(taskId, user);
33
48
  return this.commentsService.findOne(id, taskId);
34
49
  }
35
- remove(taskId, id) {
50
+ async remove(taskId, id, user) {
51
+ await this.verifyTaskAccess(taskId, user);
36
52
  return this.commentsService.remove(id, taskId);
37
53
  }
38
- update(taskId, id, updateCommentDto) {
54
+ async update(taskId, id, updateCommentDto, user) {
55
+ await this.verifyTaskAccess(taskId, user);
39
56
  return this.commentsService.update(id, updateCommentDto, taskId);
40
57
  }
41
58
  };
@@ -45,35 +62,40 @@ __decorate([
45
62
  openapi.ApiResponse({ status: 201, type: Object }),
46
63
  __param(0, (0, common_1.Param)('taskId')),
47
64
  __param(1, (0, common_1.Body)()),
65
+ __param(2, (0, current_user_decorator_1.CurrentUser)()),
48
66
  __metadata("design:type", Function),
49
- __metadata("design:paramtypes", [String, create_comment_dto_1.CreateCommentDto]),
50
- __metadata("design:returntype", void 0)
67
+ __metadata("design:paramtypes", [String, create_comment_dto_1.CreateCommentDto,
68
+ user_entity_1.User]),
69
+ __metadata("design:returntype", Promise)
51
70
  ], CommentsController.prototype, "create", null);
52
71
  __decorate([
53
72
  (0, common_1.Get)(),
54
73
  openapi.ApiResponse({ status: 200, type: [require("./entities/comment.entity").TaskComment] }),
55
74
  __param(0, (0, common_1.Param)('taskId')),
75
+ __param(1, (0, current_user_decorator_1.CurrentUser)()),
56
76
  __metadata("design:type", Function),
57
- __metadata("design:paramtypes", [String]),
58
- __metadata("design:returntype", void 0)
77
+ __metadata("design:paramtypes", [String, user_entity_1.User]),
78
+ __metadata("design:returntype", Promise)
59
79
  ], CommentsController.prototype, "findAll", null);
60
80
  __decorate([
61
81
  (0, common_1.Get)(':id'),
62
82
  openapi.ApiResponse({ status: 200, type: require("./entities/comment.entity").TaskComment }),
63
83
  __param(0, (0, common_1.Param)('taskId')),
64
84
  __param(1, (0, common_1.Param)('id')),
85
+ __param(2, (0, current_user_decorator_1.CurrentUser)()),
65
86
  __metadata("design:type", Function),
66
- __metadata("design:paramtypes", [String, String]),
67
- __metadata("design:returntype", void 0)
87
+ __metadata("design:paramtypes", [String, String, user_entity_1.User]),
88
+ __metadata("design:returntype", Promise)
68
89
  ], CommentsController.prototype, "findOne", null);
69
90
  __decorate([
70
91
  (0, common_1.Delete)(':id'),
71
92
  openapi.ApiResponse({ status: 200 }),
72
93
  __param(0, (0, common_1.Param)('taskId')),
73
94
  __param(1, (0, common_1.Param)('id')),
95
+ __param(2, (0, current_user_decorator_1.CurrentUser)()),
74
96
  __metadata("design:type", Function),
75
- __metadata("design:paramtypes", [String, String]),
76
- __metadata("design:returntype", void 0)
97
+ __metadata("design:paramtypes", [String, String, user_entity_1.User]),
98
+ __metadata("design:returntype", Promise)
77
99
  ], CommentsController.prototype, "remove", null);
78
100
  __decorate([
79
101
  (0, common_1.Patch)(':id'),
@@ -81,11 +103,15 @@ __decorate([
81
103
  __param(0, (0, common_1.Param)('taskId')),
82
104
  __param(1, (0, common_1.Param)('id')),
83
105
  __param(2, (0, common_1.Body)()),
106
+ __param(3, (0, current_user_decorator_1.CurrentUser)()),
84
107
  __metadata("design:type", Function),
85
- __metadata("design:paramtypes", [String, String, update_comment_dto_1.UpdateCommentDto]),
86
- __metadata("design:returntype", void 0)
108
+ __metadata("design:paramtypes", [String, String, update_comment_dto_1.UpdateCommentDto,
109
+ user_entity_1.User]),
110
+ __metadata("design:returntype", Promise)
87
111
  ], CommentsController.prototype, "update", null);
88
112
  exports.CommentsController = CommentsController = __decorate([
89
113
  (0, common_1.Controller)('tasks/:taskId/comments'),
90
- __metadata("design:paramtypes", [comments_service_1.CommentsService])
114
+ __metadata("design:paramtypes", [comments_service_1.CommentsService,
115
+ projects_service_1.ProjectsService,
116
+ tasks_service_1.TasksService])
91
117
  ], CommentsController);
@@ -1,43 +1,10 @@
1
1
  "use strict";
2
- var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
- if (k2 === undefined) k2 = k;
4
- var desc = Object.getOwnPropertyDescriptor(m, k);
5
- if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
- desc = { enumerable: true, get: function() { return m[k]; } };
7
- }
8
- Object.defineProperty(o, k2, desc);
9
- }) : (function(o, m, k, k2) {
10
- if (k2 === undefined) k2 = k;
11
- o[k2] = m[k];
12
- }));
13
- var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
- Object.defineProperty(o, "default", { enumerable: true, value: v });
15
- }) : function(o, v) {
16
- o["default"] = v;
17
- });
18
2
  var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
19
3
  var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
20
4
  if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
21
5
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
22
6
  return c > 3 && r && Object.defineProperty(target, key, r), r;
23
7
  };
24
- var __importStar = (this && this.__importStar) || (function () {
25
- var ownKeys = function(o) {
26
- ownKeys = Object.getOwnPropertyNames || function (o) {
27
- var ar = [];
28
- for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
29
- return ar;
30
- };
31
- return ownKeys(o);
32
- };
33
- return function (mod) {
34
- if (mod && mod.__esModule) return mod;
35
- var result = {};
36
- if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
37
- __setModuleDefault(result, mod);
38
- return result;
39
- };
40
- })();
41
8
  var __metadata = (this && this.__metadata) || function (k, v) {
42
9
  if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
43
10
  };
@@ -48,7 +15,6 @@ var CommentsService_1;
48
15
  Object.defineProperty(exports, "__esModule", { value: true });
49
16
  exports.CommentsService = void 0;
50
17
  const common_1 = require("@nestjs/common");
51
- const crypto = __importStar(require("crypto"));
52
18
  const typeorm_1 = require("@nestjs/typeorm");
53
19
  const typeorm_2 = require("typeorm");
54
20
  const comment_entity_1 = require("./entities/comment.entity");
@@ -109,10 +75,6 @@ let CommentsService = CommentsService_1 = class CommentsService {
109
75
  authorType,
110
76
  authorUser,
111
77
  authorAgent,
112
- artifacts: createCommentDto.artifacts?.map((artifact) => ({
113
- id: artifact.id || crypto.randomUUID(),
114
- ...artifact,
115
- })) || null,
116
78
  });
117
79
  const savedComment = await manager.save(comment);
118
80
  return manager.findOne(comment_entity_1.TaskComment, {
@@ -183,13 +145,6 @@ let CommentsService = CommentsService_1 = class CommentsService {
183
145
  if (updateCommentDto.content !== undefined) {
184
146
  comment.content = updateCommentDto.content;
185
147
  }
186
- if (updateCommentDto.artifacts !== undefined) {
187
- comment.artifacts =
188
- updateCommentDto.artifacts?.map((artifact) => ({
189
- id: artifact.id || crypto.randomUUID(),
190
- ...artifact,
191
- })) || null;
192
- }
193
148
  return manager.save(comment);
194
149
  });
195
150
  }
@@ -4,10 +4,4 @@ export declare class CreateCommentDto {
4
4
  authorType?: CommentAuthorType;
5
5
  authorUserId?: string;
6
6
  authorAgentId?: string;
7
- artifacts?: {
8
- id?: string;
9
- originalName: string;
10
- mimeType: string;
11
- filePath: string;
12
- }[];
13
7
  }
@@ -18,9 +18,8 @@ class CreateCommentDto {
18
18
  authorType;
19
19
  authorUserId;
20
20
  authorAgentId;
21
- artifacts;
22
21
  static _OPENAPI_METADATA_FACTORY() {
23
- return { content: { required: true, type: () => String, maxLength: 10000 }, authorType: { required: false, enum: require("../entities/comment.entity").CommentAuthorType }, authorUserId: { required: false, type: () => String, format: "uuid" }, authorAgentId: { required: false, type: () => String, format: "uuid" }, artifacts: { required: false, type: () => [({ id: { required: false, type: () => String }, originalName: { required: true, type: () => String }, mimeType: { required: true, type: () => String }, filePath: { required: true, type: () => String } })] } };
22
+ return { content: { required: true, type: () => String, maxLength: 10000 }, authorType: { required: false, enum: require("../entities/comment.entity").CommentAuthorType }, authorUserId: { required: false, type: () => String, format: "uuid" }, authorAgentId: { required: false, type: () => String, format: "uuid" } };
24
23
  }
25
24
  }
26
25
  exports.CreateCommentDto = CreateCommentDto;
@@ -45,7 +44,3 @@ __decorate([
45
44
  (0, class_validator_1.IsOptional)(),
46
45
  __metadata("design:type", String)
47
46
  ], CreateCommentDto.prototype, "authorAgentId", void 0);
48
- __decorate([
49
- (0, class_validator_1.IsOptional)(),
50
- __metadata("design:type", Array)
51
- ], CreateCommentDto.prototype, "artifacts", void 0);
@@ -1,9 +1,3 @@
1
1
  export declare class UpdateCommentDto {
2
2
  content?: string;
3
- artifacts?: {
4
- id?: string;
5
- originalName: string;
6
- mimeType: string;
7
- filePath: string;
8
- }[];
9
3
  }
@@ -14,9 +14,8 @@ const openapi = require("@nestjs/swagger");
14
14
  const class_validator_1 = require("class-validator");
15
15
  class UpdateCommentDto {
16
16
  content;
17
- artifacts;
18
17
  static _OPENAPI_METADATA_FACTORY() {
19
- return { content: { required: false, type: () => String }, artifacts: { required: false, type: () => [({ id: { required: false, type: () => String }, originalName: { required: true, type: () => String }, mimeType: { required: true, type: () => String }, filePath: { required: true, type: () => String } })] } };
18
+ return { content: { required: false, type: () => String } };
20
19
  }
21
20
  }
22
21
  exports.UpdateCommentDto = UpdateCommentDto;
@@ -25,7 +24,3 @@ __decorate([
25
24
  (0, class_validator_1.IsOptional)(),
26
25
  __metadata("design:type", String)
27
26
  ], UpdateCommentDto.prototype, "content", void 0);
28
- __decorate([
29
- (0, class_validator_1.IsOptional)(),
30
- __metadata("design:type", Array)
31
- ], UpdateCommentDto.prototype, "artifacts", void 0);
@@ -134,7 +134,7 @@ let RecurrentTaskSchedulerService = RecurrentTaskSchedulerService_1 = class Recu
134
134
  });
135
135
  try {
136
136
  this.logger.debug(`Agent ${task.assignee.name} performing recurrent task ${task.title}`);
137
- const response = await this.agentsService.probe(task.assignee.id, `Recurrent Task: ${task.title}. Description: ${task.description}`);
137
+ const response = await this.agentsService.probe(task.assignee.id, `### Recurrent Task Execution\n\n[CONTEXT]\nTitle: ${task.title}\nDescription: ${task.description}\n[/CONTEXT]\n\nPlease perform the task described above.`);
138
138
  const latencyMs = Date.now() - this.runningTasks.get(taskId).startTime;
139
139
  await this.execRepository.update(savedExec.id, {
140
140
  status: recurrent_task_exec_entity_1.ExecStatus.SUCCESS,
@@ -52,5 +52,6 @@ exports.TasksModule = TasksModule = __decorate([
52
52
  recurrent_tasks_service_1.RecurrentTasksService,
53
53
  recurrent_task_scheduler_service_1.RecurrentTaskSchedulerService,
54
54
  ],
55
+ exports: [tasks_service_1.TasksService],
55
56
  })
56
57
  ], TasksModule);
@@ -1,8 +1,13 @@
1
1
  import { StreamableFile } from '@nestjs/common';
2
2
  import type { Response } from 'express';
3
3
  import { StorageService } from '../common/storage.service';
4
+ import { User } from '../users/entities/user.entity';
5
+ import { ProjectsService } from '../projects/projects.service';
6
+ import { TasksService } from '../tasks/tasks.service';
4
7
  export declare class UploadsController {
5
8
  private readonly storageService;
6
- constructor(storageService: StorageService);
7
- getFile(rawPath: string, res: Response): StreamableFile;
9
+ private readonly projectsService;
10
+ private readonly tasksService;
11
+ constructor(storageService: StorageService, projectsService: ProjectsService, tasksService: TasksService);
12
+ getFile(rawPath: string, res: Response, user: User): Promise<StreamableFile>;
8
13
  }
@@ -52,18 +52,46 @@ const storage_service_1 = require("../common/storage.service");
52
52
  const parse_filepath_pipe_1 = require("./parse-filepath.pipe");
53
53
  const fs = __importStar(require("fs"));
54
54
  const path = __importStar(require("path"));
55
+ const current_user_decorator_1 = require("../auth/decorators/current-user.decorator");
56
+ const user_entity_1 = require("../users/entities/user.entity");
57
+ const projects_service_1 = require("../projects/projects.service");
58
+ const tasks_service_1 = require("../tasks/tasks.service");
55
59
  let UploadsController = class UploadsController {
56
60
  storageService;
57
- constructor(storageService) {
61
+ projectsService;
62
+ tasksService;
63
+ constructor(storageService, projectsService, tasksService) {
58
64
  this.storageService = storageService;
65
+ this.projectsService = projectsService;
66
+ this.tasksService = tasksService;
59
67
  }
60
- getFile(rawPath, res) {
68
+ async getFile(rawPath, res, user) {
61
69
  const bucketPath = this.storageService.getBucketPath('artifacts');
62
70
  const resolvedBucketPath = path.resolve(bucketPath);
63
71
  const nominalPath = path.resolve(bucketPath, rawPath);
64
72
  if (!nominalPath.startsWith(resolvedBucketPath + path.sep)) {
65
73
  throw new common_1.NotFoundException(`File not found`);
66
74
  }
75
+ const segments = rawPath.split(/[/\\]/);
76
+ if (user.role !== user_entity_1.UserRole.ADMIN && segments.length >= 5) {
77
+ const context = segments[3];
78
+ const contextId = segments[4];
79
+ if (context === 'tasks') {
80
+ try {
81
+ const task = await this.tasksService.findOne(contextId);
82
+ const projectId = task.project?.id || task.projectId;
83
+ if (projectId) {
84
+ await this.projectsService.findOne(projectId, user);
85
+ }
86
+ }
87
+ catch (error) {
88
+ if (error instanceof common_1.NotFoundException) {
89
+ throw new common_1.NotFoundException(`File not found`);
90
+ }
91
+ throw new common_1.ForbiddenException(`Access denied to artifact`);
92
+ }
93
+ }
94
+ }
67
95
  if (!fs.existsSync(nominalPath)) {
68
96
  throw new common_1.NotFoundException(`File not found`);
69
97
  }
@@ -105,11 +133,14 @@ __decorate([
105
133
  openapi.ApiResponse({ status: 200 }),
106
134
  __param(0, (0, common_1.Param)('filepath', parse_filepath_pipe_1.ParseFilePathPipe)),
107
135
  __param(1, (0, common_1.Res)({ passthrough: true })),
136
+ __param(2, (0, current_user_decorator_1.CurrentUser)()),
108
137
  __metadata("design:type", Function),
109
- __metadata("design:paramtypes", [String, Object]),
110
- __metadata("design:returntype", common_1.StreamableFile)
138
+ __metadata("design:paramtypes", [String, Object, user_entity_1.User]),
139
+ __metadata("design:returntype", Promise)
111
140
  ], UploadsController.prototype, "getFile", null);
112
141
  exports.UploadsController = UploadsController = __decorate([
113
142
  (0, common_1.Controller)('uploads/artifacts'),
114
- __metadata("design:paramtypes", [storage_service_1.StorageService])
143
+ __metadata("design:paramtypes", [storage_service_1.StorageService,
144
+ projects_service_1.ProjectsService,
145
+ tasks_service_1.TasksService])
115
146
  ], UploadsController);
@@ -9,11 +9,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
9
9
  exports.UploadsModule = void 0;
10
10
  const common_1 = require("@nestjs/common");
11
11
  const uploads_controller_1 = require("./uploads.controller");
12
+ const projects_module_1 = require("../projects/projects.module");
13
+ const tasks_module_1 = require("../tasks/tasks.module");
12
14
  let UploadsModule = class UploadsModule {
13
15
  };
14
16
  exports.UploadsModule = UploadsModule;
15
17
  exports.UploadsModule = UploadsModule = __decorate([
16
18
  (0, common_1.Module)({
19
+ imports: [projects_module_1.ProjectsModule, (0, common_1.forwardRef)(() => tasks_module_1.TasksModule)],
17
20
  controllers: [uploads_controller_1.UploadsController],
18
21
  })
19
22
  ], UploadsModule);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bpinhosilva/agent-orchestrator",
3
- "version": "1.0.0-alpha.30",
3
+ "version": "1.0.0-alpha.31",
4
4
  "description": "An open-source AI agent orchestrator platform built with NestJS.",
5
5
  "author": "bpinhosilva",
6
6
  "license": "MIT",
@@ -36,7 +36,8 @@
36
36
  "start:dev": "nest start --watch",
37
37
  "dev:api": "nest start --watch",
38
38
  "dev:ui": "npm --prefix ui run dev",
39
- "predev": "fuser -k 3000/tcp || true",
39
+ "prestart:dev": "ts-node -r tsconfig-paths/register scripts/setup-dev-env.ts",
40
+ "predev": "ts-node -r tsconfig-paths/register scripts/setup-dev-env.ts && (fuser -k 3000/tcp || true)",
40
41
  "dev": "concurrently \"npm run dev:api\" \"wait-on tcp:127.0.0.1:3000 && npm run dev:ui\"",
41
42
  "start:debug": "nest start --debug --watch",
42
43
  "start:prod": "node dist/main",