Add an admin page for guilds, feature gates for paid features#272
Open
Add an admin page for guilds, feature gates for paid features#272
Conversation
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>
Smoke Test Results
Tested commit: |
Contributor
There was a problem hiding this comment.
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/adminand/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.tsfile and consolidates runtime functions intoAppRuntime.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.
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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.