@mushi-mushi/core 1.13.0 → 1.14.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
@@ -39,7 +39,16 @@ interface MushiWidgetConfig {
39
39
  * banners. When set, these values win over `position` + numeric `inset`.
40
40
  */
41
41
  anchor?: MushiWidgetAnchor;
42
- theme?: 'auto' | 'light' | 'dark';
42
+ theme?: 'auto' | 'light' | 'dark' | 'inherit';
43
+ /**
44
+ * Override the widget's primary accent colour (default: vermillion #E03C2C).
45
+ * Must be a CSS colour value that has sufficient contrast against both light
46
+ * and dark widget backgrounds. The widget derives a wash + accessible ink
47
+ * colour automatically, so only the base colour is required.
48
+ */
49
+ accent?: string;
50
+ /** Explicit text colour on the accent surface. Auto-computed when omitted. */
51
+ accentText?: string;
43
52
  triggerText?: string;
44
53
  expandedTitle?: string;
45
54
  mode?: 'simple' | 'conversational';
@@ -73,7 +82,20 @@ interface MushiWidgetConfig {
73
82
  environments?: Partial<Record<'production' | 'staging' | 'development', 'always' | 'never' | 'manual'>>;
74
83
  /** Opt-in smart trigger behavior; planned to become the default in a later minor. */
75
84
  smartHide?: boolean | MushiWidgetSmartHideConfig;
76
- draggable?: boolean;
85
+ /**
86
+ * Allow the FAB to be dragged and repositioned by the user.
87
+ * - `true` — drag enabled, persisted to localStorage, snaps to nearest edge on release.
88
+ * - `false` — fixed position (default).
89
+ * - Object — fine-grained control:
90
+ * - `persist` save position per projectId (default true when draggable).
91
+ * - `snapToEdge` snap to the nearest left/right edge on release (default true).
92
+ * - `axis` constrain movement to one axis (`'x'`, `'y'`, or `'both'` default).
93
+ */
94
+ draggable?: boolean | {
95
+ persist?: boolean;
96
+ snapToEdge?: boolean;
97
+ axis?: 'both' | 'x' | 'y';
98
+ };
77
99
  /** Show the tiny "Powered by Mushi vX" footer inside the widget panel. */
78
100
  brandFooter?: boolean;
79
101
  /** How the widget should surface SDK freshness warnings. Defaults to auto. */
@@ -1299,6 +1321,38 @@ interface MushiApiClient {
1299
1321
  project_name: string;
1300
1322
  };
1301
1323
  }>>;
1324
+ /** Link the anonymous reporter_token_hash to the caller's mushi_testers row. */
1325
+ sendMagicLink(email: string): Promise<MushiApiResponse<{
1326
+ ok: boolean;
1327
+ }>>;
1328
+ linkReporterToken(reporterTokenHash: string, jwt: string): Promise<MushiApiResponse<{
1329
+ ok: boolean;
1330
+ linked: number;
1331
+ }>>;
1332
+ /** All reports filed by the signed-in tester, across all projects. */
1333
+ getCrossAppReports(jwt: string, opts?: {
1334
+ limit?: number;
1335
+ offset?: number;
1336
+ }): Promise<MushiApiResponse<{
1337
+ reports: MushiCrossAppReport[];
1338
+ }>>;
1339
+ /** The signed-in tester's global rank + points. */
1340
+ getMyReputation(jwt: string): Promise<MushiApiResponse<{
1341
+ reputation: MushiTesterReputation | null;
1342
+ }>>;
1343
+ /** Top-N global tester leaderboard (no auth required). */
1344
+ getPublicLeaderboard(limit?: number): Promise<MushiApiResponse<{
1345
+ leaderboard: MushiLeaderboardEntry[];
1346
+ }>>;
1347
+ /** Whether the caller has a mushi_testers row. */
1348
+ getTesterStatus(jwt: string): Promise<MushiApiResponse<{
1349
+ is_tester: boolean;
1350
+ tester: {
1351
+ id: string;
1352
+ public_handle: string | null;
1353
+ display_name: string | null;
1354
+ } | null;
1355
+ }>>;
1302
1356
  }
