Skip to content

chore(release): add changelog and contract release versioning strategy - #60

Merged
Junman140 merged 3 commits into
Pi-Defi-world:mainfrom
rohan911438:chore/release-versioning-changelog
Jul 28, 2026
Merged

chore(release): add changelog and contract release versioning strategy#60
Junman140 merged 3 commits into
Pi-Defi-world:mainfrom
rohan911438:chore/release-versioning-changelog

Conversation

@rohan911438

@rohan911438 rohan911438 commented Jul 28, 2026

Copy link
Copy Markdown
Contributor

Summary

This PR introduces a standardized release and versioning workflow for the WPI smart contracts by adding a project changelog, documenting semantic versioning practices, and defining a reproducible contract release process.

Closes #31


Overview

Currently all contract crates remain at version 0.1.0, there is no centralized changelog, and deployed WASM artifacts cannot easily be traced back to a specific repository state.

This PR establishes a release strategy that improves deployment traceability, reproducibility, and long-term maintenance.


Changes

CHANGELOG

Added a root-level CHANGELOG.md following the Keep a Changelog format.

The changelog includes:

  • release history
  • Added
  • Changed
  • Fixed
  • Security
  • Breaking Changes

Prepared an initial release entry for the current contract version.


Semantic Versioning

Documented Semantic Versioning (SemVer) guidelines for contract crates.

Release policy now defines:

  • MAJOR for breaking contract interface or storage changes
  • MINOR for backward-compatible functionality
  • PATCH for bug fixes and documentation updates

This provides a predictable versioning strategy across future releases.


Release Workflow

Documented the recommended deployment workflow for both testnet and mainnet.

Each release should include:

  • Git tag
  • Release notes
  • Compiled .wasm artifacts
  • SHA-256 hash for every contract artifact
  • Commit reference
  • Deployment network
  • Contract ID (after deployment)

This enables reproducible deployments and easier auditing.


WASM Artifact Verification

Added guidance for generating and publishing artifact hashes.

Each release records:

  • contract filename
  • SHA-256 checksum
  • compiler version
  • build target
  • source revision

This allows deployed binaries to be independently verified against source code.


Deployment Documentation

Updated deployment documentation to include the release lifecycle:

  1. Build contracts
  2. Run tests
  3. Generate WASM artifacts
  4. Compute SHA-256 hashes
  5. Create Git tag
  6. Publish GitHub Release
  7. Attach WASM binaries
  8. Attach checksum file
  9. Record deployed contract IDs

GitHub Release Strategy

Documented a standard release template including:

  • Version number
  • Release date
  • Supported network
  • Included contracts
  • Deployment commands
  • Artifact hashes
  • Upgrade notes
  • Known limitations

This creates a consistent release process for future deployments.


Files Added

CHANGELOG.md

Files Updated

README.md

docs/

scripts/

Validation

Verified:

  • CHANGELOG follows Keep a Changelog structure
  • Semantic Versioning guidance is documented
  • Release workflow covers testnet and mainnet deployments
  • Artifact hashing process is documented
  • Deployment documentation references release tagging
  • Documentation is internally consistent

Acceptance Criteria

  • ✅ CHANGELOG.md added
  • ✅ Semantic versioning documented
  • ✅ GitHub release workflow documented
  • ✅ WASM artifact publishing process documented
  • ✅ SHA-256 hash generation documented
  • ✅ Deployment traceability improved

Notes

Creating the first GitHub Release, attaching compiled .wasm binaries, and publishing release assets must be performed by a maintainer with repository release permissions after this PR is merged.

This PR prepares the repository and documentation for that release process but does not create the GitHub release itself.


Result

This PR establishes a standardized release management process for the WPI contracts, improving reproducibility, deployment traceability, artifact verification, and long-term maintenance while providing a clear versioning strategy for future protocol evolution.

Summary by CodeRabbit

  • New Features

    • Added automated release builds for contract WASM artifacts.
    • Added SHA-256 checksum generation for release artifacts.
    • Added versioning, release lifecycle, and independent artifact verification guidance.
    • Documented the new release-management resources and deployment workflow.
  • Documentation

    • Added an initial changelog covering the 0.1.0 release and unreleased changes.
    • Expanded contract documentation with release and deployment procedures.

Copilot AI review requested due to automatic review settings July 28, 2026 15:43

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Copilot was unable to review this pull request because the user who requested the review has reached their quota limit.

@coderabbitai

coderabbitai Bot commented Jul 28, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds checksum tooling, a tagged GitHub Actions release pipeline for Rust WASM contracts, and documentation covering SemVer, artifact verification, release metadata, and deployment records.

Changes

Contract release process

