Skip to content

Release 3.0.0: redesigned app, 150-source catalog, desktop builds, pools, schedules and API - #28

Merged
DavidVoitenko merged 22 commits into
mainfrom
release/3.0.0
Sep 27, 2026
Merged

DavidVoitenko merged 22 commits into
mainfrom
release/3.0.0

Conversation

@DavidVoitenko

Copy link
Copy Markdown
Owner

Proxy Workbench 3.0.0

The largest release so far. The full list of changes is in CHANGELOG.md; this is the short version.

What users get

  • Redesigned interface in dark and light themes, adapted to phones and tablets, in 12 languages.
  • Source catalog of 150 sources (117 fully free and public; 106 feeds collected out of the box), with sets, per-source reports and overlap detection.
  • Desktop app: macOS menu-bar app (.app / .dmg, Apple Silicon and Intel) and a Windows installer with separate GUI and CLI executables; per-user data folders and an opt-in portable mode.
  • Pools and schedules that keep N working proxies fresh on their own, named profiles with revisions, list import with preview, API keys with permissions and scope, diagnostics that explain an empty result, backups with preview.
  • Versioned control API /v1 for scripts and integrations.

Verified before release

  • Collection against the real public lists: all 106 default feeds, 102 answering (the rest are dead, empty or over the size limit and reported as such); 133 s → 79 s; four previously silent sources fixed; source history bounded so the database no longer grows under --watch.
  • Checking engine on local mock proxies: 3,000 mostly dead candidates in ~14 s (was hours: a self-inflicted database lock and a concurrency collapse on dead proxies); stop/resume, --watch, --want, budgets, judge, speed test, reputation, geo and every export file checked.
  • API: every one of the 103 /v1 operations called with valid and invalid input and with a scoped key; about 30 defects fixed (audit log, scope bypass through body fields, event streams, paging, status codes, key leak in a URL, collection revisions, merge/replace, gateway settings, network Host handling).
  • Interface: all pages in both themes, all 12 languages and a phone viewport opened in a real browser with no script errors; fixed languages falling back to English after a restart, table cells under the wrong headers, and unreadable light-theme table text.
  • macOS app: built with the dmg and menu-bar helper, smoke-tested, launched, a check run through the frozen worker, single-instance and quit verified, dmg mounted and inspected.
  • Windows installer: command-line shortcuts, PATH refresh and a way to quit the app fixed; the build and launch are verified by the Windows CI jobs on this PR.

Breaking changes

  • proxy-workbench with no arguments starts the desktop app; proxy-workbench gui opens only the web interface.
  • Database schema 20; older data folders are migrated with a backup taken first.
  • The rotating gateway has its own password (--gateway-token), separate from the API token.

Repository cleanup

Internal planning documents and contributor boilerplate were removed; the README, the landing page, screenshots, the demo animation and the social preview were rewritten for 3.0.0.

Anonymous added 22 commits September 27, 2026 01:29
- Version 3.0.0; CHANGELOG, README (EN/RU) and the landing page describe the
  new catalog, desktop app, pools, schedules, keys, diagnostics, backups and
  12 languages, without links to removed documents.
- A saved or system language from a lazy pack is loaded at start; before,
  ten of twelve languages fell back to English after a restart.
- Result rows re-apply the hidden columns after every render, so cells no
  longer slide under the wrong headers.
- Results table text follows the theme instead of a dark-only colour.
- Comments no longer point at internal planning documents.
- New screenshots on synthetic RFC 5737 data.
The installer's command line shortcuts started the windowed GUI executable
with --help, which prints nowhere; they now open a console running the CLI
executable. The installer also announces its Path change so new consoles
find the command.

Windows has no menu bar and the GUI build has no console, so the running
app could only be stopped from the Task Manager, and the uninstaller could
not remove an executable that was still running. The desktop host now has a
--quit command that asks the running instance to quit over its control
channel and waits until it has released its data folder. The installer
adds a Start menu entry for it and runs it before uninstalling.
The CLI scan opened a second SQLite connection for its job store while
the scan kept a write batch open on the first. Every job item claim then
waited out the busy timeout with the event loop blocked (about 5 s per
result) and left the item pending. The job store now reuses the scan's
connection.

