@mushi-mushi/core 1.20.0 → 1.21.0

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/CONTRIBUTING.md CHANGED
@@ -70,7 +70,7 @@ packages/
70
70
  react-native/ React Native SDK (MIT)
71
71
  cli/ CLI tool (MIT)
72
72
  mcp/ MCP server for coding agents (MIT)
73
- server/ Supabase Edge Functions (AGPLv3)
73
+ server/ Supabase Edge Functions (AGPLv3; ee/ is commercial)
74
74
  agents/ Agentic fix pipeline (AGPLv3)
75
75
  verify/ Fix verification (AGPLv3)
76
76
  apps/
@@ -211,7 +211,7 @@ chore: bump dependencies
211
211
  ## License
212
212
 
213
213
  - SDK packages are MIT — your contributions will be MIT-licensed
214
- - Server/agents/verify are AGPLv3 — contributions to those packages fall under AGPLv3
214
+ - Server/agents/verify are AGPLv3 — contributions to those packages fall under AGPLv3. A [commercial license](./COMMERCIAL-LICENSE.md) is available for hosted-SaaS use cases that cannot publish modifications. The `packages/server/ee/` directory is source-available but commercial (production use needs a license); contributions there are accepted under the same EE terms.
215
215
 
216
216
  ## Questions?
217
217
 
package/SECURITY.md CHANGED
@@ -113,7 +113,7 @@ What we treat as in-scope attacker capabilities, and what we don't.
113
113
  | Compromised Supabase service-role key | ❌ | Treated as a tier-0 incident; would require key rotation and audit-log forensics. Not defendable in software. |
114
114
  | Compromise of `kensaurus@gmail.com` | ❌ | Treated as a project-fork event; downstream consumers should pin to the last known-good version and follow the new release channel. |
115
115
  | Physical / OS-level attacker on an end-user device | ❌ | Out of scope. |
116
- | Malicious fork using the Mushi name to ship malware | ❌ (technical) ✅ (legal) | The MIT/BSL grant lets the fork exist; the trademark policy (`TRADEMARK.md`) makes shipping it under the Mushi name an infringement we will pursue. |
116
+ | Malicious fork using the Mushi name to ship malware | ❌ (technical) ✅ (legal) | The MIT / AGPLv3 grant lets the fork exist; the trademark policy (`TRADEMARK.md`) makes shipping it under the Mushi name an infringement we will pursue. |
117
117
 
118
118
  ## Data handling and PII
119
119
 
package/dist/index.cjs CHANGED
@@ -42,6 +42,47 @@ function formatBytes(n) {
42
42
  return `${(n / (1024 * 1024)).toFixed(2)} MB`;
43
43
  }
44
44
 
45
+ // src/digest.ts
46
+ function getSubtle() {
47
+ try {
48
+ const g = globalThis;
49
+ const crypto2 = g["crypto"];
50
+ if (crypto2?.subtle) return crypto2.subtle;
51
+ } catch {
52
+ }
53
+ return null;
54
+ }
55
+ function bytesToHex(bytes) {
56
+ return Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
57
+ }
58
+ async function sha256Hex(value) {
59
+ const subtle = getSubtle();
60
+ if (subtle) {
61
+ const buffer = await subtle.digest("SHA-256", new TextEncoder().encode(value));
62
+ return bytesToHex(new Uint8Array(buffer));
63
+ }
64
+ const { sha256 } = await import('@noble/hashes/sha2.js');
65
+ return bytesToHex(sha256(new TextEncoder().encode(value)));
66
+ }
67
+ async function hmacSha256Hex(secret, value) {
68
+ const subtle = getSubtle();
69
+ if (subtle) {
70
+ const key = await subtle.importKey(
71
+ "raw",
72
+ new TextEncoder().encode(secret),
73
+ { name: "HMAC", hash: "SHA-256" },
74
+ false,
75
+ ["sign"]
76
+ );
77
+ const buffer = await subtle.sign("HMAC", key, new TextEncoder().encode(value));
78
+ return bytesToHex(new Uint8Array(buffer));
79
+ }
80
+ const { hmac } = await import('@noble/hashes/hmac.js');
81
+ const { sha256 } = await import('@noble/hashes/sha2.js');
82
+ const result = hmac(sha256, new TextEncoder().encode(secret), new TextEncoder().encode(value));
83
+ return bytesToHex(result);
84
+ }
85
+
45
86
  // src/api-client.ts
