mobbdev 1.4.65 → 1.4.67

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.
@@ -1485,6 +1485,11 @@ var init_analysis = __esm({
1485
1485
  createdOn: z3.string(),
1486
1486
  state: z3.enum(Fix_Report_State_Enum),
1487
1487
  isFixEnabled: z3.boolean().nullish(),
1488
+ // When this report's fixes expire(d). Nullish because the column is, and
1489
+ // because the issue screen reads it only to date the "fixes expired"
1490
+ // messaging — a missing date degrades to the undated wording rather than
1491
+ // failing the parse (MOBB-3769).
1492
+ expirationOn: z3.string().nullish(),
1488
1493
  repo: z3.object({
1489
1494
  name: z3.string().nullable(),
1490
1495
  originalUrl: z3.string(),
@@ -1579,7 +1584,10 @@ var init_issue = __esm({
1579
1584
  })
1580
1585
  }).transform(async ({ sourceCodeFile }) => {
1581
1586
  const { url } = sourceCodeFile.signedFile;
1582
- const sourceCodeRes = await fetch(url);
1587
+ const sourceCodeRes = await fetch(url).catch(() => null);
1588
+ if (!sourceCodeRes?.ok) {
1589
+ return null;
1590
+ }
1583
1591
  if (Number(sourceCodeRes.headers.get("Content-Length")) > MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES) {
1584
1592
  return null;
1585
1593
  }
@@ -1590,16 +1598,40 @@ var init_issue = __esm({
1590
1598
  })
1591
1599
  ).transform((nodes) => nodes.filter((node) => node !== null)),
1592
1600
  fix: FixPartsForFixScreenZ.nullish(),
1601
+ // Null when the diff cannot actually be read, not merely when the row is
1602
+ // absent. The `vulnerability_report_issue_node_diff_file_id` column outlives
1603
+ // the object it points at — only code-node rows are GC'd — and `getFile`
1604
+ // signs a URL without checking existence, so a fixes-expired report hands
1605
+ // back a perfectly valid URL for an object the lifecycle already swept.
1606
+ //
1607
+ // Treating the row as proof of the object put an empty box under "The issue
1608
+ // was reported in the following locations:", because the renderer took the
1609
+ // diff branch and had nothing to draw. Collapsing to null falls back to the
1610
+ // locations list, which is the honest thing to show. Same rule as the
1611
+ // snippet reader: an id is not evidence a file exists.
1593
1612
  vulnerabilityReportIssueNodeDiffFile: z4.object({
1594
1613
  signedFile: z4.object({
1595
1614
  url: z4.string()
1596
- }).transform(async ({ url }) => {
1597
- const codeDiff = await fetch(url).then((res) => res.text());
1598
- return { codeDiff };
1599
1615
  })
1600
- }).nullish(),
1616
+ }).nullish().transform(async (nodeDiffFile) => {
1617
+ if (!nodeDiffFile) {
1618
+ return nodeDiffFile;
1619
+ }
1620
+ const response = await fetch(nodeDiffFile.signedFile.url).catch(
1621
+ () => null
1622
+ );
1623
+ if (!response?.ok) {
1624
+ return null;
1625
+ }
1626
+ return { signedFile: { codeDiff: await response.text() } };
1627
+ }),
1601
1628
  sharedState: VulnerabilityReportIssueSharedStateZ,
1602
- unfixableId: z4.guid().nullish()
1629
+ unfixableId: z4.guid().nullish(),
1630
+ // The DB link to the fix, which outlives the fix's S3 artifacts. Non-null
1631
+ // means "this issue had a fix" even when `fix` above is absent because the
1632
+ // report's fixes expired, and that distinction is what keeps such an issue
1633
+ // from being rendered as if it were never fixable (MOBB-3769).
1634
+ fixId: z4.guid().nullish()
1603
1635
  });
