# Native release artifact audit

MetaCrate's release gate builds and inspects every release crate and every
shipped program. The gate proves that the deliverables are native Rust
artifacts: they neither contain nor load LibreMetaverse assemblies, a CLR or
Mono host, generated foreign bindings, RPC bridges, downloaded fallbacks, or
helper subprocesses.

The authoritative inventory and allowlists are
[`ci/artifact-policy.json`](../ci/artifact-policy.json). Adding a publishable
crate, binary target, native FFI boundary, copied package input, or offline
smoke requires an explicit policy update. The auditor rejects an incomplete or
duplicate inventory.

## Clean Ubuntu prerequisites

The automated gate runs only on `ubuntu-latest`, using Rust 1.97.1 for all
release work. The clean worker installs:

- a C/C++ build toolchain, Clang, CMake, Ninja, `pkg-config`, Python 3, and
  `curl` for the pinned Skia build/download path;
- Fontconfig and FreeType development libraries for Skia;
- OpenJPEG 2.5.4 through `tools/install_openjpeg_2_5_4.sh`; and
- the distribution Opus development package.

No reference LibreMetaverse checkout, .NET SDK/runtime, Mono installation,
credentials, `.env` file, or live grid is present. The release runtime smoke is
deliberately offline. Live OpenSim validation is a separate credentialed gate
documented in [the live-grid guide](live-grid-smoke.md).

## What the gate verifies

The `artifact-audit` command performs all of these checks and fails closed:

1. Resolve the locked Cargo graph and require all 16 release/source packages to
   use versioned internal dependencies. Reject known managed-host dependencies.
2. Scan production Rust and manifest sources for helper processes, runtime
   loading, managed assemblies, and unreviewed `extern "C"` boundaries. The only
   native FFI allowlist is the reviewed OpenJPEG and Opus adapters.
3. Inspect every `.crate` archive with byte and entry limits. Reject path
   traversal, links, special files, managed-code extensions, forbidden runtime
   markers, and retained workspace dependency paths.
4. Extract the packages into a new temporary workspace and build every library
   and binary offline. All internal crates are resolved from the extracted
   archives and `METACRATE_REFERENCE_ROOT` points to a path that cannot exist.
5. Parse each executable as ELF, PE, or Mach-O and record imported symbols and
   linked libraries. Reject forbidden CLR/Mono/LibreMetaverse markers.
6. Remove all grid credentials, install traps for common managed/download
   helpers, disable external networking with invalid proxy endpoints, run
   `--help` for every binary, and execute the declared deeper fake/offline
   smokes. A helper invocation, timeout, external-service dependency, or absent
   required output fails the audit.

The resulting JSON records the source commit, exact Rust compiler, host,
package and executable hashes, binary formats, linked libraries, import counts,
runtime smoke results, and zero forbidden findings. It is created with
create-new semantics so prior evidence cannot be silently overwritten.

## Reproducing the gate

After installing the prerequisites above, package all release members in one
Cargo invocation. Atomic packaging lets Cargo resolve the versioned internal
crate set exactly as a registry publication batch would:

```sh
cargo package --locked --no-verify \
  -p libremetaverse-types -p libremetaverse-structured-data \
  -p libremetaverse-imaging -p libremetaverse-imaging-skia \
  -p libremetaverse-openjpeg -p libremetaverse-opus \
  -p libremetaverse-prim-mesher -p metacrate-lsl-tools \
  -p libremetaverse -p libremetaverse-rendering-simple \
  -p libremetaverse-rendering-mesh-foundry -p libremetaverse-rlv \
  -p libremetaverse-utilities -p libremetaverse-voice-vivox \
  -p libremetaverse-voice-webrtc -p libremetaverse-programs

METACRATE_RUST_COMMIT=$(git rev-parse --verify HEAD) \
  cargo build --locked --release -j 1 -p libremetaverse-programs --bins

cargo run --locked -p metacrate-ci-matrix -- artifact-audit \
  --artifact-dir target/release \
  --package-dir target/package \
  --evidence artifacts/release/artifact-audit.json
```

`--no-verify` prevents Cargo from building each archive redundantly. It does
not skip release verification: the following audit extracts all archives and
performs one stricter offline build of the complete package set. The generated
core is large, so the workspace release profile uses bounded optimization and
single-job CI to remain within an 8 GiB clean worker.
