Welcome to Cougr
Cougr is an on-chain game engine built for the Stellar network and Soroban smart contracts. It provides a full Entity-Component-System (ECS) runtime alongside account abstraction and zero-knowledge primitives in a single crate.
This documentation site is generated automatically from the salazarsebas/Cougr repository.
Start
Welcome to the Start section. If you're new to Cougr, this is the right place to begin.
- Getting Started — install the toolchain and run your first test in under two minutes.
- Build Your First Game — a step-by-step walkthrough from an empty directory to a deployed game on Stellar Testnet.
Getting Started
This page is synced from the main Cougr repository. To edit it, open a PR against
salazarsebas/Cougr.
Prerequisites
Before you can build a Cougr game, you need the following tools installed:
| Tool | Install command |
|---|---|
| Rust | `curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs |
| Stellar CLI | cargo install stellar-cli --features opt |
| wasm32 target | rustup target add wasm32-unknown-unknown |
Clone and run the starter example
git clone https://github.com/salazarsebas/Cougr
cd Cougr/examples/spawn_and_move
cargo test
All tests should pass within two minutes on a machine that has Rust installed.
Next step
Once the tests pass, head over to Build Your First Game for the full sequential tutorial.
Build Your First Game
⏳ This page is being written. It will be synced automatically from
docs/start/build-your-first-game.mdin the main Cougr repository once merged.Tracked in:
salazarsebas/Cougr— Stage 3 Tutorial issue
What you'll build
A fully working "Spawn and Move" game — players enter a shared world, get assigned an entity ID, and can walk in four directions. At the end you'll deploy it to Stellar Testnet.
Time to complete: ~30 minutes
Prerequisites: Getting Started steps complete.
Check back soon — or watch the repository to be notified when this page goes live.
Learn
The Learn section takes you from a working first game to understanding the design decisions that make Cougr work the way it does.
| Guide | Status |
|---|---|
| Architecture | ✅ Available |
| Game Patterns | ✅ Available |
| On-Chain / Off-Chain Boundary Guide | 🔜 Coming soon |
| Smart Contract Patterns | 🔜 Coming soon |
| Testing Guide | 🔜 Coming soon |
| Deployment Guide | 🔜 Coming soon |
Architecture
High-level overview of how Cougr is organized. For usage, see README.md.
Layers
┌──────────────────────────────────────────────────────────────┐
│ game::SorobanGame (contract integration) │ Contract layer
├──────────────────────────────────────────────────────────────┤
│ app::GameApp │ Default runtime surface
├───────────┬───────────────┬──────────────────────────────────┤
│ ECS │ Accounts │ Standards │ ZK Proofs │
├───────────┴───────────────┴─────────────────┴────────────────┤
│ soroban-sdk 25.1.0 (no_std, WASM) │
└──────────────────────────────────────────────────────────────┘
game::SorobanGame (src/game.rs) bridges the ECS and Soroban contract models.
The SorobanGame trait provides load_world and save_world as default methods,
eliminating repetitive storage-key boilerplate from contract entrypoints. Wire up
once with impl_soroban_game!(MyContract, "key").
The companion helpers SimpleWorld::load_from_instance and save_to_instance
are the underlying primitives when you want finer control.
GameApp (src/plugin/mod.rs) is the default onboarding layer for complex
games. It owns a SimpleWorld, the scheduler, plugin registration, and runtime
resources in one place.
ECS
Two storage backends, same ComponentTrait interface:
| Backend | File | Strategy | Best for |
|---|---|---|---|
| SimpleWorld | src/simple_world/ | Map<(EntityId, Symbol), Bytes> with dual Table/Sparse indexes | General use, small entity counts |
| ArchetypeWorld | src/archetype_world/ | Groups entities by component signature | Large entity counts, batch queries |
Both support typed access (get_typed<T>, set_typed<T>) and raw access (get_component, add_component).
Supporting systems:
- Query cache (
src/query/) — version-tagged, invalidates on world mutation - Hooks (
src/hooks.rs) — callbacks on component add/remove - Observers (
src/observers.rs) — event-driven reactions - Commands (
src/commands.rs) — deferred mutations during system execution - Scheduler (
src/scheduler/) — stage-based, dependency-aware system ordering - Change tracker (
src/change_tracker.rs) — per-component dirty flags - Plugins (
src/plugin/) — modular game logic bundles - Incremental storage (
src/incremental/) — only persist dirty entities
Component definition
Three macros cover every component case:
| Macro | When to use |
|---|---|
impl_component! | Fixed-size primitives (i32, u32, u64, u128, u8, bool, bytes32) |
impl_component_observed! | Same as above, plus structured Soroban events on every set |
impl_rich_component! | Complex types via XDR codec: Address, Vec, String, Option, nested structs |
impl_rich_component! requires #[contracttype] on the struct. The XDR serialisation is handled entirely by the Soroban SDK — no manual serialize/deserialize implementation is needed.
Rich components are stored in Soroban instance storage (not the ECS Map) but share the same entity ID space.
ZK Proofs (src/zk/)
All ZK operations use Stellar Protocol 25 (X-Ray) host functions — the heavy crypto runs on the host, not in WASM.
- Groth16 (
groth16.rs) — proof verification via BN254 pairing - BLS12-381 (
bls12_381.rs) — G1 add/mul/MSM, pairing checks - Poseidon2 (
crypto.rs) — ZK-friendly hashing, behindhazmat-cryptofeature - Merkle trees (
merkle/) — SHA256 and Poseidon variants, sparse trees, on-chain proofs - Pedersen (
commitment.rs) — commitment scheme for hidden state - Game circuits (
circuits.rs,traits.rs) —GameCircuittrait + pre-built circuits (Movement, Combat, Inventory, TurnSequence) +CustomCircuitBuilder - ECS integration (
components.rs,systems.rs) —CommitReveal,HiddenState,ProofSubmissioncomponents with verification systems
Accounts (src/accounts/)
Account abstraction layer with pluggable implementations:
CougrAccount (trait)
├── ClassicAccount — standard Stellar keypair
└── ContractAccount — smart contract wallet
├── SessionStorage — persistent session keys
├── RecoveryStorage — guardian-based recovery
├── DeviceStorage — multi-device key management
└── Secp256r1Storage — WebAuthn/Passkey keys
Key traits: CougrAccount, SessionKeyProvider, RecoveryProvider, MultiDeviceProvider.
SessionBuilder provides a fluent API for constructing scoped session keys. authorize_with_fallback handles graceful degradation from session keys to direct authorization. See ADR 0005.
Standards (src/standards/)
Reusable contract standards for integrations that need explicit operational controls:
OwnableandOwnable2Stepfor owner-managed authorityAccessControlfor role-based authorization with delegated adminsPausablefor emergency stopsExecutionGuardfor serialized critical sectionsRecoveryGuardfor blocking sensitive paths during recovery windowsBatchExecutorfor bounded multi-operation flowsDelayedExecutionPolicyfor time-delayed operation queues
Each standard instance is keyed by a caller-supplied Symbol, which keeps storage deterministic and avoids collisions when a contract composes multiple modules.
Competitive Layers (workspace subcrates)
Three layers ship inside the single cougr-core crate. Implementation lives in
src/{circuits,session,test}/; internal/cougr-core-* workspace members use
stubs for isolated cargo check -p runs.
| Public module | Source | Maturity | Feature |
|---|---|---|---|
cougr_core::circuits | src/circuits/ | Experimental | always |
cougr_core::session | src/session/ | Beta | always |
cougr_core::test | src/test/ | Beta | testutils |
Circuit builders: hidden_cards, fog_of_war, fair_dice, sealed_bid →
GameCircuitSpec. Examples: hidden_hand, fog_explorer, dice_duel,
blind_auction. See ADR 0006.
The test sandbox uses no_std + alloc with Soroban testutils — not std.
Enable with cougr-core feature testutils. Modules: GameHarness, Scenario,
WorldFixture, ReplayLog, SnapshotAssert. See ADR 0004 and ADR 0007.
Feature Flags
| Flag | Enables |
|---|---|
hazmat-crypto | Poseidon2 hash, BN254 curve ops (via soroban-sdk/hazmat-crypto) |
testutils | cougr_core::test sandbox, MockAccount, Soroban test helpers |
debug | Runtime introspection, metrics, state snapshots (src/debug/) |
Build
Release builds are configured with LTO, opt-level = "z", and overflow-checks = true to keep artifacts optimized for constrained execution environments.
Primary target: wasm32v1-none.
Cougr Patterns
Purpose
This document captures the recommended architectural patterns for new Soroban game contracts built on Cougr.
The goal is to standardize how teams structure worlds, systems, stages, and storage choices instead of relying on ad-hoc example interpretation.
Find a pattern by problem
Start here if you know what you're trying to build but not which Cougr module answers it. Each row links to the module-level doc for full detail, and to a concrete, current example that demonstrates it.
| I want... | Use | Example | Read more |
|---|---|---|---|
| Fairness (a roll, a draw, an outcome no one can predict or bias) | circuits::FairDiceBuilder — on-chain Groth16-verified randomness (Experimental) | dice_duel | Hidden Information Guidance below, PRIVACY_MODEL.md |
| Hidden information (cards, ship positions, sealed bids — state some players shouldn't see) | privacy::stable commit-reveal + Merkle primitives | battleship (canonical), rock_paper_scissors, hidden_hand, blind_auction | Hidden Information Guidance below, PRIVACY_MODEL.md |
| To gate an action behind a role (admin-only, minter-only, etc.) | AccessControl — role-based authorization with per-role admin delegation | — | STANDARDS_LAYER.md § AccessControl |
| Off-chain-friendly real-time movement (clients track state without polling) | impl_component_observed! — emits a (COUGR, set, <component>) event on every change | spawn_and_move (start here), snake | System Design and Query Guidance below, docs/ECS_CORE.md |
| A passwordless sign-in (Face ID / Touch ID instead of a seed phrase) | secp256r1 passkey signer, composed through AccountKernel | guild_arena | ACCOUNT_KERNEL.md § Signers |
| A session players approve once, not per-transaction | Session signer + SessionPolicy (scope, expiry, operation budget) | session_arena | ACCOUNT_KERNEL.md § Session Model |
| Account recovery if a device is lost | GuardianPolicy + ActiveDevicePolicy | guild_arena | ACCOUNT_KERNEL.md § Policies |
| An emergency stop / pause switch | Pausable | — | STANDARDS_LAYER.md § Pausable |
| To serialize mutations / guard against reentrancy-like issues | ExecutionGuard | — | STANDARDS_LAYER.md § ExecutionGuard |
| Delayed or timelocked execution | DelayedExecutionPolicy | — | STANDARDS_LAYER.md § DelayedExecutionPolicy |
| To batch several operations safely | BatchExecutor | — | STANDARDS_LAYER.md § BatchExecutor |
| To know whether I even need ECS | Direct contract model for small/config-driven contracts | — | When Not To Use ECS below |
| To pick table vs. sparse storage | Table for hot-loop state, sparse for infrequent markers | — | Storage Guidance below |
| A thin, explicit contract entrypoint / gameplay loop | GameApp + explicit stage placement | spawn_and_move, snake | Default Entry Point and Stage Layout below |
Everything below this point is the module-level architectural guidance the table above links into — organized by Cougr's internal structure rather than by problem, for readers who already know which area they're working in.
Default Entry Point
Use GameApp as the default runtime entrypoint.
Recommended shape:
- build the app
- register plugins and startup systems
- register tick systems into explicit stages, preferably with
named_system(...)/named_context_system(...) - run one schedule tick per contract invocation that advances gameplay
This keeps the "contract entrypoint" thin and the gameplay loop explicit.
Stage Layout
Cougr's recommended schedule is:
Startup: one-time entity/resource setupPreUpdate: input decoding, action validation, turn preparationUpdate: core gameplay state transitionsPostUpdate: scoring, derived-state maintenance, indexing side effectsCleanup: despawns, expiry handling, transient marker removal
Do not use cross-stage before / after dependencies. Stage order is already the primary contract between phases.
System Design
Prefer small systems with one responsibility:
- validation systems should reject or mark invalid intent
- update systems should apply game-state transitions
- cleanup systems should remove expired markers or entities
Use context-aware systems when you need deferred structural changes:
- queue spawns during iteration
- queue despawns after collision passes
- queue marker additions that should apply after the current scan
Use plain world/env systems when the system only needs direct mutation and no command buffering.
Query Guidance
Prefer SimpleQueryBuilder for gameplay queries that need:
- multiple required components
- negative filters
- sparse-component inclusion
- "any-of" matching
Guidelines:
- default to table-only queries for tight loops
- opt into sparse inclusion only when marker/tag data must participate
- choose required components carefully so the scheduler can use the narrowest candidate set
Hidden Information Guidance
For hidden-state or commit-reveal contracts:
- keep the contract entrypoints thin and verification-oriented
- use
privacy::stableMerkle and commit-reveal primitives instead of example-local crypto formats - treat proof verification as a boundary concern, not as something every gameplay system needs to understand
- keep public derived state separate from private commitments and Merkle roots
battleship is the canonical reference for this pattern.
Storage Guidance
Use table storage for:
- frequently scanned gameplay state
- canonical state that participates in core loops
- components used by
Updatesystems on most ticks
Use sparse storage for:
- infrequent markers
- administrative tags
- components mostly accessed by targeted lookups instead of broad scans
If a component becomes part of the hot loop, move it to table storage instead of compensating with more complex query logic.
Recommended Separation
Keep modules separated by concern:
- ECS/gameplay core
- account/auth flows
- privacy/ZK
- standards/operational controls
Do not let auth or ZK concerns leak into every system by default. Compose them at the boundaries where they are needed.
When Not To Use ECS
Do not force ECS into contracts that are:
- tiny and single-entity
- mostly configuration/state-machine driven
- dominated by one-off administrative flows
If the problem is closer to a fixed state machine than a world simulation, a direct contract model may be simpler and cheaper.
On-Chain / Off-Chain Boundary Guide
⏳ This page is being written.
Named as the second-highest-priority missing document in
docs/strategy/08-ux-strategy.mdanddocs/strategy/12-documentation-architecture.md.Tracked in:
salazarsebas/Cougrissues
What this guide will cover
Developers coming from traditional game development or web backends often hit the same wall: what logic actually needs to be on-chain, and what doesn't? Getting this wrong is expensive — literally, in gas fees.
This guide will answer:
- Which game state must live in Soroban contract storage vs. what can stay off-chain
- How Cougr's observed components (
impl_component_observed!) bridge the gap with real-time events - Patterns for off-chain movement with on-chain settlement
- Resource cost intuition: what makes a transaction cheap vs. expensive
Check back soon — or watch the repository to be notified when this page goes live.
Smart Contract Patterns
⏳ This page is being written.
Will consolidate Soroban-specific patterns from
PATTERNS.mdandSTANDARDS_LAYER.mdinto one place, distinguishing "Cougr patterns" from "general Soroban patterns."Tracked in:
salazarsebas/Cougrissues
What this guide will cover
- Access control with
AccessControlandOwnable - Emergency stop patterns with
Pausable - Time-delayed operations with
DelayedExecutionPolicy - Batch operations with
BatchExecutor - How these standards compose with the ECS world
Check back soon — or watch the repository.
Testing Guide
⏳ This page is being written.
GameHarness,Scenario, andSnapshotAssertexist in the codebase and are used across thousands of lines of tests, but have no standalone guide yet. Named explicitly indocs/strategy/08-ux-strategy.mdStage 5.Tracked in:
salazarsebas/Cougrissues
What this guide will cover
- Setting up
GameHarnessfor unit tests - Writing
Scenario-based integration tests - Using
SnapshotAssertto lock in expected world state - How the Soroban test sandbox works (and how it differs from running
cargo testfor a normal library) - Estimating resource costs before you deploy
Check back soon — or watch the repository.
Deployment Guide
⏳ This page is being written.
The README has dev commands, but there's no standalone guide walking through production deployment to Stellar Testnet and Mainnet.
Tracked in:
salazarsebas/Cougrissues
What this guide will cover
- Configuring the Stellar CLI for Testnet and Mainnet
- Building a release
.wasmbinary with the correct flags (LTO,opt-level = "z") - Deploying with
stellar contract deploy - Understanding what a deployment costs (resource fees)
- Upgrading a contract after deploy
Check back soon — or watch the repository.
Reference
The Reference section contains low-level documentation for Cougr's modules, the API surface, and architectural decision records.
| Document | Description |
|---|---|
| ECS Core | The core ECS primitives: Entity, Component, Query, System, Scheduler |
| Account Kernel | Account abstraction layer — session keys, recovery, passkeys |
| Standards Layer | Reusable contract standards: AccessControl, Pausable, Ownable, etc. |
| Privacy Model | ZK proofs, Pedersen commitments, hidden state |
| Feature Flags | hazmat-crypto, testutils, debug — what each enables |
| Performance Guide | Resource cost intuition, benchmarks, optimization patterns |
| API Contract | Public API guarantees and stability promises |
| Compatibility Promises | What Cougr will and won't break between releases |
| Migration Guide | How to update your game for new cougr-core versions |
| CLI Reference | 🔜 Ships with the CLI |
| Client SDK Reference | 🔜 Ships with the TypeScript SDK |
| ADRs | Architecture Decision Records |
Cougr ECS Core
Purpose
This document defines the defended conceptual model for Cougr's ECS runtime.
It is the answer to "what are the actual core primitives?" and "which path is the one new users should learn first?"
Core Model
The stable conceptual model is:
Entity: an opaque runtime identityComponent: typed or raw data attached to entitiesQuery: a declarative selection over entities by component presenceSystem: logic that reads or mutates the worldCommandQueue: deferred structural mutationsGameApp: app-level orchestration over world + scheduler + pluginsRuntimeWorld/RuntimeWorldMut: the shared backend contract for Soroban-first worlds
For Soroban gameplay contracts, the recommended path is:
appSimpleWorldSimpleQuerySimpleSchedulerGameApp
ArchetypeWorld is the alternate backend for heavier query workloads.
The shared stable overlap between those backends lives in:
ecs::RuntimeWorldecs::RuntimeWorldMut
Backend Roles
SimpleWorld
Use when:
- entity counts are modest
- table-backed scans dominate
- operational simplicity matters more than archetype migration costs
Cost profile:
- cheap add/remove/update
- indexed table and all-storage component lookups
- predictable query path for common gameplay loops
ArchetypeWorld
Use when:
- multi-component queries dominate
- entity composition is relatively stable
- migration cost is acceptable in exchange for tighter query scopes
Cost profile:
- more expensive structural changes
- more selective scans for multi-component queries
Learnability Rule
A new user should be able to learn the main Cougr runtime from:
README.mdGameAppSimpleWorldSimpleQueryBuilder- one or two canonical examples
If a concept requires diving outside the Soroban-first runtime path to understand basic gameplay flow, that is a product bug.
Account Kernel
Purpose
The goal is to make authorization explicit, modular, and replay-safe while keeping the accounts namespace outside Cougr's frozen 1.0 stable contract.
Core Model
The account subsystem is now organized around:
AccountKernel- the orchestrator that runs signer verification, policy checks, and replay protection
- signer interfaces
AccountSigner- base implementations: direct owner auth, session auth, secp256r1 passkey auth
- policy interfaces
- generic
Policy<C> - base implementations for intent expiry, session enforcement, active device checks, and guardian checks
- generic
- signed intent schema
SignedIntent,SignerRef,IntentProof
- structured auth results
AuthResult,AuthMethod
Signed Intent Schema
SignedIntent binds:
- target account
- signer reference
- action payload
- nonce
- expiry
- deterministic
action_hash - proof material
The deterministic hash is derived from:
- nonce
- expiry
- signer identity fields
- action system name
- action bytes
Replay Protection
Cougr uses two replay domains:
- per-account nonce tracking for direct owner auth and passkey auth
- per-session nonce tracking for session intents
The replay implementation lives in:
Session Model
Session state now includes:
- unique
key_id - scoped allowed actions
- operation budget
- expiration timestamp
next_nonce
Session enforcement requires all of:
- session exists
- action is in scope
- session is not expired
- operation budget remains
- intent nonce matches
next_nonce
On success the session consumes one operation and advances next_nonce.
Signers
Current base signer implementations:
- direct owner signer
- uses
require_auth
- uses
- session signer
- explicit non-fallback session path evaluated by the kernel
- secp256r1 passkey signer
- verifies signatures against registered passkeys
Policies
The policy layer is intentionally reusable across account features.
Current base policies:
IntentExpiryPolicySessionPolicyActiveDevicePolicyGuardianPolicy
This is how device and recovery support now live under the same policy model instead of ad hoc checks.
Auth Results
AuthResult returns structured information instead of only Result<(), AccountError>.
Current fields:
- method used
- nonce consumed
- session key id, when applicable
- remaining operations, when applicable
Integration Note
The account kernel is now consumed through the curated accounts / auth
surface directly.
The previous GameWorld wrapper was removed so 1.0.0 does not freeze an
extra orchestration layer. Authorization should be composed explicitly at the
application layer around GameApp, SimpleWorld, and the account primitives.
Standards Layer
Purpose
The standards layer introduces reusable, storage-aware contract primitives in the style of OpenZeppelin building blocks, but shaped for Cougr's Soroban-oriented single-crate model.
These modules are meant to be composed into application contracts and account flows without depending on any example project.
Included Standards
Ownable
- single-owner access primitive
- explicit initialization
- direct transfer and renounce flows
- typed ownership transition events
Ownable2Step
- staged ownership handoff
- pending-owner tracking in storage
- explicit acceptance requirement before ownership changes
- cancellation support for abandoned handoffs
AccessControl
- role-based authorization keyed by
Symbol - per-role admin delegation
- explicit grant, revoke, and renounce semantics
- default admin role for bootstrapping new modules
Pausable
- storage-backed emergency stop flag
- explicit paused and unpaused transitions
- guard methods for mutating entrypoints
ExecutionGuard
- storage-backed execution lock
- suited for reentrancy-like protection and mutation serialization
- can be used as explicit enter/exit calls or as a scoped closure wrapper
RecoveryGuard
- blocks sensitive flows while a recovery window is active
- generic enough to compose with account recovery or application-defined incident response
BatchExecutor
- reusable batch length validation
- single-path execution semantics for collections of operations
- explicit empty and oversize rejection
DelayedExecutionPolicy
- storage-backed delayed operation queue
- deterministic operation IDs
- readiness and expiry checks
- cancellation and execution events
Storage and Namespacing
Each standards module is instantiated with a Symbol identifier.
That identifier becomes part of the storage key, which allows a single contract to host multiple independent instances of the same standard without collisions.
Authorization Model
These modules do not assume hidden caller semantics.
Where authorization matters:
OwnableandOwnable2Steprequire an explicit caller addressAccessControlchecks the caller against the relevant admin rolePausable,RecoveryGuard, and similar state machines leave the surrounding authorization decision to the integrating contract
This is intentional. Cougr keeps authorization visible at the integration boundary instead of burying it in generic helpers.
Error Semantics
The standards layer uses StandardsError for consistent negative-path behavior across integrations.
Important failure modes include:
- unauthorized caller
- duplicate initialization
- missing or mismatched pending owner
- duplicate role grant or missing role during revoke
- paused versus not-paused guard failures
- execution lock contention
- recovery-active guard failure
- empty or oversized batches
- delayed operation not ready, expired, already executed, or missing
Maturity
Status: Stable
The standards layer is part of Cougr's frozen 1.0 stable contract. Integrators should still supply their own caller-auth composition where required, but the module interfaces and documented failure semantics are now part of the defended public surface.
Cougr Privacy Model
Purpose
This document defines Cougr's privacy and proof-verification contract after the 1.0 release gate.
Its job is to separate the stable privacy subset from experimental proof systems so that the repository can make a smaller, stronger claim about what is safe to depend on in the stable contract.
Stable Privacy Surface
The stable privacy subset in Cougr is:
- commitments
- commit-reveal flows
- hidden-state encoding interfaces
- Merkle inclusion verification
- sparse Merkle utilities
- privacy interfaces:
CommitmentSchemeMerkleProofVerifierHiddenStateCodecProofVerifieras an interface contract only
These are exposed through:
cougr_core::privacy::stablecougr_core::zk::stableas the compatibility alias
Experimental Privacy Surface
The following remain Experimental:
- Groth16 proof verification flows
- proof-submission execution helpers
- prebuilt verification circuits
- fog-of-war Merkle exploration orchestration
- multiplayer ZK state-channel transition contracts
- recursive proof-composition descriptors
- advanced hidden-state automation
- hazmat Poseidon-based privacy helpers
- broader confidential-state abstractions
These are exposed through:
cougr_core::privacy::experimentalcougr_core::zk::experimentalas the compatibility alias
Compatibility note:
Experimental modules may still be re-exported from cougr_core::zk for transition
convenience, but they are not part of Cougr's stable privacy promise. New application
code should prefer cougr_core::privacy::experimental so the product-level intent is
obvious at the import site.
1.0 Privacy Freeze
The frozen 1.0 privacy contract is exactly:
- commitments
- commit-reveal flows
- hidden-state codec interfaces
- Merkle inclusion verification
- sparse Merkle utilities
- the interface contracts re-exported from
cougr_core::privacy::stable
The following are explicitly excluded from the 1.0 stable privacy contract:
zk::experimental- proof-submission orchestration that depends on experimental verification
- Groth16 verifier implementations
- prebuilt advanced circuit helpers
- state-channel, recursive, and fog-of-war orchestration helpers
Privacy Maturity Table
| Surface | Status | Notes |
|---|---|---|
| Commitments | Stable | Explicit interface and verification contract |
| Commit-reveal | Stable | Explicit component semantics and deadline behavior |
| Hidden-state encoding | Stable | Stable codec interface; fixed-width codecs can be defended |
| Merkle inclusion and sparse Merkle utilities | Stable | Malformed proof behavior and inclusion semantics are explicit |
| Proof submission systems | Beta | Useful orchestration, but still coupled to experimental verification flows |
| Groth16 verification and prebuilt circuits | Experimental | Assumptions are explicit, but not yet strong enough for a stable promise |
Proof Verification Contract
Cougr's experimental Groth16 verifier makes these explicit guarantees:
- verification keys must satisfy
vk.ic.len() == public_inputs.len() + 1 - malformed verification-key shape returns
ZKError::InvalidVerificationKey - malformed pairing inputs return
ZKError::InvalidInput - a well-formed but invalid proof returns
Ok(false)only when the pairing check fails
Cougr does not currently claim stronger guarantees for Groth16 around:
- subgroup validation beyond Soroban host-type decoding
- normalization guarantees beyond fixed-width typed wrappers
- broader proof-system maturity for production confidentiality claims
That is why the implementation remains Experimental even though the verifier interface is explicit.
Merkle Verification Contract
Cougr's stable Merkle verification guarantees:
- malformed proofs with
siblings.len() != depthreturnZKError::InvalidProofLength - well-formed but non-matching proofs return
Ok(false) - sparse Merkle utilities produce the same on-chain proof representation used by the stable SHA256 verifier
Hidden-State Encoding Contract
Stable hidden-state codecs must:
- define an exact byte-level representation
- reject malformed encoded state with
ZKError::InvalidInput - avoid silent truncation or padding
The built-in Bytes32HiddenStateCodec satisfies this by requiring an exact
32-byte payload in both directions.
Relationship to Public Surface
This model works with:
Any future claim that advanced proof verification is Stable should add stronger input-validation guarantees, clearer host-assumption boundaries, and tighter negative-path coverage than exists today.
Cougr Feature Flags
Purpose
This document groups Cougr feature flags by maturity and intended usage.
Current Flags
| Flag | Maturity | Intended use | Notes |
|---|---|---|---|
debug | Support-only | Local diagnostics and introspection | Exposes runtime snapshots and metrics that are not part of the stable product contract |
hazmat-crypto | Experimental | Advanced ZK and cryptographic integrations | Enables low-level host crypto helpers; do not treat as part of the stable privacy promise |
testutils | Non-contract support surface | Tests and explicit test-utility consumers | Enables testing helpers such as MockAccount |
Policy
- feature flags do not automatically promote a surface into the stable contract
- test-only or support-only flags remain outside compatibility guarantees
- new security-sensitive flags should default to Beta or Experimental until their contracts are written down
Relationship To Public Surface
The maturity of the feature flag should be interpreted together with:
In the product-level facade:
authmirrors the Betaaccountssurfaceprivacy::stableandprivacy::experimentalmirror the split insidezkopsmirrors the stablestandardssurface
Cougr Performance Guide
Purpose
This document explains the current performance model for Cougr's Soroban-first ECS path.
It is not a promise of fixed gas costs. It is a guide to the data structures and tradeoffs that determine query and scheduling behavior.
The practical question it should answer is:
- which backend should I use
- where should a component live
- what kinds of mutations are cheap versus expensive
SimpleWorld Query Model
SimpleWorld now maintains direct component indexes:
table_indexfor table-backed componentsall_indexfor table + sparse lookups
That changes the expected behavior of the common query paths:
get_table_entities_with_component()uses the direct table indexget_all_entities_with_component()uses the all-storage indexSimpleQueryselects the narrowest available required component index before filtering
This is the default performance story for gameplay loops.
Use SimpleWorld by default when:
- your hot loop is dominated by one- or two-component scans
- you mutate entity composition often
- you rely on table vs sparse placement to control scan scope
Use ArchetypeWorld when:
- your hot loop is dominated by repeated multi-component queries
- entity compositions are relatively stable after setup
- you are willing to pay more for add/remove migrations to get tighter query scopes
Storage Tradeoffs
Table storage:
- optimized for repeated scans
- should back components that appear in hot gameplay loops
Sparse storage:
- better for infrequent markers or tags
- excluded from table-only scans by default
If a sparse component starts showing up in tick-critical queries, it is usually a signal that the component belongs in table storage.
Prescriptive rule:
- if you scan it every tick, it probably belongs in table storage
- if you mostly address it directly or use it as a sparse marker, keep it sparse
Scheduler Tradeoffs
SimpleScheduler now validates stage-local dependencies before execution.
Costs introduced by the stronger model:
- dependency validation during run planning
- topological ordering within each stage
Benefits:
- explicit execution order
- early detection of invalid schedules
- safer composition as system counts grow
This is a good trade in Soroban-oriented contracts because schedule size is typically small relative to the cost of incorrect execution order.
Benchmark Focus Areas
Benchmarks should answer these practical questions:
- how many entities can the indexed query path scan efficiently
- when does
ArchetypeWorldoutperformSimpleWorld - what is the cost of adding/removing indexed components
- what is the cost of stage validation and deferred command application
The current benchmark suite in benches/ecs_bench.rs covers these paths directly.
It now includes:
- entity spawn cost
- component insert / lookup cost
- indexed query vs sparse-inclusive query cost
- cache warm-read vs invalidated-read behavior
- scheduler validation + execution cost
SimpleWorldvsArchetypeWorldmulti-component query comparisonSimpleWorldvsArchetypeWorldstructural mutation comparison
Reading The Current Benchmarks
Interpret the benchmark output in this order:
Query PathsIf plain indexed queries and cached queries are already cheap enough, stay onSimpleWorld.Backend Query ComparisonIfArchetypeWorldis materially better on your real multi-component query shape, it may be worth adopting.Backend Structural Mutation ComparisonIf archetype migration is significantly more expensive for your workload, do not switch just because query numbers look better in isolation.Query Cache InvalidationIf your world mutates every tick, cache benefits may collapse; optimize data shape first.
Decision Heuristics
Choose SimpleWorld when:
- gameplay writes are frequent
- entity compositions change often
- table/sparse separation gives you enough control
- your queries are broad but predictable
Choose ArchetypeWorld when:
- the same multi-component query runs constantly
- compositions are mostly fixed after startup
- entity migration cost is amortized over many reads
Keep GameApp, SimpleWorld, and SimpleQuery as the default performance story for new Soroban gameplay code.
Interpretation Rules
Use benchmark output to compare patterns, not to claim universal throughput numbers.
For real contracts, evaluate:
- data shape
- component cardinality
- table vs sparse placement
- how often the world mutates between repeated queries
Performance guidance should always be tied back to those conditions.
If benchmark results and your data shape disagree, trust the data shape first.
Cougr Public API Contract
Purpose
This document defines how Cougr presents its public Rust API for 1.0.
It answers four practical questions:
- which entrypoints are central to the product
- which surfaces are usable but still evolving
- which modules should not be interpreted as production commitments
- which compatibility shims or testing helpers are intentionally outside the long-term contract
API Positioning
Cougr exposes a broad crate surface, but only a scoped subset is part of the defended 1.0 contract.
The current product story is:
cougr-coreis primarily an ECS framework for Soroban-compatible applicationsappis the default gameplay runtime surface for new projectsauth,privacy, andopsare the clearest product-level domain namespaces- accounts remain Beta, while privacy is split between a stable primitive subset and experimental proof systems
- ECS onboarding/runtime surfaces and
standardsare part of the1.0stable contract - helper APIs that exist only for compatibility or transition should remain clearly demoted
Recommended Public Contract
This file now serves as the explicit 1.0 stable API list for cougr-core.
Core entrypoints
These are the frozen entrypoints for the 1.0 stable contract:
SimpleWorldArchetypeWorldecs::{RuntimeWorld, RuntimeWorldMut, WorldBackend}- typed and raw component operations
- command queues
- scheduling primitives
- events, hooks, and observers
- incremental persistence utilities
Concrete frozen root-level contract:
SimpleWorldArchetypeWorldCommandQueueComponent,ComponentTrait,ComponentStorage,ComponentIdSimpleQuery,SimpleQueryBuilderRuntimeWorld,RuntimeWorldMut,WorldBackendResourceruntime::ChangeTracker,runtime::TrackedWorldPlugin,PluginGroup,GameAppScheduleStage,SystemConfig,SimpleScheduler,SystemGrouppreluderuntimeappopsas the clearest Stable standards namespacestandardsas a Stable namespaceprivacy::stableas the clearest stable privacy namespacezk::stableas the stable privacy namespaceauthas the clearest Beta account namespaceaccountsas a Beta namespaceprivacy::experimentalas an explicitly non-contract namespacezk::experimentalas an explicitly non-contract namespace
Supported but evolving surfaces
These surfaces are useful and implemented, but should continue to be presented as Beta:
accounts- higher-level query helpers
- higher-level scheduler helpers
- proof-submission helpers in
zk
Stable privacy subset
These privacy surfaces are intentionally narrower and can be presented as Stable:
- commitments
- commit-reveal
- hidden-state codec interfaces
- Merkle inclusion and sparse Merkle utilities
zk::stable
Non-contract surfaces
These surfaces are public today, but they must not be interpreted as stable commitments:
- testing-only helpers
- advanced proof-verification APIs whose assumptions are still being hardened
zk::experimental- compatibility shims retained for transition
- internals-heavy modules whose invariants are not yet documented as stable guarantees
Top-Level Surface in src/lib.rs
Public modules
Current top-level modules:
appauthaccountsarchetype_worldcommandscomponentdebugbehind feature flagerroreventopsprivacypluginqueryresourceschedulersimple_worldzk
Internal implementation modules such as hidden scheduler helpers, storage
internals, and entity internals are no longer part of
the intended default public surface. They may still exist in the repository,
but the root crate is not meant to advertise them as onboarding entrypoints.
Advanced runtime support such as hooks, observers, change tracking, and
incremental storage is exposed through curated re-exports and runtime
instead of direct top-level module entrypoints.
Public re-exports
Current top-level re-exports emphasize:
- worlds:
SimpleWorld,ArchetypeWorld - backend contracts:
RuntimeWorld,RuntimeWorldMut,WorldBackend - ECS data:
Component,ComponentId,ComponentStorage,ComponentTrait,Position,Resource - orchestration:
CommandQueue,GameApp, schedulers - queries:
SimpleQuery,SimpleQueryBuilder - domain access through explicit namespaces:
auth,privacy,ops,accounts,zk::stable,zk::experimental
Public top-level helper functions
There are no root-level placeholder helper functions in the supported contract.
The sanctioned onboarding path is the curated root surface itself:
appauthprivacyopsSimpleWorldArchetypeWorldCommandQueueGameAppapp::{named_system, named_context_system}andadd_systems
Compatibility Exceptions
Public API Risks
The main public API risks before this cleanup were:
- the crate exports more surface area than it can reasonably defend as stable
- some internals-heavy modules are public before their long-term contract is clearly documented
- some privacy and verification surfaces are easy to overread as production guarantees
- accounts and privacy modules still include beta-grade behavior that is intentionally documented outside the stable story
Freeze Direction
The 1.0 freeze is intentionally narrower than the full public module graph:
appis the clearest default runtime namespace for new gameplay codeauthis the clearest Beta auth namespace for application codeprivacyis the clearest domain namespace for privacy adoption, with stability determined by submoduleopsis the clearest stable namespace for operational standards in application code- root re-exports and
preludeare the default onboarding path runtimeis the supported namespace for advanced ECS integrations that are not part of the smallest onboarding contractqueryandarchetype_worldretain their cache/state helpers outside the smallest root onboarding surfacestandardsis a supported stable namespaceaccountsremains a public Beta namespacezk::stableis the only privacy namespace treated as Stablezk::experimentalremains public for explicit opt-in use, but outside compatibility guarantees
Cougr Compatibility Promises
Purpose
This document defines the compatibility story Cougr is prepared to defend at 1.0.
It turns the maturity model into explicit expectations for adopters, contributors, and maintainers.
1.0 Baseline
Cougr 1.0.0 freezes a scoped stable surface inside a broader public crate.
That means:
- compatibility promises are scoped by maturity, not by visibility alone
- stable, beta, and experimental namespaces can coexist in the same crate
- the stable guarantee is the documented contract, not every public symbol
Stable Surfaces
The following surfaces are treated as Cougr's strongest 1.0 compatibility commitments:
- root ECS onboarding and runtime entrypoints documented in API_CONTRACT.md
preluderuntimeopsstandardsprivacy::stablezk::stable- the contracts documented in PRIVACY_MODEL.md for commit-reveal, hidden-state codecs, and Merkle verification
For these surfaces, maintainers should preserve:
- type and function intent unless there is a documented breaking reason
- documented failure behavior
- documented malformed-input behavior where applicable
- byte-level or proof-shape contracts already written in the privacy model
Beta Surfaces
The following surfaces are supported but intentionally not frozen:
- higher-level ECS helpers outside the frozen root/runtime contract
authaccounts- proof-submission orchestration that depends on experimental verification flows
For Beta surfaces, maintainers commit to:
- keep the product direction coherent
- document meaningful semantic changes
- avoid gratuitous churn
- preserve the curated onboarding path where practical
For Beta surfaces, maintainers do not yet promise:
- SemVer-stable signatures
- unchanged storage layouts for every helper
- unchanged auth or orchestration semantics across all releases
Experimental Surfaces
The following surfaces are explicitly outside compatibility guarantees:
privacy::experimentalzk::experimental- hazmat cryptographic helpers
- advanced proof-verification helpers and descriptors
- any public support surface documented as test-only or transition-only
These may:
- change shape
- move namespace
- be removed
- gain stronger validation that changes edge-case behavior
Non-Contract Support Surfaces
Support-only surfaces such as MockAccount are not part of the default product contract.
They exist for tests and explicit utility consumers, not as long-term framework guarantees.
Change Management Rules
When changing a Stable or Beta public surface, update at minimum:
- MATURITY_MODEL.md if the classification changes
- API_CONTRACT.md if the recommended contract changes
- PUBLIC_GAPS.md if a known gap is closed or newly introduced
- THREAT_MODEL.md if trust assumptions or security posture change
1.0 Freeze Decisions
The 1.0 release gate decisions are:
- ECS onboarding and runtime surfaces are in the stable contract
opsis the stable domain alias for standardsstandardsis in the stable contractauthis a Beta domain alias and is not part of the stable guaranteeaccountsremains Beta and is not part of the stable guaranteeprivacy::stablemaps to the frozen privacy contractzk::stableis the frozen privacy contractprivacy::experimentalremains outside compatibility guaranteeszk::experimentalremains outside compatibility guarantees
Migration Guide
Purpose
This guide explains how to move existing Cougr integrations toward the curated 1.0 product surface.
It is not a promise that every older pattern disappears immediately. It is the recommended direction for users who want to converge on the defended path.
Core Direction
Prefer these namespaces in new or updated code:
appfor gameplay runtimeauthfor account and session flowsprivacy::stablefor stable privacy primitivesopsfor operational standards
Runtime Migration
From direct world/scheduler wiring
If you currently do something like:
#![allow(unused)] fn main() { let mut world = SimpleWorld::new(&env); let mut scheduler = SimpleScheduler::new(); }
prefer:
#![allow(unused)] fn main() { let mut app = cougr_core::app::GameApp::new(&env); }
and register systems through GameApp.
When multiple systems belong to the same phase, prefer the declarative path:
#![allow(unused)] fn main() { use cougr_core::app::{named_context_system, named_system, GameApp, ScheduleStage}; let mut app = GameApp::new(&env); app.add_systems(( named_system("spawn", |world, env| { let entity = world.spawn_entity(); world.set_typed(env, entity, &Position::new(0, 0)); }) .in_stage(ScheduleStage::Startup), named_context_system("cleanup_tags", |context| { let entities = context .world() .get_entities_with_component(&symbol_short!("expired"), context.env()); for i in 0..entities.len() { let entity = entities.get(i).unwrap(); context .commands() .remove_component(entity, symbol_short!("expired")); } }) .in_stage(ScheduleStage::Cleanup), )); }
Why:
- clearer lifecycle
- explicit stages
- one onboarding surface instead of several loose primitives
- a single system registration model for plain and context-aware systems
From the removed pre-1.0 ECS model
If you were previously on the removed pre-1.0 World / System path, port directly to
GameApp, SimpleWorld, and SimpleQuery.
Query Migration
If you still do ad-hoc scans or manual component filtering, prefer:
SimpleQueryBuilderSimpleQueryStateSimpleQueryCache
Both SimpleQueryBuilder and ArchetypeQueryBuilder now support:
with_components(...)without_components(...)with_any_components(...)
If you need backend-agnostic gameplay helpers across Soroban-first worlds, prefer:
RuntimeWorldRuntimeWorldMut
These are the shared contracts between SimpleWorld and ArchetypeWorld.
Domain Migration
Accounts
If you currently import from accounts directly in application code:
#![allow(unused)] fn main() { use cougr_core::accounts::SessionBuilder; }
prefer:
#![allow(unused)] fn main() { use cougr_core::auth::SessionBuilder; }
The semantics are the same today. The change is about product clarity.
Privacy
If you rely on stable privacy primitives, prefer:
#![allow(unused)] fn main() { use cougr_core::privacy::stable::... }
instead of:
#![allow(unused)] fn main() { use cougr_core::zk::stable::... }
If you rely on advanced proof tooling, prefer:
#![allow(unused)] fn main() { use cougr_core::privacy::experimental::... }
and treat it as an explicit opt-in to non-frozen APIs.
Standards
If you currently import standards directly:
#![allow(unused)] fn main() { use cougr_core::standards::Pausable; }
prefer:
#![allow(unused)] fn main() { use cougr_core::ops::Pausable; }
Again, this is a namespace migration for clarity, not a semantic rewrite.
Example-Level Migration
Use these examples as references:
snakeforapp::GameAppand stage-based gameplay loopsbattleshipforprivacy::stableand hidden-information patternsguild_arenafor account/session/recovery patterns
What Does Not Need Immediate Migration
You do not need to rewrite everything at once if:
- the contract still needs a focused port from the removed pre-1.0 runtime path
- you are preserving an older example or integration
- your current code already sits behind a stable local abstraction
The main goal is to stop growing new code on top of older default imports.
Migration Checklist
-
move runtime entrypoints to
appwhere practical -
move account imports to
auth -
move stable privacy imports to
privacy::stable -
move standards imports to
ops - update local docs/examples to use the curated namespaces
CLI Reference
⏳ This page does not exist yet because the
cougr-clicrate does not exist yet.Per
docs/strategy/12-documentation-architecture.md: "CLI reference — Does not exist because the CLI does not exist yet; ships alongside it."When the CLI ships, this page will document all
cougr new,cougr add, andcougr checksubcommands.Tracked in:
salazarsebas/Cougrissues
Client SDK Reference
⏳ This page does not exist yet because the TypeScript client SDK does not exist yet.
Per
docs/strategy/12-documentation-architecture.md: "Client SDK reference — Ships alongside the SDK described in 06-product-strategy.md."When the SDK ships, this page will document the TypeScript API for connecting a frontend to a Cougr game contract, including wallet integration and session key management.
Tracked in:
salazarsebas/Cougrissues
Architecture Decision Records
Architecture Decision Records (ADRs) document significant technical decisions made in Cougr's design. They are kept in the main salazarsebas/Cougr repository under docs/adr/ and synced here automatically.
Each ADR follows the format: context → decision → consequences.
| ADR | Title |
|---|---|
| 0001 | Public API Surface |
| 0002 | Accounts Beta |
| 0003 | Privacy Model Split |
| 0004 | Standards Layer Stable |
| 0006 | Game Circuit Suite |
| 0007 | Workspace Subcrates |
Showcase
⏳ The showcase gallery generator is a separate epic. This page reserves its place in the navigation.
The Showcase is a live directory of games and demos built with Cougr. It will be generated automatically from the examples/ directory in the main repository and from community submissions.
Examples in the core repository
| Example | Description | Complexity |
|---|---|---|
spawn_and_move | Canonical hello-world: spawn a player, walk in four directions | Starter |
tic_tac_toe | Turn-based two-player game; rich component demonstration | Intermediate |
murdoku | Full game with a client frontend | Advanced |
Submit your game
Once the showcase gallery is built, you'll be able to submit your Cougr game for a "Cougr Verified" badge by opening a PR to this repository.
Check back soon — or watch the repository.
Example Gallery
⏳ This page will be auto-generated. The gallery generator is tracked as a separate epic.
See the Showcase index for an overview of currently known examples.
Design
⏳ This section is being built. All design documents are gaps identified in
docs/strategy/12-documentation-architecture.mdand will be produced alongside the design system rollout.
The Design section contains guidelines for anyone building a client application against Cougr, contributing visual work, or working on the docs site itself.
| Guide | Status |
|---|---|
| Branding Guide | 🔜 Coming soon |
| UI Guidelines | 🔜 Coming soon |
| UX Guidelines | 🔜 Coming soon |
| Accessibility | 🔜 Coming soon |
Branding Guide
⏳ This page is being written.
Will cover: logo usage, color palette, typography, design tokens, and the "Cougr Verified" badge. Full specification in docs/strategy/09-design-strategy.md in the main repository.
UI Guidelines
⏳ This page is being written.
Will cover UI patterns for building a client application against a Cougr game contract. The murdoku frontend in the main repo is the first worked reference this guide will draw from.
UX Guidelines
⏳ This page is being written.
Will cover player-facing UX patterns — wallet connection, session key UX, and transaction feedback — distinct from the developer UX covered in the Learn section.
Accessibility
⏳ This page is being written.
Will cover accessibility requirements for both this documentation site and for client applications built on Cougr. Currently unaddressed anywhere in the project — flagged in docs/strategy/12-documentation-architecture.md.
Community
Welcome to the Community section. This is where you'll find everything about how to contribute, how decisions are made, and how to stay up to date.
| Document | Description |
|---|---|
| Contributing | How to open issues, write code, and get PRs merged |
| Code of Conduct | Expected behaviour in all project spaces |
| Governance | How decisions are made, who can merge, how disputes are resolved |
| Security | How to report vulnerabilities |
| Roadmap | Where the project is headed |
| RFC Process | How to propose significant changes before implementing them |
| Changelog | What changed in each release |
Contributing
Contributions should improve the framework, the example catalog, or the supporting documentation with a clear purpose. This repository is structured to be useful both as a reusable library and as a reference codebase, so changes should optimize for correctness, clarity, and maintainability.
Scope
Good contributions typically fall into one of these categories:
| Area | Expected outcome |
|---|---|
| Core framework | Improved ECS, scheduling, storage, authorization, or zero-knowledge capabilities |
| Examples | New game patterns, better reference implementations, or tighter example documentation |
| Documentation | Clearer architecture, setup, or usage guidance aligned with the current codebase |
| Quality | Better tests, tooling, validation, or CI coverage |
Development Standards
- Keep changes focused. Avoid mixing unrelated refactors with feature work.
- Update documentation when behavior, structure, or public APIs change.
- Prefer clear names and straightforward control flow over clever abstractions.
- Preserve repository consistency. New files should fit the existing layout and conventions.
- Do not add generated reports, ad hoc summaries, or temporary planning documents to the repository root.
Local Validation
Run the relevant checks before opening a pull request:
cargo fmt --check
cargo clippy --all-targets --all-features -- -D warnings
cargo test
If you modify an example project, also run that example's local checks from its own directory. If the example supports Soroban contract builds, validate that flow as well.
Documentation Expectations
Documentation should be professional, current, and proportionate:
- avoid stale exact counts when the repository is expected to grow
- explain decisions and usage patterns without turning every page into a long-form essay
- use tables when they improve scanability, not as a default for all content
- keep root-level documentation limited to material with clear long-term value
- follow the terminology and voice rules in docs/VOICE_GUIDE.md for all doc, example, and marketing copy
Pull Requests
Pull requests should make it easy to review technical intent. A strong PR description usually covers:
- what changed
- why the change was needed
- how it was validated
- any follow-up work or constraints reviewers should know about
Adding Examples
When adding a new example:
- make the example self-contained
- include a local
README.md - keep the example focused on one or two clear patterns
- add CI coverage when the example is meant to remain a maintained reference
Review Criteria
Changes are more likely to be accepted when they:
- solve a real problem in the framework or examples
- keep the API and repository structure coherent
- include appropriate validation
- improve the repository without increasing maintenance noise
Public API Checklist
Changes that touch public Rust APIs should be reviewed against this checklist before merge:
- the symbol belongs to the curated onboarding path or an intentional namespace such as
accounts,zk::stable, orzk::experimental - stable, beta, experimental, and test-only surfaces are not mixed in the same default entrypoint
- new public names do not duplicate an existing public concept
- root-level re-exports are intentional and minimal
- examples and integration tests use the sanctioned public path instead of deep internal module paths
- documentation is updated to match the actual exported API
Code of Conduct
⚠️ This document is an urgent gap identified in
docs/strategy/12-documentation-architecture.md: "Missing despite 25+ active external contributors. Should be added immediately, independent of any other work in this package — this is a near-zero-cost fix for a real, present governance gap."Tracked in:
salazarsebas/Cougrissues
A Code of Conduct will be added here imminently. It will be based on the Contributor Covenant and apply to all project spaces including GitHub Issues, Pull Requests, and any community channels.
Governance
⏳ This page is being written.
Identified as a gap in
docs/strategy/12-documentation-architecture.md. No documented decision-making process exists yet.
Will cover:
- Who can merge pull requests
- How disputes over public API changes are resolved
- How maintainer status is granted and revoked
- The relationship between the existing
CONTRIBUTING.mdPublic API Checklist and final authority on API decisions
Tracked in: salazarsebas/Cougr issues
Security Policy
Status
Cougr now defines a 1.0.0 stable contract for a scoped subset of the crate. Not every public subsystem is part of that stable guarantee.
Security-sensitive areas include:
- account authorization
- session lifecycle and replay protection
- persistent storage integrity
- proof verification and privacy primitives
- ECS mutation ordering where authorization depends on state transitions
Maturity and Guarantees
Current guidance:
| Area | Status | Guidance |
|---|---|---|
| ECS runtime and storage | Stable | Part of the 1.0 contract when used through the documented onboarding and runtime surfaces |
| Accounts and smart-account flows | Beta | Do not assume full production guarantees without project-specific review |
Standards layer (standards) | Stable | Reusable contract primitives are part of the 1.0 stable contract |
Privacy primitives (zk::stable) | Stable | Commit-reveal, hidden-state codecs, and Merkle utilities are the stable privacy contract |
| Advanced ZK verification | Experimental | Treat as non-stable until verification contracts and assumptions are fully hardened |
The latest maturity definitions live in docs/MATURITY_MODEL.md. The current threat-model baseline lives in docs/THREAT_MODEL.md. The explicit compatibility story lives in docs/COMPATIBILITY_PROMISES.md.
Threat Model Expectations
Cougr does not currently claim:
- external audit coverage
- formal verification
- full production guarantees across all auth and privacy paths
- stable compatibility guarantees for experimental modules
Before adopting Cougr in security-critical deployments, review at minimum:
- auth and signer flows
- replay handling
- session scope and revocation rules
- storage schema assumptions
- proof verification assumptions
Reporting a Vulnerability
If you find a security issue:
- Do not open a public issue with exploit details.
- Report the issue privately to the project maintainers.
- Include:
- affected module
- reproduction steps
- impact assessment
- version or commit information
- suggested mitigation if available
Until a dedicated security contact is published, use the maintainer channels associated with this repository and clearly label the report as a security disclosure.
Supported Versions
The latest stable release line and current mainline development state should be assumed relevant for fixes unless a maintenance policy says otherwise.
Secure Contribution Expectations
Changes affecting auth, privacy, storage, or unsafe internals should include:
- updated invariants or trust assumptions
- negative-path tests
- compatibility notes when public behavior changes
- documentation changes when guarantees or maturity shift
Roadmap
⏳ This page is being written.
No
ROADMAP.mdexists in the main repository yet. Perdocs/strategy/12-documentation-architecture.md: "Should be a public, living version of 13-roadmap.md, updated quarterly, not a one-time publish."
The public roadmap will be maintained here once established. It will track:
- Near-term:
cougr-cli(cougr new,cougr add,cougr check) - Medium-term: TypeScript client SDK, resource-cost reporting in test harness
- Long-term: Visual editor, showcase gallery, hosted-service option
Tracked in: salazarsebas/Cougr issues
RFC Process
⏳ This page is being written.
The ADR practice (
docs/adr/) covers internal architecture decisions well. An RFC process is the public-facing counterpart for changes the community should weigh in on before they happen.Per
docs/strategy/12-documentation-architecture.md: "Recommend adopting a lightweight RFC template modeled directly on the existing ADR format, since the team already has the discipline to use it well."
When the RFC process is established it will cover:
- What kinds of changes require an RFC (public API changes, new primitives, breaking changes)
- The RFC template (based on the existing ADR format)
- How to submit, how long the comment period is, and who has final say
Tracked in: salazarsebas/Cougr issues
Changelog
Unreleased
Added
cougr-cli— new workspace member publishing thecougrbinarycougr new <name> [--template <name>]— scaffolds a Soroban game contract crate following the canonicallib.rs/components.rs/systems.rslayout, with a passingtest::GameHarnesssuite and a dependency on the publishedcougr-corerelease rather than a path dependency- Four embedded templates, each derived from a canonical example and compiled into
the binary so
cougr newworks offline:starter(spawn_and_move),turn-based(tic_tac_toe),hidden-info(hidden_hand),session-auth(session_arena) - CLI CI workflow — lints and tests
cougr-cli, then generates each template and runscargo fmt,clippy,cargo test, and awasm32v1-nonerelease build against it
1.1.0
Added
game::SorobanGametrait — standardload_world/save_worldcontract pattern; implement once withimpl_soroban_game!(Contract, "key"), use in every entrypointimpl_soroban_game!macro — wiresSorobanGameto any#[contract]structSimpleWorld::load_from_instance— load world from Soroban instance storage, returning a fresh empty world on first callSimpleWorld::save_to_instance— persist world to Soroban instance storageSimpleWorld::set_rich_observed— store a rich component and emit aRichComponentChangedEventfor off-chain indexersSimpleWorld::remove_rich_observed— remove a rich component and emit adeleventRichComponentChangedEvent— new Soroban event type with topics("COUGR", "rich", component_type)for rich component change notificationsspawn_and_moveexample — canonical Cougr starter game demonstrating the complete idiomatic pattern:impl_component_observed!+SorobanGame+ typed ECS accessSorobanGamere-exported fromprelude— import fromcougr_core::prelude::*cougr_core::circuits— four pre-built ZK game builders (hidden cards, fog of war, fair dice, sealed bid) with pipeline-embedded verification keyscougr_core::session—SessionManager,SessionStatus, andActiveSession(Beta)cougr_core::test—GameHarness,Scenario, andReplayLogsandbox behind thetestutilsfeature- Circom pipeline —
internal/cougr-core-circuitswith CI workflow and on-chain Groth16 proof verification using real VKs - ZK examples —
hidden_hand,fog_explorer,dice_duel, andblind_auction - Workspace subcrates —
internal/cougr-core-{circuits,session,test}per ADR 0007
Changed
tic_tac_toeexample modernised: replaced ~200 lines of manual serialization withimpl_rich_component!forBoardandPlayers, andimpl_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_arenaexample added as canonical reference forsession::SessionManager
Stability Notes
game::SorobanGameis StableSimpleWorld::load_from_instance/save_to_instanceare Stableset_rich_observed/remove_rich_observedare StableRichComponentChangedEventis Stablecougr_core::sessionis Betacougr_core::circuitsand embedded test VKs are Experimentalcougr_core::testis Experimental (testutilsonly)
1.0.0
Added
appas the default gameplay runtime surfaceauth,privacy, andopsas product-level domain namespacesRuntimeWorldandRuntimeWorldMutas shared Soroban-first backend contracts- stronger stage scheduling with ordering, sets, and validation
SimpleQueryBuilder, query state/cache improvements, and richerArchetypeWorldquery 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
battleshipnow uses stable privacy primitives fromzk::stable- documentation now treats
SimpleWorldandArchetypeWorldas 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
appover 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, andSimpleQuery - Prefer
ops,privacy, andauthin 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