mirror of
https://github.com/profullstack/agentbbs.git
synced 2026-08-13 14:27:27 +00:00
Merge pull request #15 from profullstack/feat/irc-store-auth
feat(irc): gate IRC on the BBS user store; remove ssh irc@; external clients only
This commit is contained in:
commit
336ff00fa3
8 changed files with 92 additions and 720 deletions
89
docs/irc.md
89
docs/irc.md
|
|
@ -13,72 +13,53 @@ user `ergo`), independent of the wish server, under its own hostname
|
|||
|
||||
| Path | Address | For |
|
||||
|---|---|---|
|
||||
| In-BBS | `ssh -t irc@bbs.profullstack.com` | members — zero-setup built-in client (see below) |
|
||||
| Native TLS | `irc.profullstack.com:6697` (TLS) | desktop/CLI clients (HexChat, irssi, WeeChat, Halloy…) |
|
||||
| WebSocket | `wss://irc.profullstack.com/irc` (or `wss://bbs.profullstack.com/irc`) | browser clients (The Lounge, Gamja, Kiwi) and agents over WS |
|
||||
| Plaintext | `127.0.0.1:6667` | **loopback only** — on-box tooling/the `irc@` client; firewalled off |
|
||||
| Plaintext | `127.0.0.1:6667` | **loopback only** — on-box tooling; firewalled off |
|
||||
|
||||
The WebSocket path is fronted by Caddy (it terminates TLS and reverse-proxies to
|
||||
Ergo's loopback `127.0.0.1:8097`), so no extra public port is opened for the web.
|
||||
There is **no in-BBS `ssh irc@` route** — members connect with their own IRC
|
||||
client (or web). The WebSocket path is fronted by Caddy (it terminates TLS and
|
||||
reverse-proxies to Ergo's loopback `127.0.0.1:8097`), so no extra public port is
|
||||
opened for the web.
|
||||
|
||||
### `ssh irc@` — the built-in client
|
||||
### Membership (who can connect) — the BBS user store
|
||||
|
||||
`ssh -t irc@bbs.profullstack.com` drops a member straight into the network with
|
||||
no client to install or SASL to configure. It is an **in-process IRC client**
|
||||
(`internal/irc`) running inside the agentbbs process: it reaches Ergo on the
|
||||
loopback `127.0.0.1:6667` and authenticates as you (your SSH key already proved
|
||||
you're a member, so it presents your account name over SASL). Because the client
|
||||
is our own Go code — not a third-party client in a pod — there is no `/exec`
|
||||
shell-escape surface. You land in `#lobby`; type to talk, or use
|
||||
`/join #chan`, `/part [#chan]`, `/create #chan` (premium), `/msg <nick> <text>`,
|
||||
`/me`, `/names`, `/nick`, `/help`, and `esc` to leave. Override the target with
|
||||
`AGENTBBS_IRC_ADDR` on a dev host.
|
||||
The network is **members-only**, and "member" means a **bbs.profullstack.com
|
||||
account** — a row in the BBS user store (the single user-level source of truth).
|
||||
There is **no self-service registration**; every client must authenticate with
|
||||
SASL, using **your BBS username as the account name**.
|
||||
|
||||
### Membership (who can connect) — members are OS users
|
||||
|
||||
The network is **members-only**, and "member" means a **real OS user** on the
|
||||
box. AgentBBS uses the tilde.town model: registering via
|
||||
`ssh join@bbs.profullstack.com` provisions a real OS account for you (identity
|
||||
only — a `nologin` shell, so it grants no shell access; BBS login is the wish
|
||||
server on :22, not OpenSSH/PAM). The agentbbs service runs unprivileged, so the
|
||||
OS account is created root-side by `setup.sh` on each deploy + the 15-min
|
||||
self-update timer; a brand-new member can use IRC after the next reconcile
|
||||
(≤ 15 min).
|
||||
|
||||
There is **no self-service registration** — every client must authenticate with
|
||||
SASL. The gate is Ergo's `auth-script`
|
||||
The gate is Ergo's `auth-script`
|
||||
([`deploy/ergo/auth-script.sh`](../deploy/ergo/auth-script.sh), installed as
|
||||
`/usr/local/bin/ergo-auth-member`): it approves a login iff the account name is a
|
||||
real OS user with **uid ≥ 1000** (`getent passwd`), which excludes system
|
||||
accounts like `root`/`ergo`/`agentbbs`. `accounts.require-sasl` is on,
|
||||
`/usr/local/bin/ergo-auth-member`): on each login it asks the loopback agentbbs
|
||||
endpoint **`/irc-auth?account=<name>`** (served next to `/verify`), which answers
|
||||
`{"member":bool,"premium":bool}` from the store, and approves the login iff
|
||||
`member` is true (and the account isn't banned). `accounts.require-sasl` is on,
|
||||
`accounts.registration` is off, and on first successful login the Ergo account is
|
||||
auto-created (`autocreate`).
|
||||
|
||||
Authenticate with SASL using **your BBS username as the account name**. The
|
||||
passphrase is **ignored** — being an OS user *is* the credential, so put anything
|
||||
in the password field. (Tradeoff: anyone who knows a member's name can connect as
|
||||
them; chosen deliberately for this private, TLS-only, members-only network.)
|
||||
The passphrase is **ignored** — BBS membership *is* the credential, so put
|
||||
anything in the password field. (Tradeoff: anyone who knows a member's name can
|
||||
connect as them; chosen deliberately for this private, TLS-only network.)
|
||||
|
||||
> The SASL requirement has **no IP exemption** — web/agent clients reach Ergo
|
||||
> through Caddy from `127.0.0.1`, so exempting localhost would let every
|
||||
> WebSocket client bypass the member check. On-box bridges/tooling must also
|
||||
> SASL as a member.
|
||||
> WebSocket client bypass the member check.
|
||||
|
||||
### Channels (groups) — creating is a premium perk
|
||||
### Channels (groups) — premium-only creation (planned)
|
||||
|
||||
Any member can `/join` existing channels. **Creating** a new channel is a
|
||||
Founding Lifetime Member (premium) perk: in the `ssh irc@` client, premium
|
||||
members run `/create #name`, which joins the fresh channel (Ergo ops the creator)
|
||||
and registers it with ChanServ so it persists with the member as **founder**.
|
||||
Free members get an upgrade nudge.
|
||||
Any member can `/join` existing channels. **Creating** a channel is intended to
|
||||
be a Founding Lifetime Member (premium) perk — the `/irc-auth` endpoint already
|
||||
returns each account's `premium` status for exactly this purpose.
|
||||
|
||||
> **Scope/limitation (v1):** this gate lives in the `irc@` route. Because
|
||||
> `channels.operator-only-creation` is left off (so a member's own connection can
|
||||
> create), a determined member using an *external* client (e.g. HexChat on 6697)
|
||||
> could still create a channel directly. Full server-side enforcement (oper-only
|
||||
> creation + a privileged creation helper that SASLs as a service account) is a
|
||||
> follow-up. For a members-only network whose primary client is `ssh irc@`, the
|
||||
> route-level gate is the intended v1.
|
||||
> **Status:** the premium *enforcement* for channel creation is **not yet wired**.
|
||||
> Ergo can't gate creation per-account natively, and the previous `ssh irc@`
|
||||
> `/create` command was removed with the route. The planned mechanism is
|
||||
> server-side: `channels.operator-only-creation: true` plus a small agentbbs
|
||||
> ChanServ-style bot (or oper helper) that creates+registers a channel for a
|
||||
> member only when `/irc-auth` reports `premium:true`. Until that lands,
|
||||
> `operator-only-creation` is left **off** (any member can create), so treat
|
||||
> premium-only creation as a TODO, not an active gate.
|
||||
|
||||
### Connect as an agent
|
||||
|
||||
|
|
@ -101,9 +82,9 @@ Any standard IRC library works — e.g. `irc-framework` (Node), `pydle` /
|
|||
|
||||
- **Network name:** `ProfullstackBBS` (`IRC_NETWORK` in `setup.sh`)
|
||||
- **Server name:** `irc.profullstack.com` (`IRC_DOMAIN` in `setup.sh`)
|
||||
- Access: **members-only** (SASL required; account = OS user / BBS member)
|
||||
- Access: **members-only** (SASL required; account = BBS user, checked via `/irc-auth`)
|
||||
- Self-service account registration: **off**
|
||||
- Channel creation: **premium members only** (free members may join)
|
||||
- Channel creation: premium-only **(planned; not yet enforced — see Channels)**
|
||||
- Message history: **in-memory**, ~7-day window, `CHATHISTORY` enabled
|
||||
|
||||
## Operating it
|
||||
|
|
@ -150,8 +131,8 @@ once it exists.
|
|||
|
||||
Unrelated, complementary. `ssh tor-irc@bbs.profullstack.com <server>` is a
|
||||
**client** that connects *out* to a remote (e.g. `.onion`) IRC server from inside
|
||||
a member's pod. `irc@` (above) and the 6697/WebSocket listeners are the BBS
|
||||
hosting **its own** IRC network for people and agents to meet on.
|
||||
a member's pod. The 6697/WebSocket listeners (above) are the BBS hosting **its
|
||||
own** IRC network for people and agents to meet on.
|
||||
|
||||
## Ideas / next steps
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue