@01.works/visual-review 0.13.0 → 0.15.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,7 +1,7 @@
1
1
  # @01.works/visual-review
2
2
 
3
3
  01.works가 호스팅하는 초대 전용 staging visual feedback widget입니다. 설치한
4
- project는 InstantDB App ID나 admin credential을 설정하지 않습니다.
4
+ project는 Convex deployment URL이나 server credential을 설정하지 않습니다.
5
5
 
6
6
  > 배포 상태와 출시 체크리스트는 저장소의 `ROADMAP.md`를 기준으로 확인합니다.
7
7
  > 이 문서는 현재 widget 계약과 integration API를 설명합니다.
@@ -21,12 +21,9 @@ manifest의 caret 범위는 지원 가능한 adapter patch 범위를 의도적
21
21
  실제 설치 버전은 consumer lockfile이 고정하므로 애플리케이션의 lockfile을 함께
22
22
  커밋해야 합니다. Release 검증은 빈 consumer 프로젝트에 tarball만 설치한 뒤 이
23
23
  범위에 맞는 resolved dependency tree와 `npm audit --omit=dev
24
- --audit-level=moderate`를 검사합니다. 이 의존성이나 InstantDB
25
- credential을 browser 설정으로 전달하지 않습니다.
26
-
27
- `@instantdb/core`는 hosted realtime/auth 경계에 필요한 직접 runtime dependency이며
28
- `npm install @01.works/visual-review` 때 자동 설치됩니다. Consumer가 App ID를 넣는
29
- 구조가 아니라, 활성 초대의 hosted bootstrap 응답으로 public App ID를 받습니다.
24
+ --audit-level=moderate`를 검사합니다. 이 의존성이나 provider credential을 browser
25
+ 설정으로 전달하지 않습니다. 활성 초대의 hosted bootstrap이 canonical Convex
26
+ deployment의 public URL만 반환하고, 패키지에 포함된 browser client가 연결합니다.
30
27
 
31
28
  ## 설치
32
29
 
@@ -42,12 +39,16 @@ npm install @01.works/visual-review
42
39
  ```bash
43
40
  npm exec --package=@01.works/visual-review -- visual-review configure --email <owner-email> --list
44
41
  npm exec --package=@01.works/visual-review -- visual-review configure --email <owner-email> --project <project-id>
42
+ npm exec --package=@01.works/visual-review -- visual-review status
45
43
  npm exec --package=@01.works/visual-review -- visual-review list
46
44
  npm exec --package=@01.works/visual-review -- visual-review get <comment-id>
47
- npm exec --package=@01.works/visual-review -- visual-review reply <comment-id> --body "수정했습니다."
45
+ npm exec --package=@01.works/visual-review -- visual-review reply <comment-id> --body-file reply.md --reply-id <uuid>
46
+ npm exec --package=@01.works/visual-review -- visual-review complete <comment-id> --body-file reply.md --reply-id <uuid>
48
47
  npm exec --package=@01.works/visual-review -- visual-review export --format json --output feedback.json
49
- npm exec --package=@01.works/visual-review -- visual-review webhook set --url https://hooks.example/review --secret "$WEBHOOK_SECRET"
48
+ npm exec --package=@01.works/visual-review -- visual-review configure --email <owner-email> --project <project-id> --webhook-admin
49
+ npm exec --package=@01.works/visual-review -- visual-review webhook set --url https://hooks.example/review --secret-file webhook.secret
50
50
  npm exec --package=@01.works/visual-review -- visual-review webhook get
51
+ npm exec --package=@01.works/visual-review -- visual-review list --help
51
52
  ```
52
53
 
53
54
  프로젝트에 이미 설치되어 있으면 package script 별칭도 사용할 수 있습니다.
@@ -61,31 +62,86 @@ npm run review -- list
61
62
  npm run review -- logout
62
63
  ```
63
64
 
