diff --git a/src/game/project.godot b/src/game/project.godot index e97ceb4e..9cad5e2a 100644 --- a/src/game/project.godot +++ b/src/game/project.godot @@ -28,6 +28,7 @@ StatsTracker="*res://engine/src/autoloads/stats_tracker.gd" TurnManager="*res://engine/src/autoloads/turn_manager.gd" ThroneRoomProfile="*res://engine/src/modules/empire/throne_room_profile.gd" SpriteManifest="*res://engine/src/autoloads/sprite_manifest.gd" +ModLoader="*res://engine/src/autoloads/mod_loader.gd" ProceduralRenderer="*res://engine/src/world/procedural_renderer.gd" ScreenCapture="*res://engine/scenes/tests/capture_screenshot.gd" AutoPlay="*res://engine/scenes/tests/auto_play.gd" diff --git a/tools/sign-mod.sh b/tools/sign-mod.sh new file mode 100755 index 00000000..44c68022 --- /dev/null +++ b/tools/sign-mod.sh @@ -0,0 +1,64 @@ +#!/usr/bin/env bash +# sign-mod.sh — produce the base64 ed25519 signature for a native AI-controller +# mod payload, ready to drop into manifest.json#/signature. +# +# Usage: +# tools/sign-mod.sh +# +# Where: +# Path to controller.so / controller.dll / controller.dylib +# PEM-encoded ed25519 private key. Generate one with: +# openssl genpkey -algorithm ed25519 -out engine.key +# and publish the matching public key: +# openssl pkey -in engine.key -pubout -out engine.pub +# +# Output: 88-char base64 string (64 raw bytes) on stdout. Paste into the +# mod's manifest.json #/signature field. +# +# Protocol (mirrors mc-mod-host/src/signing.rs): +# 1. SHA-256 the binary bytes. +# 2. Sign the 32-byte digest with the ed25519 private key. +# 3. Base64-encode the 64-byte signature. +# +# The host re-computes the digest and verifies against the engine-release +# public key embedded in ENGINE_PUBKEY (see signing.rs). Mods built +# without access to the matching private key will not load. +# +# TRACKED: the engine release pubkey constant is currently zero-bytes, +# so signatures produced here will NOT verify against the shipped +# engine until the release pipeline (Stage 6) bakes in a real key. +# See docs/modding/abi-decisions.md §"Native sandbox" for the deferral. + +set -euo pipefail + +if [[ $# -ne 2 ]]; then + echo "usage: $0 " >&2 + exit 64 +fi + +BIN="$1" +KEY="$2" + +if [[ ! -f "$BIN" ]]; then + echo "error: binary not found: $BIN" >&2 + exit 66 +fi +if [[ ! -f "$KEY" ]]; then + echo "error: private key not found: $KEY" >&2 + exit 66 +fi + +TMP_DIGEST="$(mktemp)" +TMP_SIG="$(mktemp)" +trap 'rm -f "$TMP_DIGEST" "$TMP_SIG"' EXIT + +# 1. SHA-256 the binary into raw 32 bytes. +openssl dgst -sha256 -binary "$BIN" > "$TMP_DIGEST" + +# 2. Sign the digest with the ed25519 private key. `openssl pkeyutl` with +# an ed25519 key takes the message directly (no -digest flag). +openssl pkeyutl -sign -inkey "$KEY" -rawin -in "$TMP_DIGEST" -out "$TMP_SIG" + +# 3. Base64-encode and emit on a single line. +base64 -w 0 < "$TMP_SIG" +echo