# Obfuscation glossary

AfterPack's documentation vocabulary: polymorphism, non-materialization, reversal classes, and the rest, defined once.

Source: https://www.afterpack.dev/docs/glossary

AfterPack's documentation uses these terms with the meanings defined here.

## The two axes

AfterPack's protection is described along two independent axes: how hard *one* build is to reverse, and how different builds are *from each other*. You can turn one up without the other.

### Complexity

How hard a single build is to reverse: the depth of protection within one artifact. Set by [`complexity`](#complexity), directly or from a [preset](https://www.afterpack.dev/docs/presets#the-ladder).

### Per-build polymorphism

How different each build is from the last. Set by the [seed](#seed): [`seed`](https://www.afterpack.dev/docs/config#seed) in the engine config, [`--seed`](https://www.afterpack.dev/docs/config#seed) on the command line. This is AfterPack's primary defense. Because there's [no fixed structure](#no-fixed-structure) to fingerprint, a deobfuscator written against one build does not carry to the next. An attacker who fully reverses one build has to start over on the next, and that work doesn't transfer. See [How AfterPack works](https://www.afterpack.dev/docs/concepts#a-new-program-every-build).

## Configuration

### Preset

A named bundle of protection settings, selected with [one flag](https://www.afterpack.dev/docs/config#preset): `minify`, `light`, `medium`, `hard`, `extreme`. Default is `light`. One preset name sets three parameters together: [`complexity`](#complexity), the total output multiplier, and the [inflation budget](https://www.afterpack.dev/docs/config#inflation-max). The ladder and the target each rung sets are on [Presets](https://www.afterpack.dev/docs/presets#the-ladder).

### complexity

The degree of entanglement in the output; see [Configuration](https://www.afterpack.dev/docs/config#complexity). It has no upper bound. The engine keeps inflating output toward this target; an explicit [`inflation.max`](https://www.afterpack.dev/docs/config#inflation-max) that blocks it fails the build, while the preset's own budget stops the inflation and still emits. Per-preset values are on [Presets](https://www.afterpack.dev/docs/presets#the-ladder).

### Directives

In-source [block](https://www.afterpack.dev/docs/directives#writing-one) comments that adjust protection on the construct they attach to. An inline [`/* @afterpack preset=extreme */`](https://www.afterpack.dev/docs/config#preset) covers the literal right after it. A block form, `/* @afterpack <key>=<value> */ … /* @afterpack end */`, opens with the marker alone on its line and closes with the matching `end`, covering an explicit span. A `//` line comment is not scanned. [`skip`](https://www.afterpack.dev/docs/config#skip) reduces protection where you need compatibility; [`preset=hard`](https://www.afterpack.dev/docs/config#preset) or [`preset=extreme`](https://www.afterpack.dev/docs/config#preset) raise it. Only a [Pro](https://www.afterpack.dev/docs/pro) engine honors a region; see [Free builds](https://www.afterpack.dev/docs/directives#free-builds). A Free carve-out uses [`paths.exclude`](https://www.afterpack.dev/docs/config#paths-exclude) or [`identifiers.reserved`](https://www.afterpack.dev/docs/config#identifiers-reserved) instead. See [Directives](https://www.afterpack.dev/docs/directives).

### `preset=hard`

A directive (`/* @afterpack preset=hard */`) that raises a [region](https://www.afterpack.dev/docs/directives#what-you-can-set) to [`complexity`](#complexity) 25, the [`hard` rung](https://www.afterpack.dev/docs/presets#the-ladder), and forces the [string floor](https://www.afterpack.dev/docs/config#strings-encode) on for that region regardless of the global preset. [`/* @afterpack preset=extreme */`](https://www.afterpack.dev/docs/config#preset) does the same at target 80.

## Reversal and the attacker model

### No fixed structure

The property that separates polymorphism that defeats a deobfuscator from polymorphism that doesn't. Any obfuscator can vary constants build to build. What matters is whether a persistent shape remains underneath: a string array (even encrypted), a VM interpreter, a fixed decoder bootstrap the same across every build. That shape is what a tool like `webcrack`, or a model, learns once and reuses on every build sharing it. AfterPack draws its shapes, names, constants and layout fresh from each build's [seed](#seed), so there is no build-invariant structure for a reusable recognizer to key on: a recognizer written against one build does not match the next. See [No peelable obfuscation layers](https://www.afterpack.dev/docs/concepts#no-peelable-obfuscation-layers).

### Reversal classes

Three static-attacker classes describing what a reader of the bytes, grep, AST tooling, or a blind LLM that doesn't execute the code, walks away with: renamed & encoded, flattened & fused, and destroyed & fused. A dynamic attacker who runs the code is a separate, stronger case. The class table and what each buys an attacker are on [Reversal classes](https://www.afterpack.dev/docs/reversal-classes). The third class, destroyed & fused, is not available.

### Non-materialization

The mechanism that protects a secret, separate from the reversal classes above, which recover structure rather than values. Delivered by [`transforms.comparisonHardening.enabled`](https://www.afterpack.dev/docs/config#transforms-kind-enabled), which rewrites a string equality gate into a one-way digest check so the literal is absent from the artifact. This differs from the [string floor](https://www.afterpack.dev/docs/config#strings-encode), which encodes a literal but still reconstructs it at use. It defeats a static reader and a blind LLM. It does not defeat an attacker who runs the code under an instrumented runtime; no build-time obfuscator changes that. See [How secrets survive](https://www.afterpack.dev/docs/concepts#how-secrets-survive).

## Delivery, seed and tiers

### Seed

The build parameter that selects which polymorphic output gets produced. Random by default. It is not a secret: the shipped artifact is public regardless, and knowing a build's seed doesn't help reverse it. Vary it per release in production. Pin it ([`--seed=git`](https://www.afterpack.dev/docs/config#seed)) only when you need byte-identical output, for CI caching or a reproducible audit. See [`seed`](https://www.afterpack.dev/docs/config#seed) and [Builds & releases](https://www.afterpack.dev/docs/builds).

### Source maps

Mappings that chain obfuscated output back to your original source. Useful for local debugging. A public `.map` hands an attacker a direct path to your source. Never ship one to production. AfterPack [defaults source maps off](https://www.afterpack.dev/docs/config#sourceMap-enabled) on a [production](https://www.afterpack.dev/docs/config#build-mode) build and drops the [`sourceMappingURL` comment](https://www.afterpack.dev/docs/config#sourceMap-emitUrl) too.

### Protection Map

The per-region report showing which [reversal class](#reversal-classes) landed on which line of your source. Engine-driven by default; user-directed once you [mark regions](https://www.afterpack.dev/docs/directives) on [Pro](https://www.afterpack.dev/docs/pro). Controlled by [`protectionMap.enabled`](https://www.afterpack.dev/docs/config#protectionMap-enabled). See [Protection Map](https://www.afterpack.dev/docs/protection-map), or open the [live demo](https://www.afterpack.dev/protection-map-demo.html).

### Tiers

Free, Extra MB, Indie, Team, Studio, [Enterprise](https://www.afterpack.dev/docs/enterprise). Free applies full-strength protection uniformly across the bundle. Paid tiers apply it per region and per file. Prices, allowances, and project limits are on [Plans & tiers](https://www.afterpack.dev/docs/tiers).

### Fail-closed

The rule that a Pro build never ships weaker protection than you asked for. If the Pro cloud is unreachable after retrying, or quota runs out mid-batch, AfterPack stops with a non-zero exit. It does not fall back to Free-tier or plaintext output. See [Exit codes & fail-closed](https://www.afterpack.dev/docs/diagnostics#fail-closed-no-exceptions).

## Next

- [How AfterPack works](https://www.afterpack.dev/docs/concepts): where most of these terms are used in context.
- [Configuration](https://www.afterpack.dev/docs/config): every option, and which form can set it.
- [Directives](https://www.afterpack.dev/docs/directives): the full `@afterpack` grammar and which keys apply.
- [Presets](https://www.afterpack.dev/docs/presets): the ladder the target values above come from.
- [Diagnostics](https://www.afterpack.dev/docs/diagnostics): the `DIAG_*` codes these terms show up in.
