Skip to content

fix(security): mod-permission gate for App Review (cm-devvit 0.3.x)#34

Merged
StephenSook merged 5 commits into
mainfrom
fix/app-review-mod-permissions
Jun 7, 2026
Merged

fix(security): mod-permission gate for App Review (cm-devvit 0.3.x)#34
StephenSook merged 5 commits into
mainfrom
fix/app-review-mod-permissions

Conversation

@StephenSook

Copy link
Copy Markdown
Owner

What

Reddit App Review rejected cm-devvit 0.3.0 on mod-permission handling (2026-06-07). This PR closes the gap and documents the permission model so the app can be re-submitted.

Reviewer's four bullets, addressed

  1. Menu items use forUserType: "moderator": already true for all six items in devvit.json (now documented).
  2. Webview displays mod data only to mods: /api/* endpoints were already mod-gated; the client now shows an explicit "Moderators only" notice on 403 instead of a misleading error banner.
  3. Actions check mod perms before submit: NEW. All six /internal/menu/* handlers now call requireModerator() server-side. They previously relied only on forUserType, but the endpoints are HTTP-reachable by any custom-post viewer.
  4. Exceptions documented in README: NEW "Moderator permissions and data access" section.

Commits (atomic)

  • refactor(auth): extract shared authFailToast helper
  • fix(security): verify moderator on every mod-menu handler
  • feat(client): moderators-only gate on 403
  • docs(readme): permission-model section + FAQ fix
  • docs: App Review feedback response + changelog

Verification

  • npm run type-check + npm run lint: clean
  • npm run test: 923/923 pass (adds menu-auth, authFailToast, client 403-gate coverage)
  • Second-model adversarial audit (gemini-agent) confirmed every mod-data and mod-action endpoint is gated and fails closed; the only ungated endpoints are the unauthenticated /api/health liveness probe and platform-only trigger/cron routes.

After merge

Re-submit via npm run launch from main (ships 0.3.1 for review). r/cm_devvit_test is public with the Observatory post visible, so the reviewer can test.

🤖 Generated with Claude Code

StephenSook and others added 5 commits June 7, 2026 15:50
… mod-gates

Pulls the requireModerator() failure-to-toast mapping out of forms.ts into src/lib/authFailToast.ts so menu.ts can reuse the exact wording (including the Polish #10 transient-vs-terminal split). One source of truth, same anti-drift rationale as openaiErrors.ts. No behavior change. Pinned by tests/lib/authFailToast.test.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Reddit App Review rejected 0.3.0: mod-only actions must check mod perms server-side, not rely on the menu forUserType. The six /internal/menu/* handlers are HTTP-reachable by any Observatory custom-post viewer, so a non-mod could POST them directly (reload-config publishes config, recent-actions creates a post). All six now call requireModerator() before acting and return a Mod-only toast otherwise; the two action handlers resolve the sub via auth.sub. Verified: 923/923 tests including new tests/routes/menu-auth.test.ts; tsc + lint clean.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…rns 403

A non-mod opening the Observatory post previously saw an empty shell plus a misleading 'Telemetry API unreachable' banner (no data leaked, but it reads as a bug). The client now renders a dedicated 'Moderators only' notice when /api/recent or /api/stats reply 403, gated strictly on a forbidden flag (status 403) so a transient 503/500 for a real mod still shows the retry banner. Pinned by tests/client/app.test.tsx + api.test.ts.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
New 'Moderator permissions and data access' section (App Review bullet 4): every gated surface, the binary is-a-moderator gate, the intentional any-mod-can-edit-config exception (analogous to AutoModerator), and the safe unauth exceptions (/api/health, ?demo=1, platform-only trigger/cron). FAQ 'Can other mods edit the config?' corrected to cover the in-app editor path.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…entry

Verbatim rejection + tiered findings + bullet-by-bullet status in docs/submission/app-review-feedback-2026-06-07.md; Unreleased changelog entry. Second-model adversarial audit (gemini-agent, Codex CLI unavailable) confirmed every mod-data/mod-action endpoint is gated and fails closed.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Comment thread tests/client/app.test.tsx

import { describe, it, expect, vi, beforeEach, afterEach } from 'vitest';
import { render, screen, waitFor, act } from '@testing-library/react';
import { render, screen, waitFor, act, within } from '@testing-library/react';
@StephenSook StephenSook merged commit 74f8dda into main Jun 7, 2026
12 checks passed
@StephenSook StephenSook deleted the fix/app-review-mod-permissions branch June 9, 2026 20:23
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.

2 participants