46
87
  var _credWarningEmitted = false;
47
88
  var MUSHI_USER_TOKEN_HEADER = "X-Mushi-User-Token";
@@ -411,21 +452,6 @@ function createApiClient(options) {
411
452
  }
412
453
  };
413
454
  }
414
- async function sha256Hex(value) {
415
- const buffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
416
- return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
417
- }
418
- async function hmacSha256Hex(secret, value) {
419
- const key = await crypto.subtle.importKey(
420
- "raw",
421
- new TextEncoder().encode(secret),
422
- { name: "HMAC", hash: "SHA-256" },
423
- false,
424
- ["sign"]
425
- );
426
- const buffer = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(value));
427
- return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
428
- }
429
455
  function sleep(ms) {
430
456
  return new Promise((resolve) => setTimeout(resolve, ms));
431
457
  }
@@ -1381,20 +1407,9 @@ function capturePageLoadTiming(win) {
1381
1407
  }
1382
1408
 
1383
1409
  // src/reporter-token.ts
1384
- var STORAGE_KEY = "mushi_reporter_token";
1385
- function getReporterToken() {
1386
- if (typeof localStorage !== "undefined") {
1387
- const existing = localStorage.getItem(STORAGE_KEY);
1388
- if (existing) return existing;
1389
- }
1390
- const token = generateToken();
1391
- if (typeof localStorage !== "undefined") {
1392
- try {
1393
- localStorage.setItem(STORAGE_KEY, token);
1394
- } catch {
1395
- }
1396
- }
1397
- return token;
1410
+ var LEGACY_STORAGE_KEY = "mushi_reporter_token";
1411
+ function storageKey(projectId) {
1412
+ return `mushi:reporter-token:${projectId}`;
1398
1413
  }
1399
1414
  function generateToken() {
1400
1415
  if (typeof crypto !== "undefined" && crypto.randomUUID) {
@@ -1411,6 +1426,38 @@ function generateToken() {
1411
1426
  const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0")).join("");
1412
1427
  return `mushi_${hex}`;
1413
1428
  }
1429
+ function readStoredToken(key) {
1430
+ if (typeof localStorage === "undefined") return null;
1431
+ try {
1432
+ const existing = localStorage.getItem(key);
1433
+ return existing && existing.length > 0 ? existing : null;
1434
+ } catch {
1435
+ return null;
1436
+ }
1437
+ }
1438
+ function writeStoredToken(key, token) {
1439
+ if (typeof localStorage === "undefined") return;
1440
+ try {
1441
+ localStorage.setItem(key, token);
1442
+ } catch {
1443
+ }
1444
+ }
1445
+ function getReporterToken(projectId) {
1446
+ if (!projectId) {
1447
+ const legacy2 = readStoredToken(LEGACY_STORAGE_KEY);
1448
+ if (legacy2) return legacy2;
1449
+ const token2 = generateToken();
1450
+ writeStoredToken(LEGACY_STORAGE_KEY, token2);
1451
+ return token2;
1452
+ }
1453
+ const key = storageKey(projectId);
1454
+ const scoped = readStoredToken(key);
1455
+ if (scoped) return scoped;
1456
+ const legacy = readStoredToken(LEGACY_STORAGE_KEY);
1457
+ const token = legacy ?? generateToken();
1458
+ writeStoredToken(key, token);
1459
+ return token;
1460
+ }
1414
1461
 
1415
1462
  // src/uuid.ts
1416
1463
  function newUuid() {
@@ -1706,6 +1753,42 @@ var MUSHI_COLORS_DARK = {
1706
1753
  ok: "#4ADE80",
1707
1754
  danger: "#F87171"
1708
1755
  };
1756
+ var MUSHI_TIER_COLORS = {
1757
+ free: MUSHI_COLORS_LIGHT.inkMuted,
1758
+ explorer: "#2563EB",
1759
+ contributor: "#7C3AED",
1760
+ champion: "#D97706",
1761
+ default: MUSHI_COLORS_LIGHT.accent
1762
+ };
1763
+ var MUSHI_BANNER_NEON = {
1764
+ bg: "#0FFF50",
1765
+ fg: "#0a1a0a",
1766
+ border: "#00C43A"
1767
+ };
1768
+ var MUSHI_ON_ACCENT = "#FAF7F0";
1769
+ var MUSHI_INVERSE = "#ffffff";
1770
+ var MUSHI_ACCENT_SHADOW = {
1771
+ light: "#9A2A1E",
1772
+ dark: "#7A1F15"
1773
+ };
1774
+ var MUSHI_BANNER_BRAND_BORDER = {
1775
+ light: "#B52F1F",
1776
+ dark: "#C4321E"
1777
+ };
1778
+ var MUSHI_REPORTER_STATUS = {
1779
+ light: {
1780
+ sent: { fg: "#1E4A8C", bg: "rgba(30,74,140,0.08)", border: "rgba(30,74,140,0.16)" },
1781
+ review: { fg: "#8A5A00", bg: "rgba(180,120,0,0.10)", border: "rgba(180,120,0,0.18)" },
1782
+ fixing: { fg: "#9A3D12", bg: "rgba(224,60,44,0.10)", border: "rgba(224,60,44,0.18)" },
1783
+ fixed: { fg: "#1F6B3A", bg: "rgba(31,107,58,0.10)", border: "rgba(31,107,58,0.18)" }
1784
+ },
1785
+ dark: {
1786
+ sent: { fg: "#A8C4FF", bg: "rgba(120,160,255,0.12)", border: "rgba(120,160,255,0.22)" },
1787
+ review: { fg: "#FFD27A", bg: "rgba(255,190,90,0.12)", border: "rgba(255,190,90,0.22)" },
1788
+ fixing: { fg: "#FFB899", bg: "rgba(255,120,60,0.12)", border: "rgba(255,120,60,0.24)" },
1789
+ fixed: { fg: "#8FE3B0", bg: "rgba(80,200,130,0.12)", border: "rgba(80,200,130,0.22)" }
1790
+ }
1791
+ };
1709
1792
  function mushiPalette(mode) {
1710
1793
  return mode === "dark" ? MUSHI_COLORS_DARK : MUSHI_COLORS_LIGHT;
1711
1794
  }
@@ -1752,16 +1835,32 @@ var MUSHI_MOTION = {
1752
1835
  var MUSHI_GEOMETRY = {
1753
1836
  bannerHeight: 36,
1754
1837
  fabSize: 52,
1755
- edgeTabWidth: 28,
1838
+ /** edge-tab launcher width (px) */
1839
+ edgeTabWidth: 32,
1756
1840
  /** default gutter from the screen edge (added on top of safe-area insets) */
1757
1841
  gutter: 24,
1758
- panelWidth: 384,
1842
+ /** Web panel width (px) — matches shipped Shadow DOM widget */
1843
+ panelWidth: 360,
1844
+ /** max panel height before keyboard inset (px) */
1845
+ panelMaxHeight: 480,
1759
1846
  /** below this viewport width the panel becomes a full-width bottom sheet */
1760
1847
  panelSheetBreakpoint: 480
1761
1848
  };
1849
+ function safeWidgetHex(v) {
1850
+ return /^#[0-9a-fA-F]{3,8}$/.test(v) ? v : "";
1851
+ }
1852
+ function resolveWidgetAccent(mode, accent = "", accentText = "") {
1853
+ const pal = mushiPalette(mode);
1854
+ const safeAccent = safeWidgetHex(accent);
1855
+ const safeAccentText = safeWidgetHex(accentText);
1856
+ const resolvedAccent = safeAccent || pal.accent;
1857
+ const accentWash = safeAccent ? mode === "dark" ? `${resolvedAccent}1F` : `${resolvedAccent}14` : pal.accentWash;
1858
+ const accentInk = safeAccentText || pal.accentInk;
1859
+ return { accent: resolvedAccent, accentWash, accentInk };
1860
+ }
1762
1861
  var MUSHI_COPY = {
1763
1862
  bannerLabel: "Beta",
1764
- bannerMessage: "Help us improve \u2014 your feedback shapes what we ship.",
1863
+ bannerMessage: "Found a bug? Tap to report it.",
1765
1864
  bugCta: "Report a bug",
1766
1865
  featureCta: "Feature request",
1767
1866
  triggerText: "\u{1F41B}",
@@ -2015,6 +2114,9 @@ function isSafeFaviconHref(href) {
2015
2114
  exports.DEFAULT_API_ENDPOINT = DEFAULT_API_ENDPOINT;
2016
2115
  exports.MAX_REPORT_PAYLOAD_BYTES = MAX_REPORT_PAYLOAD_BYTES;
2017
2116
  exports.MAX_SCREENSHOT_DATA_URL_BYTES = MAX_SCREENSHOT_DATA_URL_BYTES;
2117
+ exports.MUSHI_ACCENT_SHADOW = MUSHI_ACCENT_SHADOW;
2118
+ exports.MUSHI_BANNER_BRAND_BORDER = MUSHI_BANNER_BRAND_BORDER;
2119
+ exports.MUSHI_BANNER_NEON = MUSHI_BANNER_NEON;
2018
2120
  exports.MUSHI_COLORS_DARK = MUSHI_COLORS_DARK;
2019
2121
  exports.MUSHI_COLORS_LIGHT = MUSHI_COLORS_LIGHT;
2020
2122
  exports.MUSHI_COPY = MUSHI_COPY;
@@ -2022,12 +2124,16 @@ exports.MUSHI_GEOMETRY = MUSHI_GEOMETRY;
2022
2124
  exports.MUSHI_IDENTITY_TOKEN_PREFIX = MUSHI_IDENTITY_TOKEN_PREFIX;
2023
2125
  exports.MUSHI_INTERNAL_HEADER = MUSHI_INTERNAL_HEADER;
2024
2126
  exports.MUSHI_INTERNAL_INIT_MARKER = MUSHI_INTERNAL_INIT_MARKER;
2127
+ exports.MUSHI_INVERSE = MUSHI_INVERSE;
2025
2128
  exports.MUSHI_MOTION = MUSHI_MOTION;
2129
+ exports.MUSHI_ON_ACCENT = MUSHI_ON_ACCENT;
2026
2130
  exports.MUSHI_PROJECT_HEADER = MUSHI_PROJECT_HEADER;
2027
2131
  exports.MUSHI_RADIUS = MUSHI_RADIUS;
2132
+ exports.MUSHI_REPORTER_STATUS = MUSHI_REPORTER_STATUS;
2028
2133
  exports.MUSHI_SDK_PACKAGE_HEADER = MUSHI_SDK_PACKAGE_HEADER;
2029
2134
  exports.MUSHI_SDK_VERSION_HEADER = MUSHI_SDK_VERSION_HEADER;
2030
2135
  exports.MUSHI_SPACING = MUSHI_SPACING;
2136
+ exports.MUSHI_TIER_COLORS = MUSHI_TIER_COLORS;
2031
2137
  exports.MUSHI_TYPE = MUSHI_TYPE;
2032
2138
  exports.MUSHI_USER_TOKEN_HEADER = MUSHI_USER_TOKEN_HEADER;
2033
2139
  exports.MUSHI_Z = MUSHI_Z;
@@ -2050,6 +2156,7 @@ exports.getDeviceFingerprintHash = getDeviceFingerprintHash;
2050
2156
  exports.getReporterToken = getReporterToken;
2051
2157
  exports.getSessionId = getSessionId;
2052
2158
  exports.githubRepoDomainHint = githubRepoDomainHint;
2159
+ exports.hmacSha256Hex = hmacSha256Hex;
2053
2160
  exports.isLikelyGenericFavicon = isLikelyGenericFavicon;
2054
2161
  exports.isUntrustedFaviconUrl = isUntrustedFaviconUrl;
2055
2162
  exports.mushiPalette = mushiPalette;
@@ -2067,6 +2174,9 @@ exports.resolveEnvConfig = resolveEnvConfig;
2067
2174
  exports.resolveProjectDomain = resolveProjectDomain;
2068
2175
  exports.resolveProjectFaviconDomains = resolveProjectFaviconDomains;
2069
2176
  exports.resolveRegionEndpoint = resolveRegionEndpoint;
2177
+ exports.resolveWidgetAccent = resolveWidgetAccent;
2178
+ exports.safeWidgetHex = safeWidgetHex;
2070
2179
  exports.scrubPii = scrubPii;
2180
+ exports.sha256Hex = sha256Hex;
2071
2181
  //# sourceMappingURL=index.cjs.map
2072
2182
  //# sourceMappingURL=index.cjs.map