The adaptive concurrency limit treated a dead proxy as overload, so a
mostly dead corpus drove the scan down to one check at a time. The scan
now counts only failures without a measurement stage (local trouble) as
overload. Descriptor exhaustion (EMFILE and similar) is raised instead of
being recorded as an unreachable proxy.
- Write pipeline audit rows again (the adapter shadowed its own writer).
- Enforce resource scope named by body or query fields, not only path ones.
- Serve event streams: accept the page shape, stream frames on the serve
  socket, give the system stream a global sequence and a working cursor.
- Result listings follow their cursor and apply every declared filter,
  sort and count; selection accepts host:port; one engine per country
  filter instead of one database connection per row.
- Scoped keys see the members of their own collection; pool members of a
  missing or hidden pool are 404.
- Missing jobs answer 404, validation errors 400, engine ValueError 400.
- Source refresh returns a job id; unknown source ids are 404.
- Expired idempotency keys accept a new body; PUT answers 405; legacy
  read-only paths refuse other methods; localhost reaches /v1.
- Subscription revoke only revokes subscriptions; half a rate limit and a
  create-time rotation grace are refused; profile@revision is routable.
- Snapshots exported with --min-success 0 are readable again.
- The GUI no longer sends the administrator key in a URL.
Write collected addresses in key-sorted batches of set-based statements
instead of several statements per address, with a fast path for plain
IPv4 lines in the proxy normalizer. A list without country claims no
longer clears a country stored by an earlier source or import.

Catalog line records now honor their http-fields and text formats and
drop trailing inline comments. A source past its own size or candidate
limit is reported as a partial read of a working transport and is not
backed off or quarantined. Cache validators are stored only with a body
that was read whole, and a 304 without validators keeps the stored ones.
Next-url pagination keeps the path and query of absolute links.
…keys

Collections carry a revision (migration 20), so PATCH and DELETE honour
If-Match and PATCH applies archived. Merge copies from_collection_id, replace
answers with a job id, member add refuses values that are not proxy
addresses and member removal takes the endpoint id.

Source comparisons check every named collection against the key scope.
Pool creation defaults the profile to the last checked one and refuses an
unknown profile; renaming a pool is refused instead of dropped. Schedules
refuse an unknown collection. The gateway configuration is stored under a
revision with validated transports, and stored bindings are listed with
their own revision. Only revoked keys can be deleted.

A wildcard or network bind accepts loopback names, the machine name and its
routed addresses as Host, and still refuses other names. Audit retention no
longer scans the whole table on every insert.
Keep only the newest three generations per source (entries included) and
the newest fifty fetch observations, pruned in batches right after each
source is committed; the generations the source state names are never
pruned. Backup retention previews and removes history left by older
versions.

A 304 now writes the last good generation into the target collection,
restoring missing members without re-dating the ones that are there.
A retry after a broken download starts from the counters the attempt
started with, so a large list no longer fails its own size limit.
JSON pages are parsed once, and a list cut off by the candidate limit
reports the page it read.
A stopped or failed CLI scan left its job running, so every later scan
was refused with E_CONFLICT_BUSY and left another queued job behind for
the background runner. The job is now paused on a stop, a stale running
check job is paused under the data lock, and the same command resumes the
paused job with the same input instead of measuring finished items again.
A job that cannot start is cancelled instead of left queued.

Watch rounds reused the first run's closed job, which made every address
look finished: a round measured nothing and republished old verdicts.
Each round now opens its own job for the passing addresses.

Also refuse --speedtest-bytes below the minimum honest sample, which
could only ever produce insufficient speed results.
A worker waited for a busy host with the item in hand, so a list with
many ports on one address put every worker behind that host while other
hosts sat in the queue. An item whose host is busy is now parked for the
worker holding that host (bounded by the queue size), and the worker
moves on. The stop check is repeated after a host wait, so a reached
--want, deadline or budget is not followed by more measurements.

hostport.txt lists a port that passes as several protocols once.

Tests cover stop and continue, watch rounds, host parking, want on one
host, hostport dedupe and the speed test minimum, on local mocks.
@DavidVoitenko
DavidVoitenko merged commit 3eca6b7 into main Sep 27, 2026
22 checks passed
@DavidVoitenko
DavidVoitenko deleted the release/3.0.0 branch September 27, 2026 08:47
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.

1 participant