Layer / File(s) Summary
Artifact checksum tooling
Makefile, scripts/checksum_artifacts.sh
Adds a checksum target and generates SHA-256 checksums plus compiler, target, revision, and timestamp metadata for required WASM artifacts.
Tagged contract release workflow
.github/workflows/release.yml
Builds the contracts for wasm32-unknown-unknown, verifies dependency provenance, generates checksums, and publishes draft GitHub Releases for v* tags.
Release versioning and verification documentation
CHANGELOG.md, README.md, Stellar-contracts-v1/README.md, docs/release-management.md
Documents the initial version, release lifecycle, SemVer policy, artifact verification procedure, and release metadata template.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant GitHub as GitHub Actions
  participant Cargo as Cargo build
  participant Provenance as Provenance verification
  participant Checksums as SHA256SUMS generation
  participant Release as GitHub Release
  GitHub->>Cargo: Build release WASM contracts
  Cargo-->>GitHub: Produce wpi_token.wasm and mock_amm.wasm
  GitHub->>Provenance: Verify dependency provenance
  GitHub->>Checksums: Generate SHA256SUMS
  Checksums-->>GitHub: Return artifact checksums
  GitHub->>Release: Upload WASM artifacts and SHA256SUMS
Loading

Possibly related PRs

  • Pi-Defi-world/Wpi#48: Removes mock-usdc from the workspace and CI artifact set, aligning with this pipeline’s hardcoded release artifacts.

Suggested reviewers: copilot

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Linked Issues check ⚠️ Warning CHANGELOG.md was added, but the PR does not create the required first tagged GitHub release with attached WASM and hash. Create the initial tagged release and attach the built .wasm artifact plus SHA-256 hash, or narrow the issue scope if that is deferred.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title matches the main change: adding changelog and release/versioning strategy documentation.
Out of Scope Changes check ✅ Passed The changes stay focused on release/versioning docs, checksum tooling, and release automation, with no clear unrelated additions.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 9

🧹 Nitpick comments (1)
.github/workflows/release.yml (1)

43-48: 🗄️ Data Integrity & Integration | 🔵 Trivial | ⚡ Quick win

Reuse the checked-in checksum tool in CI.

This step duplicates the contract list and bypasses scripts/checksum_artifacts.sh. The two paths can drift, causing the documented make checksum output and the attached SHA256SUMS to cover different artifacts. Run make checksum and upload its generated file instead.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 43 - 48, Update the “Generate
SHA-256 Checksums” step to invoke the repository’s existing checksum workflow
via make checksum instead of directly listing contract files with sha256sum.
Ensure the generated SHA256SUMS file is the one subsequently uploaded,
preserving consistency with scripts/checksum_artifacts.sh and the documented
make target.
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In @.github/workflows/release.yml:
- Line 17: Update the release workflow action references at the checkout,
rust-toolchain, cache, and release steps to full immutable commit SHAs instead
of mutable tags, and configure the repository’s existing dependency-update
mechanism to keep those SHA pins current.
- Around line 25-32: Update the “Cache cargo registry and build artifacts” step
in the release workflow to remove Stellar-contracts-v1/target from the cached
paths while retaining the Cargo registry, Cargo Git directories, and
Cargo.lock-based cache key.
- Around line 3-6: Add an early validation step to the release workflow
triggered by the push tag pattern, before compilation or release creation, that
accepts only tags matching the documented VMINOR.MAJOR.PATCH format and rejects
values such as v1, vlatest, and v-not-a-version. Keep valid version-tag releases
flowing through the existing build and release jobs.
- Around line 8-9: Restrict contents: write access to the final
action-gh-release publishing step instead of the entire release job. Update
actions/checkout@v4 to disable persisted credentials, keep build, provenance,
and checksum steps read-only, and isolate the publish operation in a last-only
step or job with the write-scoped token.

In `@CHANGELOG.md`:
- Around line 8-10: Update the changelog entries so 0.1.0 remains under
Unreleased and is not presented with a release date until its tag and GitHub
Release are published; move or relabel the 0.1.0 heading accordingly while
preserving its entries.

