| Branch | Commit message | Author | Age |
| main | Default REGISTER-before-connect and email-required to ON | EuAndreh | 22 hours |
| |
| |
| Age | Commit message | Author | Files | Lines |
| 22 hours | Default REGISTER-before-connect and email-required to ON•••These knobs were opt-in (env unset = off) for the irctest harness'
benefit; the harness exercises both branches and is happy to set the
env explicitly. But for the hosted papod deployment that papoweb is
moving towards, we definitely want both:
- REGISTER before connect: web clients can create an account in one
CAP/NICK/USER round-trip instead of completing the IRC handshake
twice (register, disconnect, log in).
- Email required: enables password recovery and abuse signal; cost
is one extra field at signup.
Invert the env-var sense so production picks up the secure defaults
with no env tweaks; tests that need the old behavior pin
PAPOD_REG_BEFORE_CONNECT=0 / PAPOD_REG_EMAIL_REQUIRED=0. The irctest
controller and papoweb's integration harness are updated separately
to pin "0" explicitly so a future default flip doesn't silently change
which branches they exercise.
HEADmain | EuAndreh | 1 | -2/+6 |
| 6 days | doc/c10m.adoc | EuAndreh | 1 | -0/+117 |
| 8 days | Record topic setter + set-time so 333 reports the truth•••RPL_TOPICWHOTIME (333) was emitted on JOIN with the *joiner's*
nick as the setter and System/currentTimeMillis as the set-time —
neither of which has any relationship to who actually set the
topic when.
Add :papod.channel/topic-set-by (string) and :papod.channel/topic-
set-at (long unix seconds) to the schema, populate them in the
TOPIC handler, and read them in join-one!'s 333 emission (falling
back to nick / now if absent, e.g. an empty channel snapshot
imported without the new attrs).
Surfaced by the chat.papo.im differential test (333 line diverged
between fake-ircd's correctly-tracked setter and papod's broken
output).
| EuAndreh | 1 | -4/+18 |
| 8 days | Fix JOIN race: pin NAMES/broadcast to atomic membership snapshot•••Two clients JOINing the same channel concurrently could each see the
other in their own NAMES reply, and both could end up auto-opped on
a freshly-created channel. The cause was that join-one! did:
(swap! channels update handle (fnil conj #{}) nick)
...
(get @channels handle) ;; for NAMES + broadcast + auto-op
Between the swap! and the @channels read, a peer's swap! could land,
so the read returned a set that already included them.
Switch the swap to swap-vals!, capture members-before / members-after
as a snapshot of state at the moment of our atomic update, and feed
that snapshot to the broadcast loop, the metadata-2 push, the away-
notify push, the auto-op decision, and the NAMES reply (via a new
:members keyword on names-for). Auto-op now keys off (empty?
members-before) instead of comparing the live atom to #{nick}.
Surfaced and verified by the differential test in chat.papo.im,
which previously had to insert quiesce checkpoints between concurrent
JOINs to dodge the race; those checkpoints are no longer needed.
| EuAndreh | 1 | -23/+34 |
| 9 days | Bump welcome-banner counts after RPL_005 split•••The welcome burst grew to three RPL_005 lines a while back, but
test_replies-for! / test_sasl / test_memoserv still asserted the
old counts (7/7/8). Update them to 8/8/9 to match what the server
actually emits.
| EuAndreh | 1 | -3/+6 |
| 9 days | Identify networks via PROXY v2 AUTHORITY; drop default network•••papod no longer pre-creates a "default network" at boot. Instead,
each accepted connection is expected to begin with a PROXY protocol
v2 header (RFC: haproxy.org proxy-protocol.txt) carrying the SNI in
a PP2_TYPE_AUTHORITY (0x02) TLV — exactly what untls now injects.
The authority is used to look up (or create) a network by name, and
the resulting network-id is bound to the client at connect time
rather than at registration time. Connections that arrive without
a header and without the PAPOD_NETWORK_NAME fallback set are refused
with "ERROR :Closing link: (No network)".
PAPOD_NETWORK_NAME exists for environments where untls is not in
the path (notably the integration test harness, where binder/wscat
speak raw bytes); production deployments should leave it unset and
let untls supply the SNI.
Unit tests cover the parser: a valid header returns the AUTHORITY
and leaves trailing bytes intact; non-PROXY input returns nil and
preserves the stream; PROXY without an AUTHORITY TLV returns "".
| EuAndreh | 2 | -18/+221 |
| 9 days | Implement ADMIN, STATS, LINKS, TRACE, USERS, REHASH, CONNECT•••Previously these commands fell through to the catch-all 421
'Unknown command' branch. All of them are RFC1459 commands a
modern client may probe; we now respond with the RFC numerics:
- ADMIN: 256 + 257 + 258 + 259 administrative info burst.
- STATS: 219 terminator always; the 'u' query returns 242
with a parsed uptime, the default returns a single 250
summary line. Other queries (m, l, o) are accepted with
only the terminator (no records to report).
- LINKS: 364 line for ourselves + 365 terminator (we don't
link to other servers).
- TRACE: 206 server entry + 262 terminator.
- USERS: 392 header + 393 entries + 394 terminator, or 395
when nobody is logged in.
- REHASH: 382 for opers, 481 otherwise. No actual config
reload (papod reads only env vars at startup).
- CONNECT: 481 for non-opers, 402 'no such server' otherwise
(we do not link).
Also added :started-at to the components map so STATS u can
report uptime.
| EuAndreh | 1 | -0/+149 |
| 9 days | Implement VERSION, ISON, and CHGHOST••• - VERSION: emit 351 with version + server name, followed by
the same three-line 005 ISUPPORT burst we send on welcome.
- ISON: reply with 303, listing only those of the requested
targets that have a live client entry.
- CHGHOST (oper-only): introduce a per-client :host field
(defaulting to 'localhost' when unset) and update both
client-prefix and nuh-for-nick to use it. CHGHOST <target>
<newuser> <newhost> mutates the target's :user :username
and :host, replies 396 to the target itself, and broadcasts
':oldprefix CHGHOST newuser newhost' to peers in shared
channels that negotiated the chghost cap. Non-opers get
481; missing params get 461; bad chars get 501.
Was previously surfaced as gaps by the chat.papo.im
integration suite; all three commands now respond with the
RFC-mandated numerics.
| EuAndreh | 1 | -4/+129 |
| 9 days | Honor CAP REQ -cap and ignore unknown batch refs•••Two compliance gaps surfaced by the chat.papo.im integration
suite:
- CAP REQ :-echo-message previously matched no supported cap
name (because of the leading '-'), so it was NAKed; even when
a client sent a plain disable like above, papod silently kept
the cap in the active set. We now split each REQ token by
the '-' prefix, mark it as :add or :remove, and update the
client's cap set accordingly. An REQ containing a mix of
known and unknown caps is still NAKed atomically.
- A message tagged with @batch=X referring to a batch that was
never opened (e.g. because handle-batch-open! rejected the
BATCH because of a missing target) used to fall through into
normal command processing — so a malformed multiline batch
would still deliver its inner PRIVMSG. Per IRCv3 we now
silently drop those messages instead.
| EuAndreh | 1 | -10/+24 |
| 9 days | Honor userhost-in-names and account-tag caps end-to-end•••NAMES (RPL_NAMREPLY) now appends nick!user@host when the requesting
client has negotiated userhost-in-names, both on JOIN and on the
explicit NAMES command.
account-tag is now applied even for unauthenticated senders: per
the IRCv3 spec, the value is the literal '*' when no account is
known. Previously we silently dropped the tag, which made the
ACK meaningless for anonymous clients.
| EuAndreh | 1 | -35/+38 |
| [...] |