# Client integration Your current client already has a custom `PackLib` using `zstd` and `XChaCha20`. This project should become the next iteration, not a parallel dead tool. ## Suggested migration 1. Keep the current `PackManager` interface stable. 2. Add a new loader beside the current pack code, for example: - `src/PackLib/M2PackArchive.h` - `src/PackLib/M2PackArchive.cpp` 3. Route `CPackManager::AddPack()` by extension: - legacy format for old `.pack` - new format for `.m2p` 4. Embed only the signing public key in the client. 5. Resolve the content decryption key from runtime delivery: - launcher-provided memory - machine-bound cache - or a derived release secret ## Client key header For the current implementation, the client expects: - `src/PackLib/M2PackKeys.h` Generate it from the release key material with: ```bash m2pack export-client-config \ --key keys/master.key \ --public-key keys/signing.pub \ --key-id 1 \ --output /path/to/m2dev-client-src/src/PackLib/M2PackKeys.h ``` That keeps loader constants aligned with the archive builder. Important: - the generated client header no longer embeds the real master key - `.m2p` loading now requires a runtime master key - the runtime master key must match the archive `key_id` - if a `.m2p` file exists and fails validation or runtime key resolution, the client should not silently fall back to `.pck` ## Runtime validation Minimum validation: - verify header magic and version - compare manifest hash - verify manifest signature - reject duplicate paths - reject path traversal - verify AEAD tag before decompression ## Launcher key delivery The client now supports runtime key overrides and no longer has to rely only on the compiled fallback key. Supported inputs, highest priority last: 1. shared memory mapping 2. environment variables 3. command line arguments ### Command line ```text --m2pack-key-hex <64-hex-master-key> --m2pack-pubkey-hex <64-hex-public-key> --m2pack-key-map --m2pack-key-id ``` ### Environment ```text M2PACK_MASTER_KEY_HEX M2PACK_SIGN_PUBKEY_HEX M2PACK_KEY_MAP M2PACK_KEY_ID ``` ### Shared memory Default mapping name: ```text Local\M2PackSharedKeys ``` Binary layout: ```c struct M2PackSharedKeys { char magic[8]; // "M2KEYS1\0" uint32_t version; // 1 uint32_t flags; // reserved uint32_t key_id; // runtime master key slot uint8_t master_key[32]; uint8_t sign_public_key[32]; }; ``` Recommended production path: - launcher fetches or unwraps the current content key - launcher creates the shared mapping - launcher starts the client with `--m2pack-key-map Local\\M2PackSharedKeys` - client reads runtime keys during startup - client rejects `.m2p` loading if the runtime master key is missing ## Loader notes - Use memory-mapped I/O for the archive. - Keep a path-to-entry map in lowercase normalized form. - Decrypt per request, not by unpacking the full archive. - Keep a small decompression scratch buffer pool if the client reads in parallel. ## Release model - `master.key`: private content encryption key - `signing.key`: private release signing key - `signing.pub`: embedded client verifier key The signing key belongs in CI or a secured release box. The public key belongs in the client binary or in a protected launcher manifest.