Centralizar decrypt de Secret em @decocms/start/sdk/crypto:resolveSecret (em vez de cada app reimplementar)
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 1
- Forks
- 0
- PR merge metrics
- No merged PRs in 30d
Description
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
encryptedfalha
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-start — website/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.ts — resolveSecret:
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
- Substituir
website/loaders/secret.tsem apps-start por uma versão que chamaresolveSecretdo framework e expõe a interfaceSecret { get() }por compat com call sites legados. - Migrar
magento/client.ts:resolveSecretinterno pra delegar pro framework — mesma função, com decrypt grátis. - Mesma migração para
algolia/client.ts(PR #69 / #66 follow-up). - (Opcional) Remover
website/actions/secrets/encrypt.tsdo 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
Contributor guide
No contributing guide indexed for this repository
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start by comparing website/loaders/secret.ts with the existing resolveSecret and decryptSecret implementations in sdk/crypto.ts. Then inspect the local resolveSecret functions in magento/client.ts and algolia/client.ts, along with their callers. Done means the loader and clients delegate to the framework helper while preserving the legacy Secret { get() } interface and encrypted-secret fallback behavior.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- security
- Issue type
- Refactor
- Difficulty
- 4/5
- Estimated time
- 3-5 days
- Activity status
- Quiet
- Clarity
- Mostly clear
- Newbie friendliness
- 55/100