Skip to content

Fix Kaufland request signing; scope MOTIS_URL to Deutsche Bahn - #959

Merged
keysersoft merged 2 commits into
mainfrom
fix/kaufland-signature
Oct 8, 2026
Merged

keysersoft merged 2 commits into
mainfrom
fix/kaufland-signature

Conversation

@keysersoft

@keysersoft keysersoft commented Oct 8, 2026 •

Copy link
Copy Markdown
Contributor

Summary

A Kaufland seller on Cloud reported that every call fails with 401 "Request signature is corrupted" even though the keys are right. They were right: the signature was wrong on our side. They also noticed a MOTIS_URL variable on their Kaufland connector, which belongs to Deutsche Bahn only.

Changes

  • HMAC signing (rest.engine.ts): ${url} and ${path} now include the query string that is actually sent, and the serializer is pinned so the signed query is the one on the wire. The default template no longer ends with a newline.
  • Kaufland adapter: the template drops the trailing \n (Kaufland joins method, URL, body and timestamp with newlines and adds nothing after the timestamp). kaufland_list_storefronts now calls /info/storefront (/storefronts is a 404). kaufland_list_shipments is removed because /shipments doesn't exist. list_orders loses an embedded param that Kaufland ignores, and get_order now lists the values Kaufland accepts (order_invoices, delivery, kss_delivery).
  • Operator-provided env vars (cloud-managed-env.ts): MOTIS_URL used to be merged into every catalog install. Now only adapters that declare it get it, and a value posted under that name for any other adapter is dropped.

Type

  • Bug fix

Testing

  • Added/updated unit tests: the engine test reproduces the signature from Kaufland's own documentation (da0b65f5…2e2a), plus a test that a query-string request signs the URL axios really builds. Added a static check that the adapter only uses endpoints that exist, and tests for the env-var scoping.
  • Tested manually against a real seller account (read-only, in a throwaway container on the cloud host, with the reporting customer's keys): the current code gets 401. With this branch, all 7 tools return data (warehouses, storefronts, orders, get_order, order units, units, tickets).

Commands (in packages/backend unless noted):

  • npm run lint: 0 errors (12 existing warnings; unrelated --fix rewrites reverted)
  • npx tsc --noEmit -p tsconfig.json: clean
  • npm test: 480 suites passed, 10418 tests passed
  • repo root: node scripts/validate-adapters.mjs --warn exits 0, no Kaufland warnings; node scripts/adapter-count.mjs --check OK

Cloud audit (read-only): the only HMAC connector in production is the Kaufland install that reported this, so changing what ${url} means affects nobody else. 834 connectors on other adapters carry a stray MOTIS_URL. This PR stops new ones; existing rows need a separate cleanup.

Cloud and self-hosted behave the same. On self-hosted, MOTIS_URL only applies when MOTIS_INTERNAL_URL is set.

After deploy

Existing installs keep the old template stored in their encrypted authConfig, and the reconciler doesn't touch auth or endpoints. The one affected connector needs its template patched and a full catalog resync (new storefronts path, removed shipments tool).

Checklist

  • My code follows the existing code style
  • I have tested my changes locally
  • I have updated documentation (if applicable): adapter instructions
  • All existing tests pass (npm test)
  • This PR has a descriptive title

…apters

Kaufland signs METHOD\nURL\nBODY\nTIMESTAMP with no trailing newline and
with the query string in the URL. The adapter template added a newline and
the engine signed the URL without its query, so every call failed with 401
"Request signature is corrupted". Also point list_storefronts at
/info/storefront, drop list_shipments (no such endpoint) and correct the
embedded values the order tools advertise.

The cloud's operator-provided MOTIS_URL was merged into every catalog
install; only adapters that declare the variable get it now.
@keysersoft
keysersoft requested a review from D3nisty as a code owner October 8, 2026 13:25
@keysersoft
keysersoft merged commit 56c2b06 into main Oct 8, 2026
13 checks passed
@keysersoft
keysersoft deleted the fix/kaufland-signature branch October 8, 2026 13:31
@github-actions github-actions Bot locked and limited conversation to collaborators Oct 8, 2026
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant