@sylergydigital/issue-pin-sdk 0.6.2 → 0.6.4
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/CHANGELOG.md +228 -0
- package/README.md +48 -0
- package/dist/index.cjs +61 -3
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +13 -1
- package/dist/index.d.ts +13 -1
- package/dist/index.js +59 -3
- package/dist/index.js.map +1 -1
- package/package.json +6 -2
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `@sylergydigital/issue-pin-sdk` are documented here.
|
|
4
|
+
|
|
5
|
+
## [0.6.3] - 2026-04-14
|
|
6
|
+
|
|
7
|
+
### Added
|
|
8
|
+
- **UUID normalization for non-UUID auth providers** — SDK auto-converts Firebase, Auth0, Cognito, and other non-UUID user IDs to deterministic UUID v5 format at the SDK boundary. Existing UUID-format IDs pass through unchanged.
|
|
9
|
+
- `normalizeUserId()` / `toSupabaseUuid()` — public utility export for converting user IDs outside the SDK component lifecycle.
|
|
10
|
+
- `CSP_REQUIREMENTS` — typed constant exporting all Content Security Policy directives required by the SDK (`connect-src`, `img-src`, `style-src`), usable in server middleware or build-time CSP generation.
|
|
11
|
+
- Runtime CSP violation detection — `subscribeCspDetection()` automatically activates on SDK mount and logs actionable `[IssuePin]` console warnings when CSP blocks SDK functionality. Per-directive deduplication prevents warning spam.
|
|
12
|
+
- CSP documentation section in SDK README with copy-paste directive block, per-directive explanation table, and programmatic access example.
|
|
13
|
+
- Debug logging for ID conversions — when `debug={true}`, logs `[EW SDK] User ID normalized: "{raw}" -> "{effective}"` for converted IDs.
|
|
14
|
+
|
|
15
|
+
### Fixed
|
|
16
|
+
- Stale closure in identity warning gated on `authReady` state.
|
|
17
|
+
- Missing SSR guard in `subscribeCspDetection` (safe for server-side rendering).
|
|
18
|
+
|
|
19
|
+
### Dependencies
|
|
20
|
+
- Added `uuid@^11.0.3` as bundled dependency (CommonJS-compatible).
|
|
21
|
+
|
|
22
|
+
## [0.6.2] - 2026-04-02
|
|
23
|
+
|
|
24
|
+
### Fixed
|
|
25
|
+
- Replaced `html2canvas` with `html2canvas-pro` to support modern CSS features like `oklab` color space.
|
|
26
|
+
|
|
27
|
+
## [0.6.1] - 2026-03-24
|
|
28
|
+
|
|
29
|
+
### Changed
|
|
30
|
+
- Set up public SDK mirror and npm release pipeline.
|
|
31
|
+
|
|
32
|
+
## [0.6.0] - 2026-03-24
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
- Set up public SDK mirror and npm release pipeline.
|
|
36
|
+
|
|
37
|
+
## [0.5.9] - 2026-03-24
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
- Public SDK mirror and npm registry setup.
|
|
41
|
+
|
|
42
|
+
## [0.5.8] - 2026-03-23
|
|
43
|
+
|
|
44
|
+
### Added
|
|
45
|
+
- `showHints` toggle for instructional UI hints in the SDK.
|
|
46
|
+
|
|
47
|
+
## [0.5.7] - 2026-03-23
|
|
48
|
+
|
|
49
|
+
### Added
|
|
50
|
+
- Verified LMS federation rollout (patch).
|
|
51
|
+
|
|
52
|
+
## [0.5.6] - 2026-03-23
|
|
53
|
+
|
|
54
|
+
### Added
|
|
55
|
+
- LMS federation rollout with verification.
|
|
56
|
+
|
|
57
|
+
## [0.5.5] - 2026-03-22
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
- SDK build and packaging fixes.
|
|
61
|
+
|
|
62
|
+
## [0.5.4] - 2026-03-22
|
|
63
|
+
|
|
64
|
+
### Fixed
|
|
65
|
+
- SDK build and packaging fixes.
|
|
66
|
+
|
|
67
|
+
## [0.5.3] - 2026-03-22
|
|
68
|
+
|
|
69
|
+
### Changed
|
|
70
|
+
- Aligned SDK docs and package metadata with router-free integration.
|
|
71
|
+
|
|
72
|
+
## [0.5.2] - 2026-03-22
|
|
73
|
+
|
|
74
|
+
### Added
|
|
75
|
+
- Iframe review mode for SDK pins (canvas review surface).
|
|
76
|
+
|
|
77
|
+
## [0.5.1] - 2026-03-22
|
|
78
|
+
|
|
79
|
+
### Added
|
|
80
|
+
- Anonymous screenshot reads for SDK workspaces via Supabase RLS.
|
|
81
|
+
- ThreadPins test coverage.
|
|
82
|
+
- npm registry publishing.
|
|
83
|
+
|
|
84
|
+
## [0.5.0] - 2026-03-22
|
|
85
|
+
|
|
86
|
+
### Changed
|
|
87
|
+
- npm versioning aligned with git tags.
|
|
88
|
+
|
|
89
|
+
## [0.4.9] - 2026-03-22
|
|
90
|
+
|
|
91
|
+
### Changed
|
|
92
|
+
- Vite host allowlist and gitignore for local tooling.
|
|
93
|
+
|
|
94
|
+
## [0.4.8] - 2026-03-17
|
|
95
|
+
|
|
96
|
+
### Added
|
|
97
|
+
- SDK customization APIs for launcher visibility and pin visibility control.
|
|
98
|
+
|
|
99
|
+
## [0.4.7] - 2026-03-17
|
|
100
|
+
|
|
101
|
+
### Fixed
|
|
102
|
+
- SDK publish build for controlled pin mode.
|
|
103
|
+
|
|
104
|
+
## [0.4.6] - 2026-03-17
|
|
105
|
+
|
|
106
|
+
### Changed
|
|
107
|
+
- Thread pins open in a new tab.
|
|
108
|
+
|
|
109
|
+
## [0.4.5] - 2026-03-17
|
|
110
|
+
|
|
111
|
+
### Changed
|
|
112
|
+
- Rewrote SDK pin positioning lifecycle for stability.
|
|
113
|
+
|
|
114
|
+
## [0.4.4] - 2026-03-17
|
|
115
|
+
|
|
116
|
+
### Fixed
|
|
117
|
+
- Stabilized SDK pin rehydration observer.
|
|
118
|
+
|
|
119
|
+
## [0.4.3] - 2026-03-17
|
|
120
|
+
|
|
121
|
+
### Changed
|
|
122
|
+
- Allow anonymous `sdk-resolve` calls.
|
|
123
|
+
|
|
124
|
+
## [0.4.2] - 2026-03-17
|
|
125
|
+
|
|
126
|
+
### Changed
|
|
127
|
+
- Allow commenter workspace memberships.
|
|
128
|
+
|
|
129
|
+
## [0.4.1] - 2026-03-17
|
|
130
|
+
|
|
131
|
+
### Added
|
|
132
|
+
- Documentation for federated first-write gating.
|
|
133
|
+
|
|
134
|
+
## [0.4.0] - 2026-03-17
|
|
135
|
+
|
|
136
|
+
### Fixed
|
|
137
|
+
- Federated SDK author attribution.
|
|
138
|
+
|
|
139
|
+
## [0.3.4] - 2026-03-16
|
|
140
|
+
|
|
141
|
+
### Added
|
|
142
|
+
- Anonymous update RLS policy.
|
|
143
|
+
|
|
144
|
+
## [0.3.3] - 2026-03-16
|
|
145
|
+
|
|
146
|
+
### Changed
|
|
147
|
+
- Enabled React Router v7 future flag.
|
|
148
|
+
|
|
149
|
+
## [0.3.2] - 2026-03-16
|
|
150
|
+
|
|
151
|
+
### Changed
|
|
152
|
+
- Relaxed thread comments foreign key constraint.
|
|
153
|
+
|
|
154
|
+
## [0.3.1] - 2026-03-16
|
|
155
|
+
|
|
156
|
+
### Added
|
|
157
|
+
- RLS policies for anonymous inserts.
|
|
158
|
+
|
|
159
|
+
## [0.3.0] - 2026-03-16
|
|
160
|
+
|
|
161
|
+
### Fixed
|
|
162
|
+
- SDK feedback launcher click behavior.
|
|
163
|
+
|
|
164
|
+
## [0.2.9] - 2026-03-16
|
|
165
|
+
|
|
166
|
+
### Added
|
|
167
|
+
- Hardcoded SDK theme for consistent styling.
|
|
168
|
+
|
|
169
|
+
## [0.2.8] - 2026-03-16
|
|
170
|
+
|
|
171
|
+
### Fixed
|
|
172
|
+
- FeedbackButton `.d.ts` build ordering.
|
|
173
|
+
|
|
174
|
+
## [0.2.7] - 2026-03-16
|
|
175
|
+
|
|
176
|
+
### Added
|
|
177
|
+
- Debug logging for SDK menu state.
|
|
178
|
+
|
|
179
|
+
### Fixed
|
|
180
|
+
- SDK menu state management hardened.
|
|
181
|
+
|
|
182
|
+
## [0.2.6] - 2026-03-16
|
|
183
|
+
|
|
184
|
+
### Fixed
|
|
185
|
+
- SDK feedback launcher click handling.
|
|
186
|
+
|
|
187
|
+
## [0.2.5] - 2026-03-16
|
|
188
|
+
|
|
189
|
+
### Fixed
|
|
190
|
+
- FeedbackButton interaction reliability.
|
|
191
|
+
|
|
192
|
+
## [0.2.4] - 2026-03-16
|
|
193
|
+
|
|
194
|
+
### Fixed
|
|
195
|
+
- Stabilized `getSignedUrlRef` for screenshot storage.
|
|
196
|
+
|
|
197
|
+
## [0.2.3] - 2026-03-16
|
|
198
|
+
|
|
199
|
+
### Added
|
|
200
|
+
- Error boundary wrapping for ThreadPins.
|
|
201
|
+
|
|
202
|
+
## [0.2.0] - 2026-03-16
|
|
203
|
+
|
|
204
|
+
### Changed
|
|
205
|
+
- Renamed SDK package to `@sylergydigital/issue-pin-sdk`.
|
|
206
|
+
|
|
207
|
+
## [0.1.8] - 2026-03-16
|
|
208
|
+
|
|
209
|
+
### Fixed
|
|
210
|
+
- TS2722 error in ScreenshotFeedback component.
|
|
211
|
+
|
|
212
|
+
## [0.1.6] - 2026-03-16
|
|
213
|
+
|
|
214
|
+
### Fixed
|
|
215
|
+
- Viewport auto-screenshot capture.
|
|
216
|
+
|
|
217
|
+
## [0.1.5] - 2026-03-16
|
|
218
|
+
|
|
219
|
+
### Fixed
|
|
220
|
+
- Auto-screenshot fetch reliability.
|
|
221
|
+
|
|
222
|
+
## [0.1.0] - 2026-03-16
|
|
223
|
+
|
|
224
|
+
### Added
|
|
225
|
+
- Initial SDK release as `@sylergydigital/issue-pin-sdk`.
|
|
226
|
+
- `<IssuePin />` drop-in component with pin annotations, screenshot capture, and threaded discussions.
|
|
227
|
+
- Supabase-backed real-time data layer.
|
|
228
|
+
- Federated user identity for SDK consumers.
|
package/README.md
CHANGED
|
@@ -356,6 +356,54 @@ For bulk provisioning or non-Supabase apps, use the `federate-user` edge functio
|
|
|
356
356
|
|
|
357
357
|
The API key is a **publishable key** — safe to include in client-side code. It only grants scoped access to create threads and comments for the associated workspace, enforced server-side via Row Level Security.
|
|
358
358
|
|
|
359
|
+
## Content Security Policy (CSP)
|
|
360
|
+
|
|
361
|
+
If your app sets a Content Security Policy header, add these directives so the IssuePin SDK can connect to Supabase, render screenshot previews, and apply inline styles:
|
|
362
|
+
|
|
363
|
+
```
|
|
364
|
+
connect-src https://*.supabase.co wss://*.supabase.co;
|
|
365
|
+
img-src data: blob:;
|
|
366
|
+
style-src 'unsafe-inline';
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
Merge these with your existing CSP directives — for example, if you already have `connect-src 'self'`, change it to `connect-src 'self' https://*.supabase.co wss://*.supabase.co;`.
|
|
370
|
+
|
|
371
|
+
> **Narrower alternative:** Replace `*.supabase.co` with your project's specific URL (e.g. `https://abcdef.supabase.co`) for a tighter policy.
|
|
372
|
+
|
|
373
|
+
### Why each directive is needed
|
|
374
|
+
|
|
375
|
+
| Directive | Sources | Reason |
|
|
376
|
+
|-----------|---------|--------|
|
|
377
|
+
| `connect-src` | `https://*.supabase.co` | REST API calls to read/write threads and comments |
|
|
378
|
+
| `connect-src` | `wss://*.supabase.co` | WebSocket connections for real-time thread updates |
|
|
379
|
+
| `img-src` | `data:` `blob:` | Screenshot preview thumbnails rendered as data URIs and blob URLs |
|
|
380
|
+
| `style-src` | `'unsafe-inline'` | html2canvas-pro injects inline styles during screenshot capture |
|
|
381
|
+
|
|
382
|
+
### Programmatic access
|
|
383
|
+
|
|
384
|
+
The SDK exports a typed constant for use in server-side middleware or build-time CSP generation:
|
|
385
|
+
|
|
386
|
+
```typescript
|
|
387
|
+
import { CSP_REQUIREMENTS } from "@sylergydigital/issue-pin-sdk";
|
|
388
|
+
|
|
389
|
+
// CSP_REQUIREMENTS = {
|
|
390
|
+
// "connect-src": ["https://*.supabase.co", "wss://*.supabase.co"],
|
|
391
|
+
// "img-src": ["data:", "blob:"],
|
|
392
|
+
// "style-src": ["'unsafe-inline'"],
|
|
393
|
+
// }
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
### Runtime detection
|
|
397
|
+
|
|
398
|
+
When a CSP policy blocks an SDK operation, the browser console shows a warning like:
|
|
399
|
+
|
|
400
|
+
```
|
|
401
|
+
[IssuePin] CSP violation: connect-src blocked "https://abc.supabase.co/rest/v1/threads".
|
|
402
|
+
Add to your Content-Security-Policy: connect-src https://*.supabase.co wss://*.supabase.co
|
|
403
|
+
```
|
|
404
|
+
|
|
405
|
+
These warnings appear automatically — no `debug` flag needed.
|
|
406
|
+
|
|
359
407
|
## AI Agent Prompt
|
|
360
408
|
|
|
361
409
|
Paste this into **Claude Code**, **Cursor**, or **Codex** to integrate the SDK automatically:
|
package/dist/index.cjs
CHANGED
|
@@ -30,6 +30,7 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
+
CSP_REQUIREMENTS: () => CSP_REQUIREMENTS,
|
|
33
34
|
ElementWhisperer: () => IssuePin,
|
|
34
35
|
FeedbackButton: () => FeedbackButton,
|
|
35
36
|
FeedbackOverlay: () => FeedbackOverlay,
|
|
@@ -40,6 +41,7 @@ __export(index_exports, {
|
|
|
40
41
|
SdkCommentPopover: () => SdkCommentPopover,
|
|
41
42
|
ThreadPins: () => ThreadPins,
|
|
42
43
|
Z: () => Z,
|
|
44
|
+
normalizeUserId: () => normalizeUserId,
|
|
43
45
|
useFeedback: () => useFeedback,
|
|
44
46
|
useFeedbackSafe: () => useFeedbackSafe,
|
|
45
47
|
useIssuePinAnchor: () => useIssuePinAnchor
|
|
@@ -125,6 +127,51 @@ var T = {
|
|
|
125
127
|
ring: "#6366f1"
|
|
126
128
|
};
|
|
127
129
|
|
|
130
|
+
// src/uuid.ts
|
|
131
|
+
var import_uuid = require("uuid");
|
|
132
|
+
var NAMESPACE = "8920e263-ef53-4df0-8108-968cd5d8939e";
|
|
133
|
+
var UUID_SHAPE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;
|
|
134
|
+
function normalizeUserId(userId) {
|
|
135
|
+
if (UUID_SHAPE.test(userId)) return userId;
|
|
136
|
+
return (0, import_uuid.v5)(userId, NAMESPACE);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
// src/csp.ts
|
|
140
|
+
var CSP_REQUIREMENTS = {
|
|
141
|
+
"connect-src": ["https://*.supabase.co", "wss://*.supabase.co"],
|
|
142
|
+
"img-src": ["data:", "blob:"],
|
|
143
|
+
"style-src": ["'unsafe-inline'"]
|
|
144
|
+
};
|
|
145
|
+
var warnedDirectives = /* @__PURE__ */ new Set();
|
|
146
|
+
function isIssuePinViolation(event) {
|
|
147
|
+
const blocked = event.blockedURI;
|
|
148
|
+
const directive = event.violatedDirective;
|
|
149
|
+
if (directive.startsWith("connect-src") && blocked.includes("supabase.co")) return true;
|
|
150
|
+
if (directive.startsWith("img-src") && (blocked === "data" || blocked === "blob")) return true;
|
|
151
|
+
if (directive.startsWith("style-src") && (blocked === "inline" || blocked === "'unsafe-inline'")) return true;
|
|
152
|
+
return false;
|
|
153
|
+
}
|
|
154
|
+
function handleViolation(event) {
|
|
155
|
+
if (!isIssuePinViolation(event)) return;
|
|
156
|
+
const directive = event.violatedDirective.split(" ")[0];
|
|
157
|
+
if (warnedDirectives.has(directive)) return;
|
|
158
|
+
warnedDirectives.add(directive);
|
|
159
|
+
const sources = CSP_REQUIREMENTS[directive];
|
|
160
|
+
const fix = sources ? sources.join(" ") : event.blockedURI;
|
|
161
|
+
console.warn(
|
|
162
|
+
`[IssuePin] CSP violation: ${directive} blocked "${event.blockedURI}". Add to your Content-Security-Policy: ${directive} ${fix}`
|
|
163
|
+
);
|
|
164
|
+
}
|
|
165
|
+
function subscribeCspDetection() {
|
|
166
|
+
if (typeof document === "undefined") return () => {
|
|
167
|
+
};
|
|
168
|
+
const handler = (e) => handleViolation(e);
|
|
169
|
+
document.addEventListener("securitypolicyviolation", handler);
|
|
170
|
+
return () => {
|
|
171
|
+
document.removeEventListener("securitypolicyviolation", handler);
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
|
|
128
175
|
// src/FeedbackProvider.tsx
|
|
129
176
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
130
177
|
var FeedbackContext = (0, import_react2.createContext)(null);
|
|
@@ -176,11 +223,11 @@ function setThreadsSchemaMode(workspaceId, mode) {
|
|
|
176
223
|
threadsSchemaModeByWorkspace.set(workspaceId, mode);
|
|
177
224
|
}
|
|
178
225
|
function resolveIssuePinActorUserId(opts) {
|
|
179
|
-
if (opts.explicitUserId) return opts.explicitUserId;
|
|
226
|
+
if (opts.explicitUserId) return normalizeUserId(opts.explicitUserId);
|
|
180
227
|
if (opts.hasApiKey && !opts.skipFederation && opts.autoIdentityUserId) {
|
|
181
228
|
return opts.federatedLocalUserId;
|
|
182
229
|
}
|
|
183
|
-
return opts.autoIdentityUserId;
|
|
230
|
+
return opts.autoIdentityUserId ? normalizeUserId(opts.autoIdentityUserId) : opts.autoIdentityUserId;
|
|
184
231
|
}
|
|
185
232
|
function resolveIssuePinActorReady(opts) {
|
|
186
233
|
if (!opts.authReady) return false;
|
|
@@ -417,6 +464,10 @@ function FeedbackProvider({
|
|
|
417
464
|
hasApiKey: !!config.apiKey,
|
|
418
465
|
skipFederation: config.skipFederation
|
|
419
466
|
});
|
|
467
|
+
const rawUserId = config.userId ?? autoIdentity.userId;
|
|
468
|
+
if (config.debug && rawUserId && effectiveUserId && rawUserId !== effectiveUserId) {
|
|
469
|
+
console.log(`[EW SDK] User ID normalized: "${rawUserId}" -> "${effectiveUserId}"`);
|
|
470
|
+
}
|
|
420
471
|
const actorReady = resolveIssuePinActorReady({
|
|
421
472
|
authReady,
|
|
422
473
|
explicitUserId: config.userId,
|
|
@@ -501,12 +552,13 @@ function FeedbackProviderInner({
|
|
|
501
552
|
console.log(`[EW SDK] ${message}`, extra);
|
|
502
553
|
}, [debug]);
|
|
503
554
|
(0, import_react2.useEffect)(() => {
|
|
555
|
+
if (!authReady) return;
|
|
504
556
|
if (!userDisplayName && !userEmail) {
|
|
505
557
|
console.warn(
|
|
506
558
|
'[IssuePin] No user identity provided \u2014 comments will appear as "Unknown". Pass supabaseClient={supabase} for automatic identity, or user={{ email, displayName }} for manual attribution. See https://github.com/sylergydigital/issue-pin/blob/main/sdk/README.md#user-identity-avoiding-unknown-comments'
|
|
507
559
|
);
|
|
508
560
|
}
|
|
509
|
-
}, []);
|
|
561
|
+
}, [authReady, userDisplayName, userEmail]);
|
|
510
562
|
const client = (0, import_react2.useMemo)(() => {
|
|
511
563
|
try {
|
|
512
564
|
return (0, import_supabase_js.createClient)(supabaseUrl, supabaseAnonKey, {
|
|
@@ -613,6 +665,10 @@ function FeedbackProviderInner({
|
|
|
613
665
|
debugLog("FeedbackProvider unmounted", { workspaceId, path: pathname });
|
|
614
666
|
};
|
|
615
667
|
}, [debugLog, workspaceId, pathname]);
|
|
668
|
+
(0, import_react2.useEffect)(() => {
|
|
669
|
+
const unsubscribe = subscribeCspDetection();
|
|
670
|
+
return unsubscribe;
|
|
671
|
+
}, []);
|
|
616
672
|
(0, import_react2.useEffect)(() => {
|
|
617
673
|
debugLog("mode / feedbackActive", { mode, feedbackActive });
|
|
618
674
|
}, [debugLog, mode, feedbackActive]);
|
|
@@ -2483,6 +2539,7 @@ function PinsSlot() {
|
|
|
2483
2539
|
}
|
|
2484
2540
|
// Annotate the CommonJS export names for ESM import in node:
|
|
2485
2541
|
0 && (module.exports = {
|
|
2542
|
+
CSP_REQUIREMENTS,
|
|
2486
2543
|
ElementWhisperer,
|
|
2487
2544
|
FeedbackButton,
|
|
2488
2545
|
FeedbackOverlay,
|
|
@@ -2493,6 +2550,7 @@ function PinsSlot() {
|
|
|
2493
2550
|
SdkCommentPopover,
|
|
2494
2551
|
ThreadPins,
|
|
2495
2552
|
Z,
|
|
2553
|
+
normalizeUserId,
|
|
2496
2554
|
useFeedback,
|
|
2497
2555
|
useFeedbackSafe,
|
|
2498
2556
|
useIssuePinAnchor
|