@resolveio/server-lib 20.14.19 → 20.14.22

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.
@@ -136,6 +136,7 @@ var AI_ASSISTANT_SYSTEM_PROMPT = [
136
136
  '- Do not modify files, run destructive commands, or access databases directly.',
137
137
  '- Read-only Mongo access is allowed only via the MONGO_READ directive (see below).',
138
138
  '- Do not access secrets, credentials, or user data.',
139
+ '- If the user has a customer portal scope (other.id_customer), only discuss that customer\'s data and what is visible in their customer portal. Never reference other customers or internal/admin-only data. If asked for anything outside the portal, say it isn\'t available.',
139
140
  '- Do not assist with hacking, bypassing security, or abuse.',
140
141
  '- Prefer high-level explanations and point to routes instead of code. Only mention file paths if explicitly requested.',
141
142
  '- When asked where to do something, give the exact screen name and the in-app route as a standalone path starting with "/" so it can be clicked.',
@@ -684,10 +685,10 @@ function executeAiFormPatch(payload, context) {
684
685
  }
685
686
  function executeAiAssistantCodexRun(payload, context) {
686
687
  return __awaiter(this, void 0, void 0, function () {
687
- var input, message, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, prompt, workspaceRoot, codexConfig, runOptions, responseText, assistantContent, userDoc, assistantDoc, insertResult;
688
- var _b;
689
- return __generator(this, function (_c) {
690
- switch (_c.label) {
688
+ var input, message, guardrail, conversation_2, now_2, userMsg, assistantMsg, user, isSuperAdmin, hasInvoiceAccess, customerId, conversation, now, attachments, attachmentData, historyLimit, history, _a, historyLines, prompt, workspaceRoot, codexConfig, runOptions, responseText, assistantContent, userDoc, assistantDoc, insertResult;
689
+ var _b, _c;
690
+ return __generator(this, function (_d) {
691
+ switch (_d.label) {
691
692
  case 0:
692
693
  input = payload || {};
693
694
  message = normalizeOptionalString(input.message);
@@ -701,7 +702,7 @@ function executeAiAssistantCodexRun(payload, context) {
701
702
  if (!(guardrail === null || guardrail === void 0 ? void 0 : guardrail.blocked)) return [3 /*break*/, 5];
702
703
  return [4 /*yield*/, ensureConversation(input, 'codex')];
703
704
  case 1:
704
- conversation_2 = _c.sent();
705
+ conversation_2 = _d.sent();
705
706
  now_2 = new Date();
706
707
  userMsg = {
707
708
  id_conversation: conversation_2._id,
@@ -723,13 +724,13 @@ function executeAiAssistantCodexRun(payload, context) {
723
724
  };
724
725
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userMsg)];
725
726
  case 2:
726
- _c.sent();
727
+ _d.sent();
727
728
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantMsg)];
728
729
  case 3:
729
- _c.sent();
730
+ _d.sent();
730
731
  return [4 /*yield*/, touchConversation(conversation_2._id, now_2)];
731
732
  case 4:
732
- _c.sent();
733
+ _d.sent();
733
734
  return [2 /*return*/, {
734
735
  conversation: conversation_2,
735
736
  message: assistantMsg,
@@ -737,26 +738,27 @@ function executeAiAssistantCodexRun(payload, context) {
737
738
  }];
738
739
  case 5: return [4 /*yield*/, user_collection_1.Users.findById(context === null || context === void 0 ? void 0 : context.id_user)];
739
740
  case 6:
740
- user = _c.sent();
741
+ user = _d.sent();
741
742
  isSuperAdmin = !!((_b = user === null || user === void 0 ? void 0 : user.roles) === null || _b === void 0 ? void 0 : _b.super_admin);
742
743
  hasInvoiceAccess = userHasInvoiceAccess(user);
744
+ customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
743
745
  return [4 /*yield*/, ensureConversation(input, 'codex')];
744
746
  case 7:
745
- conversation = _c.sent();
747
+ conversation = _d.sent();
746
748
  now = new Date();
747
749
  attachments = Array.isArray(input.attachments) ? input.attachments : [];
748
750
  return [4 /*yield*/, readAttachmentContents(attachments)];
749
751
  case 8:
750
- attachmentData = _c.sent();
752
+ attachmentData = _d.sent();
751
753
  historyLimit = normalizeHistoryLimit(input.max_history);
752
754
  if (!(historyLimit > 0)) return [3 /*break*/, 10];
753
755
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.find({ id_conversation: conversation._id, role: { $in: ['user', 'assistant'] } }, { sort: { createdAt: 1 }, limit: historyLimit * 2 })];
754
756
  case 9:
755
- _a = _c.sent();
757
+ _a = _d.sent();
756
758
  return [3 /*break*/, 11];
757
759
  case 10:
758
760
  _a = [];
759
- _c.label = 11;
761
+ _d.label = 11;
760
762
  case 11:
761
763
  history = _a;
762
764
  historyLines = [];
@@ -767,10 +769,10 @@ function executeAiAssistantCodexRun(payload, context) {
767
769
  historyLines.push("".concat(role, ": ").concat(content));
768
770
  }
769
771
  });
770
- prompt = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), buildAssistantContext(input, { isSuperAdmin: isSuperAdmin, hasInvoiceAccess: hasInvoiceAccess }));
772
+ prompt = buildAssistantCodexPrompt(message, attachmentData.promptText, historyLines.join('\n'), buildAssistantContext(input, { isSuperAdmin: isSuperAdmin, hasInvoiceAccess: hasInvoiceAccess, customerId: customerId }));
771
773
  return [4 /*yield*/, resolveAssistantWorkspaceRoot()];
772
774
  case 12:
773
- workspaceRoot = _c.sent();
775
+ workspaceRoot = _d.sent();
774
776
  codexConfig = resolveCodexSettings();
775
777
  runOptions = {
776
778
  timeoutMs: resolveCodexTimeoutMs(),
@@ -787,7 +789,7 @@ function executeAiAssistantCodexRun(payload, context) {
787
789
  };
788
790
  return [4 /*yield*/, runCodexInWorkerThread(prompt, runOptions, codexConfig)];
789
791
  case 13:
790
- responseText = _c.sent();
792
+ responseText = _d.sent();
791
793
  assistantContent = sanitizeAssistantResponse(responseText);
792
794
  userDoc = {
793
795
  id_conversation: conversation._id,
@@ -809,18 +811,18 @@ function executeAiAssistantCodexRun(payload, context) {
809
811
  };
810
812
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(userDoc)];
811
813
  case 14:
812
- _c.sent();
814
+ _d.sent();
813
815
  return [4 /*yield*/, ai_terminal_message_collection_1.AiTerminalMessages.insertOne(assistantDoc)];
814
816
  case 15:
815
- insertResult = _c.sent();
817
+ insertResult = _d.sent();
816
818
  return [4 /*yield*/, touchConversation(conversation._id, now, insertResult._id)];
817
819
  case 16:
818
- _c.sent();
820
+ _d.sent();
819
821
  if (!(input.delete_files_after_run !== false)) return [3 /*break*/, 18];
820
822
  return [4 /*yield*/, cleanupAttachments(attachmentData.attachments)];
821
823
  case 17:
822
- _c.sent();
823
- _c.label = 18;
824
+ _d.sent();
825
+ _d.label = 18;
824
826
  case 18: return [2 /*return*/, {
825
827
  conversation: conversation,
826
828
  message: assistantDoc
@@ -831,9 +833,10 @@ function executeAiAssistantCodexRun(payload, context) {
831
833
  }
832
834
  function executeAiAssistantMongoRead(payload, context) {
833
835
  return __awaiter(this, void 0, void 0, function () {
834
- var input, collection, _a, user, isSuperAdmin, dbName, db, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, scopedQuery, normalized, documents, total, sanitizedDocuments;
835
- return __generator(this, function (_c) {
836
- switch (_c.label) {
836
+ var input, collection, _a, user, isSuperAdmin, customerId, dbName, db, baseQuery, userId, normalizedClient, shouldScopeByClient, _b, clientScopedQuery, scopedQuery, normalized, documents, total, sanitizedDocuments;
837
+ var _c;
838
+ return __generator(this, function (_d) {
839
+ switch (_d.label) {
837
840
  case 0:
838
841
  input = payload || {};
839
842
  collection = normalizeOptionalString(input.collection);
@@ -842,10 +845,11 @@ function executeAiAssistantMongoRead(payload, context) {
842
845
  }
843
846
  return [4 /*yield*/, ensureAssistantReadAccess(context, input.permissionView, collection)];
844
847
  case 1:
845
- _a = _c.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
848
+ _a = _d.sent(), user = _a.user, isSuperAdmin = _a.isSuperAdmin;
846
849
  if (!isSuperAdmin && AI_ASSISTANT_BLOCKED_COLLECTIONS.has(collection)) {
847
850
  throw new Error('AI assistant mongo read: Access denied.');
848
851
  }
852
+ customerId = normalizeOptionalString((_c = user === null || user === void 0 ? void 0 : user.other) === null || _c === void 0 ? void 0 : _c.id_customer);
849
853
  dbName = resolveAssistantDatabaseName(input.database, input.mongo);
850
854
  db = resolveio_server_app_1.ResolveIOServer.getMongoConnection().db(dbName);
851
855
  baseQuery = normalizeMongoQuery(input.query);
@@ -862,26 +866,27 @@ function executeAiAssistantMongoRead(payload, context) {
862
866
  if (!(!isSuperAdmin && normalizedClient)) return [3 /*break*/, 3];
863
867
  return [4 /*yield*/, collectionHasClientIndex(db, dbName, collection)];
864
868
  case 2:
865
- _b = _c.sent();
869
+ _b = _d.sent();
866
870
  return [3 /*break*/, 4];
867
871
  case 3:
868
872
  _b = false;
869
- _c.label = 4;
873
+ _d.label = 4;
870
874
  case 4:
871
875
  shouldScopeByClient = _b;
872
- scopedQuery = shouldScopeByClient
876
+ clientScopedQuery = shouldScopeByClient
873
877
  ? applyClientScopeFilter(baseQuery, normalizedClient, isSuperAdmin)
874
878
  : baseQuery;
879
+ scopedQuery = applyCustomerScopeFilter(clientScopedQuery, collection, customerId, isSuperAdmin);
875
880
  normalized = normalizeAssistantFindOptions(input.options);
876
881
  return [4 /*yield*/, db.collection(collection).find(scopedQuery, normalized.findOptions).toArray()];
877
882
  case 5:
878
- documents = _c.sent();
883
+ documents = _d.sent();
879
884
  total = null;
880
885
  if (!normalized.includeTotal) return [3 /*break*/, 7];
881
886
  return [4 /*yield*/, db.collection(collection).countDocuments(scopedQuery)];
882
887
  case 6:
883
- total = _c.sent();
884
- _c.label = 7;
888
+ total = _d.sent();
889
+ _d.label = 7;
885
890
  case 7:
886
891
  sanitizedDocuments = isSuperAdmin
887
892
  ? documents
@@ -1057,6 +1062,24 @@ function applyClientScopeFilter(query, idClient, isSuperAdmin) {
1057
1062
  $and: [query, { id_client: normalizedClient }]
1058
1063
  };
1059
1064
  }
1065
+ function applyCustomerScopeFilter(query, collection, idCustomer, isSuperAdmin) {
1066
+ var _a;
1067
+ if (isSuperAdmin === void 0) { isSuperAdmin = false; }
1068
+ if (isSuperAdmin) {
1069
+ return query;
1070
+ }
1071
+ var normalizedCustomer = normalizeOptionalString(idCustomer);
1072
+ if (!normalizedCustomer) {
1073
+ return query;
1074
+ }
1075
+ var normalizedCollection = normalizeOptionalString(collection).toLowerCase();
1076
+ var customerField = normalizedCollection === 'users' || normalizedCollection === 'user-versions'
1077
+ ? 'other.id_customer'
1078
+ : 'id_customer';
1079
+ return {
1080
+ $and: [query, (_a = {}, _a[customerField] = normalizedCustomer, _a)]
1081
+ };
1082
+ }
1060
1083
  function userHasViewPermission(user, view) {
1061
1084
  var _a, _b, _c;
1062
1085
  if (!user || !view) {
@@ -1446,6 +1469,11 @@ function buildAssistantContext(input, userContext) {
1446
1469
  if (typeof (userContext === null || userContext === void 0 ? void 0 : userContext.hasInvoiceAccess) === 'boolean') {
1447
1470
  lines.push("User has invoice access: ".concat(userContext.hasInvoiceAccess ? 'yes' : 'no'));
1448
1471
  }
1472
+ var customerId = normalizeOptionalString(userContext === null || userContext === void 0 ? void 0 : userContext.customerId);
1473
+ if (customerId) {
1474
+ lines.push('Customer portal scope: yes');
1475
+ lines.push("Customer id: ".concat(customerId));
1476
+ }
1449
1477
  var contextMode = normalizeOptionalString((_a = input === null || input === void 0 ? void 0 : input.context) === null || _a === void 0 ? void 0 : _a.mode);
1450
1478
  var contextRoute = normalizeOptionalString((_b = input === null || input === void 0 ? void 0 : input.context) === null || _b === void 0 ? void 0 : _b.route);
1451
1479
  if (contextMode) {