Skip to content

Release History

magicelk235 edited this page Jul 24, 2026 · 29 revisions

Release History

viaduct is versioned with npm semver and shipped from git tags. Every published GitHub Release triggers a GitHub Action that publishes the package to npm as @magicelk235/viaduct over Trusted Publishing (OIDC): no long-lived NPM_TOKEN. The current released version is 1.8.0. The project spans roughly 185 commits from 2026-05-29 (scaffold) to 2026-07-22 (working branch), and this page maps each tag to what actually shipped in it, grounded in the commit record.

Every bullet cites the (shorthash) it came from. Newest release is on top.

Cross-references: Runtime Shim · Manifest Transform · Analyzer · Build and Install · OAuth Bridge · Safari Quirks


Unreleased

Theme: an adversarially-verified sweep over the whole pipeline — eight correctness/robustness fixes, none behavior-visible on the happy path. All land in 92fa2ee.

  • Recover the CRX-embedded key with the lenient parseJsonc, not strict JSON.parse. A Chrome manifest carrying a BOM, // comment, or trailing comma made JSON.parse throw, so the key was silently dropped and the derived Chrome id (OAuth bridge, chrome-extension:// origin spoof) was lost for exactly the bundles most likely to be hand-edited (92fa2ee), see Input Handling and OAuth Bridge.
  • defaultBundleId now hashes whenever the slug isn't a lossless rendering of the name, not only when it's empty. Two distinct names reducing to the same non-empty slug (Foo/1Foo, Cafe/Café, MyExt/My-Ext) previously collapsed to one bundle id and shadowed each other in LaunchServices (92fa2ee), see Build and Install.
  • --uninstall reads the installed app's real CFBundleIdentifier to key the native-messaging broker LaunchAgent, instead of recomputing the default id. An extension installed with a custom --bundle-id used to leave an orphaned KeepAlive agent running open on the deleted app forever (92fa2ee), see Build and Install and OAuth Bridge.
  • The whole-download 5-minute wall-clock deadline is threaded through the redirect recursion as one shared deadline, instead of re-armed per hop — a 5-hop redirect chain could otherwise stay open ~30 min (92fa2ee), see Input Handling.
  • The ancestorOrigins guard regex no longer allows )/] in the receiver walk-back, so it can't start a match mid-expression (foo().ancestorOrigins…) and emit unbalanced parentheses. Latent (real bundles never call through to ancestorOrigins), but a token rewrite must never be able to produce invalid JS (92fa2ee), see Safari Quirks E3.
  • The action hotkey maps a named command key to its DOM KeyboardEvent.key form (UpArrowUp, Space" ", …) instead of the bare WebExtensions token, and falls back to the Ctrl+Shift+Y default when a token is unmappable. A command like Ctrl+Shift+Up used to wire a shortcut that could never fire (92fa2ee), see Runtime Shim and Safari Quirks A5.
  • Drop the dead try/catch around Buffer.from(key, "base64") in deriveChromeId — Node's base64 decoder never throws; the der.length === 0 check is the real malformed-key guard (92fa2ee), see OAuth Bridge.
  • Strip comments before the importScripts dynamic-argument residue test, so importScripts("a.js" /*x*/, "b.js") is recognized as fully static instead of being flipped to dynamic — which needlessly triggered webpack-chunk collection and module-mode background loading (92fa2ee), see Runtime Shim and Conversion Pipeline.

