mobbdev 1.1.10 → 1.1.12

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.
@@ -5133,7 +5133,99 @@ async function uploadFile({
5133
5133
  import { OpenRedaction } from "@openredaction/openredaction";
5134
5134
  import { spawn } from "child_process";
5135
5135
  import { installGitleaks } from "gitleaks-secret-scanner/lib/installer.js";
5136
- var openRedaction = new OpenRedaction();
5136
+ var openRedaction = new OpenRedaction({
5137
+ patterns: [
5138
+ // Core Personal Data
5139
+ "EMAIL",
5140
+ "SSN",
5141
+ "NATIONAL_INSURANCE_UK",
5142
+ "DATE_OF_BIRTH",
5143
+ // Identity Documents
5144
+ "PASSPORT_UK",
5145
+ "PASSPORT_US",
5146
+ "PASSPORT_MRZ_TD1",
5147
+ "PASSPORT_MRZ_TD3",
5148
+ "DRIVING_LICENSE_UK",
5149
+ "DRIVING_LICENSE_US",
5150
+ "VISA_NUMBER",
5151
+ "VISA_MRZ",
5152
+ "TAX_ID",
5153
+ // Financial Data
5154
+ "CREDIT_CARD",
5155
+ "IBAN",
5156
+ "BANK_ACCOUNT_UK",
5157
+ "ROUTING_NUMBER_US",
5158
+ "SWIFT_BIC",
5159
+ "CARD_TRACK1_DATA",
5160
+ "CARD_TRACK2_DATA",
5161
+ "CARD_EXPIRY",
5162
+ "CARD_AUTH_CODE",
5163
+ // Cryptocurrency
5164
+ "BITCOIN_ADDRESS",
5165
+ "ETHEREUM_ADDRESS",
5166
+ "LITECOIN_ADDRESS",
5167
+ "CARDANO_ADDRESS",
5168
+ "SOLANA_ADDRESS",
5169
+ "MONERO_ADDRESS",
5170
+ "RIPPLE_ADDRESS",
5171
+ // Medical Data
5172
+ "NHS_NUMBER",
5173
+ "MEDICAL_RECORD_NUMBER",
5174
+ "AUSTRALIAN_MEDICARE",
5175
+ "HEALTH_PLAN_NUMBER",
5176
+ "PRESCRIPTION_NUMBER",
5177
+ "PATIENT_ID",
5178
+ // Communications
5179
+ "PHONE_US",
5180
+ "PHONE_UK",
5181
+ "PHONE_UK_MOBILE",
5182
+ "PHONE_INTERNATIONAL",
5183
+ "PHONE_LINE_NUMBER",
5184
+ "EMERGENCY_CONTACT",
5185
+ "ADDRESS_STREET",
5186
+ "ADDRESS_PO_BOX",
5187
+ "POSTCODE_UK",
5188
+ "ZIP_CODE_US",
5189
+ // Network & Technical
5190
+ "IPV4",
5191
+ "IPV6",
5192
+ "MAC_ADDRESS",
5193
+ "URL_WITH_AUTH",
5194
+ // Security Keys & Tokens
5195
+ "PRIVATE_KEY",
5196
+ "SSH_PRIVATE_KEY",
5197
+ "AWS_SECRET_KEY",
5198
+ "AWS_ACCESS_KEY",
5199
+ "AZURE_STORAGE_KEY",
5200
+ "GCP_SERVICE_ACCOUNT",
5201
+ "JWT_TOKEN",
5202
+ "OAUTH_TOKEN",
5203
+ "OAUTH_CLIENT_SECRET",
5204
+ "BEARER_TOKEN",
5205
+ "PAYMENT_TOKEN",
5206
+ "GENERIC_SECRET",
5207
+ "GENERIC_API_KEY",
5208
+ // Platform-Specific API Keys
5209
+ "GITHUB_TOKEN",
5210
+ "SLACK_TOKEN",
5211
+ "STRIPE_API_KEY",
5212
+ "GOOGLE_API_KEY",
5213
+ "FIREBASE_API_KEY",
5214
+ "HEROKU_API_KEY",
5215
+ "MAILGUN_API_KEY",
5216
+ "SENDGRID_API_KEY",
5217
+ "TWILIO_API_KEY",
5218
+ "NPM_TOKEN",
5219
+ "PYPI_TOKEN",
5220
+ "DOCKER_AUTH",
5221
+ "KUBERNETES_SECRET",
5222
+ // Government & Legal
5223
+ "POLICE_REPORT_NUMBER",
5224
+ "IMMIGRATION_NUMBER",
5225
+ "COURT_REPORTER_LICENSE",
5226
+ "CLIENT_ID"
5227
+ ]
5228
+ });
5137
5229
  var gitleaksBinaryPath = null;
5138
5230
  async function initializeGitleaks() {
5139
5231
  try {
@@ -5211,16 +5303,7 @@ async function sanitizeDataWithCounts(obj) {
5211
5303
  ...piiDetections.medium,
5212
5304
  ...piiDetections.low
5213
5305
  ];
5214
- const filteredDetections = allDetections.filter((detection) => {
5215
- if (detection.type === "INSTAGRAM_USERNAME") {
5216
- return false;
5217
- }
5218
- if (detection.value.length < 3 && detection.severity !== "high") {
5219
- return false;
5220
- }
5221
- return true;
5222
- });
5223
- for (const detection of filteredDetections) {
5306
+ for (const detection of allDetections) {
5224
5307
  counts.pii.total++;
5225
5308
  if (detection.severity === "high") counts.pii.high++;
5226
5309
  else if (detection.severity === "medium") counts.pii.medium++;
@@ -5291,9 +5374,15 @@ var PromptItemZ = z26.object({
5291
5374
  });
5292
5375
  var PromptItemArrayZ = z26.array(PromptItemZ);
5293
5376
  function getSystemInfo() {
5377
+ let userName;
5378
+ try {
5379
+ userName = os2.userInfo().username;
5380
+ } catch {
5381
+ userName = void 0;
5382
+ }
5294
5383
  return {
5295
5384
  computerName: os2.hostname(),
5296
- userName: os2.userInfo().username
5385
+ userName
5297
5386
  };
5298
5387
  }
5299
5388
  function uploadAiBlameBuilder(args) {
package/dist/index.mjs CHANGED
@@ -6635,6 +6635,18 @@ var SCMLib = class {
6635
6635
  password: accessToken
6636
6636
  });
6637
6637
  }
6638
+ /**
6639
+ * Fetches commits for multiple PRs in a single batch request.
6640
+ * This is an optimization that not all SCM providers may support efficiently.
6641
+ * Default implementation throws - override in subclasses that support batching.
6642
+ *
6643
+ * @param repoUrl - Repository URL
6644
+ * @param prNumbers - Array of PR numbers to fetch commits for
6645
+ * @returns Map of PR number to array of commit SHAs
6646
+ */
6647
+ async getPrCommitsBatch(_repoUrl, _prNumbers) {
6648
+ throw new Error("getPrCommitsBatch not implemented for this SCM provider");
6649
+ }
6638
6650
  getAccessToken() {
6639
6651
  return this.accessToken || "";
6640
6652
  }
@@ -7493,13 +7505,6 @@ var GET_BLAME_DOCUMENT = `
7493
7505
  ranges {
7494
7506
  commit {
7495
7507
  oid
7496
- author {
7497
- user {
7498
- name
7499
- login
7500
- }
7501
- }
7502
- authoredDate
7503
7508
  }
7504
7509
  startingLine
7505
7510
  endingLine
@@ -7539,6 +7544,7 @@ var GITHUB_GRAPHQL_FRAGMENTS = {
7539
7544
  /**
7540
7545
  * Fragment for fetching blame data.
7541
7546
  * Use with object(expression: $ref) on Commit type.
7547
+ * Note: $path placeholder must be replaced with actual file path.
7542
7548
  */
7543
7549
  BLAME_RANGES: `
7544
7550
  blame(path: "$path") {
@@ -7547,13 +7553,6 @@ var GITHUB_GRAPHQL_FRAGMENTS = {
7547
7553
  endingLine
7548
7554
  commit {
7549
7555
  oid
7550
- author {
7551
- user {
7552
- name
7553
- login
7554
- email
7555
- }
7556
- }
7557
7556
  }
7558
7557
  }
7559
7558
  }
@@ -7717,19 +7716,27 @@ async function executeBatchGraphQL(octokit, owner, repo, config2) {
7717
7716
  }
7718
7717
  }
7719
7718
  `;
7720
- const response = await octokit.graphql(query, { owner, repo });
7719
+ let response;
7720
+ try {
7721
+ response = await octokit.graphql(query, { owner, repo });
7722
+ } catch (error) {
7723
+ const graphqlError = error;
7724
+ if (graphqlError.data?.repository) {
7725
+ response = graphqlError.data;
7726
+ } else {
7727
+ throw error;
7728
+ }
7729
+ }
7721
7730
  const result = /* @__PURE__ */ new Map();
7722
7731
  items.forEach((item, index) => {
7723
7732
  const data = response.repository[`${aliasPrefix}${index}`];
7724
- if (data) {
7725
- const extracted = extractResult(
7726
- data,
7727
- item,
7728
- index
7729
- );
7730
- if (extracted !== void 0) {
7731
- result.set(item, extracted);
7732
- }
7733
+ const extracted = extractResult(
7734
+ data || {},
7735
+ item,
7736
+ index
7737
+ );
7738
+ if (extracted !== void 0) {
7739
+ result.set(item, extracted);
7733
7740
  }
7734
7741
  });
7735
7742
  return result;
@@ -7875,9 +7882,15 @@ function getGithubSdk(params = {}) {
7875
7882
  }));
7876
7883
  } catch (e) {
7877
7884
  if (e instanceof RequestError && e.status === 401) {
7885
+ console.warn(
7886
+ "GitHub API returned 401 Unauthorized when listing repos - token may be expired or lack repo scope"
7887
+ );
7878
7888
  return [];
7879
7889
  }
7880
7890
  if (e instanceof RequestError && e.status === 404) {
7891
+ console.warn(
7892
+ "GitHub API returned 404 Not Found when listing repos - user may not exist"
7893
+ );
7881
7894
  return [];
7882
7895
  }
7883
7896
  throw e;
@@ -8023,13 +8036,42 @@ function getGithubSdk(params = {}) {
8023
8036
  (range) => ({
8024
8037
  startingLine: range.startingLine,
8025
8038
  endingLine: range.endingLine,
8026
- commitSha: range.commit.oid,
8027
- email: range.commit.author.user?.email || "",
8028
- name: range.commit.author.user?.name || "",
8029
- login: range.commit.author.user?.login || ""
8039
+ commitSha: range.commit.oid
8030
8040
  })
8031
8041
  );
8032
8042
  },
8043
+ /**
8044
+ * Fetches commits for multiple PRs in a single GraphQL request.
8045
+ * This is much more efficient than making N separate REST API calls.
8046
+ *
8047
+ * @param params.owner - Repository owner
8048
+ * @param params.repo - Repository name
8049
+ * @param params.prNumbers - Array of PR numbers to fetch commits for
8050
+ * @returns Map of PR number to array of commit SHAs
8051
+ */
8052
+ async getPrCommitsBatch(params2) {
8053
+ return executeBatchGraphQL(octokit, params2.owner, params2.repo, {
8054
+ items: params2.prNumbers,
8055
+ aliasPrefix: "prCommits",
8056
+ buildFragment: (prNumber, index) => `
8057
+ prCommits${index}: pullRequest(number: ${prNumber}) {
8058
+ commits(first: 100) {
8059
+ nodes {
8060
+ commit {
8061
+ oid
8062
+ }
8063
+ }
8064
+ }
8065
+ }`,
8066
+ extractResult: (data) => {
8067
+ const prData = data;
8068
+ if (prData?.commits?.nodes) {
8069
+ return prData.commits.nodes.map((node) => node.commit.oid);
8070
+ }
8071
+ return [];
8072
+ }
8073
+ });
8074
+ },
8033
8075
  // todo: refactor the name for this function
8034
8076
  async createPr(params2) {
8035
8077
  const { sourceRepoUrl, filesPaths, userRepoUrl, title, body } = params2;
@@ -8250,7 +8292,7 @@ function getGithubSdk(params = {}) {
8250
8292
  },
8251
8293
  /**
8252
8294
  * Batch fetch blame data for multiple files via GraphQL.
8253
- * Field selection matches GITHUB_GRAPHQL_FRAGMENTS.BLAME_RANGES pattern.
8295
+ * Uses GITHUB_GRAPHQL_FRAGMENTS.BLAME_RANGES for the field selection.
8254
8296
  */
8255
8297
  async getBlameBatch(params2) {
8256
8298
  return executeBatchGraphQL(octokit, params2.owner, params2.repo, {
@@ -8259,15 +8301,7 @@ function getGithubSdk(params = {}) {
8259
8301
  buildFragment: (path22, index) => `
8260
8302
  file${index}: object(expression: "${params2.ref}") {
8261
8303
  ... on Commit {
8262
- blame(path: "${path22}") {
8263
- ranges {
8264
- startingLine
8265
- endingLine
8266
- commit {
8267
- oid
8268
- }
8269
- }
8270
- }
8304
+ ${GITHUB_GRAPHQL_FRAGMENTS.BLAME_RANGES.replace("$path", path22)}
8271
8305
  }
8272
8306
  }`,
8273
8307
  extractResult: (data) => {
@@ -8276,11 +8310,7 @@ function getGithubSdk(params = {}) {
8276
8310
  return fileData.blame.ranges.map((range) => ({
8277
8311
  startingLine: range.startingLine,
8278
8312
  endingLine: range.endingLine,
8279
- commitSha: range.commit.oid,
8280
- // This is an urgent fix. We need to later remove these fields from the return type and propagate the change.
8281
- email: "",
8282
- name: "",
8283
- login: ""
8313
+ commitSha: range.commit.oid
8284
8314
  }));
8285
8315
  }
8286
8316
  return void 0;
@@ -8681,11 +8711,7 @@ var GithubSCMLib = class extends SCMLib {
8681
8711
  })
8682
8712
  )
8683
8713
  );
8684
- const diffLines = await this._attributeLinesViaBlame(
8685
- pr.head.ref,
8686
- filesRes.data,
8687
- commits
8688
- );
8714
+ const diffLines = filesRes ? await this._attributeLinesViaBlame(pr.head.ref, filesRes.data, commits) : [];
8689
8715
  return {
8690
8716
  diff: prDiff,
8691
8717
  createdAt: new Date(pr.created_at),
@@ -8743,6 +8769,19 @@ var GithubSCMLib = class extends SCMLib {
8743
8769
  });
8744
8770
  return submitRequests;
8745
8771
  }
8772
+ /**
8773
+ * Fetches commits for multiple PRs in a single GraphQL request.
8774
+ * Much more efficient than calling getSubmitRequestDiff for each PR.
8775
+ *
8776
+ * @param repoUrl - Repository URL
8777
+ * @param prNumbers - Array of PR numbers to fetch commits for
8778
+ * @returns Map of PR number to array of commit SHAs
8779
+ */
8780
+ async getPrCommitsBatch(repoUrl, prNumbers) {
8781
+ this._validateAccessToken();
8782
+ const { owner, repo } = parseGithubOwnerAndRepo(repoUrl);
8783
+ return this.githubSdk.getPrCommitsBatch({ owner, repo, prNumbers });
8784
+ }
8746
8785
  /**
8747
8786
  * Parse a Linear ticket from URL and name
8748
8787
  * Returns null if invalid or missing data
@@ -9211,10 +9250,7 @@ async function getGitlabBlameRanges({ ref, gitlabUrl, path: path22 }, options) {
9211
9250
  return {
9212
9251
  startingLine: oldLineNumber,
9213
9252
  endingLine: lineNumber - 1,
9214
- commitSha: range.commit.id,
9215
- login: range.commit.author_email,
9216
- email: range.commit.author_email,
9217
- name: range.commit.author_name
9253
+ commitSha: range.commit.id
9218
9254
  };
9219
9255
  });
9220
9256
  }
@@ -13268,7 +13304,99 @@ import z31 from "zod";
13268
13304
  import { OpenRedaction } from "@openredaction/openredaction";
13269
13305
  import { spawn } from "child_process";
13270
13306
  import { installGitleaks } from "gitleaks-secret-scanner/lib/installer.js";
13271
- var openRedaction = new OpenRedaction();
13307
+ var openRedaction = new OpenRedaction({
13308
+ patterns: [
13309
+ // Core Personal Data
13310
+ "EMAIL",
13311
+ "SSN",
13312
+ "NATIONAL_INSURANCE_UK",
13313
+ "DATE_OF_BIRTH",
13314
+ // Identity Documents
13315
+ "PASSPORT_UK",
13316
+ "PASSPORT_US",
13317
+ "PASSPORT_MRZ_TD1",
13318
+ "PASSPORT_MRZ_TD3",
13319
+ "DRIVING_LICENSE_UK",
13320
+ "DRIVING_LICENSE_US",
13321
+ "VISA_NUMBER",
13322
+ "VISA_MRZ",
13323
+ "TAX_ID",
13324
+ // Financial Data
13325
+ "CREDIT_CARD",
13326
+ "IBAN",
13327
+ "BANK_ACCOUNT_UK",
13328
+ "ROUTING_NUMBER_US",
13329
+ "SWIFT_BIC",
13330
+ "CARD_TRACK1_DATA",
13331
+ "CARD_TRACK2_DATA",
13332
+ "CARD_EXPIRY",
13333
+ "CARD_AUTH_CODE",
13334
+ // Cryptocurrency
13335
+ "BITCOIN_ADDRESS",
13336
+ "ETHEREUM_ADDRESS",
13337
+ "LITECOIN_ADDRESS",
13338
+ "CARDANO_ADDRESS",
13339
+ "SOLANA_ADDRESS",
13340
+ "MONERO_ADDRESS",
13341
+ "RIPPLE_ADDRESS",
13342
+ // Medical Data
13343
+ "NHS_NUMBER",
13344
+ "MEDICAL_RECORD_NUMBER",
13345
+ "AUSTRALIAN_MEDICARE",
13346
+ "HEALTH_PLAN_NUMBER",
13347
+ "PRESCRIPTION_NUMBER",
13348
+ "PATIENT_ID",
13349
+ // Communications
13350
+ "PHONE_US",
13351
+ "PHONE_UK",
13352
+ "PHONE_UK_MOBILE",
13353
+ "PHONE_INTERNATIONAL",
13354
+ "PHONE_LINE_NUMBER",
13355
+ "EMERGENCY_CONTACT",
13356
+ "ADDRESS_STREET",
13357
+ "ADDRESS_PO_BOX",
13358
+ "POSTCODE_UK",
13359
+ "ZIP_CODE_US",
13360
+ // Network & Technical
13361
+ "IPV4",
13362
+ "IPV6",
13363
+ "MAC_ADDRESS",
13364
+ "URL_WITH_AUTH",
13365
+ // Security Keys & Tokens
13366
+ "PRIVATE_KEY",
13367
+ "SSH_PRIVATE_KEY",
13368
+ "AWS_SECRET_KEY",
13369
+ "AWS_ACCESS_KEY",
13370
+ "AZURE_STORAGE_KEY",
13371
+ "GCP_SERVICE_ACCOUNT",
13372
+ "JWT_TOKEN",
13373
+ "OAUTH_TOKEN",
13374
+ "OAUTH_CLIENT_SECRET",
13375
+ "BEARER_TOKEN",
13376
+ "PAYMENT_TOKEN",
13377
+ "GENERIC_SECRET",
13378
+ "GENERIC_API_KEY",
13379
+ // Platform-Specific API Keys
13380
+ "GITHUB_TOKEN",
13381
+ "SLACK_TOKEN",
13382
+ "STRIPE_API_KEY",
13383
+ "GOOGLE_API_KEY",
13384
+ "FIREBASE_API_KEY",
13385
+ "HEROKU_API_KEY",
13386
+ "MAILGUN_API_KEY",
13387
+ "SENDGRID_API_KEY",
13388
+ "TWILIO_API_KEY",
13389
+ "NPM_TOKEN",
13390
+ "PYPI_TOKEN",
13391
+ "DOCKER_AUTH",
13392
+ "KUBERNETES_SECRET",
13393
+ // Government & Legal
13394
+ "POLICE_REPORT_NUMBER",
13395
+ "IMMIGRATION_NUMBER",
13396
+ "COURT_REPORTER_LICENSE",
13397
+ "CLIENT_ID"
13398
+ ]
13399
+ });
13272
13400
  var gitleaksBinaryPath = null;
13273
13401
  async function initializeGitleaks() {
13274
13402
  try {
@@ -13346,16 +13474,7 @@ async function sanitizeDataWithCounts(obj) {
13346
13474
  ...piiDetections.medium,
13347
13475
  ...piiDetections.low
13348
13476
  ];
13349
- const filteredDetections = allDetections.filter((detection) => {
13350
- if (detection.type === "INSTAGRAM_USERNAME") {
13351
- return false;
13352
- }
13353
- if (detection.value.length < 3 && detection.severity !== "high") {
13354
- return false;
13355
- }
13356
- return true;
13357
- });
13358
- for (const detection of filteredDetections) {
13477
+ for (const detection of allDetections) {
13359
13478
  counts.pii.total++;
13360
13479
  if (detection.severity === "high") counts.pii.high++;
13361
13480
  else if (detection.severity === "medium") counts.pii.medium++;
@@ -13426,9 +13545,15 @@ var PromptItemZ = z31.object({
13426
13545
  });
13427
13546
  var PromptItemArrayZ = z31.array(PromptItemZ);
13428
13547
  function getSystemInfo() {
13548
+ let userName;
13549
+ try {
13550
+ userName = os2.userInfo().username;
13551
+ } catch {
13552
+ userName = void 0;
13553
+ }
13429
13554
  return {
13430
13555
  computerName: os2.hostname(),
13431
- userName: os2.userInfo().username
13556
+ userName
13432
13557
  };
13433
13558
  }
13434
13559
  function uploadAiBlameBuilder(args) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.1.10",
3
+ "version": "1.1.12",
4
4
  "description": "Automated secure code remediation tool",
5
5
  "repository": "git+https://github.com/mobb-dev/bugsy.git",
6
6
  "main": "dist/index.mjs",