feat(magento,algolia): use shared resolveSecret to decrypt CMS secrets#72
Merged
Merged
Conversation
`initMagentoFromBlocks` and `initAlgoliaFromBlocks` each carried their
own local `resolveSecret` helper that *only* read `process.env[name]`.
For sites that ship their secrets through the production Deco CMS —
where every Secret block looks like
`{ encrypted: "<aes-cbc hex>", name: "ENV_NAME" }` — the env-var-only
helper silently produced `apiKey: ""` and the downstream `magentoFetch`
suppressed the `Authorization: Bearer` header. Result: every Magento
request returned 401 Unauthorized, which surfaced in the field as a
minicart that never loaded (cart loader threw on the auth failure).
VTEX and Shopify already accept a `ResolveSecretFn` parameter and use
the shared `resolveSecret` from `@decocms/start/sdk/crypto`, which
walks:
1. plain string (dev override)
2. `{ get: () => string }` (legacy Secret object)
3. `{ encrypted: "<hex>" }` decrypted via (prod default)
`DECO_CRYPTO_KEY` (AES-CBC)
4. `process.env[name]` (fallback)
Magento + Algolia now follow the same chain. Both inits are async
(decryption is async) — site setups need to `await` the call before
any loader fires.
`resend/client.ts` does not have an `initFromBlocks` helper yet —
left a TODO referencing this commit so the same migration ships when
Resend grows a CMS-block bootstrap (it's currently configured via
`configureResend({ apiKey: process.env.X! })`).
Tests:
- magento/__tests__/client.test.ts: 5 new cases covering missing
block, plain string, Secret + env var, no-decrypt no-env-var
fallback, and dual apiKey + originHeader resolution.
- algolia/__tests__/client.test.ts: all existing init tests
converted to async + new env-var-fallback case for the encrypted
branch without DECO_CRYPTO_KEY.
Breaking change: `initMagentoFromBlocks` and `initAlgoliaFromBlocks`
now return `Promise<void>` and `Promise<boolean>` respectively. Site
setups must add `await`. Existing call sites (granadobr-tanstack)
will be updated in the bump-and-refactor follow-up.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
🎉 This PR is included in version 4.0.0 🎉 The release is available on:
Your semantic-release bot 📦🚀 |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Replaces local
resolveSecrethelpers inmagento/client.tsandalgolia/client.tswith the sharedresolveSecretfrom@decocms/start/sdk/cryptoso encrypted CMS secrets actually decrypt at boot.Why
Both
initMagentoFromBlocksandinitAlgoliaFromBlockscarried their own localresolveSecretthat only readprocess.env[name]. Sites whose Deco CMS ships secrets as{ encrypted: "<aes-cbc hex>", name: "X" }(the production default — admin AES-encrypts every Secret block with the site'sDECO_CRYPTO_KEY) silently producedapiKey: "". DownstreammagentoFetch.buildHeadersthen skipped theAuthorization: Bearerline entirely → every Magento request returned 401 Unauthorized.This surfaced live on
granadobr-tanstackas a minicart that wouldn't load. Curl reproduction:VTEX and Shopify already accept a
ResolveSecretFnparameter (seevtex/mod.ts:53,shopify/mod.ts:40) that walks the full chain:{ get: () => string }— legacy Secret loader{ encrypted: "<hex>" }— AES-CBC decrypt viaDECO_CRYPTO_KEY(prod)process.env[name]— env-var fallbackMagento and Algolia now follow the same chain via direct import from
@decocms/start/sdk/crypto.Breaking change
initMagentoFromBlocksandinitAlgoliaFromBlocksare now async (Promise<void>/Promise<boolean>) because the decrypt step is async. Site setups mustawaitthe calls before any loader fires.The only known consumer (
granadobr-tanstack) gets theawaitin the follow-up bump commit.Resend
resend/client.tsdoesn't have aninitFromBlockshelper yet — sites currently callconfigureResend({ apiKey: process.env.X! })manually. Left a TODO referencing this change so the same migration ships when Resend grows a CMS-block bootstrap.Tests
magento/__tests__/client.test.ts: 5 new cases — missing block, plain string, Secret + env var, no-decrypt no-env-var fallback, dual apiKey + originHeader resolution.algolia/__tests__/client.test.ts: existing init tests converted to async + new case for the env-var-fallback through an encrypted branch whenDECO_CRYPTO_KEYis unset.601 tests pass on
bun run test;bun run typecheckclean.Test plan
bun run typecheckcleanbun run test— all 49 files / 601 tests pass (+ 6 new)@decocms/appsin granadobr-tanstack,awaitthe inits, verify/deco/invoke/magento/loaders/cartno longer 401s, minicart loads end-to-end.🤖 Generated with Claude Code
Summary by cubic
Magento and Algolia now use the shared
resolveSecretfrom@decocms/start/sdk/cryptoto decrypt CMS secrets at boot, fixing empty API keys and 401s. Both init helpers are now async and must be awaited.Bug Fixes
resolveSecret(string →.get()→ AES-CBC decrypt viaDECO_CRYPTO_KEY→process.env), ensuringAuthorizationheaders are set and Magento/Algolia loaders work.Migration
awaittoinitMagentoFromBlocks(...)andinitAlgoliaFromBlocks(...)before any loader runs.Written for commit af3f294. Summary will update on new commits.