# `MobDev.SecurityScan.BundledRuntime.Fingerprint`
[🔗](https://github.com/genericjam/mob_dev/blob/master/lib/mob_dev/security_scan/bundled_runtime/fingerprint.ex#L1)

Extracts versions from `~/.mob/cache/otp-*-{hash}/` and from exqlite
C sources in a project's `deps/`.

This module is the *receipt* side of the manifest-first design.
`BundledVersions` records what we *claim* shipped; `Fingerprint`
reads what's *actually* on disk. The bundled-runtime scan layer
asserts they agree.

Pure functions only — no advisory feed lookups, no severity
judgements. The fingerprinter answers "what version is this binary?"
and nothing else.

# `tarball`

```elixir
@type tarball() :: %{
  platform: :android | :android_arm32 | :ios_sim | :ios_device,
  hash: String.t(),
  path: Path.t()
}
```

One cached tarball found on disk.
`:platform` is decoded from the directory name; `:hash` is the trailing
OTP commit hash from `MobDev.OtpDownloader`.

# `tarball_versions`

```elixir
@type tarball_versions() :: %{
  erts: String.t() | nil,
  elixir: String.t() | nil,
  openssl: String.t() | nil,
  exqlite_beam: String.t() | nil
}
```

Versions extracted from a single tarball. Any field may be `nil` if
fingerprinting failed for that artifact (e.g. libcrypto.a was stripped
in an unexpected way). The layer reports such cases as findings, not
silent failures.

# `fingerprint_sqlite`

```elixir
@spec fingerprint_sqlite(Path.t()) ::
  {:ok, String.t()} | {:error, :not_found | :unparseable}
```

Fingerprint the SQLite version compiled into exqlite from a
project's `deps/exqlite/c_src/sqlite3.c`. SQLite is bundled per-app
via the exqlite Hex package, not via the OTP tarball, so it's
scanned at the project level.

# `fingerprint_tarball`

```elixir
@spec fingerprint_tarball(Path.t()) :: tarball_versions()
```

Fingerprint a single tarball directory. Returns the versions
extracted from disk.

# `locate_cached_tarballs`

```elixir
@spec locate_cached_tarballs(keyword()) :: [tarball()]
```

Locate every cached OTP tarball under `~/.mob/cache/`.

Returns a list of `tarball/0` entries, sorted by platform then hash
for stable output. Filters out anything that isn't a directory or
doesn't match the `otp-{platform}-{hash}` naming scheme.

Pass `:cache_dir` to override the default path (used in tests).

---

*Consult [api-reference.md](api-reference.md) for complete listing*