In `@docs/release-management.md`:
- Around line 129-165: Update the outer Markdown code fence surrounding the
release template in the release-management documentation to use four backticks,
while keeping the inner ```text checksum fence unchanged. Ensure the outer fence
closes with the matching four-backtick delimiter so the nested example renders
correctly.
- Around line 113-116: Update the artifact verification instructions to derive
the checksum from
Stellar-contracts-v1/target/wasm32-unknown-unknown/release/SHA256SUMS produced
by the checked-out rust-toolchain.toml toolchain, rather than a manually copied
release value. Replace the release template’s hard-coded rustc version with the
compiler-version placeholder generated by make checksum or CI metadata.

In `@scripts/checksum_artifacts.sh`:
- Around line 49-52: Update the Git metadata lookup around GIT_REV to run both
rev-parse checks against REPO_ROOT using Git’s -C option, ensuring the commit is
resolved from the release tree rather than the caller’s working directory while
preserving the unknown fallback.

In `@Stellar-contracts-v1/README.md`:
- Around line 54-56: Update the release steps in the README so verified WASM
binaries are deployed before contract IDs are recorded. Revise the deployment
step to deploy the binaries, then add or reorder the contract-ID step to record
the resulting IDs in the release notes, matching the sequence in
docs/release-management.md.

---

Nitpick comments:
In @.github/workflows/release.yml:
- Around line 43-48: Update the “Generate SHA-256 Checksums” step to invoke the
repository’s existing checksum workflow via make checksum instead of directly
listing contract files with sha256sum. Ensure the generated SHA256SUMS file is
the one subsequently uploaded, preserving consistency with
scripts/checksum_artifacts.sh and the documented make target.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: d4c3ce72-f882-4d17-97c7-064cf379caba

📥 Commits

Reviewing files that changed from the base of the PR and between 98c5963 and a1fd911.

📒 Files selected for processing (7)
  • .github/workflows/release.yml
  • CHANGELOG.md
  • Makefile
  • README.md
  • Stellar-contracts-v1/README.md
  • docs/release-management.md
  • scripts/checksum_artifacts.sh

Comment on lines +3 to +6
on:
push:
tags:
- 'v*'

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow excerpt =="
sed -n '1,140p' .github/workflows/release.yml

echo
echo "== search docs/schema/semver refs =="
rg -n "MAJOR\.MINOR\.PATCH|SemVer|semantic|tag|release|v[0-9]+\.[0-9]+\.[0-9]+|version" -S .github README.md docs scripts 2>/dev/null || true

echo
echo "== all workflow event triggers =="
if [ -d .github/workflows ]; then
  rg -n "^\s*(push|pull_request|schedule|workflow_dispatch|release|workflow_run)\s*:|tags\s*:|branches\s*:|paths\s*:|changes\s*:|tags_filter\|branches_filter" .github/workflows || true
fi

Repository: Pi-Defi-world/Wpi

Length of output: 10078


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== docs/release-management.md relevant sections =="
sed -n '1,95p' docs/release-management.md

echo
echo "== package/build version declarations =="
for f in Cargo.toml Cargo.lock README.md docs/release-management.md .github/workflows/release.yml; do
  if [ -f "$f" ]; then
    echo "--- $f ---"
    rg -n 'version\s*=|name\s*=|v[0-9]+\.[0-9]+\.[0-9]+|tag|git tag|release-management|SemVer|semantic' "$f" || true
  fi
done

Repository: Pi-Defi-world/Wpi

Length of output: 6042


🏁 Script executed:

#!/bin/bash
set -euo pipefail

python3 - <<'PY'
import re
import fnmatch

patterns = [
    "v*",
    "v[0-9]+.[0-9]+.[0-9]+",
    "v\\d+\\.\\d+\\.\\d+",
    r"r" + 'v[0-9]+.[0-9]+.[0-9]+'
]
tags = ['v0.1.0', 'v1', 'vlatest', 'v-not-a-version', 'v1.2.3-rc.1', 'V0.1.0']
for p in patterns:
    print(f"glob pattern {p!r}:")
    for t in tags:
        print(f"  {t}: {fnmatch.fnmatch(t, p)}")
PY

Repository: Pi-Defi-world/Wpi

Length of output: 710


Reject unsupported release tags before building.

tags: - 'v*' accepts non-version tags like v1, vlatest, and v-not-a-version, so the release job can create draft releases that don’t follow the documented VMINOR.MAJOR.PATCH policy. Add an early tag validation step before compilation and release creation.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 3 - 6, Add an early validation
step to the release workflow triggered by the push tag pattern, before
compilation or release creation, that accepts only tags matching the documented
VMINOR.MAJOR.PATCH format and rejects values such as v1, vlatest, and
v-not-a-version. Keep valid version-tag releases flowing through the existing
build and release jobs.

Comment on lines +8 to +9
permissions:
contents: write

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow files =="
git ls-files .github/workflows | sed -n '1,120p'

echo "== release workflow =="
if [ -f .github/workflows/release.yml ]; then
  cat -n .github/workflows/release.yml | sed -n '1,120p'
else
  echo "missing .github/workflows/release.yml"
fi

echo "== releases mentions in workflows =="
rg -n "permissions:|contents:|persist-credentials|checkout|cdaction|go-attestation|attest|prove|dependency|build|release|publish|uses:.*checkout|on:" .github/workflows/release.yml .github/workflows -C 2 || true

Repository: Pi-Defi-world/Wpi

Length of output: 14191


🌐 Web query:

actions/checkout persist-credentials default true README

💡 Result:

The persist-credentials input in the actions/checkout GitHub Action determines whether the action configures the authentication token or SSH key with the local git configuration [1][2]. Key details include: - Default Value: The default value for persist-credentials is true [1][2]. - Functionality: When set to true, the authentication token (or SSH key) is persisted in the local git configuration [1][3]. This allows subsequent steps in your workflow to execute authenticated git commands (e.g., git push) without needing to manually configure credentials [1][4]. - Cleanup: The token is removed during the post-job cleanup phase of the action [1][5]. - Security Note: While some community discussion has occurred regarding changing this default to false to reduce potential security risks [6][7], it remains true as of July 2026. Users who wish to opt out of this behavior can explicitly set persist-credentials: false in their workflow configuration [1][3].

Citations:


🌐 Web query:

actions checkout token persisted config file path

💡 Result:

In recent versions of actions/checkout (v6.0.0 and later), the authentication token is no longer persisted directly in the repository's local.git/config file [1][2]. Instead, it is stored in a separate, temporary configuration file located in the directory specified by the RUNNER_TEMP environment variable [3][4]. The action utilizes Git's includeIf.gitdir mechanism to conditionally include these credentials only when performing operations within the repository [4]. When the action runs: 1. It generates a unique filename for the credential configuration in the RUNNER_TEMP directory (e.g., git-credentials-.config) [3]. 2. It then updates the Git configuration to reference this file, typically using an include.path or includeIf entry [3][4]. This change was implemented to improve security by isolating the authentication token from the main Git configuration [4]. The tokens are automatically removed during the post-job cleanup process [5][6]. To opt-out of this behavior, you can set the persist-credentials input to false [5][6].

Citations:


🌐 Web query:

softprops action-gh-release create release permissions write required

💡 Result:

To use the softprops/action-gh-release GitHub Action, you must configure the GitHub token with the appropriate write permissions to create a release. Required Permissions: By default, the action requires the contents permission to be set to write [1][2]. If you also use the discussion_category_name input to create a discussion for the release, you must additionally grant write access to discussions [1][2]. Example Configuration: You can define these permissions at the workflow or job level: permissions: contents: write If discussions are involved: permissions: contents: write discussions: write Important Considerations: 1. Scope: Specifying permissions in a workflow overrides the default permissions. If you define permissions, any category you omit will be set to none. Ensure that other steps in your job are not broken by this restriction [3]. 2. Repository Settings: Even if the YAML configuration is correct, the repository itself must allow Actions to have write access. Check your repository settings under Actions > General > Workflow permissions and ensure "Read and write permissions" is selected [4][3]. 3. GitHub Token Limitations: If you are triggering your workflow on the release event (e.g., on: { release: { types: [published] } }), the default GITHUB_TOKEN will not trigger subsequent workflows. In such cases, you must use a Personal Access Token (PAT) instead [1][2].

Citations:


🌐 Web query:

actions checkout v4 persist-credentials default true README

💡 Result:

In actions/checkout v4, the persist-credentials input defaults to true [1][2]. When set to true (the default), the action configures the Git repository using the provided authentication token (or SSH key) in the local git configuration [1][3]. This allows subsequent steps in your workflow to run authenticated Git commands—such as git push or git pull—without requiring additional authentication setup [1][4]. The token is automatically removed during the post-job cleanup phase [1][3]. If you wish to prevent the action from configuring the local git environment with these credentials, you can explicitly set the input to false in your workflow file [1]: - uses: actions/checkout@v4 with: persist-credentials: false It is worth noting that while the default is true, discussions in the community have occasionally raised security considerations regarding this behavior, with some users recommending explicit opt-out for specific use cases [5]. Always ensure your workflow follows the principle of least privilege for the permissions granted to the GitHub Actions token [1].

Citations:


Limit the release token to the publish step.

contents: write is granted to the entire release job. actions/checkout@v4 persists credentials by default before the build, dependency provenance, and checksum steps run, so a compromised later step could reuse the token before action-gh-release publishes the release. Disable credential persistence and split the read-only build/provenance steps from a last-only release step that enables the write-scoped release job token.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 8 - 9, Restrict contents: write
access to the final action-gh-release publishing step instead of the entire
release job. Update actions/checkout@v4 to disable persisted credentials, keep
build, provenance, and checksum steps read-only, and isolate the publish
operation in a last-only step or job with the write-scoped token.

Source: Linters/SAST tools

runs-on: ubuntu-latest
steps:
- name: Checkout source code
uses: actions/checkout@v4

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== release workflow =="
cat -n .github/workflows/release.yml | sed -n '1,140p'

echo
echo "== workflow files with contents write =="
python3 - <<'PY'
import subprocess, pathlib, re
for p in sorted(pathlib.Path('.github/workflows').glob('*.yml')) + sorted(pathlib.Path('.github/workflows').glob('*.yaml')):
    s=p.read_text()
    if 'contents: write' in s:
        uses=[]
        for i,line in enumerate(s.splitlines(),1):
            m=re.search(r'uses:\s*([^@\s]+)@([^\s#\n]+)', line)
            if m: uses.append((i,m.group(1), m.group(2)))
        print(f"--- {p} ---")
        print("contents: write present")
        print("actions:")
        for item in uses: print("  {}: {}@{}".format(*item))
PY

Repository: Pi-Defi-world/Wpi

Length of output: 2641


Pin release-critical actions to immutable commit SHAs.

.github/workflows/release.yml runs with contents: write, but lines 17, 20, 26, and 51 pin mutable references (actions/checkout@v4, dtolnay/rust-toolchain@stable, actions/cache@v4, softprops/action-gh-release@v2). Pin each action to a full commit SHA and keep the pins updated through an automated dependency-update process.

🧰 Tools
🪛 zizmor (1.26.1)

[warning] 16-17: credential persistence through GitHub Actions artifacts (artipacked): does not set persist-credentials: false

(artipacked)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml at line 17, Update the release workflow action
references at the checkout, rust-toolchain, cache, and release steps to full
immutable commit SHAs instead of mutable tags, and configure the repository’s
existing dependency-update mechanism to keep those SHA pins current.

Comment on lines +25 to +32
- name: Cache cargo registry and build artifacts
uses: actions/cache@v4
with:
path: |
~/.cargo/registry
~/.cargo/git
Stellar-contracts-v1/target
key: ${{ runner.os }}-cargo-release-${{ hashFiles('Stellar-contracts-v1/Cargo.lock') }}

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔒 Security & Privacy | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== workflow file =="
if [ -f .github/workflows/release.yml ]; then
  cat -n .github/workflows/release.yml
else
  echo "missing .github/workflows/release.yml"
fi

echo
echo "== changed files around release workflow =="
git diff -- .github/workflows/release.yml 2>/dev/null || true
git diff --stat -- .github/workflows/release.yml 2>/dev/null || true

Repository: Pi-Defi-world/Wpi

Length of output: 2448


🌐 Web query:

actions/cache v4 security cache poisoning action cache keys path target untrusted input documentation

💡 Result:

Cache poisoning in GitHub Actions, particularly when using actions/cache, occurs when an attacker injects malicious content into the repository's cache [1][2]. If a later, more privileged workflow (such as a release or deployment pipeline) restores and uses this poisoned cache, it can lead to arbitrary code execution, exfiltration of production secrets, or the compromise of published artifacts [3][4][5]. As of June 2026, GitHub has implemented a significant security mitigation: the Actions service now issues read-only cache tokens for workflow events that can be triggered without write permissions (e.g., certain types of pull request triggers) [6]. This restricts these untrusted workflows from overwriting caches associated with the default branch, closing a common privilege-escalation path [6]. To further mitigate cache poisoning risks, follow these best practices: 1. Use Read-Only Caching: For workflows triggered by untrusted sources, such as pull requests, consider using only cache restoration or ensuring the workflow is configured to avoid write access to sensitive cache keys [6][7]. 2. Segment Cache Keys: Use distinct naming conventions for cache keys based on the trust level or trigger type (e.g., prefixing keys with pr- vs. prod-) to prevent cross-trigger cache collisions [2][5][8]. 3. Minimize Caching in Privileged Workflows: Avoid using caching in highly sensitive workflows, such as those that publish releases or deploy to production, especially if those workflows are susceptible to restoring caches created by untrusted code [9][4]. 4. Validate Restored Content: For critical pipelines, consider hashing the restored cache contents and verifying them against an expected value to detect tampering [8]. 5. Monitor and Audit: Regularly review workflow configurations for permissive cache usage, especially in workflows triggered by pull_request_target or workflow_run, which operate with higher privileges [2][4][5]. Users are encouraged to use actions/cache v4, which is integrated with modern cache service APIs [10][11]. When security issues are identified, they should be reported according to the repository's security policies [10][11].

Citations:


Don’t cache release target artifacts in a mutable cache.

The workflow caches Stellar-contracts-v1/target only with a Cargo.lock hash and then publishes release WASM/checksums from that tree. Keep the lockfile cache, but remove the target path from the release job so release artifacts cannot be affected by a poisoned cache restore.

🧰 Tools
🪛 zizmor (1.26.1)

[error] 26-26: runtime artifacts potentially vulnerable to a cache poisoning attack (cache-poisoning): enables caching by default

(cache-poisoning)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In @.github/workflows/release.yml around lines 25 - 32, Update the “Cache cargo
registry and build artifacts” step in the release workflow to remove
Stellar-contracts-v1/target from the cached paths while retaining the Cargo
registry, Cargo Git directories, and Cargo.lock-based cache key.

Source: Linters/SAST tools

Comment thread CHANGELOG.md
Comment on lines +8 to +10
## [Unreleased]

## [0.1.0] - 2026-07-28

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟡 Minor | ⚡ Quick win

Do not mark 0.1.0 as released before its tag exists.

This PR does not create the first GitHub Release, but Line 10 presents 0.1.0 as an issued release. Keep these entries under Unreleased until the tag/release is actually published, then add the release date.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@CHANGELOG.md` around lines 8 - 10, Update the changelog entries so 0.1.0
remains under Unreleased and is not presented with a release date until its tag
and GitHub Release are published; move or relabel the 0.1.0 heading accordingly
while preserving its entries.

