Repository navigation
Releases: rajatrv-fullstack/raindrop-brave-sync
Release list
1.1.0: installable by anyone
A deployability release. An independent fresh-install audit of 1.0.1 found that a clone of the
public repository could not be installed at all, plus twenty verified defects a second machine
would hit. Every one of them is fixed here, and the install is now rehearsed in CI on a clean
macOS runner.
Fixed
- Install blocker:
bootstrap.shcopied.env.example, which.gitignore's.env.*rule
had kept out of the repository, so every first-time install aborted before creating anything.
Bootstrap now writes.envitself and.env.exampleis tracked. RAINDROP_SYNC_ROOTnever reached the native host or the launchd agent: the host manifest
now points at a wrapper (bin/native_host) that pins the root and the interpreter, and the
plist carriesRAINDROP_SYNC_ROOTandRAINDROP_SYNC_PROFILE.- The Brave profile was hard-wired to
Brave-Browser/Default. Bootstrap now resolves the
last-used profile across stable, Beta and Nightly fromLocal State, honours
RAINDROP_SYNC_PROFILE, records the result inconfig.json(whichapply_brave.pyreads),
refuses with a clear message when noBookmarksfile exists, and detects Brave Sync (no
launchd agent is installed when it is on; the extension path still works). - A missing Xcode Command Line Tools interpreter is detected before anything is created.
- A folder rebuild (
reset_folders.json) removed every applied bookmark under the folder and
the ledger then prevented them from ever being re-created. The host now clears its ledger
rows for the folder in the same reply, so the rebuild re-creates everything. - A staged URL in a non-canonical form (
https://WWW.example.org) was duplicated beside the
browser'shttps://www.example.org/by both appliers. Both now compare canonically and the
extension trustschrome.bookmarks.search. - An entry Chromium refuses (unparseable URL, empty folder path) was retried every minute
forever and left an empty folder behind. Such entries are nowrejectedonce, terminally,
by whichever side sees them first, and the extension validates before touching the tree. - The service worker ran a second full sync on every wake; the top-level sync is gone.
- Host failures were swallowed: the extension now persists the error and backs off (1 minute
doubling to 15), checks theappliedacknowledgement, and never records a failed run as a
success. - The folder-path rule differed between the host, the file writer and the extension; one rule
now, held to one table (tests/js/folder_paths.json) by all three test suites. native_host.log,apply.out.logandapply.err.logrotate at 1 MB.is_brave_running()recognises Brave Beta and Nightly.launchctl load/unloadreplaced bybootout/bootstrap; the plist is rendered with
plistlibinstead ofsed.- SETUP.md: prerequisites were incomplete (Command Line Tools, the Raindrop MCP connector,
git); three verification greps could never match the agent label; the host version, the
manifest example, the plist PATH, the Brave Sync abort text and the ledger table names were
wrong; steps 3, 4 and 6 redid what bootstrap had done and step 3 silently replaced the key;
the skill's token example put the token incurl's argv. All corrected; the manual steps
are now an appendix, and there are "Make it daily" and "Uninstall" sections. .coveragewas committed by mistake.
Added
scripts/doctor.sh(installed asbin/doctor.sh): oneok/warn/FAILline per check,
exit 0 iff nothing failed, never prints the token. Run it first; send its output when asking
for help.scripts/ci-rehearsal.shand theInstallworkflow: a sandboxed first-time install on a
clean macOS runner with the stockpython3, on every push touching the installer orsrc/.native_host.py --init-dbcreatesstate.dbwith all four ledger tables, so the classifier
never has to; the schema has one home.tests/js/run.mjs: 25 checks over the realsw.jsunder a stubchrome, run in CI.- Eight new pytest tests (33 total).
- Knobs:
RAINDROP_SYNC_SKIP_PROFILE_CHECK,RAINDROP_SYNC_NO_KEYCHAIN,
RAINDROP_SYNC_KEYCHAIN_SERVICE;seed-token.sh --dry-run.
Upgrade impact
- Re-run
scripts/bootstrap.shfrom the updated checkout, then click reload on the
extension card inbrave://extensions(the worker changed; unpacked extensions do not
hot-reload). Your key, id, token and ledger are kept. The host manifest and plist are
rewritten to the new wrapper and environment. - No ledger migration: the four tables are created if missing and existing rows are untouched.
1.0.1: fuzz harness
Added
fuzz/: two atheris targets (native host message handler; bookmark checksum and preflight)
with aFuzzworkflow that runs them for 45 seconds on every push touchingsrc/and for
ten minutes weekly. Crashing inputs are uploaded as workflow artifacts.native_host.handle(msg): the dispatch is now a function that returns a reply dict for any
input, so it can be tested and fuzzed without a pipe.
Fixed
apply_brave.preflightraisedUnicodeEncodeErrorinstead of aborting with exit 2 when a
URL or id in the Bookmarks file held an unpaired surrogate. Found by the fuzz harness on its
first run.apply_brave.preflightnow also aborts cleanly on a Bookmarks file that is not valid JSON,
has norootsobject, or has a malformed tree, instead of raising.native_hostno longer raises on a non-object message, a non-stringclient, or a
resultsfield that is not a list of objects; each returns an error reply.
Upgrade impact
- None for users; re-run
scripts/bootstrap.shto pick up the newsrc/. No change to the
extension, the manifest, the ledger schema or any file format.
v1.0.0: first public release
First public release.
What it does: an LLM classifies a Raindrop.io library into a pinned taxonomy, writes collections and tags back, and mirrors the result onto Brave's bookmarks bar within about a minute, through an unpacked MV3 extension with a launchd file-writer as fallback.
Included:
- src/apply_brave.py: atomic Bookmarks-file writer with preflight aborts, marker-based ownership, per-prefix backups and post-write verification.
- src/native_host.py: stdio native-messaging host with a per-browser applied ledger.
- extension/: MV3 worker with serialized syncs and folder rebuild support.
- scripts/bootstrap.sh: installer that generates a signing key, derives the extension id, and registers the host in the directory Brave actually reads.
- skill/raindrop-sync: the classification pass for Claude Code.
- RESEARCH.md: ten documented Chromium and Brave behaviours, each marked verified, source-derived or untested.
Security: no known vulnerabilities fixed in this release. CodeQL, Bandit and Semgrep run on every push with hash-pinned dependencies; secret scanning with push protection and private vulnerability reporting are enabled.
Not included, by design: Safari support (no supported write path exists), a bundled taxonomy, any cloud component, any telemetry.