diff --git a/CHANGELOG.md b/CHANGELOG.md index d8b6720..48b58e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,14 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +## [0.10.1] - 2026-07-17 + +### Fixed + +- **ProxyBase — migrated to the current client.** ProxyBase retired its Docker Hub image and old GHCR org and moved to `proxybase.org`, so the catalog entry no longer worked. The image is now `ghcr.io/proxybaseorg/peer-cli` (digest-pinned, multi-arch amd64/arm64/armv7 — arm64/Raspberry Pi now supported), the credentials are the client's current `ID` (relabelled **Access Token**, masked) and `NAME` env vars (the retired `USER_ID`/`DEVICE_NAME` are ignored by the new client), every URL points at `proxybase.org`, and datacenter IPs are now marked as accepted (residential still earns most). Existing ProxyBase services must be re-deployed with a fresh Access Token. + +## [0.10.0] - 2026-07-11 + ### Changed - **Fleet server — per-worker keys.** The fleet heartbeat API (`/api/workers/heartbeat`) now issues each device its own key on first contact — returned once as `worker_key` — and requires it thereafter. The shared fleet token (`CASHPILOT_API_KEY`) becomes an enrollment-only bootstrap credential and is rejected for a device once it has confirmed its own key, so a leaked device key is scoped to that device and no device can impersonate another. A fresh key is re-delivered on each heartbeat until the device confirms it, so a dropped response can't lock a device out. Interoperates with the CashPilot web UI (v1.0.0) and the CashPilot-android client. A forward-only SQLite migration adds the per-device key columns. diff --git a/README.md b/README.md index b5b8389..82a31a1 100644 --- a/README.md +++ b/README.md @@ -92,7 +92,7 @@ Services CashPilot can deploy and manage automatically via Docker containers. | [MystNodes](https://mystnodes.co/?referral_code=do7v7YOoBBpbOstKQovX2pUvZYKia4ZhH3QIdNtE) | ✅ | ✅ | Unlimited | Unlimited | Crypto (MYST) | | [PacketStream](https://packetstream.io/?psr=7xgZ) | ✅ | ❌ | Unlimited | 1 | PayPal | | [Presearch](https://presearch.com/signup?rid=4872322) | ✅ | ✅ | Unlimited | 1 | Crypto (PRE) | -| [ProxyBase](https://peer.proxybase.org?referral=nXzS3c6iTO) | ✅ | ❌ | Unlimited | 1 | Crypto | +| [ProxyBase](https://peer.proxybase.org?referral=nXzS3c6iTO) | ✅ | ✅ | Unlimited | 1 | Crypto | | [ProxyLite](https://proxylite.ru/?r=KMUPRZIZ) | ✅ | ✅ | Unlimited | 1 | Crypto, PayPal | | [ProxyRack](https://peer.proxyrack.com/ref/mpwiok3xlaxeycnn5znqlg7ipjeutxyxr6xl7vmn) | ✅ | ✅ | 500 | 1 | PayPal, Crypto | | [Repocket](https://repocket.com/) | ✅ | ❌ | 5 | 2 | PayPal, Crypto | diff --git a/docs/BRANCH-2-RUNTIME.md b/docs/BRANCH-2-RUNTIME.md index 5647b76..254df94 100644 --- a/docs/BRANCH-2-RUNTIME.md +++ b/docs/BRANCH-2-RUNTIME.md @@ -89,8 +89,9 @@ Of the 16 core earners studied — **~12 have official native binaries (≥ Wind headless-browser path is justified — heavy; the Wails WebView can't load Chrome extensions, so it's not a free win. Defer. - **Catalog corrections needed** (stale data): Gradient `status: active → dead`; Salad `platforms` add - `macos`/`linux` (graduated from beta); PacketStream add `macos`; ProxyBase image ref - (`ghcr.io/proxybase-org-company/peer-cli`). Peer2Profit already `dead`. + `macos`/`linux` (graduated from beta); PacketStream add `macos`. Peer2Profit already `dead`. + ProxyBase image ref: **done** in v0.10.1 — migrated to the digest-pinned `ghcr.io/proxybaseorg/peer-cli` + (note: the org is `proxybaseorg`; the older `proxybase-org-company` org no longer exists). - **Business-model note:** Honeygain/Bright Data run official partner-SDK programs that *pay* to bundle their client — but they require exclusivity ("no competing tech") that conflicts with the aggregator model. **Stay on the current model** (run the *retail* client with the *user's own* account credentials) — it's a diff --git a/frontend/package-lock.json b/frontend/package-lock.json index ce4970b..6f400b0 100644 --- a/frontend/package-lock.json +++ b/frontend/package-lock.json @@ -1,12 +1,12 @@ { "name": "cashpilot-desktop-frontend", - "version": "0.9.0", + "version": "0.10.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "cashpilot-desktop-frontend", - "version": "0.9.0", + "version": "0.10.1", "devDependencies": { "typescript": "^7.0.2", "vite": "^8.1.4" diff --git a/frontend/package.json b/frontend/package.json index fdbc0a6..776e559 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "cashpilot-desktop-frontend", - "version": "0.9.0", + "version": "0.10.1", "private": true, "type": "module", "scripts": { diff --git a/internal/catalog/proxybase_test.go b/internal/catalog/proxybase_test.go new file mode 100644 index 0000000..f93e521 --- /dev/null +++ b/internal/catalog/proxybase_test.go @@ -0,0 +1,85 @@ +package catalog + +import ( + "os" + "path/filepath" + "strings" + "testing" +) + +// TestProxyBaseContainerContract is a regression guard for the ProxyBase migration +// (CashPilot web issue #103). ProxyBase retired its Docker Hub image and old GHCR org +// and shipped a new client whose env contract is ID + NAME (verified against the +// image's own --help: "ProxyBase-Peer [ []]", "set env var ID" / "set env +// var NAME"). The retired USER_ID/DEVICE_NAME are ignored by the new client, so a +// container built on those silently fails with "Missing ID and NAME". Pin by digest, +// never the retired proxybase/proxybase image or a floating tag. +func TestProxyBaseContainerContract(t *testing.T) { + cat, err := LoadEmbedded(os.DirFS(filepath.Join("..", ".."))) + if err != nil { + t.Fatalf("load real services catalog: %v", err) + } + + svc, ok := cat.Get("proxybase") + if !ok { + t.Fatal("proxybase service not found in catalog") + } + + if !strings.HasPrefix(svc.Docker.Image, "ghcr.io/proxybaseorg/peer-cli@sha256:") { + t.Errorf("ProxyBase must use the digest-pinned GHCR peer-cli image, got %q", svc.Docker.Image) + } + + arm64 := false + for _, p := range svc.Docker.Platforms { + if p == "linux/arm64" { + arm64 = true + } + } + if !arm64 { + t.Errorf("ProxyBase must keep linux/arm64 (multi-arch image; Raspberry Pi support), got %v", svc.Docker.Platforms) + } + + byKey := map[string]EnvVar{} + for _, e := range svc.Docker.Env { + byKey[e.Key] = e + } + if len(byKey) != 2 || byKey["ID"].Key == "" || byKey["NAME"].Key == "" { + keys := make([]string, 0, len(byKey)) + for k := range byKey { + keys = append(keys, k) + } + t.Fatalf("ProxyBase container env must be exactly ID + NAME (the peer-cli contract), got %v", keys) + } + if !byKey["ID"].Required { + t.Error("ID (Access Token) must be required") + } + if !byKey["ID"].Secret { + t.Error("ID (Access Token) must be marked secret (masked in the UI)") + } + if !byKey["NAME"].Required { + t.Error("NAME (Device Name) must be required") + } + + // Referral revenue guard: the signup URL must keep the referral code. + if svc.Referral.SignupURL != "https://peer.proxybase.org?referral=nXzS3c6iTO" { + t.Errorf("signup_url must keep the referral code, got %q", svc.Referral.SignupURL) + } + + // Datacenter/VPS IPs are accepted (per the ProxyBase team); drives the UI badge. + if svc.Requirements.ResidentialIP { + t.Error("ProxyBase no longer requires a residential IP") + } + if !svc.Requirements.VPSIP { + t.Error("ProxyBase must mark VPS/datacenter IPs as supported") + } + + // Domain migrated proxybase.io -> proxybase.org across every user-facing URL. + if strings.Contains(svc.Website, "proxybase.io") { + t.Errorf("website must use proxybase.org, got %q", svc.Website) + } + for _, e := range svc.Docker.Env { + if strings.Contains(e.Description, "proxybase.io") { + t.Errorf("env %s description still links proxybase.io", e.Key) + } + } +} diff --git a/package.json b/package.json index 4d8bdb7..c6e3b93 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cashpilot-desktop", - "version": "0.9.0", + "version": "0.10.1", "private": true, "scripts": { "dev": "wails dev", diff --git a/services/bandwidth/proxybase.yml b/services/bandwidth/proxybase.yml index e98b35b..77929b2 100644 --- a/services/bandwidth/proxybase.yml +++ b/services/bandwidth/proxybase.yml @@ -2,30 +2,31 @@ name: ProxyBase slug: proxybase category: bandwidth status: active -website: https://proxybase.io +website: https://proxybase.org description: > ProxyBase is a bandwidth-sharing platform that pays users in cryptocurrency for - sharing their unused internet connection. Uses a simple user ID-based authentication - system. Works on residential connections. Official Docker image available. -short_description: Bandwidth sharing - crypto payout, user ID auth + sharing their unused internet connection. You authenticate the peer client with an + Access Token from your dashboard. Residential IPs earn the most, but datacenter IPs + are also supported. Official multi-arch Docker image (amd64/arm64/armv7). +short_description: Bandwidth sharing - crypto payout, Access Token auth referral: signup_url: "https://peer.proxybase.org?referral=nXzS3c6iTO" docker: - image: "proxybase/proxybase@sha256:04d63c3b7727fe7b988600a5b7663144957aee9997ddf82bdb0f6d6007dfb3e3" - platforms: [linux/amd64] + image: "ghcr.io/proxybaseorg/peer-cli@sha256:b78dda3969019eb9e0d3ba0aeba0929148337898b00d99cf780f4d8c99b31b0e" + platforms: [linux/amd64, linux/arm64, linux/arm/v7] env: - - key: USER_ID - label: "User ID" + - key: ID + label: "Access Token" required: true - secret: false - description: "Log in at dashboard.proxybase.io → your User ID is shown in the Docker command on the setup page" - - key: DEVICE_NAME + secret: true + description: "Log in at peer.proxybase.org/dashboard → copy your Access Token (shown in the Docker command on the setup page)" + - key: NAME label: "Device Name" required: true secret: false - description: "Name shown in your ProxyBase dashboard (container crashes without it)" + description: "Any name to identify this device in your ProxyBase dashboard" default: "cashpilot-{hostname}" ports: [] volumes: [] @@ -36,7 +37,8 @@ docker: oom_score_adj: 300 requirements: - residential_ip: true + residential_ip: false + vps_ip: true min_bandwidth: "" gpu: false min_storage: "" diff --git a/wails.json b/wails.json index cca2c62..1d09758 100644 --- a/wails.json +++ b/wails.json @@ -12,7 +12,7 @@ }, "info": { "productName": "CashPilot Desktop", - "productVersion": "0.9.0", + "productVersion": "0.10.1", "copyright": "Copyright 2026 Sergio Fernandez", "comments": "Local-first passive income and DePIN service manager" }