# Trust: signatures, tiers, the feed and the publish check (v0)

BUILD.md steps 6.1-6.3, VISION.md §9 ("Trust & safety") and §11 (takedown rules). Code:
`crates/fusion-core/src/trust.rs`, `publish.rs`, `content.rs`; commands in `fusion-cli keys`,
`package`, `feed`.

Off Steam, no store review stands between a bad package and players, so Fusion checks for itself.

## Keys

Every author has an **ed25519 key**. The secret half stays on their PC; the public half (64 hex
digits) travels in what they sign.

- Players get one the first time they **Share** something: `%LOCALAPPDATA%/Fusion/keys/me.key`,
  signing as their Windows user name.
- `fusion-cli keys new NAME [--out FILE]` makes another (for publishing routers, say).
- Fusion never overwrites a key file: a lost key can't sign updates any more, so back it up.

**Fusion's official keys** are built into Fusion (`trust::OFFICIAL_KEYS`). Since 2026-10-04 that's
the **release key** (`ca4c81b7…`, named "SteonMod"), which signs Fusion's release feed, the
content hub's index and feed, and official router packages. Its secret is kept outside the
repository and outside Fusion's data folder (`%USERPROFILE%\SteonMod-keys\official-release.key`
on the maintainer's PC); keep two offline copies (USB sticks). It replaced the development key
(`9f05ac65…`), which signs nothing official any more. Tests and development add their own keys
with `FUSION_OFFICIAL_KEYS`. steonmod.com checks the same signatures before it lists anything. Never commit a secret key: the publish check refuses packages that
contain one, and `.gitignore` should never be relied on for it.

## Signed packages

A package carries `signature.toml`: the signer's public key, the name they signed as, and a
signature over the sha256 of every other file (sorted `path<TAB>sha256` lines, hashed). Changing,
adding or removing any file breaks it, and Fusion then refuses to read the package ("it was changed
after it was signed"). Share signs automatically; `fusion-cli package sign FILE [--key K]` signs by
hand, and `fusion-cli package router FOLDER --out FILE` makes a signed router package.

## Tiers

| Tier | Who | May ship |
|---|---|---|
| **Official** | signed with one of Fusion's official keys | anything |
| **Verified** | signed with a key the feed lists as a verified author | anything, after review |
| **Community** | signed by anyone else | text, Lua, pictures, sounds, models: no program files |
| **Unsigned** | nobody | the same as community, with a stronger warning |

**Program files** are `.dll .exe .so .dylib .sys .com .scr .msi .bat .cmd .ps1 .vbs .jar .asi .pyd
.node .drv .ocx .cpl`. A community or unsigned package that carries one can't be installed. The
content browser shows each package's tier ("Community: signed by Ali (key bf444bffebbeb3ea)").

## The feed: verified authors and the kill switch

One TOML file, signed by an official key, published next to the content hub's index and fetched at
start and every hour. Players' Fusion keeps the newest one it has seen in
`%LOCALAPPDATA%/Fusion/feed/` (`feed.toml` + `feed.toml.sig`).

```toml
sequence = 3                     # always increases; a lower one never replaces a higher one
issued = "2026-10-04"

[[verified]]
key = "bf444bffebbeb3ea369d34cc2ed6ef21304a54b3382b0c49f8426e5bec732d96"
name = "Ali"

[[block]]
router = "vein"                  # or package = "zombie-arena"
versions = ["0.1.0"]             # empty: every version
reason = "Taken down at the publisher's request (2026-10-05)."
```

`fusion-cli feed sign feed.toml --key official.key` writes `feed.toml.sig`. A blocked router or
package can't be installed, and a scenario using a blocked router isn't playable, with the reason
on screen. Because `sequence` only goes up, an old feed can't be replayed to undo a block.

## The publish check (refuses game files)

Before a package is shared (Share, `package router`, `package check`), every file is checked:

- **Copies of game files:** compared by size, then sha256, with every file of every installed Steam
  game and every router's game on this PC (My Games), and Fusion's read-in-place cache. Files that
  Fusion's own setup put into a game's folder (a kit, a router's files) don't count. About 3 s for
  470,000 files on the developer's PC (10 s the first time, while Windows reads its folders).
- **Game data files by kind:** `.pak .ucas .utoc .uasset .uexp .umap .ubulk .bsa .ba2 .esp .esm .esl
  .assets .ress .resource .bundle .unity3d .vpk .gcf .forge .rpf .wad`.
- **Decompiled code:** decompiler names (`FUN_00401000`, `sub_140001000`, `dword_14F00A0`, ...).
- **Raw addresses** of a game build (`0x1400A3F20`, `0x180012340`, `0x7FF6A1B2C3D4`): they break on
  the next patch; routers find things by name through the kit.
- **Secrets:** private keys, Fusion signing keys, AI-service, GitHub, AWS, Google, Slack and
  Hugging Face tokens.

Any finding blocks the package, file by file, in plain words.

## Not yet

- Verified authors are vetted by hand; there's no application flow.
- Revoking an author's key (other than blocking their packages).
- The release key (see Keys).
