Exponential backoff up to 300s made no sense with rotating Tor exits
where each reconnect gets a fresh IP. Single 1s delay is sufficient.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Block all non-ACTION CTCP/DCC from client-to-server (outbound) and add
security logging when inbound CTCP/DCC is stripped. Hard boundary with
no config toggle -- DCC exposes the client's real IP which defeats the
stealth proxy architecture.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Fix E501 line-too-long in backlog.py, network.py, test_network.py.
Fix F541 f-string-without-placeholders in network.py.
Fix I001 unsorted imports in network.py.
Remove unused datetime import in test_cert.py (F401).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Add channel_keys dict to NetworkConfig for storing per-channel keys.
Keys are used in KICK rejoin, passed via AUTOJOIN +#channel key syntax,
supported in ADDNETWORK channel_keys= parameter, and propagated through
REHASH. Extract rehash() as reusable async function for SIGHUP reuse.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Accept TLS-encrypted connections from IRC clients. Auto-generates a
self-signed EC P-256 listener certificate (bouncer.pem) when no custom
cert is provided. Remove CTCP response items from roadmap (stealth by
design -- router already suppresses all CTCP except ACTION).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
_on_verify_success() was missing _nickserv_complete() call, causing
_go_ready() to hang at _nickserv_done.wait() when registration
completed immediately (no email verification needed).
get_pending_registration() was not returning verify_url from the DB,
so _resume_pending_verification() never restored self._verify_url --
breaking cross-session captcha resume for OFTC-style networks.
Four regression tests added.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
PING watchdog sends PING after configurable silence interval and
disconnects on timeout, detecting stale connections that TCP alone
misses. IRCv3 server-time capability is requested on every connection;
timestamps are injected on dispatch and backlog replay for clients
that support message tags. Push notifications via ntfy or generic
webhook fire on highlights and PMs when no clients are attached,
with configurable cooldown and optional SOCKS5 routing.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Cover state machine, markov nick generation, SASL negotiation,
NickServ/Q-bot auth flows, probation timer, reconnection backoff,
read loop buffering, and IRC message handling.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Replace hardcoded values across network, captcha, email, and cert
modules with BouncerConfig fields. All values have safe defaults
and are overridable in the [bouncer] section of the config file.
Configurable: probation_seconds, backoff_steps, nick_timeout,
rejoin_delay, http_timeout, captcha_poll_interval/timeout,
email_poll_interval/max_polls/request_timeout, cert_validity_days.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Users can now inspect bouncer state and manage it from their IRC client
by sending PRIVMSG to *bouncer (or bouncer). Supported commands:
HELP, STATUS, INFO, UPTIME, NETWORKS, CREDS. Responses arrive as
NOTICE messages. All commands are case-insensitive.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
irssi (and other IRC clients) only open a channel window when they see
a JOIN from their own nick. The synthetic JOINs were using the network
nick (e.g. pagumowa) but the client registered as tester -- mismatch.
Three changes:
- Synthetic JOIN prefix is now client_nick!user@bouncer
- 001 welcome uses the client's registered nick
- encode_nick/encode_message accept client_nick param to rewrite own
nicks from any network to the client's nick, so irssi recognizes
all self-actions consistently
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Multiplex all networks onto a single client connection using /network
suffixes on channels and nicks. PASS is now just the password (no
network prefix). Channels appear as #channel/network, foreign nicks as
nick/network, own nicks stay bare.
New namespace.py module with pure encode/decode functions. Router
tracks clients globally (not per-network), namespaces messages before
delivery. Client attaches to all networks on connect, sends synthetic
JOIN/TOPIC/NAMES for every channel across all networks.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Async Python IRC bouncer with SOCKS5 proxy support, multi-network
connections, password auth, and persistent SQLite backlog with replay.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>