diff --git a/.github/workflows/cougr-site.yml b/.github/workflows/cougr-site.yml new file mode 100644 index 0000000..7769c0b --- /dev/null +++ b/.github/workflows/cougr-site.yml @@ -0,0 +1,62 @@ +name: Cougr Site + +on: + push: + branches: [main, develop] + paths: + - 'cougr-site/**' + - 'docs/**' + - 'ARCHITECTURE.md' + - 'CONTRIBUTING.md' + - 'CHANGELOG.md' + - 'SECURITY.md' + - '.github/workflows/cougr-site.yml' + pull_request: + branches: [main, develop] + paths: + - 'cougr-site/**' + - 'docs/**' + - 'ARCHITECTURE.md' + - 'CONTRIBUTING.md' + - 'CHANGELOG.md' + - 'SECURITY.md' + - '.github/workflows/cougr-site.yml' + +concurrency: + group: cougr-site-${{ github.workflow }}-${{ github.ref }} + cancel-in-progress: true + +jobs: + site: + name: Build and verify cougr-site + runs-on: ubuntu-latest + timeout-minutes: 10 + + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: '3.x' + + - name: Sync docs into cougr-site/src + run: python3 cougr-site/sync.py + + # The sync reads straight from this checkout, so any drift here means + # cougr-site/src was committed out of date with its docs/*.md source. + - name: Verify synced content matches docs/*.md + run: | + if ! git diff --quiet -- cougr-site/src; then + echo "cougr-site/src is out of sync with its source docs." + echo "Run 'python3 cougr-site/sync.py' and commit the result." + git diff --stat -- cougr-site/src + exit 1 + fi + + - uses: peaceiris/actions-mdbook@v2 + with: + mdbook-version: 'latest' + + - name: Build the book + working-directory: ./cougr-site + run: mdbook build diff --git a/cougr-site/.gitignore b/cougr-site/.gitignore new file mode 100644 index 0000000..6fe79f0 --- /dev/null +++ b/cougr-site/.gitignore @@ -0,0 +1,9 @@ +# mdBook build output — never commit +book/ + +# macOS +.DS_Store + +# Editor +.vscode/ +.idea/ diff --git a/cougr-site/book.toml b/cougr-site/book.toml new file mode 100644 index 0000000..9b3d7ba --- /dev/null +++ b/cougr-site/book.toml @@ -0,0 +1,13 @@ +[book] +authors = ["Cougr Contributors"] +language = "en" +src = "src" +title = "Cougr Documentation" + +[build] +build-dir = "book" +create-missing = false + +[output.html] +git-repository-url = "https://github.com/salazarsebas/Cougr" +edit-url-template = "https://github.com/salazarsebas/Cougr/edit/main/{path}" diff --git a/cougr-site/src/README.md b/cougr-site/src/README.md new file mode 100644 index 0000000..bb01338 --- /dev/null +++ b/cougr-site/src/README.md @@ -0,0 +1,5 @@ +# 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](https://github.com/salazarsebas/Cougr) repository. diff --git a/cougr-site/src/SUMMARY.md b/cougr-site/src/SUMMARY.md new file mode 100644 index 0000000..7656be8 --- /dev/null +++ b/cougr-site/src/SUMMARY.md @@ -0,0 +1,42 @@ +# Summary + +[Welcome](README.md) + +- [Start](start/README.md) + - [Getting Started](start/getting-started.md) + - [Build Your First Game](start/build-your-first-game.md) +- [Learn](learn/README.md) + - [Architecture](learn/ARCHITECTURE.md) + - [Game Patterns](learn/PATTERNS.md) + - [On-Chain / Off-Chain Boundary Guide](learn/boundary-guide.md) + - [Smart Contract Patterns](learn/smart-contract-patterns.md) + - [Testing Guide](learn/testing-guide.md) + - [Deployment Guide](learn/deployment-guide.md) +- [Reference](reference/README.md) + - [ECS Core](reference/ECS_CORE.md) + - [Account Kernel](reference/ACCOUNT_KERNEL.md) + - [Standards Layer](reference/STANDARDS_LAYER.md) + - [Privacy Model](reference/PRIVACY_MODEL.md) + - [Feature Flags](reference/FEATURE_FLAGS.md) + - [Performance Guide](reference/PERFORMANCE.md) + - [API Contract](reference/API_CONTRACT.md) + - [Compatibility Promises](reference/COMPATIBILITY_PROMISES.md) + - [Migration Guide](reference/MIGRATION_GUIDE.md) + - [CLI Reference](reference/cli-reference.md) + - [Client SDK Reference](reference/sdk-reference.md) + - [ADR: Architecture Decision Records](reference/adr/README.md) +- [Showcase](showcase/README.md) + - [Example Gallery](showcase/gallery.md) +- [Design](design/README.md) + - [Branding Guide](design/branding-guide.md) + - [UI Guidelines](design/ui-guidelines.md) + - [UX Guidelines](design/ux-guidelines.md) + - [Accessibility](design/accessibility.md) +- [Community](community/README.md) + - [Contributing](community/CONTRIBUTING.md) + - [Code of Conduct](community/CODE_OF_CONDUCT.md) + - [Governance](community/governance.md) + - [Security](community/SECURITY.md) + - [Roadmap](community/roadmap.md) + - [RFC Process](community/rfc-process.md) + - [Changelog](community/CHANGELOG.md) diff --git a/cougr-site/src/community/CHANGELOG.md b/cougr-site/src/community/CHANGELOG.md new file mode 100644 index 0000000..16c89fc --- /dev/null +++ b/cougr-site/src/community/CHANGELOG.md @@ -0,0 +1,100 @@ +# Changelog + +## Unreleased + +### Added + +- **`cougr-cli`** — new workspace member publishing the `cougr` binary +- **`cougr new [--template ]`** — 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** — lints and tests `cougr-cli`, then generates each template and + runs `cargo fmt`, `clippy`, `cargo test`, and a `wasm32v1-none` release build against it + +## 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](../reference/MIGRATION_GUIDE.md) for concrete migration mappings diff --git a/cougr-site/src/community/CODE_OF_CONDUCT.md b/cougr-site/src/community/CODE_OF_CONDUCT.md new file mode 100644 index 0000000..09cab49 --- /dev/null +++ b/cougr-site/src/community/CODE_OF_CONDUCT.md @@ -0,0 +1,10 @@ +# 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/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) + +--- + +A Code of Conduct will be added here imminently. It will be based on the [Contributor Covenant](https://www.contributor-covenant.org/) and apply to all project spaces including GitHub Issues, Pull Requests, and any community channels. diff --git a/cougr-site/src/community/CONTRIBUTING.md b/cougr-site/src/community/CONTRIBUTING.md new file mode 100644 index 0000000..81ac3f0 --- /dev/null +++ b/cougr-site/src/community/CONTRIBUTING.md @@ -0,0 +1,82 @@ +# 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: + +```bash +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](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: + +1. what changed +2. why the change was needed +3. how it was validated +4. 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`, or `zk::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 diff --git a/cougr-site/src/community/README.md b/cougr-site/src/community/README.md new file mode 100644 index 0000000..0033fd3 --- /dev/null +++ b/cougr-site/src/community/README.md @@ -0,0 +1,13 @@ +# 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](CONTRIBUTING.md) | How to open issues, write code, and get PRs merged | +| [Code of Conduct](CODE_OF_CONDUCT.md) | Expected behaviour in all project spaces | +| [Governance](governance.md) | How decisions are made, who can merge, how disputes are resolved | +| [Security](SECURITY.md) | How to report vulnerabilities | +| [Roadmap](roadmap.md) | Where the project is headed | +| [RFC Process](rfc-process.md) | How to propose significant changes before implementing them | +| [Changelog](CHANGELOG.md) | What changed in each release | diff --git a/cougr-site/src/community/SECURITY.md b/cougr-site/src/community/SECURITY.md new file mode 100644 index 0000000..fbb0066 --- /dev/null +++ b/cougr-site/src/community/SECURITY.md @@ -0,0 +1,74 @@ +# 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](docs/MATURITY_MODEL.md). +The current threat-model baseline lives in [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md). +The explicit compatibility story lives in [docs/COMPATIBILITY_PROMISES.md](../reference/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: + +1. Do not open a public issue with exploit details. +2. Report the issue privately to the project maintainers. +3. 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 diff --git a/cougr-site/src/community/governance.md b/cougr-site/src/community/governance.md new file mode 100644 index 0000000..716191e --- /dev/null +++ b/cougr-site/src/community/governance.md @@ -0,0 +1,16 @@ +# 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.md` Public API Checklist and final authority on API decisions + +**Tracked in:** [`salazarsebas/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) diff --git a/cougr-site/src/community/rfc-process.md b/cougr-site/src/community/rfc-process.md new file mode 100644 index 0000000..fb1d837 --- /dev/null +++ b/cougr-site/src/community/rfc-process.md @@ -0,0 +1,17 @@ +# 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](https://github.com/salazarsebas/Cougr/issues) diff --git a/cougr-site/src/community/roadmap.md b/cougr-site/src/community/roadmap.md new file mode 100644 index 0000000..b8fa0f0 --- /dev/null +++ b/cougr-site/src/community/roadmap.md @@ -0,0 +1,15 @@ +# Roadmap + +> ⏳ **This page is being written.** +> +> No `ROADMAP.md` exists in the main repository yet. Per `docs/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](https://github.com/salazarsebas/Cougr/issues) diff --git a/cougr-site/src/design/README.md b/cougr-site/src/design/README.md new file mode 100644 index 0000000..b9b8a4a --- /dev/null +++ b/cougr-site/src/design/README.md @@ -0,0 +1,14 @@ +# Design + +> ⏳ **This section is being built.** All design documents are gaps identified in `docs/strategy/12-documentation-architecture.md` and 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](branding-guide.md) | 🔜 Coming soon | +| [UI Guidelines](ui-guidelines.md) | 🔜 Coming soon | +| [UX Guidelines](ux-guidelines.md) | 🔜 Coming soon | +| [Accessibility](accessibility.md) | 🔜 Coming soon | diff --git a/cougr-site/src/design/accessibility.md b/cougr-site/src/design/accessibility.md new file mode 100644 index 0000000..a9e3ffc --- /dev/null +++ b/cougr-site/src/design/accessibility.md @@ -0,0 +1,5 @@ +# 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`. diff --git a/cougr-site/src/design/branding-guide.md b/cougr-site/src/design/branding-guide.md new file mode 100644 index 0000000..c136fab --- /dev/null +++ b/cougr-site/src/design/branding-guide.md @@ -0,0 +1,5 @@ +# 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. diff --git a/cougr-site/src/design/ui-guidelines.md b/cougr-site/src/design/ui-guidelines.md new file mode 100644 index 0000000..9b2ce1d --- /dev/null +++ b/cougr-site/src/design/ui-guidelines.md @@ -0,0 +1,5 @@ +# 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. diff --git a/cougr-site/src/design/ux-guidelines.md b/cougr-site/src/design/ux-guidelines.md new file mode 100644 index 0000000..9f31c7e --- /dev/null +++ b/cougr-site/src/design/ux-guidelines.md @@ -0,0 +1,5 @@ +# 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. diff --git a/cougr-site/src/learn/ARCHITECTURE.md b/cougr-site/src/learn/ARCHITECTURE.md new file mode 100644 index 0000000..fd3e4b5 --- /dev/null +++ b/cougr-site/src/learn/ARCHITECTURE.md @@ -0,0 +1,143 @@ +# Architecture + +High-level overview of how Cougr is organized. For usage, see [README.md](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`, `set_typed`) 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, behind `hazmat-crypto` feature +- **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`) — `GameCircuit` trait + pre-built circuits (Movement, Combat, Inventory, TurnSequence) + `CustomCircuitBuilder` +- **ECS integration** (`components.rs`, `systems.rs`) — `CommitReveal`, `HiddenState`, `ProofSubmission` components 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](../reference/adr/0005-session-ux.md). + +## Standards (`src/standards/`) + +Reusable contract standards for integrations that need explicit operational controls: + +- `Ownable` and `Ownable2Step` for owner-managed authority +- `AccessControl` for role-based authorization with delegated admins +- `Pausable` for emergency stops +- `ExecutionGuard` for serialized critical sections +- `RecoveryGuard` for blocking sensitive paths during recovery windows +- `BatchExecutor` for bounded multi-operation flows +- `DelayedExecutionPolicy` for 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](../reference/adr/0006-game-circuit-suite.md). + +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](../reference/adr/0004-sandbox-design.md) and [ADR 0007](../reference/adr/0007-workspace-subcrates.md). + +## 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`. diff --git a/cougr-site/src/learn/PATTERNS.md b/cougr-site/src/learn/PATTERNS.md new file mode 100644 index 0000000..3e4ab3b --- /dev/null +++ b/cougr-site/src/learn/PATTERNS.md @@ -0,0 +1,135 @@ +# 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`](../examples/dice_duel) | [Hidden Information Guidance](#hidden-information-guidance) below, [PRIVACY_MODEL.md](../reference/PRIVACY_MODEL.md) | +| **Hidden information** (cards, ship positions, sealed bids — state some players shouldn't see) | `privacy::stable` commit-reveal + Merkle primitives | [`battleship`](../examples/battleship) (canonical), [`rock_paper_scissors`](../examples/rock_paper_scissors), [`hidden_hand`](../examples/hidden_hand), [`blind_auction`](../examples/blind_auction) | [Hidden Information Guidance](#hidden-information-guidance) below, [PRIVACY_MODEL.md](../reference/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](../reference/STANDARDS_LAYER.md#accesscontrol) | +| **Off-chain-friendly real-time movement** (clients track state without polling) | `impl_component_observed!` — emits a `(COUGR, set, )` event on every change | [`spawn_and_move`](../examples/spawn_and_move) (start here), [`snake`](../examples/snake) | [System Design](#system-design) and [Query Guidance](#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`](../examples/guild_arena) | [ACCOUNT_KERNEL.md § Signers](../reference/ACCOUNT_KERNEL.md#signers) | +| **A session players approve once, not per-transaction** | Session signer + `SessionPolicy` (scope, expiry, operation budget) | [`session_arena`](../examples/session_arena) | [ACCOUNT_KERNEL.md § Session Model](../reference/ACCOUNT_KERNEL.md#session-model) | +| **Account recovery if a device is lost** | `GuardianPolicy` + `ActiveDevicePolicy` | [`guild_arena`](../examples/guild_arena) | [ACCOUNT_KERNEL.md § Policies](../reference/ACCOUNT_KERNEL.md#policies) | +| **An emergency stop / pause switch** | `Pausable` | — | [STANDARDS_LAYER.md § Pausable](../reference/STANDARDS_LAYER.md#pausable) | +| **To serialize mutations / guard against reentrancy-like issues** | `ExecutionGuard` | — | [STANDARDS_LAYER.md § ExecutionGuard](../reference/STANDARDS_LAYER.md#executionguard) | +| **Delayed or timelocked execution** | `DelayedExecutionPolicy` | — | [STANDARDS_LAYER.md § DelayedExecutionPolicy](../reference/STANDARDS_LAYER.md#delayedexecutionpolicy) | +| **To batch several operations safely** | `BatchExecutor` | — | [STANDARDS_LAYER.md § BatchExecutor](../reference/STANDARDS_LAYER.md#batchexecutor) | +| **To decide what belongs on-chain at all** (which state and rules justify their cost, and which should stay client-side) | The five-question boundary framework, applied per piece of state | [`battleship`](../examples/battleship), [`snake`](../examples/snake), [`blind_auction`](../examples/blind_auction) | [ONCHAIN_OFFCHAIN_BOUNDARY.md](./ONCHAIN_OFFCHAIN_BOUNDARY.md) | +| **To know whether I even need ECS** | Direct contract model for small/config-driven contracts | — | [When Not To Use ECS](#when-not-to-use-ecs) below | +| **To pick table vs. sparse storage** | Table for hot-loop state, sparse for infrequent markers | — | [Storage Guidance](#storage-guidance) below | +| **A thin, explicit contract entrypoint / gameplay loop** | `GameApp` + explicit stage placement | [`spawn_and_move`](../examples/spawn_and_move), [`snake`](../examples/snake) | [Default Entry Point](#default-entry-point) and [Stage Layout](#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: + +1. build the app +2. register plugins and startup systems +3. register tick systems into explicit stages, preferably with `named_system(...)` / `named_context_system(...)` +4. 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 setup +- `PreUpdate`: input decoding, action validation, turn preparation +- `Update`: core gameplay state transitions +- `PostUpdate`: scoring, derived-state maintenance, indexing side effects +- `Cleanup`: 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::stable` Merkle 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 `Update` systems 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. diff --git a/cougr-site/src/learn/README.md b/cougr-site/src/learn/README.md new file mode 100644 index 0000000..d3feec9 --- /dev/null +++ b/cougr-site/src/learn/README.md @@ -0,0 +1,12 @@ +# 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](ARCHITECTURE.md) | ✅ Available | +| [Game Patterns](PATTERNS.md) | ✅ Available | +| [On-Chain / Off-Chain Boundary Guide](boundary-guide.md) | 🔜 Coming soon | +| [Smart Contract Patterns](smart-contract-patterns.md) | 🔜 Coming soon | +| [Testing Guide](testing-guide.md) | 🔜 Coming soon | +| [Deployment Guide](deployment-guide.md) | 🔜 Coming soon | diff --git a/cougr-site/src/learn/boundary-guide.md b/cougr-site/src/learn/boundary-guide.md new file mode 100644 index 0000000..94544d0 --- /dev/null +++ b/cougr-site/src/learn/boundary-guide.md @@ -0,0 +1,22 @@ +# 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.md` and `docs/strategy/12-documentation-architecture.md`. +> +> **Tracked in:** [`salazarsebas/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) + +--- + +## 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](https://github.com/salazarsebas/Cougr) to be notified when this page goes live. diff --git a/cougr-site/src/learn/deployment-guide.md b/cougr-site/src/learn/deployment-guide.md new file mode 100644 index 0000000..e2f38a2 --- /dev/null +++ b/cougr-site/src/learn/deployment-guide.md @@ -0,0 +1,19 @@ +# 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/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) + +--- + +## What this guide will cover + +- Configuring the Stellar CLI for Testnet and Mainnet +- Building a release `.wasm` binary 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](https://github.com/salazarsebas/Cougr). diff --git a/cougr-site/src/learn/smart-contract-patterns.md b/cougr-site/src/learn/smart-contract-patterns.md new file mode 100644 index 0000000..2009747 --- /dev/null +++ b/cougr-site/src/learn/smart-contract-patterns.md @@ -0,0 +1,19 @@ +# Smart Contract Patterns + +> ⏳ **This page is being written.** +> +> Will consolidate Soroban-specific patterns from `PATTERNS.md` and `STANDARDS_LAYER.md` into one place, distinguishing "Cougr patterns" from "general Soroban patterns." +> +> **Tracked in:** [`salazarsebas/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) + +--- + +## What this guide will cover + +- Access control with `AccessControl` and `Ownable` +- 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](https://github.com/salazarsebas/Cougr). diff --git a/cougr-site/src/learn/testing-guide.md b/cougr-site/src/learn/testing-guide.md new file mode 100644 index 0000000..54e84dd --- /dev/null +++ b/cougr-site/src/learn/testing-guide.md @@ -0,0 +1,19 @@ +# Testing Guide + +> ⏳ **This page is being written.** +> +> `GameHarness`, `Scenario`, and `SnapshotAssert` exist in the codebase and are used across thousands of lines of tests, but have no standalone guide yet. Named explicitly in `docs/strategy/08-ux-strategy.md` Stage 5. +> +> **Tracked in:** [`salazarsebas/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) + +--- + +## What this guide will cover + +- Setting up `GameHarness` for unit tests +- Writing `Scenario`-based integration tests +- Using `SnapshotAssert` to lock in expected world state +- How the Soroban test sandbox works (and how it differs from running `cargo test` for a normal library) +- Estimating resource costs before you deploy + +Check back soon — or [watch the repository](https://github.com/salazarsebas/Cougr). diff --git a/cougr-site/src/reference/ACCOUNT_KERNEL.md b/cougr-site/src/reference/ACCOUNT_KERNEL.md new file mode 100644 index 0000000..ef909f7 --- /dev/null +++ b/cougr-site/src/reference/ACCOUNT_KERNEL.md @@ -0,0 +1,118 @@ +# 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` + - base implementations for intent expiry, session enforcement, active device checks, and guardian checks +- 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: + +- [src/accounts/replay.rs](../src/accounts/replay.rs) +- [src/accounts/storage.rs](../src/accounts/storage.rs) + +## 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` +- 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: + +- `IntentExpiryPolicy` +- `SessionPolicy` +- `ActiveDevicePolicy` +- `GuardianPolicy` + +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. diff --git a/cougr-site/src/reference/API_CONTRACT.md b/cougr-site/src/reference/API_CONTRACT.md new file mode 100644 index 0000000..7710c13 --- /dev/null +++ b/cougr-site/src/reference/API_CONTRACT.md @@ -0,0 +1,181 @@ +# 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-core` is primarily an ECS framework for Soroban-compatible applications +- `app` is the default gameplay runtime surface for new projects +- `auth`, `privacy`, and `ops` are 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 `standards` are part of the `1.0` stable 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: + +- `SimpleWorld` +- `ArchetypeWorld` +- `ecs::{RuntimeWorld, RuntimeWorldMut, WorldBackend}` +- typed and raw component operations +- command queues +- scheduling primitives +- events, hooks, and observers +- incremental persistence utilities + +Concrete frozen root-level contract: + +- `SimpleWorld` +- `ArchetypeWorld` +- `CommandQueue` +- `Component`, `ComponentTrait`, `ComponentStorage`, `ComponentId` +- `SimpleQuery`, `SimpleQueryBuilder` +- `RuntimeWorld`, `RuntimeWorldMut`, `WorldBackend` +- `Resource` +- `runtime::ChangeTracker`, `runtime::TrackedWorld` +- `Plugin`, `PluginGroup`, `GameApp` +- `ScheduleStage`, `SystemConfig`, `SimpleScheduler`, `SystemGroup` +- `prelude` +- `runtime` +- `app` +- `ops` as the clearest Stable standards namespace +- `standards` as a Stable namespace +- `privacy::stable` as the clearest stable privacy namespace +- `zk::stable` as the stable privacy namespace +- `auth` as the clearest Beta account namespace +- `accounts` as a Beta namespace +- `privacy::experimental` as an explicitly non-contract namespace +- `zk::experimental` as 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: + +- `app` +- `auth` +- `accounts` +- `archetype_world` +- `commands` +- `component` +- `debug` behind feature flag +- `error` +- `event` +- `ops` +- `privacy` +- `plugin` +- `query` +- `resource` +- `scheduler` +- `simple_world` +- `zk` + +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: + +- `app` +- `auth` +- `privacy` +- `ops` +- `SimpleWorld` +- `ArchetypeWorld` +- `CommandQueue` +- `GameApp` +- `app::{named_system, named_context_system}` and `add_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: + +- `app` is the clearest default runtime namespace for new gameplay code +- `auth` is the clearest Beta auth namespace for application code +- `privacy` is the clearest domain namespace for privacy adoption, with stability determined by submodule +- `ops` is the clearest stable namespace for operational standards in application code +- root re-exports and `prelude` are the default onboarding path +- `runtime` is the supported namespace for advanced ECS integrations that are not part of the smallest onboarding contract +- `query` and `archetype_world` retain their cache/state helpers outside the smallest root onboarding surface +- `standards` is a supported stable namespace +- `accounts` remains a public Beta namespace +- `zk::stable` is the only privacy namespace treated as Stable +- `zk::experimental` remains public for explicit opt-in use, but outside compatibility guarantees diff --git a/cougr-site/src/reference/COMPATIBILITY_PROMISES.md b/cougr-site/src/reference/COMPATIBILITY_PROMISES.md new file mode 100644 index 0000000..df0b348 --- /dev/null +++ b/cougr-site/src/reference/COMPATIBILITY_PROMISES.md @@ -0,0 +1,105 @@ +# 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](API_CONTRACT.md) +- `prelude` +- `runtime` +- `ops` +- `standards` +- `privacy::stable` +- `zk::stable` +- the contracts documented in [PRIVACY_MODEL.md](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 +- `auth` +- `accounts` +- 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::experimental` +- `zk::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](MATURITY_MODEL.md) if the classification changes +- [API_CONTRACT.md](API_CONTRACT.md) if the recommended contract changes +- [PUBLIC_GAPS.md](PUBLIC_GAPS.md) if a known gap is closed or newly introduced +- [THREAT_MODEL.md](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 +- `ops` is the stable domain alias for standards +- `standards` is in the stable contract +- `auth` is a Beta domain alias and is not part of the stable guarantee +- `accounts` remains Beta and is not part of the stable guarantee +- `privacy::stable` maps to the frozen privacy contract +- `zk::stable` is the frozen privacy contract +- `privacy::experimental` remains outside compatibility guarantees +- `zk::experimental` remains outside compatibility guarantees diff --git a/cougr-site/src/reference/ECS_CORE.md b/cougr-site/src/reference/ECS_CORE.md new file mode 100644 index 0000000..4dd49a4 --- /dev/null +++ b/cougr-site/src/reference/ECS_CORE.md @@ -0,0 +1,75 @@ +# 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 identity +- `Component`: typed or raw data attached to entities +- `Query`: a declarative selection over entities by component presence +- `System`: logic that reads or mutates the world +- `CommandQueue`: deferred structural mutations +- `GameApp`: app-level orchestration over world + scheduler + plugins +- `RuntimeWorld` / `RuntimeWorldMut`: the shared backend contract for Soroban-first worlds + +For Soroban gameplay contracts, the recommended path is: + +- `app` +- `SimpleWorld` +- `SimpleQuery` +- `SimpleScheduler` +- `GameApp` + +`ArchetypeWorld` is the alternate backend for heavier query workloads. + +The shared stable overlap between those backends lives in: + +- `ecs::RuntimeWorld` +- `ecs::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: + +1. `README.md` +2. `GameApp` +3. `SimpleWorld` +4. `SimpleQueryBuilder` +5. 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. diff --git a/cougr-site/src/reference/FEATURE_FLAGS.md b/cougr-site/src/reference/FEATURE_FLAGS.md new file mode 100644 index 0000000..1a9063a --- /dev/null +++ b/cougr-site/src/reference/FEATURE_FLAGS.md @@ -0,0 +1,33 @@ +# 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: + +- [MATURITY_MODEL.md](MATURITY_MODEL.md) +- [API_CONTRACT.md](API_CONTRACT.md) +- [COMPATIBILITY_PROMISES.md](COMPATIBILITY_PROMISES.md) + +In the product-level facade: + +- `auth` mirrors the Beta `accounts` surface +- `privacy::stable` and `privacy::experimental` mirror the split inside `zk` +- `ops` mirrors the stable `standards` surface diff --git a/cougr-site/src/reference/MIGRATION_GUIDE.md b/cougr-site/src/reference/MIGRATION_GUIDE.md new file mode 100644 index 0000000..bc6b3c0 --- /dev/null +++ b/cougr-site/src/reference/MIGRATION_GUIDE.md @@ -0,0 +1,177 @@ +# 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: + +- `app` for gameplay runtime +- `auth` for account and session flows +- `privacy::stable` for stable privacy primitives +- `ops` for operational standards + +## Runtime Migration + +### From direct world/scheduler wiring + +If you currently do something like: + +```rust +let mut world = SimpleWorld::new(&env); +let mut scheduler = SimpleScheduler::new(); +``` + +prefer: + +```rust +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: + +```rust +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: + +- `SimpleQueryBuilder` +- `SimpleQueryState` +- `SimpleQueryCache` + +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: + +- `RuntimeWorld` +- `RuntimeWorldMut` + +These are the shared contracts between `SimpleWorld` and `ArchetypeWorld`. + +## Domain Migration + +### Accounts + +If you currently import from `accounts` directly in application code: + +```rust +use cougr_core::accounts::SessionBuilder; +``` + +prefer: + +```rust +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: + +```rust +use cougr_core::privacy::stable::... +``` + +instead of: + +```rust +use cougr_core::zk::stable::... +``` + +If you rely on advanced proof tooling, prefer: + +```rust +use cougr_core::privacy::experimental::... +``` + +and treat it as an explicit opt-in to non-frozen APIs. + +### Standards + +If you currently import standards directly: + +```rust +use cougr_core::standards::Pausable; +``` + +prefer: + +```rust +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: + +- `snake` for `app::GameApp` and stage-based gameplay loops +- `battleship` for `privacy::stable` and hidden-information patterns +- `guild_arena` for 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 + +- [x] move runtime entrypoints to `app` where practical +- [x] move account imports to `auth` +- [x] move stable privacy imports to `privacy::stable` +- [x] move standards imports to `ops` +- [x] update local docs/examples to use the curated namespaces diff --git a/cougr-site/src/reference/PERFORMANCE.md b/cougr-site/src/reference/PERFORMANCE.md new file mode 100644 index 0000000..eca0cad --- /dev/null +++ b/cougr-site/src/reference/PERFORMANCE.md @@ -0,0 +1,148 @@ +# 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_index` for table-backed components +- `all_index` for table + sparse lookups + +That changes the expected behavior of the common query paths: + +- `get_table_entities_with_component()` uses the direct table index +- `get_all_entities_with_component()` uses the all-storage index +- `SimpleQuery` selects 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 `ArchetypeWorld` outperform `SimpleWorld` +- 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 +- `SimpleWorld` vs `ArchetypeWorld` multi-component query comparison +- `SimpleWorld` vs `ArchetypeWorld` structural mutation comparison + +## Reading The Current Benchmarks + +Interpret the benchmark output in this order: + +1. `Query Paths` + If plain indexed queries and cached queries are already cheap enough, stay on `SimpleWorld`. +2. `Backend Query Comparison` + If `ArchetypeWorld` is materially better on your real multi-component query shape, it may be worth adopting. +3. `Backend Structural Mutation Comparison` + If archetype migration is significantly more expensive for your workload, do not switch just because query numbers look better in isolation. +4. `Query Cache Invalidation` + If 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. + +## Related + +This guide answers where a component should live once you have decided it belongs on-chain. For +the prior decision, whether a piece of state or logic justifies being on-chain in the first place, +see [ONCHAIN_OFFCHAIN_BOUNDARY.md](./ONCHAIN_OFFCHAIN_BOUNDARY.md). diff --git a/cougr-site/src/reference/PRIVACY_MODEL.md b/cougr-site/src/reference/PRIVACY_MODEL.md new file mode 100644 index 0000000..255e4b1 --- /dev/null +++ b/cougr-site/src/reference/PRIVACY_MODEL.md @@ -0,0 +1,136 @@ +# 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: + - `CommitmentScheme` + - `MerkleProofVerifier` + - `HiddenStateCodec` + - `ProofVerifier` as an interface contract only + +These are exposed through: + +- `cougr_core::privacy::stable` +- `cougr_core::zk::stable` as 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::experimental` +- `cougr_core::zk::experimental` as 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() != depth` return `ZKError::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: + +- [docs/MATURITY_MODEL.md](docs/MATURITY_MODEL.md) +- [docs/API_CONTRACT.md](docs/API_CONTRACT.md) +- [docs/PUBLIC_GAPS.md](docs/PUBLIC_GAPS.md) +- [docs/THREAT_MODEL.md](docs/THREAT_MODEL.md) + +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. diff --git a/cougr-site/src/reference/README.md b/cougr-site/src/reference/README.md new file mode 100644 index 0000000..d9b163e --- /dev/null +++ b/cougr-site/src/reference/README.md @@ -0,0 +1,18 @@ +# Reference + +The **Reference** section contains low-level documentation for Cougr's modules, the API surface, and architectural decision records. + +| Document | Description | +|---|---| +| [ECS Core](ECS_CORE.md) | The core ECS primitives: Entity, Component, Query, System, Scheduler | +| [Account Kernel](ACCOUNT_KERNEL.md) | Account abstraction layer — session keys, recovery, passkeys | +| [Standards Layer](STANDARDS_LAYER.md) | Reusable contract standards: AccessControl, Pausable, Ownable, etc. | +| [Privacy Model](PRIVACY_MODEL.md) | ZK proofs, Pedersen commitments, hidden state | +| [Feature Flags](FEATURE_FLAGS.md) | `hazmat-crypto`, `testutils`, `debug` — what each enables | +| [Performance Guide](PERFORMANCE.md) | Resource cost intuition, benchmarks, optimization patterns | +| [API Contract](API_CONTRACT.md) | Public API guarantees and stability promises | +| [Compatibility Promises](COMPATIBILITY_PROMISES.md) | What Cougr will and won't break between releases | +| [Migration Guide](MIGRATION_GUIDE.md) | How to update your game for new cougr-core versions | +| [CLI Reference](cli-reference.md) | 🔜 Ships with the CLI | +| [Client SDK Reference](sdk-reference.md) | 🔜 Ships with the TypeScript SDK | +| [ADRs](adr/README.md) | Architecture Decision Records | diff --git a/cougr-site/src/reference/STANDARDS_LAYER.md b/cougr-site/src/reference/STANDARDS_LAYER.md new file mode 100644 index 0000000..49d4a80 --- /dev/null +++ b/cougr-site/src/reference/STANDARDS_LAYER.md @@ -0,0 +1,100 @@ +# 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: + +- `Ownable` and `Ownable2Step` require an explicit caller address +- `AccessControl` checks the caller against the relevant admin role +- `Pausable`, `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. diff --git a/cougr-site/src/reference/adr/0001-public-surface.md b/cougr-site/src/reference/adr/0001-public-surface.md new file mode 100644 index 0000000..cf556bd --- /dev/null +++ b/cougr-site/src/reference/adr/0001-public-surface.md @@ -0,0 +1,25 @@ +# ADR 0001: Curated Public Surface + +## Status + +Accepted + +## Context + +Cougr exposes a broad API. Without curation, adopters can easily mistake public visibility for stable-contract inclusion. + +## Decision + +Cougr keeps a curated onboarding path at the crate root and explicitly separates: + +- root-level ECS onboarding re-exports +- `standards` as a Stable namespace +- `zk::stable` as the stable privacy namespace +- `accounts` as a Beta namespace +- `zk::experimental` as the explicit non-contract privacy namespace + +## Consequences + +- docs can name the golden path without pretending the whole crate is frozen +- advanced but useful namespaces remain available +- public visibility alone is no longer the compatibility signal diff --git a/cougr-site/src/reference/adr/0002-accounts-beta.md b/cougr-site/src/reference/adr/0002-accounts-beta.md new file mode 100644 index 0000000..3c42360 --- /dev/null +++ b/cougr-site/src/reference/adr/0002-accounts-beta.md @@ -0,0 +1,19 @@ +# ADR 0002: Keep Accounts Out Of The Stable 1.0 Contract + +## Status + +Accepted + +## Context + +The account kernel, typed intents, replay domains, passkey support, and session enforcement are implemented. However, account abstraction remains a security-sensitive area with meaningful design-space risk. + +## Decision + +Cougr will keep `accounts` as a Beta namespace at `1.0` even though the kernel exists and is tested. + +## Consequences + +- the repo can truthfully document real implementation value +- maintainers keep room to tighten signer, policy, and integration contracts +- adopters are warned not to treat the current account API as SemVer-frozen diff --git a/cougr-site/src/reference/adr/0003-privacy-split.md b/cougr-site/src/reference/adr/0003-privacy-split.md new file mode 100644 index 0000000..9d32bc2 --- /dev/null +++ b/cougr-site/src/reference/adr/0003-privacy-split.md @@ -0,0 +1,22 @@ +# ADR 0003: Stable Privacy Subset With Experimental Verification + +## Status + +Accepted + +## Context + +Cougr contains both defensible privacy primitives and faster-moving proof-verification helpers. Treating them as one maturity tier would overclaim guarantees. + +## Decision + +Cougr formally splits privacy into: + +- `zk::stable` for commitments, commit-reveal, hidden-state codecs, and Merkle verification +- `zk::experimental` for advanced proof verification, circuits, channels, recursive layouts, and hazmat helpers + +## Consequences + +- privacy claims can stay narrow and defendable +- advanced ZK work can continue without blocking the stable subset +- compatibility promises can be scoped precisely by namespace diff --git a/cougr-site/src/reference/adr/0004-sandbox-design.md b/cougr-site/src/reference/adr/0004-sandbox-design.md new file mode 100644 index 0000000..ad65612 --- /dev/null +++ b/cougr-site/src/reference/adr/0004-sandbox-design.md @@ -0,0 +1,19 @@ +# ADR 0004: Sandbox Design + +## Status + +Accepted + +## Context + +We need a secure testing and simulation environment for contracts to allow developers to validate logic (like ECS events and ZK proofs) locally without full node deployments. The sandbox should emulate the target environment accurately. + +## Decision + +We introduce a test sandbox utilizing `no_std` and `alloc` alongside the Soroban `testutils` feature. This sandbox provides core modules for testing games (such as `GameHarness`, `Scenario`, `WorldFixture`, `ReplayLog`, and `SnapshotAssert`). + +## Consequences + +- Developers can write fast local tests with a familiar testing API. +- We must maintain parity between sandbox behavior and on-chain execution. +- Relies on the `testutils` feature flag being managed correctly in the crate. diff --git a/cougr-site/src/reference/adr/0004-standards-stable.md b/cougr-site/src/reference/adr/0004-standards-stable.md new file mode 100644 index 0000000..3340285 --- /dev/null +++ b/cougr-site/src/reference/adr/0004-standards-stable.md @@ -0,0 +1,19 @@ +# ADR 0004: Include Standards In The Stable 1.0 Contract + +## Status + +Accepted + +## Context + +The standards layer is documented, integration-tested, and intentionally designed as a reusable framework surface rather than example glue. + +## Decision + +Cougr includes `standards` in the stable `1.0` contract. + +## Consequences + +- integrators can treat `standards` as part of the defended public framework surface +- future changes to these modules now carry stable-contract weight +- authorization composition remains explicit at the integration boundary rather than hidden inside the primitives diff --git a/cougr-site/src/reference/adr/0005-session-ux.md b/cougr-site/src/reference/adr/0005-session-ux.md new file mode 100644 index 0000000..50dd856 --- /dev/null +++ b/cougr-site/src/reference/adr/0005-session-ux.md @@ -0,0 +1,19 @@ +# ADR 0005: Session UX + +## Status + +Accepted + +## Context + +Repeatedly signing transactions degrades the user experience for on-chain games, especially those requiring frequent interactions (like real-time or turn-based strategy). Players expect a seamless experience akin to Web2 gaming without constantly engaging with a wallet prompt. + +## Decision + +We introduce session keys with a fluent `SessionBuilder` API to authorize specific game actions over a time-bound window without requiring repeated user prompts. `authorize_with_fallback` will be used for graceful degradation, allowing operations to fall back to direct authorization when a session is expired or unavailable. + +## Consequences + +- Massively improved gameplay experience for end users. +- Integration becomes slightly more complex to handle session lifecycles. +- Wallets and client integrations must support and manage session key delegation. diff --git a/cougr-site/src/reference/adr/0006-game-circuit-suite.md b/cougr-site/src/reference/adr/0006-game-circuit-suite.md new file mode 100644 index 0000000..dd68861 --- /dev/null +++ b/cougr-site/src/reference/adr/0006-game-circuit-suite.md @@ -0,0 +1,54 @@ +# ADR 0006: Game Circuit Suite (`cougr_core::circuits`) + +## Status + +Accepted + +## Context + +Game developers need fog-of-war, hidden cards, fair dice, and sealed-bid mechanics +without authoring Circom circuits and wiring Groth16 verification by hand. Cougr +already exposes low-level verifiers under `zk::experimental`, but the onboarding +path requires weeks of ZK specialization. + +## Decision + +1. Ship four pre-built circuit builders under `cougr_core::circuits` (always + available, Experimental maturity): + + | Builder | Public inputs | + |---------|---------------| + | `hidden_cards(deck_size, hand_size)` | deck_root, hand_commitment, player_id, deck_size, hand_size | + | `fog_of_war(w, h, radius)` | map_root, prior/next explored roots, origin, tile, radius | + | `fair_dice(sides, seed_commitment)` | seed_commitment, roll_result, sides, nonce | + | `sealed_bid(max_bid)` | auction_id, bid_commitment, revealed_bid, max_bid | + +2. Each builder returns `GameCircuitSpec` with a frozen `PublicInputLayout`, + placeholder VK (correct IC length), and typed verify methods that delegate to + `zk::experimental::verify_groth16`. Production deploys replace the VK via + `with_verification_key`. + +3. `fog_of_war` reuses `FogOfWarCircuit` in `zk::advanced` — no duplicate + verification logic. + +4. Circom scaffolds and off-chain scripts live in + `internal/cougr-core-circuits/` (`publish = false`). Rust implementation lives + in `src/circuits/`. + +5. Canonical examples demonstrate each builder: + + - `examples/hidden_hand/` + - `examples/fog_explorer/` + - `examples/dice_duel/` + - `examples/blind_auction/` + +## Consequences + +- Developers integrate common game privacy patterns in hours, not weeks. +- Public-input layouts are versioned by `CircuitId` and must not change without a + new ADR. +- On-chain builders ship an unbound VK; load test/production keys from + `internal/cougr-core-circuits` (`bun run pipeline` → `exported/*_vk.json`). +- Circuits use Poseidon + game constraints (~325–13.6k R1CS); pot14 trusted setup. +- `zk::stable` remains unchanged; all new surface stays Experimental until external + audit. \ No newline at end of file diff --git a/cougr-site/src/reference/adr/0007-workspace-subcrates.md b/cougr-site/src/reference/adr/0007-workspace-subcrates.md new file mode 100644 index 0000000..fffed5f --- /dev/null +++ b/cougr-site/src/reference/adr/0007-workspace-subcrates.md @@ -0,0 +1,42 @@ +# ADR 0007: Workspace Subcrates Compiled Into cougr-core + +## Status + +Accepted + +## Context + +Cougr is adding three competitive layers (ZK circuit builders, session UX, game +testing sandbox). They need compile-time isolation without publishing separate +crates.io packages, so download metrics stay unified under `cougr-core`. + +## Decision + +1. Add a Cargo workspace with three internal members under `internal/`: + - `cougr-core-circuits` + - `cougr-core-session` + - `cougr-core-test` + +2. Each internal member sets `publish = false`. + +3. Each layer's implementation lives in `src/{circuits,session,test}/inner.rs`. + The public modules `include!` that file; internal workspace members point their + `[lib] path` at the same `inner.rs` for isolated `cargo check -p` runs. This avoids: + - circular dependencies (session needs `auth` from the same crate) + - `cargo publish` failures on unpublished path deps + - missing files in the published tarball + +4. Public API: + - `cougr_core::circuits` — always available + - `cougr_core::session` — always available + - `cougr_core::test` — `testutils` feature only + +5. The test sandbox uses `no_std` + `alloc`, not `std`. It runs in Soroban + `testutils` environments the same way contract tests do today. + +## Consequences + +- One `cargo add cougr-core` for all capabilities +- Internal folders can still be checked with `cargo check -p cougr-core-session` +- `cargo publish` ships `internal/**` sources inside the `cougr-core` tarball +- Feature `testutils` keeps sandbox code out of contract WASM builds \ No newline at end of file diff --git a/cougr-site/src/reference/adr/0008-standards-stable.md b/cougr-site/src/reference/adr/0008-standards-stable.md new file mode 100644 index 0000000..2c43c19 --- /dev/null +++ b/cougr-site/src/reference/adr/0008-standards-stable.md @@ -0,0 +1,19 @@ +# ADR 0008: Include Standards In The Stable 1.0 Contract + +## Status + +Accepted + +## Context + +The standards layer is documented, integration-tested, and intentionally designed as a reusable framework surface rather than example glue. + +## Decision + +Cougr includes `standards` in the stable `1.0` contract. + +## Consequences + +- integrators can treat `standards` as part of the defended public framework surface +- future changes to these modules now carry stable-contract weight +- authorization composition remains explicit at the integration boundary rather than hidden inside the primitives diff --git a/cougr-site/src/reference/adr/README.md b/cougr-site/src/reference/adr/README.md new file mode 100644 index 0000000..f4cdcf8 --- /dev/null +++ b/cougr-site/src/reference/adr/README.md @@ -0,0 +1,14 @@ +# Architecture Decision Records + +Architecture Decision Records (ADRs) document significant technical decisions made in Cougr's design. They are kept in the main [`salazarsebas/Cougr`](https://github.com/salazarsebas/Cougr) repository under `docs/adr/` and synced here automatically. + +Each ADR follows the format: context → decision → consequences. + +| ADR | Title | +|---|---| +| [0001](0001-public-surface.md) | Public API Surface | +| [0002](0002-accounts-beta.md) | Accounts Beta | +| [0003](0003-privacy-split.md) | Privacy Model Split | +| [0004](0004-standards-stable.md) | Standards Layer Stable | +| [0006](0006-game-circuit-suite.md) | Game Circuit Suite | +| [0007](0007-workspace-subcrates.md) | Workspace Subcrates | diff --git a/cougr-site/src/reference/cli-reference.md b/cougr-site/src/reference/cli-reference.md new file mode 100644 index 0000000..81ed0bd --- /dev/null +++ b/cougr-site/src/reference/cli-reference.md @@ -0,0 +1,9 @@ +# CLI Reference + +> ⏳ **This page does not exist yet because the `cougr-cli` crate 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`, and `cougr check` subcommands. +> +> **Tracked in:** [`salazarsebas/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) diff --git a/cougr-site/src/reference/sdk-reference.md b/cougr-site/src/reference/sdk-reference.md new file mode 100644 index 0000000..861d87d --- /dev/null +++ b/cougr-site/src/reference/sdk-reference.md @@ -0,0 +1,9 @@ +# 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/Cougr` issues](https://github.com/salazarsebas/Cougr/issues) diff --git a/cougr-site/src/showcase/README.md b/cougr-site/src/showcase/README.md new file mode 100644 index 0000000..db13231 --- /dev/null +++ b/cougr-site/src/showcase/README.md @@ -0,0 +1,21 @@ +# 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](https://github.com/salazarsebas/Cougr). diff --git a/cougr-site/src/showcase/gallery.md b/cougr-site/src/showcase/gallery.md new file mode 100644 index 0000000..4c4305c --- /dev/null +++ b/cougr-site/src/showcase/gallery.md @@ -0,0 +1,5 @@ +# Example Gallery + +> ⏳ **This page will be auto-generated.** The gallery generator is tracked as a separate epic. + +See the [Showcase index](README.md) for an overview of currently known examples. diff --git a/cougr-site/src/start/README.md b/cougr-site/src/start/README.md new file mode 100644 index 0000000..24228f9 --- /dev/null +++ b/cougr-site/src/start/README.md @@ -0,0 +1,6 @@ +# Start + +Welcome to the **Start** section. If you're new to Cougr, this is the right place to begin. + +- [Getting Started](getting-started.md) — install the toolchain and run your first test in under two minutes. +- [Build Your First Game](build-your-first-game.md) — a step-by-step walkthrough from an empty directory to a deployed game on Stellar Testnet. diff --git a/cougr-site/src/start/build-your-first-game.md b/cougr-site/src/start/build-your-first-game.md new file mode 100644 index 0000000..8eec8da --- /dev/null +++ b/cougr-site/src/start/build-your-first-game.md @@ -0,0 +1,261 @@ +# Build Your First Game + +Welcome to Cougr! This tutorial will take you from an empty directory to a fully tested, testnet-deployed game. + +This guide is designed for developers who already know **Rust** but have no prior experience with **Cougr**, **Soroban**, or **Stellar**. By the end, you'll understand how Cougr's Entity-Component-System (ECS) architecture translates into safe, efficient smart contracts. + +We are going to build a simple 2D grid game where a player can spawn into the world and walk in four directions. + +--- + +## 1. Project Setup + +Since we're building a smart contract, we start with a standard Rust library rather than a binary. + +```bash +cargo new --lib my_first_game +cd my_first_game +``` + +Add `cougr-core` and the `soroban-sdk` to your `Cargo.toml`. We enable the `testutils` feature to get access to Cougr's built-in testing harness later. + +```toml +[package] +name = "my_first_game" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +soroban-sdk = "25.3.2" +cougr-core = "1.1.0" # or the latest version from crates.io + +[features] +testutils = ["soroban-sdk/testutils", "cougr-core/testutils"] +``` + +--- + +## 2. The Mental Model: ECS on Soroban + +If you've used an ECS in a game engine like Bevy or Unity, you already know the basics: **Entities** are just IDs, **Components** hold data, and **Systems** run logic. + +However, building for a blockchain introduces new constraints you must consider: + +> [!WARNING] +> **Soroban-Specific Constraints** +> +> 1. **Storage is not a normal database:** You cannot freely iterate over millions of rows. State must be loaded into memory, modified, and saved back efficiently. +> 2. **Execution costs money:** Every instruction, memory allocation, and storage write costs "gas". Infinite loops or massive arrays will cause your transaction to exceed resource limits and fail. +> 3. **Instance Storage vs Persistent Storage:** Cougr uses Soroban's "Instance Storage" by default for your hot-loop game state. This means all active gameplay components are loaded in a single read, making operations extremely cheap and fast, but it requires you to be mindful of total state size. + +Cougr abstracts the heavy lifting of storage management, but you still need to write code with these constraints in mind. + +--- + +## 3. Defining Components + +Let's open `src/lib.rs`. First, we clear out the default code and define our game's data. + +We need two components: a `Position` to track where the player is, and `Moves` to track how many steps they have left. + +```rust +#![no_std] + +use cougr_core::game::SorobanGame; +use cougr_core::{impl_component, impl_component_observed, impl_soroban_game}; +use soroban_sdk::{contract, contractimpl, contracttype, Env}; + +// `Position` emits an indexed event on every change (so a UI can watch it) +#[contracttype] +#[derive(Clone, Debug, PartialEq)] +pub struct Position { + pub x: i32, + pub y: i32, +} +impl_component_observed!(Position, "position", Table, { x: i32, y: i32 }); + +// `Moves` is kept private; it doesn't need to emit an event on every step +#[contracttype] +#[derive(Clone, Debug, PartialEq)] +pub struct Moves { + pub remaining: u32, +} +impl_component!(Moves, "moves", Table, { remaining: u32 }); +``` + +Notice the two different macros: +- `impl_component_observed!` tells Cougr to emit a Soroban event every time this component is modified. This is crucial for off-chain clients (like your web frontend) to track movement in real-time without polling the blockchain. +- `impl_component!` is for standard data that doesn't need to be broadcasted to indexers, saving you gas on event emissions. + +--- + +## 4. Writing the Game Contract (Systems) + +Next, we define our contract. In Cougr, the contract acts as the outer shell that loads the ECS world, runs your system logic (the functions), and saves the world back. + +Add this to the bottom of `src/lib.rs`: + +```rust +#[contract] +#[derive(Clone)] +pub struct MyFirstGame; + +// This macro wires up the `load_world` and `save_world` boilerplate. +impl_soroban_game!(MyFirstGame, "world"); + +#[contractimpl] +impl MyFirstGame { + + /// Spawns a new player entity into the world. + pub fn spawn(env: Env) -> u32 { + // 1. Load the ECS world from Soroban storage + let mut world = MyFirstGame::load_world(&env); + + // 2. Spawn an entity and attach our components + let entity = world.spawn_entity(); + world.set_typed_observed(&env, entity, &Position { x: 0, y: 0 }); + world.set_typed(&env, entity, &Moves { remaining: 10 }); + + // 3. Save the ECS world back to Soroban storage + MyFirstGame::save_world(&env, &world); + + entity + } + + /// Moves a player entity in a given direction (0=North, 1=East, 2=South, 3=West). + pub fn move_entity(env: Env, entity_id: u32, direction: u32) { + let mut world = MyFirstGame::load_world(&env); + + let mut pos = world.get_typed::(&env, entity_id).unwrap(); + let mut moves = world.get_typed::(&env, entity_id).unwrap(); + + if moves.remaining == 0 { + panic!("no moves left"); + } + + match direction { + 0 => pos.y += 1, // North + 1 => pos.x += 1, // East + 2 => pos.y -= 1, // South + 3 => pos.x -= 1, // West + _ => panic!("invalid direction"), + } + + moves.remaining -= 1; + + // Apply changes + world.set_typed_observed(&env, entity_id, &pos); + world.set_typed(&env, entity_id, &moves); + + MyFirstGame::save_world(&env, &world); + } + + /// Query a player's current position. + pub fn get_position(env: Env, entity_id: u32) -> Option { + let world = MyFirstGame::load_world(&env); + world.get_typed::(&env, entity_id) + } +} +``` + +This pattern—**Load World -> Query/Modify -> Save World**—is the backbone of every Cougr contract entry point. + +--- + +## 5. Local Testing + +Testing smart contracts on an actual network is slow. Cougr provides a powerful local `GameHarness` to run tests instantly in memory. + +Create a new file `src/test.rs` and add it to your module tree by adding `#[cfg(test)] mod test;` to the very bottom of `src/lib.rs`. + +In `src/test.rs`: + +```rust +#![cfg(test)] + +use super::*; +use cougr_core::test::{GameHarness, Scenario}; +use soroban_sdk::Env; + +#[test] +fn test_spawn_and_move() { + let env = Env::default(); + + // Register our contract using Cougr's test harness + let harness = GameHarness::new(env, MyFirstGame); + + // The macro generated a "MyFirstGameClient" for us automatically + let client = MyFirstGameClient::new(harness.env(), harness.contract_id()); + + // 1. Spawn the entity + let entity_id = client.spawn(); + + let pos = client.get_position(&entity_id).unwrap(); + assert_eq!(pos.x, 0); + assert_eq!(pos.y, 0); + + // 2. Use Cougr's Scenario builder to simulate turns/moves + Scenario::new("move north") + .turns(1) + .run(&harness, |_player, _turn, h| { + let c = MyFirstGameClient::new(h.env(), h.contract_id()); + + // Move North (direction = 0) + c.move_entity(&entity_id, &0); + + let pos = c.get_position(&entity_id).unwrap(); + assert_eq!(pos.x, 0); + assert_eq!(pos.y, 1); + }); +} +``` + +Run your tests to verify your game works locally: + +```bash +cargo test +``` + +If it passes, you are ready to deploy! + +--- + +## 6. Deploying to Testnet + +To deploy, we need to compile our game to a WebAssembly (WASM) binary and use the Stellar CLI. + +> [!TIP] +> If you haven't installed the Stellar CLI yet, check out the [Stellar Quickstart](https://developers.stellar.org/docs/build/smart-contracts/getting-started/deploy-to-testnet). + +**1. Build the WASM file:** +```bash +cargo build --target wasm32-unknown-unknown --release +``` +Your compiled game is now located at `target/wasm32-unknown-unknown/release/my_first_game.wasm`. + +**2. Configure your testnet identity:** +```bash +stellar keys generate alice --network testnet +``` + +**3. Deploy the contract:** +```bash +stellar contract deploy \ + --wasm target/wasm32-unknown-unknown/release/my_first_game.wasm \ + --source alice \ + --network testnet +``` + +If successful, the CLI will return a `C...` contract address. **Congratulations!** Your game is live on the Stellar Testnet. + +--- + +## 7. Next Steps + +You've built and deployed a basic ECS contract. However, real games require more advanced mechanics like access control, hidden information (Fog of War), or multi-contract plugin architectures. + +- **Learn the architecture:** Read [Cougr Patterns](../learn/PATTERNS.md) to understand how to structure larger, production-ready games. +- **Get inspired:** Browse the **Showcase** (like `murdoku` or `battleship`) in the `examples/` directory to see full-stack implementations. diff --git a/cougr-site/src/start/getting-started.md b/cougr-site/src/start/getting-started.md new file mode 100644 index 0000000..5645c5a --- /dev/null +++ b/cougr-site/src/start/getting-started.md @@ -0,0 +1,29 @@ +# Getting Started + +> **This page is synced from the main Cougr repository.** To edit it, open a PR against [`salazarsebas/Cougr`](https://github.com/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 | sh` | +| **Stellar CLI** | `cargo install stellar-cli --features opt` | +| **wasm32 target** | `rustup target add wasm32-unknown-unknown` | + +## Clone and run the starter example + +```bash +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](build-your-first-game.md) for the full sequential tutorial. diff --git a/cougr-site/sync.py b/cougr-site/sync.py new file mode 100644 index 0000000..ab72def --- /dev/null +++ b/cougr-site/sync.py @@ -0,0 +1,105 @@ +#!/usr/bin/env python3 +import os +import re + +# cougr-site/ lives directly under the repo root, so the source docs are +# always right next to this script's own directory. No network clone needed. +SITE_DIR = os.path.dirname(os.path.abspath(__file__)) +REPO_ROOT = os.path.dirname(SITE_DIR) + +# Mapping from source repo path to mdBook src path +MAPPING = { + "docs/start/build-your-first-game.md": "start/build-your-first-game.md", + "ARCHITECTURE.md": "learn/ARCHITECTURE.md", + "docs/PATTERNS.md": "learn/PATTERNS.md", + "docs/ECS_CORE.md": "reference/ECS_CORE.md", + "docs/ACCOUNT_KERNEL.md": "reference/ACCOUNT_KERNEL.md", + "docs/STANDARDS_LAYER.md": "reference/STANDARDS_LAYER.md", + "docs/PRIVACY_MODEL.md": "reference/PRIVACY_MODEL.md", + "docs/FEATURE_FLAGS.md": "reference/FEATURE_FLAGS.md", + "docs/PERFORMANCE.md": "reference/PERFORMANCE.md", + "docs/API_CONTRACT.md": "reference/API_CONTRACT.md", + "docs/COMPATIBILITY_PROMISES.md": "reference/COMPATIBILITY_PROMISES.md", + "docs/MIGRATION_GUIDE.md": "reference/MIGRATION_GUIDE.md", + "CONTRIBUTING.md": "community/CONTRIBUTING.md", + "CHANGELOG.md": "community/CHANGELOG.md", + "SECURITY.md": "community/SECURITY.md", +} + +def sync(): + # Discover adr files dynamically + adr_dir = os.path.join(REPO_ROOT, "docs/adr") + if os.path.exists(adr_dir): + for filename in os.listdir(adr_dir): + if filename.endswith(".md"): + repo_rel = f"docs/adr/{filename}" + mdbook_rel = f"reference/adr/{filename}" + MAPPING[repo_rel] = mdbook_rel + + # Copy files and rewrite links + for repo_rel, mdbook_rel in MAPPING.items(): + src_file = os.path.join(REPO_ROOT, repo_rel) + if not os.path.exists(src_file): + print(f"Warning: {repo_rel} not found in source repo.") + continue + + with open(src_file, "r") as f: + content = f.read() + + content = rewrite_links(content, repo_rel) + + dest_file = os.path.join(SITE_DIR, "src", mdbook_rel) + os.makedirs(os.path.dirname(dest_file), exist_ok=True) + with open(dest_file, "w") as f: + f.write(content) + print(f"Synced {repo_rel} -> src/{mdbook_rel}") + +def rewrite_links(content, current_file_repo_rel): + """ + Finds markdown links and rewrites them if they point to another mapped file. + """ + def replacer(match): + full_match = match.group(0) + link_text = match.group(1) + link_url = match.group(2) + + # Ignore external links, anchors, mailto + if link_url.startswith(("http", "mailto", "#")): + return full_match + + # Split anchor from url + anchor = "" + if "#" in link_url: + link_url, anchor = link_url.split("#", 1) + anchor = "#" + anchor + + if not link_url: + return full_match + + # Normalize target path relative to the repo root + current_dir = os.path.dirname(current_file_repo_rel) + target_repo_rel = os.path.normpath(os.path.join(current_dir, link_url)) + + # Windows paths normpath fix + target_repo_rel = target_repo_rel.replace('\\', '/') + + if target_repo_rel in MAPPING: + # We have a mapping for the target! + # Calculate new relative path in mdBook + current_mdbook_rel = MAPPING[current_file_repo_rel] + target_mdbook_rel = MAPPING[target_repo_rel] + + current_mdbook_dir = os.path.dirname(current_mdbook_rel) + new_rel_path = os.path.relpath(target_mdbook_rel, current_mdbook_dir) + new_rel_path = new_rel_path.replace('\\', '/') + + return f"[{link_text}]({new_rel_path}{anchor})" + + return full_match + + # Regex for standard markdown links: [text](url) + pattern = re.compile(r'\[([^\]]+)\]\(([^)]+)\)') + return pattern.sub(replacer, content) + +if __name__ == "__main__": + sync() diff --git a/docs/start/build-your-first-game.md b/docs/start/build-your-first-game.md new file mode 100644 index 0000000..bc54c8d --- /dev/null +++ b/docs/start/build-your-first-game.md @@ -0,0 +1,261 @@ +# Build Your First Game + +Welcome to Cougr! This tutorial will take you from an empty directory to a fully tested, testnet-deployed game. + +This guide is designed for developers who already know **Rust** but have no prior experience with **Cougr**, **Soroban**, or **Stellar**. By the end, you'll understand how Cougr's Entity-Component-System (ECS) architecture translates into safe, efficient smart contracts. + +We are going to build a simple 2D grid game where a player can spawn into the world and walk in four directions. + +--- + +## 1. Project Setup + +Since we're building a smart contract, we start with a standard Rust library rather than a binary. + +```bash +cargo new --lib my_first_game +cd my_first_game +``` + +Add `cougr-core` and the `soroban-sdk` to your `Cargo.toml`. We enable the `testutils` feature to get access to Cougr's built-in testing harness later. + +```toml +[package] +name = "my_first_game" +version = "0.1.0" +edition = "2021" + +[lib] +crate-type = ["cdylib", "rlib"] + +[dependencies] +soroban-sdk = "25.3.2" +cougr-core = "1.1.0" # or the latest version from crates.io + +[features] +testutils = ["soroban-sdk/testutils", "cougr-core/testutils"] +``` + +--- + +## 2. The Mental Model: ECS on Soroban + +If you've used an ECS in a game engine like Bevy or Unity, you already know the basics: **Entities** are just IDs, **Components** hold data, and **Systems** run logic. + +However, building for a blockchain introduces new constraints you must consider: + +> [!WARNING] +> **Soroban-Specific Constraints** +> +> 1. **Storage is not a normal database:** You cannot freely iterate over millions of rows. State must be loaded into memory, modified, and saved back efficiently. +> 2. **Execution costs money:** Every instruction, memory allocation, and storage write costs "gas". Infinite loops or massive arrays will cause your transaction to exceed resource limits and fail. +> 3. **Instance Storage vs Persistent Storage:** Cougr uses Soroban's "Instance Storage" by default for your hot-loop game state. This means all active gameplay components are loaded in a single read, making operations extremely cheap and fast, but it requires you to be mindful of total state size. + +Cougr abstracts the heavy lifting of storage management, but you still need to write code with these constraints in mind. + +--- + +## 3. Defining Components + +Let's open `src/lib.rs`. First, we clear out the default code and define our game's data. + +We need two components: a `Position` to track where the player is, and `Moves` to track how many steps they have left. + +```rust +#![no_std] + +use cougr_core::game::SorobanGame; +use cougr_core::{impl_component, impl_component_observed, impl_soroban_game}; +use soroban_sdk::{contract, contractimpl, contracttype, Env}; + +// `Position` emits an indexed event on every change (so a UI can watch it) +#[contracttype] +#[derive(Clone, Debug, PartialEq)] +pub struct Position { + pub x: i32, + pub y: i32, +} +impl_component_observed!(Position, "position", Table, { x: i32, y: i32 }); + +// `Moves` is kept private; it doesn't need to emit an event on every step +#[contracttype] +#[derive(Clone, Debug, PartialEq)] +pub struct Moves { + pub remaining: u32, +} +impl_component!(Moves, "moves", Table, { remaining: u32 }); +``` + +Notice the two different macros: +- `impl_component_observed!` tells Cougr to emit a Soroban event every time this component is modified. This is crucial for off-chain clients (like your web frontend) to track movement in real-time without polling the blockchain. +- `impl_component!` is for standard data that doesn't need to be broadcasted to indexers, saving you gas on event emissions. + +--- + +## 4. Writing the Game Contract (Systems) + +Next, we define our contract. In Cougr, the contract acts as the outer shell that loads the ECS world, runs your system logic (the functions), and saves the world back. + +Add this to the bottom of `src/lib.rs`: + +```rust +#[contract] +#[derive(Clone)] +pub struct MyFirstGame; + +// This macro wires up the `load_world` and `save_world` boilerplate. +impl_soroban_game!(MyFirstGame, "world"); + +#[contractimpl] +impl MyFirstGame { + + /// Spawns a new player entity into the world. + pub fn spawn(env: Env) -> u32 { + // 1. Load the ECS world from Soroban storage + let mut world = MyFirstGame::load_world(&env); + + // 2. Spawn an entity and attach our components + let entity = world.spawn_entity(); + world.set_typed_observed(&env, entity, &Position { x: 0, y: 0 }); + world.set_typed(&env, entity, &Moves { remaining: 10 }); + + // 3. Save the ECS world back to Soroban storage + MyFirstGame::save_world(&env, &world); + + entity + } + + /// Moves a player entity in a given direction (0=North, 1=East, 2=South, 3=West). + pub fn move_entity(env: Env, entity_id: u32, direction: u32) { + let mut world = MyFirstGame::load_world(&env); + + let mut pos = world.get_typed::(&env, entity_id).unwrap(); + let mut moves = world.get_typed::(&env, entity_id).unwrap(); + + if moves.remaining == 0 { + panic!("no moves left"); + } + + match direction { + 0 => pos.y += 1, // North + 1 => pos.x += 1, // East + 2 => pos.y -= 1, // South + 3 => pos.x -= 1, // West + _ => panic!("invalid direction"), + } + + moves.remaining -= 1; + + // Apply changes + world.set_typed_observed(&env, entity_id, &pos); + world.set_typed(&env, entity_id, &moves); + + MyFirstGame::save_world(&env, &world); + } + + /// Query a player's current position. + pub fn get_position(env: Env, entity_id: u32) -> Option { + let world = MyFirstGame::load_world(&env); + world.get_typed::(&env, entity_id) + } +} +``` + +This pattern—**Load World -> Query/Modify -> Save World**—is the backbone of every Cougr contract entry point. + +--- + +## 5. Local Testing + +Testing smart contracts on an actual network is slow. Cougr provides a powerful local `GameHarness` to run tests instantly in memory. + +Create a new file `src/test.rs` and add it to your module tree by adding `#[cfg(test)] mod test;` to the very bottom of `src/lib.rs`. + +In `src/test.rs`: + +```rust +#![cfg(test)] + +use super::*; +use cougr_core::test::{GameHarness, Scenario}; +use soroban_sdk::Env; + +#[test] +fn test_spawn_and_move() { + let env = Env::default(); + + // Register our contract using Cougr's test harness + let harness = GameHarness::new(env, MyFirstGame); + + // The macro generated a "MyFirstGameClient" for us automatically + let client = MyFirstGameClient::new(harness.env(), harness.contract_id()); + + // 1. Spawn the entity + let entity_id = client.spawn(); + + let pos = client.get_position(&entity_id).unwrap(); + assert_eq!(pos.x, 0); + assert_eq!(pos.y, 0); + + // 2. Use Cougr's Scenario builder to simulate turns/moves + Scenario::new("move north") + .turns(1) + .run(&harness, |_player, _turn, h| { + let c = MyFirstGameClient::new(h.env(), h.contract_id()); + + // Move North (direction = 0) + c.move_entity(&entity_id, &0); + + let pos = c.get_position(&entity_id).unwrap(); + assert_eq!(pos.x, 0); + assert_eq!(pos.y, 1); + }); +} +``` + +Run your tests to verify your game works locally: + +```bash +cargo test +``` + +If it passes, you are ready to deploy! + +--- + +## 6. Deploying to Testnet + +To deploy, we need to compile our game to a WebAssembly (WASM) binary and use the Stellar CLI. + +> [!TIP] +> If you haven't installed the Stellar CLI yet, check out the [Stellar Quickstart](https://developers.stellar.org/docs/build/smart-contracts/getting-started/deploy-to-testnet). + +**1. Build the WASM file:** +```bash +cargo build --target wasm32-unknown-unknown --release +``` +Your compiled game is now located at `target/wasm32-unknown-unknown/release/my_first_game.wasm`. + +**2. Configure your testnet identity:** +```bash +stellar keys generate alice --network testnet +``` + +**3. Deploy the contract:** +```bash +stellar contract deploy \ + --wasm target/wasm32-unknown-unknown/release/my_first_game.wasm \ + --source alice \ + --network testnet +``` + +If successful, the CLI will return a `C...` contract address. **Congratulations!** Your game is live on the Stellar Testnet. + +--- + +## 7. Next Steps + +You've built and deployed a basic ECS contract. However, real games require more advanced mechanics like access control, hidden information (Fog of War), or multi-contract plugin architectures. + +- **Learn the architecture:** Read [Cougr Patterns](../PATTERNS.md) to understand how to structure larger, production-ready games. +- **Get inspired:** Browse the **Showcase** (like `murdoku` or `battleship`) in the `examples/` directory to see full-stack implementations.