Add feature-flag system: schema, evaluation service, router gating, and admin UI - #152
Draft
Tim-Machine wants to merge 5 commits into
Draft
Add feature-flag system: schema, evaluation service, router gating, and admin UI#152Tim-Machine wants to merge 5 commits into
Tim-Machine wants to merge 5 commits into
Conversation
Scoped flags: community_id NULL = global default, platform NULL = all platforms, rollout_pct 0-100 for sticky percentage rollouts. Append-only audit table. Verified against a live PostgreSQL 16 in a rolled-back transaction; picked up automatically by the Alembic baseline glob. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Async Redis-cached flag resolution (most-specific scope wins), sticky sha256 percentage bucketing on community_id, fail-open on errors, and pub/sub invalidation via the feature_flags:reload channel. Mirrored into the services/core-community flask_core copy per the dual-layout convention. 20 stdlib-only unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
New _dispatch_gate enforces core-module bypass (identity/workflow are never blockable, now enforced at dispatch rather than only in the admin API), the community module toggle, and a module.<name> feature-flag check on both the command path and the interaction path - the latter previously dispatched with no enable check at all. Adds a background listener on feature_flags:reload for cache invalidation and threads platform into flag evaluation. 11 unit tests. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Community admins manage per-community overrides (scoped CRUD, cannot touch global or foreign rows); superadmins manage global flags and the audit trail. Effective-state display replicates the router's specificity resolution exactly (community scope outranks platform scope). Every mutation writes an audit row in-transaction and publishes feature_flags:reload via a new shared node-redis client. Redis ACLs grant the hub user publish and the router user subscribe on that channel - the router user previously had no channel permissions at all, which also silently broke its existing command:reload subscription. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Contributor
Reviewer's GuideImplements a full feature-flag system with database schema, a shared evaluation service, router dispatch gating, Redis-based cache invalidation, and admin UI/API surfaces for superadmins and community admins, plus unit tests and minor cleanup. Sequence diagram for feature-flag mutation and router cache invalidationsequenceDiagram
actor SuperAdmin
participant SuperAdminFeatureFlags as SuperAdminFeatureFlagsUI
participant HubBackend as featureFlagAdminController
participant Postgres as PostgresDB
participant Redis as RedisPubSub
participant Router as RouterApp
participant FlagService as FeatureFlagService
SuperAdmin ->> SuperAdminFeatureFlags: superAdminApi.updateFeatureFlag(id, data)
SuperAdminFeatureFlags ->> HubBackend: updateGlobalFlag(req)
HubBackend ->> Postgres: SELECT * FROM feature_flags WHERE id = $1
HubBackend ->> Postgres: UPDATE feature_flags SET ... WHERE id = $id
HubBackend ->> Postgres: insertFlagAudit(client, { flagKey, communityId, platform, ... })
HubBackend ->> Redis: publishReload(flagKey, null)
Router ->> Redis: _feature_flag_reload_listener(feature_flag_service, REDIS_URL)
Redis -->> Router: message on feature_flags:reload
Router ->> FlagService: handle_reload(message)
FlagService ->> Redis: _invalidate(flag_key)
FlagService ->> Redis: DEL feature_flag:*:flag_key:*
FlagService -->> Router: cache invalidated
Entity-relationship diagram for feature_flags and feature_flag_auditerDiagram
feature_flags {
int id
varchar flag_key
int community_id
varchar platform
boolean is_enabled
smallint rollout_pct
text description
}
feature_flag_audit {
int id
varchar flag_key
int community_id
varchar platform
varchar action
jsonb old_value
jsonb new_value
varchar changed_by
timestamp changed_at
}
feature_flags ||--o{ feature_flag_audit : audit_for_flag
File-Level Changes
Tips and commandsInteracting with Sourcery
Customizing Your ExperienceAccess your dashboard to:
Getting Help
|
| * exported client is null, and if Redis is unreachable every operation fails | ||
| * soft (logged, never thrown). The app must run fine with Redis down or absent. | ||
| */ | ||
| import { createClient } from 'redis'; |
Contributor
There was a problem hiding this comment.
have nodejs do "backend" things would be a change of architecture.. we typically use Python3.12+ / Quart , Rust for clients, and GoLang for networking to handle "backend" things and simply use nextjs for a thin web layer.
Changing languages is not out of the question, but we should talk through it first.
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.
Summary
Adds an end-to-end feature-flag system so features can be toggled per community without redeploying:
feature_flagsandfeature_flag_audittables (numbered SQL migration per the dual-schema convention).FeatureFlagServiceinlibs/flask_core(mirrored intoservices/layout): evaluation helper for flag lookups with community-level overrides.processing/router_modulechecks feature flags before dispatching commands.admin/hub_module.EXIT:deploy-log file that was an invalid path on Windows.Testing
tests/unit/test_feature_flags.pyandtests/unit/test_router_feature_flags.py.🤖 Generated with Claude Code
Summary by Sourcery
Introduce a shared feature-flag system used by the router for command/interaction gating and by the hub admin portal for global and community-scoped flag management, backed by new database tables and Redis-based cache invalidation.
New Features:
Enhancements:
Build:
Tests:
Chores: