@arvoretech/bug-jar 0.3.1 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -1,12 +1,12 @@
1
1
  # 🪲 Bug Jar
2
2
 
3
- Capture everything for non-technical people to help debug. One script tag, zero config.
3
+ Capture everything for non-technical people to help debug. One debug link, zero config.
4
4
 
5
- Bug Jar is a lightweight JavaScript library that silently records all browser activity (network requests, console logs, errors, user actions, performance metrics, and more) and lets anyone — even non-technical users — generate a complete debug report with a single click.
5
+ Bug Jar is a lightweight JavaScript library that silently records all browser activity (network requests, console logs, errors, user actions, performance metrics, and more) and lets you capture a complete, encrypted debug session from a one-time debug link.
6
6
 
7
7
  ## Why?
8
8
 
9
- Because asking someone to "open DevTools and check the Network tab" doesn't scale. Bug Jar gives your support team, QA, and stakeholders a one-click way to capture everything developers need to reproduce and fix bugs.
9
+ Because asking someone to "open DevTools and check the Network tab" doesn't scale. Bug Jar gives your support team and QA a link they can send to anyone to capture everything developers need to reproduce and fix bugs.
10
10
 
11
11
  ## What it captures
12
12
 
@@ -26,30 +26,19 @@ Because asking someone to "open DevTools and check the Network tab" doesn't scal
26
26
 
27
27
  ## Quick Start
28
28
 
29
- ### Script tag (zero config)
29
+ Bug Jar runs as a **debug session**: staff generates a one-time link, the user
30
+ opens it in the real app, and the encrypted package is uploaded to S3. See
31
+ [Debug Session Mode](#debug-session-mode-encrypted-upload-to-s3) below.
30
32
 
31
33
  ```html
32
34
  <script src="https://unpkg.com/@arvoretech/bug-jar"></script>
33
35
  <script>
34
- BugJar.init();
36
+ BugJar.init({
37
+ debugSessionEndpoint: 'https://api.arvore.com.br/debug-sessions',
38
+ })
35
39
  </script>
36
40
  ```
37
41
 
38
- ### NPM
39
-
40
- ```bash
41
- npm install @arvoretech/bug-jar
42
- ```
43
-
44
- ```typescript
45
- import { init } from '@arvoretech/bug-jar'
46
-
47
- init({
48
- endpoint: 'https://your-api.com/bug-reports',
49
- uiPosition: 'bottom-right',
50
- })
51
- ```
52
-
53
42
  ## Configuration
54
43
 
55
44
  ```typescript
@@ -74,16 +63,12 @@ init({
74
63
  // Privacy — fields containing these strings are redacted
75
64
  sensitiveFields: ['password', 'token', 'secret', 'authorization', 'cookie', 'session', 'credit_card', 'cvv', 'ssn', 'cpf'],
76
65
 
77
- // Where to send reports (if not set, downloads as JSON file)
78
- endpoint: 'https://your-api.com/bug-reports',
79
-
80
66
  // Callback when report is generated
81
67
  onCapture: (report) => console.log(report),
82
68
 
83
- // UI widget
84
- ui: true,
85
- uiPosition: 'bottom-right', // bottom-right | bottom-left | top-right | top-left
86
- uiLabel: 'Reportar Bug',
69
+ // Debug session
70
+ debugSessionEndpoint: 'https://api.arvore.com.br/debug-sessions',
71
+ // debugToken is read automatically from the ?debug=<token> query param
87
72
  })
88
73
  ```
89
74
 
@@ -92,7 +77,7 @@ init({
92
77
  ```typescript
93
78
  import { BugJar } from '@arvoretech/bug-jar'
94
79
 
95
- const jar = new BugJar({ ui: false })
80
+ const jar = new BugJar()
96
81
  jar.start()
97
82
 
98
83
  // Later, capture a report programmatically
@@ -105,12 +90,46 @@ await fetch('/api/bugs', {
105
90
  })
106
91
  ```
107
92
 
93
+ ## Debug Session Mode (encrypted upload to S3)
94
+
95
+ For non-technical users, staff can generate a one-time debug link. The user opens
96
+ the link in the real app, reproduces the bug, and Bug Jar records the whole flow,
97
+ encrypts the package end-to-end in the browser, and uploads it straight to a
98
+ private S3 bucket via a presigned URL. No AWS credentials ever reach the browser.
99
+
100
+ ```html
101
+ <script src="https://unpkg.com/@arvoretech/bug-jar"></script>
102
+ <script>
103
+ BugJar.init({
104
+ debugSessionEndpoint: 'https://api.arvore.com.br/debug-sessions',
105
+ // debugToken is read automatically from the ?debug=<token> query param
106
+ })
107
+ </script>
108
+ ```
109
+
110
+ Flow:
111
+
112
+ 1. Staff (admin) calls `POST /debug-sessions` with the target app URL and gets back
113
+ a `debugLink` (`https://app.../?debug=<token>`), the presigned PUT URL, the
114
+ server public key, and an expiry.
115
+ 2. The user opens the link. Bug Jar detects `?debug=<token>`, fetches the session
116
+ from `debugSessionEndpoint`, starts screen recording, and shows a top banner.
117
+ 3. The user clicks **Finalizar e enviar**. Bug Jar builds the ZIP, encrypts it
118
+ (libsodium sealed box + secretbox hybrid), and uploads the encrypted blob to S3.
119
+ 4. Staff downloads the `.bin` via `GET /debug-sessions/:token/download` and
120
+ decrypts it offline with the private key.
121
+
122
+ The package leaves the browser already unreadable; only the holder of the X25519
123
+ private key can open it. `libsodium-wrappers` is loaded dynamically, so it only
124
+ ships when debug mode is actually used.
125
+
126
+
108
127
  ## Privacy & Security
109
128
 
110
129
  - Sensitive fields are automatically redacted (passwords, tokens, secrets, etc.)
111
130
  - Password inputs are never captured
112
131
  - You control what gets captured via configuration
113
- - No data leaves the browser unless you configure an endpoint
132
+ - No data leaves the browser unless a debug session is active
114
133
  - All processing happens client-side
115
134
 
116
135
  ## Browser Support
package/dist/index.d.mts CHANGED
@@ -15,11 +15,8 @@ interface BugJarConfig {
15
15
  sensitiveFields: string[];
16
16
  endpoint?: string;
17
17
  onCapture?: (report: BugReport) => void;
18
- ui: boolean;
19
- uiPosition: "bottom-right" | "bottom-left" | "top-right" | "top-left";
20
- uiLabel: string;
21
- hideOnMobile?: boolean;
22
- uiCompactOnMobile?: boolean;
18
+ debugToken?: string;
19
+ debugSessionEndpoint?: string;
23
20
  }
24
21
  interface NetworkEntry {
25
22
  id: string;
@@ -136,6 +133,14 @@ declare function generateSummary(report: BugReport): string;
136
133
 
137
134
  declare function exportAsZip(report: BugReport, videoBlob: Blob | null): Promise<Blob>;
138
135
 
136
+ interface DebugSessionPayload {
137
+ token: string;
138
+ publicKey: string;
139
+ presignedPut: string;
140
+ reportId: string;
141
+ expiresAt: number;
142
+ }
143
+
139
144
  declare class BugJar {
140
145
  private config;
141
146
  private network;
@@ -148,7 +153,8 @@ declare class BugJar {
148
153
  private screenshot;
149
154
  private featureFlags;
150
155
  private screenRecorder;
151
- private ui;
156
+ private debugBanner;
157
+ private debugSession;
152
158
  private started;
153
159
  constructor(config?: Partial<BugJarConfig>);
154
160
  start(): void;
@@ -158,7 +164,9 @@ declare class BugJar {
158
164
  capture(userDescription?: string): Promise<BugReport>;
159
165
  captureAndExport(userDescription?: string): Promise<BugReport>;
160
166
  getReport(): Promise<BugReport>;
167
+ private startDebugSession;
168
+ private finishDebugSession;
161
169
  }
162
170
  declare function init(config?: Partial<BugJarConfig>): BugJar;
163
171
 
164
- export { BugJar, type BugJarConfig, type BugReport, BugJar as default, exportAsZip, generateSummary, init };
172
+ export { BugJar, type BugJarConfig, type BugReport, type DebugSessionPayload, BugJar as default, exportAsZip, generateSummary, init };
package/dist/index.d.ts CHANGED
@@ -15,11 +15,8 @@ interface BugJarConfig {
15
15
  sensitiveFields: string[];
16
16
  endpoint?: string;
17
17
  onCapture?: (report: BugReport) => void;
18
- ui: boolean;
19
- uiPosition: "bottom-right" | "bottom-left" | "top-right" | "top-left";
20
- uiLabel: string;
21
- hideOnMobile?: boolean;
22
- uiCompactOnMobile?: boolean;
18
+ debugToken?: string;
19
+ debugSessionEndpoint?: string;
23
20
  }
24
21
  interface NetworkEntry {
25
22
  id: string;
@@ -136,6 +133,14 @@ declare function generateSummary(report: BugReport): string;
136
133
 
137
134
  declare function exportAsZip(report: BugReport, videoBlob: Blob | null): Promise<Blob>;
138
135
 
136
+ interface DebugSessionPayload {
137
+ token: string;
138
+ publicKey: string;
139
+ presignedPut: string;
140
+ reportId: string;
141
+ expiresAt: number;
142
+ }
143
+
139
144
  declare class BugJar {
140
145
  private config;
141
146
  private network;
@@ -148,7 +153,8 @@ declare class BugJar {
148
153
  private screenshot;
149
154
  private featureFlags;
150
155
  private screenRecorder;
151
- private ui;
156
+ private debugBanner;
157
+ private debugSession;
152
158
  private started;
153
159
  constructor(config?: Partial<BugJarConfig>);
154
160
  start(): void;
@@ -158,7 +164,9 @@ declare class BugJar {
158
164
  capture(userDescription?: string): Promise<BugReport>;
159
165
  captureAndExport(userDescription?: string): Promise<BugReport>;
160
166
  getReport(): Promise<BugReport>;
167
+ private startDebugSession;
168
+ private finishDebugSession;
161
169
  }
162
170
  declare function init(config?: Partial<BugJarConfig>): BugJar;
163
171
 
164
- export { BugJar, type BugJarConfig, type BugReport, BugJar as default, exportAsZip, generateSummary, init };
172
+ export { BugJar, type BugJarConfig, type BugReport, type DebugSessionPayload, BugJar as default, exportAsZip, generateSummary, init };