Changelog

Unreleased

Changed

  • Upgrade the workspace and path-dependent examples to Soroban SDK 29.0.1 and Rust 1.91.0.

Added

  • cougr_core::accounts::AccountError::DuplicateDeviceKey - new error variant (code 45) returned when attempting to register a device key that is already active, distinguishing "device already registered" from "device limit reached"
  • cougr_core::accounts::derive_session_key_id - deterministic session-key identifier derivation, so the Rust core and the TypeScript session client agree on session identity instead of re-deriving it off-chain
  • cougr_core::cors - CORS configuration validation and dynamic origin allowlist for HTTP gateways in front of a game contract: CorsConfig validates origins, methods, header names, and credential/wildcard combinations; OriginAllowlist supports runtime add/remove of exact, single-label wildcard subdomain (https://*.example.com), and global * entries with case/default-port-normalized matching; preflight evaluation returns ready-to-emit response headers
  • cougr-cli - new workspace member publishing the cougr binary
  • cougr new <name> [--template <name>] - scaffolds a Soroban game contract crate following the canonical lib.rs / components.rs / systems.rs layout, with a passing test::GameHarness suite and a dependency on the published cougr-core release rather than a path dependency
  • Four embedded templates, each derived from a canonical example and compiled into the binary so cougr new works offline: starter (spawn_and_move), turn-based (tic_tac_toe), hidden-info (hidden_hand), session-auth (session_arena)
  • CLI CI workflow - validates cougr-cli once, caches the root workspace target, and compiles generated projects when template sources change

Fixed

  • zk::merkle::proof::verify_inclusion - a proof's leaf_index was never checked against the position its path_bits actually walk, so a proof for one leaf could be relabelled to claim another leaf's position and still verify. verify_inclusion now rejects a path_bits/leaf_index mismatch (ZKError::LeafIndexMismatch), an out-of-range leaf_index (ZKError::LeafOutOfBounds), and depth > MAX_DEPTH (ZKError::MaxDepthExceeded, previously an overflow panic on path_bits >> i for depth > 32) before hashing. zk::merkle::tree::verify_proof, the in-memory equivalent, gets the same path_indices/leaf_index check
  • zk::merkle::proof::verify_inclusion_at_depth - new function that additionally pins the proof to an exact expected depth, so a shorter-than-expected proof (including a degenerate depth = 0 proof with leaf == root) is rejected even though it would otherwise be internally consistent
  • examples/battleship, examples/treasure_hunt - both pin the expected proof depth and recheck path_bits against the claimed cell locally, since they still depend on the published cougr-core = "1.1.0" and won't pick up the core fix until a release

1.1.0

Added

  • game::SorobanGame trait - standard load_world / save_world contract pattern; implement once with impl_soroban_game!(Contract, "key"), use in every entrypoint
  • impl_soroban_game! macro - wires SorobanGame to any #[contract] struct
  • SimpleWorld::load_from_instance - load world from Soroban instance storage, returning a fresh empty world on first call
  • SimpleWorld::save_to_instance - persist world to Soroban instance storage
  • SimpleWorld::set_rich_observed - store a rich component and emit a RichComponentChangedEvent for off-chain indexers
  • SimpleWorld::remove_rich_observed - remove a rich component and emit a del event
  • RichComponentChangedEvent - new Soroban event type with topics ("COUGR", "rich", component_type) for rich component change notifications
  • spawn_and_move example - canonical Cougr starter game demonstrating the complete idiomatic pattern: impl_component_observed! + SorobanGame + typed ECS access
  • SorobanGame re-exported from prelude - import from cougr_core::prelude::*
  • cougr_core::circuits - four pre-built ZK game builders (hidden cards, fog of war, fair dice, sealed bid) with pipeline-embedded verification keys
  • cougr_core::session - SessionManager, SessionStatus, and ActiveSession (Beta)
  • cougr_core::test - GameHarness, Scenario, and ReplayLog sandbox behind the testutils feature
  • Circom pipeline - internal/cougr-core-circuits with CI workflow and on-chain Groth16 proof verification using real VKs
  • ZK examples - hidden_hand, fog_explorer, dice_duel, and blind_auction
  • Workspace subcrates - internal/cougr-core-{circuits,session,test} per ADR 0007

Changed

  • tic_tac_toe example modernised: replaced ~200 lines of manual serialization with impl_rich_component! for Board and Players, and impl_soroban_game! for load/save. Public API is unchanged; all existing tests pass
  • README rewritten with clean 30-line quick start and full feature documentation
  • canonical example set expanded from three (snake, battleship, guild_arena) to ten: spawn_and_move (Starter), tic_tac_toe (Rich components), session_arena (Session UX), hidden_hand, fog_explorer, dice_duel, blind_auction (ZK circuits), snake (Arcade/GameApp), battleship (Hidden information), guild_arena (Auth & recovery)
  • session_arena example added as canonical reference for session::SessionManager

Stability Notes

  • game::SorobanGame is Stable
  • SimpleWorld::load_from_instance / save_to_instance are Stable
  • set_rich_observed / remove_rich_observed are Stable
  • RichComponentChangedEvent is Stable
  • cougr_core::session is Beta
  • cougr_core::circuits and embedded test VKs are Experimental
  • cougr_core::test is Experimental (testutils only)

1.0.0

Added

  • app as the default gameplay runtime surface
  • auth, privacy, and ops as product-level domain namespaces
  • RuntimeWorld and RuntimeWorldMut as shared Soroban-first backend contracts
  • stronger stage scheduling with ordering, sets, and validation
  • SimpleQueryBuilder, query state/cache improvements, and richer ArchetypeWorld query helpers
  • expanded benchmark coverage for backend comparisons and cache invalidation behavior

Changed

  • the recommended onboarding path is now app::GameApp + SimpleWorld + SimpleQueryBuilder
  • canonical examples now emphasize the curated runtime story and explicit maturity boundaries
  • battleship now uses stable privacy primitives from zk::stable
  • documentation now treats SimpleWorld and ArchetypeWorld as the defended Soroban-first backends

Stability Notes

  • Stable: ECS onboarding/runtime contract, app, ops, standards, privacy::stable, zk::stable
  • Beta: auth, accounts, game_world
  • Experimental: privacy::experimental, zk::experimental, hazmat cryptographic helpers

Upgrade Notes

  • Prefer app over wiring scheduler/world primitives directly for new gameplay code
  • If you still have pre-1.0 code built around removed runtime abstractions, port directly to GameApp, SimpleWorld, and SimpleQuery
  • Prefer ops, privacy, and auth in application code when you want domain-oriented imports
  • Treat root-level advanced re-exports as compatibility/advanced surfaces rather than the default learning path
  • See docs/MIGRATION_GUIDE.md for concrete migration mappings