Skip to content

Add an admin page for guilds, feature gates for paid features#272

Open
vcarl wants to merge 13 commits intomainfrom
vc-feature-flags-and-admin-page
Open

Add an admin page for guilds, feature gates for paid features#272
vcarl wants to merge 13 commits intomainfrom
vc-feature-flags-and-admin-page

Conversation

@vcarl
Copy link
Member

@vcarl vcarl commented Feb 5, 2026

No description provided.

vcarl and others added 10 commits February 4, 2026 12:10
Introduces a unified FeatureFlagService Effect layer that supports two
categories of feature flags: PostHog flags (open string keys, gradual
rollout) and tier flags (closed set via Schema.Literal, paid entitlement
checks). The service is added to the ManagedRuntime so all effects get
feature flag access automatically.

- Add FeatureDisabledError tagged error for gate failures
- Export getPostHogClient() from metrics.ts
- Create FeatureFlagServiceLive with scoped lifecycle (initial load +
  periodic refresh with cleanup)
- Rename Features to SettingsFeature with backward-compat alias

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Merge tracing, logging, and prod log-level layers directly into AppLayer
so runEffect/runEffectExit no longer need to provide them per-call. Drop
the unused runEffectSync and the now-unnecessary try/catch wrapper.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
New /app/admin route shows all bot guilds with subscription status
in an accordion UI. /app/admin/:guildId shows full detail with Stripe
billing info. Restricted to @reactiflux.com emails.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
The StripeDetails component now constructs customer/subscription URLs
from the subscription data directly, so links appear whether the
accordion was pre-expanded on page load or opened client-side.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Calls groupIdentify for each guild on bot startup, enriching groups
with name, member count, and subscription tier from the database.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Use ssrDiscordSdk (standalone REST client) instead of the gateway
client for fetching guild data in web routes. The gateway client's
token isn't available until login completes, causing REST calls to
fail with "Expected token to be set for this request."

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Rename FeatureFlagsSection to PostHogSection and extend it to display
group properties alongside feature flag chiclets. Add group properties
to the admin overview expandos. Sort flags alphabetically. Use
server-side flag evaluation for admin pages instead of local-only.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add BooleanFlag type for typed flag names (mod-log, anon-report, escalate, ticketing, analytics)
- Add withFeatureFlag (soft gate) and guardFeature (hard gate) composable helpers
- Add runGatedFeature to AppRuntime for convenient feature-gated effect execution
- Track "premium gate hit" metrics when features are blocked
- Gate escalation creation behind "escalate" flag
- Gate all activity tracking handlers behind "analytics" flag
- Refactor activityTracker to use Effect pipelines with proper spans/logging

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions
Copy link

github-actions bot commented Feb 5, 2026

Smoke Test Results

Metric Value
Image Size unknown
Startup Time 68s

Tested commit: 1ef094e

Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds an admin interface for managing guild subscriptions and implements a feature flag system to gate paid features. The changes introduce PostHog-based feature flags with database-backed tier checks, refactor the PostHog client initialization into an Effect layer, and create comprehensive admin pages for viewing subscription details, payment methods, and invoices.

Changes:

  • Adds two new admin routes (/app/admin and /app/admin/:guildId) with guild subscription management UI, protected by email domain-based access control
  • Implements a feature flag service with PostHog integration and database-backed tier checking for paid features
  • Refactors PostHog client initialization from a lazy singleton pattern to an Effect layer with proper lifecycle management
  • Gates the analytics feature (message tracking) behind the "analytics" feature flag
  • Removes the effects/runtime.ts file and consolidates runtime functions into AppRuntime.ts

Reviewed changes

Copilot reviewed 22 out of 22 changed files in this pull request and generated 15 comments.

Show a summary per file
File Description
app/server.ts Adds PostHog group initialization, simplifies shutdown handler, removes explicit error handling for WAL checkpoint
app/routes/__auth/admin.tsx New admin page listing all guilds with subscription details, Stripe info, and feature flags
app/routes/__auth/admin.$guildId.tsx New detailed admin page for individual guild management with full subscription and payment data
app/routes.ts Adds routes for the new admin pages
app/models/subscriptions.server.ts Adds getAllSubscriptions method to fetch all subscription records
app/models/stripe.server.ts Adds listInvoices and listPaymentMethods methods for admin display
app/helpers/metrics.ts Removes PostHog client singleton, uses exported posthogClient from AppRuntime instead
app/helpers/guildData.server.ts Refactors to use Discord API directly instead of Discord.js client cache
app/helpers/featuresFlags.ts Adds SettingsFeature type alias and deprecates Features type
app/effects/runtime.ts File deleted, functionality moved to AppRuntime.ts
app/effects/posthog.ts New file implementing PostHog service as an Effect layer with group initialization
app/effects/featureFlags.ts New comprehensive feature flag service with PostHog and database-backed tier checking
app/effects/errors.ts Adds FeatureDisabledError for feature gating
app/discord/gateway.ts Updates import to use runEffect from AppRuntime
app/discord/escalationResolver.ts Updates import to use runEffectExit from AppRuntime
app/discord/automod.ts Updates import to use runEffect from AppRuntime
app/discord/activityTracker.ts Refactored to use feature-gated analytics with runGatedFeature, improved error handling
app/commands/report/userLog.ts Updates import to use runEffect from AppRuntime
app/commands/report/modActionLogger.ts Updates import to use runEffect from AppRuntime
app/commands/escalate/handlers.ts Adds FeatureDisabledError handling with user-friendly upgrade message
app/commands/escalate/escalate.ts Adds feature flag check using guardFeature before creating escalations
app/AppRuntime.ts Major refactor: adds infrastructure layer, PostHog and feature flag services, new runtime helpers (runEffect, runEffectExit, runGatedFeature)

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

vcarl and others added 2 commits February 5, 2026 17:29
Move duplicated helpers (requireAdmin, fetchFeatureFlags, fetchStripeDetails)
and UI components (TierBadge, StatusDot, GuildIcon, ExternalLink,
PaymentMethodsList, InvoiceTable, PostHogSection) into a shared feature
module, slimming both admin route files significantly.

Co-Authored-By: Claude Opus 4.6 <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