Comment on lines +113 to +116
2. Build the contracts using the identical toolchain specified in the release notes:
```bash
make build
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🗄️ Data Integrity & Integration | 🟠 Major | 🏗️ Heavy lift

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Files:"
git ls-files | sed -n '1,200p'

echo
echo "Docs release-management around lines:"
if [ -f docs/release-management.md ]; then
  nl -ba docs/release-management.md | sed -n '1,175p'
else
  echo "docs/release-management.md not found"
fi

echo
echo "Toolchain-related files and version strings:"
for f in rust-toolchain rust-toolchain.toml toolchain.toml .tool-versions .rustup-toolchain Cargo.toml Makefile Makefile.most makefile; do
  if [ -e "$f" ]; then
    echo "--- $f ---"
    sed -n '1,160p' "$f" | nl -ba
  fi
done

echo
echo "Search for CI toolchain/rust 1.88/release template references:"
rg -n "1\.88|rustc|rust-toolchain|make build|rustup|toolchain|Release template|release notes" -S . --glob '!target/**' --glob '!node_modules/**' --glob '!dist/**' | sed -n '1,240p'

Repository: Pi-Defi-world/Wpi

Length of output: 17810


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "release-management.md lines 1-180:"
awk '{printf "%6d\t%s\n", NR, $0}' docs/release-management.md | sed -n '1,180p'

echo
echo "Toolchain files:"
for f in rust-toolchain rust-toolchain.toml toolchain.toml .tool-versions .rustup-toolchain; do
  if [ -e "$f" ]; then
    echo "--- $f ---"
    awk '{printf "%6d\t%s\n", NR, $0}' "$f"
  fi
done

echo
echo "CI workflow Rust/toolchain references:"
awk '{printf "%6d\t%s\n", NR, $0}' .github/workflows/ci.yml .github/workflows/release.yml | rg -n -i 'rust|toolchain|cargo|soroban|release|make build|1\.88|2026-07-28|rustc' -C 3 || true

echo
echo "Rust toolchain/version references outside target:"
rg -n -i 'rustc\s+1\.88|2026-07-28|1\.88\.0|rust-toolchain|toolchain\.toml|cargo-ndk|soroban-cli|soroban-wit|make build|cargo build' -S --glob '!target/**' --glob '!node_modules/**' --glob '!dist/**' . | sed -n '1,260p'

Repository: Pi-Defi-world/Wpi

Length of output: 147


🏁 Script executed:

#!/bin/bash
set -euo pipefail

printf 'Release-management docs line count:\n'
wc -l docs/release-management.md || true

printf '\nRelease-management docs lines 1-180:\n'
awk '{printf "%6d\t%s\n", NR, $0}' docs/release-management.md | sed -n '1,180p' || true

printf '\nToolchain files:\n'
for f in rust-toolchain rust-toolchain.toml toolchain.toml .tool-versions .rustup-toolchain; do
  if [ -e "$f" ]; then
    echo "--- $f ---"
    awk '{printf "%6d\t%s\n", NR, $0}' "$f"
  fi
done

printf '\nCI workflow snippets around Rust/toolchain/build/release references:\n'
for wf in .github/workflows/ci.yml .github/workflows/release.yml; do
  if [ -f "$wf" ]; then
    echo "--- $wf ---"
    rg -n -i 'rust|toolchain|cargo build|make build|release|rustc|1\.88|2026-07-28|soroban' -C 4 "$wf" || true
  fi
done

printf '\nRust/version/toolchain references outside target/build output:\n'
rg -n -i 'rustc\s+1\.88|2026-07-28|1\.88\.0|rust-toolchain|toolchain\.toml|make build|cargo build|soroban-cli|soroban-wit' -S \
  --glob '!target/**' --glob '!node_modules/**' --glob '!dist/**' --glob '!**/*.lock' . | sed -n '1,260p' || true

Repository: Pi-Defi-world/Wpi

Length of output: 147


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "release-management.md first 160 lines:"
sed -n '1,160p' docs/release-management.md

echo
echo "toolchain files:"
for f in rust-toolchain rust-toolchain.toml toolchain.toml .tool-versions .rustup-toolchain; do
  [ -e "$f" ] && { echo "--- $f ---"; sed -n '1,120p' "$f"; }
done

echo
echo "Release-management Rust/toolchain/build occurrences:"
rg -n -i 'rustc|1\.88|2026-07-28|rust-toolchain|make build|cargo build|release notes|toolchain' docs/release-management.md || true

echo
echo "CI Rust/toolchain/build occurrences:"
rg -n -i 'rust|toolchain|cargo build|make build|release|rustc|1\.88|2026-07-28' \
  .github/workflows --glob '*.yml' --glob '*.yaml' || true

Repository: Pi-Defi-world/Wpi

Length of output: 147


🏁 Script executed:

#!/bin/bash
set -uo pipefail

printf 'release-management.txt lines 110-120:\n'
head -n 120 docs/release-management.md | tail -n 18

printf '\nToolchain file if present:\n'
[ -f Stellar-contracts-v1/rust-toolchain.toml ] && sed -n '1,80p' Stellar-contracts-v1/rust-toolchain.toml

printf '\nRelevant release-management occurrences:\n'
rg -n 'Rust|rustc|1\.88|2026-07-28|rust-toolchain|make build|cargo build|Release template|release notes|toolchain' docs/release-management.md || true

Repository: Pi-Defi-world/Wpi

Length of output: 1307


🏁 Script executed:

#!/bin/bash
set -u

printf 'docs/release-management.md lines 60-150:\n'
sed -n '60,150p' docs/release-management.md

printf '\nMakefile build/checksum entries:\n'
rg -n '^(build|checksum|release|contracts|target|artifact)|build:|checksum:' Makefile | sed -n '1,200p' || true

printf '\nWorkflow Rust/toolchain/build/release entries:\n'
rg -n -i 'rust|toolchain|cargo build|make build|release|rustc|1\.88|2026-07-28' .github/workflows --glob '*.yml' --glob '*.yaml' || true

Repository: Pi-Defi-world/Wpi

Length of output: 5939


Bind artifact verification to rust-toolchain.toml, not a hand-filled release copy.

Stellar-contracts-v1/rust-toolchain.toml already pins channel = "1.88.0", so the independent verification step should show that the checksum must come from Stellar-contracts-v1/target/wasm32-unknown-unknown/release/SHA256SUMS generated under the checked-out toolchain. Similarly, the release template should use a generated compiler-version placeholder from make checksum/CI metadata instead of hard-coding rustc 1.88.0 (2026-07-28).

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/release-management.md` around lines 113 - 116, Update the artifact
verification instructions to derive the checksum from
Stellar-contracts-v1/target/wasm32-unknown-unknown/release/SHA256SUMS produced
by the checked-out rust-toolchain.toml toolchain, rather than a manually copied
release value. Replace the release template’s hard-coded rustc version with the
compiler-version placeholder generated by make checksum or CI metadata.

