Skip to content

feat(stack): engine-managed WARP IPv6 pool by default - #4

Merged
ebouther merged 4 commits into
mainfrom
feat/engine-warp-ipv6
Oct 27, 2026
Merged

ebouther merged 4 commits into
mainfrom
feat/engine-warp-ipv6

Conversation

@ebouther

Copy link
Copy Markdown
Owner

What changed

The free-tier quota is counted per egress block: /64 on IPv6, /32 on IPv4, with a daily reset at 00:00 UTC. The external WARP nodes share Cloudflare's IPv4 NAT, which other users routinely exhaust, so widening or rotating that pool stopped adding headroom.

opencode2api v1.4.4+ can run its own userspace WARP pool and key exits by egress block. With warp.stack: ipv6 and a routed source_ipv6 prefix, each exit binds its own outer address and gets a distinct /64. This PR makes that the default.

  • pin the engine to v1.4.5 (per-request project id, ses_ timestamp fix, Retry-After pacing, exit rotation on 429/403)
  • generate only config-init and opencode-engine when warp.enabled is true
  • seed warp.source_ipv6 from WARP_SOURCE_IPV6 in .env, so the prefix is not committed
  • require WARP_ACCEPT_TOS=1 in both modes, so the terms are never accepted silently
  • set retry.max_attempts to 6 so a request can walk past exhausted exits
  • keep the external pool generator for warp.enabled: false
  • make scripts/smoke.sh mode-aware and treat a cooling pool as quota, not a stack fault

Evidence

Measured 2026-10-27 on a host with a routed /64:

  • residential IPv4 and WARP IPv4 both returned 429 with Retry-After resolving to exactly 00:00:00 UTC
  • a WARP IPv6 exit returned 200 "42" while IPv4 was refused
  • three parallel beam-free requests through two distinct /64 exits all returned 200

Migration

Hosts without a routed IPv6 /64 can keep warp.enabled: false and use the external pool or their own proxies through proxyfile. Without IPv6, WARP falls back to the shared IPv4 NAT and the pool adds no headroom.

Tests

python3 -m unittest discover -s tests -v gives 135 tests, 2 skipped (the legacy-only port checks).

Notes

The two setup bugs reported in #3 (config-init labels on Fedora, engine cold-start catalogue) are separate and not addressed here.

The external rotator's health check only treated 429 as a rotation trigger, so a WARP exit flagged with the free tier's 403 "abusive traffic" response kept serving until a collision forced a rotate. Treat both as signals to re-register.
The free-tier quota is counted per egress block (/64 on IPv6, /32 on
IPv4), with a daily reset at 00:00 UTC. The external WARP nodes share
Cloudflare's IPv4 NAT, which other users routinely exhaust, so widening
or rotating that pool stopped adding headroom.

opencode2api v1.4.4+ can run its own userspace WARP pool and key exits
by egress block. With warp.stack: ipv6 and a routed source_ipv6 prefix,
each exit binds its own outer address and gets a distinct /64. This
commit switches the default stack to that mode:

- pin the engine to v1.4.5 (per-request project id, ses_ timestamp fix,
  Retry-After pacing, exit rotation on 429/403)
- generate only config-init and opencode-engine when warp.enabled is true
- seed warp.source_ipv6 from WARP_SOURCE_IPV6 in .env, so the prefix is
  not committed
- set retry.max_attempts to 6 so a request can walk past exhausted exits
- keep the external pool generator for warp.enabled: false

Verified locally: host IPv4 returns 429 until the daily reset, while
three parallel beam-free requests through distinct WARP /64 exits return
200.
The external WARP nodes refuse to start unless WARP_ACCEPT_TOS=1. The
engine-managed mode uses Cloudflare's network too, so config-init now
enforces the same explicit opt-in before seeding the config.
- default architecture, requirements, and scaling now describe the
  engine-owned WARP pool and the /64 vs /32 quota unit
- quota axis records the 2026-10-27 measurement: shared Retry-After to
  00:00 UTC on IPv4, 200s on distinct IPv6 /64 exits
- smoke.sh detects the mode, reads /healthz for the WARP pool, and skips
  completion checks when every exit is cooling down
@ebouther
ebouther merged commit 6da9b5c into main Oct 27, 2026
4 checks passed
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