Keychain 4.0.0 — Release Announcementc

Keychain 4.0.0 — Release Announcement

We are pleased to announce Keychain 4.0.0, a major release of the Moqui Shopify credential-vault component. This release brings an OMS instance approval workflow, per-purpose email notifications, expanded access scope management, and full compatibility with Moqui/Maarg 4.0.0.

Full diff: Full Changelog: https://github.com/hotwax/keychain/compare/v3.4.0...v4.0.0


Highlight: OMS Instance Link Approval Flow

The most significant change in this release is that linking a Shopify app installation to a HotWax OMS instance now requires explicit approval from an authorized Keychain user before any credentials are delivered.

How it works:

  1. The connector app (or merchant) submits a link request as before — POST /rest/s1/shopify/app/instance with the instance address and OMS Access token.
  2. Keychain records a Pending ShopAppInstanceRequest and holds the OMS token in escrow. The ShopifyShopApp record is not updated at this point — no credentials are sent to the OMS.
  3. Approvers receive an email notification (via the new KC_INST_REQ_APPROVAL template, configured per-app in ShopifyAppEmail).
  4. An authorized user reviews the request on the Instance Requests screen or the Installation Detail screen and either Accepts or Rejects it.
  5. On acceptance, Keychain immediately pushes the escrowed credentials to the OMS via sync#InstanceRequest. If the OMS returns an error (unreachable host, expired token, etc.) the request moves to Failed — ShopifyShopApp remains untouched and the token stays in escrow so the sync can be retried from the screen.
  6. Once a request reaches Accepted, that is the terminal state. A repeat set#HotwaxInstance call for the same shop + app + instance returns the current status without re-sending credentials or overwriting the token.

Request lifecycle:

Status Meaning
SairPending Awaiting approver action; token held in escrow
SairAccepted Credentials delivered to OMS; link written to ShopifyShopApp
SairFailed OMS delivery failed; token still in escrow; retryable via Sync
SairRejected Approver rejected; no credentials sent
SairSuperseded A new request replaced this one

Edge cases handled:

  • A repeat submission for the same instance on an open Pending request refreshes the escrowed token and timestamp — no duplicate request or second notification is created.
  • A submission for a different instance while a Pending request is open supersedes the existing request and opens a new Pending one.
  • Shop apps already linked to an OMS (pre-upgrade) have no ShopAppInstanceRequest row. Their next set#HotwaxInstance call will create a Pending request that must be approved once; credential rotation continues to work meanwhile since ShopifyShopApp is untouched. To pre-approve existing links, insert an SairAccepted row per active installation with a hotwaxInstanceId (no instanceToken required).

New Features

  • Per-purpose notification emails — New ShopifyAppEmail entity replaces the single contactEmail field. Recipients and email templates are configured per app and purpose (SaepAppInstall for installation notifications, SaepInstanceApproval for OMS link approval requests). Both fields must be set or the notification is skipped.
  • Uninstall webhook — Added service to subscribe to the Shopify app/uninstalled webhook; installations are automatically expired when the app is removed from a shop.
  • Tenant management screens — New screens to find and create HotWax tenants; create#Tenant renamed to findOrCreate#Tenant with host-address normalization.
  • About screen — New screen with options to clear the Moqui cache and run GC.
  • App scope management — New screens to list and manage Shopify access scopes per app; custom scope detail page; accepted scope tracking via ShopifyAppAcceptedScope entity; audit history via seca rule.
  • User groups — Two pre-configured groups: KEYCHAIN_VIEW (view-only) and KEYCHAIN_ACCESS (full action access).
  • User account screen — New screen to create and view Keychain user accounts.
  • OMS sync log — Every credential sync attempt is logged as a SystemMessage of type HotwaxInstanceSync (status, endpoint type, timestamp, sanitized error). Visible on the Installation Detail screen and in the System app’s System Message screens.

Improvements

  • Upgraded to Moqui/Maarg 4.0.0 compatibility
  • Component renamed from shopify-app to keychain
  • Maarg instance support for credential sync: Keychain auto-detects whether the target OMS is a Maarg instance or a legacy OFBiz OMS via a handshake request and routes credentials accordingly
  • Masked display of app secrets and Shopify access tokens in all screens
  • Status field added to ShopifyShop and HotWax instance records
  • Expired app installations are now displayed on the shop detail screen
  • Filter added to the Find Installation screen
  • getShopAccessScope and getShopifyShop moved from XML to Groovy for readability
  • FK constraints added to ShopifyShopWebhookContent; index added to ShopifyAppHistory
  • Default Moqui REST endpoints (/rest/s1/moqui, /rest/m1) are now denied for ALL_USERS by default; grant AUTHZT_ALWAYS to a user group to re-enable

Bug Fixes

  • Fixed HMAC verification to use MessageDigest.isEqual (timing-safe) instead of .equals()
  • Fixed webhook payload storage: now stored as JSON instead of a Java Map
  • Fixed custom scope inclusion in access scope during installation and reinstallation
  • Handled client secret rotation: Keychain now validates HMAC against both the current and previous secret so shops using old credentials during a rotation window are not rejected
  • Fixed app/uninstall webhook subscription to use the actual Shopify app ID instead of the internal ID
  • Fixed NPE in installation flow

Upgrade Notes

Run the SQL migrations in upgrade/UpcomingRelease/UpgradeSteps.md before deploying. Key steps:

  1. Add FK constraint on SHOPIFY_SHOP_WEBHOOK_CONTENT
  2. Add index SHPFY_APP_HIST_SHOP on SHOPIFY_APP_HISTORY
  3. Load UpgradeData.xml (new enumerations, user groups, email templates, artifact authz)
  4. Configure ShopifyAppEmail records for each app and notification purpose
  5. Update any component references from shopify-app to keychain

Feature Maarg instance support for credential sync will be available from maarg v6.0.0 release