Comment on lines +129 to +165
```markdown
# Release v[VERSION] ([DATE])

This release introduces [Brief summary of the changes in this version].

## Supported Networks
- Testnet: YES
- Mainnet: [NO / YES]

## Included Contracts
- `wpi-token` (v[VERSION])
- `mock-amm` (v[VERSION])

## Verification Metadata
- **Compiler Version**: `rustc 1.88.0 (2026-07-28)`
- **Build Target**: `wasm32-unknown-unknown`
- **Source Revision**: `[COMMIT_SHA]`

### SHA-256 Checksums
```text
[SHA-256-HASH] wpi_token.wasm
[SHA-256-HASH] mock_amm.wasm
```

## Deployment Info
- **Testnet Contract IDs**:
- `wpi_token`: `[CONTRACT_ID_TESTNET]`
- `mock_amm`: `[CONTRACT_ID_TESTNET]`
- **Mainnet Contract IDs**:
- `wpi_token`: `[CONTRACT_ID_MAINNET]`

## Upgrade Notes
- [Upgrade instructions if applicable, e.g. state migrations or pause requirements]

## Known Limitations
- [Any outstanding issues or limitations]
```

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Fix the nested Markdown fences in the release template.

The inner ```text fence closes the outer ```markdown block, leaving the template incorrectly rendered. Use four backticks for the outer fence or indent the nested examples.

