# El Protection Map: qué protegió un build

El informe HTML que muestra lo que AfterPack hizo con tu código: cada token coloreado según cuánta transformación recibió.

Source: https://www.afterpack.dev/es/docs/protection-map

El Protection Map es la forma de verificar tu protección: tu código fuente original, con cada token coloreado según cuánta transformación recibió.

```bash
npx afterpack@latest dist/
```

Obtienes este mapa:

*(live Protection Map demo embed — see https://www.afterpack.dev/protection-map-demo)*

## Cómo leerlo

Los tokens se colorean según la puntuación de complejidad: cuánta transformación recibió cada token, el número cuyo objetivo fija [`complexity`](https://www.afterpack.dev/es/docs/config#complexity). Cuanto más rojo el token, más transformación recibió:

| Color | Puntuación de complejidad |
| --- | --- |
| Gris | Sin complejidad añadida. El código que se deja legible a propósito también es gris. |
| Verde | Menos de 4 |
| Amarillo | De 4 a 7 |
| Rojo | De 7 a 10 |
| Rojo oscuro | Más de 10 |

El color muestra cuánto se aplicó. Selecciona un token y el inspector muestra por lo que pasó su región: las transformaciones aplicadas, cuánto de la región cubren y por qué quedó legible el código que sigue siéndolo. Un mapa de un motor anterior no tiene puntuaciones por token y muestra todo el código protegido en un solo color. Una declaración que el motor reescribió, como `var` a `let` o una función a una función flecha, aparece en una línea "Also rewritten". Un formateador deshace esas reescrituras, así que no añaden complejidad ni color.

La transformación más fuerte que tocó un token determina su etiqueta de [clase de reversión](https://www.afterpack.dev/es/docs/reversal-classes), que se muestra junto a sus transformaciones. Son clases de [atacante estático](https://www.afterpack.dev/es/docs/threat-model): describen a qué se enfrenta alguien que lee los bytes. Cuatro etiquetas:

| Etiqueta | Clase de reversión | Qué significa |
| --- | --- | --- |
| **Preservado** | Ninguna | Sin tocar: [imports de terceros](https://www.afterpack.dev/es/docs/config#paths-exclude), exportaciones públicas, todo lo [excluido](https://www.afterpack.dev/es/docs/config#paths-exclude) o marcado con [`skip`](https://www.afterpack.dev/es/docs/config#skip). Se deja legible para que los llamadores sigan resolviéndose. |
| **Renombrado y codificado** | [polinómico-inyectivo](https://www.afterpack.dev/es/docs/reversal-classes) | Identificadores renombrados, [cadenas codificadas](https://www.afterpack.dev/es/docs/config#strings-encode), flujo de control aplanado, identidades fusionadas. La estructura se puede recuperar con un esfuerzo real; derrota a los explicadores con IA y a los desofuscadores estándar. |
| **Aplanado y fusionado** | polinómico-no inyectivo | La lógica se reescribe para que varios originales distintos colapsen en la misma salida, y un atacante recupera un cálculo equivalente, no el tuyo. Ninguna transformación publicada alcanza hoy esta clase. |
| **Destruido y fusionado** | fusión destructiva | Descompuesto y fusionado a lo largo del bundle. Un lector estático recupera un programa equivalente, no cuál es el original que escribiste. No disponible; consulta más abajo. |

Pasa el cursor sobre un token para ver las transformaciones que se le aplicaron, agrupadas por categoría (por ejemplo, aplanamiento del flujo de control), junto a la clase en la que queda. [Pruébalo en la demo en vivo](https://www.afterpack.dev/protection-map-demo).

El número detrás del color es la puntuación de complejidad. Una región que recibió menos transformación de la que esperabas es la que debes subir con su [`preset`](https://www.afterpack.dev/es/docs/config#preset) o marcar con [`preset=hard`](https://www.afterpack.dev/es/docs/config#preset).

> **Un color no es una garantía de seguridad**
>
> Una región protegida resiste una lectura estática: grep, herramientas de AST, un LLM a ciegas. Un valor que usa el código en ejecución sigue siendo observable para un atacante que [lo ejecuta en un runtime instrumentado](https://www.afterpack.dev/es/docs/threat-model#the-boundary). Mantén los secretos de verdadero valor [en el servidor](https://www.afterpack.dev/es/docs/threat-model#not-a-substitute-for-server-authoritative-validation). El mapa muestra a qué se enfrenta un lector estático, nada más.

## Marca el código de alto valor

El mapa muestra más transformación donde la pides. Dos [formas de directiva](https://www.afterpack.dev/es/docs/directives#writing-one) cubren casi todos los casos. Un marcador en línea abarca el literal o la expresión del resto de su línea. Un marcador de bloque solo en su línea abre una región que cierra el `/* @afterpack end */` correspondiente; todo lo que queda entre ambos está cubierto, incluidos cuerpos de función completos.

```ts
// A single literal — API keys, license secrets, sensitive constants:
const SECRET = /* @afterpack preset=extreme */ "EXPECTED_LICENSE_SECRET";

// A whole function — validators, anti-cheat, payment flow.
// The opener is alone on its line; the matching end closes the block:
/* @afterpack preset=hard */
export function checkLicense(token: string): LicenseClaims | null {
  // ...everything in here is at complexity target 12...
}
/* @afterpack end */

// A span of several statements:
/* @afterpack preset=extreme */
const claims = JSON.parse(atob(payload));
if (claims.secret !== SECRET) return null;
/* @afterpack end */
```

Si una región que marcaste no muestra más transformación que el código que la rodea, la directiva no tuvo efecto. Normalmente un compilador eliminó el comentario antes de que AfterPack lo viera. AfterPack [informa de ello](https://www.afterpack.dev/es/docs/directives#checking-what-was-applied). La gramática completa de las directivas está en [Directivas](https://www.afterpack.dev/es/docs/directives#writing-one); los marcadores usados arriba son [`preset=hard`](https://www.afterpack.dev/es/docs/config#preset) y [`preset=extreme`](https://www.afterpack.dev/es/docs/config#preset).

## Free frente a Pro

Free ya renombra y codifica con el preset `light` por defecto, y a partir de `medium` también aplana el flujo de control y fusiona identidades dentro de un archivo. Todo eso se queda en la [clase](https://www.afterpack.dev/es/docs/reversal-classes) polinómico-inyectivo: un lector estático recupera tu estructura original con un esfuerzo real que se renueva en cada build.

[Pro](https://www.afterpack.dev/es/docs/pro) añade la [selección quirúrgica por región](https://www.afterpack.dev/es/docs/directives#what-you-can-set), que te permite pintar exactamente la docena de funciones en las que equivocarse sale caro, además de las dos transformaciones de endurecimiento ([`selfIntegrity`](https://www.afterpack.dev/es/docs/config#transforms-kind-enabled), [`comparisonHardening`](https://www.afterpack.dev/es/docs/config#transforms-kind-enabled)). Free cubre bien el grueso de un código real; Pro es lo que usas alrededor de las comprobaciones de licencia y los secretos. Compáralos lado a lado en [Niveles](https://www.afterpack.dev/es/docs/tiers).

Hoy ninguna transformación publicada produce las clases aplanado y fusionado ni destruido y fusionado. Consulta [Clases de reversión](https://www.afterpack.dev/es/docs/reversal-classes).

## Genera el tuyo

```bash
npx afterpack@latest dist/
```

Obtienes la misma vista interactiva generada sobre tu propio código fuente: un archivo HTML estático, sin inicio de sesión ni [telemetría](https://www.afterpack.dev/es/docs/config#telemetry-enabled), que puedes adjuntar a un PR. El mapa muestra tu código fuente original, así que, por defecto, solo se escribe cuando tu build emitió un source map que el motor pueda encadenar, y no en CI (`CI=true` o `CI=1`). En otro caso es opcional: pasa [`protectionMap: { enabled: true }`](https://www.afterpack.dev/es/docs/config#protectionMap-enabled) en las opciones de tu plugin y el plugin activa por ti el source map del bundler. Pasa [`--protectionMap.enabled=false`](https://www.afterpack.dev/es/docs/config#protectionMap-enabled) para omitirlo. Apunta a tu directorio de build: [Next.js](https://www.afterpack.dev/es/docs/frameworks/nextjs) escribe en `.next/`, [Nuxt](https://www.afterpack.dev/es/docs/frameworks/nuxt) en `.output/` y la mayoría de los bundlers en `dist/`.

## Dónde vive tu mapa

Un [build local (Free)](https://www.afterpack.dev/es/docs/deployment-modes) escribe el mapa en [`.afterpack/protectionMap.html`](https://www.afterpack.dev/es/docs/cli#files) en tu máquina y no envía nada a ningún sitio. El directorio lleva su propio `.gitignore`, así que git lo ignora. La CLI se niega a escribir el mapa en una ruta que se sirve. Un Protection Map publicado contiene todo tu código fuente. Nunca lo publiques.

Un [build Pro en la nube](https://www.afterpack.dev/es/docs/deployment-modes) no escribe ningún archivo local. AfterPack guarda su mapa en el [panel](https://www.afterpack.dev/es/docs/dashboard/builds) y, cuando [`protectionMap.enabled`](https://www.afterpack.dev/es/docs/config#protectionMap-enabled) está activado, el build imprime un enlace a ese mapa al terminar. El mapa lo genera el motor en la nube que hizo la ofuscación, el único motor que respeta tus directivas [`preset=hard`](https://www.afterpack.dev/es/docs/config#preset), [`preset=extreme`](https://www.afterpack.dev/es/docs/config#preset) y [`skip`](https://www.afterpack.dev/es/docs/config#skip), así que es el único mapa que puede mostrar su efecto.

> **Un mapa guardado contiene tu código fuente original**
>
> Un Protection Map es tu código, coloreado. En un build Pro en la nube se guarda en la infraestructura de AfterPack y lo puede leer **cualquier miembro del [espacio de trabajo](https://www.afterpack.dev/es/docs/dashboard/workspaces) al que pertenece el proyecto**. Si tu código fuente no debe poder leerse en todo el espacio de trabajo, desactívalo. Consulta más abajo.

Qué se guarda, exactamente:

- **Los datos del mapa de cada build**: tu código fuente original más las métricas por token que hay detrás de los colores, en Cloudflare R2, cifrados en reposo con AES-256, junto con una fila de cifras resumen (cobertura, inflación, recuentos de puntos débiles) que grafica el panel. Tu salida ofuscada no se guarda.
- **Acotado a un proyecto**, aquel al que está vinculada la [clave](https://www.afterpack.dev/es/docs/dashboard/api-keys) del build.
- **Solo lo pueden leer los miembros de ese espacio de trabajo.** No es público, no se indexa y no tiene enlace para compartir.
- **Se conserva un año y los últimos 500 builds por proyecto, lo que se agote antes.** Una tarea horaria elimina todo lo que supera cualquiera de los dos límites. La ventana de un año permite comparar una versión con la anterior. El límite de 500 builds evita que un proyecto que compila muchas veces al día acumule un año de copias de su código fuente; en un proyecto así, ese límite es el que se alcanza primero.
- **Un build que no pudo guardar un mapa deja en su lugar una nota**, que registra el motivo y los tamaños implicados, nunca tu código ni un nombre de archivo. Se conserva y se elimina con el mismo calendario, y el panel muestra ese build como *no guardado* en lugar de como uno que nunca se ejecutó.
- **Pasada esa ventana, el panel lo indica.** Las notas y los mapas caducan juntos; tu historial de builds no. Un build más antiguo que la retención anterior aparece como *sin registro*.

### Desactivarlo

Guardar mapas está activado por defecto, por proyecto. Un administrador del [espacio de trabajo](https://www.afterpack.dev/es/docs/dashboard/workspaces) puede desactivarlo en los ajustes del proyecto. A partir de entonces, los nuevos builds en la nube de ese proyecto no generan ni guardan nada; los mapas ya guardados caducan según la retención anterior en lugar de desaparecer de inmediato. Los builds Free no se ven afectados en ningún caso: su mapa se escribe en local y nunca toca la red.

**Los [gráficos de tu panel](https://www.afterpack.dev/es/docs/dashboard/builds) siguen funcionando.** Desactivar esto deja de conservar tu código fuente. No deja de registrar lo que midió un build. La cobertura, la inflación, la complejidad y el tiempo de build no contienen código, y se siguen registrando y graficando en un proyecto con la captura desactivada. El recuento de puntos débiles es la única excepción, porque se cuenta dentro de un mapa guardado. La salida ofuscada no cambia.

Un mapa guardado es lo único que AfterPack conserva en reposo que contiene tu código fuente. Todo lo demás de un [build en la nube](https://www.afterpack.dev/es/docs/cloud-api) permanece en memoria lo que dura una petición. Consulta [Privacidad y manejo de datos](https://www.afterpack.dev/es/docs/privacy).

## Siguiente

- [Clases de reversión](https://www.afterpack.dev/es/docs/reversal-classes): las tres clases que hay detrás de estas etiquetas, por transformación.
- [Buenas prácticas](https://www.afterpack.dev/es/docs/best-practices): patrones para marcar las regiones adecuadas.
- [Configuración](https://www.afterpack.dev/es/docs/config): gramática de directivas, reglas por archivo, presets.
- [Cómo funciona AfterPack](https://www.afterpack.dev/es/docs/concepts): las tres clases de reversión en profundidad.
- [Modelo de amenaza](https://www.afterpack.dev/es/docs/threat-model): el eje estático frente a dinámico que presuponen estas etiquetas.
- [Privacidad y manejo de datos](https://www.afterpack.dev/es/docs/privacy): qué guarda un build en la nube, durante cuánto tiempo y quién puede leerlo.
- [Directivas](https://www.afterpack.dev/es/docs/directives): cada marcador que puedes poner delante de una región.
- [Pro](https://www.afterpack.dev/es/docs/pro): qué desbloquea el marcado por región y los mapas guardados.
- [Demo en vivo](https://www.afterpack.dev/protection-map-demo): la misma vista, sobre código de ejemplo, sin instalar nada.
