@buoy-gg/sentry 0.0.0-stage → 7.0.77

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.
Files changed (113) hide show
  1. package/LICENSE +58 -0
  2. package/README.md +69 -2
  3. package/lib/commonjs/SentryRoot.js +1 -0
  4. package/lib/commonjs/audit/auditSource.js +1 -0
  5. package/lib/commonjs/audit/pii.js +1 -0
  6. package/lib/commonjs/audit/pii.test.js +1 -0
  7. package/lib/commonjs/audit/rules.js +1 -0
  8. package/lib/commonjs/audit/rules.test.js +1 -0
  9. package/lib/commonjs/capture/attach.js +1 -0
  10. package/lib/commonjs/capture/attach.test.js +1 -0
  11. package/lib/commonjs/capture/sentrySDK.js +1 -0
  12. package/lib/commonjs/capture/sentrySDK.web.js +1 -0
  13. package/lib/commonjs/components/SentryIcon.js +1 -0
  14. package/lib/commonjs/components/SentryIcon.native.js +1 -0
  15. package/lib/commonjs/components/SentryModal.js +1 -0
  16. package/lib/commonjs/devtools/SentryAuditView.js +1 -0
  17. package/lib/commonjs/devtools/SentryBody.js +1 -0
  18. package/lib/commonjs/devtools/SentryCostView.js +1 -0
  19. package/lib/commonjs/devtools/SentryDropsView.js +1 -0
  20. package/lib/commonjs/devtools/SentryHeader.js +1 -0
  21. package/lib/commonjs/devtools/SentryToolView.js +1 -0
  22. package/lib/commonjs/devtools/attachStatus.js +1 -0
  23. package/lib/commonjs/devtools/layout.js +1 -0
  24. package/lib/commonjs/devtools/useSentryController.js +1 -0
  25. package/lib/commonjs/drops/dropStore.js +1 -0
  26. package/lib/commonjs/drops/dropStore.test.js +1 -0
  27. package/lib/commonjs/drops/observe.js +1 -0
  28. package/lib/commonjs/drops/types.js +1 -0
  29. package/lib/commonjs/index.js +1 -0
  30. package/lib/commonjs/package.json +1 -0
  31. package/lib/commonjs/preset.js +1 -0
  32. package/lib/commonjs/quota/plans.js +1 -0
  33. package/lib/commonjs/quota/usage.js +1 -0
  34. package/lib/commonjs/quota/usage.test.js +1 -0
  35. package/lib/commonjs/store/sanitize.js +1 -0
  36. package/lib/commonjs/store/sentryEnvelopeStore.js +1 -0
  37. package/lib/commonjs/sync/sentrySyncAdapter.js +1 -0
  38. package/lib/commonjs/sync/sentrySyncAdapter.test.js +1 -0
  39. package/lib/commonjs/types.js +1 -0
  40. package/lib/module/SentryRoot.js +1 -0
  41. package/lib/module/audit/auditSource.js +1 -0
  42. package/lib/module/audit/pii.js +1 -0
  43. package/lib/module/audit/pii.test.js +1 -0
  44. package/lib/module/audit/rules.js +1 -0
  45. package/lib/module/audit/rules.test.js +1 -0
  46. package/lib/module/capture/attach.js +1 -0
  47. package/lib/module/capture/attach.test.js +1 -0
  48. package/lib/module/capture/sentrySDK.js +1 -0
  49. package/lib/module/capture/sentrySDK.web.js +1 -0
  50. package/lib/module/components/SentryIcon.js +1 -0
  51. package/lib/module/components/SentryIcon.native.js +1 -0
  52. package/lib/module/components/SentryModal.js +1 -0
  53. package/lib/module/devtools/SentryAuditView.js +1 -0
  54. package/lib/module/devtools/SentryBody.js +1 -0
  55. package/lib/module/devtools/SentryCostView.js +1 -0
  56. package/lib/module/devtools/SentryDropsView.js +1 -0
  57. package/lib/module/devtools/SentryHeader.js +1 -0
  58. package/lib/module/devtools/SentryToolView.js +1 -0
  59. package/lib/module/devtools/attachStatus.js +1 -0
  60. package/lib/module/devtools/layout.js +1 -0
  61. package/lib/module/devtools/useSentryController.js +1 -0
  62. package/lib/module/drops/dropStore.js +1 -0
  63. package/lib/module/drops/dropStore.test.js +1 -0
  64. package/lib/module/drops/observe.js +1 -0
  65. package/lib/module/drops/types.js +1 -0
  66. package/lib/module/index.js +1 -0
  67. package/lib/module/preset.js +1 -0
  68. package/lib/module/quota/plans.js +1 -0
  69. package/lib/module/quota/usage.js +1 -0
  70. package/lib/module/quota/usage.test.js +1 -0
  71. package/lib/module/store/sanitize.js +1 -0
  72. package/lib/module/store/sentryEnvelopeStore.js +1 -0
  73. package/lib/module/sync/sentrySyncAdapter.js +1 -0
  74. package/lib/module/sync/sentrySyncAdapter.test.js +1 -0
  75. package/lib/module/types.js +1 -0
  76. package/lib/typescript/SentryRoot.d.ts +17 -0
  77. package/lib/typescript/audit/auditSource.d.ts +18 -0
  78. package/lib/typescript/audit/pii.d.ts +32 -0
  79. package/lib/typescript/audit/pii.test.d.ts +8 -0
  80. package/lib/typescript/audit/rules.d.ts +57 -0
  81. package/lib/typescript/audit/rules.test.d.ts +7 -0
  82. package/lib/typescript/capture/attach.d.ts +18 -0
  83. package/lib/typescript/capture/attach.test.d.ts +8 -0
  84. package/lib/typescript/capture/sentrySDK.d.ts +4 -0
  85. package/lib/typescript/capture/sentrySDK.web.d.ts +4 -0
  86. package/lib/typescript/components/SentryIcon.d.ts +3 -0
  87. package/lib/typescript/components/SentryIcon.native.d.ts +3 -0
  88. package/lib/typescript/components/SentryModal.d.ts +16 -0
  89. package/lib/typescript/devtools/SentryAuditView.d.ts +19 -0
  90. package/lib/typescript/devtools/SentryBody.d.ts +15 -0
  91. package/lib/typescript/devtools/SentryCostView.d.ts +20 -0
  92. package/lib/typescript/devtools/SentryDropsView.d.ts +17 -0
  93. package/lib/typescript/devtools/SentryHeader.d.ts +21 -0
  94. package/lib/typescript/devtools/SentryToolView.d.ts +14 -0
  95. package/lib/typescript/devtools/attachStatus.d.ts +13 -0
  96. package/lib/typescript/devtools/layout.d.ts +16 -0
  97. package/lib/typescript/devtools/useSentryController.d.ts +69 -0
  98. package/lib/typescript/drops/dropStore.d.ts +48 -0
  99. package/lib/typescript/drops/dropStore.test.d.ts +7 -0
  100. package/lib/typescript/drops/observe.d.ts +33 -0
  101. package/lib/typescript/drops/types.d.ts +50 -0
  102. package/lib/typescript/index.d.ts +30 -0
  103. package/lib/typescript/preset.d.ts +36 -0
  104. package/lib/typescript/quota/plans.d.ts +37 -0
  105. package/lib/typescript/quota/usage.d.ts +56 -0
  106. package/lib/typescript/quota/usage.test.d.ts +8 -0
  107. package/lib/typescript/store/sanitize.d.ts +18 -0
  108. package/lib/typescript/store/sentryEnvelopeStore.d.ts +49 -0
  109. package/lib/typescript/sync/sentrySyncAdapter.d.ts +64 -0
  110. package/lib/typescript/sync/sentrySyncAdapter.test.d.ts +2 -0
  111. package/lib/typescript/types.d.ts +61 -0
  112. package/lib/web/index.mjs +1 -0
  113. package/package.json +99 -3
package/LICENSE ADDED
@@ -0,0 +1,58 @@
1
+ PROPRIETARY SOFTWARE LICENSE
2
+
3
+ Copyright (c) 2024-present Buoy. All rights reserved.
4
+
5
+ This software and its source code are proprietary and confidential.
6
+
7
+ NOTICE: This is NOT open source software. This software is licensed,
8
+ not sold, and is protected by copyright laws and international treaties.
9
+
10
+ TERMS AND CONDITIONS:
11
+
12
+ 1. LICENSE GRANT
13
+ Subject to the terms of this Agreement and payment of applicable fees,
14
+ Buoy grants you a limited, non-exclusive, non-transferable license
15
+ to use the compiled software packages in your applications.
16
+
17
+ 2. RESTRICTIONS
18
+ You may NOT:
19
+ - Copy, modify, or distribute the source code
20
+ - Reverse engineer, decompile, or disassemble the software
21
+ - Remove or alter any proprietary notices or labels
22
+ - Sublicense, rent, lease, or lend the software
23
+ - Use the software to create competing products
24
+ - Share access credentials with unauthorized parties
25
+
26
+ 3. OWNERSHIP
27
+ React Buoy retains all right, title, and interest in the software,
28
+ including all intellectual property rights. This license does not
29
+ grant you any rights to trademarks or service marks.
30
+
31
+ 4. TERMINATION
32
+ This license is effective until terminated. Your rights under this
33
+ license will terminate automatically without notice if you fail to
34
+ comply with any of its terms. Upon termination, you must cease all
35
+ use and destroy all copies of the software.
36
+
37
+ 5. DISCLAIMER OF WARRANTIES
38
+ THE SOFTWARE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
39
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
40
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, AND NONINFRINGEMENT.
41
+
42
+ 6. LIMITATION OF LIABILITY
43
+ IN NO EVENT SHALL BUOY BE LIABLE FOR ANY INDIRECT, INCIDENTAL,
44
+ SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES ARISING OUT OF OR IN
45
+ CONNECTION WITH THIS LICENSE OR THE USE OF THE SOFTWARE.
46
+
47
+ 7. GOVERNING LAW
48
+ This Agreement shall be governed by and construed in accordance with
49
+ the laws of the United States, without regard to its conflict of
50
+ law provisions.
51
+
52
+ For licensing inquiries and subscription information:
53
+ - Website: https://buoy.gg
54
+ - Email: AustinLovesWorking@gmail.com
55
+
56
+ Unauthorized reproduction or distribution of this software, or any
57
+ portion of it, may result in severe civil and criminal penalties,
58
+ and will be prosecuted to the maximum extent possible under the law.
package/README.md CHANGED
@@ -1,3 +1,70 @@
1
- # Temporary Holding Version
1
+ # @buoy-gg/sentry
2
2
 
3
- This version is a temporary placeholder for this package. An operational version to replace this has been submitted for review and is awaiting a staged release.
3
+ Inspect Sentry envelopes observed in your React Native app, including item types, approximate serialized sizes, and captured payloads. The tool also provides usage estimates, drop diagnostics, and configuration checks.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install @buoy-gg/core @buoy-gg/sentry
9
+ ```
10
+
11
+ Your app needs a configured, compatible `@sentry/react-native` SDK. Follow that SDK's installation requirements; Buoy does not configure Sentry for you. The Sentry peer is optional so the tool can report an absent SDK.
12
+
13
+ ## Account setup
14
+
15
+ Start in a development build. You need a Free or Pro Buoy account. Sign in from your app's folder:
16
+
17
+ ```bash
18
+ npx --package=@buoy-gg/core buoy login
19
+ ```
20
+
21
+ Your browser opens buoy.gg. Click Allow. The CLI then writes a dev token. It works in dev builds for 30 days.
22
+
23
+ On Expo, the token goes in `.env.development.local`. Buoy reads it by itself in dev builds. You can also pass it in yourself:
24
+
25
+ ```tsx
26
+ import { Buoy } from "@buoy-gg/core";
27
+
28
+ Buoy.init({ licenseKey: process.env.EXPO_PUBLIC_BUOY_KEY });
29
+ ```
30
+
31
+ On React Native CLI, the token goes in `.env.local` as `BUOY_KEY`. React Native does not load that file by itself. Pass the token in with your app's own env setup. Keep the menu inside the providers used by your app. Restart the development server after installing packages. See the [Quick Start](https://buoy.gg/buoy/latest/docs/quick-start) for the complete root component.
32
+
33
+ ## Attach to your client
34
+
35
+ Keep your existing Sentry.init configuration. Mount the following inside your app root after initializing Buoy. Explicitly passing your client's getter is useful when Metro cannot resolve the same SDK instance:
36
+
37
+ ```tsx
38
+ import { FloatingDevTools } from "@buoy-gg/core";
39
+ import { sentryToolPreset, SentryRoot } from "@buoy-gg/sentry";
40
+ import * as Sentry from "@sentry/react-native";
41
+
42
+ <>
43
+ <SentryRoot getClient={Sentry.getClient} />
44
+ <FloatingDevTools apps={[sentryToolPreset]} />
45
+ </>;
46
+ ```
47
+
48
+ In a test Sentry project, send a recognizable test event after capture and account access are ready. Find the envelope in Buoy, inspect its items, and compare it with the event received by Sentry.
49
+
50
+ ## What the results mean
51
+
52
+ The JavaScript beforeEnvelope hook observes a supported client's outgoing envelopes without intentionally changing their payloads or send behavior. It cannot recover envelopes emitted before attachment. Native-only traffic and provider-side outcomes require their own evidence; a captured envelope does not prove delivery or ingestion.
53
+
54
+ Sizes and usage projections are estimates based on observed data and the configured model. They are not an invoice or a guarantee of quota consumption. Check current Sentry billing and project settings before making a cost decision.
55
+
56
+ Drop diagnostics and audit findings depend on available signals. Read a finding's explanation and verify it against your SDK version and configuration. See the [Sentry guide](https://buoy.gg/buoy/latest/docs/tools/sentry) for capture paths and diagnostic limits.
57
+
58
+ ## Desktop and MCP
59
+
60
+ React Native connections require `@buoy-gg/external-sync`. Follow the [Desktop connection guide](https://buoy.gg/buoy/latest/docs/desktop), sign in to Desktop separately, and confirm the selected device. [MCP](https://buoy.gg/buoy/latest/docs/mcp) uses the sign-in from `buoy login` on your computer. Free has the basic MCP. Reading this tool from the MCP needs Pro.
61
+
62
+ Device data can travel over your LAN to the configured broker. Account validation makes network requests. See [Telemetry](https://buoy.gg/buoy/latest/docs/telemetry) for data-flow details.
63
+
64
+ ## License
65
+
66
+ MIT. Buoy account and feature requirements still apply to the surrounding tools.
67
+
68
+ ## Web support (unreleased)
69
+
70
+ Pass the existing browser SDK’s getClient through the host’s sentryGetClient prop. Envelope capture and diagnostic panels use the shared implementation. The browser build is available in this checkout and has not been published yet. See the [web setup guide](https://buoy.gg/buoy/latest/docs/web-preview) for registration, dependencies, and browser boundaries.
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryRoot=SentryRoot;var _react=require("react");var _attach=require("./capture/attach");function SentryRoot({getClient:e}={}){(0,_react.useEffect)(()=>{(0,_attach.installSentryCapture)(e?{getClient:e}:{})},[e]);return null}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.readAuditInput=readAuditInput;exports.setAuditSource=setAuditSource;let client=null;function setAuditSource(t){client=t??null}function integrationNames(t){try{const e=t._integrations;return e?Object.keys(e):[]}catch{return[]}}function readAuditInput(){if(!client)return null;try{const t=client.getOptions?.();if(!t)return null;return{options:{...t},integrations:integrationNames(client),isDev:typeof __DEV__!=="undefined"&&__DEV__}}catch{return null}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.PII_KIND_LABEL=void 0;exports.scanForPii=scanForPii;const EMAIL=/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;const JWT=/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]+/;const BEARER=/\bBearer\s+[A-Za-z0-9._\-+/=]{12,}/i;const CARD=/\b(?:\d[ -]?){13,16}\b/;function passesLuhn(o){let e=0;let t=false;for(let r=o.length-1;r>=0;r--){let i=o.charCodeAt(r)-48;if(i<0||i>9)return false;if(t){i*=2;if(i>9)i-=9}e+=i;t=!t}return e%10===0}const CARD_IIN=/^(?:4|5[1-5]|2[2-7]|3[47]|3(?:0[0-5]|[68])|6(?:011|5|4[4-9]))/;const PHONE=/\+\d{1,3}[\s-]?\(?\d{2,4}\)?[\s-]?\d{3,4}[\s-]?\d{3,4}\b/;const SENSITIVE_KEYS=/^(authorization|cookie|set-cookie|x-api-key|api[-_]?key|password|passwd|secret|token|access[-_]?token|refresh[-_]?token|session[-_]?id|ssn)$/i;const COORD_KEYS=/^(lat|latitude|lng|lon|longitude)$/i;const SKIP_PATHS=/(^|\.)(event_id|trace_id|span_id|parent_span_id|dsn|sdk\.|debug_meta|modules)/;const MAX_DEPTH=8;function redact(o){const e=o.trim();if(e.length<=8)return`${e.slice(0,2)}\u2026`;return`${e.slice(0,4)}\u2026${e.slice(-2)}`}function classify(o,e){if(JWT.test(e)||BEARER.test(e))return"auth-token";if(SENSITIVE_KEYS.test(o))return"sensitive-key";if(EMAIL.test(e))return"email";const t=CARD.exec(e);if(t){const r=t[0].replace(/[ -]/g,"");if(r.length>=13&&CARD_IIN.test(r)&&passesLuhn(r)){return"credit-card"}}if(PHONE.test(e))return"phone";return null}function scanForPii(o,e=25){const t=[];const r=new WeakSet;const i=(n,c,f)=>{if(t.length>=e||f>MAX_DEPTH)return;if(n===null||n===void 0)return;if(typeof n==="number"){const s=c.split(".").pop()??"";if(COORD_KEYS.test(s)){t.push({kind:"coordinates",path:c,sample:redact(String(n))})}return}if(typeof n==="string"){if(SKIP_PATHS.test(c))return;const s=c.split(".").pop()??"";const d=classify(s,n);if(d)t.push({kind:d,path:c,sample:redact(n)});return}if(typeof n!=="object")return;const u=n;if(r.has(u))return;r.add(u);if(Array.isArray(n)){for(let s=0;s<n.length&&t.length<e;s++){i(n[s],`${c}[${s}]`,f+1)}return}for(const[s,d]of Object.entries(u)){if(t.length>=e)return;i(d,c?`${c}.${s}`:s,f+1)}};i(o,"",0);return t}const PII_KIND_LABEL=exports.PII_KIND_LABEL={email:"Email address","auth-token":"Auth token","credit-card":"Card number",phone:"Phone number",coordinates:"Location","sensitive-key":"Sensitive field"};
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest");var _pii=require("./pii");const kinds=e=>(0,_pii.scanForPii)(e).map(t=>t.kind);const paths=e=>(0,_pii.scanForPii)(e).map(t=>t.path);function luhn(e){let t=0;let a=false;for(let n=e.length-1;n>=0;n--){let i=e.charCodeAt(n)-48;if(a){i*=2;if(i>9)i-=9}t+=i;a=!a}return t%10===0}(0,_vitest.describe)("scanForPii \u2014 what it finds",()=>{(0,_vitest.it)("finds an email and names the path to fix",()=>{const e=(0,_pii.scanForPii)({user:{email:"ada@example.com"}});(0,_vitest.expect)(e[0].kind).toBe("email");(0,_vitest.expect)(e[0].path).toBe("user.email")});(0,_vitest.it)("finds a JWT and a bearer header",()=>{(0,_vitest.expect)(kinds({token:"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.abcdefghijk"})).toContain("auth-token");(0,_vitest.expect)(kinds({note:"Bearer sk_live_ABCDEFGHIJKLMNOP"})).toContain("auth-token")});(0,_vitest.it)("flags a sensitive key by its NAME, whatever the value looks like",()=>{(0,_vitest.expect)(kinds({password:"hunter2"})).toEqual(["sensitive-key"]);(0,_vitest.expect)(kinds({headers:{Cookie:"sid=1"}})).toEqual(["sensitive-key"])});(0,_vitest.it)("finds a card number and an international phone number",()=>{(0,_vitest.expect)(kinds({card:"4111 1111 1111 1111"})).toContain("credit-card");(0,_vitest.expect)(kinds({contact:"+1 415 555 0132"})).toContain("phone")});(0,_vitest.it)("finds coordinates by key name",()=>{(0,_vitest.expect)(kinds({latitude:51.5074})).toContain("coordinates")});(0,_vitest.it)("walks nested objects and arrays",()=>{(0,_vitest.expect)(paths({a:{b:[{email:"x@y.co"}]}})).toEqual(["a.b[0].email"])})});(0,_vitest.describe)("scanForPii \u2014 what it must NOT flag",()=>{(0,_vitest.it)("ignores Sentry's own ids and DSN, which naive patterns match",()=>{(0,_vitest.expect)((0,_pii.scanForPii)({event_id:"b6154766b46446329f13fc9cf50e75f0",trace_id:"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",dsn:"https://abc123@o447951.ingest.sentry.io/5428561"})).toEqual([])});(0,_vitest.it)("ignores ordinary numbers that are not coordinates",()=>{(0,_vitest.expect)((0,_pii.scanForPii)({count:42,timestamp:1788325151403})).toEqual([])});(0,_vitest.it)("ignores a bare long number that is not card-shaped",()=>{(0,_vitest.expect)((0,_pii.scanForPii)({note:"order 12345"})).toEqual([])});(0,_vitest.it)("ignores a millisecond timestamp, which is 13 digits like a card",()=>{(0,_vitest.expect)((0,_pii.scanForPii)({note:"timeout after 1788325151403"})).toEqual([]);(0,_vitest.expect)((0,_pii.scanForPii)({note:"1788325151403"})).toEqual([])});(0,_vitest.it)("ignores an epoch timestamp that happens to satisfy Luhn",()=>{(0,_vitest.expect)(luhn("1756934567807")).toBe(true);(0,_vitest.expect)((0,_pii.scanForPii)({note:"timeout after 1756934567807"})).toEqual([]);(0,_vitest.expect)((0,_pii.scanForPii)({note:"1756934567807"})).toEqual([])});(0,_vitest.it)("still catches a real card number, which satisfies Luhn",()=>{(0,_vitest.expect)(kinds({note:"4111111111111111"})).toContain("credit-card")});(0,_vitest.it)("catches the other issuers, not only Visa",()=>{(0,_vitest.expect)(kinds({note:"5555555555554444"})).toContain("credit-card");(0,_vitest.expect)(kinds({note:"378282246310005"})).toContain("credit-card");(0,_vitest.expect)(kinds({note:"6011111111111117"})).toContain("credit-card")})});(0,_vitest.describe)("scanForPii \u2014 safety properties",()=>{(0,_vitest.it)("never stores the value it found",()=>{const e="ada.lovelace@analyticalengine.org";const[t]=(0,_pii.scanForPii)({email:e});(0,_vitest.expect)(t.sample).not.toContain("lovelace");(0,_vitest.expect)(t.sample).not.toBe(e);(0,_vitest.expect)(t.sample.startsWith("ada.")).toBe(true)});(0,_vitest.it)("redacts even a short value",()=>{const[e]=(0,_pii.scanForPii)({password:"abc"});(0,_vitest.expect)(e.sample).not.toBe("abc")});(0,_vitest.it)("survives a cycle instead of hanging",()=>{const e={email:"a@b.co"};e.self=e;(0,_vitest.expect)(kinds(e)).toEqual(["email"])});(0,_vitest.it)("caps the number of findings so one payload cannot flood the panel",()=>{const e=Object.fromEntries(Array.from({length:100},(t,a)=>[`email${a}`,`user${a}@example.com`]));(0,_vitest.expect)((0,_pii.scanForPii)(e,25)).toHaveLength(25)});(0,_vitest.it)("returns nothing for empty or primitive payloads",()=>{(0,_vitest.expect)((0,_pii.scanForPii)(null)).toEqual([]);(0,_vitest.expect)((0,_pii.scanForPii)(void 0)).toEqual([]);(0,_vitest.expect)((0,_pii.scanForPii)({})).toEqual([])})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.auditConfig=auditConfig;exports.worstSeverity=worstSeverity;const num=a=>typeof a==="number"&&Number.isFinite(a)?a:null;function auditConfig(a){const{options:e,isDev:s}=a;const o=[];const t=d=>o.push(d);if(!e.dsn){t({id:"no-dsn",severity:"critical",category:"correctness",title:"No DSN",detail:"The SDK is initialized without a DSN, so nothing is sent anywhere. Usually an env var that didn't reach the bundle."})}if(!e.release||!e.dist){t({id:"release-dist",severity:"warning",category:"correctness",title:"release or dist not set explicitly",detail:"Stack traces are only symbolicated when release and dist match the source maps you uploaded, exactly. Sentry never reprocesses old events, so a mismatch means minified traces forever \u2014 set both explicitly and use the same values at upload."})}if(e.debug===true&&!s){t({id:"debug-in-release",severity:"warning",category:"correctness",title:"debug is on in a release build",detail:"Verbose SDK logging is shipping to users. Gate it: debug: __DEV__."})}if(e.enableNative===false){t({id:"native-disabled",severity:"warning",category:"correctness",title:"Native layer disabled",detail:"enableNative: false gives up native crash capture, offline caching, and release-health sessions \u2014 hard crashes will never be reported."})}const i=num(e.tracesSampleRate);if(i!==null&&i>=1&&!s){t({id:"traces-full",severity:"critical",category:"quota",title:"tracesSampleRate is 1.0 in production",detail:"Every transaction is sent, and spans are billed individually \u2014 this is the fastest way to exhaust a span quota. Lower the rate, or use tracesSampler to keep full detail only on the routes you care about."})}else if(i!==null&&i>.2&&!s){t({id:"traces-high",severity:"warning",category:"quota",title:`tracesSampleRate is ${i}`,detail:"Spans are billed per span, so tracing volume scales with this rate times the spans each transaction carries. Check the Cost tab before shipping it."})}const r=num(e.replaysSessionSampleRate);if(r!==null&&r>.01&&!s){t({id:"replay-session-rate",severity:"critical",category:"quota",title:`replaysSessionSampleRate is ${r}`,detail:"Replays are billed per session and free plans include only 50 a month, so anything above a fraction of a percent burns the quota on a real user base. Prefer replaysOnErrorSampleRate, which records only sessions that hit an error."})}if(e.attachScreenshot===true&&e.attachViewHierarchy===true){t({id:"heavy-attachments",severity:"warning",category:"quota",title:"Screenshots and view hierarchies on every error",detail:"Both attachments ride every error event and are billed by volume. Keep the one you actually open when debugging."})}if(e.enableLogs===true&&e.enableAutoConsoleLogs!==false){t({id:"auto-console-logs",severity:"info",category:"quota",title:"Console output is forwarded as logs",detail:"Every console.* call becomes billable log volume. Fine if your app is quiet; expensive if it logs in a render or a loop."})}const l=num(e.profilesSampleRate);if(l!==null&&l>0){t({id:"profiling-on",severity:"info",category:"quota",title:"Profiling is enabled",detail:"Profiling is billed by the hour and free plans cannot use it at all \u2014 profiles sent from a free-plan app are simply discarded."})}if(e.sendDefaultPii===true){t({id:"send-default-pii",severity:"critical",category:"privacy",title:"sendDefaultPii is on",detail:"The SDK attaches identifying data \u2014 IP address, and on some versions request headers including Authorization and Cookie \u2014 to every event. Turn it off unless you have a reason and a data-retention policy that covers it."})}const c=num(e.replaysOnErrorSampleRate);if(r!==null&&r>0||c!==null&&c>0){t({id:"replay-masking",severity:"info",category:"privacy",title:"Session Replay is recording",detail:"Replay captures the screen. Confirm masking covers every field showing personal data \u2014 the defaults mask text and images, and a custom unmasked view opts out of that."})}const n=num(e.maxBreadcrumbs);if(n!==null&&n>100){t({id:"many-breadcrumbs",severity:"info",category:"privacy",title:`maxBreadcrumbs is ${n}`,detail:"Breadcrumbs accumulate and ride every event, growing both payload size and the chance that something logged along the way is personal data."})}return o}function worstSeverity(a){if(a.some(e=>e.severity==="critical"))return"critical";if(a.some(e=>e.severity==="warning"))return"warning";if(a.length>0)return"info";return null}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest");var _rules=require("./rules");const input=(e,t={})=>({options:{dsn:"https://k@o0.ingest.sentry.io/1",release:"app@1.0.0",dist:"1",...e},integrations:[],isDev:false,...t});const ids=e=>(0,_rules.auditConfig)(e).map(t=>t.id);(0,_vitest.describe)("auditConfig \u2014 correctness",()=>{(0,_vitest.it)("flags a missing DSN as critical, because nothing is sent at all",()=>{const e=(0,_rules.auditConfig)(input({dsn:void 0}));const t=e.find(a=>a.id==="no-dsn");(0,_vitest.expect)(t?.severity).toBe("critical")});(0,_vitest.it)("flags release or dist left unset \u2014 source maps will never match",()=>{(0,_vitest.expect)(ids(input({release:void 0}))).toContain("release-dist");(0,_vitest.expect)(ids(input({dist:void 0}))).toContain("release-dist");(0,_vitest.expect)(ids(input({}))).not.toContain("release-dist")});(0,_vitest.it)("flags debug left on in a release build, but not in dev",()=>{(0,_vitest.expect)(ids(input({debug:true}))).toContain("debug-in-release");(0,_vitest.expect)(ids(input({debug:true},{isDev:true}))).not.toContain("debug-in-release")});(0,_vitest.it)("flags a disabled native layer \u2014 hard crashes would go unreported",()=>{(0,_vitest.expect)(ids(input({enableNative:false}))).toContain("native-disabled")})});(0,_vitest.describe)("auditConfig \u2014 quota",()=>{(0,_vitest.it)("flags full tracing in production as critical",()=>{const e=(0,_rules.auditConfig)(input({tracesSampleRate:1})).find(t=>t.id==="traces-full");(0,_vitest.expect)(e?.severity).toBe("critical");(0,_vitest.expect)(e?.category).toBe("quota")});(0,_vitest.it)("does not flag full tracing in a dev build, where volume is irrelevant",()=>{(0,_vitest.expect)(ids(input({tracesSampleRate:1},{isDev:true}))).not.toContain("traces-full")});(0,_vitest.it)("warns on a merely high trace rate, separately from a full one",()=>{const e=ids(input({tracesSampleRate:.5}));(0,_vitest.expect)(e).toContain("traces-high");(0,_vitest.expect)(e).not.toContain("traces-full")});(0,_vitest.it)("leaves a modest trace rate alone",()=>{(0,_vitest.expect)(ids(input({tracesSampleRate:.1}))).not.toContain("traces-high")});(0,_vitest.it)("flags session replay sampling above a fraction of a percent",()=>{(0,_vitest.expect)(ids(input({replaysSessionSampleRate:.1}))).toContain("replay-session-rate");(0,_vitest.expect)(ids(input({replaysSessionSampleRate:.005}))).not.toContain("replay-session-rate")});(0,_vitest.it)("flags screenshots and view hierarchies riding every error together",()=>{(0,_vitest.expect)(ids(input({attachScreenshot:true,attachViewHierarchy:true}))).toContain("heavy-attachments");(0,_vitest.expect)(ids(input({attachScreenshot:true}))).not.toContain("heavy-attachments")});(0,_vitest.it)("notes auto console logging, and respects an explicit opt-out",()=>{(0,_vitest.expect)(ids(input({enableLogs:true}))).toContain("auto-console-logs");(0,_vitest.expect)(ids(input({enableLogs:true,enableAutoConsoleLogs:false}))).not.toContain("auto-console-logs")});(0,_vitest.it)("notes profiling, which free plans cannot use at all",()=>{(0,_vitest.expect)(ids(input({profilesSampleRate:.1}))).toContain("profiling-on");(0,_vitest.expect)(ids(input({profilesSampleRate:0}))).not.toContain("profiling-on")})});(0,_vitest.describe)("auditConfig \u2014 privacy",()=>{(0,_vitest.it)("flags sendDefaultPii as critical",()=>{const e=(0,_rules.auditConfig)(input({sendDefaultPii:true})).find(t=>t.id==="send-default-pii");(0,_vitest.expect)(e?.severity).toBe("critical");(0,_vitest.expect)(e?.category).toBe("privacy")});(0,_vitest.it)("raises masking as a question whenever replay records at all",()=>{(0,_vitest.expect)(ids(input({replaysOnErrorSampleRate:1}))).toContain("replay-masking");(0,_vitest.expect)(ids(input({replaysSessionSampleRate:.001}))).toContain("replay-masking");(0,_vitest.expect)(ids(input({}))).not.toContain("replay-masking")});(0,_vitest.it)("notes an unusually large breadcrumb buffer",()=>{(0,_vitest.expect)(ids(input({maxBreadcrumbs:300}))).toContain("many-breadcrumbs");(0,_vitest.expect)(ids(input({maxBreadcrumbs:100}))).not.toContain("many-breadcrumbs")})});(0,_vitest.describe)("auditConfig \u2014 a clean config",()=>{(0,_vitest.it)("says nothing about a sensible production setup",()=>{(0,_vitest.expect)((0,_rules.auditConfig)(input({tracesSampleRate:.1,sampleRate:1,sendDefaultPii:false,debug:false}))).toEqual([])})});(0,_vitest.describe)("worstSeverity",()=>{(0,_vitest.it)("reports the most severe finding present",()=>{const e=(0,_rules.auditConfig)(input({sendDefaultPii:true,maxBreadcrumbs:300}));(0,_vitest.expect)((0,_rules.worstSeverity)(e)).toBe("critical")});(0,_vitest.it)("is null when there is nothing to report",()=>{(0,_vitest.expect)((0,_rules.worstSeverity)([])).toBeNull()})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.attachToClient=attachToClient;exports.installSentryCapture=installSentryCapture;exports.parseEnvelope=parseEnvelope;var _sentrySDK=require("./sentrySDK");var _sharedUi=require("@buoy-gg/shared-ui");var _sanitize=require("../store/sanitize");var _sentryEnvelopeStore=require("../store/sentryEnvelopeStore");var _observe=require("../drops/observe");var _auditSource=require("../audit/auditSource");const SIZE_WALK_LIMIT=8*1024*1024;const ATTACH_RETRY_MS=500;const MAX_ATTACH_TRIES=60;function isTypedArray(e){return typeof e==="object"&&e!==null&&typeof e.byteLength==="number"&&ArrayBuffer.isView(e)}function payloadBytes(e){if(typeof e==="string")return e.length;if(isTypedArray(e))return e.byteLength;return(0,_sharedUi.approxJsonSize)(e,SIZE_WALK_LIMIT).bytes}function firstString(...e){for(const n of e){if(typeof n==="string"&&n.length>0)return n}return void 0}function summarize(e,n){const t=n;try{switch(e){case"event":{const r=t?.exception?.values?.[0];if(r){const a=firstString(r.value,r.type)??"exception";return r.type&&r.value?`${r.type}: ${r.value}`:a}const s=firstString(t?.message?.formatted,t?.message,t?.logentry?.message);if(s)return s;if(t?.type==="feedback")return"user feedback";return firstString(t?.transaction)??"event"}case"transaction":{return firstString(t?.transaction)??"transaction"}case"session":return firstString(t?.status)??"session";case"sessions":return"session aggregates";case"client_report":{const r=Array.isArray(t?.discarded_events)?t.discarded_events.reduce((s,a)=>s+(a?.quantity??1),0):0;return`${r} discarded event${r===1?"":"s"}`}case"log":{const r=Array.isArray(t?.items)?t.items.length:void 0;return r!=null?`${r} log${r===1?"":"s"}`:"logs"}case"attachment":return firstString(t?.filename)??"attachment";case"profile":case"profile_chunk":return"profile";case"user_report":case"feedback":return"user feedback";case"replay_event":case"replay_recording":return"replay";case"check_in":return firstString(t?.monitor_slug)??"check-in";default:return e}}catch{return e}}function countSpans(e,n){if(e!=="transaction")return void 0;const t=n?.spans;return Array.isArray(t)?t.length+1:1}function parseEnvelope(e){const n=Date.now();try{if(!Array.isArray(e)||!Array.isArray(e[1])){throw new Error("not an envelope")}const[t,r]=e;const s=[];let a=0;for(const l of r){if(!Array.isArray(l))continue;const[o,i]=l;const u=typeof o?.type==="string"?o.type:"unknown";const f=payloadBytes(i);a+=f;const c=isTypedArray(i);s.push({type:u,bytes:f,summary:c?summarize(u,o):summarize(u,i),spanCount:countSpans(u,i),binary:c||void 0,payload:c?void 0:(0,_sanitize.sanitizePayload)(i)})}return{timestamp:n,origin:"js",eventId:typeof t?.event_id==="string"?t.event_id:void 0,header:(0,_sanitize.sanitizePayload)(t),items:s,totalBytes:a}}catch{return{timestamp:n,origin:"js",items:[{type:"unknown",bytes:0,summary:"unparseable envelope"}],totalBytes:0}}}const attachedClients=new WeakSet;let installStarted=false;let attachTimer=null;let userGetClient;function attachToClient(e){const n=e;if(!n||typeof n.on!=="function")return false;if(attachedClients.has(n))return true;attachedClients.add(n);try{n.on("beforeEnvelope",t=>{try{const r=parseEnvelope(t);const s=r.items.some(a=>a.type==="event");(0,_sentryEnvelopeStore.recordEnvelope)(r,{urgent:s})}catch{}})}catch{return false}try{(0,_observe.observeDrops)(n)}catch{}try{(0,_auditSource.setAuditSource)(n)}catch{}(0,_sentryEnvelopeStore.setAttachStatus)("attached");return true}function resolveClient(){if(userGetClient){try{return{client:userGetClient(),sdkPresent:true}}catch{return{client:void 0,sdkPresent:true}}}const e=(0,_sentrySDK.loadSentrySDK)();if(!e||typeof e.getClient!=="function"){return{client:void 0,sdkPresent:false}}try{return{client:e.getClient(),sdkPresent:true}}catch{return{client:void 0,sdkPresent:true}}}function installSentryCapture(e={}){if(e.getClient)userGetClient=e.getClient;if(installStarted&&(0,_sentryEnvelopeStore.getAttachStatus)()==="attached")return;if(installStarted&&attachTimer!==null)return;installStarted=true;let n=0;const t=()=>{n+=1;const{client:r,sdkPresent:s}=resolveClient();if(r&&attachToClient(r)){if(attachTimer!==null){clearInterval(attachTimer);attachTimer=null}return}if(!s&&!userGetClient){(0,_sentryEnvelopeStore.setAttachStatus)("sdk-not-found");if(attachTimer!==null){clearInterval(attachTimer);attachTimer=null}return}if(n>=MAX_ATTACH_TRIES){(0,_sentryEnvelopeStore.setAttachStatus)("no-client");if(attachTimer!==null){clearInterval(attachTimer);attachTimer=null}}};t();if((0,_sentryEnvelopeStore.getAttachStatus)()==="attached"||attachTimer!==null)return;if((0,_sentryEnvelopeStore.getAttachStatus)()==="sdk-not-found")return;attachTimer=setInterval(t,ATTACH_RETRY_MS)}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest");var _attach=require("./attach");function raw(e,t){return[e,t]}(0,_vitest.describe)("parseEnvelope",()=>{(0,_vitest.it)("reads the event id and item types off a normal envelope",()=>{const e=(0,_attach.parseEnvelope)(raw({event_id:"abc123",sent_at:"2026-09-02T00:00:00Z"},[[{type:"event"},{exception:{values:[{type:"TypeError",value:"x is not a function"}]}}]]));(0,_vitest.expect)(e.eventId).toBe("abc123");(0,_vitest.expect)(e.items).toHaveLength(1);(0,_vitest.expect)(e.items[0].type).toBe("event");(0,_vitest.expect)(e.items[0].summary).toBe("TypeError: x is not a function")});(0,_vitest.it)("counts a transaction's spans as children plus the root",()=>{const e=(0,_attach.parseEnvelope)(raw({},[[{type:"transaction"},{transaction:"/checkout",spans:[{},{},{}]}]]));(0,_vitest.expect)(e.items[0].spanCount).toBe(4);(0,_vitest.expect)(e.items[0].summary).toBe("/checkout")});(0,_vitest.it)("treats a transaction with no spans array as one span",()=>{const e=(0,_attach.parseEnvelope)(raw({},[[{type:"transaction"},{transaction:"/"}]]));(0,_vitest.expect)(e.items[0].spanCount).toBe(1)});(0,_vitest.it)("leaves spanCount unset for everything that is not a transaction",()=>{const e=(0,_attach.parseEnvelope)(raw({},[[{type:"event"},{message:"hi"}]]));(0,_vitest.expect)(e.items[0].spanCount).toBeUndefined()});(0,_vitest.it)("records binary payloads by size without keeping their content",()=>{const e=(0,_attach.parseEnvelope)(raw({},[[{type:"attachment",filename:"screenshot.png"},new Uint8Array(2048)]]));(0,_vitest.expect)(e.items[0].binary).toBe(true);(0,_vitest.expect)(e.items[0].bytes).toBe(2048);(0,_vitest.expect)(e.items[0].payload).toBeUndefined();(0,_vitest.expect)(e.items[0].summary).toBe("screenshot.png")});(0,_vitest.it)("summarizes a client report by how many events were discarded",()=>{const e=(0,_attach.parseEnvelope)(raw({},[[{type:"client_report"},{discarded_events:[{quantity:3},{quantity:2}]}]]));(0,_vitest.expect)(e.items[0].summary).toBe("5 discarded events")});(0,_vitest.it)("survives a malformed envelope instead of throwing on the send path",()=>{const e=(0,_attach.parseEnvelope)("not an envelope at all");(0,_vitest.expect)(e.items[0].summary).toBe("unparseable envelope");(0,_vitest.expect)(e.totalBytes).toBe(0)});(0,_vitest.it)("survives an envelope whose payload holds a cycle",()=>{const e={message:"loop"};e.self=e;const t=(0,_attach.parseEnvelope)(raw({},[[{type:"event"},e]]));(0,_vitest.expect)(t.items[0].type).toBe("event");(0,_vitest.expect)(JSON.stringify(t.items[0].payload)).toContain("[Circular]")});(0,_vitest.it)("sums item sizes into the envelope total",()=>{const e=(0,_attach.parseEnvelope)(raw({},[[{type:"attachment"},new Uint8Array(1e3)],[{type:"attachment"},new Uint8Array(500)]]));(0,_vitest.expect)(e.totalBytes).toBe(1500)})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.loadSentrySDK=loadSentrySDK;function loadSentrySDK(){try{return require("@sentry/react-native")}catch{return null}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.loadSentrySDK=loadSentrySDK;function loadSentrySDK(){return null}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SENTRY_ICON_COLOR=void 0;Object.defineProperty(exports,"SentryIcon",{enumerable:true,get:function(){return _sharedUi.SentryIcon}});var _sharedUi=require("@buoy-gg/shared-ui");const SENTRY_ICON_COLOR=exports.SENTRY_ICON_COLOR="#9945FF";
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SENTRY_ICON_COLOR=void 0;Object.defineProperty(exports,"SentryIcon",{enumerable:true,get:function(){return _sharedUi.SentryIcon}});var _sharedUi=require("@buoy-gg/shared-ui");const SENTRY_ICON_COLOR=exports.SENTRY_ICON_COLOR="#9945FF";
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryModal=SentryModal;var _react=_interopRequireDefault(require("react"));var _sharedUi=require("@buoy-gg/shared-ui");var _useSentryController=require("../devtools/useSentryController");var _SentryHeader=require("../devtools/SentryHeader");var _SentryBody=require("../devtools/SentryBody");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function SentryModal({visible:e,onClose:t,onBack:o,onMinimize:n,persistenceKey:s}){const r=(0,_useSentryController.useSentryController)();return(0,_jsxRuntime.jsx)(_sharedUi.JsModal,{visible:e,onClose:t,onMinimize:n,persistenceKey:s??"buoy-sentry",header:{showToggleButton:true,customContent:(0,_jsxRuntime.jsx)(_SentryHeader.SentryHeader,{c:r,onBack:o})},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:(0,_jsxRuntime.jsx)(_SentryBody.SentryBody,{c:r})})}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryAuditView=SentryAuditView;var _react=_interopRequireDefault(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _layout=require("./layout");var _pii=require("../audit/pii");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(t){return t&&t.__esModule?t:{default:t}}const MONO=_sharedUi.monoFont;const SEVERITY_COLOR={critical:"#F87171",warning:"#FBBF24",info:"#60A5FA"};const CATEGORY_LABEL={quota:"Quota",privacy:"Privacy",correctness:"Correctness"};function SentryAuditView({c:t}){const{audit:r,piiFindings:a}=t;if(!r){return(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:"sentry-audit-unavailable",otto:"scanning",title:"No client to audit",message:"The audit reads the options Sentry.init actually resolved, so it needs a live client. Once the tool attaches, the resolved config is graded here."})}const o=r.findings.length===0&&a.length===0;return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.container,contentContainerStyle:styles.content,testID:"sentry-audit-view",children:[o?(0,_jsxRuntime.jsxs)(_sharedUi.DevToolsCard,{testID:"sentry-audit-clean",contentStyle:styles.cardBody,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.title,children:"Nothing to flag"}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{tone:"secondary",style:styles.inCard,children:"The resolved config raised no findings, and nothing sent this session matched a personal-data pattern."})]}):null,r.findings.length>0?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{style:styles.sectionLabel,children:"CONFIG"}),r.findings.map(e=>(0,_jsxRuntime.jsxs)(_sharedUi.DevToolsCard,{testID:`sentry-audit-${e.id}`,style:[styles.stripe,{borderLeftColor:SEVERITY_COLOR[e.severity]}],contentStyle:styles.cardBody,accessible:true,accessibilityLabel:`${e.severity} ${e.category} finding. ${e.title}. ${e.detail}`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.head,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.title,children:e.title}),(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:CATEGORY_LABEL[e.category]??e.category,color:SEVERITY_COLOR[e.severity],variant:"tinted"})]}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{tone:"secondary",style:styles.inCard,children:e.detail})]},e.id))]}):null,a.length>0?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{style:styles.sectionLabel,children:"PERSONAL DATA IN SENT PAYLOADS"}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{style:styles.piiNote,children:"Values are redacted here \u2014 the path is what you need to fix."}),a.map((e,i)=>(0,_jsxRuntime.jsxs)(_sharedUi.DevToolsCard,{testID:`sentry-pii-${i}`,style:[styles.stripe,{borderLeftColor:SEVERITY_COLOR.critical}],contentStyle:styles.cardBody,accessible:true,accessibilityLabel:`${_pii.PII_KIND_LABEL[e.kind]} at ${e.path}, value redacted as ${e.sample}`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.head,children:[(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:_pii.PII_KIND_LABEL[e.kind],color:SEVERITY_COLOR.critical,variant:"tinted"}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.sample,children:e.sample})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.path,selectable:true,children:e.path})]},`${e.path}-${i}`))]}):null]})}const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},content:{paddingTop:_layout.SENTRY_BODY_TOP_INSET,paddingBottom:24},sectionLabel:{marginHorizontal:12,marginTop:10,marginBottom:2},piiNote:{marginHorizontal:12,marginTop:0,marginBottom:2},cardBody:{gap:6},inCard:{marginTop:2,marginLeft:0},stripe:{borderLeftWidth:3,borderRadius:8},head:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8},title:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"700",flexShrink:1},sample:{color:_sharedUi.night.color.textTertiary,fontSize:10,fontFamily:MONO},path:{color:_sharedUi.night.color.textSecondary,fontSize:11,fontFamily:MONO}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryBody=SentryBody;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _dataViewer=require("@buoy-gg/shared-ui/dataViewer");var _layout=require("./layout");var _attachStatus=require("./attachStatus");var _SentryCostView=require("./SentryCostView");var _SentryDropsView=require("./SentryDropsView");var _SentryAuditView=require("./SentryAuditView");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(t,e){if("function"==typeof WeakMap)var r=new WeakMap,o=new WeakMap;return(_interopRequireWildcard=function(n,d){if(!d&&n&&n.__esModule)return n;var a,i,l={__proto__:null,default:n};if(null===n||"object"!=typeof n&&"function"!=typeof n)return l;if(a=d?o:r){if(a.has(n))return a.get(n);a.set(n,l)}for(const s in n)"default"!==s&&{}.hasOwnProperty.call(n,s)&&((i=(a=Object.defineProperty)&&Object.getOwnPropertyDescriptor(n,s))&&(i.get||i.set)?a(l,s,i):l[s]=n[s]);return l})(t,e)}const MONO=_sharedUi.monoFont;const TYPE_COLORS={event:"#F87171",transaction:"#A78BFA",session:"#34D399",sessions:"#34D399",client_report:"#FBBF24",log:"#60A5FA",attachment:"#F472B6",profile:"#FB923C",profile_chunk:"#FB923C",replay_event:"#22D3EE",replay_recording:"#22D3EE",user_report:"#F472B6",feedback:"#F472B6"};const TYPE_SHORT_LABEL={client_report:"report",replay_recording:"replay",replay_event:"replay",profile_chunk:"profile",user_report:"feedback"};function typeColor(t){return TYPE_COLORS[t]??"#9CA3AF"}function typeLabel(t){return TYPE_SHORT_LABEL[t]??t}function formatClock(t){const e=new Date(t);const r=o=>String(o).padStart(2,"0");return`${r(e.getHours())}:${r(e.getMinutes())}:${r(e.getSeconds())}`}function EnvelopeRow({envelope:t,onPress:e}){const r=t.items[0];const o=t.items.reduce((a,i)=>a+(i.spanCount??0),0);const n=t.items.length-1;const d=`${r?.summary??"envelope"}${o>0?` \xB7 ${o} span${o===1?"":"s"}`:""}`;return(0,_jsxRuntime.jsx)(_sharedUi.CompactRow,{statusDotColor:typeColor(r?.type??""),statusLabel:typeLabel(r?.type??"envelope"),statusSublabel:n>0?`+${n} more`:void 0,primaryText:d,secondaryText:n>0?t.items.map(a=>a.type).join(" + "):void 0,badgeText:(0,_sharedUi.formatBytes)(t.totalBytes),badgeColor:_sharedUi.night.color.textSecondary,bottomRightText:(0,_jsxRuntime.jsx)(_sharedUi.RelativeTime,{timestamp:t.timestamp}),showChevron:true,onPress:()=>e(t.id),testID:`sentry-envelope-row-${t.id}`})}function FeedMeta({c:t}){const e=_attachStatus.STATUS_META[t.status];return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.meta,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{testID:"sentry-status-chip",accessible:true,accessibilityLabel:`Sentry capture: ${e.label}`,children:(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:e.label,color:e.color,variant:"quiet",dot:true})}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.metaTotals,testID:"sentry-totals",children:[t.rows.length," \xB7 ",(0,_sharedUi.formatBytes)(t.totalBytes)]})]})}function EmptyList({status:t}){const e=t==="attached"?"Attached to the Sentry client. Envelopes will appear here as the app sends them.":t==="sdk-not-found"?"@sentry/react-native isn't installed in this app (or isn't resolvable). Pass getClient to installSentryCapture / SentryRoot to attach explicitly.":t==="no-client"?"Sentry SDK found, but no client appeared \u2014 is Sentry.init() being called?":"Looking for the app's Sentry client\u2026";return(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:"sentry-empty",otto:t==="attached"?"guard":"scanning",title:"No envelopes captured",message:e})}function pretty(t){try{return JSON.stringify(t,null,2)??String(t)}catch{return String(t)}}function PayloadBlock({value:t,testID:e}){const r=t!==null&&typeof t==="object";if(!r){const o=pretty(t);return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.payloadBlock,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.payloadCopy,children:(0,_jsxRuntime.jsx)(_sharedUi.CopyButton,{value:o,size:12})}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.payload,selectable:true,testID:e,children:o})]})}return(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.payloadTree,testID:e,children:(0,_jsxRuntime.jsx)(_dataViewer.DataViewer,{title:"",data:t,rawMode:true,showTypeFilter:true,initialExpanded:false,testIDPrefix:e?`${e}-node`:void 0})})}function ItemCard({item:t,index:e}){return(0,_jsxRuntime.jsxs)(_sharedUi.DevToolsCard,{testID:`sentry-item-${e}`,contentStyle:styles.cardBody,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.itemHead,children:[(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:t.type,color:typeColor(t.type),variant:"outline"}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.itemMeta,children:[(0,_sharedUi.formatBytes)(t.bytes),t.spanCount!=null?` \xB7 ${t.spanCount} span${t.spanCount===1?"":"s"}`:""]})]}),(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.itemSummary,testID:`sentry-item-${e}-summary`,children:t.summary}),t.binary?(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.itemBinary,children:["binary payload (",(0,_sharedUi.formatBytes)(t.bytes),")"]}):t.payload!==void 0?(0,_jsxRuntime.jsx)(PayloadBlock,{value:t.payload,testID:`sentry-item-${e}-payload`}):null]})}function EnvelopeDetail({envelope:t}){return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.container,contentContainerStyle:styles.detailContent,testID:"sentry-envelope-detail",children:[(0,_jsxRuntime.jsxs)(_sharedUi.DevToolsCard,{contentStyle:styles.cardBody,children:[(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:"Captured",value:formatClock(t.timestamp)}),(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:"Size",value:(0,_sharedUi.formatBytes)(t.totalBytes)}),(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:"Items",value:String(t.items.length)}),(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:"Origin",value:t.origin}),t.eventId?(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:"Event ID",value:t.eventId,mono:true,copyable:true}):null]}),(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{style:styles.sectionLabel,children:"ITEMS"}),t.items.map((e,r)=>(0,_jsxRuntime.jsx)(ItemCard,{item:e,index:r},r)),t.header!==void 0?(0,_jsxRuntime.jsxs)(_jsxRuntime.Fragment,{children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{style:styles.sectionLabel,children:"ENVELOPE HEADER"}),(0,_jsxRuntime.jsx)(_sharedUi.DevToolsCard,{contentStyle:styles.cardBody,children:(0,_jsxRuntime.jsx)(PayloadBlock,{value:t.header,testID:"sentry-envelope-header"})})]}):null]})}function SentryBody({c:t}){const e=(0,_react.useCallback)(({item:r})=>(0,_jsxRuntime.jsx)(EnvelopeRow,{envelope:r,onPress:t.openDetail}),[t.openDetail]);if(t.tab==="cost"){return(0,_jsxRuntime.jsx)(_SentryCostView.SentryCostView,{c:t})}if(t.tab==="drops"){return(0,_jsxRuntime.jsx)(_SentryDropsView.SentryDropsView,{c:t})}if(t.tab==="audit"){return(0,_jsxRuntime.jsx)(_SentryAuditView.SentryAuditView,{c:t})}if(t.view==="detail"&&t.selected){return(0,_jsxRuntime.jsx)(EnvelopeDetail,{envelope:t.selected})}return(0,_jsxRuntime.jsx)(_reactNative.FlatList,{style:styles.container,data:t.rows,keyExtractor:r=>String(r.id),renderItem:e,ListHeaderComponent:(0,_jsxRuntime.jsx)(FeedMeta,{c:t}),ListEmptyComponent:(0,_jsxRuntime.jsx)(EmptyList,{status:t.status}),contentContainerStyle:styles.listContent,..._sharedUi.LOG_LIST_PRESET,testID:"sentry-envelope-list"})}const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},listContent:{paddingTop:_layout.SENTRY_BODY_TOP_INSET,paddingBottom:12},meta:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8,paddingHorizontal:12,paddingBottom:8},metaTotals:{color:_sharedUi.night.color.textTertiary,fontSize:11,fontVariant:["tabular-nums"]},detailContent:{paddingTop:_layout.SENTRY_BODY_TOP_INSET,paddingBottom:24},sectionLabel:{marginHorizontal:12,marginTop:10,marginBottom:2},cardBody:{gap:8},itemHead:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8},itemMeta:{color:_sharedUi.night.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},itemSummary:{color:_sharedUi.night.color.text,fontSize:12,fontWeight:"600"},itemBinary:{color:_sharedUi.night.color.textTertiary,fontSize:11,fontStyle:"italic"},payloadBlock:{backgroundColor:_sharedUi.night.color.fill,borderRadius:6,padding:8,paddingRight:26},payloadTree:{backgroundColor:_sharedUi.night.color.fill,borderRadius:6,marginHorizontal:-4,paddingVertical:4,overflow:"hidden"},payloadCopy:{position:"absolute",top:4,right:4,zIndex:1},payload:{color:_sharedUi.night.color.textSecondary,fontSize:11,fontFamily:MONO,lineHeight:16}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryCostView=SentryCostView;var _react=_interopRequireDefault(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _layout=require("./layout");var _plans=require("../quota/plans");var _usage=require("../quota/usage");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function fractionColor(e){if(e===null)return _sharedUi.night.color.textTertiary;if(e>=1)return"#F87171";if(e>=.6)return"#FBBF24";return"#34D399"}function formatUnits(e,n){if(n==="bytes")return(0,_sharedUi.formatBytes)(e);if(e>=1e6)return`${(e/1e6).toFixed(1)}M`;if(e>=1e3)return`${(e/1e3).toFixed(1)}k`;return String(e)}function formatFraction(e){if(e===null)return"\u2014";if(!Number.isFinite(e))return"not on plan";if(e>=10)return`${Math.round(e)}\xD7 quota`;return`${Math.round(e*100)}% of quota`}function CategoryCard({category:e,session:n,projected:i,quota:r,usable:s}){const o=s?(0,_usage.quotaFraction)(i,r):null;const l=fractionColor(o);const t=o===null||!Number.isFinite(o)?o===null?0:100:Math.min(100,o*100);const a=s?`, about ${formatUnits(i,e.format)} per month, ${formatFraction(o)}`:", projection needs a longer session";const c=r>0?`, quota ${formatUnits(r,e.format)}`:", not included in this plan";return(0,_jsxRuntime.jsxs)(_sharedUi.DevToolsCard,{testID:`sentry-cost-${e.key}`,contentStyle:styles.cardBody,accessible:true,accessibilityLabel:`${e.label}: ${formatUnits(n,e.format)} this session${a}${c}`,children:[(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.head,children:[(0,_jsxRuntime.jsx)(_reactNative.Text,{style:styles.label,children:e.label}),(0,_jsxRuntime.jsxs)(_reactNative.Text,{style:styles.session,children:[formatUnits(n,e.format)," this session"]})]}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.barTrack,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:[styles.barFill,{width:`${t}%`,backgroundColor:l}]})}),(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:"Projected",value:s?`${formatUnits(i,e.format)}/mo \xB7 ${formatFraction(o)}`:"needs a longer session",valueColor:l}),(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:"Quota",value:r>0?formatUnits(r,e.format):"not included"}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{style:styles.hint,children:e.hint})]})}function SentryCostView({c:e}){const{usage:n,projection:i,plan:r}=e;const{scrollProps:s,onTouchStart:o,isTap:l}=(0,_sharedUi.useChipTap)();return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.container,contentContainerStyle:styles.content,testID:"sentry-cost-view",children:[(0,_jsxRuntime.jsx)(_sharedUi.ChipStrip,{scrollProps:s,contentStyle:styles.planStrip,sentryLabel:"ignore devtools sentry plan strip scroll",children:_plans.SENTRY_PLANS.map(t=>(0,_jsxRuntime.jsx)(_reactNative.View,{onTouchStart:o,children:(0,_jsxRuntime.jsx)(_sharedUi.NightChip,{label:t.name,selected:t.id===r.id,onPress:()=>{if(l())e.setPlanId(t.id)},testID:`sentry-plan-${t.id}`})},t.id))}),(0,_jsxRuntime.jsxs)(_sharedUi.NightFootnote,{style:styles.windowNote,children:[e.rows.length," envelope",e.rows.length===1?"":"s"," over"," ",(0,_sharedUi.formatDuration)(n.windowMs),i.usable?" \xB7 projection extrapolates this rate to 30 days":""]}),_plans.CATEGORY_META.map(t=>(0,_jsxRuntime.jsx)(CategoryCard,{category:t,session:n.totals[t.key],projected:i.totals[t.key],quota:r.quota[t.key],usable:i.usable},t.key)),n.contributors.length>0?(0,_jsxRuntime.jsxs)(_reactNative.View,{testID:"sentry-cost-contributors",children:[(0,_jsxRuntime.jsx)(_sharedUi.NightSectionLabel,{style:styles.sectionLabel,children:"WHAT COSTS THE MOST"}),(0,_jsxRuntime.jsx)(_sharedUi.DevToolsCard,{contentStyle:styles.contribBody,children:n.contributors.slice(0,8).map(t=>{const a=_plans.CATEGORY_META.find(c=>c.key===t.category);return(0,_jsxRuntime.jsx)(_sharedUi.InfoRow,{label:t.label,value:`${formatUnits(t.units,a?.format??"count")} ${a?.label.toLowerCase()??t.category}${t.occurrences>1?` \xD7${t.occurrences}`:""}`},`${t.category}:${t.label}`)})})]}):null,(0,_jsxRuntime.jsxs)(_sharedUi.NightFootnote,{style:styles.footnote,children:["Sentry bills on receipt \u2014 data their server-side sampling later drops is still charged, so the only lossless lever is client config, and on mobile that ships frozen in the binary. Quotas as published ",_plans.SENTRY_PLANS_VERIFIED_ON,"."]})]})}const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},content:{paddingTop:_layout.SENTRY_BODY_TOP_INSET,paddingBottom:24},planStrip:{paddingHorizontal:12,gap:8},windowNote:{marginHorizontal:12,marginTop:6},sectionLabel:{marginHorizontal:12,marginTop:12,marginBottom:2},cardBody:{gap:6},hint:{marginTop:2,marginLeft:0,fontSize:_sharedUi.night.font.micro,lineHeight:_sharedUi.night.font.micro*1.4},contribBody:{gap:0},head:{flexDirection:"row",alignItems:"baseline",justifyContent:"space-between",gap:8},label:{color:_sharedUi.night.color.text,fontSize:13,fontWeight:"700"},session:{color:_sharedUi.night.color.textSecondary,fontSize:11,fontVariant:["tabular-nums"]},barTrack:{height:10,borderRadius:5,backgroundColor:_sharedUi.night.color.fill,overflow:"hidden"},barFill:{height:10,borderRadius:5},footnote:{marginHorizontal:12,marginTop:10}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryDropsView=SentryDropsView;var _react=_interopRequireWildcard(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _layout=require("./layout");var _types=require("../drops/types");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireWildcard(n,i){if("function"==typeof WeakMap)var l=new WeakMap,u=new WeakMap;return(_interopRequireWildcard=function(t,e){if(!e&&t&&t.__esModule)return t;var r,o,s={__proto__:null,default:t};if(null===t||"object"!=typeof t&&"function"!=typeof t)return s;if(r=e?u:l){if(r.has(t))return r.get(t);r.set(t,s)}for(const a in t)"default"!==a&&{}.hasOwnProperty.call(t,a)&&((o=(r=Object.defineProperty)&&Object.getOwnPropertyDescriptor(t,a))&&(o.get||o.set)?r(s,a,o):s[a]=t[a]);return s})(n,i)}const REASON_COLOR={before_send:"#F87171",sample_rate:"#60A5FA",event_processor:"#FBBF24",rn_discard:"#A78BFA",client_report:"#FB923C",native:"#F472B6",other:"#9CA3AF"};function SentryDropsView({c:n}){const[i,l]=(0,_react.useState)(null);const{scrollProps:u}=(0,_sharedUi.useChipTap)();const t=(0,_react.useCallback)(e=>l(r=>r===e?null:e),[]);if(n.drops.length===0){return(0,_jsxRuntime.jsx)(_sharedUi.ToolEmptyState,{testID:"sentry-drops-empty",otto:"scanning",title:"Nothing dropped yet",message:"Events the SDK discards before sending will be listed here with the reason \u2014 a beforeSend that returned null, a sample-rate roll, dedupe, or a native rate limit."})}return(0,_jsxRuntime.jsxs)(_reactNative.ScrollView,{style:styles.container,contentContainerStyle:styles.content,testID:"sentry-drops-view",children:[(0,_jsxRuntime.jsx)(_sharedUi.ChipStrip,{scrollProps:u,contentStyle:styles.summaryStrip,sentryLabel:"ignore devtools sentry drop summary scroll",children:n.dropSummary.map(e=>(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:`${e.units} \xD7 ${_types.DROP_REASON_META[e.reason].label}`,color:REASON_COLOR[e.reason],variant:"tinted",size:"sm",uppercase:false,testID:`sentry-drop-summary-${e.reason}`},e.reason))}),n.dropRows.map(e=>(0,_jsxRuntime.jsx)(_sharedUi.CompactRow,{statusDotColor:REASON_COLOR[e.reason],statusLabel:e.category,statusSublabel:e.source,primaryText:e.detail,secondaryAccessory:(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:_types.DROP_REASON_META[e.reason].label,color:REASON_COLOR[e.reason],variant:"outline",uppercase:false}),badgeText:e.quantity>1?`\xD7${e.quantity}`:void 0,badgeColor:REASON_COLOR[e.reason],bottomRightText:(0,_jsxRuntime.jsx)(_sharedUi.RelativeTime,{timestamp:e.timestamp}),isExpanded:i===e.id,expandedGlowColor:REASON_COLOR[e.reason],expandedContent:(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.expanded,children:[(0,_jsxRuntime.jsx)(_sharedUi.Pill,{label:_types.DROP_REASON_META[e.reason].label,color:REASON_COLOR[e.reason],variant:"outline",uppercase:false}),(0,_jsxRuntime.jsx)(_sharedUi.NightFootnote,{style:styles.explanation,children:_types.DROP_REASON_META[e.reason].explanation})]}),showChevron:true,onPress:()=>t(e.id),testID:`sentry-drop-row-${e.id}`},e.id))]})}const styles=_reactNative.StyleSheet.create({container:{flex:1,backgroundColor:"transparent"},content:{paddingTop:_layout.SENTRY_BODY_TOP_INSET,paddingBottom:24},summaryStrip:{paddingHorizontal:12,gap:8,paddingBottom:4},expanded:{gap:6,alignItems:"flex-start"},explanation:{marginTop:2,marginLeft:0}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryHeader=SentryHeader;var _react=_interopRequireDefault(require("react"));var _reactNative=require("react-native");var _sharedUi=require("@buoy-gg/shared-ui");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const TABS=[{key:"feed",label:"Feed"},{key:"cost",label:"Cost"},{key:"drops",label:"Drops"},{key:"audit",label:"Audit"}];function SentryHeader({c:e,onBack:a}){if(e.view==="detail"){const r=e.selected?e.selected.items.map(o=>o.type).join(" + ")||"Envelope":"Envelope";return(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation,{onBack:e.closeDetail}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:r})]})}const t=e.rows.length>0;return(0,_jsxRuntime.jsxs)(_sharedUi.ModalHeader,{children:[a?(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Navigation,{onBack:a}):null,(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Content,{title:"",noMargin:true,children:(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.tabs,children:(0,_jsxRuntime.jsx)(_sharedUi.TabSelector,{tabs:TABS,activeTab:e.tab,onTabChange:r=>e.setTab(r),testIDPrefix:"sentry-tab"})})}),(0,_jsxRuntime.jsx)(_sharedUi.ModalHeader.Actions,{children:(0,_jsxRuntime.jsx)(_reactNative.TouchableOpacity,{onPress:e.clear,disabled:!t,style:[styles.actionBtn,!t&&styles.actionBtnDisabled],accessibilityLabel:"Clear captured envelopes",testID:"sentry-clear",children:(0,_jsxRuntime.jsx)(_sharedUi.Trash2,{size:14,color:t?_sharedUi.night.color.textSecondary:_sharedUi.night.color.textTertiary})})})]})}const styles=_reactNative.StyleSheet.create({tabs:{maxWidth:360},actionBtn:{width:32,height:32,borderRadius:8,backgroundColor:_sharedUi.night.color.buttonSurface,borderWidth:1,borderColor:_sharedUi.night.color.border,alignItems:"center",justifyContent:"center"},actionBtnDisabled:{opacity:.55}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SentryToolView=SentryToolView;var _react=_interopRequireDefault(require("react"));var _reactNative=require("react-native");var _useSentryController=require("./useSentryController");var _SentryHeader=require("./SentryHeader");var _SentryBody=require("./SentryBody");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}function SentryToolView(){const e=(0,_useSentryController.useSentryController)();return(0,_jsxRuntime.jsxs)(_reactNative.View,{style:styles.root,children:[(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.headerSlot,children:(0,_jsxRuntime.jsx)(_SentryHeader.SentryHeader,{c:e})}),(0,_jsxRuntime.jsx)(_reactNative.View,{style:styles.body,children:(0,_jsxRuntime.jsx)(_SentryBody.SentryBody,{c:e})})]})}const styles=_reactNative.StyleSheet.create({root:{flex:1,flexDirection:"column",backgroundColor:"transparent"},headerSlot:{flexGrow:0,flexShrink:0},body:{flex:1}});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.STATUS_META=void 0;const STATUS_META=exports.STATUS_META={attached:{label:"Attached",color:"#34D399"},searching:{label:"Searching\u2026",color:"#FBBF24"},"sdk-not-found":{label:"SDK not found",color:"#F87171"},"no-client":{label:"No client",color:"#F87171"}};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SENTRY_BODY_TOP_INSET=void 0;const SENTRY_BODY_TOP_INSET=exports.SENTRY_BODY_TOP_INSET=16;
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"formatBytes",{enumerable:true,get:function(){return _sharedUi.formatBytes}});exports.useSentryController=useSentryController;var _react=require("react");var _sentryEnvelopeStore=require("../store/sentryEnvelopeStore");var _plans=require("../quota/plans");var _usage=require("../quota/usage");var _dropStore=require("../drops/dropStore");var _rules=require("../audit/rules");var _auditSource=require("../audit/auditSource");var _pii=require("../audit/pii");var _sharedUi=require("@buoy-gg/shared-ui");const PII_SCAN_ENVELOPES=20;function useSentryController(){const e=(0,_react.useSyncExternalStore)(_sentryEnvelopeStore.subscribe,_sentryEnvelopeStore.getEnvelopes,_sentryEnvelopeStore.getEnvelopes);const m=(0,_react.useSyncExternalStore)(_sentryEnvelopeStore.subscribe,_sentryEnvelopeStore.getAttachStatus,_sentryEnvelopeStore.getAttachStatus);const[s,b]=(0,_react.useState)("feed");const[v,a]=(0,_react.useState)("list");const[i,c]=(0,_react.useState)(null);const[p,y]=(0,_react.useState)(_plans.DEFAULT_PLAN_ID);const M=(0,_react.useMemo)(()=>[...e].reverse(),[e]);const r=(0,_react.useSyncExternalStore)(_sentryEnvelopeStore.subscribe,_sentryEnvelopeStore.getMirroredUsage,_sentryEnvelopeStore.getMirroredUsage);const n=(0,_react.useMemo)(()=>(0,_usage.computeUsage)(e),[e]);const l=(0,_react.useMemo)(()=>{if(!r?.session)return n;return{totals:r.session,windowMs:r.windowMs??n.windowMs,contributors:r.topContributors??n.contributors}},[r,n]);const _=(0,_react.useMemo)(()=>(0,_usage.projectMonthly)(l),[l]);const E=(0,_react.useMemo)(()=>(0,_plans.getPlan)(p),[p]);const o=(0,_react.useSyncExternalStore)(_dropStore.subscribeDrops,_dropStore.getDrops,_dropStore.getDrops);const q=(0,_react.useMemo)(()=>[...o].reverse(),[o]);const w=(0,_react.useMemo)(()=>(0,_dropStore.summarizeDrops)(o),[o]);const D=(0,_react.useMemo)(()=>{if(s!=="audit")return null;const t=(0,_auditSource.readAuditInput)();return t?{findings:(0,_rules.auditConfig)(t)}:null},[s]);const h=(0,_react.useMemo)(()=>{if(s!=="audit")return[];const t=e.slice(-PII_SCAN_ENVELOPES);const u=[];const S=new Set;for(const U of t){for(const f of U.items){if(f.payload===void 0)continue;for(const d of(0,_pii.scanForPii)(f.payload)){const g=`${d.kind}:${d.path}`;if(S.has(g))continue;S.add(g);u.push(d)}}}return u},[s,e]);const C=(0,_react.useMemo)(()=>i==null?void 0:e.find(t=>t.id===i),[e,i]);const I=(0,_react.useMemo)(()=>e.reduce((t,u)=>t+u.totalBytes,0),[e]);const P=(0,_react.useCallback)(t=>{c(t);a("detail")},[]);const x=(0,_react.useCallback)(()=>{a("list");c(null)},[]);const A=(0,_react.useCallback)(()=>{(0,_sentryEnvelopeStore.clearEnvelopes)();(0,_dropStore.clearDrops)();a("list");c(null)},[]);return{tab:s,setTab:b,view:v,envelopes:e,rows:M,selected:C,status:m,totalBytes:I,usage:l,projection:_,plan:E,setPlanId:y,drops:o,dropRows:q,dropSummary:w,audit:D,piiFindings:h,openDetail:P,closeDetail:x,clear:A}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.clearDrops=clearDrops;exports.dropFromNativeLog=dropFromNativeLog;exports.dropFromRnDiscard=dropFromRnDiscard;exports.dropsFromClientReport=dropsFromClientReport;exports.getDrops=getDrops;exports.reconcileReported=reconcileReported;exports.recordDrop=recordDrop;exports.recordReportedDrops=recordReportedDrops;exports.replaceDrops=replaceDrops;exports.rnDiscardReason=rnDiscardReason;exports.subscribeDrops=subscribeDrops;exports.summarizeDrops=summarizeDrops;exports.tallyObserved=tallyObserved;var _sharedUi=require("@buoy-gg/shared-ui");const MAX_DROPS=300;const store=(0,_sharedUi.createToolStore)({id:"sentry-drops",max:MAX_DROPS,order:"append",coalesce:"frame"});const unreported=new Map;const reportKey=(e,o)=>`${e==="rn_discard"?"event_processor":e}|${o}`;function recordDrop(e){if(e.source==="observed")tallyObserved(unreported,e);store.add({...e,id:store.allocId()})}function reconcileReported(e,o){const r=[];for(const t of o){const a=reportKey(t.reason,t.category);const n=e.get(a)??0;const i=Math.min(n,t.quantity);if(i>0)e.set(a,n-i);const s=t.quantity-i;if(s<=0)continue;r.push(s===t.quantity?t:{...t,quantity:s,detail:t.detail.replace(/^\d+/,String(s))})}return r}function tallyObserved(e,o){const r=reportKey(o.reason,o.category);e.set(r,(e.get(r)??0)+o.quantity)}function recordReportedDrops(e){for(const o of reconcileReported(unreported,e))store.add({...o,id:store.allocId()})}function subscribeDrops(e){return store.subscribe(e)}function getDrops(){return store.getSnapshot()}function clearDrops(){unreported.clear();store.clear()}function replaceDrops(e){store.set(e)}const CLIENT_REPORT_REASONS={before_send:"before_send",event_processor:"event_processor",sample_rate:"sample_rate",ratelimit_backoff:"native",network_error:"native",queue_overflow:"native",cache_overflow:"native",send_error:"native"};function dropsFromClientReport(e,o){const r=e?.discarded_events;if(!Array.isArray(r))return[];const t=[];for(const a of r){const n=a;const i=typeof n.reason==="string"?n.reason:"";const s=typeof n.category==="string"?n.category:"unknown";const c=typeof n.quantity==="number"?n.quantity:1;const d=CLIENT_REPORT_REASONS[i]??"other";t.push({timestamp:o,reason:d,category:s,quantity:c,detail:d==="other"&&i?`${c} ${s} \u2014 SDK reason "${i}"`:`${c} ${s}`,source:"reported"})}return t}const RN_DISCARD_ATTRIBUTE="sentry.rn.discard_reason";const RN_DISCARD_COPY={empty_back_navigation:"back navigation that produced no spans",no_route_info:"no route info was available",no_child_spans:"the transaction had no child spans",discarded_latest_navigation:"a newer navigation superseded it"};function rnDiscardReason(e){const o=e?.contexts?.trace?.data;const r=o?.[RN_DISCARD_ATTRIBUTE];return typeof r==="string"?r:null}function dropFromRnDiscard(e,o,r){return{timestamp:r,reason:"rn_discard",category:"transaction",quantity:1,detail:`${o} \u2014 ${RN_DISCARD_COPY[e]??e}`,source:"observed"}}function dropFromNativeLog(e,o){const r=e.toLowerCase();const t=r.includes("429")||r.includes("rate limit");const a=r.includes("413")||r.includes("payload too large");const n=r.includes("discard")||r.includes("dropp");if(!t&&!a&&!n)return null;return{timestamp:o,reason:"native",category:t?"rate-limited":a?"oversize":"unknown",quantity:1,detail:e.trim().slice(0,300),source:"reported"}}function summarizeDrops(e){const o=new Map;for(const r of e){const t=o.get(r.reason);if(t){t.units+=r.quantity;t.records+=1}else{o.set(r.reason,{units:r.quantity,records:1})}}return[...o.entries()].map(([r,t])=>({reason:r,...t})).sort((r,t)=>t.units-r.units)}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest");var _dropStore=require("./dropStore");(0,_vitest.describe)("dropsFromClientReport",()=>{(0,_vitest.it)("maps the SDK's reasons onto ours and keeps the quantity",()=>{const e=(0,_dropStore.dropsFromClientReport)({discarded_events:[{reason:"before_send",category:"error",quantity:3},{reason:"sample_rate",category:"transaction",quantity:7}]},1e3);(0,_vitest.expect)(e).toHaveLength(2);(0,_vitest.expect)(e[0]).toMatchObject({reason:"before_send",category:"error",quantity:3});(0,_vitest.expect)(e[1]).toMatchObject({reason:"sample_rate",quantity:7})});(0,_vitest.it)("files transport-level reasons under native",()=>{const[e]=(0,_dropStore.dropsFromClientReport)({discarded_events:[{reason:"ratelimit_backoff",category:"error",quantity:1}]},1e3);(0,_vitest.expect)(e.reason).toBe("native")});(0,_vitest.it)("keeps an unrecognized reason visible instead of hiding it",()=>{const[e]=(0,_dropStore.dropsFromClientReport)({discarded_events:[{reason:"some_future_reason",category:"span",quantity:2}]},1e3);(0,_vitest.expect)(e.reason).toBe("other");(0,_vitest.expect)(e.detail).toContain("some_future_reason")});(0,_vitest.it)("returns nothing for a payload with no discarded events",()=>{(0,_vitest.expect)((0,_dropStore.dropsFromClientReport)({},1e3)).toEqual([]);(0,_vitest.expect)((0,_dropStore.dropsFromClientReport)(null,1e3)).toEqual([]);(0,_vitest.expect)((0,_dropStore.dropsFromClientReport)("nonsense",1e3)).toEqual([])});(0,_vitest.it)("defaults a missing quantity to one rather than zero",()=>{const[e]=(0,_dropStore.dropsFromClientReport)({discarded_events:[{reason:"before_send",category:"error"}]},1e3);(0,_vitest.expect)(e.quantity).toBe(1)})});(0,_vitest.describe)("rnDiscardReason",()=>{(0,_vitest.it)("reads the reason RN tracing stamps on the root span",()=>{const e={contexts:{trace:{data:{"sentry.rn.discard_reason":"no_child_spans"}}}};(0,_vitest.expect)((0,_dropStore.rnDiscardReason)(e)).toBe("no_child_spans")});(0,_vitest.it)("returns null for an ordinary transaction",()=>{(0,_vitest.expect)((0,_dropStore.rnDiscardReason)({contexts:{trace:{data:{}}}})).toBeNull();(0,_vitest.expect)((0,_dropStore.rnDiscardReason)({})).toBeNull();(0,_vitest.expect)((0,_dropStore.rnDiscardReason)(null)).toBeNull()});(0,_vitest.it)("turns the reason into copy that names the cause",()=>{const e=(0,_dropStore.dropFromRnDiscard)("empty_back_navigation","/cart",1e3);(0,_vitest.expect)(e.reason).toBe("rn_discard");(0,_vitest.expect)(e.category).toBe("transaction");(0,_vitest.expect)(e.detail).toContain("/cart");(0,_vitest.expect)(e.detail).toContain("back navigation")});(0,_vitest.it)("falls back to the raw reason when it is one we have no copy for",()=>{const e=(0,_dropStore.dropFromRnDiscard)("brand_new_reason","/x",1e3);(0,_vitest.expect)(e.detail).toContain("brand_new_reason")})});(0,_vitest.describe)("dropFromNativeLog",()=>{(0,_vitest.it)("recognizes a rate limit",()=>{const e=(0,_dropStore.dropFromNativeLog)("Transport: rate limit reached, backing off",1e3);(0,_vitest.expect)(e?.reason).toBe("native");(0,_vitest.expect)(e?.category).toBe("rate-limited")});(0,_vitest.it)("recognizes an oversize rejection",()=>{const e=(0,_dropStore.dropFromNativeLog)("HTTP 413 payload too large",1e3);(0,_vitest.expect)(e?.category).toBe("oversize")});(0,_vitest.it)("ignores ordinary native chatter",()=>{(0,_vitest.expect)((0,_dropStore.dropFromNativeLog)("Sentry SDK initialized",1e3)).toBeNull();(0,_vitest.expect)((0,_dropStore.dropFromNativeLog)("Sending envelope to https://\u2026",1e3)).toBeNull()});(0,_vitest.it)("caps a very long native line so one log cannot dominate the panel",()=>{const e=(0,_dropStore.dropFromNativeLog)(`discarded ${"x".repeat(1e3)}`,1e3);(0,_vitest.expect)(e).not.toBeNull();(0,_vitest.expect)(e.detail.length).toBeLessThanOrEqual(300)})});(0,_vitest.describe)("summarizeDrops",()=>{const e=(t,r)=>({id:Math.random(),timestamp:0,reason:t,category:"error",quantity:r,detail:"",source:"observed"});(0,_vitest.it)("totals units per reason and ranks the worst first",()=>{const t=(0,_dropStore.summarizeDrops)([e("sample_rate",2),e("before_send",5),e("before_send",4)]);(0,_vitest.expect)(t[0]).toEqual({reason:"before_send",units:9,records:2});(0,_vitest.expect)(t[1]).toEqual({reason:"sample_rate",units:2,records:1})});(0,_vitest.it)("is empty for no drops",()=>{(0,_vitest.expect)((0,_dropStore.summarizeDrops)([])).toEqual([])})});(0,_vitest.describe)("observed and reported drops of the same event",()=>{const e={timestamp:1,reason:"before_send",category:"error",quantity:1,detail:"[checkout] order failed",source:"observed"};(0,_vitest.it)("counts a beforeSend drop once when the client report repeats it",()=>{const t=new Map;(0,_dropStore.tallyObserved)(t,e);const r=(0,_dropStore.reconcileReported)(t,[{timestamp:2,reason:"before_send",category:"error",quantity:1,detail:"1 error",source:"reported"}]);(0,_vitest.expect)(r).toEqual([])});(0,_vitest.it)("keeps the part of a report we didn't see",()=>{const t=new Map;(0,_dropStore.tallyObserved)(t,e);const r=(0,_dropStore.reconcileReported)(t,[{timestamp:2,reason:"before_send",category:"error",quantity:3,detail:"3 error",source:"reported"}]);(0,_vitest.expect)(r).toHaveLength(1);(0,_vitest.expect)(r[0].quantity).toBe(2);(0,_vitest.expect)(r[0].detail).toBe("2 error")});(0,_vitest.it)("leaves other reasons alone",()=>{const t=new Map;(0,_dropStore.tallyObserved)(t,e);const r=(0,_dropStore.reconcileReported)(t,[{timestamp:2,reason:"sample_rate",category:"error",quantity:1,detail:"1 error",source:"reported"}]);(0,_vitest.expect)(r).toHaveLength(1)})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.noteNativeLog=noteNativeLog;exports.observeDrops=observeDrops;var _dropStore=require("./dropStore");const WRAPPED="__buoySentryDropWatch";function eventName(o,e){const n=o;if(e==="transaction")return n?.transaction??"transaction";const t=n?.exception?.values?.[0];if(t?.value)return String(t.value);if(t?.type)return String(t.type);const c=n?.message?.formatted??n?.message;return typeof c==="string"?c:"event"}function wrapBeforeSend(o,e){if(typeof o!=="function")return o;if(o[WRAPPED])return o;const n=(t,c)=>{const s=eventName(t,e);let r;try{r=o(t,c)}catch(a){try{(0,_dropStore.recordDrop)({timestamp:Date.now(),reason:"before_send",category:e==="transaction"?"transaction":"error",quantity:1,detail:`${s} \u2014 the callback threw`,source:"observed"})}catch{}throw a}const i=a=>{if(a!==null)return;try{(0,_dropStore.recordDrop)({timestamp:Date.now(),reason:"before_send",category:e==="transaction"?"transaction":"error",quantity:1,detail:s,source:"observed"})}catch{}};if(r&&typeof r.then==="function"){return r.then(a=>{i(a);return a})}i(r);return r};n[WRAPPED]=true;return n}function observeDrops(o){const e=o;if(!e)return false;let n=false;try{const t=e.getOptions?.();if(t){t.beforeSend=wrapBeforeSend(t.beforeSend,"error");t.beforeSendTransaction=wrapBeforeSend(t.beforeSendTransaction,"transaction");n=true}}catch{}try{e.on?.("beforeEnvelope",t=>{try{const c=t?.[1];if(!Array.isArray(c))return;const s=Date.now();for(const r of c){if(!Array.isArray(r))continue;const[i,a]=r;if(i?.type==="client_report"){(0,_dropStore.recordReportedDrops)((0,_dropStore.dropsFromClientReport)(a,s))}}}catch{}});n=true}catch{}try{const t=e.getOptions?.();if(t){const c=t.beforeSendTransaction;const s=(r,i)=>{try{const a=(0,_dropStore.rnDiscardReason)(r);if(a){(0,_dropStore.recordDrop)((0,_dropStore.dropFromRnDiscard)(a,eventName(r,"transaction"),Date.now()))}}catch{}return typeof c==="function"?c(r,i):r};s[WRAPPED]=true;t.beforeSendTransaction=s}}catch{}return n}function noteNativeLog(o){try{const e=(0,_dropStore.dropFromNativeLog)(o,Date.now());if(e)(0,_dropStore.recordDrop)(e)}catch{}}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.DROP_REASON_META=void 0;const DROP_REASON_META=exports.DROP_REASON_META={before_send:{label:"beforeSend returned null",explanation:"Your own callback discarded it. This is the most common cause of a missing event, and it leaves no trace anywhere else."},sample_rate:{label:"sampled out",explanation:"A sample-rate roll went against it. Expected \u2014 unless the rate is lower than you meant it to be."},event_processor:{label:"dropped by a processor",explanation:"An integration returned null \u2014 usually dedupe (a repeat of an event already sent) or an inbound filter such as ignoreErrors."},rn_discard:{label:"discarded by RN tracing",explanation:"React Native tracing judged the transaction empty \u2014 no child spans, no route info, or a back navigation that went nowhere."},client_report:{label:"reported dropped by the SDK",explanation:"The SDK's own client report counted this as discarded. It arrives one envelope late, so it names a count rather than the event."},native:{label:"rejected natively",explanation:"The native transport refused it \u2014 a 429 rate limit, a payload over the size cap, or an offline cache eviction. Only visible with debug enabled."},other:{label:"dropped",explanation:"The SDK recorded a discard under a reason this tool doesn't model."}};
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});Object.defineProperty(exports,"CATEGORY_META",{enumerable:true,get:function(){return _plans.CATEGORY_META}});Object.defineProperty(exports,"DEFAULT_PLAN_ID",{enumerable:true,get:function(){return _plans.DEFAULT_PLAN_ID}});Object.defineProperty(exports,"DROP_REASON_META",{enumerable:true,get:function(){return _types.DROP_REASON_META}});Object.defineProperty(exports,"PII_KIND_LABEL",{enumerable:true,get:function(){return _pii.PII_KIND_LABEL}});Object.defineProperty(exports,"SENTRY_ICON_COLOR",{enumerable:true,get:function(){return _SentryIcon.SENTRY_ICON_COLOR}});Object.defineProperty(exports,"SENTRY_PLANS",{enumerable:true,get:function(){return _plans.SENTRY_PLANS}});Object.defineProperty(exports,"SENTRY_PLANS_VERIFIED_ON",{enumerable:true,get:function(){return _plans.SENTRY_PLANS_VERIFIED_ON}});Object.defineProperty(exports,"SentryAuditView",{enumerable:true,get:function(){return _SentryAuditView.SentryAuditView}});Object.defineProperty(exports,"SentryBody",{enumerable:true,get:function(){return _SentryBody.SentryBody}});Object.defineProperty(exports,"SentryCostView",{enumerable:true,get:function(){return _SentryCostView.SentryCostView}});Object.defineProperty(exports,"SentryDropsView",{enumerable:true,get:function(){return _SentryDropsView.SentryDropsView}});Object.defineProperty(exports,"SentryHeader",{enumerable:true,get:function(){return _SentryHeader.SentryHeader}});Object.defineProperty(exports,"SentryIcon",{enumerable:true,get:function(){return _SentryIcon.SentryIcon}});Object.defineProperty(exports,"SentryModal",{enumerable:true,get:function(){return _SentryModal.SentryModal}});Object.defineProperty(exports,"SentryRoot",{enumerable:true,get:function(){return _SentryRoot.SentryRoot}});Object.defineProperty(exports,"SentryToolView",{enumerable:true,get:function(){return _SentryToolView.SentryToolView}});Object.defineProperty(exports,"attachToClient",{enumerable:true,get:function(){return _attach.attachToClient}});Object.defineProperty(exports,"auditConfig",{enumerable:true,get:function(){return _rules.auditConfig}});Object.defineProperty(exports,"clearDrops",{enumerable:true,get:function(){return _dropStore.clearDrops}});Object.defineProperty(exports,"clearEnvelopes",{enumerable:true,get:function(){return _sentryEnvelopeStore.clearEnvelopes}});Object.defineProperty(exports,"computeUsage",{enumerable:true,get:function(){return _usage.computeUsage}});Object.defineProperty(exports,"createSentryTool",{enumerable:true,get:function(){return _preset.createSentryTool}});Object.defineProperty(exports,"dropFromNativeLog",{enumerable:true,get:function(){return _dropStore.dropFromNativeLog}});Object.defineProperty(exports,"dropFromRnDiscard",{enumerable:true,get:function(){return _dropStore.dropFromRnDiscard}});Object.defineProperty(exports,"dropsFromClientReport",{enumerable:true,get:function(){return _dropStore.dropsFromClientReport}});Object.defineProperty(exports,"formatBytes",{enumerable:true,get:function(){return _useSentryController.formatBytes}});Object.defineProperty(exports,"getAttachStatus",{enumerable:true,get:function(){return _sentryEnvelopeStore.getAttachStatus}});Object.defineProperty(exports,"getDrops",{enumerable:true,get:function(){return _dropStore.getDrops}});Object.defineProperty(exports,"getEnvelopes",{enumerable:true,get:function(){return _sentryEnvelopeStore.getEnvelopes}});Object.defineProperty(exports,"getMirroredUsage",{enumerable:true,get:function(){return _sentryEnvelopeStore.getMirroredUsage}});Object.defineProperty(exports,"getPlan",{enumerable:true,get:function(){return _plans.getPlan}});Object.defineProperty(exports,"installSentryCapture",{enumerable:true,get:function(){return _attach.installSentryCapture}});Object.defineProperty(exports,"noteNativeLog",{enumerable:true,get:function(){return _observe.noteNativeLog}});Object.defineProperty(exports,"observeDrops",{enumerable:true,get:function(){return _observe.observeDrops}});Object.defineProperty(exports,"onClear",{enumerable:true,get:function(){return _sentryEnvelopeStore.onClear}});Object.defineProperty(exports,"parseEnvelope",{enumerable:true,get:function(){return _attach.parseEnvelope}});Object.defineProperty(exports,"projectMonthly",{enumerable:true,get:function(){return _usage.projectMonthly}});Object.defineProperty(exports,"quotaFraction",{enumerable:true,get:function(){return _usage.quotaFraction}});Object.defineProperty(exports,"replaceAttachStatus",{enumerable:true,get:function(){return _sentryEnvelopeStore.replaceAttachStatus}});Object.defineProperty(exports,"replaceDrops",{enumerable:true,get:function(){return _dropStore.replaceDrops}});Object.defineProperty(exports,"replaceEnvelopes",{enumerable:true,get:function(){return _sentryEnvelopeStore.replaceEnvelopes}});Object.defineProperty(exports,"replaceUsage",{enumerable:true,get:function(){return _sentryEnvelopeStore.replaceUsage}});Object.defineProperty(exports,"rnDiscardReason",{enumerable:true,get:function(){return _dropStore.rnDiscardReason}});Object.defineProperty(exports,"scanForPii",{enumerable:true,get:function(){return _pii.scanForPii}});Object.defineProperty(exports,"sentrySyncAdapter",{enumerable:true,get:function(){return _sentrySyncAdapter.sentrySyncAdapter}});Object.defineProperty(exports,"sentryToolPreset",{enumerable:true,get:function(){return _preset.sentryToolPreset}});Object.defineProperty(exports,"subscribe",{enumerable:true,get:function(){return _sentryEnvelopeStore.subscribe}});Object.defineProperty(exports,"subscribeDrops",{enumerable:true,get:function(){return _dropStore.subscribeDrops}});Object.defineProperty(exports,"summarizeDrops",{enumerable:true,get:function(){return _dropStore.summarizeDrops}});Object.defineProperty(exports,"useSentryController",{enumerable:true,get:function(){return _useSentryController.useSentryController}});Object.defineProperty(exports,"worstSeverity",{enumerable:true,get:function(){return _rules.worstSeverity}});var _preset=require("./preset");var _SentryRoot=require("./SentryRoot");var _attach=require("./capture/attach");var _SentryModal=require("./components/SentryModal");var _SentryIcon=require("./components/SentryIcon");var _SentryHeader=require("./devtools/SentryHeader");var _SentryBody=require("./devtools/SentryBody");var _useSentryController=require("./devtools/useSentryController");var _SentryCostView=require("./devtools/SentryCostView");var _SentryToolView=require("./devtools/SentryToolView");var _plans=require("./quota/plans");var _usage=require("./quota/usage");var _SentryDropsView=require("./devtools/SentryDropsView");var _dropStore=require("./drops/dropStore");var _observe=require("./drops/observe");var _types=require("./drops/types");var _SentryAuditView=require("./devtools/SentryAuditView");var _rules=require("./audit/rules");var _pii=require("./audit/pii");var _sentrySyncAdapter=require("./sync/sentrySyncAdapter");var _sentryEnvelopeStore=require("./store/sentryEnvelopeStore");
@@ -0,0 +1 @@
1
+ {"type":"commonjs"}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.sentryToolPreset=exports.createSentryTool=void 0;var _react=_interopRequireDefault(require("react"));var _sharedUi=require("@buoy-gg/shared-ui");var _SentryIcon=require("./components/SentryIcon");var _SentryModal=require("./components/SentryModal");var _attach=require("./capture/attach");var _jsxRuntime=require("react/jsx-runtime");function _interopRequireDefault(e){return e&&e.__esModule?e:{default:e}}const rnGlobals=globalThis;const isReactNativeRuntime=typeof rnGlobals.ErrorUtils?.setGlobalHandler==="function"||typeof rnGlobals.RN$registerExceptionListener==="function";if(isReactNativeRuntime&&typeof __DEV__!=="undefined"&&__DEV__){(0,_attach.installSentryCapture)()}const sentryToolPreset=exports.sentryToolPreset=(0,_sharedUi.defineToolPreset)({id:"sentry",name:"SENTRY",description:"Envelopes the app sends to Sentry",slot:"both",icon:({size:e,color:t})=>(0,_jsxRuntime.jsx)(_SentryIcon.SentryIcon,{size:e,color:t??_SentryIcon.SENTRY_ICON_COLOR}),component:_SentryModal.SentryModal});const createSentryTool=exports.createSentryTool=(0,_sharedUi.createToolFactory)(sentryToolPreset);
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SENTRY_PLANS_VERIFIED_ON=exports.SENTRY_PLANS=exports.DEFAULT_PLAN_ID=exports.CATEGORY_META=void 0;exports.getPlan=getPlan;const SENTRY_PLANS_VERIFIED_ON=exports.SENTRY_PLANS_VERIFIED_ON="2026-09";const GB=1024*1024*1024;const SENTRY_PLANS=exports.SENTRY_PLANS=[{id:"developer",name:"Developer (free)",quota:{errors:5e3,spans:5e6,replays:50,logBytes:5*GB,attachmentBytes:1*GB}},{id:"team",name:"Team",quota:{errors:5e4,spans:5e6,replays:50,logBytes:5*GB,attachmentBytes:1*GB}},{id:"business",name:"Business",quota:{errors:5e4,spans:5e6,replays:50,logBytes:5*GB,attachmentBytes:1*GB}}];const DEFAULT_PLAN_ID=exports.DEFAULT_PLAN_ID="developer";function getPlan(e){return SENTRY_PLANS.find(t=>t.id===e)??SENTRY_PLANS[0]}const CATEGORY_META=exports.CATEGORY_META=[{key:"errors",label:"Errors",format:"count",hint:"One per captured event, including repeats on issues you've ignored."},{key:"spans",label:"Spans",format:"count",hint:"Billed individually \u2014 one transaction is a bundle of many."},{key:"replays",label:"Replays",format:"count",hint:"One per session, whatever its length."},{key:"logBytes",label:"Logs",format:"bytes",hint:"Billed by volume received."},{key:"attachmentBytes",label:"Attachments",format:"bytes",hint:"Screenshots and view hierarchies attached to events."}];
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.MIN_PROJECTION_WINDOW_MS=void 0;exports.computeUsage=computeUsage;exports.projectMonthly=projectMonthly;exports.quotaFraction=quotaFraction;const EMPTY_TOTALS=()=>({errors:0,spans:0,replays:0,logBytes:0,attachmentBytes:0});function isFeedbackEvent(t){return t?.type==="feedback"}function transactionLabel(t){return t.summary||"transaction"}function computeUsage(t){const n=EMPTY_TOTALS();const o=new Map;const s=(a,e,r)=>{n[e]+=r;const i=`${e}:${a}`;const c=o.get(i);if(c){c.units+=r;c.occurrences+=1}else{o.set(i,{label:a,category:e,units:r,occurrences:1})}};for(const a of t){for(const e of a.items){switch(e.type){case"event":if(!isFeedbackEvent(e.payload))s(e.summary,"errors",1);break;case"transaction":s(transactionLabel(e),"spans",e.spanCount??1);break;case"replay_event":s("session replay","replays",1);break;case"log":s("logs","logBytes",e.bytes);break;case"attachment":s(e.summary||"attachment","attachmentBytes",e.bytes);break;default:break}}}const u=t[0]?.timestamp??0;const l=t[t.length-1]?.timestamp??0;return{totals:n,windowMs:Math.max(0,l-u),contributors:[...o.values()].sort((a,e)=>e.units-a.units)}}const MIN_PROJECTION_WINDOW_MS=exports.MIN_PROJECTION_WINDOW_MS=3e4;const MS_PER_MONTH=30*24*60*60*1e3;function projectMonthly(t){if(t.windowMs<MIN_PROJECTION_WINDOW_MS){return{usable:false,totals:EMPTY_TOTALS()}}const n=MS_PER_MONTH/t.windowMs;const o=EMPTY_TOTALS();for(const s of Object.keys(o)){o[s]=Math.round(t.totals[s]*n)}return{usable:true,totals:o}}function quotaFraction(t,n){if(n<=0)return t>0?Infinity:null;return t/n}
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest");var _usage=require("./usage");let nextId=1;function envelope(e,s=1e3){const o=e.map(t=>({type:t.type??"event",bytes:t.bytes??100,summary:t.summary??"",spanCount:t.spanCount,payload:t.payload,binary:t.binary}));return{id:nextId++,timestamp:s,origin:"js",items:o,totalBytes:o.reduce((t,a)=>t+a.bytes,0)}}(0,_vitest.describe)("computeUsage",()=>{(0,_vitest.it)("counts one error per event",()=>{const{totals:e}=(0,_usage.computeUsage)([envelope([{type:"event",summary:"boom"}]),envelope([{type:"event",summary:"boom again"}])]);(0,_vitest.expect)(e.errors).toBe(2)});(0,_vitest.it)("counts a transaction as its SPANS, not as one unit",()=>{const{totals:e}=(0,_usage.computeUsage)([envelope([{type:"transaction",summary:"/checkout",spanCount:12}])]);(0,_vitest.expect)(e.spans).toBe(12);(0,_vitest.expect)(e.errors).toBe(0)});(0,_vitest.it)("falls back to a single span when the count is unknown",()=>{const{totals:e}=(0,_usage.computeUsage)([envelope([{type:"transaction",summary:"//",spanCount:void 0}])]);(0,_vitest.expect)(e.spans).toBe(1)});(0,_vitest.it)("does not bill a feedback event as an error",()=>{const{totals:e}=(0,_usage.computeUsage)([envelope([{type:"event",summary:"feedback",payload:{type:"feedback"}}])]);(0,_vitest.expect)(e.errors).toBe(0)});(0,_vitest.it)("meters logs and attachments by bytes, replays by session",()=>{const{totals:e}=(0,_usage.computeUsage)([envelope([{type:"log",bytes:2048}]),envelope([{type:"attachment",bytes:4096,summary:"screenshot.png"}]),envelope([{type:"replay_event",bytes:500}])]);(0,_vitest.expect)(e.logBytes).toBe(2048);(0,_vitest.expect)(e.attachmentBytes).toBe(4096);(0,_vitest.expect)(e.replays).toBe(1)});(0,_vitest.it)("ignores item types it does not model rather than guessing",()=>{const{totals:e}=(0,_usage.computeUsage)([envelope([{type:"session"},{type:"client_report"},{type:"profile"}])]);(0,_vitest.expect)(e).toEqual({errors:0,spans:0,replays:0,logBytes:0,attachmentBytes:0})});(0,_vitest.it)("groups contributors by label and ranks them by units",()=>{const{contributors:e}=(0,_usage.computeUsage)([envelope([{type:"transaction",summary:"/cheap",spanCount:2}]),envelope([{type:"transaction",summary:"/expensive",spanCount:30}]),envelope([{type:"transaction",summary:"/expensive",spanCount:30}])]);(0,_vitest.expect)(e[0]).toMatchObject({label:"/expensive",units:60,occurrences:2});(0,_vitest.expect)(e[1]).toMatchObject({label:"/cheap",units:2})});(0,_vitest.it)("measures the window between first and last envelope",()=>{const e=(0,_usage.computeUsage)([envelope([{type:"event"}],1e4),envelope([{type:"event"}],7e4)]);(0,_vitest.expect)(e.windowMs).toBe(6e4)});(0,_vitest.it)("has an empty, zeroed report for no envelopes",()=>{const e=(0,_usage.computeUsage)([]);(0,_vitest.expect)(e.windowMs).toBe(0);(0,_vitest.expect)(e.contributors).toEqual([]);(0,_vitest.expect)(e.totals.errors).toBe(0)})});(0,_vitest.describe)("projectMonthly",()=>{(0,_vitest.it)("refuses to project from a window too short to mean anything",()=>{const e=(0,_usage.computeUsage)([envelope([{type:"event"}],0),envelope([{type:"event"}],_usage.MIN_PROJECTION_WINDOW_MS-1)]);(0,_vitest.expect)((0,_usage.projectMonthly)(e).usable).toBe(false)});(0,_vitest.it)("extrapolates the observed rate to 30 days",()=>{const e=60*60*1e3;const s={totals:{errors:10,spans:0,replays:0,logBytes:0,attachmentBytes:0},windowMs:e,contributors:[]};const o=(0,_usage.projectMonthly)(s);(0,_vitest.expect)(o.usable).toBe(true);(0,_vitest.expect)(o.totals.errors).toBe(7200)})});(0,_vitest.describe)("quotaFraction",()=>{(0,_vitest.it)("reports usage as a fraction of the allowance",()=>{(0,_vitest.expect)((0,_usage.quotaFraction)(2500,5e3)).toBe(.5)});(0,_vitest.it)("returns null for an unused category the plan excludes",()=>{(0,_vitest.expect)((0,_usage.quotaFraction)(0,0)).toBeNull()});(0,_vitest.it)("is infinite when a plan excludes a category the app still uses",()=>{(0,_vitest.expect)((0,_usage.quotaFraction)(5,0)).toBe(Infinity)})});
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.SNAPSHOT_STRING_LIMIT=void 0;exports.capString=capString;exports.sanitizePayload=sanitizePayload;const MAX_DEPTH=8;const MAX_ARRAY=200;const MAX_KEYS=200;const SNAPSHOT_STRING_LIMIT=exports.SNAPSHOT_STRING_LIMIT=2*1024;function capString(t,r=SNAPSHOT_STRING_LIMIT){if(t.length<=r)return t;return`${t.slice(0,r)}\u2026 [${t.length-r} more]`}function sanitizeValue(t,r,i){if(t===null)return null;if(typeof t==="string")return capString(t);if(typeof t==="boolean")return t;if(typeof t==="number")return Number.isFinite(t)?t:String(t);if(typeof t==="undefined")return"undefined";if(typeof t==="bigint")return`${String(t)}n`;if(typeof t==="function"){return`\u0192 ${t.name||"(anonymous)"}`}if(typeof t==="symbol")return t.toString();if(t instanceof Error){return{name:t.name,message:capString(t.message),stack:t.stack?capString(t.stack,4*1024):t.stack}}if(r>=MAX_DEPTH)return Array.isArray(t)?"[Array]":"{\u2026}";const o=t;if(i.has(o))return"[Circular]";i.add(o);try{if(Array.isArray(t)){const n=t.slice(0,MAX_ARRAY).map(s=>sanitizeValue(s,r+1,i));if(t.length>MAX_ARRAY)n.push(`\u2026 ${t.length-MAX_ARRAY} more`);return n}const e={};for(const n of Object.keys(o).slice(0,MAX_KEYS)){try{e[n]=sanitizeValue(o[n],r+1,i)}catch{e[n]="[Unserializable]"}}return e}finally{i.delete(o)}}function sanitizePayload(t){const r=new WeakSet;return sanitizeValue(t,0,r)}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.clearEnvelopes=clearEnvelopes;exports.getAttachStatus=getAttachStatus;exports.getEnvelopes=getEnvelopes;exports.getMirroredUsage=getMirroredUsage;exports.onClear=onClear;exports.recordEnvelope=recordEnvelope;exports.replaceAttachStatus=replaceAttachStatus;exports.replaceEnvelopes=replaceEnvelopes;exports.replaceUsage=replaceUsage;exports.setAttachStatus=setAttachStatus;exports.subscribe=subscribe;var _sharedUi=require("@buoy-gg/shared-ui");const MAX_ENVELOPES=500;const store=(0,_sharedUi.createToolStore)({id:"sentry",max:MAX_ENVELOPES,order:"append",coalesce:"frame"});let status="searching";let mirroredUsage=null;function recordEnvelope(e,t={}){store.add({...e,id:store.allocId()});if(t.urgent)store.flushSync(true)}function setAttachStatus(e){if(status===e)return;status=e;store.notify()}function subscribe(e){return store.subscribe(e)}function getEnvelopes(){return store.getSnapshot()}function getAttachStatus(){return status}function clearEnvelopes(){store.clear()}function replaceEnvelopes(e){store.set(e)}function getMirroredUsage(){return mirroredUsage}function replaceUsage(e){mirroredUsage=e??null;store.notify()}function replaceAttachStatus(e){setAttachStatus(e)}function onClear(e){return store.onClear(e)}
@@ -0,0 +1 @@
1
+ "use strict";Object.defineProperty(exports,"__esModule",{value:true});exports.sentrySyncAdapter=void 0;exports.wireDrops=wireDrops;var _sharedUi=require("@buoy-gg/shared-ui");var _sentryEnvelopeStore=require("../store/sentryEnvelopeStore");var _usage=require("../quota/usage");var _dropStore=require("../drops/dropStore");const MAX_WIRE_DROPS=50;function wireDrops(e){const s=t=>t.category==="span"||t.category==="transaction";const r=e.filter(t=>!s(t)).slice(-20);const o=e.filter(s).slice(-(MAX_WIRE_DROPS-r.length));return[...r,...o].sort((t,n)=>t.timestamp-n.timestamp||t.id-n.id)}const MAX_SNAPSHOT_BYTES=1.5*1024*1024;const MAX_ENTRY_BYTES=32*1024;const PAYLOAD_OMITTED=Object.freeze({__buoyTruncated:true,note:"Payload omitted \u2014 inspect it on-device."});const wireCache=new WeakMap;function toWireEntry(e){const s=wireCache.get(e);if(s)return s;const r=(0,_sharedUi.approxJsonSize)(e,MAX_ENTRY_BYTES);const o=r.bytes<=MAX_ENTRY_BYTES?{envelope:e,bytes:r.bytes}:(()=>{const t={...e,items:e.items.map(n=>({...n,payload:n.payload===void 0?void 0:PAYLOAD_OMITTED}))};return{envelope:t,bytes:(0,_sharedUi.approxJsonSize)(t,MAX_ENTRY_BYTES).bytes}})();wireCache.set(e,o);return o}function newestFitting(e){const s=[];let r=48;for(let o=e.length-1;o>=0;o--){const t=toWireEntry(e[o]);if(r+t.bytes>MAX_SNAPSHOT_BYTES&&s.length>0)break;s.push(t.envelope);r+=t.bytes}s.reverse();return s}const sentrySyncAdapter=exports.sentrySyncAdapter={version:1,getSnapshot(){const e=(0,_sentryEnvelopeStore.getEnvelopes)();const s=(0,_dropStore.getDrops)();const r=(0,_usage.computeUsage)(e);const o=(0,_usage.projectMonthly)(r);return{status:(0,_sentryEnvelopeStore.getAttachStatus)(),envelopes:newestFitting(e),usage:{session:r.totals,projectedMonthly:o.usable?o.totals:null,windowMs:r.windowMs,topContributors:r.contributors.slice(0,8).map(t=>({label:t.label,category:t.category,units:t.units}))},drops:{summary:(0,_dropStore.summarizeDrops)(s),recent:wireDrops(s)}}},subscribe(e){const s=(0,_sentryEnvelopeStore.subscribe)(e);const r=(0,_dropStore.subscribeDrops)(e);return()=>{s();r()}},actions:{clearEnvelopes(){(0,_sentryEnvelopeStore.clearEnvelopes)();(0,_dropStore.clearDrops)();return{cleared:true}}}};
@@ -0,0 +1 @@
1
+ "use strict";var _vitest=require("vitest");var _sentrySyncAdapter=require("./sentrySyncAdapter");const drop=(r,e,t="other")=>({id:r,timestamp:r,reason:t,category:e,quantity:1,detail:`${e} ${r}`,source:"reported"});(0,_vitest.describe)("wireDrops",()=>{(0,_vitest.it)("keeps a dropped error on the wire when hundreds of span drops came after it",()=>{const r=[drop(1,"error","before_send"),...Array.from({length:200},(t,s)=>drop(s+2,"span"))];const e=(0,_sentrySyncAdapter.wireDrops)(r);(0,_vitest.expect)(e.length).toBeLessThanOrEqual(50);(0,_vitest.expect)(e.some(t=>t.reason==="before_send")).toBe(true);(0,_vitest.expect)(e[0].id).toBe(1)})});
@@ -0,0 +1 @@
1
+ "use strict";
@@ -0,0 +1 @@
1
+ "use strict";import{useEffect as t}from"react";import{installSentryCapture as o}from"./capture/attach";export function SentryRoot({getClient:r}={}){t(()=>{o(r?{getClient:r}:{})},[r]);return null}
@@ -0,0 +1 @@
1
+ "use strict";let n=null;export function setAuditSource(t){n=t??null}function r(t){try{const e=t._integrations;return e?Object.keys(e):[]}catch{return[]}}export function readAuditInput(){if(!n)return null;try{const t=n.getOptions?.();if(!t)return null;return{options:{...t},integrations:r(n),isDev:typeof __DEV__!=="undefined"&&__DEV__}}catch{return null}}
@@ -0,0 +1 @@
1
+ "use strict";const l=/[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,}/i;const _=/\beyJ[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]{8,}\.[A-Za-z0-9_-]+/;const k=/\bBearer\s+[A-Za-z0-9._\-+/=]{12,}/i;const A=/\b(?:\d[ -]?){13,16}\b/;function p(o){let t=0;let e=false;for(let r=o.length-1;r>=0;r--){let i=o.charCodeAt(r)-48;if(i<0||i>9)return false;if(e){i*=2;if(i>9)i-=9}t+=i;e=!e}return t%10===0}const g=/^(?:4|5[1-5]|2[2-7]|3[47]|3(?:0[0-5]|[68])|6(?:011|5|4[4-9]))/;const y=/\+\d{1,3}[\s-]?\(?\d{2,4}\)?[\s-]?\d{3,4}[\s-]?\d{3,4}\b/;const b=/^(authorization|cookie|set-cookie|x-api-key|api[-_]?key|password|passwd|secret|token|access[-_]?token|refresh[-_]?token|session[-_]?id|ssn)$/i;const h=/^(lat|latitude|lng|lon|longitude)$/i;const m=/(^|\.)(event_id|trace_id|span_id|parent_span_id|dsn|sdk\.|debug_meta|modules)/;const E=8;function a(o){const t=o.trim();if(t.length<=8)return`${t.slice(0,2)}\u2026`;return`${t.slice(0,4)}\u2026${t.slice(-2)}`}function I(o,t){if(_.test(t)||k.test(t))return"auth-token";if(b.test(o))return"sensitive-key";if(l.test(t))return"email";const e=A.exec(t);if(e){const r=e[0].replace(/[ -]/g,"");if(r.length>=13&&g.test(r)&&p(r)){return"credit-card"}}if(y.test(t))return"phone";return null}export function scanForPii(o,t=25){const e=[];const r=new WeakSet;const i=(n,c,f)=>{if(e.length>=t||f>E)return;if(n===null||n===void 0)return;if(typeof n==="number"){const s=c.split(".").pop()??"";if(h.test(s)){e.push({kind:"coordinates",path:c,sample:a(String(n))})}return}if(typeof n==="string"){if(m.test(c))return;const s=c.split(".").pop()??"";const d=I(s,n);if(d)e.push({kind:d,path:c,sample:a(n)});return}if(typeof n!=="object")return;const u=n;if(r.has(u))return;r.add(u);if(Array.isArray(n)){for(let s=0;s<n.length&&e.length<t;s++){i(n[s],`${c}[${s}]`,f+1)}return}for(const[s,d]of Object.entries(u)){if(e.length>=t)return;i(d,c?`${c}.${s}`:s,f+1)}};i(o,"",0);return e}export const PII_KIND_LABEL={email:"Email address","auth-token":"Auth token","credit-card":"Card number",phone:"Phone number",coordinates:"Location","sensitive-key":"Sensitive field"};
@@ -0,0 +1 @@
1
+ "use strict";import{describe as l,it as a,expect as e}from"vitest";import{scanForPii as n}from"./pii";const o=t=>n(t).map(i=>i.kind);const d=t=>n(t).map(i=>i.path);function h(t){let i=0;let s=false;for(let c=t.length-1;c>=0;c--){let r=t.charCodeAt(c)-48;if(s){r*=2;if(r>9)r-=9}i+=r;s=!s}return i%10===0}l("scanForPii \u2014 what it finds",()=>{a("finds an email and names the path to fix",()=>{const t=n({user:{email:"ada@example.com"}});e(t[0].kind).toBe("email");e(t[0].path).toBe("user.email")});a("finds a JWT and a bearer header",()=>{e(o({token:"eyJhbGciOiJIUzI1NiJ9.eyJzdWIiOiIxMjM0NSJ9.abcdefghijk"})).toContain("auth-token");e(o({note:"Bearer sk_live_ABCDEFGHIJKLMNOP"})).toContain("auth-token")});a("flags a sensitive key by its NAME, whatever the value looks like",()=>{e(o({password:"hunter2"})).toEqual(["sensitive-key"]);e(o({headers:{Cookie:"sid=1"}})).toEqual(["sensitive-key"])});a("finds a card number and an international phone number",()=>{e(o({card:"4111 1111 1111 1111"})).toContain("credit-card");e(o({contact:"+1 415 555 0132"})).toContain("phone")});a("finds coordinates by key name",()=>{e(o({latitude:51.5074})).toContain("coordinates")});a("walks nested objects and arrays",()=>{e(d({a:{b:[{email:"x@y.co"}]}})).toEqual(["a.b[0].email"])})});l("scanForPii \u2014 what it must NOT flag",()=>{a("ignores Sentry's own ids and DSN, which naive patterns match",()=>{e(n({event_id:"b6154766b46446329f13fc9cf50e75f0",trace_id:"a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6",dsn:"https://abc123@o447951.ingest.sentry.io/5428561"})).toEqual([])});a("ignores ordinary numbers that are not coordinates",()=>{e(n({count:42,timestamp:1788325151403})).toEqual([])});a("ignores a bare long number that is not card-shaped",()=>{e(n({note:"order 12345"})).toEqual([])});a("ignores a millisecond timestamp, which is 13 digits like a card",()=>{e(n({note:"timeout after 1788325151403"})).toEqual([]);e(n({note:"1788325151403"})).toEqual([])});a("ignores an epoch timestamp that happens to satisfy Luhn",()=>{e(h("1756934567807")).toBe(true);e(n({note:"timeout after 1756934567807"})).toEqual([]);e(n({note:"1756934567807"})).toEqual([])});a("still catches a real card number, which satisfies Luhn",()=>{e(o({note:"4111111111111111"})).toContain("credit-card")});a("catches the other issuers, not only Visa",()=>{e(o({note:"5555555555554444"})).toContain("credit-card");e(o({note:"378282246310005"})).toContain("credit-card");e(o({note:"6011111111111117"})).toContain("credit-card")})});l("scanForPii \u2014 safety properties",()=>{a("never stores the value it found",()=>{const t="ada.lovelace@analyticalengine.org";const[i]=n({email:t});e(i.sample).not.toContain("lovelace");e(i.sample).not.toBe(t);e(i.sample.startsWith("ada.")).toBe(true)});a("redacts even a short value",()=>{const[t]=n({password:"abc"});e(t.sample).not.toBe("abc")});a("survives a cycle instead of hanging",()=>{const t={email:"a@b.co"};t.self=t;e(o(t)).toEqual(["email"])});a("caps the number of findings so one payload cannot flood the panel",()=>{const t=Object.fromEntries(Array.from({length:100},(i,s)=>[`email${s}`,`user${s}@example.com`]));e(n(t,25)).toHaveLength(25)});a("returns nothing for empty or primitive payloads",()=>{e(n(null)).toEqual([]);e(n(void 0)).toEqual([]);e(n({})).toEqual([])})});
@@ -0,0 +1 @@
1
+ "use strict";const s=a=>typeof a==="number"&&Number.isFinite(a)?a:null;export function auditConfig(a){const{options:e,isDev:n}=a;const l=[];const t=u=>l.push(u);if(!e.dsn){t({id:"no-dsn",severity:"critical",category:"correctness",title:"No DSN",detail:"The SDK is initialized without a DSN, so nothing is sent anywhere. Usually an env var that didn't reach the bundle."})}if(!e.release||!e.dist){t({id:"release-dist",severity:"warning",category:"correctness",title:"release or dist not set explicitly",detail:"Stack traces are only symbolicated when release and dist match the source maps you uploaded, exactly. Sentry never reprocesses old events, so a mismatch means minified traces forever \u2014 set both explicitly and use the same values at upload."})}if(e.debug===true&&!n){t({id:"debug-in-release",severity:"warning",category:"correctness",title:"debug is on in a release build",detail:"Verbose SDK logging is shipping to users. Gate it: debug: __DEV__."})}if(e.enableNative===false){t({id:"native-disabled",severity:"warning",category:"correctness",title:"Native layer disabled",detail:"enableNative: false gives up native crash capture, offline caching, and release-health sessions \u2014 hard crashes will never be reported."})}const i=s(e.tracesSampleRate);if(i!==null&&i>=1&&!n){t({id:"traces-full",severity:"critical",category:"quota",title:"tracesSampleRate is 1.0 in production",detail:"Every transaction is sent, and spans are billed individually \u2014 this is the fastest way to exhaust a span quota. Lower the rate, or use tracesSampler to keep full detail only on the routes you care about."})}else if(i!==null&&i>.2&&!n){t({id:"traces-high",severity:"warning",category:"quota",title:`tracesSampleRate is ${i}`,detail:"Spans are billed per span, so tracing volume scales with this rate times the spans each transaction carries. Check the Cost tab before shipping it."})}const r=s(e.replaysSessionSampleRate);if(r!==null&&r>.01&&!n){t({id:"replay-session-rate",severity:"critical",category:"quota",title:`replaysSessionSampleRate is ${r}`,detail:"Replays are billed per session and free plans include only 50 a month, so anything above a fraction of a percent burns the quota on a real user base. Prefer replaysOnErrorSampleRate, which records only sessions that hit an error."})}if(e.attachScreenshot===true&&e.attachViewHierarchy===true){t({id:"heavy-attachments",severity:"warning",category:"quota",title:"Screenshots and view hierarchies on every error",detail:"Both attachments ride every error event and are billed by volume. Keep the one you actually open when debugging."})}if(e.enableLogs===true&&e.enableAutoConsoleLogs!==false){t({id:"auto-console-logs",severity:"info",category:"quota",title:"Console output is forwarded as logs",detail:"Every console.* call becomes billable log volume. Fine if your app is quiet; expensive if it logs in a render or a loop."})}const c=s(e.profilesSampleRate);if(c!==null&&c>0){t({id:"profiling-on",severity:"info",category:"quota",title:"Profiling is enabled",detail:"Profiling is billed by the hour and free plans cannot use it at all \u2014 profiles sent from a free-plan app are simply discarded."})}if(e.sendDefaultPii===true){t({id:"send-default-pii",severity:"critical",category:"privacy",title:"sendDefaultPii is on",detail:"The SDK attaches identifying data \u2014 IP address, and on some versions request headers including Authorization and Cookie \u2014 to every event. Turn it off unless you have a reason and a data-retention policy that covers it."})}const d=s(e.replaysOnErrorSampleRate);if(r!==null&&r>0||d!==null&&d>0){t({id:"replay-masking",severity:"info",category:"privacy",title:"Session Replay is recording",detail:"Replay captures the screen. Confirm masking covers every field showing personal data \u2014 the defaults mask text and images, and a custom unmasked view opts out of that."})}const o=s(e.maxBreadcrumbs);if(o!==null&&o>100){t({id:"many-breadcrumbs",severity:"info",category:"privacy",title:`maxBreadcrumbs is ${o}`,detail:"Breadcrumbs accumulate and ride every event, growing both payload size and the chance that something logged along the way is personal data."})}return l}export function worstSeverity(a){if(a.some(e=>e.severity==="critical"))return"critical";if(a.some(e=>e.severity==="warning"))return"warning";if(a.length>0)return"info";return null}
@@ -0,0 +1 @@
1
+ "use strict";import{describe as r,it as n,expect as e}from"vitest";import{auditConfig as s,worstSeverity as l}from"./rules";const t=(i,o={})=>({options:{dsn:"https://k@o0.ingest.sentry.io/1",release:"app@1.0.0",dist:"1",...i},integrations:[],isDev:false,...o});const a=i=>s(i).map(o=>o.id);r("auditConfig \u2014 correctness",()=>{n("flags a missing DSN as critical, because nothing is sent at all",()=>{const i=s(t({dsn:void 0}));const o=i.find(c=>c.id==="no-dsn");e(o?.severity).toBe("critical")});n("flags release or dist left unset \u2014 source maps will never match",()=>{e(a(t({release:void 0}))).toContain("release-dist");e(a(t({dist:void 0}))).toContain("release-dist");e(a(t({}))).not.toContain("release-dist")});n("flags debug left on in a release build, but not in dev",()=>{e(a(t({debug:true}))).toContain("debug-in-release");e(a(t({debug:true},{isDev:true}))).not.toContain("debug-in-release")});n("flags a disabled native layer \u2014 hard crashes would go unreported",()=>{e(a(t({enableNative:false}))).toContain("native-disabled")})});r("auditConfig \u2014 quota",()=>{n("flags full tracing in production as critical",()=>{const i=s(t({tracesSampleRate:1})).find(o=>o.id==="traces-full");e(i?.severity).toBe("critical");e(i?.category).toBe("quota")});n("does not flag full tracing in a dev build, where volume is irrelevant",()=>{e(a(t({tracesSampleRate:1},{isDev:true}))).not.toContain("traces-full")});n("warns on a merely high trace rate, separately from a full one",()=>{const i=a(t({tracesSampleRate:.5}));e(i).toContain("traces-high");e(i).not.toContain("traces-full")});n("leaves a modest trace rate alone",()=>{e(a(t({tracesSampleRate:.1}))).not.toContain("traces-high")});n("flags session replay sampling above a fraction of a percent",()=>{e(a(t({replaysSessionSampleRate:.1}))).toContain("replay-session-rate");e(a(t({replaysSessionSampleRate:.005}))).not.toContain("replay-session-rate")});n("flags screenshots and view hierarchies riding every error together",()=>{e(a(t({attachScreenshot:true,attachViewHierarchy:true}))).toContain("heavy-attachments");e(a(t({attachScreenshot:true}))).not.toContain("heavy-attachments")});n("notes auto console logging, and respects an explicit opt-out",()=>{e(a(t({enableLogs:true}))).toContain("auto-console-logs");e(a(t({enableLogs:true,enableAutoConsoleLogs:false}))).not.toContain("auto-console-logs")});n("notes profiling, which free plans cannot use at all",()=>{e(a(t({profilesSampleRate:.1}))).toContain("profiling-on");e(a(t({profilesSampleRate:0}))).not.toContain("profiling-on")})});r("auditConfig \u2014 privacy",()=>{n("flags sendDefaultPii as critical",()=>{const i=s(t({sendDefaultPii:true})).find(o=>o.id==="send-default-pii");e(i?.severity).toBe("critical");e(i?.category).toBe("privacy")});n("raises masking as a question whenever replay records at all",()=>{e(a(t({replaysOnErrorSampleRate:1}))).toContain("replay-masking");e(a(t({replaysSessionSampleRate:.001}))).toContain("replay-masking");e(a(t({}))).not.toContain("replay-masking")});n("notes an unusually large breadcrumb buffer",()=>{e(a(t({maxBreadcrumbs:300}))).toContain("many-breadcrumbs");e(a(t({maxBreadcrumbs:100}))).not.toContain("many-breadcrumbs")})});r("auditConfig \u2014 a clean config",()=>{n("says nothing about a sensible production setup",()=>{e(s(t({tracesSampleRate:.1,sampleRate:1,sendDefaultPii:false,debug:false}))).toEqual([])})});r("worstSeverity",()=>{n("reports the most severe finding present",()=>{const i=s(t({sendDefaultPii:true,maxBreadcrumbs:300}));e(l(i)).toBe("critical")});n("is null when there is nothing to report",()=>{e(l([])).toBeNull()})});
@@ -0,0 +1 @@
1
+ "use strict";import{loadSentrySDK as b}from"./sentrySDK";import{approxJsonSize as S}from"@buoy-gg/shared-ui";import{sanitizePayload as v}from"../store/sanitize";import{recordEnvelope as C,setAttachStatus as y,getAttachStatus as p}from"../store/sentryEnvelopeStore";import{observeDrops as I}from"../drops/observe";import{setAuditSource as T}from"../audit/auditSource";const w=8*1024*1024;const x=500;const E=60;function A(e){return typeof e==="object"&&e!==null&&typeof e.byteLength==="number"&&ArrayBuffer.isView(e)}function P(e){if(typeof e==="string")return e.length;if(A(e))return e.byteLength;return S(e,w).bytes}function o(...e){for(const r of e){if(typeof r==="string"&&r.length>0)return r}return void 0}function k(e,r){const t=r;try{switch(e){case"event":{const n=t?.exception?.values?.[0];if(n){const a=o(n.value,n.type)??"exception";return n.type&&n.value?`${n.type}: ${n.value}`:a}const i=o(t?.message?.formatted,t?.message,t?.logentry?.message);if(i)return i;if(t?.type==="feedback")return"user feedback";return o(t?.transaction)??"event"}case"transaction":{return o(t?.transaction)??"transaction"}case"session":return o(t?.status)??"session";case"sessions":return"session aggregates";case"client_report":{const n=Array.isArray(t?.discarded_events)?t.discarded_events.reduce((i,a)=>i+(a?.quantity??1),0):0;return`${n} discarded event${n===1?"":"s"}`}case"log":{const n=Array.isArray(t?.items)?t.items.length:void 0;return n!=null?`${n} log${n===1?"":"s"}`:"logs"}case"attachment":return o(t?.filename)??"attachment";case"profile":case"profile_chunk":return"profile";case"user_report":case"feedback":return"user feedback";case"replay_event":case"replay_recording":return"replay";case"check_in":return o(t?.monitor_slug)??"check-in";default:return e}}catch{return e}}function $(e,r){if(e!=="transaction")return void 0;const t=r?.spans;return Array.isArray(t)?t.length+1:1}export function parseEnvelope(e){const r=Date.now();try{if(!Array.isArray(e)||!Array.isArray(e[1])){throw new Error("not an envelope")}const[t,n]=e;const i=[];let a=0;for(const h of n){if(!Array.isArray(h))continue;const[f,c]=h;const u=typeof f?.type==="string"?f.type:"unknown";const g=P(c);a+=g;const d=A(c);i.push({type:u,bytes:g,summary:d?k(u,f):k(u,c),spanCount:$(u,c),binary:d||void 0,payload:d?void 0:v(c)})}return{timestamp:r,origin:"js",eventId:typeof t?.event_id==="string"?t.event_id:void 0,header:v(t),items:i,totalBytes:a}}catch{return{timestamp:r,origin:"js",items:[{type:"unknown",bytes:0,summary:"unparseable envelope"}],totalBytes:0}}}const _=new WeakSet;let m=false;let s=null;let l;export function attachToClient(e){const r=e;if(!r||typeof r.on!=="function")return false;if(_.has(r))return true;_.add(r);try{r.on("beforeEnvelope",t=>{try{const n=parseEnvelope(t);const i=n.items.some(a=>a.type==="event");C(n,{urgent:i})}catch{}})}catch{return false}try{I(r)}catch{}try{T(r)}catch{}y("attached");return true}function B(){if(l){try{return{client:l(),sdkPresent:true}}catch{return{client:void 0,sdkPresent:true}}}const e=b();if(!e||typeof e.getClient!=="function"){return{client:void 0,sdkPresent:false}}try{return{client:e.getClient(),sdkPresent:true}}catch{return{client:void 0,sdkPresent:true}}}export function installSentryCapture(e={}){if(e.getClient)l=e.getClient;if(m&&p()==="attached")return;if(m&&s!==null)return;m=true;let r=0;const t=()=>{r+=1;const{client:n,sdkPresent:i}=B();if(n&&attachToClient(n)){if(s!==null){clearInterval(s);s=null}return}if(!i&&!l){y("sdk-not-found");if(s!==null){clearInterval(s);s=null}return}if(r>=E){y("no-client");if(s!==null){clearInterval(s);s=null}}};t();if(p()==="attached"||s!==null)return;if(p()==="sdk-not-found")return;s=setInterval(t,x)}
@@ -0,0 +1 @@
1
+ "use strict";import{describe as r,it as n,expect as t}from"vitest";import{parseEnvelope as a}from"./attach";function s(e,o){return[e,o]}r("parseEnvelope",()=>{n("reads the event id and item types off a normal envelope",()=>{const e=a(s({event_id:"abc123",sent_at:"2026-09-02T00:00:00Z"},[[{type:"event"},{exception:{values:[{type:"TypeError",value:"x is not a function"}]}}]]));t(e.eventId).toBe("abc123");t(e.items).toHaveLength(1);t(e.items[0].type).toBe("event");t(e.items[0].summary).toBe("TypeError: x is not a function")});n("counts a transaction's spans as children plus the root",()=>{const e=a(s({},[[{type:"transaction"},{transaction:"/checkout",spans:[{},{},{}]}]]));t(e.items[0].spanCount).toBe(4);t(e.items[0].summary).toBe("/checkout")});n("treats a transaction with no spans array as one span",()=>{const e=a(s({},[[{type:"transaction"},{transaction:"/"}]]));t(e.items[0].spanCount).toBe(1)});n("leaves spanCount unset for everything that is not a transaction",()=>{const e=a(s({},[[{type:"event"},{message:"hi"}]]));t(e.items[0].spanCount).toBeUndefined()});n("records binary payloads by size without keeping their content",()=>{const e=a(s({},[[{type:"attachment",filename:"screenshot.png"},new Uint8Array(2048)]]));t(e.items[0].binary).toBe(true);t(e.items[0].bytes).toBe(2048);t(e.items[0].payload).toBeUndefined();t(e.items[0].summary).toBe("screenshot.png")});n("summarizes a client report by how many events were discarded",()=>{const e=a(s({},[[{type:"client_report"},{discarded_events:[{quantity:3},{quantity:2}]}]]));t(e.items[0].summary).toBe("5 discarded events")});n("survives a malformed envelope instead of throwing on the send path",()=>{const e=a("not an envelope at all");t(e.items[0].summary).toBe("unparseable envelope");t(e.totalBytes).toBe(0)});n("survives an envelope whose payload holds a cycle",()=>{const e={message:"loop"};e.self=e;const o=a(s({},[[{type:"event"},e]]));t(o.items[0].type).toBe("event");t(JSON.stringify(o.items[0].payload)).toContain("[Circular]")});n("sums item sizes into the envelope total",()=>{const e=a(s({},[[{type:"attachment"},new Uint8Array(1e3)],[{type:"attachment"},new Uint8Array(500)]]));t(e.totalBytes).toBe(1500)})});
@@ -0,0 +1 @@
1
+ "use strict";export function loadSentrySDK(){try{return require("@sentry/react-native")}catch{return null}}
@@ -0,0 +1 @@
1
+ "use strict";export function loadSentrySDK(){return null}
@@ -0,0 +1 @@
1
+ "use strict";export{SentryIcon}from"@buoy-gg/shared-ui";export const SENTRY_ICON_COLOR="#9945FF";
@@ -0,0 +1 @@
1
+ "use strict";export{SentryIcon}from"@buoy-gg/shared-ui";export const SENTRY_ICON_COLOR="#9945FF";
@@ -0,0 +1 @@
1
+ "use strict";import u from"react";import{JsModal as m}from"@buoy-gg/shared-ui";import{useSentryController as c}from"../devtools/useSentryController";import{SentryHeader as l}from"../devtools/SentryHeader";import{SentryBody as a}from"../devtools/SentryBody";import{jsx as e}from"react/jsx-runtime";export function SentryModal({visible:r,onClose:t,onBack:n,onMinimize:i,persistenceKey:s}){const o=c();return e(m,{visible:r,onClose:t,onMinimize:i,persistenceKey:s??"buoy-sentry",header:{showToggleButton:true,customContent:e(l,{c:o,onBack:n})},enablePersistence:true,initialMode:"bottomSheet",disableScrollWrapper:true,children:e(a,{c:o})})}
@@ -0,0 +1 @@
1
+ "use strict";import B from"react";import{View as y,Text as i,ScrollView as T,StyleSheet as f}from"react-native";import{night as s,DevToolsCard as c,NightSectionLabel as p,NightFootnote as d,Pill as m,ToolEmptyState as v}from"@buoy-gg/shared-ui";import{SENTRY_BODY_TOP_INSET as N}from"./layout";import{PII_KIND_LABEL as u}from"../audit/pii";import{monoFont as C}from"@buoy-gg/shared-ui";import{jsx as o,jsxs as r,Fragment as g}from"react/jsx-runtime";const S=C;const l={critical:"#F87171",warning:"#FBBF24",info:"#60A5FA"};const I={quota:"Quota",privacy:"Privacy",correctness:"Correctness"};export function SentryAuditView({c:b}){const{audit:a,piiFindings:n}=b;if(!a){return o(v,{testID:"sentry-audit-unavailable",otto:"scanning",title:"No client to audit",message:"The audit reads the options Sentry.init actually resolved, so it needs a live client. Once the tool attaches, the resolved config is graded here."})}const L=a.findings.length===0&&n.length===0;return r(T,{style:e.container,contentContainerStyle:e.content,testID:"sentry-audit-view",children:[L?r(c,{testID:"sentry-audit-clean",contentStyle:e.cardBody,children:[o(i,{style:e.title,children:"Nothing to flag"}),o(d,{tone:"secondary",style:e.inCard,children:"The resolved config raised no findings, and nothing sent this session matched a personal-data pattern."})]}):null,a.findings.length>0?r(g,{children:[o(p,{style:e.sectionLabel,children:"CONFIG"}),a.findings.map(t=>r(c,{testID:`sentry-audit-${t.id}`,style:[e.stripe,{borderLeftColor:l[t.severity]}],contentStyle:e.cardBody,accessible:true,accessibilityLabel:`${t.severity} ${t.category} finding. ${t.title}. ${t.detail}`,children:[r(y,{style:e.head,children:[o(i,{style:e.title,children:t.title}),o(m,{label:I[t.category]??t.category,color:l[t.severity],variant:"tinted"})]}),o(d,{tone:"secondary",style:e.inCard,children:t.detail})]},t.id))]}):null,n.length>0?r(g,{children:[o(p,{style:e.sectionLabel,children:"PERSONAL DATA IN SENT PAYLOADS"}),o(d,{style:e.piiNote,children:"Values are redacted here \u2014 the path is what you need to fix."}),n.map((t,h)=>r(c,{testID:`sentry-pii-${h}`,style:[e.stripe,{borderLeftColor:l.critical}],contentStyle:e.cardBody,accessible:true,accessibilityLabel:`${u[t.kind]} at ${t.path}, value redacted as ${t.sample}`,children:[r(y,{style:e.head,children:[o(m,{label:u[t.kind],color:l.critical,variant:"tinted"}),o(i,{style:e.sample,children:t.sample})]}),o(i,{style:e.path,selectable:true,children:t.path})]},`${t.path}-${h}`))]}):null]})}const e=f.create({container:{flex:1,backgroundColor:"transparent"},content:{paddingTop:N,paddingBottom:24},sectionLabel:{marginHorizontal:12,marginTop:10,marginBottom:2},piiNote:{marginHorizontal:12,marginTop:0,marginBottom:2},cardBody:{gap:6},inCard:{marginTop:2,marginLeft:0},stripe:{borderLeftWidth:3,borderRadius:8},head:{flexDirection:"row",alignItems:"center",justifyContent:"space-between",gap:8},title:{color:s.color.text,fontSize:13,fontWeight:"700",flexShrink:1},sample:{color:s.color.textTertiary,fontSize:10,fontFamily:S},path:{color:s.color.textSecondary,fontSize:11,fontFamily:S}});