@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 +2 -2
- package/SECURITY.md +1 -1
- package/dist/index.cjs +142 -32
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +118 -7
- package/dist/index.d.ts +118 -7
- package/dist/index.js +132 -33
- package/dist/index.js.map +1 -1
- package/package.json +8 -5
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/
|
|
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
|
|
1385
|
-
function
|
|
1386
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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: "
|
|
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
|