diff --git a/README.md b/README.md index a4dde62..e3701cb 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,9 @@ cargo build --release ``` ```bash +# Run the offline demo (inspect, spec, diff, compat, fingerprint) +bash demo/run-demo.sh + # Inspect an artifact (JSON) stellar-contract-platform inspect contract.wasm --json @@ -83,13 +86,17 @@ Early but practical. The project focuses on contract intelligence, compatibility ## Documentation +- [Why Observatory](docs/WHY_OBSERVATORY.md) - [Architecture](docs/architecture.md) - [Getting started](docs/getting-started.md) +- [Installation](docs/installation.md) - [CLI reference](docs/cli.md) - [Compatibility](docs/compatibility.md) - [Verification](docs/verification.md) +- [Demo](demo/README.md) - [Roadmap](docs/roadmap.md) - [Drips readiness and appeal checklist](docs/DRIPS_READINESS.md) +- [Appeal summary](docs/APPEAL.md) ## License diff --git a/crates/observatory-testutil/examples/make_demo_fixtures.rs b/crates/observatory-testutil/examples/make_demo_fixtures.rs new file mode 100644 index 0000000..5cf7e88 --- /dev/null +++ b/crates/observatory-testutil/examples/make_demo_fixtures.rs @@ -0,0 +1,50 @@ +//! Generate the deterministic WASM fixtures used by `demo/`. +//! +//! Run from the repository root: +//! +//! ```bash +//! cargo run -p observatory-testutil --example make_demo_fixtures +//! ``` +//! +//! The fixtures are checked in so the demo does not need to rebuild them. + +use std::fs; + +use observatory_testutil::module_with_spec; +use observatory_testutil::spec::{spec_function, spec_struct, ty_udt}; +use stellar_xdr::ScSpecTypeDef; + +fn main() { + let old = vec![ + spec_function( + "transfer", + &[("to", ty_udt("Recipient")), ("amount", ScSpecTypeDef::I128)], + Some(ScSpecTypeDef::Bool), + ), + spec_function( + "balance", + &[("owner", ty_udt("Recipient"))], + Some(ScSpecTypeDef::I128), + ), + spec_struct("Recipient", &[("address", ScSpecTypeDef::Address)]), + ]; + + let new = vec![ + spec_function( + "transfer", + &[("to", ty_udt("Recipient")), ("amount", ScSpecTypeDef::I128)], + Some(ScSpecTypeDef::I128), + ), + spec_function( + "mint", + &[("to", ty_udt("Recipient")), ("amount", ScSpecTypeDef::I128)], + None, + ), + spec_struct("Recipient", &[("address", ScSpecTypeDef::Address)]), + ]; + + fs::create_dir_all("demo/fixtures").expect("create demo/fixtures"); + fs::write("demo/fixtures/old.wasm", module_with_spec(&old)).expect("write old.wasm"); + fs::write("demo/fixtures/new.wasm", module_with_spec(&new)).expect("write new.wasm"); + println!("wrote demo/fixtures/old.wasm and demo/fixtures/new.wasm"); +} diff --git a/demo/README.md b/demo/README.md new file mode 100644 index 0000000..61d2455 --- /dev/null +++ b/demo/README.md @@ -0,0 +1,65 @@ +# Contract intelligence demo + +A short, offline tour of the Observatory using two deterministic WASM fixtures. + +- `old.wasm` — `transfer(to, amount) -> bool`, `balance(owner) -> i128`, and a + `Recipient` struct. +- `new.wasm` — `transfer` now returns `i128`, `balance` was removed, and `mint` + was added. + +The fixtures are generated by the checked-in example: + +```bash +cargo run -p observatory-testutil --example make_demo_fixtures +``` + +## Run + +```bash +bash demo/run-demo.sh +``` + +or on Windows: + +```powershell +pwsh demo/run-demo.ps1 +``` + +If `stellar-contract-platform` is not on `PATH`, the script uses +`cargo run -p observatory-cli --`. + +## What it shows + +1. `doctor` — tool and capability report. +2. `inspect --json` — bounded WASM metadata and the parsed interface. +3. `spec` — functions, structs, and the declared signatures. +4. `diff` — breaking, non-breaking, and informational changes. +5. `compat` — the compatibility decision and the reasons for it. +6. `fingerprint --json` — artifact and interface SHA-256 values. + +## Expected output (abridged) + +```text +$ stellar-contract-platform diff demo/fixtures/old.wasm demo/fixtures/new.wasm +changes: 2 breaking, 1 non-breaking, 0 informational +! function::balance: function `balance` was removed +! function::transfer: return type changed from `bool` to `i128` ++ function::mint: function `mint` was added +``` + +```text +$ stellar-contract-platform compat demo/fixtures/old.wasm demo/fixtures/new.wasm +status: incompatible + breaking function `balance` was removed + breaking return type changed from `bool` to `i128` + note function `mint` was added +``` + +`compat` exits non-zero when the result is incompatible. That is the intended +CI behavior, so the demo reports it as an expected result. + +## Reproducing the fixtures + +The example uses the same `contractspecv0` builders as the test suite. It does +not execute WASM and does not need network access. The generated `.wasm` files +are committed so the demo works from a fresh clone. diff --git a/demo/fixtures/new.wasm b/demo/fixtures/new.wasm new file mode 100644 index 0000000..13567ed Binary files /dev/null and b/demo/fixtures/new.wasm differ diff --git a/demo/fixtures/old.wasm b/demo/fixtures/old.wasm new file mode 100644 index 0000000..7db429e Binary files /dev/null and b/demo/fixtures/old.wasm differ diff --git a/demo/run-demo.ps1 b/demo/run-demo.ps1 new file mode 100644 index 0000000..5e05cc7 --- /dev/null +++ b/demo/run-demo.ps1 @@ -0,0 +1,43 @@ +$ErrorActionPreference = "Stop" + +Set-Location (Join-Path $PSScriptRoot "..") + +function Invoke-Observatory { + param( + [Parameter(ValueFromRemainingArguments = $true)] + [string[]] $Arguments + ) + + if (Get-Command stellar-contract-platform -ErrorAction SilentlyContinue) { + & stellar-contract-platform @Arguments + } elseif (Test-Path "target/debug/stellar-contract-platform.exe") { + & "target/debug/stellar-contract-platform.exe" @Arguments + } else { + & cargo run -q -p observatory-cli -- @Arguments + } +} + +Write-Host "== doctor" +Invoke-Observatory doctor + +Write-Host "`n== inspect" +Invoke-Observatory inspect demo/fixtures/new.wasm --json + +Write-Host "`n== spec" +Invoke-Observatory spec demo/fixtures/new.wasm + +Write-Host "`n== diff" +Invoke-Observatory diff demo/fixtures/old.wasm demo/fixtures/new.wasm + +Write-Host "`n== compat (non-zero exit is expected for incompatible changes)" +$compatExit = 0 +try { + Invoke-Observatory compat demo/fixtures/old.wasm demo/fixtures/new.wasm + $compatExit = $LASTEXITCODE +} catch { + $compatExit = $LASTEXITCODE +} +Write-Host "(compat exit code: $compatExit)" + +Write-Host "`n== fingerprint" +Invoke-Observatory fingerprint demo/fixtures/new.wasm --json diff --git a/demo/run-demo.sh b/demo/run-demo.sh new file mode 100644 index 0000000..243df07 --- /dev/null +++ b/demo/run-demo.sh @@ -0,0 +1,42 @@ +#!/usr/bin/env bash +set -u + +cd "$(dirname "$0")/.." + +run() { + if command -v stellar-contract-platform >/dev/null 2>&1; then + stellar-contract-platform "$@" + elif [ -x target/debug/stellar-contract-platform ]; then + target/debug/stellar-contract-platform "$@" + elif [ -x target/debug/stellar-contract-platform.exe ]; then + target/debug/stellar-contract-platform.exe "$@" + elif command -v cargo >/dev/null 2>&1; then + cargo run -q -p observatory-cli -- "$@" + else + echo "error: neither stellar-contract-platform nor cargo was found on PATH" >&2 + exit 1 + fi +} + +echo "== doctor" +run doctor + +echo +echo "== inspect" +run inspect demo/fixtures/new.wasm --json + +echo +echo "== spec" +run spec demo/fixtures/new.wasm + +echo +echo "== diff" +run diff demo/fixtures/old.wasm demo/fixtures/new.wasm + +echo +echo "== compat (non-zero exit is expected for incompatible changes)" +run compat demo/fixtures/old.wasm demo/fixtures/new.wasm || true + +echo +echo "== fingerprint" +run fingerprint demo/fixtures/new.wasm --json diff --git a/docs/APPEAL.md b/docs/APPEAL.md new file mode 100644 index 0000000..b055368 --- /dev/null +++ b/docs/APPEAL.md @@ -0,0 +1,80 @@ +# Drips Wave Appeal Summary + +This page prepares an appeal for a rejected repository application. It does not +guarantee reconsideration. Appeals are decided by the Stellar Wave organizers. + +## Before submitting + +1. Open **Maintainers → Orgs and Repos** in the Drips Wave app. +2. Confirm the status of `AyinkxLab/stellar-contract-platform`: + - **Pending** — wait; there is nothing to appeal yet. + - **Approved** — add issues from the dashboard. + - **Rejected** — note the date and any stated reason. +3. Timing rules: + - First appeal: **no earlier than two weeks after rejection**. + - Declined appeal: **one-month cooldown**. + - Maximum **three appeals** per repository. +4. Submit **only through the app**; email/Discord appeals are ignored. + +## What changed since the last review + +| Concern | Change | Evidence | +| ------- | ------ | -------- | +| CI was red | MSRV raised to 1.88; `serde_yml` replaced with `serde_yaml_ng`; RustSec clean | CI and `Dependency Security Audit` on `main` | +| Docs pointed at the old owner | Repository, install, and Wave links now use `AyinkxLab/...` | README, `Cargo.toml`, `docs/installation.md`, `docs/WAVE_BOARD.md` | +| Docs claimed 130 issues and CI success | Counts and CI status updated; completed issues closed | `docs/PROJECT_STATUS.md`, `docs/FINAL_AUDIT.md`, `docs/ISSUE_BACKLOG.md` | +| Wave board contained completed work | #9, #102, #112 closed; board rebuilt with open, independent issues | `docs/WAVE_BOARD.md` | +| No installable artifact | Tag-driven release workflow; Linux/macOS/Windows archives with SHA256 | `v0.1.0` release | +| Possible overlap with other repos | Scope boundary documented | `docs/WHY_OBSERVATORY.md` | + +## Short appeal text (adapt as needed) + +> Since the previous review, Stellar Contract Observatory has changed in five +> concrete ways: +> +> 1. **CI is green.** The MSRV is now Rust 1.88, and the unmaintained +> `serde_yml`/`noyalib` dependency was replaced with `serde_yaml_ng`. Format, +> Clippy, tests on Linux/Windows/macOS, docs, coverage, MSRV, and the RustSec +> audit all pass on `main`. +> 2. **The docs match the repository.** Install and Wave links now use +> `AyinkxLab/stellar-contract-platform`; test and issue counts are current. +> 3. **The backlog is accurate.** Completed issues #9, #102, and #112 were +> closed. The curated Wave board contains 20 open, independent, unimplemented +> issues. +> 4. **There is a release.** `v0.1.0` publishes Linux, macOS, and Windows +> archives with SHA256 checksums. +> 5. **The scope is distinct.** This is a contract-intelligence layer for +> pre-deployment safety: inspect, fingerprint, diff, and verify compiled +> Soroban artifacts. It is not an AI assistant, an XDR/RPC devkit, or a +> source-level vulnerability scanner. +> +> Evidence: +> - Repository: https://github.com/AyinkxLab/stellar-contract-platform +> - CI: https://github.com/AyinkxLab/stellar-contract-platform/actions +> - Release: https://github.com/AyinkxLab/stellar-contract-platform/releases/tag/v0.1.0 +> - Status: https://github.com/AyinkxLab/stellar-contract-platform/blob/main/docs/PROJECT_STATUS.md +> - Scope: https://github.com/AyinkxLab/stellar-contract-platform/blob/main/docs/WHY_OBSERVATORY.md +> - Wave board: https://github.com/AyinkxLab/stellar-contract-platform/blob/main/docs/WAVE_BOARD.md + +If the review cited a specific concern, answer it first and link the change. + +## Contribution integrity + +Do **not** present commits from maintainer-controlled accounts as independent +external contributions. Reviewers can correlate account ownership, email +domains, and activity patterns. If there are no genuine independent contributors +yet, say so and describe the outreach plan. + +## Do not claim + +- That the repository is approved, funded, or guaranteed points. +- That crates.io packages exist. +- That the platform layer is a hardened production service. +- That the tool proves a contract is secure. +- That the repository has significant external adoption. + +## Still worth doing + +- Publish crates to crates.io (16-crate dependency order; separate workflow). +- Get genuinely independent contributors or documented real usage. +- Add live RPC transport and SSRF hardening (#13, #58). diff --git a/docs/DRIPS_READINESS.md b/docs/DRIPS_READINESS.md index 26afd9c..ae54b5f 100644 --- a/docs/DRIPS_READINESS.md +++ b/docs/DRIPS_READINESS.md @@ -10,6 +10,32 @@ artifacts, parsing and fingerprinting contract interfaces, classifying interface changes, evaluating compatibility policies, and verifying deployed artifact identity. It includes a CLI and an API/platform layer. +## Current readiness snapshot (2026-10-28) + +- **MSRV:** Rust 1.88, tested in CI (`MSRV (1.88.0)`). +- **Dependencies:** `serde_yml` replaced with `serde_yaml_ng`; `noyalib` is no + longer present. `cargo audit` reports 0 vulnerabilities (one allowed, + non-vulnerability warning for the unmaintained `unsafe-libyaml`). +- **CI:** Format, Clippy, tests on Linux/Windows/macOS, docs, coverage, MSRV, and + the RustSec audit are green on `main` after the readiness PR. +- **Release:** a tag-driven `Release` workflow builds Linux x86_64, macOS arm64, + and Windows x86_64 archives with SHA256 checksums. +- **Backlog:** 123 open issues; the curated [Wave board](WAVE_BOARD.md) has 20 + open, independent, unimplemented issues (2,700 points). +- **Docs:** repository, install, and Wave links use `AyinkxLab/...`; completed + issues #9, #102, and #112 are closed and removed from the board. +- **Positioning:** [Why Observatory](WHY_OBSERVATORY.md) documents the boundary + with `ai-code-assistant`, `stellar-devkit`, and `soroban-security-scanner`. +- **Not done:** crates.io publication, live RPC transport, persistence, SDKs, + webhooks, and a composite GitHub Action. + +## Contribution integrity + +Do not count commits from accounts controlled by the maintainer as independent +external contributions. Reviewers can correlate account ownership and activity +patterns, and sockpuppeting is a Wave terms violation. If there are no genuinely +independent contributors yet, say so and describe the outreach plan instead. + ## Verified implementation and boundaries Implemented capabilities are tracked in [Project Status](PROJECT_STATUS.md) and diff --git a/docs/roadmap.md b/docs/roadmap.md index 4249293..2069193 100644 --- a/docs/roadmap.md +++ b/docs/roadmap.md @@ -10,12 +10,12 @@ GitHub issues. - Deployed WASM retrieval (`LedgerKeyContractCode`) and interface comparison of local vs. deployed code. - Rename detection in the diff engine. -- Interface diff output formats beyond text/JSON. ## Medium term - GitHub Action and an `observatory.yml` configuration schema. -- Report generation (Markdown) for inspection, diff, and compatibility. +- Markdown report generation for inspection and compatibility results (the diff + renderer already exists). - Additional hash algorithms / selectable fingerprints. - More audit rules, each with a documented rationale. @@ -25,7 +25,8 @@ GitHub issues. comparison. - Multi-provider RPC support and caching. - Fuzzing targets for the WASM, spec, event, and diff parsers. -- crates.io packaging and release automation. +- crates.io packaging for the workspace (the tag-driven binary release workflow + is already in place). ## Non-goals