Regression tests added for the bundle-id collision, the hotkey key mapping, and the ancestorOrigins call-receiver balance.

  • Stop overwriting an extension's own browser-polyfill.min.js. uBlock Origin ships its own polyfill in its content-script list; writePolyfill copied viaduct's webextension-polyfill build over that exact file, so uBlock's vapi.js (compiled against its own copy) threw at load and every content script after it, including contentscript.js (the cosmetic/element-hiding engine), never ran. The extension installed, enabled, and badged from the background but did nothing on the page. viaduct now writes its copy under viaduct-browser-polyfill.min.js when the extension already ships one, leaving the original intact and loading both (the polyfill is idempotent) (622001c), see Runtime Shim and Safari Quirks E5. Closes #10.
  • Strip a chrome://-scheme URL (and any other unparseable-scheme host pattern, e.g. ws://) from permissions / optional_permissions during transform. Tampermonkey ships chrome://favicon/ in permissions; left in place, Safari treats the whole manifest as invalid and never loads the extension, even though it installs and registers with pluginkit. The analyzer already warned but the converter left it alone (warn-don't-move), which is right for a merely-ignored https:// pattern but fatal for a Chrome-only scheme Safari can't grant anywhere. The transform now drops these the same way host_permissions already filters unparseable schemes, and the analyzer reports the case as auto-fixed (31d13b9), see Manifest Transform and Safari Quirks A6. Closes #11.

v1.8.0, 2026-07-23