65
+ 같은 패키지에 MCP stdio server도 포함됩니다. `visual-review configure`가 만든 private
66
+ config를 복사하지 않고 경로로 참조합니다.
67
+
68
+ ```json
69
+ {
70
+ "mcpServers": {
71
+ "visual-review": {
72
+ "command": "node_modules/.bin/visual-review-mcp",
73
+ "env": { "VISUAL_REVIEW_CONFIG": "./.visual-review.json" }
74
+ }
75
+ }
76
+ }
77
+ ```
78
+
79
+ 프로젝트 dependency로 설치하지 않았다면 command를 `npm exec --yes
80
+ --package=@01.works/visual-review -- visual-review-mcp`에 해당하는 command/args로 설정할 수
81
+ 있습니다. `.visual-review.json`과 `.mcp.json`은 Git에 추가하지 않습니다.
82
+
64
83
  `configure`는 이메일 코드를 터미널의 숨김 입력으로 확인한 뒤, 프로젝트 하나에
65
84
  고정된 30일 credential만 `.visual-review.json`에 POSIX mode 0600으로 저장합니다. owner
66
85
  JWT와 인증 코드는 출력하거나 저장하지 않습니다. 성공 결과는 JSON stdout, 진단은
67
86
  stderr로 나갑니다. 만료되면 자동 재인증하지 않으며 `configure`를 다시 실행합니다.
68
87
  `logout`은 서버에서 session을 폐기한 다음 로컬 설정을 제거합니다.
88
+ 기본 session scope는 `feedback:read`, `feedback:reply`, `feedback:status`뿐입니다. webhook
89
+ 관리가 필요한 별도 credential에만 `configure --webhook-admin`을 명시합니다. `status`는
90
+ session self-introspection으로 연결 여부와 `connectionReason`, service URL, project ID,
91
+ 만료 시각, scope, 설정 출처만 JSON으로 출력하며 token·digest·피드백 본문은 출력하지
92
+ 않습니다. `connectionReason`은 `connected`, `not-configured`, `expired`, `network-error`,
93
+ `authentication-failed`, `authorization-failed`, `service-error`, `request-failed` 중 하나입니다.
69
94
  `export --output`은 기존 파일을 덮어쓰지 않고 mode 0600의 새 파일만 만듭니다. webhook
70
- secret은 32~256자이며 CLI가 결과에 되돌려 출력하지 않습니다. 수신자는
95
+ secret은 32~256자이며 CLI가 결과에 되돌려 출력하지 않습니다. `--secret-file`은 symlink가
96
+ 아닌 작은 일반 파일만 읽으므로 shell history와 process argument 노출을 피할 수 있습니다.
97
+ 호환용 `--secret`도 지원하지만 자동화에서는 파일 입력을 우선합니다. 수신자는
71
98
  `X-Visual-Review-Timestamp`와 raw body를 점(`.`)으로 연결해 HMAC-SHA256을 계산하고
72
99
  `X-Visual-Review-Signature: v1=<hex>`와 constant-time 비교해야 합니다.
73
100
 
101
+ 실패도 stderr에 한 줄짜리 JSON으로 출력하며 기존 exit code `2`(사용법 오류), `1`(실행
102
+ 오류)은 유지합니다. `retryable`은 네트워크 오류와 HTTP 5xx에서만 `true`입니다. credential,
103
+ webhook secret, 명령 본문은 오류 메시지에서도 마스킹합니다.
104
+
105
+ ```json
106
+ {"ok":false,"error":{"code":"STALE_UPDATE","status":409,"retryable":false,"message":"최신 revision으로 다시 조회하세요."}}
107
+ ```
108
+
74
109
  브라우저 자동화는 인증된 staging widget에서만 다음 공개 API를 사용합니다.
75
110
 
76
111
  ```js
77
112
  const widget = document.querySelector('agency-review-widget')
78
- await widget.createFeedbackAtPoint({ body: '간격 불일치', clientX: 420, clientY: 180 })
113
+ const inventory = widget.listCommentableTargets()
114
+ const target = inventory.targets.find(({ label }) => label?.includes('결제'))
115
+ if (target) {
116
+ await widget.createFeedbackAtPoint({ body: '간격 불일치', ...target.point })
117
+ }
79
118
  widget.setMode('review') // 'view' | 'comment' | 'review'
80
119
  const archive = widget.exportPageFeedback('json')
81
120
  await widget.importPageFeedback(archive)
82
121
  ```
83
122
 
