# What an attacker can recover (reversal classes)

The static-attacker classes AfterPack's transforms fall into, and what recovering each one gets an attacker.

Source: https://www.afterpack.dev/docs/reversal-classes

AfterPack sorts its protections into classes. Each class raises the cost of reversal differently. Knowing which class covers [a region](https://www.afterpack.dev/docs/directives#what-you-can-set) of your code tells you what an attacker recovers if they read it. The [Protection Map](https://www.afterpack.dev/docs/protection-map) colors every token by the class it landed in.

## Static attacker, defined

These are **static-attacker** classes. They describe what someone who reads the bytes faces: grep, AST tooling, a deobfuscator pass, or an LLM that explains code without running it. An attacker who runs the artifact under instrumentation is a separate, stronger case, covered in the [threat model](https://www.afterpack.dev/docs/threat-model).

*(interactive reversal-classes diagram — see the web page)*

## The classes

| Class | What a static attacker recovers | Tier |
|---|---|---|
| **Renamed & encoded** (polynomial-injective) | The structure, with effort. Names and literals take real pattern-recognition work. That work has to be redone on [every build](https://www.afterpack.dev/docs/config#seed). | Free |
| **Flattened & fused** (polynomial-non-injective) | An equivalent program with the same behavior. Control flow is flattened and identities are fused, so several different original computations collapse to the same output. The mapping back to which one you wrote is gone. | Free |

The Free tier reaches both classes across your entire bundle ([the full matrix is in Plans & tiers](https://www.afterpack.dev/docs/tiers)). Higher [presets](https://www.afterpack.dev/docs/presets) push harder within those classes. The default preset is `light` ([complexity target](https://www.afterpack.dev/docs/config#complexity) `2`), so set a stronger preset explicitly for production, for example [`--preset=hard`](https://www.afterpack.dev/docs/config#preset). At `hard`, the engine applies control-flow flattening, identity fusion, and [constant destruction](https://www.afterpack.dev/docs/config#strings-encode) uniformly across the bundle.

> **A third class, destroyed & fused, is not available**
>
> No build produces it, and no region is ever classed "destroyed & fused". [`/* @afterpack preset=extreme */`](https://www.afterpack.dev/docs/config#preset) raises a region to [complexity target](https://www.afterpack.dev/docs/config#complexity) `80` with the [string floor](https://www.afterpack.dev/docs/config#strings-encode) on, which is real, measurable protection inside the flattened & fused class.

## What recovering a class gets an attacker

What a class gets an attacker depends on what they were after.

- **A secret** (an API key, a license threshold, a hardcoded table): neither class hides it on its own. A secret comes out of any program that behaves the way yours does, including the equivalent one recovered from a flattened-and-fused region. Protecting a secret takes a different mechanism. See [Protecting a secret](https://www.afterpack.dev/docs/threat-model#protecting-a-secret).
- **Understanding and cloning your code**: the flattened & fused class gives real protection here. The attacker gets a working, readable equivalent, but never proof of which implementation you actually shipped: no attribution, no library fingerprint, no confirmation it is the same algorithm as a specific project it may have come from. See [What AfterPack does not replace](https://www.afterpack.dev/docs/threat-model#what-afterpack-does-not-replace) for the limits of this property.
- **Locating and patching one check** (disabling a paywall, flipping one `return true`): neither class helps much on its own. The attacker only needs to find that one node. Finding it again costs something, and it [resets on every release](https://www.afterpack.dev/docs/config#seed). The anti-tamper transform ([`transforms.selfIntegrity.enabled`](https://www.afterpack.dev/docs/config#transforms-kind-enabled)) makes a patched build produce garbage instead of running. See [Best practices](https://www.afterpack.dev/docs/best-practices) on rotation.

## Verify it on your own build

The [Protection Map](https://www.afterpack.dev/docs/protection-map) shows the per-token proof: your original source, colored by which class hit each line, with the transform stack behind it on hover. [Open the live demo](https://www.afterpack.dev/protection-map-demo.html) or generate your own with [`npx afterpack@latest`](https://www.afterpack.dev/docs/cli#usage).

## Next

- [Threat model](https://www.afterpack.dev/docs/threat-model): the adversary ladder these classes are scoped against.
- [Protection Map](https://www.afterpack.dev/docs/protection-map): the per-token view for your own build.
- [Best practices](https://www.afterpack.dev/docs/best-practices): what to mark and why.
- [Directives](https://www.afterpack.dev/docs/directives): the markers that move a region between classes.
- [Presets](https://www.afterpack.dev/docs/presets): the ladder and the complexity target each rung sets.