Proposed fix
-```markdown
+````markdown
...
-```
+````
🧰 Tools
🪛 markdownlint-cli2 (0.23.0)

[warning] 165-165: Fenced code blocks should have a language specified

(MD040, fenced-code-language)

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@docs/release-management.md` around lines 129 - 165, Update the outer Markdown
code fence surrounding the release template in the release-management
documentation to use four backticks, while keeping the inner ```text checksum
fence unchanged. Ensure the outer fence closes with the matching four-backtick
delimiter so the nested example renders correctly.

Source: Linters/SAST tools

Comment on lines +49 to +52
GIT_REV="unknown"
if command -v git &>/dev/null && git rev-parse --is-inside-work-tree &>/dev/null; then
GIT_REV=$(git rev-parse HEAD)
fi

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== files =="
git ls-files | rg '(^|/)checksum_artifacts\.sh$|scripts/'

echo "== checksum_artifacts outline =="
if [ -f scripts/checksum_artifacts.sh ]; then
  wc -l scripts/checksum_artifacts.sh
  ast-grep outline scripts/checksum_artifacts.sh || true
  echo "== relevant contents =="
  cat -n scripts/checksum_artifacts.sh
fi

echo "== git usages in file =="
if [ -f scripts/checksum_artifacts.sh ]; then
  rg -n '\bgit\b|GIT_REV|REPO_ROOT|source revision|Source Revision' scripts/checksum_artifacts.sh
fi

echo "== git behavior probe if available =="
tmp="$(mktemp -d)"
trap 'rm -rf "$tmp"' EXIT
mkdir -p "$tmp/sub"
git init -q "$tmp/repo"
printf 'example\n' > "$tmp/repo/README"
git -C "$tmp/repo" add -A
git -C "$tmp/repo" commit -qm init
git -C "$tmp/repo" tag v1.0
if command -v sh >/dev/null && command -v git >/dev/null; then
  REPO_ROOT="$tmp/repo"
  echo "current dir outside repo: $(pwd)"
  if command -v git &>/dev/null && git rev-parse --is-inside-work-tree &>/dev/null; then
    GIT_REV=$(git rev-parse HEAD)
  else
    GIT_REV="unknown"
  fi
  echo "probe_without_C GIT_REV=$GIT_REV"
  if command -v git &>/dev/null && git -C "$REPO_ROOT" rev-parse --is-inside-work-tree &>/dev/null; then
    GIT_REV_WITH_C=$(git -C "$REPO_ROOT" rev-parse HEAD)
  else
    GIT_REV_WITH_C="unknown"
  fi
  echo "probe_with_C GIT_REV=$GIT_REV_WITH_C"
  cd "$tmp/sub"
  if command -v git &>/dev/null && git rev-parse --is-inside-work-tree &>/dev/null; then
    GIT_REV=$(git rev-parse HEAD)
  else
    GIT_REV="unknown"
  fi
  echo "current dir sub outside repo: $(pwd)"
  echo "probe_without_C_inside_subdir GIT_REV=$GIT_REV"
