Skip to content

feat(files): SFTP member storage — private workspaces + shared public area + mgmt TUI#56

Merged
ralyodio merged 3 commits into
mainfrom
feat/files-sftp
Jun 23, 2026
Merged

feat(files): SFTP member storage — private workspaces + shared public area + mgmt TUI#56
ralyodio merged 3 commits into
mainfrom
feat/files-sftp

Conversation

@ralyodio

Copy link
Copy Markdown
Contributor

Implements M4 (Files): member file storage over SFTP, reachable with the member's existing SSH login key.

What

A fully virtual Go SFTP server (pkg/sftp + crypto/ssh, no OS users) wired as an sftp subsystem on the existing :22 wish listener:

sftp files@bbs.profullstack.com        # scp/rsync ride the same endpoint

Identity is the SSH key (username is conventional/ignored). Two areas per session:

  • /me — private, per-user, quota-limited workspace
  • /public — a single shared public file area (old-school BBS file area; world-read, members-only write by default, operator-moderated)

This reverses the old NG1 "no sharing" boundary in favour of one sanctioned, inspectable sharing surface (PRD §9.3 amended; §5.3/§5.3.1 added).

Code (internal/files)

  • backend.go — service, layout, quota/usage, live-session registry, operator API
  • fs.go — per-session virtual FS; resolve() is the single security chokepoint (area confinement + symlink-escape guard) + pkg/sftp request handlers
  • server.go — subsystem handler: key auth → member session → request server, with byte metering + force-disconnect
  • tui.go — in-hub member browser (the "Files" plugin)
  • admin.go — operator management TUI

Operator console: ssh sftp@<host> (allowlist-gated; sftpadmin@/filesadmin@ aliases) — list/disconnect sessions, set per-user quotas, revoke SFTP access, toggle public write, moderate the public area.

Store: files_access (per-user quota override + revoked) and files_settings (public-write mode) tables + methods. Wiring guarded by AGENTBBS_FILES (+ AGENTBBS_FILES_QUOTA_MB, default 1 GiB). Route names reserved.

Tests & verification

  • go build ./..., go vet ./..., gofmt clean
  • Unit + -race: path traversal/confinement, symlink-escape rejection, public-write ACL, quota enforcement, usage accounting, and an end-to-end run against a real SFTP client
  • Live smoke test against the running binary: upload/download round-trip, mkdir, public write, correct on-disk layout, traversal blocked (no file leak), non-member key rejected, non-admin refused, operator admitted to the management TUI

Docs: docs/files.md; PRD §5.3/§5.3.1/§9.3 + README + setup.sh updated.

🤖 Generated with Claude Code

ralyodio and others added 2 commits June 23, 2026 09:35
… area + mgmt TUI

Implements M4 (Files). A fully virtual Go SFTP server (pkg/sftp + crypto/ssh,
no OS users) wired as an "sftp" subsystem on the existing :22 wish listener, so
members reach their files with their login key:

    sftp files@bbs.profullstack.com     # scp/rsync ride the same endpoint

Identity is the SSH key (the username is conventional/ignored). Two areas per
session: a private, quota-limited /me workspace and a single shared public file
area /public (old-school BBS file area; world-read, members-only write by
default, operator-moderated). This reverses the old NG1 "no sharing" boundary in
favour of one sanctioned, inspectable sharing surface (PRD §9.3 amended).

internal/files:
- backend.go  service, layout, quota/usage, live-session registry, operator API
- fs.go       per-session virtual FS; resolve() is the single security
              chokepoint (area confinement + symlink-escape guard) + pkg/sftp
              request handlers
- server.go   subsystem handler: key auth -> member session -> request server,
              with byte metering and force-disconnect
- tui.go      in-BBS member browser (hub plugin "Files")
- admin.go    operator management TUI: sessions, workspaces/quotas, public area

Operator console: ssh sftp@<host> (allowlist-gated; sftpadmin@/filesadmin@
aliases) — list/disconnect sessions, set per-user quotas, revoke SFTP access,
toggle public write, moderate the public area.

store: files_access (per-user quota override + revoked) and files_settings
(public-write mode) tables + methods. main.go wiring guarded by AGENTBBS_FILES
(+ AGENTBBS_FILES_QUOTA_MB, default 1 GiB). Route names reserved.

Tests (incl -race): path traversal/confinement, symlink-escape rejection,
public-write ACL, quota enforcement, usage accounting, and an end-to-end run
against a real SFTP client. Docs: docs/files.md; PRD §5.3/§5.3.1/§9.3 + README
updated.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
# Conflicts:
#	cmd/agentbbs/main.go
#	internal/auth/auth.go
#	internal/store/store.go
@socket-security

socket-security Bot commented Jun 23, 2026

Copy link
Copy Markdown

Review the following changes in direct dependencies. Learn more about Socket for GitHub.

Diff Package Supply Chain
Security
Vulnerability Quality Maintenance License
Addedgithub.com/​pkg/​sftp@​v1.13.1094100100100100

View full report

@github-actions

Copy link
Copy Markdown

vu1nz Security Review

0 finding(s) in PR #?

No security issues found.

…t Premium-gated)

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@ralyodio ralyodio merged commit 7c794dc into main Jun 23, 2026
5 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