@mushi-mushi/core 1.10.0 → 1.12.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/dist/index.d.cts CHANGED
@@ -552,6 +552,8 @@ interface MushiReport {
552
552
  timeline?: MushiTimelineEntry[];
553
553
  screenshotDataUrl?: string;
554
554
  selectedElement?: MushiSelectedElement;
555
+ /** rrweb / lite rolling-buffer events attached on submit when capture.replay is enabled. */
556
+ replayEvents?: unknown[];
555
557
  metadata?: Record<string, unknown>;
556
558
  sessionId?: string;
557
559
  reporterToken: string;
@@ -1081,6 +1083,19 @@ interface MushiSDKInstance {
1081
1083
  * Returns the newly created comment, or null on failure.
1082
1084
  */
1083
1085
  replyToReport(reportId: string, body: string): Promise<MushiReporterComment | null>;
1086
+ /**
1087
+ * Submit a structured feedback chip (confirms / not_fixed / …) on a report.
1088
+ * Drives the verify/reopen lifecycle when the report is in a fixed state.
1089
+ */
1090
+ submitFeedbackSignal(reportId: string, signal: string, note?: string): Promise<Record<string, unknown> | null>;
1091
+ /**
1092
+ * Reporter-initiated regression reopen with an optional note.
1093
+ */
1094
+ reopenReport(reportId: string, note?: string): Promise<Record<string, unknown> | null>;
1095
+ /**
1096
+ * Open the reporter inbox ("my reports") view in the widget.
1097
+ */
1098
+ openMyReports(): void;
1084
1099
  /**
1085
1100
  * Returns the global contributor hall-of-fame ranked by total points.
1086
1101
  * Safe to call without an authenticated user; uses public endpoint.
@@ -1147,8 +1162,32 @@ interface MushiApiClient {
1147
1162
  listReporterComments(reportId: string, reporterToken: string): Promise<MushiApiResponse<{
1148
1163
  comments: MushiReporterComment[];
1149
1164
  }>>;
1150
- replyToReporterReport(reportId: string, reporterToken: string, body: string): Promise<MushiApiResponse<{
1165
+ replyToReporterReport(reportId: string, reporterToken: string, body: string, feedbackSignal?: string): Promise<MushiApiResponse<{
1151
1166
  comment: MushiReporterComment;
1167
+ feedback?: Record<string, unknown>;
1168
+ }>>;
1169
+ reopenReporterReport(reportId: string, reporterToken: string, note?: string): Promise<MushiApiResponse<{
1170
+ outcome: Record<string, unknown>;
1171
+ }>>;
1172
+ /** List in-app notifications for the authenticated reporter. */
1173
+ listNotifications(reporterToken: string, opts?: {
1174
+ since?: string;
1175
+ limit?: number;
1176
+ }): Promise<MushiApiResponse<{
1177
+ notifications: Array<Record<string, unknown>>;
1178
+ }>>;
1179
+ /** Mark a single reporter notification as read. */
1180
+ markNotificationRead(notificationId: string, reporterToken: string): Promise<MushiApiResponse<{
1181
+ ok: boolean;
1182
+ }>>;
1183
+ /** List the reporter-facing feature board (public roadmap tickets). */
1184
+ listReporterFeatureBoard(reporterToken: string): Promise<MushiApiResponse<{
1185
+ tickets: Array<Record<string, unknown>>;
1186
+ }>>;
1187
+ /** Toggle the reporter's vote on a feature-board ticket. */
1188
+ voteReporterFeatureBoard(requestId: string, reporterToken: string): Promise<MushiApiResponse<{
1189
+ voted: boolean;
1190
+ action: string;
1152
1191
  }>>;
1153
1192
  /**
1154
1193
  * Submit a batch of activity events for the current user.
@@ -1253,6 +1292,10 @@ interface MushiReporterReport {
1253
1292
  created_at: string;
1254
1293
  last_admin_reply_at?: string | null;
1255
1294
  last_reporter_reply_at?: string | null;
1295
+ parent_report_id?: string | null;
1296
+ verified_at?: string | null;
1297
+ reopened_at?: string | null;
1298
+ regression_count?: number;
1256
1299
  unread_count?: number;
1257
1300
  }
1258
1301
  interface MushiReporterComment {
@@ -1497,6 +1540,31 @@ interface BreadcrumbBufferOptions {
1497
1540
  }
1498
1541
  declare function createBreadcrumbBuffer(options?: BreadcrumbBufferOptions): BreadcrumbBuffer;
1499
1542
 
1543
+ /**
1544
+ * Client-side payload size guards — prevents silent edge-function failures
1545
+ * when screenshots or log buffers inflate the report body past gateway limits.
1546
+ */
1547
+ /** Supabase edge functions tolerate ~6 MB; stay under 4 MB for headroom. */
1548
+ declare const MAX_REPORT_PAYLOAD_BYTES: number;
1549
+ /** Screenshot data URLs above this are downscaled or dropped before POST. */
1550
+ declare const MAX_SCREENSHOT_DATA_URL_BYTES: number;
1551
+ interface PayloadGuardResult {
1552
+ ok: boolean;
1553
+ bytes: number;
1554
+ maxBytes: number;
1555
+ reason?: string;
1556
+ /**
1557
+ * True when the payload could not be serialized at all (e.g. a circular
1558
+ * reference in `metadata`). This is a distinct failure from "too large" —
1559
+ * the caller should surface a `SERIALIZE_FAILED` rather than a misleading
1560
+ * "payload too large" message.
1561
+ */
1562
+ serializeFailed?: boolean;
1563
+ }
1564
+ declare function estimateJsonBytes(value: unknown): number;
1565
+ declare function checkReportPayloadSize(payload: unknown, maxBytes?: number): PayloadGuardResult;
1566
+ declare function formatBytes(n: number): string;
1567
+
1500
1568
  /**
1501
1569
  * Normalise *anything* a host might throw — `Error`, string, plain
1502
1570
  * object, `null`, frozen DOMException — into the shape Mushi reports
@@ -1581,4 +1649,4 @@ declare function createLogger(options: LoggerOptions): Logger;
1581
1649
  */
1582
1650
  declare const noopLogger: Logger;
1583
1651
 
1584
- export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
1652
+ export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MAX_REPORT_PAYLOAD_BYTES, MAX_SCREENSHOT_DATA_URL_BYTES, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PayloadGuardResult, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, checkReportPayloadSize, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, estimateJsonBytes, formatBytes, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
package/dist/index.d.ts CHANGED
@@ -552,6 +552,8 @@ interface MushiReport {
552
552
  timeline?: MushiTimelineEntry[];
553
553
  screenshotDataUrl?: string;
554
554
  selectedElement?: MushiSelectedElement;
555
+ /** rrweb / lite rolling-buffer events attached on submit when capture.replay is enabled. */
556
+ replayEvents?: unknown[];
555
557
  metadata?: Record<string, unknown>;
556
558
  sessionId?: string;
557
559
  reporterToken: string;
@@ -1081,6 +1083,19 @@ interface MushiSDKInstance {
1081
1083
  * Returns the newly created comment, or null on failure.
1082
1084
  */
1083
1085
  replyToReport(reportId: string, body: string): Promise<MushiReporterComment | null>;
1086
+ /**
1087
+ * Submit a structured feedback chip (confirms / not_fixed / …) on a report.
1088
+ * Drives the verify/reopen lifecycle when the report is in a fixed state.
1089
+ */
1090
+ submitFeedbackSignal(reportId: string, signal: string, note?: string): Promise<Record<string, unknown> | null>;
1091
+ /**
1092
+ * Reporter-initiated regression reopen with an optional note.
1093
+ */
1094
+ reopenReport(reportId: string, note?: string): Promise<Record<string, unknown> | null>;
1095
+ /**
1096
+ * Open the reporter inbox ("my reports") view in the widget.
1097
+ */
1098
+ openMyReports(): void;
1084
1099
  /**
1085
1100
  * Returns the global contributor hall-of-fame ranked by total points.
1086
1101
  * Safe to call without an authenticated user; uses public endpoint.
@@ -1147,8 +1162,32 @@ interface MushiApiClient {
1147
1162
  listReporterComments(reportId: string, reporterToken: string): Promise<MushiApiResponse<{
1148
1163
  comments: MushiReporterComment[];
1149
1164
  }>>;
1150
- replyToReporterReport(reportId: string, reporterToken: string, body: string): Promise<MushiApiResponse<{
1165
+ replyToReporterReport(reportId: string, reporterToken: string, body: string, feedbackSignal?: string): Promise<MushiApiResponse<{
1151
1166
  comment: MushiReporterComment;
1167
+ feedback?: Record<string, unknown>;
1168
+ }>>;
1169
+ reopenReporterReport(reportId: string, reporterToken: string, note?: string): Promise<MushiApiResponse<{
1170
+ outcome: Record<string, unknown>;
1171
+ }>>;
1172
+ /** List in-app notifications for the authenticated reporter. */
1173
+ listNotifications(reporterToken: string, opts?: {
1174
+ since?: string;
1175
+ limit?: number;
1176
+ }): Promise<MushiApiResponse<{
1177
+ notifications: Array<Record<string, unknown>>;
1178
+ }>>;
1179
+ /** Mark a single reporter notification as read. */
1180
+ markNotificationRead(notificationId: string, reporterToken: string): Promise<MushiApiResponse<{
1181
+ ok: boolean;
1182
+ }>>;
1183
+ /** List the reporter-facing feature board (public roadmap tickets). */
1184
+ listReporterFeatureBoard(reporterToken: string): Promise<MushiApiResponse<{
1185
+ tickets: Array<Record<string, unknown>>;
1186
+ }>>;
1187
+ /** Toggle the reporter's vote on a feature-board ticket. */
1188
+ voteReporterFeatureBoard(requestId: string, reporterToken: string): Promise<MushiApiResponse<{
1189
+ voted: boolean;
1190
+ action: string;
1152
1191
  }>>;
1153
1192
  /**
1154
1193
  * Submit a batch of activity events for the current user.
@@ -1253,6 +1292,10 @@ interface MushiReporterReport {
1253
1292
  created_at: string;
1254
1293
  last_admin_reply_at?: string | null;
1255
1294
  last_reporter_reply_at?: string | null;
1295
+ parent_report_id?: string | null;
1296
+ verified_at?: string | null;
1297
+ reopened_at?: string | null;
1298
+ regression_count?: number;
1256
1299
  unread_count?: number;
1257
1300
  }
1258
1301
  interface MushiReporterComment {
@@ -1497,6 +1540,31 @@ interface BreadcrumbBufferOptions {
1497
1540
  }
1498
1541
  declare function createBreadcrumbBuffer(options?: BreadcrumbBufferOptions): BreadcrumbBuffer;
1499
1542
 
1543
+ /**
1544
+ * Client-side payload size guards — prevents silent edge-function failures
1545
+ * when screenshots or log buffers inflate the report body past gateway limits.
1546
+ */
1547
+ /** Supabase edge functions tolerate ~6 MB; stay under 4 MB for headroom. */
1548
+ declare const MAX_REPORT_PAYLOAD_BYTES: number;
1549
+ /** Screenshot data URLs above this are downscaled or dropped before POST. */
1550
+ declare const MAX_SCREENSHOT_DATA_URL_BYTES: number;
1551
+ interface PayloadGuardResult {
1552
+ ok: boolean;
1553
+ bytes: number;
1554
+ maxBytes: number;
1555
+ reason?: string;
1556
+ /**
1557
+ * True when the payload could not be serialized at all (e.g. a circular
1558
+ * reference in `metadata`). This is a distinct failure from "too large" —
1559
+ * the caller should surface a `SERIALIZE_FAILED` rather than a misleading
1560
+ * "payload too large" message.
1561
+ */
1562
+ serializeFailed?: boolean;
1563
+ }
1564
+ declare function estimateJsonBytes(value: unknown): number;
1565
+ declare function checkReportPayloadSize(payload: unknown, maxBytes?: number): PayloadGuardResult;
1566
+ declare function formatBytes(n: number): string;
1567
+
1500
1568
  /**
1501
1569
  * Normalise *anything* a host might throw — `Error`, string, plain
1502
1570
  * object, `null`, frozen DOMException — into the shape Mushi reports
@@ -1581,4 +1649,4 @@ declare function createLogger(options: LoggerOptions): Logger;
1581
1649
  */
1582
1650
  declare const noopLogger: Logger;
1583
1651
 
1584
- export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
1652
+ export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MAX_REPORT_PAYLOAD_BYTES, MAX_SCREENSHOT_DATA_URL_BYTES, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PayloadGuardResult, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, checkReportPayloadSize, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, estimateJsonBytes, formatBytes, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
package/dist/index.js CHANGED
@@ -1,3 +1,45 @@
1
+ // src/payload-guard.ts
2
+ var MAX_REPORT_PAYLOAD_BYTES = 4 * 1024 * 1024;
3
+ var MAX_SCREENSHOT_DATA_URL_BYTES = 1.5 * 1024 * 1024;
4
+ function safeStringify(value) {
5
+ try {
6
+ return JSON.stringify(value);
7
+ } catch {
8
+ return null;
9
+ }
10
+ }
11
+ function estimateJsonBytes(value) {
12
+ const json = safeStringify(value);
13
+ return json === null ? Number.MAX_SAFE_INTEGER : new TextEncoder().encode(json).length;
14
+ }
15
+ function checkReportPayloadSize(payload, maxBytes = MAX_REPORT_PAYLOAD_BYTES) {
16
+ const json = safeStringify(payload);
17
+ if (json === null) {
18
+ return {
19
+ ok: false,
20
+ bytes: 0,
21
+ maxBytes,
22
+ serializeFailed: true,
23
+ reason: "Report could not be serialized (circular reference in metadata?)"
24
+ };
25
+ }
26
+ const bytes = new TextEncoder().encode(json).length;
27
+ if (bytes <= maxBytes) {
28
+ return { ok: true, bytes, maxBytes };
29
+ }
30
+ return {
31
+ ok: false,
32
+ bytes,
33
+ maxBytes,
34
+ reason: `Report payload ${formatBytes(bytes)} exceeds limit ${formatBytes(maxBytes)}`
35
+ };
36
+ }
37
+ function formatBytes(n) {
38
+ if (n < 1024) return `${n} B`;
39
+ if (n < 1024 * 1024) return `${(n / 1024).toFixed(1)} KB`;
40
+ return `${(n / (1024 * 1024)).toFixed(2)} MB`;
41
+ }
42
+
1
43
  // src/api-client.ts
2
44
  var DEFAULT_API_ENDPOINT = "https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api";
3
45
  var MUSHI_INTERNAL_HEADER = "X-Mushi-Internal";
@@ -107,6 +149,16 @@ function createApiClient(options) {
107
149
  }
108
150
  return {
109
151
  async submitReport(report) {
152
+ const guard = checkReportPayloadSize(report);
153
+ if (!guard.ok) {
154
+ return {
155
+ ok: false,
156
+ error: {
157
+ code: guard.serializeFailed ? "SERIALIZE_FAILED" : "PAYLOAD_TOO_LARGE",
158
+ message: guard.reason ?? "Report payload exceeds size limit"
159
+ }
160
+ };
161
+ }
110
162
  return request("POST", "/v1/reports", report, maxRetries, "report-submit");
111
163
  },
112
164
  async getReportStatus(reportId) {
@@ -138,12 +190,54 @@ function createApiClient(options) {
138
190
  reporterToken
139
191
  );
140
192
  },
141
- async replyToReporterReport(reportId, reporterToken, body) {
193
+ async replyToReporterReport(reportId, reporterToken, body, feedbackSignal) {
142
194
  return requestForReporter(
143
195
  "POST",
144
196
  `/v1/reporter/reports/${reportId}/reply`,
145
197
  reporterToken,
146
- { body }
198
+ { body, ...feedbackSignal ? { feedback_signal: feedbackSignal } : {} }
199
+ );
200
+ },
201
+ async reopenReporterReport(reportId, reporterToken, note) {
202
+ return requestForReporter(
203
+ "POST",
204
+ `/v1/reporter/reports/${reportId}/reopen`,
205
+ reporterToken,
206
+ { note: note ?? "" }
207
+ );
208
+ },
209
+ async listNotifications(reporterToken, opts) {
210
+ const qs = new URLSearchParams();
211
+ if (opts?.since) qs.set("since", opts.since);
212
+ if (opts?.limit) qs.set("limit", String(opts.limit));
213
+ const suffix = qs.size ? `?${qs.toString()}` : "";
214
+ return requestForReporter(
215
+ "GET",
216
+ `/v1/notifications${suffix}`,
217
+ reporterToken
218
+ );
219
+ },
220
+ async markNotificationRead(notificationId, reporterToken) {
221
+ return requestForReporter(
222
+ "POST",
223
+ `/v1/notifications/${notificationId}/read`,
224
+ reporterToken,
225
+ {}
226
+ );
227
+ },
228
+ async listReporterFeatureBoard(reporterToken) {
229
+ return requestForReporter(
230
+ "GET",
231
+ "/v1/reporter/feature-board",
232
+ reporterToken
233
+ );
234
+ },
235
+ async voteReporterFeatureBoard(requestId, reporterToken) {
236
+ return requestForReporter(
237
+ "POST",
238
+ `/v1/reporter/feature-board/${requestId}/vote`,
239
+ reporterToken,
240
+ {}
147
241
  );
148
242
  },
149
243
  // ─── Rewards program (P1) ──────────────────────────────────
@@ -788,7 +882,11 @@ function createOfflineQueue(config = {}) {
788
882
  }
789
883
  sent++;
790
884
  } else {
791
- const permanent = result.error?.code === "HTTP_400" || result.error?.code === "HTTP_422" || result.error?.code === "INGEST_ERROR" || result.error?.code === "VALIDATION_ERROR" || typeof result.error?.message === "string" && /invalid payload|description must be at least|validation/i.test(
885
+ const permanent = result.error?.code === "HTTP_400" || result.error?.code === "HTTP_413" || result.error?.code === "HTTP_422" || result.error?.code === "INGEST_ERROR" || result.error?.code === "VALIDATION_ERROR" || // A payload that exceeds the size guard will never shrink on its own;
886
+ // retrying re-serialises the multi-MB body every sync tick and wedges
887
+ // the queue (it matches neither permanent nor transient otherwise).
888
+ // SERIALIZE_FAILED (circular ref) is likewise unrecoverable on retry.
889
+ result.error?.code === "PAYLOAD_TOO_LARGE" || result.error?.code === "SERIALIZE_FAILED" || typeof result.error?.message === "string" && /invalid payload|description must be at least|validation/i.test(
792
890
  result.error.message
793
891
  );
794
892
  const transient = !permanent && (result.error?.code === "NETWORK_ERROR" || result.error?.code === "HTTP_403" || result.error?.code === "HTTP_429" || result.error?.code === "HTTP_502" || result.error?.code === "HTTP_503" || result.error?.code === "HTTP_504" || typeof result.error?.code === "string" && result.error.code.startsWith("HTTP_5"));
@@ -1328,6 +1426,6 @@ function normaliseThrown(thrown) {
1328
1426
  return { name: "Error", message: String(thrown) };
1329
1427
  }
1330
1428
 
1331
- export { DEFAULT_API_ENDPOINT, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, REGION_ENDPOINTS, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
1429
+ export { DEFAULT_API_ENDPOINT, MAX_REPORT_PAYLOAD_BYTES, MAX_SCREENSHOT_DATA_URL_BYTES, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, REGION_ENDPOINTS, captureEnvironment, checkReportPayloadSize, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, estimateJsonBytes, formatBytes, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
1332
1430
  //# sourceMappingURL=index.js.map
1333
1431
  //# sourceMappingURL=index.js.map