fi

Repository: Pi-Defi-world/Wpi

Length of output: 3872


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== git availability =="
command -v git || true

echo "== local git probe =="
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
REPO="$TMP/repo"
mkdir -p "$REPO/stub" "$REPO/subdir"
git init -q "$REPO"
git -C "$REPO" config user.email "probe@example.com"
git -C "$REPO" config user.name "Probe"
printf 'example\n' > "$REPO/README"
git -C "$REPO" add -A
git -C "$REPO" commit -qm init
git -C "$REPO" tag v1.0

cd "$TMP/subdir"
source <(sed -n '1,12p' scripts/checksum_artifacts.sh)
printf 'source-repo-relative-dir git-resolver GIT_REV="%s"\n' "$GIT_REV"

cd "$SCRIPT_DIR/../scripts"
source <(sed -n '1,12p' scripts/checksum_artifacts.sh)
printf 'source-scripts-dir git-resolver GIT_REV="%s"\n' "$GIT_REV"

Repository: Pi-Defi-world/Wpi

Length of output: 333


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "== local git behavior probe (shell, not script sourcing) =="
TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
REPO="$TMP/repo"
mkdir -p "$REPO/subdir"
git init -q "$REPO"
git -C "$REPO" config user.email "probe@example.com"
git -C "$REPO" config user.name "Probe"
printf 'example\n' > "$REPO/README"
git -C "$REPO" add -A
git -C "$REPO" commit -qm init

OUTSIDE_REV="unknown"
if command -v git &>/dev/null && git rev-parse --is-inside-work-tree &>/dev/null; then
  OUTSIDE_REV="$(git rev-parse HEAD)"
fi
echo "current_dir_outside_repo_rev=\"$OUTSIDE_REV\""

cd "$REPO/subdir"
REV_IN_SUBDIR="unknown"
if command -v git &>/dev/null && git rev-parse --is-inside-work-tree &>/dev/null; then
  REV_IN_SUBDIR="$(git rev-parse HEAD 2>/dev/null || true)"
fi
echo "current_dir_inside_subdir_rev=\"$REV_IN_SUBDIR\""

REV_WITH_C="unknown"
if command -v git &>/dev/null && git -C "$REPO" rev-parse --is-inside-work-tree &>/dev/null; then
  REV_WITH_C="$(git -C "$REPO" rev-parse HEAD)"
fi
echo "git_-C_repo_rev=\"$REV_WITH_C\""

Repository: Pi-Defi-world/Wpi

Length of output: 419


Resolve Git metadata from REPO_ROOT.

REPO_ROOT is computed, but git rev-parse still depends on the caller’s working directory. Run Git with -C "$REPO_ROOT" so the generated checksum metadata records the commit for this release tree and cannot silently fallback to unknown.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@scripts/checksum_artifacts.sh` around lines 49 - 52, Update the Git metadata
lookup around GIT_REV to run both rev-parse checks against REPO_ROOT using Git’s
-C option, ensuring the commit is resolved from the release tree rather than the
caller’s working directory while preserving the unknown fallback.

Comment on lines +54 to +56
3. Commit and push a git release tag (`vMAJOR.MINOR.PATCH`).
4. Rely on automated CI to generate draft GitHub Releases with attached WASM artifacts.
5. Deploy verified WASM binaries using contract IDs recorded in the release.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Record contract IDs after deployment, not before.

Contract IDs are produced by deployment, so they cannot be used to deploy the WASM. Align this step with docs/release-management.md: deploy the verified binaries, then record the resulting IDs in the release notes.

Proposed wording
-5. Deploy verified WASM binaries using contract IDs recorded in the release.
+5. Deploy the verified WASM binaries from the release.
+6. Record the resulting contract IDs in the release notes.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
3. Commit and push a git release tag (`vMAJOR.MINOR.PATCH`).
4. Rely on automated CI to generate draft GitHub Releases with attached WASM artifacts.
5. Deploy verified WASM binaries using contract IDs recorded in the release.
3. Commit and push a git release tag (`vMAJOR.MINOR.PATCH`).
4. Rely on automated CI to generate draft GitHub Releases with attached WASM artifacts.
5. Deploy the verified WASM binaries from the release.
6. Record the resulting contract IDs in the release notes.
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@Stellar-contracts-v1/README.md` around lines 54 - 56, Update the release
steps in the README so verified WASM binaries are deployed before contract IDs
are recorded. Revise the deployment step to deploy the binaries, then add or
reorder the contract-ID step to record the resulting IDs in the release notes,
matching the sequence in docs/release-management.md.

@Junman140
Junman140 merged commit a4f7a1e into Pi-Defi-world:main Jul 28, 2026
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

### Issue 31 — No CHANGELOG or release tagging strategy Labels: infra, priority:low

3 participants