Theme: Safari runtime-compat fixes, driven by the TWP – Translate Web Pages conversion (#4) and a review-surfaced XHR bug (#6). Squash-merged as #5 (7247e8b) and #8 (47d2454); per-fix shorthashes below are the working-branch commits.

  • Route content-script messages and XHR through the correct Safari paths (26605b7), see Runtime Shim.
  • Stop hijacking onClicked actions and preserve version_name in the transformed manifest (5b1bd03), see Manifest Transform.
  • Guard ancestorOrigins reads and rewrite self-page chrome-extension:// URLs during staging (02c4007), see Safari Quirks E3 / B1.
  • Prepend the compat shim to MV2 background scripts so the background survives load (0240e1d), see Safari Quirks A1.
  • Strip ftp:// from contextMenus URL patterns (4a5cae9), see Safari Quirks F4.
  • Cap commands at Safari's 4-shortcut limit (d3fcb9a), see Manifest Transform / Safari Quirks A4.
  • Make top-level content-script globals re-injection-safe (const/letvar) so Safari's double-evaluation of a document_end/all_frames group into a shared world can't throw "Can't create duplicate variable" (1f22a10), then normalize ./ and backslash content-script js paths so every referenced file is reached (2dc30ca), see Safari Quirks E4. Closes #4.
  • Proxied XHR fires timeout (+ loadend), not error, on a timeout (2501a8b), see Safari Quirks D6. Closes #6.

v1.7.0, 2026-07-21

Theme: debugger/CDP emulation, native-messaging broker, real Chrome-id derivation, plus licensing.

  • Emulate chrome.debugger / the Chrome DevTools Protocol for converted extensions (a2a0f55), see Runtime Shim.
  • Native-messaging broker so runtime.connectNative works on Safari (05cc244), see OAuth Bridge.
  • Derive the Chrome extension id from the CRX public key instead of guessing (34d4724), see Build and Install.
  • Source-comment tidy (f7e3c75).

Licensing / meta milestones folded into this release window:

  • Added an MIT license and privacy policy (8579c84), then a security policy (3c94a79).
  • Relicensed under PolyForm Shield 1.0.0 (a8bd84d), the current license.

v1.6.0, 2026-07-18

Theme: main-world content scripts.

  • Re-declare content-script page-world injections as world: MAIN so scripts that expect the page's own JS context behave on Safari (d35e3ad), see Manifest Transform and Safari Quirks.

v1.5.0, 2026-07-18

Theme: popup-less action buttons.

  • Popover-free toggle for popup-less onClicked actions, so a toolbar button with no popup fires its click handler on Safari instead of opening an empty popover (e9ba1e3), see Safari Quirks.
  • Analyzer now flags blocking-webRequest content blockers that can't block in Safari (dbe3442), with README guidance that full uBO can't block and users should reach for uBO Lite (644e97e), see Analyzer.
  • deriveAppName whitelists characters to stop XML/scheme injection into generated project files (ba89cc7).

v1.4.8, 2026-07-14

Theme: URL-rewrite correctness fix.

  • Keep concrete-host chrome-extension:// URLs intact rather than rewriting them (1b7b6f5), see Safari Quirks.

v1.4.7, 2026-07-13

Theme: docs.

  • Spell out the Safari website-access grant step users must perform after install (2ea6657), see Build and Install.

v1.4.6, 2026-07-12

Theme: Safari blob downloads, dark mode, webpack SWs, popup tightening.

  • Safari blob downloads, dark-mode pages, webpack service workers, and WebSocket hosts (7acf2ca), with follow-ups to preserve the filename via the share sheet (bfa7903) and to make direct one-click blob downloads keep the correct extension (6c2396d).
  • Route offscreen-document replies and rewrite the chrome-extension: scheme (5a12186); strip the ?tabId query from popup sender.url (49c41cb), see Runtime Shim.
  • Keep a declarativeContent-gated action button clickable and further tighten popup sizing (db06848), see Safari Quirks.

v1.4.4, 2026-07-06

Theme: docs / release chore.

  • Smaller viaduct ASCII icon in the README (39820ba); release bump (886284c). No code changes.

v1.4.3, 2026-07-06

Theme: docs / release chore.

  • New viaduct ASCII icon and README banner update (357a49e); release bump (a62f069). No code changes.

v1.4.2, 2026-07-05

Theme: bug-hunt hardening at scale, plus config/batch/--verify.

This is a large release built mostly from multi-agent audit passes, hundreds of small correctness fixes across the shim, manifest transform, OAuth templates, and analyzer accuracy:

  • Config file, batch convert, and --verify mode (33e9bce), the batch/verify feature landed here, see Build and Install.
  • Wire 4 previously-inert shim stubs to real Safari/web implementations (94ad310); strip two Safari-unrecognized permission tokens (774d0a8), see Runtime Shim and Manifest Transform.
  • Shim runtime hardening, frozen-root throw guards, storage.session correctness, missing runtime APIs (f344d7a); external-messaging events and proxy-config substitution guard (54172b4).
  • Resolve __MSG_*__ i18n placeholders in the generated background.html title (f02a0cc), see Manifest Transform.
  • Rolled-up audit fixes: 6 bugs (e9150d8), 9 bugs (4f42d8f), 5 issues (23aef5e), 13 issues (b016620), 8 more shim gaps from corpus cross-reference (8f8aef6), 22 issues across runtime/CLI/analyze (9a221ce), 13 bugs incl. iOS build/crashes/OAuth/codegen (eb71af6), and 28 bugs incl. shim semantics/manifest/OAuth/analyze (6e0d73b).
  • Single source of truth for the default Safari min-version (45f4d29); removed the scratch scripts/ and docs/ dirs (7f971ad); new README ASCII icon (dd17de2).

v1.4.1, 2026-06-24

Theme: sidePanel + action badge fixes.

  • Safari sidePanel toggle and action-badge init-abort fixes, with 5 extension test reports (4d1109a), see Safari Quirks.
  • 14 correctness bugs from a deep multi-agent codebase audit (e5d343b).

v1.4.0, 2026-06-24

Theme: many audit fixes, the Grammarly port-routing rewrite, and the src/ reorg.

The headline work is getting real extensions (Grammarly, uBlock) to actually run on Safari, driven by the port-routing rewrite:

  • Rewrite chrome.runtime.id to the UUID host and strip the runtime.id prefix from port-routing matchers so Safari routes popup↔background ports correctly (362feb9, cc611a3), then remove the now-dead port-clone machinery the matcher rewrite superseded (43047af), see Runtime Shim. Root-cause chain documented in b05abd8.
  • Supporting shim fixes for the same goal: route popup port by lowercasing sender.url host (e90a45f); forward cloned-port methods bound to the real port for Safari's brand check (7c39c87); defineProperty-wrap native onConnect/onMessage/cookies events (16eccc6); backfill storage.session.setAccessLevel and clear runtime.lastError so background init can't hang or reject (e0a70ea, f3eb880); carry the httpOnly session cookie through the native-host auth proxy (6071347); guard cookies.onChanged against Safari null events (8952cd5); restore resource loading + connect-src 'self' for Grammarly's background init (7debbf8).
  • Make converted extensions survive Safari's frozen/exotic namespaces and no-chrome globals; backfill MV3 enums/storage/userScripts events on the resolved namespace (73c1926, ca523e8, b81dda0, 1880790); blocking webRequest degrades instead of aborting conversion (aa89a20), see Runtime Shim and Analyzer.
  • Input: descend into the lone manifest-bearing subdir of a repo-style layout (e64f335); balanced-paren importScripts neutralization + DNR path-escape guard (e8830e0).
  • Large refactor splitting src/ into concern folders input/manifest/analyze/runtime/build (a07abde), extracting the shim runtime JS to src/runtime/safari-compat-shim.js (2927cdf) and the Safari compat-data tables out of manifest.ts (3f919d0); added CLAUDE.md architecture docs (41779ff).
  • Final rollup of audit correctness bugs across shim/analyze/manifest/build (d885422); the release also carries per-extension Safari test reports and a live-testing debug protocol (7bd822d).

v1.3.1, 2026-06-21

Theme: UA-sniffing detection + a bug hunt.

  • Detect navigator.userAgent Chrome-version sniffing so the analyzer can warn about it (a534d69), see Analyzer.
  • Surface shim-emulated APIs in analysis output and fix pluginkit parsing (30509f8), see Analyzer.
  • Bug-hunt fixes: 3 conversion bugs (cef6aee); bundle-id collisions + a symlink leak in staging (b0c81a1); native-proxy Response crashes on out-of-range/null-body status (3a16e42); shim fill() no longer clobbers legitimately-falsy native members (273272b); sanitize hosts/origin in generated native-proxy Swift literals (dab04f1); fix report handling of the MV2 page_action fold (72158b8).

v1.3.0, 2026-06-20

Theme: emulate complex Chrome APIs behind a catch-all shim safety net; keyboard-shortcut management.

  • Emulate complex Chrome APIs and add a catch-all shim safety net so unknown chrome.* access degrades gracefully (75d6cd2), see Runtime Shim.
  • Make keyboard-shortcut management work in Safari, which has no chrome://extensions/shortcuts page (503e14f), and warn at build time on hardcoded chrome://extensions/shortcuts (or settings) links (f74597a); documented in the shim feature list (e7d1653), see Safari Quirks.
  • First real test suite lands and hardens the release: applyDnr (7e8477d), analyzeManifest CSP/host-misplacement (1156251), scanExtension detections (2cc6c34), extract.ts CRX3/zip-slip (748a9eb), plus a DNR keyless-ruleset fix and sidepanel-open test (cd9b73c).
  • GitHub issue templates for conversion failures, broken extensions, and feature requests (ed8be98, later trimmed in 2d7b4ac).

(This tag range also sweeps up the tail of the README ASCII-banner iteration 700c32185e408c and the final publishing-pipeline commits 1d728d247b3dea, see the v1.2.x note below.)


v1.2.8, 2026-06-19

Theme: the rename to viaduct, @magicelk235 scoping, and the Trusted-Publishing burst.

This is where chrome2safari became viaduct and npm publishing was rebuilt:

  • Rename chrome2safariviaduct across README, package, CLI, and source (6624163, c497683); scope the package as @magicelk235/viaduct and add a release publish workflow (aaa1437); switch to npm Trusted Publishing (OIDC) instead of NPM_TOKEN (df4346f), see Build and Install.
  • Publishing-pipeline hardening (one note for the whole burst). Standing up OIDC Trusted Publishing took an iterative sequence of CI/npmrc fixes, 1197fd9 (bump past the burned 1.2.6 publish), a983d3a, 2a8ce3f (run on macos-latest, the package is os:darwin), cca58cd (shell-expanded test glob), 1d728d2 (pin node, verify npm version), 01cc7a7/8073d4e/0dadd91 (registry-url and .npmrc token-auth juggling so OIDC isn't shadowed), 6038846/47b3dea (diagnostics added then removed once proven). The 1.2.6/1.2.7 versions were consumed pre-tag; v1.2.8 is the first tag published via Trusted Publishing.
  • Shim/analyzer work carried in this window: shim chrome.windows/devtools/app plus a CORS proxy and build-config hardening (8255ebc); first test suite + CI gate with corpus-run bug fixes (0dd9519); oauth-bridge idempotency, CSP sandbox scoping, optional-perm host warning, CDP MAIN-world eval (0fe0447), see OAuth Bridge; derive extension id generically instead of hardcoding Claude's (208eaa6); two converter-hardening sweeps (0ed107a, 7395bec); flag native-messaging usage for Safari (a9c2e80).
  • Manifest/CLI/analyzer additions earlier in the window: manifest compat transforms + validation + input hardening (b20954b); CLI lifecycle flags and new compat checks (a40114e, 24424b4); complete chrome.i18n and harden the runtime shim (1f3af6f); harden staging/extraction/reporting (781b01c).
  • Popup sizing on Safari iterated toward "floor only, never overrides the app's own size" (0601904, b33698a, fb05734, bf77318), see Safari Quirks. Service-worker importScripts hoisted into the background page for a CSP-safe fix (fc49074).

v1.2.0, 2026-06-12

Theme: DNR sanitize, broaden the shim, unified scanner + i18n, packaging robustness.

  • Sanitize static DNR rulesets for Safari (55d8b0e), see Manifest Transform.
  • Broaden chrome.* polyfill coverage and fix runtime gaps (a69e926), see Runtime Shim.
  • Unified scanner with i18n name resolution and richer checks (744822b), see Analyzer.
  • Packaging robustness and lockfile sync (f415d0c); publish-workflow token fix (7dc63b0), and a post-tag URL fix for provenance validation after the repo rename (e1d9317).

v1.1.0, 2026-06-08

Theme: expanded compat analysis, stub no-equivalent namespaces, bundle the polyfill.

  • Expand Safari compatibility-analysis coverage (0d9e8e4), see Analyzer.
  • Stub no-equivalent chrome.* namespaces in the compat shim (1232fff), see Runtime Shim.
  • Bundle webextension-polyfill for browser.* parity (67e2039).
  • CI to auto-publish to npm with provenance on version tags (45e6366), the first publishing automation, later replaced by OIDC in the v1.2.x burst.

v1.0.1, 2026-06-06

Theme: the initial converter, made npm-publishable.

The 1.0 line predates tags, it runs from the scaffold at 2fd033c through the v1.0.1 tag. This is the whole first-cut pipeline:

  • TypeScript CLI scaffold and workspace hygiene (2fd033c); shared types and process/IO utilities (ac8f154).
  • zip/crx/dir extraction with xattr cleanup (3846882); Safari manifest analysis/transform and a JS API scanner (5103497), see Manifest Transform and Analyzer.
  • The runtime compatibility shim, storage.sync, identity, sidePanel, notifications (530a7ed), see Runtime Shim.
  • Clean asset staging into a persistent output dir (7f0e825); packager wrapper with built-.appex bundle-id verification (e3e3007); pipeline orchestrator, CLI, reporting, and Safari 18 temp-load (c212d81), see Build and Install.
  • Safari OAuth bridge, identity polyfill + page bridges (53b8e3c), see OAuth Bridge; DNR ruleset to pin Origin for api.anthropic.com (5d1d542); a second runtime shim pass with a chrome.debugger polyfill and SW→background-page conversion (2b09dd6).
  • Safari fixes that made the output actually load: extension discovery + popup compatibility (a3a7ef5), persistent install via team signing + crash fixes (1a6ecef), MV3 non-persistent background + move-not-copy of the built app (bd3bbc7), and the analyze exit code / empty-action injection / debugger.onDetach fixes (146b6ca).
  • Made the package npm/npx-publishable (3013af2) and cut the release (c996214).

Clone this wiki locally