Skip to content

Say in the forum list what a caller may do in each forum - #17

Merged
ralyodio merged 1 commit into
mainfrom
worktree-forum-canpost
Sep 8, 2026
Merged

Say in the forum list what a caller may do in each forum#17
ralyodio merged 1 commit into
mainfrom
worktree-forum-canpost

Conversation

@ralyodio

@ralyodio ralyodio commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

A client cannot tell a feed-only forum from an ordinary one until it tries to post into one.

news on bbs.hqtui.com is memberPosting: 'replies' — the hqtui blog opens the topics and members reply. A new topic there answers 403, and GET /api/v1/forums described it identically to announcements. So a posting client discovers the difference in public, which is exactly what happened to a myna release announcement:

FAIL  tsbb:member@bbs.hqtui.com  403 bbs.hqtui.com/api/v1/forums/news/topics — forbidden

The board already knew the answer. resolvePermissions resolves canPost per viewer, forum.isLocked sits beside it, and the write route checks both:

if (!permissions.canPost || forum.isLocked) return c.json({ error: 'forbidden' }, 403);

The change

ForumNode carries canPost and canReply for the viewer it was built for, resolved by that same function with the same two conditions. /api/v1/forums and /api/v1/board both return them, plus the forum's own locked flag. A category is never postable — it holds forums, not topics. The OpenAPI description says what they mean.

Nothing changes for the HTML pages and no permission decision moves: this publishes a decision the board was already making.

Verified

  • pnpm typecheck clean; pnpm test 193 pass, 0 fail (1 new).
  • The new test asserts the claim against the write route in the same run: it creates a reply-only forum and a locked one, checks the list says canPost: false for both, then posts to the reply-only forum for the 403 and to general for the 201. A permission hint that can drift from what it describes is worse than no hint.

Once this is released, myna login tsbb <board> --forum <slugs> can reject a feed-only forum up front instead of learning from a 403 on the first announcement.

🤖 Generated with Claude Code

https://claude.ai/code/session_011XqFUXQkK6npCGxBtgizQg

A client could not tell a feed-only forum from an ordinary one until it tried to
post into it. `news` on bbs.hqtui.com is `memberPosting: 'replies'`, so a new
topic there answers 403, and `GET /api/v1/forums` described it exactly as it
described `announcements`. A posting client therefore discovered the difference
in public, which is what happened to myna's release announcement.

The board already knew: `resolvePermissions` resolves `canPost` per viewer and
`forum.isLocked` sits beside it, and the write route checks both. So the tree
now carries `canPost` and `canReply` for the viewer it was built for, resolved
by that same function, and both `/api/v1/forums` and `/api/v1/board` return them
along with the forum's own `locked` flag. A category is never postable: it holds
forums, not topics.

The test asserts the claim against the write route in the same run, posting to a
reply-only forum for the 403 and to an ordinary one for the 201. A permission
hint that can drift from the thing it describes is worse than no hint.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_011XqFUXQkK6npCGxBtgizQg
@ralyodio
ralyodio merged commit 8ccdcdc into main Sep 8, 2026
3 checks passed
@ralyodio ralyodio mentioned this pull request Sep 8, 2026
ralyodio added a commit that referenced this pull request Sep 8, 2026
The forum list says what a caller may do in each forum: canPost, canReply and
locked, resolved the same way the write routes resolve them (#17).


Claude-Session: https://claude.ai/code/session_011XqFUXQkK6npCGxBtgizQg

Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
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