Skip to content

Centralizar decrypt de Secret em @decocms/start/sdk/crypto:resolveSecret (em vez de cada app reimplementar) #70

Description

@JonasJesus42

Resumo

@decocms/apps-start/website/loaders/secret.ts não decripta secrets — apenas lê process.env[name] ou retorna o encrypted hex as-is. Todos os inits/clients que precisam de credenciais (magento, vtex, algolia que vão sendo portados) reimplementam a mesma função resolveSecret local que também só lê env var.

Enquanto isso, @decocms/start/sdk/crypto.ts já tem resolveSecret(value, envVarName) e decryptSecret(encryptedHex) que:

  • Decriptam AES-CBC via DECO_CRYPTO_KEY (mesma chave do deco-cx/apps Fresh)
  • Cacheam o resultado em memória
  • Fazem fallback pra env var quando encrypted falha

Resultado prático: sites que não setam env var pra cada secret têm o site quebrado em prod, mesmo tendo o encrypted válido no bloco do CMS.

Comparação

deco-cx/apps (Fresh/Deno)website/loaders/secret.ts:

const getSecret = async (props: Props): Promise<string | null> => {
  if (name && Deno.env.has(name)) return Deno.env.get(name)!;
  // ...
  return moduleCache[encrypted] ??= decryptFromHex(encrypted).then(d => d.decrypted);
};

Decripta de fato — decryptFromHex usa DECO_CRYPTO_KEY.

@decocms/apps-startwebsite/loaders/secret.ts:

const getSecret = (props: Props): string | null => {
  if (name && process.env[name] !== undefined) return process.env[name]!;
  // ...
  if (process.env.NODE_ENV !== "production") console.warn(...);
  return encrypted;  // ← devolve o hex sem decriptar!
};

Só lê env var. Devolve o hex sem decriptar (o consumidor não tem como saber que é encrypted e não plaintext).

@decocms/start/sdk/crypto.tsresolveSecret:

export async function resolveSecret(value: unknown, envVarName?: string): Promise<string | null> {
  if (typeof value === "string" && value.length > 0) return value;
  if (value && typeof value === "object") {
    if (typeof obj.get === "function") { /* old Secret loader pattern */ }
    if (typeof obj.encrypted === "string") {
      const decrypted = await decryptSecret(obj.encrypted);
      if (decrypted) return decrypted;
    }
  }
  if (envVarName) return process.env[envVarName] ?? null;
  return null;
}

Faz tudo certo — decripta, faz fallback, cacheia.

Proposta

  1. Substituir website/loaders/secret.ts em apps-start por uma versão que chama resolveSecret do framework e expõe a interface Secret { get() } por compat com call sites legados.
  2. Migrar magento/client.ts:resolveSecret interno pra delegar pro framework — mesma função, com decrypt grátis.
  3. Mesma migração para algolia/client.ts (PR feat(algolia)!: migrate to algoliasearch v5 for CF Workers compat #69 / feat(algolia): initial scaffold port from deco-cx/apps #66 follow-up).
  4. (Opcional) Remover website/actions/secrets/encrypt.ts do roadmap de port — admin de criação de segredos roda no painel decocms, não precisa estar no client storefront.

Impacto

Desbloqueia sites em CF Workers que dependem só do DECO_CRYPTO_KEY env var (já setado nos deploys do decocms) sem precisar setar cada secret name individualmente. Em granadobr-tanstack: MAGENTO_API_KEY, ORIGIN_HEADER, ADMIN_KEY (algolia) — todos viriam decriptados automaticamente.

🤖 Generated with Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions