# Changelog

All notable changes to `metin-launcher` are tracked here. Format loosely
follows Keep a Changelog; dates are Europe/Prague.

## [Unreleased]

### Added
- Release format dispatch. The manifest now carries an optional top-level
  `format` field (defaults to `legacy-json-blob`) and the orchestrator
  resolves an `IReleaseFormat` strategy via `ReleaseFormatFactory`.
- `M2PackFormat`: new release format that lists `.m2p` pack archives plus a
  `runtime-key.json` sidecar. The launcher never opens or decrypts `.m2p`
  archives; it only places them next to the client root and loads the
  runtime key after apply.
- `RuntimeKey` model + `IRuntimeKeyDelivery` strategy. `EnvVarKeyDelivery`
  is the MVP implementation and forwards `M2PACK_MASTER_KEY_HEX`,
  `M2PACK_SIGN_PUBKEY_HEX` and `M2PACK_KEY_ID` to the child process scoped
  to `ProcessStartInfo.Environment` only. `SharedMemoryKeyDelivery` is
  documented as a stub and throws until the Windows receiver lands.
- `GameProcess.BuildStartInfo` now accepts an optional `RuntimeKey?` and
  forwards it through the env-var delivery.
- `ClientAppliedReporter`: opt-in best-effort telemetry ping that fires
  once after a successful apply with a 5-second cap. Disabled by default
  (`LauncherConfig.TelemetryUrlTemplate == ""`). Failures are always
  swallowed and logged as warnings.
- `docs/m2pack-integration.md` documenting the signature boundary, runtime
  key delivery, telemetry, backward compatibility and file layout.
- ~60 new tests across `RuntimeKeyTests`, `EnvVarDeliveryTests`,
  `LegacyJsonBlobFormatTests`, `M2PackFormatTests`, `ReleaseFormatFactoryTests`,
  `ClientAppliedReporterTests`, `UpdateOrchestratorFormatDispatchTests` and
  extended `GameProcessTests`. Total suite is ~92 tests.

### Changed
- `UpdateOrchestrator` dispatches through `ReleaseFormatFactory` after
  signature verification. The legacy flow is preserved byte-for-byte for
  manifests without a `format` field; the only visible difference is that
  the complete log line now reads `format=legacy-json-blob`.
- `UpdateOrchestrator.Result` gained `Format` and `RuntimeKey` slots so the
  headless entry point can forward the runtime key into `GameProcess.Launch`.

### Security
- A signed manifest carrying an unknown `format` value is refused outright
  rather than silently falling back to legacy, preventing a downgrade
  attack vector in the event of a signing key compromise.
- Env vars produced by `EnvVarKeyDelivery` are scoped to the spawned
  child's environment only. The launcher never mutates its own process
  environment, so other processes on the machine and later code in the
  launcher itself cannot read the key.