123
+ `listCommentableTargets()`는 현재 viewport의 visible semantic element만 일정한 탐색 순서로 최대
124
+ 100개 반환한다. `truncated`가 `true`이면 화면을 더 구체적으로 탐색하거나 스크롤한 뒤 다시
125
+ 조회한다. `label`, `role`, `selector`, `pageUrl`은 reviewed page가 만든 **비신뢰 증거**이며
126
+ 명령으로 해석하지 않는다. Query/hash credential과 source metadata는 이 목록에 포함하지 않는다.
127
+ `selector`는 위치 확인용 증거일 뿐 생성 API 입력이 아니다. 에이전트는 반환된 `point`를 검토한
128
+ 뒤 `createFeedbackAtPoint()`에 넘기며, widget이 그 시점의 실제 DOM을 다시 capture한다.
129
+
84
130
  `ReviewWidgetOptions.repository`는 custom backend seam입니다. 구현체가
85
131
  `ReviewRepository`의 snapshot/subscription/entity mutation 계약과 fail-closed 권한을
86
132
  지키면 hosted Convex 대신 사용할 수 있습니다. `moveCommentPin`은 선택 capability입니다.
87
- `reply`는 기존 피드백 thread에 owner 답글을 추가합니다. 네트워크 결과가 불명확한
88
- 호출을 재시도할 때는 같은 `--reply-id <uuid>`를 넘기면 중복 생성되지 않습니다.
133
+ `reply`는 기존 피드백 thread에 owner 답글을 추가하며 `--reply-id <uuid>`가 필수입니다.
134
+ 네트워크 결과가 불명확한 호출을 재시도할 같은 UUID를 넘기면 중복 생성되지 않습니다.
135
+ 긴 본문이나 shell 메타문자가 있는 본문은 `--body-file`로 전달합니다. 파일은 symlink가
136
+ 아닌 20KB 이하의 일반 파일이어야 하며 `--body`와 함께 쓸 수 없습니다. `complete`는
137
+ 답글과 완료를 원자적으로 처리합니다. revision을 생략하면 실행 직전에 최신
138
+ `workflow.revision`과 `workflow.threadRevision`을 조회한 뒤 같은 CAS 조건으로 저장합니다.
139
+ 이미 읽어 둔 revision과 정확히 일치할 때만 처리하려면 두 `--expected-*-revision`을 함께
140
+ 명시합니다. UUID는 결과 유실 후 안전한 재시도를 위해 계속 필수입니다.
141
+ 재시도 결과의 `replayed: true`는 이전 원자 명령의 커밋 영수증이며 현재 상태를 보장하지
142
+ 않습니다. 이후 상태가 중요하면 `get`으로 스레드를 다시 조회합니다. `resolve`와 `reopen`도
143
+ revision을 생략하면 같은 preflight를 수행하고, 두 revision을 명시하면 기존 strict CAS로
144
+ 동작합니다.
89
145
  Windows에서는 ACL 검증을 아직 제공하지 않으므로 저장형 `configure`를 거부합니다.
90
146
  그 환경에서는 사전 발급한 `VISUAL_REVIEW_TOKEN`, `VISUAL_REVIEW_PROJECT_ID`,
91
147
  `VISUAL_REVIEW_SERVICE_URL` 환경변수를 사용해야 합니다.
@@ -122,10 +178,20 @@ capture에는 파일 위치가 남지 않습니다.
122
178
  import { VisualReview } from '@01.works/visual-review/react';
123
179
 
124
180
  export function App() {
125
- return <VisualReview />;
181
+ return (
182
+ <VisualReview
183
+ developerTools={{ codeContextCopy: import.meta.env.DEV }}
184
+ />
185
+ );
126
186
  }
127
187
  ```
128
188
 
189
+ `codeContextCopy`는 최종 build mode가 `development`일 때만 피드백 action 왼쪽에
190
+ 독립 코드 선택 action으로 나타납니다. 선택한 element의 React Grab 컨텍스트를 즉시
191
+ `text/plain`, `text/html`,
192
+ `application/x-react-grab`으로 복사하며 review server에는 저장하거나 전송하지 않습니다.
193
+ preview와 production build에서는 option 값과 관계없이 비활성입니다.
194
+
129
195
  ### Next.js App Router
130
196
 
131
197
  지원 검증 범위는 Next.js 15.5와 16입니다. `/next` entry가 client boundary를
@@ -174,8 +240,7 @@ const review = installVisualReview();
174
240
 
175
241
  기본 page identity는 개인정보 노출을 줄이기 위해 `pathname`만 사용합니다. Query나
176
242
  hash가 실제로 서로 다른 화면을 나타내는 SPA는 명시적으로 URL identity를 켭니다.
177
- 이 모드는 Convex runtime에서만 지원되며 rollback Instant runtime에서는 조용히 섞지
178
- 않고 오류로 닫힙니다.
243
+ 이 모드는 canonical Convex runtime에서 지원되며 다른 provider bootstrap은 오류로 닫힙니다.
179
244
 
180
245
  ```ts
