Sam's direction (2026-07-22): under Community, a Discover sub-tab where users browse joinable public pods (Bug Reports, Feature Requests, …) and join at will — NOT auto-joined. Only HQ auto-joins. Mirrors Google Workspace Chat 'Browse spaces'.
Model (reuses existing fields — no new schema):
Backend:
POST /api/pods/:podId/join — direct self-join, idempotent, gated on the join rule above (403 if invite-only / not listed). Distinct from invite-redeem (no token). Rate-limited.
- Community scope query splits:
scope=community (member community pods) vs scope=discover (communityListed + joinable + caller NOT a member).
Frontend:
- Community tab gains a Discover sub-tab: lists discoverable non-member pods with a 加入 (Join) button + member count; join moves the pod into the user's Community list. i18n both locales (发现/加入 per glossary).
Seed (operational, in the PR or a script): create 'Bug Reports' + 'Feature Requests' pods — communityListed, open joinPolicy, children of HQ.
Decision (Sam leaning open): start one-click open join for these pods; request-to-join is a future per-pod option, not now.
Tests: join endpoint (success/idempotent/invite-only-403/not-listed-403), discover scope excludes member+non-discoverable+personal types, sub-tab render.
Sam's direction (2026-07-22): under Community, a Discover sub-tab where users browse joinable public pods (Bug Reports, Feature Requests, …) and join at will — NOT auto-joined. Only HQ auto-joins. Mirrors Google Workspace Chat 'Browse spaces'.
Model (reuses existing fields — no new schema):
communityListed && joinPolicy !== 'invite-only'(communityListed from fix(community): listing is opt-in — separate communityListed from publicRead #722, joinPolicy from feat(v2): guide newly created pods to first message #723). A discoverable pod = listed + not invite-only.Backend:
POST /api/pods/:podId/join— direct self-join, idempotent, gated on the join rule above (403 if invite-only / not listed). Distinct from invite-redeem (no token). Rate-limited.scope=community(member community pods) vsscope=discover(communityListed + joinable + caller NOT a member).Frontend:
Seed (operational, in the PR or a script): create 'Bug Reports' + 'Feature Requests' pods — communityListed, open joinPolicy, children of HQ.
Decision (Sam leaning open): start one-click open join for these pods; request-to-join is a future per-pod option, not now.
Tests: join endpoint (success/idempotent/invite-only-403/not-listed-403), discover scope excludes member+non-discoverable+personal types, sub-tab render.