Repository navigation
feat(bookmarks): the sidebar page is a bookmark list, and stops shipping as evidence - #32
Merged
Merged
Conversation
…ing as evidence The open ruling from 8b, decided against the code rather than against the word on the sidebar. The answer is not "make quickmarks append-only too" — it is that the table was never a record, and the product has been claiming it was. Six columns, no operator_id, no engagement_id, no hash. Every feature on its page is a bookmark feature: a CDP poll for the focused tab, title and URL autofill, open-in-browser, and a dot whose colour is a hash of the title. Its own shipped copy says "Click + Capture to bookmark the current browser state", and ARCHITECTURE.md already classified it as "Bookmarks. Not chained." So mutability was never the false part. These three were, and all three are fixed here: The sidebar called it 標記 while every gesture an operator would call dropping a mark — ⌘⇧M, the title-bar button, the tray, both HUD buttons, the timeline right-click — writes a chained `marker` event and never touches this table. The page's own empty state told the operator to press ⌘⇧M, a key that cannot produce a row on it. It shipped as evidence: written into the bundle unconditionally, beside events.jsonl, in a bundle whose README classifies two files and never names it, and which the bundled verifier never opens. Worse, the scope-filtered export ran events through the scope filter and these rows around it — so a file labelled scope-filtered carried URLs for hosts the operator had deliberately excluded. And 8b's shipped ruling says `url` is an immutable marker field, while no marker had a `url` at all. Markers now carry `url`, filled once from the browser connector and editable, deliberately NOT amendable — it is where the mark points, the web analogue of `atTimestamp`. That makes 8b true, so 8b moves from partial to done. Append-only was rejected on the evidence: triggers on a table with no hash, no signature, no place in the chain or the anchor, and no verifier that reads it buy the feeling of immutability and none of the checking — `DELETE FROM quickmarks` still works. And they would remove the only removal path that exists: `createQuickMark` runs no redaction and `sanitize` reads `events` only, so a password pasted into a note is unmaskable in both directions and the hard delete is the operator's sole remedy. Append-only would keep that credential forever, and until this commit it also shipped. Deferred, recorded: the internal identifiers (findings.ts, FindingsView, `quickmarks:*` IPC, the REST route, the CLI verb, the `read:findings` plugin capability) keep their old names. Renaming those needs aliases so third-party plugin manifests and installed integrations do not break, and that belongs in a rename-only PR. The SQL table name stays too. npm run typecheck clean · npm test 1055 passed (98 files) · npm run build · playwright 89 passed, 1 skipped Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Team Run ID: Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
This was referenced Sep 4, 2026
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
Seven P1 findings from the UI/UX audit, batched: • #15 HUD auto-collapse now pauses while the pointer is on the overlay (audit was: hard 8s timer, no way to keep it open while reading the topology chain / Reveal button). • #16 Terminal tab labels ("Shell 1", "Shell 2" …) used tabs.length + 1 → duplicated after any close. Now uses a monotonic counter. • #17 Closing a terminal tab kills the PTY silently. Now confirms via ConfirmDialog when the tab is still alive (matches ProjectPicker delete pattern). • #21 Settings CDP test callback had a `const tab = ...` shadowing the outer `tab` state (settings tab name). Renamed to `cdpTab`. • #28-29 EventMarker showed raw enum strings ("info" / "initial_access") for severity + category — now i18n'd (marker.severity.*, marker. category.*). Also added an opt-out "Capture screenshot too" checkbox (default on) so a mark taken over sensitive UI doesn't force a capture. • #30 EventMarker gained role="dialog", aria-modal, aria-label, and an Escape-to-close handler on the backdrop. Autofocus lands on the dialog body so keyboard users have a hook. • #32 App title-bar Mark button title="Ctrl+Shift+M" was hardcoded — Mac users saw the wrong hint. Uses isMac to pick ⌘⇧M vs Ctrl+Shift+M. Deferred (need bigger refactors): #9-14/#49-50 shared IPC store to stop per-event refetches across StatusBar/Sidebar/Dashboard/LootPanel/TargetView/ ScopeStatus; #22-24 sidebar keyboard drag; #25-27 FindingsView/SearchPanel/ LootPanel interactive; #33 uptime should be engagement-scoped not window- scoped; #34 StatusBar record toggle button styling; #37-38 timeline layout constraints. All queued for the next batch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
…line ↑/↓ nav - LootPanel: chip-based type filter with per-type counts + dedup toggle collapses same (type, preview) match across events (audit #18) - ScreenshotsView: trigger-type chip filter (periodic/manual/mark) so grid isn't a mixed pile (audit #32) - Timeline: ↑/↓ walks the selected event across visible (hidden-lane-aware) events; skips inputs so search field still types normally (audit #5) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
feat(bookmarks): the sidebar page is a bookmark list, and stops shipping as evidence
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
… part A) PR #32 renamed the feature to bookmarks in the UI but left the code as QuickMark. This is the INTERNAL half — no external contract changes: - db/findings.ts → db/bookmarks.ts; QuickMark(Context) → Bookmark(Context); create/list/get/update/delete/deleteOlderThan QuickMark(s) → …Bookmark(s). - SQL table quickmarks → bookmarks, with a migration that renames an existing table in place (ALTER TABLE RENAME) so an older project's rows carry over — the SQL-table-rename decision, accepted. - IPC channels quickmarks:* → bookmarks:*, the preload namespace and env.d.ts contract, and every renderer caller. - FindingsView.tsx → BookmarksView.tsx. - visibility signal, retention, bundle, tray, browser-launcher call sites. Deliberately KEPT for part B (external contracts, need an alias window): the REST route /api/quickmarks and its `quickmarks` response key, the CLI quickmark/quickmarks verbs, and the plugin read:findings capability / findings.list method. Validated: typecheck clean, unit 1152 passed, e2e 16 passed (incl. cli-smoke hitting the kept REST route and the bookmark visibility flow). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
Seven P1 findings from the UI/UX audit, batched: • #15 HUD auto-collapse now pauses while the pointer is on the overlay (audit was: hard 8s timer, no way to keep it open while reading the topology chain / Reveal button). • #16 Terminal tab labels ("Shell 1", "Shell 2" …) used tabs.length + 1 → duplicated after any close. Now uses a monotonic counter. • #17 Closing a terminal tab kills the PTY silently. Now confirms via ConfirmDialog when the tab is still alive (matches ProjectPicker delete pattern). • #21 Settings CDP test callback had a `const tab = ...` shadowing the outer `tab` state (settings tab name). Renamed to `cdpTab`. • #28-29 EventMarker showed raw enum strings ("info" / "initial_access") for severity + category — now i18n'd (marker.severity.*, marker. category.*). Also added an opt-out "Capture screenshot too" checkbox (default on) so a mark taken over sensitive UI doesn't force a capture. • #30 EventMarker gained role="dialog", aria-modal, aria-label, and an Escape-to-close handler on the backdrop. Autofocus lands on the dialog body so keyboard users have a hook. • #32 App title-bar Mark button title="Ctrl+Shift+M" was hardcoded — Mac users saw the wrong hint. Uses isMac to pick ⌘⇧M vs Ctrl+Shift+M. Deferred (need bigger refactors): #9-14/#49-50 shared IPC store to stop per-event refetches across StatusBar/Sidebar/Dashboard/LootPanel/TargetView/ ScopeStatus; #22-24 sidebar keyboard drag; #25-27 FindingsView/SearchPanel/ LootPanel interactive; #33 uptime should be engagement-scoped not window- scoped; #34 StatusBar record toggle button styling; #37-38 timeline layout constraints. All queued for the next batch. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
…line ↑/↓ nav - LootPanel: chip-based type filter with per-type counts + dedup toggle collapses same (type, preview) match across events (audit #18) - ScreenshotsView: trigger-type chip filter (periodic/manual/mark) so grid isn't a mixed pile (audit #32) - Timeline: ↑/↓ walks the selected event across visible (hidden-lane-aware) events; skips inputs so search field still types normally (audit #5) Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
feat(bookmarks): the sidebar page is a bookmark list, and stops shipping as evidence
guan4tou2
added a commit
that referenced
this pull request
Oct 8, 2026
… part A) PR #32 renamed the feature to bookmarks in the UI but left the code as QuickMark. This is the INTERNAL half — no external contract changes: - db/findings.ts → db/bookmarks.ts; QuickMark(Context) → Bookmark(Context); create/list/get/update/delete/deleteOlderThan QuickMark(s) → …Bookmark(s). - SQL table quickmarks → bookmarks, with a migration that renames an existing table in place (ALTER TABLE RENAME) so an older project's rows carry over — the SQL-table-rename decision, accepted. - IPC channels quickmarks:* → bookmarks:*, the preload namespace and env.d.ts contract, and every renderer caller. - FindingsView.tsx → BookmarksView.tsx. - visibility signal, retention, bundle, tray, browser-launcher call sites. Deliberately KEPT for part B (external contracts, need an alias window): the REST route /api/quickmarks and its `quickmarks` response key, the CLI quickmark/quickmarks verbs, and the plugin read:findings capability / findings.list method. Validated: typecheck clean, unit 1152 passed, e2e 16 passed (incl. cli-smoke hitting the kept REST route and the bookmark visibility flow). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The ruling 8b left open, decided against the code rather than against the word on the sidebar. The answer is not "make quickmarks append-only too" — it is that the table was never a record, and the product has been claiming it was.
Six columns, no
operator_id, noengagement_id, nohash. Every feature on its page is a bookmark feature: a CDP poll for the focused tab, title/URL autofill, open-in-browser, a dot whose colour is a hash of the title. Its own shipped copy reads "Click + Capture to bookmark the current browser state", and ARCHITECTURE.md already classified it "Bookmarks. Not chained."So mutability was never the false part. These three were:
markerevent and never touches this table. The page's empty state told them to press ⌘⇧M, a key that cannot produce a row on it.events.jsonl, in a bundle whose README classifies two files and never names it, and which the bundled verifier never opens. Sharpest case: the scope-filtered export ran events through the filter and these rows around it, so a file labelled scope-filtered carried URLs for hosts the operator had deliberately excluded.urlis an immutable marker field, and no marker had aurl.Markers now carry
url— filled once from the browser connector, editable, and deliberately not amendable, because it is where the mark points (the web analogue ofatTimestamp). That makes 8b true; 8b moves from partial to done.Why not append-only. Triggers on a table with no hash, no signature, no place in the chain or the anchor, and no verifier that reads it buy the feeling of immutability and none of the checking —
DELETE FROM quickmarksstill works. And they would remove the only removal path there is:createQuickMarkruns no redaction andsanitizereadseventsonly, so a password pasted into a note is unmaskable in both directions and the hard delete is the operator's sole remedy. Append-only would keep that credential forever — and until this PR it also shipped it.Deferred, recorded: the internal identifiers (
findings.ts,FindingsView,quickmarks:*IPC, the REST route, the CLI verb, theread:findingsplugin capability) keep their old names. Renaming them needs aliases so third-party plugin manifests and installed integrations survive — a rename-only PR. The SQL table name stays for the same reason.Verification: npm run typecheck clean · npm test 1055 passed (98 files) · npm run build · playwright 89 passed, 1 skipped.
🤖 Generated with Claude Code