# Architecture

The framework is a TypeScript executable that links four internal subsystems. They are described below in execution order. Each subsystem is documented in detail in the corresponding reference chapter; this section sketches the contract between them.

## The fork engine

The fork engine is responsible for materialising a snapshot of on-chain state on the local filesystem. Given a program ID and a network, it issues a `getProgramAccounts` call with `encoding=base64` to retrieve every account owned by the target program. The resulting snapshot is serialised into a `.solforge/snapshots/<network>/<programId>/<slot>.json` directory, indexed by the slot at which the snapshot was taken.

Snapshots are content-addressed by `(programId, network, slot)`. Re-running `fork` against an already-snapshotted slot is a no-op; this is what allows the recipes chapter to recommend committing snapshots into the repository.

## The IDL loader

The IDL loader resolves an Anchor IDL for a given program ID. It tries three sources in order: a local `target/idl/<program>.json` file, an `idl` PDA fetched from the network, and a path supplied via `--idl`. The first hit wins; the framework does not synthesise an IDL and will fail rather than guess.

The loader is shared by the security and fuzz subsystems. The security subsystem reads the IDL to determine which static rules apply; the fuzz subsystem reads the IDL to enumerate instruction signatures and the account constraints attached to each.

## The security engine

Security rules are typed predicates over an IDL. A rule receives the full IDL and emits zero or more findings. Each finding carries a severity (`critical`, `high`, `medium`, `low`, `info`) and a free-text rationale. The default rule set lives in `src/core/rules/`; custom rules can be added on a per-project basis by following the recipe in [Authoring a custom security check](/solanatestforge-docs/part-iii-recipes/authoring-custom-checks.md).

Findings are de-duplicated by `(rule_id, instruction_name, account_name)` tuples. A run is *failing* if it produces any finding at severity `high` or above; the threshold is configurable.

## The fuzz engine

The fuzz engine drives instruction handlers. For each instruction in the IDL, it generates a sequence of randomised input vectors — `Pubkey`s drawn from the snapshot, `u64` values in plausible ranges, well-formed but adversarial structs — and submits each vector to a sandboxed in-memory runtime that replays the handler against the forked state.

The runtime is not the BPF interpreter; it is a TypeScript reimplementation that handles the common Anchor and SPL primitives. The fuzz engine therefore does not catch bugs whose root cause is a BPF-specific deviation; it catches logic bugs, account-validation bugs, and integer-overflow bugs. The reference chapter lists which categories are covered and which are deliberately out of scope.

## Why these four

Each subsystem corresponds to a moment in the developer's day. The fork engine answers *what does production look like right now*. The IDL loader answers *which interface am I about to test*. The security engine answers *which bugs would a reviewer catch on a first reading*. The fuzz engine answers *which bugs would a determined adversary find with a thousand attempts*. The framework's value comes from chaining the four into a single feedback loop: when one subsystem changes its output, the next picks up the change without any developer action.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://solanatestforge.gitbook.io/solanatestforge-docs/part-i-foundations/architecture.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
