feat(gopher): serve BBS content over Gopher + SSH-authenticated "hedgehog"#83
Merged
Conversation
…ehog"
Add Gopher (RFC 1436) as a co-located protocol service, following the
internal/news pattern. Two surfaces share one read-only Resolve engine:
- Public Gopher on :70 (RFC 1436) for any gopher client (lynx, Lagrange).
Classic gopher is stateless with no auth verb, so this surface serves
only public content.
- `ssh gopher@` = "hedgehog": the same gopher wire semantics carried over
the authenticated SSH channel (the member's key is the credential), so it
additionally reaches members-only selectors. Gopher where gopher can,
our own gopher-like thing over SSH where it can't.
Menus surface the member directory + homepages (public_html), an About page
(brand + MOTD), public newsgroups (allowlisted on :70, all groups on
hedgehog), and members' public files. Selectors are confined to each member's
area (path-traversal guarded). New AGENTBBS_GOPHER* env vars; docs/gopher.md
and README updated (incl. the setcap note for binding privileged :70).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
vu1nz Security Review0 finding(s) in PR #? No security issues found. |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds Gopher as a co-located AgentBBS protocol service, following the
internal/newspattern.Why two surfaces (gopher and hedgehog)
Classic Gopher (RFC 1436) is a stateless, unauthenticated, one-shot TCP protocol on port 70 — it has no auth verb, so SSH-key auth can't be bolted onto a port-70 server. So this mirrors AgentBBS's existing dual-surface pattern:
:70(RFC 1436) — open content for any gopher client (lynx, Lagrange, Bombadillo).ssh gopher@= "hedgehog" — the same gopher wire semantics carried over the authenticated SSH channel (the member's key is the credential), so it additionally reaches members-only selectors. Gopher where gopher can, our own gopher-like thing over SSH where it can't.Both surfaces share one read-only
Resolveengine (internal/gopher/server.go); the only difference is anauthedflag.What it serves
Member directory + homepages (
/~name→public_html), an About page (brand + MOTD), public newsgroups (allowlisted on:70, all groups on hedgehog), and members' public files (/files/~name→/public). Selectors are confined to each member's area (path-traversal guarded).Changes
internal/gopher/package: RFC-1436 primitives +Menu, theResolveselector engine, the:70listener, and the hedgehog Bubble Tea browser TUI. Plus tests (wire-format, selector resolution, traversal guard, public-vs-authed news filtering).auth.GopherNames/IsGopherName(+ reserved),app.gopherfield, process wiring, router case,handleGopherincmd/agentbbs/main.go.AGENTBBS_GOPHER*env vars;docs/gopher.md+ README updates (incl. thesetcap cap_net_bind_servicenote for binding privileged:70).Verification
go build ./...+go vetclean; tests pass. Ran live on a high port: public surface returns valid RFC-1436 menus for root/about/members/files/homepage-dir/file/binary, blocks traversal (/~alice/../../secret.txt→3not found), type-3 errors for unknown selectors. Over SSH: non-member key rejected with the members-only hint; a registered member launches the hedgehog TUI cleanly (session recorded as appgopher).🤖 Generated with Claude Code