--- name: develop-maple-proxy description: Develop and review the maple-proxy Rust crate, binary, container, and OpenAI-compatible HTTP behavior under Maple's proxy directory. Use for proxy APIs, configuration, authentication, CORS, attested OpenSecret transport, tests, container builds, package versions, or an explicitly authorized crates.io or GHCR publishing handoff; use develop-maple for the Tauri lifecycle wrapper alone. --- # Develop Maple Proxy Work from the `MaplePrivacyLabs/Maple` repository root; the component source is under `proxy/`. Read the repository-root `AGENTS.md`, `proxy/README.md`, affected source and tests, and the root `.github/workflows/proxy-*.yml` files relevant to the change. The source is part of Maple but keeps distinct public package and runtime boundaries: - `proxy/` builds the `maple-proxy` crate and binary. - `proxy/Cargo.toml` uses a compatible `maple-sdk` registry requirement; `proxy/Cargo.lock` selects the standalone binary's version. Local SDK links are also supported during active development. - Research desktop and Maple Agent consume the in-tree proxy library and choose their SDK versions independently in their own Cargo manifests/locks. iOS and Android do not compile Research's proxy. - `apps/maple-research/frontend/src-tauri/src/proxy.rs` owns Maple's account-scoped listener, configuration, key storage, and lifecycle around the library. Do not move that application behavior into the reusable crate incidentally. Follow the [SDK consumer version policy](../../../docs/sdk-publishing.md#consumer-version-policy). Keep the embedded proxy and its host on the same SDK source/version; avoid exact-pinning the reusable library in a way that forces all hosts to upgrade. Do not commit, push, open a PR, publish, tag, release, or change live infrastructure unless the user authorizes that action. ## Keep validation and routing aligned Run the credential-free proxy checks through its pinned shell: ```sh nix develop --no-update-lock-file ./proxy -c bash -lc ' set -euo pipefail cd proxy cargo fmt --all -- --check cargo clippy --locked --all-targets --all-features -- -D warnings cargo test --locked --all-features RUSTDOCFLAGS="-D warnings" cargo doc --locked --no-deps --all-features cargo machete ' ``` The repository pre-commit hook runs exactly these commands through `proxy/.githooks/pre-commit` in the proxy shell when proxy files are staged. For Rust SDK or dependency-wiring changes, also prove Research resolves one SDK from its selected source and the in-tree proxy: ```sh nix develop --no-update-lock-file .#ci -c \ ./scripts/ci/verify-local-rust-deps.sh ``` Root workflows own proxy Rust, daily supply-chain, non-publishing container, and native-release rehearsal checks. `proxy/src/**`, `proxy/Cargo.toml`, and unknown proxy build inputs are desktop application inputs; tests, examples, docs, the standalone lockfile, and container-only files do not by themselves route expensive Maple app builds. Rust SDK build inputs (`sdk/rust/Cargo.toml`, `src/`, `build.rs`, `assets/`) select proxy and desktop checks too, because the proxy and both desktops build `sdk/rust` from the tree. When a new input changes either graph, update `scripts/ci/change_detection.py`, its table-driven tests, and workflow paths in the same change. ## Exercise the right runtime Run the standalone proxy on a checkout-specific loopback port with an explicit backend and PCR0 environment. Keep API keys in ignored local configuration or the invoking process; never print or commit them. Exercise `/health`, `/v1/models`, streaming and non-streaming chat, embeddings, invalid authentication, timeout, and cancellation only as relevant to the change. Container builds require the Maple repository root as context because the Dockerfile copies both `proxy/` and `sdk/rust`: ```sh docker build -f proxy/Dockerfile -t maple-proxy:dev . ``` Use the configured container runtime from `proxy/justfile` when Docker is not the intended local engine. A successful image build is not proof that GHCR was published or that the service works against a live enclave. For authentication, CORS, bind exposure, saved-key behavior, backend URL or PCR0 selection, request forwarding, logging, or timeout changes, load `$review-maple-security`. Preserve the core loopback and CORS-off defaults; treat container CORS-on configuration as a separate exposed mode. A configured default API key is for private/originless clients; browser-facing CORS mode must require each request's bearer key rather than spending the saved default. Never assume protections in the Tauri wrapper also exist in the standalone router. Never log any portion of an API key. Treat raw OpenAI request and response bodies as untrusted and potentially sensitive. ## Preserve publishing boundaries Maple's GitHub Release workflow builds, checksums, attests, uploads, and re-verifies four native proxy archives. Maple v3.3.9 proved this integrated publication path for macOS arm64, Linux arm64, Linux x86_64, and Windows x86_64. Never create a proxy GitHub tag or Release; a proxy-only binary fix ships through a normal Maple patch release. Crates.io publishing remains separately versioned and manual. On an authorized publish, inspect the exact package first: ```sh cargo package --locked --manifest-path proxy/Cargo.toml ``` If the proxy references a new `maple-sdk` version, publish that SDK crate first. Do not publish either crate from Maple's application Release workflow. Root proxy container CI builds without pushing. After a successful stable Maple Release, `.github/workflows/proxy-publish.yml` independently compares that release's proxy version with the previous stable Maple Release. Unchanged versions skip, including the unbackfilled 0.3.3 baseline. A strictly newer, previously unpublished version automatically publishes Linux AMD64/ARM64 to `ghcr.io/mapleprivacylabs/maple-proxy` with exact, minor, major, and `latest` tags. The workflow is serialized, rejects rollback and stale releases, verifies the public manifest, and supports manual retry from `master`. The transferred Maple repository uses its `GITHUB_TOKEN` to publish in `MaplePrivacyLabs`; the new package must be public and grant Maple Actions write access. Existing old-namespace images remain available but receive no updates. Treat any namespace, trigger, version policy, or package-access change as a separate production-authority decision. ## Report State the proxy behavior and public contract changed, SDK/application boundary, exact checks and runtime evidence, container or package inspection performed, version/publisher state left unchanged or deliberately updated, and every platform, live backend, registry, or release boundary not exercised.