Skip to content

F.14: Fediverse Admin Nest panel — moderation + crosspost queues#21

Open
kh0pper wants to merge 1 commit intof13-crosspost-scheduler-gcfrom
f14-fediverse-admin-panel
Open

F.14: Fediverse Admin Nest panel — moderation + crosspost queues#21
kh0pper wants to merge 1 commit intof13-crosspost-scheduler-gcfrom
f14-fediverse-admin-panel

Conversation

@kh0pper
Copy link
Copy Markdown
Owner

@kh0pper kh0pper commented Apr 12, 2026

Summary

Follow-up #2 after Phase 2. Closes the operator UX gap F.11/F.13 flagged: until now, moderation_actions (F.11) and crosspost_log (F.13) were only accessible through MCP tools. This PR adds a click-through Nest panel.

What lands

One panel at /dashboard/fediverse, two tabs:

Moderation Queue (?tab=moderation)

  • Shows pending / confirmed / expired / rejected / all moderation_actions rows.
  • Columns: bundle + action_type, payload key/value pairs, timing (requested-ago, expires-in, confirmed-ago), status badge, Confirm/Reject buttons.
  • Confirming records operator approval (status='confirmed', confirmed_by, confirmed_at). It does NOT yet auto-fire the action against the federated bundle — that's a follow-up scheduler (help text flags this).

Crosspost Queue (?tab=crosspost)

  • Shows queued / ready / published / manual / error / cancelled crosspost_log rows.
  • Columns: route (source→target), preview (first 180 chars of transformed payload), timing, status, Cancel / Retry buttons.
  • Retry flips error rows to ready + clears the error so the F.13 scheduler picks them up on its next tick.

Implementation

  • servers/gateway/dashboard/panels/fediverse.js (new) — SSR HTML, no client JS. All user-visible data escaped defensively via local escapeHtml() (payloads come from bundles' queueModerationAction and could carry XSS if rendered raw). Tab + filter state via ?tab= and ?filter= query params. Flash messages via ?flash=.
  • servers/gateway/dashboard/index.js — imports + registers the panel, adds POST /dashboard/fediverse/action dispatching to panel.handleAction for the four button actions.
  • servers/gateway/dashboard/nav-registry.js — adds connections category → core group so the panel lands in the sidebar's Core section.
  • CLAUDE.md — built-in panels list updated.

Test plan

  • node --check on all files
  • npm run check passes
  • Panel registers cleanly (imports resolved)
  • Live render with seeded moderation_actions + crosspost_log rows (deferred — needs the gateway running in a non-sandboxed environment)
  • Confirm/Reject/Cancel/Retry round-trip through the POST handler

Follow-ups

  • Auto-fire moderation actions when confirmed (each bundle needs its own handler — deferred)
  • Cursor-based pagination (100-row cap is fine until operators hit it)

Rollout position

Stacked on F.13.

🤖 Generated with Claude Code

Follow-up #2 after Phase 2. Closes the operator UX gap F.11 and F.13
flagged: until now, moderation_actions (F.11) and crosspost_log (F.13)
were only accessible through MCP tools — no click-through UI.

One panel, two tabs:

**Moderation Queue** — shows pending, confirmed, expired, rejected,
and all moderation_actions rows from the federated bundles. Columns:
  • bundle + action_type
  • payload (all key/value pairs from the queued action)
  • timing (requested-ago, expires-in with F.13 GC awareness, confirmed-ago)
  • status badge
  • Confirm / Reject buttons (only for pending)

Confirming records operator approval in moderation_actions
(status='confirmed', confirmed_by, confirmed_at). It does NOT yet
auto-fire the action against the federated bundle — that's a follow-up
scheduler. The panel's help text flags this; for now, confirm + invoke
the bundle's own verb by hand is the expected flow.

**Crosspost Queue** — shows queued/ready/published/manual/error/cancelled
entries from crosspost_log. Columns:
  • route (source→target + source_app#id + target_app#id once published)
  • preview (first 180 chars of transformed_payload_json)
  • timing (fires-in / published-ago / cancelled-ago + created-ago + error snippet)
  • status badge
  • Cancel button (for queued/ready), Retry button (for error — flips
    to ready and clears error so the F.13 scheduler picks it up again)

**Files**

- servers/gateway/dashboard/panels/fediverse.js — the panel. Server-side
  rendered HTML; no client JS. Style tokens from the Nest palette
  (crow-bg-elevated, crow-accent, crow-text-*). All user-visible data
  escaped via local escapeHtml() (defensive — the payload_json
  contents come from bundles' queueModerationAction and could carry
  XSS if rendered raw). Tab + filter state via ?tab= and ?filter= query
  params. Flash messages via ?flash= for post-action redirects.
- servers/gateway/dashboard/index.js — imports fediversePanel, registers
  alongside the other built-ins, adds POST /dashboard/fediverse/action
  route that dispatches to panel.handleAction for the four button
  actions.
- servers/gateway/dashboard/nav-registry.js — adds "connections"
  category → "core" group so the new panel lands in the sidebar's
  Core section next to Messages and Contacts.
- CLAUDE.md — built-in panels list now includes Fediverse Admin.

**Verified**

- node --check on all files
- npm run check passes
- Panel imports cleanly (registry sees it at /dashboard/fediverse)

**Remaining punch list**

- Auto-fire moderation actions when confirmed (the panel's help text
  explicitly calls this out as deferred). Would live in a new
  scheduler tick that polls moderation_actions WHERE status='confirmed'
  AND confirmed_at < now AND applied_at IS NULL, then calls the
  corresponding bundle's publish verb. Deferred because each bundle
  needs its own handler (defederate on pixelfed vs block_instance on
  lemmy vs block_domain on mastodon, all different REST shapes).
- Pagination: panel caps at 100 rows per query. For busy instances
  this will need cursor-based paging. Cross that bridge when operators
  hit it.
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