runtime-key.json schema mismatch: m2pack CLI output vs launcher RuntimeKey model #3

Open
opened 2026-04-15 13:00:17 +02:00 by jann · 0 comments
Member

m2pack export-runtime-key --format json and the launcher's RuntimeKey.cs disagree on the runtime-key.json schema. Nothing connects them end-to-end today because the release pipeline never used the CLI output directly — manual hand-written JSON was used in the first release.

The two schemas

m2pack export-runtime-key output (m2pack-secure/docs/launcher-contract.md):

{
  "version": 1,
  "mapping_name": "Local\\M2PackSharedKeys",
  "key_id": 1,
  "master_key_hex": "<64 hex>",
  "sign_public_key_hex": "<64 hex>"
}

Launcher RuntimeKey model (jann/metin-launcher src/Metin2Launcher/Runtime/RuntimeKey.cs):

[JsonPropertyName("key_id")]       public string KeyId { get; set; }       // STRING
[JsonPropertyName("master_key_hex")] public string MasterKeyHex { get; set; }
[JsonPropertyName("sign_pubkey_hex")] public string SignPubkeyHex { get; set; }  // PUBKEY not PUBLIC_KEY

Two mismatches

  1. key_id type: CLI emits 1 (integer), launcher expects "1" (string). System.Text.Json throws JsonException: The JSON value could not be converted to System.String. Path: $.key_id.
  2. Public key field name: CLI emits sign_public_key_hex, launcher expects sign_pubkey_hex. Silently becomes empty string on parse → validator rejects as "not 64 hex chars".

Reproduction

m2pack export-runtime-key \
  --key master.key --public-key signing.pub --key-id 1 \
  --format json --output runtime-key.json
# then run launcher against a manifest that points to this file:
# ERROR m2pack: failed to parse runtime key .../runtime-key.json
# :: System.Text.Json.JsonException: The JSON value could not be converted
# to System.String. Path: $.key_id
# -> format.OnApplied fails -> no env var delivery -> client log says
# "runtime master key with key_id=1 required for 'pack/root.m2p' (active key_id=0)"
# -> "PackInitialize: Failed to load pack/root.m2p"

Hit tonight during the 2026.04.15-m2pack-v2 release. Worked around by hand-writing runtime-key.json in the launcher-expected shape.

Fix options

Option A (preferred): m2pack emits the launcher-compatible shape (key_id stringified, sign_pubkey_hex). Bonus: drop the version / mapping_name fields from the JSON — they are Windows-shared-memory bookkeeping that env-var / CLI deliveries don't use. The binary M2KEYS1 format still uses them, that's orthogonal.

Option B: launcher RuntimeKey tolerates both shapes (JsonPropertyName with fallback alternate name, key_id accepts either int or string via a custom converter).

Both are small changes. I'll do B on the launcher side tonight (opening a follow-up commit on PR #1) so no released launcher binary ever blows up on CLI output, but A should still land on the m2pack side to make the JSON a proper contract between the two.

  • jann/metin-launcher PR #1 — will add the launcher tolerant-parse fix
  • metin-server/m2dev-client#10 — runtime-key.json pipeline integration (this issue is a sub-blocker for it)
`m2pack export-runtime-key --format json` and the launcher's `RuntimeKey.cs` disagree on the `runtime-key.json` schema. Nothing connects them end-to-end today because the release pipeline never used the CLI output directly — manual hand-written JSON was used in the first release. ## The two schemas **`m2pack export-runtime-key` output** (`m2pack-secure/docs/launcher-contract.md`): ```json { "version": 1, "mapping_name": "Local\\M2PackSharedKeys", "key_id": 1, "master_key_hex": "<64 hex>", "sign_public_key_hex": "<64 hex>" } ``` **Launcher `RuntimeKey` model** (`jann/metin-launcher` `src/Metin2Launcher/Runtime/RuntimeKey.cs`): ```csharp [JsonPropertyName("key_id")] public string KeyId { get; set; } // STRING [JsonPropertyName("master_key_hex")] public string MasterKeyHex { get; set; } [JsonPropertyName("sign_pubkey_hex")] public string SignPubkeyHex { get; set; } // PUBKEY not PUBLIC_KEY ``` ## Two mismatches 1. **`key_id` type**: CLI emits `1` (integer), launcher expects `"1"` (string). System.Text.Json throws `JsonException: The JSON value could not be converted to System.String. Path: $.key_id`. 2. **Public key field name**: CLI emits `sign_public_key_hex`, launcher expects `sign_pubkey_hex`. Silently becomes empty string on parse → validator rejects as "not 64 hex chars". ## Reproduction ```bash m2pack export-runtime-key \ --key master.key --public-key signing.pub --key-id 1 \ --format json --output runtime-key.json # then run launcher against a manifest that points to this file: # ERROR m2pack: failed to parse runtime key .../runtime-key.json # :: System.Text.Json.JsonException: The JSON value could not be converted # to System.String. Path: $.key_id # -> format.OnApplied fails -> no env var delivery -> client log says # "runtime master key with key_id=1 required for 'pack/root.m2p' (active key_id=0)" # -> "PackInitialize: Failed to load pack/root.m2p" ``` Hit tonight during the `2026.04.15-m2pack-v2` release. Worked around by hand-writing `runtime-key.json` in the launcher-expected shape. ## Fix options **Option A (preferred)**: m2pack emits the launcher-compatible shape (`key_id` stringified, `sign_pubkey_hex`). Bonus: drop the `version` / `mapping_name` fields from the JSON — they are Windows-shared-memory bookkeeping that env-var / CLI deliveries don't use. The binary `M2KEYS1` format still uses them, that's orthogonal. **Option B**: launcher `RuntimeKey` tolerates both shapes (`JsonPropertyName` with fallback alternate name, `key_id` accepts either int or string via a custom converter). Both are small changes. I'll do **B on the launcher side tonight** (opening a follow-up commit on PR #1) so no released launcher binary ever blows up on CLI output, but A should still land on the m2pack side to make the JSON a proper contract between the two. ## Related - `jann/metin-launcher` PR #1 — will add the launcher tolerant-parse fix - `metin-server/m2dev-client#10` — runtime-key.json pipeline integration (this issue is a sub-blocker for it)
Sign in to join this conversation.
No Label
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: metin-server/m2pack-secure#3