1604
1636
  FalsePositivePartsZ = z4.object({
1605
1637
  extraContext: z4.array(z4.object({ key: z4.string(), value: z4.string() })),
@@ -1619,7 +1651,13 @@ var init_issue = __esm({
1619
1651
  z4.object({
1620
1652
  category: z4.literal("FalsePositive" /* FalsePositive */),
1621
1653
  fpId: z4.guid(),
1622
- getFalsePositive: FalsePositivePartsZ
1654
+ // Nullish, like getUnfixable on GeneralIssueZ, because the explanation can
1655
+ // genuinely be absent: the analyzer's pickle dies with the report's fixes,
1656
+ // and issues processed before the persistent store existed (MOBB-3768)
1657
+ // have nothing to fall back to. This used to be required, so the
1658
+ // resolver's error member failed the parse and took down the entire issue
1659
+ // screen instead of rendering one "explanation unavailable" accordion.
1660
+ getFalsePositive: FalsePositivePartsZ.nullish()
1623
1661
  }).shape
1624
1662
  );
1625
1663
  GeneralIssueZ = BaseIssuePartsZ.extend(
@@ -2002,6 +2040,10 @@ var init_types = __esm({
2002
2040
  severityText: z7.enum(Vulnerability_Severity_Enum),
2003
2041
  vulnerabilityReportIssues: z7.array(
2004
2042
  z7.object({
2043
+ // The row's reroute target once fixes expire: a fix's own page cannot
2044
+ // render without its S3 patch, so the fixable bucket points the row
2045
+ // at this issue instead (MOBB-3769).
2046
+ id: z7.guid(),
2005
2047
  issueType: z7.string(),
2006
2048
  issueLanguage: z7.string(),
2007
2049
  sharedState: IssueSharedStateZ2
@@ -2146,7 +2188,11 @@ var init_types = __esm({
2146
2188
  email: z7.string()
2147
2189
  }).nullable(),
2148
2190
  state: z7.enum(Fix_Report_State_Enum),
2149
- expirationOn: z7.string()
2191
+ expirationOn: z7.string(),
2192
+ // Whether this org has fixes at all. Scan-only reports hit the same
2193
+ // expiry date as every other report, so the list needs this to avoid
2194
+ // badging them for fixes they never had (MOBB-3769).
2195
+ isFixEnabled: z7.boolean()
2150
2196
  })
2151
2197
  });
2152
2198
  GetProjectsQueryZ = z7.object({
package/dist/index.mjs CHANGED
@@ -1590,6 +1590,11 @@ var init_analysis = __esm({
1590
1590
  createdOn: z4.string(),
1591
1591
  state: z4.enum(Fix_Report_State_Enum),
1592
1592
  isFixEnabled: z4.boolean().nullish(),
1593
+ // When this report's fixes expire(d). Nullish because the column is, and
1594
+ // because the issue screen reads it only to date the "fixes expired"
1595
+ // messaging — a missing date degrades to the undated wording rather than
1596
+ // failing the parse (MOBB-3769).
1597
+ expirationOn: z4.string().nullish(),
1593
1598
  repo: z4.object({
1594
1599
  name: z4.string().nullable(),
1595
1600
  originalUrl: z4.string(),
@@ -1684,7 +1689,10 @@ var init_issue = __esm({
1684
1689
  })
1685
1690
  }).transform(async ({ sourceCodeFile }) => {
1686
1691
  const { url } = sourceCodeFile.signedFile;
1687
- const sourceCodeRes = await fetch(url);
1692
+ const sourceCodeRes = await fetch(url).catch(() => null);
1693
+ if (!sourceCodeRes?.ok) {
1694
+ return null;
1695
+ }
1688
1696
  if (Number(sourceCodeRes.headers.get("Content-Length")) > MAX_SOURCE_CODE_FILE_SIZE_IN_BYTES) {
1689
1697
  return null;
1690
1698
  }
@@ -1695,16 +1703,40 @@ var init_issue = __esm({
1695
1703
  })
1696
1704
  ).transform((nodes) => nodes.filter((node) => node !== null)),
1697
1705
  fix: FixPartsForFixScreenZ.nullish(),
1706
+ // Null when the diff cannot actually be read, not merely when the row is
1707
+ // absent. The `vulnerability_report_issue_node_diff_file_id` column outlives
1708
+ // the object it points at — only code-node rows are GC'd — and `getFile`
1709
+ // signs a URL without checking existence, so a fixes-expired report hands
1710
+ // back a perfectly valid URL for an object the lifecycle already swept.
1711
+ //
1712
+ // Treating the row as proof of the object put an empty box under "The issue
1713
+ // was reported in the following locations:", because the renderer took the
1714
+ // diff branch and had nothing to draw. Collapsing to null falls back to the
1715
+ // locations list, which is the honest thing to show. Same rule as the
1716
+ // snippet reader: an id is not evidence a file exists.
1698
1717
  vulnerabilityReportIssueNodeDiffFile: z5.object({
1699
1718
  signedFile: z5.object({
1700
1719
  url: z5.string()
1701
- }).transform(async ({ url }) => {
1702
- const codeDiff = await fetch(url).then((res) => res.text());
1703
- return { codeDiff };
1704
1720
  })
1705
- }).nullish(),
1721
+ }).nullish().transform(async (nodeDiffFile) => {
1722
+ if (!nodeDiffFile) {
1723
+ return nodeDiffFile;
1724
+ }
1725
+ const response = await fetch(nodeDiffFile.signedFile.url).catch(
1726
+ () => null
1727
+ );
1728
+ if (!response?.ok) {
1729
+ return null;
1730
+ }
1731
+ return { signedFile: { codeDiff: await response.text() } };
1732
+ }),
1706
1733
  sharedState: VulnerabilityReportIssueSharedStateZ,
1707
- unfixableId: z5.guid().nullish()
1734
+ unfixableId: z5.guid().nullish(),
1735
+ // The DB link to the fix, which outlives the fix's S3 artifacts. Non-null
1736
+ // means "this issue had a fix" even when `fix` above is absent because the
1737
+ // report's fixes expired, and that distinction is what keeps such an issue
1738
+ // from being rendered as if it were never fixable (MOBB-3769).
1739
+ fixId: z5.guid().nullish()
1708
1740
  });
1709
1741
  FalsePositivePartsZ = z5.object({
1710
1742
  extraContext: z5.array(z5.object({ key: z5.string(), value: z5.string() })),
@@ -1724,7 +1756,13 @@ var init_issue = __esm({
1724
1756
  z5.object({
1725
1757
  category: z5.literal("FalsePositive" /* FalsePositive */),
1726
1758
  fpId: z5.guid(),
1727
- getFalsePositive: FalsePositivePartsZ
1759
+ // Nullish, like getUnfixable on GeneralIssueZ, because the explanation can
1760
+ // genuinely be absent: the analyzer's pickle dies with the report's fixes,
1761
+ // and issues processed before the persistent store existed (MOBB-3768)
1762
+ // have nothing to fall back to. This used to be required, so the
1763
+ // resolver's error member failed the parse and took down the entire issue
1764
+ // screen instead of rendering one "explanation unavailable" accordion.
1765
+ getFalsePositive: FalsePositivePartsZ.nullish()
1728
1766
  }).shape
1729
1767
  );
1730
1768
  GeneralIssueZ = BaseIssuePartsZ.extend(
@@ -2049,6 +2087,10 @@ var init_types = __esm({
2049
2087
  severityText: z7.enum(Vulnerability_Severity_Enum),
2050
2088
  vulnerabilityReportIssues: z7.array(
2051
2089
  z7.object({
2090
+ // The row's reroute target once fixes expire: a fix's own page cannot
2091
+ // render without its S3 patch, so the fixable bucket points the row
2092
+ // at this issue instead (MOBB-3769).
2093
+ id: z7.guid(),
2052
2094
  issueType: z7.string(),
2053
2095
  issueLanguage: z7.string(),
2054
2096
  sharedState: IssueSharedStateZ2
@@ -2193,7 +2235,11 @@ var init_types = __esm({
2193
2235
  email: z7.string()
2194
2236
  }).nullable(),
2195
2237
  state: z7.enum(Fix_Report_State_Enum),
2196
- expirationOn: z7.string()
2238
+ expirationOn: z7.string(),
2239
+ // Whether this org has fixes at all. Scan-only reports hit the same
2240
+ // expiry date as every other report, so the list needs this to avoid
2241
+ // badging them for fixes they never had (MOBB-3769).
2242
+ isFixEnabled: z7.boolean()
2197
2243
  })
2198
2244
  });
2199
2245
  GetProjectsQueryZ = z7.object({
@@ -18568,7 +18614,7 @@ function createLogger(config2) {
18568
18614
 
18569
18615
  // src/features/claude_code/hook_logger.ts
18570
18616
  var DD_RUM_TOKEN = true ? "pubf59c0182545bfb4c299175119f1abf9b" : "";
18571
- var CLI_VERSION = true ? "1.4.65" : "unknown";
18617
+ var CLI_VERSION = true ? "1.4.67" : "unknown";
18572
18618
  var NAMESPACE = "mobbdev-claude-code-hook-logs";
18573
18619
  var claudeCodeVersion;
18574
18620
  function buildDdTags() {
@@ -23747,7 +23793,7 @@ All tools require authentication via the Mobb API. The tools will handle authent
23747
23793
 
23748
23794
  Common scenarios:
23749
23795
  - **No fixes found**: Repository has no vulnerabilities or they're not fixable
23750
- - **Report expired**: Previous scan is too old, need to rescan
23796
+ - **Fixes expired**: The previous scan's fixes have aged out \u2014 rescan to get new ones (the findings themselves stay viewable in the web app)
23751
23797
  - **No report found**: No previous scan exists, run scan_and_fix_vulnerabilities
23752
23798
  - **Authentication required**: User needs to authenticate with Mobb
23753
23799
 
@@ -24257,18 +24303,19 @@ var expiredReportPrompt = ({
24257
24303
  lastReportDate
24258
24304
  }) => `\u{1F50D} **MOBB SECURITY SCAN STATUS**
24259
24305
 
24260
- ## Out-of-Date Vulnerability Report
24306
+ ## Fixes Have Expired
24261
24307
 
24262
- Your most recent vulnerability report for this repository **expired on ${lastReportDate}** and is no longer available for fetching automated fixes.
24308
+ The fixes from your most recent vulnerability report for this repository **expired on ${lastReportDate}**, so there are no automated fixes left to fetch.
24263
24309
 
24264
24310
  ### \u{1F4CB} Why Did This Happen?
24265
- - Reports are automatically purged after a retention period for security and storage optimization.
24266
- - No new scans have been run since the last report expired.
24311
+ - Fixes are kept for a limited window after an analysis (extendable), and this one has passed.
24312
+ - The findings themselves have not gone anywhere: the report is still viewable in the Mobb web app, with every issue, location and severity intact.
24313
+ - No new scans have been run since those fixes expired.
24267
24314
 
24268
24315
  ### \u{1F3AF} Recommended Actions
24269
- 1. **Run a fresh security scan** to generate an up-to-date vulnerability report.
24316
+ 1. **Run a fresh security scan** to generate new fixes for the current code.
24270
24317
  - Use the \`${MCP_TOOL_SCAN_AND_FIX_VULNERABILITIES}\` tool.
24271
- 2. **Verify repository access** if scans fail to run or the repository has moved.
24318
+ 2. **Open the existing report in the web app** if you need the findings themselves \u2014 for an audit, a compliance review, or to see what was reported.
24272
24319
  3. **Review your CI/CD pipeline** to ensure regular scans are triggered.
24273
24320
 
24274
24321
  For more help:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "mobbdev",
3
- "version": "1.4.65",
3
+ "version": "1.4.67",
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",