Skip to content

Releases: ackm04/tack-ecommerce-extensions

v1.6.0 — Recovered fixes that never reached the published extensions

Choose a tag to compare

@ackm04 ackm04 released this 25 Aug 04:41
5c4dff8

This release exists because the extensions were maintained in two repositories and drifted. Some fixes were made in the TackQuote monorepo and never republished, so they were missing from the plugins merchants actually installed. Those are now recovered, and the duplication is being removed so it cannot happen again.

platform version download
WooCommerce 1.5.0 tackquote.zip
Magento 2 1.4.0 tack-magento2.zip
Shopware 6 0.3.0 tack-shopware.zip
PrestaShop 1.3.1 tack-prestashop.zip
OpenCart 1.3.1 tack.ocmod.zip

What was actually missing from your installed plugin

WooCommerce — order sync was sending a fraction of the order. The published plugin shipped a 270-line order sync against a 626-line one. Purchase-order numbers were not sent at all: if your store collects a PO number at checkout, it never reached TackQuote. Both recovered.

Magento — two fixes you have been running without. Buyer personal data was written into var/log on every API error. And a TackQuote call with a 20-second budget ran on every storefront page render rather than being cached — the fix adds a 15-minute cache and separates read and write timeouts.

Shopware — the API key field did nothing. The settings screen asked you to paste a TackQuote API key, and the plugin never read it. The method that consumes it existed in the monorepo and had never been published. If you configured a key and wondered why nothing used it, that is why.

OpenCart — the README told you to install the wrong file. It pointed at a source archive and asked you to build the installer yourself. OpenCart derives an extension's internal code from the zip filename, so following those instructions produced an extension that installs cleanly and then 404s every route. Both READMEs now point at /releases/latest/, so they cannot go stale again.

Fixes to the quote-only mode released in v1.5.0

Quote-only mode itself works, but its tests could not tell a wired guard from an unwired one. On WooCommerce and Shopware the whole suite stayed green with the enforcement disconnected — a store in that state hides the buy button while the API keeps accepting orders. That gap is closed on both.

On Magento, one merge in this release would have silently disabled all three quote-only guards on a Marketplace install: the module's class-loading map did not cover the directory the guards live in, and nothing local catches it because Magento resolves those classes anyway on a manual install. Caught and pinned.

Magento's quote-only settings section also had no translations at all, so it fell back to English in every non-English store. Fixed.

Verification

418 automated checks across the five platforms, all passing against the merged result: WooCommerce 47, Magento 173, Shopware 69, PrestaShop 58, OpenCart 71.

Every fix was proved by breaking it and confirming a test fails — 13 mutations on WooCommerce, 21 on Magento, 13 on OpenCart/PrestaShop, 5 on Shopware. Three of those mutations initially survived, each revealing something genuinely untested rather than confirming what we already believed.

Not verified: none of this was exercised against a running storefront, and wp plugin check was not run on the merged WooCommerce result. Test on a staging store before updating a live shop.

After this release

The extension copies in the TackQuote monorepo are being removed. This repository is the single source of truth: WordPress.org publishes from it, and every artifact here is built from it.

