Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion .agents/skills/release-maple/SKILL.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ commit, external effect, and authority provided by the user.
successful release workflow starts separate updater-metadata, Pages
production-branch, and best-effort Zapstore workflows. These sibling
workflows never gate or change the outcome of the core Maple release.
- The same Maple GitHub Release receives four native `maple-proxy` archives and
their checksum manifest. Never create a separate proxy Release or proxy tag;
`/releases/latest` must continue to identify the Maple application release.
- GitHub Release creation does not itself submit the release IPA or AAB to
Apple App Store review or Google Play.

Expand Down Expand Up @@ -122,7 +125,8 @@ gh run watch RELEASE_RUN_ID \
```

Stay with every platform build, signature/canonical proof, artifact upload,
updater `latest.json`, aggregate verification, and verification-guide step.
the four native proxy builds and their published-asset verification, updater
`latest.json`, aggregate verification, and verification-guide step.
Packaging success alone is not runtime smoke; inspect the workflow's actual
verification and attestation results.

Expand Down Expand Up @@ -171,6 +175,11 @@ Verify the published release and its assets:
```bash
gh release view "$tag" --repo OpenSecretCloud/Maple \
--json tagName,name,isDraft,isPrerelease,publishedAt,targetCommitish,url,assets

mkdir -p artifacts
gh release download "$tag" --repo OpenSecretCloud/Maple --dir artifacts
nix develop --no-update-lock-file .#ci -c \
./scripts/ci/verify-release-artifacts.sh artifacts proxy
```

Zapstore starts only after `Release` succeeds and is strictly best effort. Its
Expand Down
39 changes: 39 additions & 0 deletions .github/workflows/proxy-rust.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ on:
- "proxy/src/**"
- "proxy/tests/**"
- "proxy/examples/**"
- "scripts/ci/proxy-release.sh"
- "sdk/rust/Cargo.toml"
- "sdk/rust/src/**"
- "sdk/rust/assets/**"
Expand All @@ -34,6 +35,7 @@ on:
- "proxy/src/**"
- "proxy/tests/**"
- "proxy/examples/**"
- "scripts/ci/proxy-release.sh"
- "sdk/rust/Cargo.toml"
- "sdk/rust/src/**"
- "sdk/rust/assets/**"
Expand Down Expand Up @@ -73,3 +75,40 @@ jobs:
RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps --all-features
cargo machete
'

proxy-native-release:
name: proxy-native-release (${{ matrix.archive }})
runs-on: ${{ matrix.runner }}
timeout-minutes: 20
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
archive: maple-proxy-linux-x86_64.tar.gz
- runner: ubuntu-24.04-arm
archive: maple-proxy-linux-aarch64.tar.gz
- runner: macos-26-xlarge
archive: maple-proxy-macos-aarch64.tar.gz
- runner: windows-2025
archive: maple-proxy-windows-x86_64.zip
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # was v4
with:
persist-credentials: false

- name: Install Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # was stable
with:
toolchain: 1.89.0

- name: Cache proxy Rust dependencies
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # was v2
with:
workspaces: proxy -> target
add-rust-environment-hash-key: "false"
key: native-release-${{ matrix.archive }}-${{ hashFiles('proxy/Cargo.lock') }}

- name: Rehearse native proxy release asset
shell: bash
run: ./scripts/ci/proxy-release.sh proxy-release-rehearsal "${{ matrix.archive }}"
14 changes: 14 additions & 0 deletions .github/workflows/release-gates-tests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,17 @@ on:
- ".github/workflows/release.yml"
- ".github/workflows/release-gates-tests.yml"
- ".github/workflows/pages-production.yml"
- ".github/workflows/proxy-rust.yml"
- ".github/workflows/zapstore-publish.yml"
- "scripts/ci/classify-app-release.sh"
- "scripts/ci/proxy-release.sh"
- "scripts/ci/test-proxy-release-artifacts.sh"
- "scripts/ci/test-release-gates.sh"
- "scripts/ci/validate-release-version.sh"
- "scripts/ci/verify-release-artifacts.sh"
- "proxy/Cargo.toml"
- "proxy/Cargo.lock"
- "proxy/src/**"
- "frontend/package.json"
- "frontend/src-tauri/Cargo.toml"
- "frontend/src-tauri/tauri.conf.json"
Expand All @@ -21,10 +28,17 @@ on:
- ".github/workflows/release.yml"
- ".github/workflows/release-gates-tests.yml"
- ".github/workflows/pages-production.yml"
- ".github/workflows/proxy-rust.yml"
- ".github/workflows/zapstore-publish.yml"
- "scripts/ci/classify-app-release.sh"
- "scripts/ci/proxy-release.sh"
- "scripts/ci/test-proxy-release-artifacts.sh"
- "scripts/ci/test-release-gates.sh"
- "scripts/ci/validate-release-version.sh"
- "scripts/ci/verify-release-artifacts.sh"
- "proxy/Cargo.toml"
- "proxy/Cargo.lock"
- "proxy/src/**"
- "frontend/package.json"
- "frontend/src-tauri/Cargo.toml"
- "frontend/src-tauri/tauri.conf.json"
Expand Down
143 changes: 142 additions & 1 deletion .github/workflows/release.yml
Original file line number Diff line number Diff line change
Expand Up @@ -649,6 +649,146 @@ jobs:
frontend/src-tauri/target/reproducibility/web-final.sha256 \
--clobber

build-proxy:
name: Build proxy (${{ matrix.archive }})
needs: classify-app-release
runs-on: ${{ matrix.runner }}
timeout-minutes: 20
permissions:
contents: read
strategy:
fail-fast: false
matrix:
include:
- runner: ubuntu-24.04
archive: maple-proxy-linux-x86_64.tar.gz
- runner: ubuntu-24.04-arm
archive: maple-proxy-linux-aarch64.tar.gz
- runner: macos-26-xlarge
archive: maple-proxy-macos-aarch64.tar.gz
- runner: windows-2025
archive: maple-proxy-windows-x86_64.zip
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # was v4
with:
ref: ${{ needs.classify-app-release.outputs.release_sha }}
persist-credentials: false

- name: Install Rust
uses: dtolnay/rust-toolchain@29eef336d9b2848a0b548edc03f92a220660cdb8 # was stable
with:
toolchain: 1.89.0

- name: Cache proxy Rust dependencies
uses: Swatinem/rust-cache@e18b497796c12c097a38f9edb9d0641fb99eee32 # was v2
with:
workspaces: proxy -> target
add-rust-environment-hash-key: "false"
key: release-${{ matrix.archive }}-${{ hashFiles('proxy/Cargo.lock') }}

- name: Build and package native proxy binary
shell: bash
run: ./scripts/ci/proxy-release.sh proxy-release-assets "${{ matrix.archive }}"

- name: Upload native proxy binary
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # was v4
with:
name: proxy-release-${{ matrix.archive }}
path: proxy-release-assets/${{ matrix.archive }}
if-no-files-found: error
retention-days: 7

publish-proxy-release-artifacts:
needs:
- classify-app-release
- build-proxy
runs-on: ubuntu-latest
permissions:
contents: write
id-token: write
attestations: write
artifact-metadata: write
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # was v4
with:
ref: ${{ needs.classify-app-release.outputs.release_sha }}
persist-credentials: false

- name: Download native proxy binaries
uses: actions/download-artifact@d3f86a106a0bac45b974a628896c90dbdf5c8093 # was v4
with:
pattern: proxy-release-*
path: proxy-release-assets
merge-multiple: true

- name: Finalize and verify proxy release assets
run: |
set -euo pipefail
assets=(
maple-proxy-linux-aarch64.tar.gz
maple-proxy-linux-x86_64.tar.gz
maple-proxy-macos-aarch64.tar.gz
maple-proxy-windows-x86_64.zip
)
(
cd proxy-release-assets
sha256sum "${assets[@]}" > maple-proxy-release-final.sha256
)
./scripts/ci/verify-release-artifacts.sh proxy-release-assets proxy

attested_assets=(
proxy-release-assets/maple-proxy-linux-aarch64.tar.gz
proxy-release-assets/maple-proxy-linux-x86_64.tar.gz
proxy-release-assets/maple-proxy-macos-aarch64.tar.gz
proxy-release-assets/maple-proxy-windows-x86_64.zip
proxy-release-assets/maple-proxy-release-final.sha256
)
sha256sum "${attested_assets[@]}" > proxy-release-attestation.sha256
cat proxy-release-assets/maple-proxy-release-final.sha256

- name: Attest proxy release assets
uses: actions/attest@281a49d4cbb0a72c9575a50d18f6deb515a11deb # was v4
with:
subject-checksums: proxy-release-attestation.sha256

- name: Upload proxy assets to the Maple release
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ needs.classify-app-release.outputs.tag }}
run: |
set -euo pipefail
gh release upload "${RELEASE_TAG}" \
proxy-release-assets/maple-proxy-linux-aarch64.tar.gz \
proxy-release-assets/maple-proxy-linux-x86_64.tar.gz \
proxy-release-assets/maple-proxy-macos-aarch64.tar.gz \
proxy-release-assets/maple-proxy-windows-x86_64.zip \
proxy-release-assets/maple-proxy-release-final.sha256 \
--clobber

verify-proxy-release-artifacts:
needs:
- classify-app-release
- publish-proxy-release-artifacts
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- uses: actions/checkout@34e114876b0b11c390a56381ad16ebd13914f8d5 # was v4
with:
ref: ${{ needs.classify-app-release.outputs.release_sha }}
persist-credentials: false

- name: Download release artifacts
env:
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
RELEASE_TAG: ${{ needs.classify-app-release.outputs.tag }}
run: |
mkdir -p artifacts
gh release download "${RELEASE_TAG}" -D artifacts

- name: Verify published proxy release assets
run: ./scripts/ci/verify-release-artifacts.sh artifacts proxy

verify-android-release-artifacts:
needs:
- classify-app-release
Expand Down Expand Up @@ -864,6 +1004,7 @@ jobs:
- build-web
- update-latest-json
- verify-android-release-artifacts
- verify-proxy-release-artifacts
runs-on: macos-26-xlarge
permissions:
contents: read
Expand Down Expand Up @@ -906,7 +1047,7 @@ jobs:
gh release download "${RELEASE_TAG}" -D artifacts

- name: Verify release artifact reproducibility proofs
run: nix develop --no-update-lock-file .#ci -c ./scripts/ci/verify-release-artifacts.sh artifacts macos windows ios web latest-json
run: nix develop --no-update-lock-file .#ci -c ./scripts/ci/verify-release-artifacts.sh artifacts macos windows ios web latest-json proxy
env:
MAPLE_ENFORCE_IOS_SIGNED_REPRODUCIBILITY: "1"

Expand Down
3 changes: 2 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -200,7 +200,8 @@ generated output opportunistically.
Release preparation and publication are production actions. A push to
`master` that changes classified Maple app inputs starts production-shaped
signed workflows and can upload an iOS build to TestFlight; creating a GitHub
Release always starts the complete release pipeline and downstream publication.
Release always starts the complete release pipeline, attaches the four native
`maple-proxy` archives to that same release, and starts downstream publication.
Do not use either as routine validation.

Use `.agents/skills/release-maple/` for version parity, tag safety, workflow
Expand Down
4 changes: 4 additions & 0 deletions flake.nix
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,10 @@
git
jq
python3
ripgrep
gnutar
unzip
zip
yq-go
];
src = ./.;
Expand Down
13 changes: 13 additions & 0 deletions proxy/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,19 @@ Environment (TEE) processing.

### As a Binary

Every Maple GitHub Release includes native proxy archives for Linux x86_64,
Linux ARM64, Apple Silicon macOS, and Windows x86_64. The stable download URLs
use the ordinary Maple release, for example:

```bash
curl -LO https://github.com/OpenSecretCloud/Maple/releases/latest/download/maple-proxy-linux-x86_64.tar.gz
curl -LO https://github.com/OpenSecretCloud/Maple/releases/latest/download/maple-proxy-release-final.sha256
sha256sum --check --ignore-missing maple-proxy-release-final.sha256
```

There is no separate proxy GitHub Release or proxy release tag. To build from
source instead:

```bash
git clone https://github.com/OpenSecretCloud/Maple.git
cd Maple/proxy
Expand Down
1 change: 1 addition & 0 deletions proxy/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ pub const DEFAULT_STREAM_IDLE_TIMEOUT_SECS: u64 = 300;
#[derive(Parser, Debug, Clone)]
#[command(name = "maple-proxy")]
#[command(about = "Lightweight OpenAI-compatible proxy server for Maple/OpenSecret")]
#[command(version)]
pub struct Config {
/// Host to bind the server to
#[arg(long, env = "MAPLE_HOST", default_value = "127.0.0.1")]
Expand Down
Loading
Loading