feat(web): web UI v2 — bulk ops, trash, export#38
Merged
Conversation
…ions Adds two new exports to @gitmarks/core: `updateBookmarks` for applying patches to multiple bookmarks in a single atomic operation, and `restoreBookmark` which composes `updateBookmark` to clear `deleted_at`. Both are pure functions suitable for use as GitHubClient.update() callbacks. Exposes `BookmarkPatch` interface from the public index. Test count: 65 → 71. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Extend BookmarkRow with optional selected/onToggleSelect props and BookmarkList with selected/onToggleSelect/onSetAll props; checkbox UI is only rendered when onToggleSelect is provided, keeping the legacy call-site (no selection props) fully unchanged. 3 new tests → 83 total. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
… clear) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Wires useSelection + BulkActionsBar into ListPage, passing selected/onToggleSelect/onSetAll to BookmarkList. Adds two integration tests (91 web total). Also fixes BookmarkList select-all header counter text to avoid DOM ambiguity with BulkActionsBar's "N selected" label. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Adds deletedBookmarks helper, TrashList component, TrashPage route, and wires /trash into the hash router with single-item restore via bulkRestore. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…e + render Add isSafeBookmarkUrl() to @gitmarks/core with an explicit allowlist of tab-navigable schemes (http/https/mailto/ftp/chrome/about/moz-extension/ chrome-extension/view-source). BookmarkRow renders unsafe URLs as a plain italic span instead of a clickable anchor. bookmark-factory throws on any unsafe URL so the popup save-flow surfaces the error before a bad URL ever reaches the repo. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
TagChip now checks rawColor against /^#[0-9A-Fa-f]{6}$/ before using it
in the inline style object. Any value that doesn't match (e.g. a CSS
injection payload like "red; background: url(…)") falls back to the default
#475569, so React never serializes untrusted content as raw CSS.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Replace the generic readOrEmpty<T> helper with two typed functions— readBookmarksOrEmpty and readTagsOrEmpty—each of which runs safeParse after client.read returns. A schema failure (e.g. malformed attacker commit) throws, propagates to loadInitial's catch block, and surfaces as an error string instead of poisoning the in-memory state. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
encodeURIComponent() guards against owner/repo values containing slashes or other special characters that would otherwise corrupt the API path. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
Owner
Author
Post-merge security audit findings + fixesRan an Opus security audit on the project (per Sid's request). Three Critical findings; all fixed on this branch before merge. Critical fixed:
Important fixed:
Deferred to follow-ups:
Test impact:
|
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.
Summary
/trashroute with restore. Filtersdeleted_at != nullwithin the 30-day GC window.@gitmarks/core:updateBookmarks(bulk) andrestoreBookmark.Closes #25.
Test plan
packages/web/README.mdv2 checklist)gitmarks.htmlimports cleanly into Chrome / FirefoxImplementation notes
docs/superpowers/plans/2026-05-25-gitmarks-web-ui-v2.md(13 tasks, subagent-driven with per-batch review).ids+tag/folder/nowIso; the produced mutator re-readsfile.bookmarksfrom its argument, so 409 retry-replay against fresh data stays correct.🤖 Generated with Claude Code