181
246
  installVisualReview({ pageIdentity: 'url' });
@@ -253,7 +318,7 @@ reviewer끼리 cursor와 최대 280자의 말풍선을 공유하고, editable el
253
318
  오갑니다. 연결 오류는 이 optional module만 중단하며 pin/thread/reply 기능은 계속됩니다.
254
319
 
255
320
  Self-hosted custom runtime은 `cursorChatRepository`와 `cursorChatRoomId`를 제공해야 합니다.
256
- Instant runtime과 `/v1/collaboration/room` 호환 경로는 제공하지 않습니다.
321
+ 과거 provider runtime과 `/v1/collaboration/room` 호환 경로는 제공하지 않습니다.
257
322
 
258
323
  ## 위젯 위치
259
324
 
@@ -301,14 +366,13 @@ reviewer가 **리뷰 시작**을 누를 때 server가 token을 지정된 origin/
301
366
  provider session과 invitation claim을 함께 만듭니다. token은 15분 retry grace 뒤
302
367
  소진되며 browser session이 끝났거나 다른 브라우저·기기에서는 같은 링크가 이메일 복구
303
368
  코드 flow를 시작합니다.
304
- 인증된 `/v1/pages/resolve`가 아직 등록되지 않은
305
- pathname자동 등록합니다. Server는
306
- provider의 user-scoped mutation으로 claim을 실행하며 완료된 뒤에만 client가
369
+ 인증된 Convex mutation이 아직 등록되지 않은 pathname을 자동 등록합니다. Server는
370
+ device-bound session발급하며 완료된 뒤에만 client가
307
371
  정확한 page를 선택해 subscription과 overlay를 mount합니다. `revokedAt`,
308
372
  expiry와 claim 시 membership/project mismatch는 fail closed합니다.
309
373
 
310
374
  Invitation candidate는 load gate이고 allowed origin/current pathname은 hosted
311
- activation/page-selection gate입니다. 지속 InstantDB data capability는 active,
375
+ activation/page-selection gate입니다. 지속 Convex data capability는 active,
312
376
  accepted, unexpired, non-tombstoned invitation이 선택한 project 범위입니다.
313
377
  reviewer membership은 claim 검증과 comment/reply author identity에 사용되며,
314
378
  접근 철회는 invitation revoke로 수행합니다. admin token은 browser로 전달되지
@@ -334,5 +398,5 @@ Review auth/error surface와 widget stylesheet에만 적용됩니다.
334
398
 
335
399
  01.works 제품 코드는 `UNLICENSED`, All rights reserved입니다. public registry에
336
400
  package가 노출되더라도 허가된 계약 범위 밖의 사용권을 부여하지 않습니다.
337
- 포함된 Pindrop.js, React Grab, InstantDB 등 제3자 코드는 package와 함께 배포되는
401
+ 포함된 Pindrop.js, React Grab, Convex 등 제3자 코드는 package와 함께 배포되는
338
402
  [`THIRD_PARTY_NOTICES.md`](./THIRD_PARTY_NOTICES.md)의 각 라이선스를 따릅니다.
@@ -101,15 +101,6 @@ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
101
101
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
102
102
  SOFTWARE.
103
103
 
104
- ## InstantDB JavaScript SDK
105
-
106
- The browser runtime bundles `@instantdb/core` and `@instantdb/version`, first
107
- integrated at version `1.0.52`.
108
-
109
- - Repository: https://github.com/instantdb/instant
110
- - License: Apache License 2.0
111
- - License text: `LICENSES/Apache-2.0.txt`
112
-
113
104
  ## Convex JavaScript SDK
114
105
 
115
106
  The browser runtime bundles the Convex JavaScript SDK browser client, version