1303
1357
  /**
1304
1358
  * Wire shape of a single discovery event sent by the SDK to
@@ -1374,6 +1428,38 @@ interface MushiHallOfFameEntry {
1374
1428
  points_30d: number;
1375
1429
  total_points: number;
1376
1430
  }
1431
+ /** A report filed by the current tester, across any project. */
1432
+ interface MushiCrossAppReport {
1433
+ id: string;
1434
+ short_id: string | null;
1435
+ title: string | null;
1436
+ category: string;
1437
+ status: string;
1438
+ created_at: string;
1439
+ updated_at: string;
1440
+ project_id: string | null;
1441
+ app_name: string | null;
1442
+ app_slug: string | null;
1443
+ }
1444
+ /** A single entry in the global tester leaderboard. */
1445
+ interface MushiLeaderboardEntry {
1446
+ tester_id: string;
1447
+ public_handle: string | null;
1448
+ display_name: string | null;
1449
+ rank: number;
1450
+ points_30d: number;
1451
+ total_points: number;
1452
+ badge_slug?: string | null;
1453
+ }
1454
+ /** The caller's global reputation snapshot. */
1455
+ interface MushiTesterReputation {
1456
+ tester_id: string;
1457
+ public_handle: string | null;
1458
+ display_name: string | null;
1459
+ rank: number | null;
1460
+ points_30d: number;
1461
+ total_points: number;
1462
+ }
1377
1463
 
