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
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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 |
Expand Down
5 changes: 3 additions & 2 deletions docs/BRANCH-2-RUNTIME.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions frontend/package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion frontend/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cashpilot-desktop-frontend",
"version": "0.9.0",
"version": "0.10.1",
"private": true,
"type": "module",
"scripts": {
Expand Down
85 changes: 85 additions & 0 deletions internal/catalog/proxybase_test.go
Original file line number Diff line number Diff line change
@@ -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 [<ID> [<NAME>]]", "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)
}
}
}
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "cashpilot-desktop",
"version": "0.9.0",
"version": "0.10.1",
"private": true,
"scripts": {
"dev": "wails dev",
Expand Down
28 changes: 15 additions & 13 deletions services/bandwidth/proxybase.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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 <a href=\"https://dashboard.proxybase.io\">dashboard.proxybase.io</a> → your User ID is shown in the Docker command on the setup page"
- key: DEVICE_NAME
secret: true
description: "Log in at <a href=\"https://peer.proxybase.org/dashboard\">peer.proxybase.org/dashboard</a> → 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: []
Expand All @@ -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: ""
Expand Down
2 changes: 1 addition & 1 deletion wails.json
Original file line number Diff line number Diff line change
Expand Up @@ -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"
}
Expand Down
Loading