What's Changed

  • fix(wordpress): reconcile the WooCommerce plugin with the monorepo copy (#340) by @ackm04 in #15
  • fix(magento2): reconcile the two copies of the module, losing neither side's work (#340) by @ackm04 in #16
  • fix(opencart,prestashop): reconcile against the monorepo copies before they are retired (#340) by @ackm04 in #17
  • fix(shopware,squarespace): recover ping(), and prove the quote-only guard is wired (#340) by @ackm04 in #18
  • docs: state that this repository is the single source of truth (#340) by @ackm04 in #19

Full Changelog: v1.5.0...v1.6.0

v1.5.0 — Quote-only B2B store mode on all five platforms

Choose a tag to compare

@ackm04 ackm04 released this 24 Aug 18:48
b0b0b29

Turn any storefront into a B2B catalogue: Add to cart is withdrawn and customers request a quote instead. Now available on all five self-hosted platforms.

platform download version
WooCommerce tackquote.zip 1.4.0
Shopware 6 tack-shopware.zip 0.3.0
PrestaShop tack-prestashop.zip 1.3.0
OpenCart tack.ocmod.zip 1.3.0
Magento 2 tack-magento2.zip 1.3.0

On every platform you choose who it applies to — every customer, signed-out visitors only (so approved trade customers keep a normal cart), or specific customer groups — and administrators keep a working cart so you can test your own store while it is closed to customers.

It is enforced on the server, not by hiding a button

Hiding "Add to cart" with CSS is not a policy. On each platform the refusal happens in the platform's own cart code, so a hand-typed add-to-cart link, an API call, or a page served from cache is refused exactly like the button is:

  • WooCommerce — products become non-purchasable, which WC_Cart::add_to_cart() checks
  • Shopware — a decorated CartItemAddRoute throws before delegating; one decoration covers the Store API and both storefront controllers
  • PrestaShop — refused in the first statement of FrontController::init(), before any controller runs
  • OpenCart — the route is rewritten before dispatch, so core's cart controller is never constructed
  • Magento 2 — a before plugin on Quote::addProduct(), the @api method every add path funnels through

Carts that were already full

A cart filled before you switch the mode on is handled everywhere rather than left as a hole — WooCommerce and Shopware block it at checkout, PrestaShop and OpenCart refuse to grow or convert it. In every case the shopper can still empty their cart, so nobody is stranded with a basket they can neither order nor clear.

Read this before switching on

Magento: the REST, SOAP and GraphQL APIs are not covered. POST /rest/V1/guest-carts/{cartId}/items is anonymous, and Luma's own checkout places orders over webapi_rest. Quote-only is enforced for storefront traffic; a store whose API is exposed to untrusted callers is not fully closed by this release alone. Guarding those areas correctly needs work we would not guess at, so it is documented rather than faked.

Shopware Cloud is not covered. Enforcement lives in the plugin; the Shopware App ships no PHP, so a Cloud store running the app is not quote-only even if the plugin config suggests otherwise.

PrestaShop deliberately does not touch the native PS_CATALOG_MODE setting — it applies catalog mode for the current request only. That keeps per-group scoping possible, leaves the merchant's own setting alone, and means uninstalling never strands the shop in catalog mode. Order history and invoices stay reachable for customers who bought while the shop was still selling.

WooCommerce also fixes the broken Settings link

Clicking Settings on the Plugins screen previously failed with "Sorry, you are not allowed to access this page" — for administrators too. It was never a permissions problem: the link pointed at a page slug that two renames had moved. Fixed in 1.3.4 and included here.

If you are upgrading a manually installed WooCommerce 1.3.3, deactivate and delete it first — the folder changed, so WordPress treats this as a separate plugin. Your API key and settings survive.

Verification

342 automated checks across the five platforms, all passing against merged main: WooCommerce 25, PrestaShop 49, OpenCart 67, Shopware 65, Magento 136.

Each platform's guard was independently broken by hand to confirm the tests actually fail when enforcement is removed — a suite that stays green with the control deleted proves nothing.

Not verified: none of this has been exercised against a running storefront. Every platform is covered by unit tests plus reading the vendors' real source (WooCommerce 11.0.1, Shopware 6.6.10.22, PrestaShop 8.2, OpenCart 4.1.0.4, Magento 2.4.8-p5). Smoke-test on a staging store before switching a live shop to quote-only.

What's Changed

  • feat(shopware): quote-only (B2B catalog) mode, enforced on the server by @ackm04 in #10
  • feat(prestashop): quote-only (B2B catalog) mode, enforced on the server by @ackm04 in #11
  • feat(opencart): quote-only (B2B catalog) mode, enforced on the server by @ackm04 in #12
  • fix(shopware): bump plugin to 0.3.0 and add a changelog by @ackm04 in #13
  • feat(magento2): quote-only (B2B catalog) mode, enforced on the server by @ackm04 in #14

Full Changelog: v1.4.0...v1.5.0

v1.4.0 — WooCommerce 1.4.0: quote-only B2B store mode, and the Settings link fixed

Choose a tag to compare

@ackm04 ackm04 released this 24 Aug 17:53
2660682

Install

Download tackquote.zip below → WordPress admin → Plugins → Add New → Upload Plugin.

If you have 1.3.3 installed, deactivate and delete it first — 1.3.3 shipped in a tackquote-for-woocommerce/ folder, so WordPress treats this as a separate plugin. Your API key and settings are stored as WordPress options and survive.


Fixed: "Sorry, you are not allowed to access this page"

Clicking Settings on the Plugins screen failed for everyone, including full administrators.

It was never a permissions problem. The Settings link carried a hardcoded admin.php?page=tack-quotes, which was the admin page slug up to 1.3.1. The 1.3.2 and 1.3.3 renames moved the slug — first to tackquote-for-woocommerce, then to the WordPress.org slug tackquote — and left the link pointing at a page that no longer exists.

wp-admin/admin.php renders a page only if its slug is registered, and otherwise calls wp_die() with the same sentence it uses for a genuine capability failure. That collision is what made this look like a permissions bug. The page itself was always correctly registered at manage_options, and it still is — it holds the API key that authenticates your whole store.

The link is now derived from the same constant the menu is registered with, so the two cannot drift apart again.

New: quote-only (B2B catalog) store mode

A single Store mode setting turns your whole storefront into a B2B catalogue. "Add to cart" is withdrawn and customers request a quote instead — your products, categories and search keep working, only checkout goes away.

  • Applies to — every customer, or signed-out visitors only (so approved trade customers keep a normal cart), or specific roles
  • Prices — optionally replaced with "Price on request"
  • You are not locked out — anyone who can manage WooCommerce still sees a working cart, so you can test your store while it is closed to customers. Switching back restores checkout immediately.

It is enforced on the server, not by hiding a button: products become non-purchasable, so a hand-typed ?add-to-cart= link, the Store API and cached pages are all refused the same way the button is.

Two details worth knowing:

  • Carts filled before you switch are emptied on the cart and checkout pages with an explanation. WooCommerce's own cart validation checks only that a product still exists, not that it can be bought, so without this an older cart could still be checked out and the store would not really be quote-only.
  • Quote buttons now mount outside the add-to-cart form. They previously rendered inside it, so withdrawing the cart button would have removed the quote button too and left a normal-looking product page with no way to transact at all.

Other platforms

The Magento 2, OpenCart, PrestaShop, Shopware, Zen Cart, Wix and Squarespace artifacts are unchanged from v1.3.0 and are re-attached here so the latest release remains complete. Quote-only mode is being brought to the other platforms next.

What's Changed

  • fix(wordpress): Settings link led to "not allowed to access this page" by @ackm04 in #7
  • feat(wordpress): quote-only (B2B catalog) store mode by @ackm04 in #9

Full Changelog: v1.3.0...v1.4.0

v1.3.0 — WooCommerce 1.3.3 renamed to `tackquote` for WordPress.org

Choose a tag to compare

@ackm04 ackm04 released this 24 Aug 17:15
ad2e3af

Ten artifacts, all built by scripts/package-all.sh from this commit.

WooCommerce is the headline: tackquote.zip is the WordPress.org submission
artifact
, and the plugin has been renamed to its assigned directory slug.

WooCommerce — plugin 1.3.3, renamed to tackquote

WordPress.org pended our submission. The assigned slug is tackquote, and the
rule is that the text domain must equal the slug. The plugin now uses tackquote
throughout — 127 i18n literals, the Text Domain: header, the directory, the main
file, PLUGIN_SLUG and the packaged zip name.

If you installed 1.3.2 manually, delete it by hand before installing this. The
folder changed from tackquote-for-woocommerce/ to tackquote/, so WordPress sees
this as a separate plugin and you would end up with both active.

readme.txt now carries a full == External services == section — what TackQuote
is, that the plugin cannot work without it, that nothing is sent until an API key
is entered, then every endpoint with its payload and trigger, then the Terms and
Privacy links. The order-sync entry is written from this build's actual
build_payload(): eleven fields, no billing or shipping street addresses, and no
card or gateway data
.

The stale github.com/tackquote/… link that returned 404 is gone.

Downloads

Platform File Notes
WooCommerce tackquote.zip Plugins → Add New → Upload. Root is tackquote/
Shopware Cloud / 6.6+ (App) tack-shopware-app.zip Needs <setup><secret> injected — see the app README
Shopware self-hosted (plugin) tack-shopware.zip Extract to custom/plugins/TackQuote
OpenCart 4.x tack.ocmod.zip Do not rename this file — see below
OpenCart (source only) tack-opencart-source.zip Not installable; reading copy
PrestaShop tack-prestashop.zip Module Manager → Upload a module
Magento 2.4 tack-magento2.zip unzip tack-magento2.zip -d <root>/app/code
Zen Cart tack-zencart.zip Copy the contents of store-root/ only
Squarespace / Wix tack-squarespace.zip, tack-wix.zip Code snippets

OpenCart: the filename is load-bearing

OpenCart derives the extension code from the zip filename, and every namespace
and event action in the package hard-codes tack. A zip under any other name
installs successfully and then returns 404 on every route, with nothing in the
error log.

Zen Cart: copy the contents, not the folder

Copy the contents of store-root/ into your store root. Leave zc_install/
(the SQL) and the README on your own machine.

Every archive's root is now verified

scripts/addon-archive-layout.spec.mjs asserts each archive's top-level entry
against the vendor's own rule, and fails with that rule rather than just a
mismatch. It also asserts no add-on ships apps/api, apps/web,
packages/database or .env.

That gate exists because three archives were previously built with an extra
wrapper directory and could not install at all — most seriously Magento, whose
published v1.1.0 asset had a magento2/ root instead of Vendor/Module/, so
setup:upgrade could never discover it.

Verification

php -l clean on every shipped PHP file (8.2, plus 7.4 where a plugin declares
that floor). Shopware manifest validated against manifest-3.0.xsd with
name == directory. tackquote.zip confirmed to contain no bin/, tests/,
.github or *.md, with Text Domain: tackquote and Stable tag: 1.3.3 read
back out of the built archive rather than the source tree.

GitHub Actions is billing-blocked on this account, so these were built locally with
the same script the release workflow invokes.

What's Changed

  • Redesign GitHub Pages extension showcase by @ackm04 in #3
  • Refine hero banner by @ackm04 in #4
  • Mark all platform integrations as verified by @ackm04 in #5
  • fix(wporg): adopt the assigned slug tackquote, disclose the external service by @ackm04 in #6

Full Changelog: v1.2.0...v1.3.0

v1.2.0 — Storefront Extensions: reproducible builds, Shopware Cloud app, install-blocking fixes

Choose a tag to compare

@ackm04 ackm04 released this 23 Aug 18:33

Ten installable artifacts, all rebuilt from the current source by
scripts/package-all.sh.

If you tried to install from v1.1.0, that is why it did not work. No release
asset on this repo was ever built by CI — the release workflow sat in a
subdirectory where GitHub never reads it, so every zip was uploaded by hand and
they had drifted from the source.

Read this first

Platform Download Notes
Shopware Cloud / 6.6+ (App) tack-shopware-app.zip New — never shipped in a release before. Upload under Extensions → My Extensions → Upload.
Shopware self-hosted (plugin) tack-shopware.zip Extract to custom/plugins/TackQuote
WooCommerce tackquote-for-woocommerce.zip Plugins → Add New → Upload
OpenCart 4.x tack.ocmod.zip Do not rename this file. See below.
OpenCart (source only) tack-opencart-source.zip Not installable — reading copy
PrestaShop tack-prestashop.zip Module Manager → Upload a module
Magento 2.4 tack-magento2.zip unzip tack-magento2.zip -d <root>/app/code
Zen Cart tack-zencart.zip Copy the contents of store-root/ only
Squarespace / Wix tack-squarespace.zip, tack-wix.zip Code snippets

OpenCart: the filename is load-bearing

OpenCart derives the extension code from the zip filename, and every
namespace and event action in this package hard-codes tack. A zip under any
other name installs successfully and then returns 404 on every route, with
nothing in the error log. Keep it tack.ocmod.zip.

Zen Cart: copy the contents, not the folder

The archive separates what goes on the server from what must not. Copy the
contents of store-root/ into your store root. Leave zc_install/ (the SQL)
and the README on your own machine — the previous README told you to copy them
in, which published install.sql under your web root.

Fixed in this release

  • Magento's v1.1.0 asset was never installable. Its top-level directory was
    magento2/ instead of Vendor/Module/, so Magento could never discover the
    module. It also contained eight files that exist nowhere in this repository.
  • PrestaShop merchants were never offered the v1.1.0 upgrade. The module
    declared version 1.0.0 at every tag, and PrestaShop keys upgrades off that
    value.
  • PrestaShop's "no API key set" warning could never appear. config.xml said
    need_instance=0 while the class said 1, so the module installed, reported
    itself active, rendered no button, and explained nothing.
  • PrestaShop advertised order sync that does not exist. Claim corrected.
  • Zen Cart README no longer instructs you to publish the SQL under your web root.
  • WooCommerce packaging no longer risks shipping tests and dev config.
  • Versions bumped where they had never been bumped at all.

Known gaps (documented, not fixed)

  • Zen Cart install.sql is not idempotent. A second run creates a duplicate
    empty config group, then fails on a duplicate key. The README has the cleanup.
  • Zen Cart quote button on a custom template. The template file hardcodes
    template_default asset paths, so on a custom template the CSS/JS 404 and the
    button does nothing. The README documents the two manual edits.
  • Magento credential cache. After an admin edits API credentials they stay
    cached for up to 15 minutes; the observer that flushed them was one of the
    eight files that only ever existed in the old published asset.
  • Magento license metadata declares GPL-2.0-or-later while the repo LICENSE
    is MIT. Unresolved deliberately.

How these were verified

php -l on every shipped PHP file (8.3, plus 7.4 where a plugin declares that
floor); the Shopware manifest validated against manifest-3.0.xsd with
name==directory (that name is concatenated into the registration proof HMAC, so
a mismatch breaks registration silently); Zen Cart SQL executed against MySQL 8
on the authentic v1.5.8a schema; OpenCart's 29 in-repo tests passing; secret
scans clean on all ten artifacts. Every layout rule came from the vendor's own
documentation, not from a sibling directory.

GitHub Actions is billing-blocked on this account, so these were built locally
with the same script the workflow invokes.

What's Changed

  • feat(shopware): TackQuoteApp — an App installable on Shopware Cloud by @ackm04 in #2

Full Changelog: v1.1.0...v1.2.0

v1.1.0 — Storefront Extensions: security fixes, WooCommerce 1.3.1, OpenCart 1.2.0

Choose a tag to compare

@ackm04 ackm04 released this 20 Aug 18:16

First refresh of the release assets since 2026-08-01. Every archive here is rebuilt from
current main; the v1.0.0 assets were three weeks stale and predate all of the security work
below.

New in this release: tack.ocmod.zip — the OpenCart merchant installer, which was never
published before. Previously you had to build it yourself from the source archive. It must
keep that exact filename: OpenCart derives the extension code from the zip filename, nothing
inside the package pins it, and a renamed archive installs cleanly and then 404s on every route
with no error.

Package versions

Package Version Notes
tack-woocommerce.zip 1.3.1 Verified on WordPress 7.1 + WooCommerce 11.0.1
tack.ocmod.zip / tack-opencart.zip 1.2.0 Verified on OpenCart 4.1.0.4
tack-prestashop.zip 1.0.0 unchanged
tack-magento2.zip, tack-shopware.zip, tack-zencart.zip, tack-wix.zip, tack-squarespace.zip rebuilt, no source changes

WooCommerce — security and WordPress.org compliance

  • Storefront/admin XSS closed. The quote modal escaped only labels and placeholders while
    interpolating id and name raw from server-supplied requiredCompanyFields. Because the API
    base URL is a setting a shop manager can edit, this was a path to script execution in an
    administrator's browser. Proven fixed by running the shipped function against
    x" autofocus onfocus=… before and after.
  • The API key is no longer written into the settings page HTML. A masked value was computed
    and then discarded; the field emitted the real key, and type="password" hid it from the eye
    only, not from page source.
  • The settings page can now actually be saved. It was registered under manage_woocommerce
    while posting to options.php, which requires manage_options — so the one role the page was
    built for could never save it.
  • Order sync no longer sits inside checkout. It was a synchronous 20-second HTTP POST inside
    three checkout hooks, while readme.txt promised it "never blocks checkout". It is now handed
    to Action Scheduler, and that promise is true: a status transition completes in ~350 ms and
    enqueues exactly one background job — one, not two, even though both the creation and the
    transition hook fire.
  • Privacy disclosure added naming the exact fields and destination endpoint, and order sync
    now ships off by default.
  • phpcs --standard=WordPress and wp plugin check both run clean.

OpenCart

  • Admin XSS closed. The test-connection result was written with innerHTML from a remote
    response whose host is a merchant-editable setting.
  • test() now checks permissions. Against the previous code, an administrator with no rights
    on this extension could complete a live outbound call using the store's API key.
  • Silent save failures fixed. The controller wrote one error key and the template read a
    different one, so a permission denial changed nothing and said nothing. Save now answers the
    AJAX contract the form actually declares.
  • Adds the multi-product quote cart: storefront view event, drawer and controls templates, and
    the accompanying JS/CSS.

Verification

Both refreshed packages were installed and exercised on real stores rather than reasoned about.
Every archive was also checked to contain no .DS_Store, no .phpunit.cache, no node_modules,
no store-listing assets, and no secret-shaped strings — a previous release shipped test-result
caches and listing screenshots that exposed part of a development API key.

Known limitation

Buyer first/last name supplied on OpenCart and PrestaShop quote forms is not yet stored as
structured buyer identity — the buyer record's name is currently derived from the email address.
A fix is in progress and will land in a follow-up point release. WooCommerce and Magento are
unaffected and store the name as typed.

v1.0.0 - Storefront Extensions Release

Choose a tag to compare

@ackm04 ackm04 released this 01 Aug 10:21

⚠️ Superseded — do not download from this release

Use v1.1.0 instead.

The archives attached below were built on 2026-08-01 and predate every security
fix since, including:

  • a storefront XSS in the WooCommerce plugin's quote modal
  • the WooCommerce API key being printed into the settings page HTML
  • an admin XSS in the OpenCart extension's test-connection result
  • OpenCart's test() action having no permission check, so any administrator
    could spend the store's API key
  • WooCommerce order sync running a synchronous 20-second HTTP POST inside
    checkout
    , while the readme promised it never blocked checkout

They are left attached only so existing links do not 404. Nothing here should be
installed on a live store.


Initial public release of Tack B2B eCommerce extensions for WooCommerce, Magento 2, OpenCart, PrestaShop, Shopware, ZenCart, Squarespace, and Wix.