1378
1464
  interface ApiClientOptions {
1379
1465
  projectId: string;
@@ -1389,7 +1475,7 @@ interface ApiClientOptions {
1389
1475
  declare const DEFAULT_API_ENDPOINT = "https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api";
1390
1476
  declare const MUSHI_INTERNAL_HEADER = "X-Mushi-Internal";
1391
1477
  declare const MUSHI_INTERNAL_INIT_MARKER = "__mushiInternal";
1392
- type MushiInternalRequestKind = 'sdk-config' | 'report-submit' | 'report-status' | 'reporter-poll' | 'diagnose' | 'discovery';
1478
+ type MushiInternalRequestKind = 'sdk-config' | 'report-submit' | 'report-status' | 'reporter-poll' | 'diagnose' | 'discovery' | 'community';
1393
1479
  declare function createApiClient(options: ApiClientOptions): MushiApiClient;
1394
1480
 
1395
1481
  /**
@@ -1709,4 +1795,4 @@ declare function createLogger(options: LoggerOptions): Logger;
1709
1795
  */
1710
1796
  declare const noopLogger: Logger;
1711
1797
 
1712
- 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 MushiCustomCategory, 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 };
1798
+ 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 MushiCrossAppReport, type MushiCustomCategory, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiLeaderboardEntry, 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 MushiTesterReputation, 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
@@ -39,7 +39,16 @@ interface MushiWidgetConfig {
39
39
  * banners. When set, these values win over `position` + numeric `inset`.
40
40
  */
41
41
  anchor?: MushiWidgetAnchor;
42
- theme?: 'auto' | 'light' | 'dark';
42
+ theme?: 'auto' | 'light' | 'dark' | 'inherit';
43
+ /**
44
+ * Override the widget's primary accent colour (default: vermillion #E03C2C).
45
+ * Must be a CSS colour value that has sufficient contrast against both light
46
+ * and dark widget backgrounds. The widget derives a wash + accessible ink
47
+ * colour automatically, so only the base colour is required.
48
+ */
49
+ accent?: string;
50
+ /** Explicit text colour on the accent surface. Auto-computed when omitted. */
51
+ accentText?: string;
43
52
  triggerText?: string;
44
53
  expandedTitle?: string;
45
54
  mode?: 'simple' | 'conversational';
@@ -73,7 +82,20 @@ interface MushiWidgetConfig {
73
82
  environments?: Partial<Record<'production' | 'staging' | 'development', 'always' | 'never' | 'manual'>>;
74
83
  /** Opt-in smart trigger behavior; planned to become the default in a later minor. */
75
84
  smartHide?: boolean | MushiWidgetSmartHideConfig;
76
- draggable?: boolean;
85
+ /**
86
+ * Allow the FAB to be dragged and repositioned by the user.
87
+ * - `true` — drag enabled, persisted to localStorage, snaps to nearest edge on release.
88
+ * - `false` — fixed position (default).
89
+ * - Object — fine-grained control:
90
+ * - `persist` save position per projectId (default true when draggable).
91
+ * - `snapToEdge` snap to the nearest left/right edge on release (default true).
92
+ * - `axis` constrain movement to one axis (`'x'`, `'y'`, or `'both'` default).
93
+ */
94
+ draggable?: boolean | {
95
+ persist?: boolean;
96
+ snapToEdge?: boolean;
97
+ axis?: 'both' | 'x' | 'y';
98
+ };
77
99
  /** Show the tiny "Powered by Mushi vX" footer inside the widget panel. */
78
100
  brandFooter?: boolean;
79
101
  /** How the widget should surface SDK freshness warnings. Defaults to auto. */
@@ -1299,6 +1321,38 @@ interface MushiApiClient {
1299
1321
  project_name: string;
1300
1322
  };
1301
1323
  }>>;
1324
+ /** Link the anonymous reporter_token_hash to the caller's mushi_testers row. */
1325
+ sendMagicLink(email: string): Promise<MushiApiResponse<{
1326
+ ok: boolean;
1327
+ }>>;
1328
+ linkReporterToken(reporterTokenHash: string, jwt: string): Promise<MushiApiResponse<{
1329
+ ok: boolean;
1330
+ linked: number;
1331
+ }>>;
1332
+ /** All reports filed by the signed-in tester, across all projects. */
1333
+ getCrossAppReports(jwt: string, opts?: {
1334
+ limit?: number;
1335
+ offset?: number;
1336
+ }): Promise<MushiApiResponse<{
1337
+ reports: MushiCrossAppReport[];
1338
+ }>>;
1339
+ /** The signed-in tester's global rank + points. */
1340
+ getMyReputation(jwt: string): Promise<MushiApiResponse<{
1341
+ reputation: MushiTesterReputation | null;
1342
+ }>>;
1343
+ /** Top-N global tester leaderboard (no auth required). */
1344
+ getPublicLeaderboard(limit?: number): Promise<MushiApiResponse<{
1345
+ leaderboard: MushiLeaderboardEntry[];
1346
+ }>>;
1347
+ /** Whether the caller has a mushi_testers row. */
1348
+ getTesterStatus(jwt: string): Promise<MushiApiResponse<{
1349
+ is_tester: boolean;
1350
+ tester: {
1351
+ id: string;
1352
+ public_handle: string | null;
1353
+ display_name: string | null;
1354
+ } | null;
1355
+ }>>;
1302
1356
  }
1303
1357
  /**
1304
1358
  * Wire shape of a single discovery event sent by the SDK to
@@ -1374,6 +1428,38 @@ interface MushiHallOfFameEntry {
1374
1428
  points_30d: number;
1375
1429
  total_points: number;
1376
1430
  }
1431
+ /** A report filed by the current tester, across any project. */
1432
+ interface MushiCrossAppReport {
1433
+ id: string;
1434
+ short_id: string | null;
1435
+ title: string | null;
1436
+ category: string;
1437
+ status: string;
1438
+ created_at: string;
1439
+ updated_at: string;
1440
+ project_id: string | null;
1441
+ app_name: string | null;
1442
+ app_slug: string | null;
1443
+ }
1444
+ /** A single entry in the global tester leaderboard. */
1445
+ interface MushiLeaderboardEntry {
1446
+ tester_id: string;
1447
+ public_handle: string | null;
1448
+ display_name: string | null;
1449
+ rank: number;
1450
+ points_30d: number;
1451
+ total_points: number;
1452
+ badge_slug?: string | null;
1453
+ }
1454
+ /** The caller's global reputation snapshot. */
1455
+ interface MushiTesterReputation {
1456
+ tester_id: string;
1457
+ public_handle: string | null;
1458
+ display_name: string | null;
1459
+ rank: number | null;
1460
+ points_30d: number;
1461
+ total_points: number;
1462
+ }
1377
1463
 
1378
1464
  interface ApiClientOptions {
1379
1465
  projectId: string;
@@ -1389,7 +1475,7 @@ interface ApiClientOptions {
1389
1475
  declare const DEFAULT_API_ENDPOINT = "https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api";
1390
1476
  declare const MUSHI_INTERNAL_HEADER = "X-Mushi-Internal";
1391
1477
  declare const MUSHI_INTERNAL_INIT_MARKER = "__mushiInternal";
1392
- type MushiInternalRequestKind = 'sdk-config' | 'report-submit' | 'report-status' | 'reporter-poll' | 'diagnose' | 'discovery';
1478
+ type MushiInternalRequestKind = 'sdk-config' | 'report-submit' | 'report-status' | 'reporter-poll' | 'diagnose' | 'discovery' | 'community';
1393
1479
  declare function createApiClient(options: ApiClientOptions): MushiApiClient;
1394
1480
 
1395
1481
  /**
@@ -1709,4 +1795,4 @@ declare function createLogger(options: LoggerOptions): Logger;
1709
1795
  */
1710
1796
  declare const noopLogger: Logger;
1711
1797
 
1712
- 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 MushiCustomCategory, 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 };
1798
+ 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 MushiCrossAppReport, type MushiCustomCategory, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiLeaderboardEntry, 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 MushiTesterReputation, 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
@@ -55,7 +55,7 @@ function createApiClient(options) {
55
55
  maxRetries = DEFAULT_MAX_RETRIES
56
56
  } = options;
57
57
  let baseUrl = apiEndpoint.replace(/\/$/, "");
58
- async function request(method, path, body, retries = maxRetries, internalKind) {
58
+ async function request(method, path, body, retries = maxRetries, internalKind, extraHeaders) {
59
59
  const url = `${baseUrl}${path}`;
60
60
  const controller = new AbortController();
61
61
  const timer = setTimeout(() => controller.abort(), timeout);
@@ -66,7 +66,8 @@ function createApiClient(options) {
66
66
  "Content-Type": "application/json",
67
67
  "X-Mushi-Api-Key": apiKey,
68
68
  "X-Mushi-Project": projectId,
69
- ...internalKind ? { [MUSHI_INTERNAL_HEADER]: internalKind } : {}
69
+ ...internalKind ? { [MUSHI_INTERNAL_HEADER]: internalKind } : {},
70
+ ...extraHeaders
70
71
  },
71
72
  body: body ? JSON.stringify(body) : void 0,
72
73
  signal: controller.signal,
@@ -79,7 +80,7 @@ function createApiClient(options) {
79
80
  const targetBase = target.replace(/\/v1\/.*$/, "").replace(/\/$/, "");
80
81
  if (targetBase !== baseUrl) {
81
82
  baseUrl = targetBase;
82
- return request(method, path, body, retries - 1, internalKind);
83
+ return request(method, path, body, retries - 1, internalKind, extraHeaders);
83
84
  }
84
85
  }
85
86
  }
@@ -87,7 +88,7 @@ function createApiClient(options) {
87
88
  const errorBody = await response.json().catch(() => ({}));
88
89
  if (response.status >= 500 && retries > 0) {
89
90
  await sleep(getBackoffDelay(maxRetries - retries));
90
- return request(method, path, body, retries - 1, internalKind);
91
+ return request(method, path, body, retries - 1, internalKind, extraHeaders);
91
92
  }
92
93
  return {
93
94
  ok: false,
@@ -295,6 +296,69 @@ function createApiClient(options) {
295
296
  1,
296
297
  "reporter-poll"
297
298
  );
299
+ },
300
+ // ─── Cross-app community (in-widget tester identity) ──────────
301
+ async sendMagicLink(email) {
302
+ return request(
303
+ "POST",
304
+ "/v1/tester/magic-link",
305
+ { email },
306
+ 1,
307
+ "community"
308
+ );
309
+ },
310
+ async linkReporterToken(reporterTokenHash, jwt) {
311
+ return request(
312
+ "POST",
313
+ "/v1/tester/link-reporter",
314
+ { reporter_token_hash: reporterTokenHash },
315
+ 1,
316
+ "community",
317
+ { Authorization: `Bearer ${jwt}` }
318
+ );
319
+ },
320
+ async getCrossAppReports(jwt, opts) {
321
+ const qs = new URLSearchParams();
322
+ if (opts?.limit) qs.set("limit", String(opts.limit));
323
+ if (opts?.offset) qs.set("offset", String(opts.offset));
324
+ const suffix = qs.size ? `?${qs.toString()}` : "";
325
+ return request(
326
+ "GET",
327
+ `/v1/tester/cross-app-reports${suffix}`,
328
+ void 0,
329
+ 1,
330
+ "community",
331
+ { Authorization: `Bearer ${jwt}` }
332
+ );
333
+ },
334
+ async getMyReputation(jwt) {
335
+ return request(
336
+ "GET",
337
+ "/v1/tester/reputation",
338
+ void 0,
339
+ 1,
340
+ "community",
341
+ { Authorization: `Bearer ${jwt}` }
342
+ );
343
+ },
344
+ async getPublicLeaderboard(limit = 20) {
345
+ return request(
346
+ "GET",
347
+ `/v1/public/tester-leaderboard?limit=${limit}`,
348
+ void 0,
349
+ 1,
350
+ "reporter-poll"
351
+ );
352
+ },
353
+ async getTesterStatus(jwt) {
354
+ return request(
355
+ "GET",
356
+ "/v1/me/tester-status",
357
+ void 0,
358
+ 1,
359
+ "community",
360
+ { Authorization: `Bearer ${jwt}` }
361
+ );
298
362
  }
299
363
  };
300
364
  }